Merge branch 'master' of https://vcs.firestormviewer.org/phoenix-firestorm
commit
627eecd577
|
|
@ -14,7 +14,7 @@ build_docs = true
|
|||
build_Linux_Doxygen = true
|
||||
|
||||
# Need viewer-build-variables as well as other shared repositories
|
||||
buildscripts_shared_more_NAMEs="build_secrets build_variables"
|
||||
buildscripts_shared_more_NAMEs="build_secrets build_variables git_hooks"
|
||||
|
||||
################################################################
|
||||
#### Examples of how to set the viewer_channel ####
|
||||
|
|
|
|||
|
|
@ -656,9 +656,9 @@
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>51d9ce98279709854b0be5d0f450ba63</string>
|
||||
<string>96dd770f246917589b776300a2d07f9e</string>
|
||||
<key>url</key>
|
||||
<string>http://3p.firestormviewer.org/curl-7.54.1.180841943-linux64-180841943.tar.bz2</string>
|
||||
<string>http://3p.firestormviewer.org/curl-7.54.1.212891029-linux64-212891029.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>linux64</string>
|
||||
|
|
@ -814,9 +814,9 @@
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>45dedb5b09995cd794304150e94fcf21</string>
|
||||
<string>2653c3627fd8687ff9e003425fd14834</string>
|
||||
<key>url</key>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/87950/806969/dullahan-1.12.2.202109170444_91.1.21_g9dd45fe_chromium-91.0.4472.114-darwin64-563968.tar.bz2</string>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/90199/821852/dullahan-1.12.3.202111032211_91.1.21_g9dd45fe_chromium-91.0.4472.114-darwin64-565428.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>darwin64</string>
|
||||
|
|
@ -826,9 +826,9 @@
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>d0fd9d7086699da4bb5ccc935622a717</string>
|
||||
<string>b4003772562a5dd40bc112eec7cba5f5</string>
|
||||
<key>url</key>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/88276/809277/dullahan-1.12.2.202109230751_91.1.21_g9dd45fe_chromium-91.0.4472.114-windows-563968.tar.bz2</string>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/90201/821871/dullahan-1.12.3.202111032221_91.1.21_g9dd45fe_chromium-91.0.4472.114-windows-565428.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>windows</string>
|
||||
|
|
@ -838,9 +838,9 @@
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>7e8c3ccd420ff5aef24ff72d609ba394</string>
|
||||
<string>d9030d7a7390b3bda7de2adcc27e535a</string>
|
||||
<key>url</key>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/88275/809281/dullahan-1.12.2.202109230751_91.1.21_g9dd45fe_chromium-91.0.4472.114-windows64-563968.tar.bz2</string>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/90200/821876/dullahan-1.12.3.202111032221_91.1.21_g9dd45fe_chromium-91.0.4472.114-windows64-565428.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>windows64</string>
|
||||
|
|
@ -859,7 +859,7 @@
|
|||
</map>
|
||||
</map>
|
||||
<key>version</key>
|
||||
<string>1.12.2.202109230751_91.1.21_g9dd45fe_chromium-91.0.4472.114</string>
|
||||
<string>1.12.3.202111032221_91.1.21_g9dd45fe_chromium-91.0.4472.114</string>
|
||||
</map>
|
||||
<key>elfio</key>
|
||||
<map>
|
||||
|
|
@ -2315,18 +2315,18 @@
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>0a6349b11c8e9d34f0c80b8081736e75</string>
|
||||
<string>35f42f538f4dc3abdfc2b2c4a915d004</string>
|
||||
<key>hash_algorithm</key>
|
||||
<string>md5</string>
|
||||
<key>url</key>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/79438/751815/llca-202104010215.557744-common-557744.tar.bz2</string>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/87228/802959/llca-202109010216.563493-common-563493.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>common</string>
|
||||
</map>
|
||||
</map>
|
||||
<key>version</key>
|
||||
<string>202104010215.557744</string>
|
||||
<string>202109010216.563493</string>
|
||||
</map>
|
||||
<key>llphysicsextensions_source</key>
|
||||
<map>
|
||||
|
|
@ -2968,9 +2968,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>7920fce93d9addf63a420d86f91c5749</string>
|
||||
<string>ea82e634334bccf088daf3d15eab07b7</string>
|
||||
<key>url</key>
|
||||
<string>http://3p.firestormviewer.org/openssl-1.0.2l.180841936-linux64-180841936.tar.bz2</string>
|
||||
<string>http://3p.firestormviewer.org/openssl-1.1.1l.212872015-linux64-212872015.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>linux64</string>
|
||||
|
|
@ -3310,9 +3310,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>6989053898b8e81e904e75553e378820</string>
|
||||
<string>97fac6d88480445c856083ed20d78093</string>
|
||||
<key>url</key>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/77523/735051/viewer_manager-2.0.556340-darwin64-556340.tar.bz2</string>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/85206/790666/viewer_manager-2.0.562101-darwin64-562101.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>darwin64</string>
|
||||
|
|
@ -3346,9 +3346,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>3446c1e54bb32542677caad0ec0d42ac</string>
|
||||
<string>3f6271ec0e2e2f0cc1067d4c4102bb4c</string>
|
||||
<key>url</key>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/77525/735058/viewer_manager-2.0.556340-windows-556340.tar.bz2</string>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/85208/790681/viewer_manager-2.0.562101-windows-562101.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>windows</string>
|
||||
|
|
@ -3359,7 +3359,7 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
|
|||
<key>source_type</key>
|
||||
<string>hg</string>
|
||||
<key>version</key>
|
||||
<string>2.0.556340</string>
|
||||
<string>2.0.562101</string>
|
||||
</map>
|
||||
<key>vlc-bin</key>
|
||||
<map>
|
||||
|
|
@ -3378,9 +3378,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>b639d0035f4a8c9b4973be428a1b7e61</string>
|
||||
<string>738688816ebd76958e49772712a6b972</string>
|
||||
<key>url</key>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/69569/671323/vlc_bin-3.0.9.549888-darwin64-549888.tar.bz2</string>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/90004/820701/vlc_bin-3.0.16.565299-darwin64-565299.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>darwin64</string>
|
||||
|
|
@ -3414,9 +3414,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>4f50b0c47daa081dd4fcb83763d5b0b2</string>
|
||||
<string>6801f91f3f27e626898bab90d40fc1c3</string>
|
||||
<key>url</key>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/69567/671314/vlc_bin-3.0.9.549888-windows-549888.tar.bz2</string>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/90005/820712/vlc_bin-3.0.16.565299-windows-565299.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>windows</string>
|
||||
|
|
@ -3426,16 +3426,16 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>c2f8c01fb6c261b72beb07f0c4cd423f</string>
|
||||
<string>7f66982d6edf3c38f3493e28826d58e8</string>
|
||||
<key>url</key>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/69568/671315/vlc_bin-3.0.9.549888-windows64-549888.tar.bz2</string>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/90006/820713/vlc_bin-3.0.16.565299-windows64-565299.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>windows64</string>
|
||||
</map>
|
||||
</map>
|
||||
<key>version</key>
|
||||
<string>3.0.9.549888</string>
|
||||
<string>2.2.8.538966</string>
|
||||
</map>
|
||||
<key>xmlrpc-epi</key>
|
||||
<map>
|
||||
|
|
|
|||
16
build.sh
16
build.sh
|
|
@ -298,6 +298,22 @@ python_cmd "$helpers/codeticket.py" addinput "Viewer Channel" "${viewer_channel}
|
|||
|
||||
initialize_version # provided by buildscripts build.sh; sets version id
|
||||
|
||||
begin_section "coding policy check"
|
||||
# On our TC Windows build hosts, the GitPython library underlying our
|
||||
# coding_policy_git.py script fails to run git for reasons we have not tried
|
||||
# to diagnose. Clearly git works fine on those hosts, or we would never get
|
||||
# this far. Running coding policy checks on one platform *should* suffice...
|
||||
if [[ "$arch" == "Darwin" ]]
|
||||
then
|
||||
# install the git-hooks dependencies
|
||||
pip install -r "$(native_path "$git_hooks_checkout/requirements.txt")" || \
|
||||
fatal "pip install git-hooks failed"
|
||||
# validate the branch we're about to build
|
||||
python_cmd "$git_hooks_checkout/coding_policy_git.py" --all_files || \
|
||||
fatal "coding policy check failed"
|
||||
fi
|
||||
end_section "coding policy check"
|
||||
|
||||
# Now run the build
|
||||
succeeded=true
|
||||
last_built_variant=
|
||||
|
|
|
|||
|
|
@ -1,18 +0,0 @@
|
|||
secondlife-viewer (0.3) unstable; urgency=low
|
||||
|
||||
* Initial debian configuration
|
||||
|
||||
-- Don Kjer <don@lindenlab.com> Wed, 04 Jul 2012 00:43:03 +0000
|
||||
|
||||
secondlife-viewer (0.2) unstable; urgency=low
|
||||
|
||||
* Adding default LSB headers for squeeze
|
||||
|
||||
-- Tyler Kohler <tyler@lindenlab.com> Thu, 24 Mar 2011 09:43:36 -0700
|
||||
|
||||
secondlife-viewer (0.1) unstable; urgency=low
|
||||
|
||||
* Cloned from debian package skeleton.
|
||||
|
||||
-- Lex Linden <lex@lindenlab.com> Mon, 20 Sep 2010 08:01:59 -0700
|
||||
|
||||
|
|
@ -1 +0,0 @@
|
|||
5
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
Source: secondlife-viewer
|
||||
Section: unknown
|
||||
Priority: extra
|
||||
Maintainer: Don Linden <don@lindenlab.com>
|
||||
Build-Depends: debhelper (>= 5)
|
||||
Homepage: http://secondlife.com
|
||||
Standards-Version: 3.7.2
|
||||
|
||||
Package: secondlife-viewer
|
||||
Architecture: any
|
||||
Depends: ${shlibs:Depends}, ${misc:Depends},
|
||||
ia32-libs,
|
||||
ia32-libs-gtk
|
||||
Description: Second Life Viewer
|
||||
Second Life is an online virtual world developed by Linden Lab.
|
||||
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
Second Life Viewer Copyright: 2000-2012 Linden Research, Inc.
|
||||
|
||||
License:
|
||||
|
||||
3Dconnexion SDK Copyright (C) 1992-2009 3Dconnexion
|
||||
APR Copyright (C) 2011 The Apache Software Foundation
|
||||
Collada DOM Copyright 2006 Sony Computer Entertainment Inc.
|
||||
cURL Copyright (C) 1996-2010, Daniel Stenberg, (daniel@haxx.se)
|
||||
DBus/dbus-glib Copyright (C) 2002, 2003 CodeFactory AB / Copyright (C) 2003, 2004 Red Hat, Inc.
|
||||
expat Copyright (C) 1998, 1999, 2000 Thai Open Source Software Center Ltd.
|
||||
FreeType Copyright (C) 1996-2002, 2006 David Turner, Robert Wilhelm, and Werner Lemberg.
|
||||
GL Copyright (C) 1999-2004 Brian Paul.
|
||||
GLOD Copyright (C) 2003-04 Jonathan Cohen, Nat Duca, Chris Niski, Johns Hopkins University and David Luebke, Brenden Schubert, University of Virginia.
|
||||
google-perftools Copyright (c) 2005, Google Inc.
|
||||
Havok.com(TM) Copyright (C) 1999-2001, Telekinesys Research Limited.
|
||||
jpeg2000 Copyright (C) 2001, David Taubman, The University of New South Wales (UNSW)
|
||||
jpeglib Copyright (C) 1991-1998, Thomas G. Lane.
|
||||
ogg/vorbis Copyright (C) 2002, Xiphophorus
|
||||
OpenSSL Copyright (C) 1998-2008 The OpenSSL Project.
|
||||
PCRE Copyright (c) 1997-2012 University of Cambridge
|
||||
SDL Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga
|
||||
SSLeay Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
xmlrpc-epi Copyright (C) 2000 Epinions, Inc.
|
||||
zlib Copyright (C) 1995-2012 Jean-loup Gailly and Mark Adler.
|
||||
|
||||
Second Life Viewer uses Havok (TM) Physics. (c)Copyright 1999-2010 Havok.com Inc. (and its Licensors). All Rights Reserved. See www.havok.com for details.
|
||||
|
||||
This software contains source code provided by NVIDIA Corporation.
|
||||
|
||||
All rights reserved. See licenses.txt for details.
|
||||
|
||||
Voice chat Audio coding: Polycom(R) Siren14(TM) (ITU-T Rec. G.722.1 Annex C)
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
#!/bin/sh
|
||||
# postinst script for secondlife-viewer
|
||||
#
|
||||
# Delete this file if you don't need it.
|
||||
#
|
||||
# see: dh_installdeb(1)
|
||||
|
||||
set -e
|
||||
|
||||
# summary of how this script can be called:
|
||||
# * <postinst> `configure' <most-recently-configured-version>
|
||||
# * <old-postinst> `abort-upgrade' <new version>
|
||||
# * <conflictor's-postinst> `abort-remove' `in-favour' <package>
|
||||
# <new-version>
|
||||
# * <postinst> `abort-remove'
|
||||
# * <deconfigured's-postinst> `abort-deconfigure' `in-favour'
|
||||
# <failed-install-package> <version> `removing'
|
||||
# <conflicting-package> <version>
|
||||
# for details, see http://www.debian.org/doc/debian-policy/ or
|
||||
# the debian-policy package
|
||||
|
||||
|
||||
case "$1" in
|
||||
configure)
|
||||
;;
|
||||
|
||||
abort-upgrade|abort-remove|abort-deconfigure)
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "postinst called with unknown argument \`$1'" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# dh_installdeb will replace this with shell code automatically
|
||||
# generated by other debhelper scripts. Don't delete this!
|
||||
|
||||
#DEBHELPER#
|
||||
|
||||
exit 0
|
||||
|
||||
|
||||
|
|
@ -1,41 +0,0 @@
|
|||
#!/bin/sh
|
||||
# postrm script for secondlife-viewer
|
||||
#
|
||||
# Delete this file if you don't need it.
|
||||
#
|
||||
# see: dh_installdeb(1)
|
||||
|
||||
set -e
|
||||
|
||||
# summary of how this script can be called:
|
||||
# * <postrm> `remove'
|
||||
# * <postrm> `purge'
|
||||
# * <old-postrm> `upgrade' <new-version>
|
||||
# * <new-postrm> `failed-upgrade' <old-version>
|
||||
# * <new-postrm> `abort-install'
|
||||
# * <new-postrm> `abort-install' <old-version>
|
||||
# * <new-postrm> `abort-upgrade' <old-version>
|
||||
# * <disappearer's-postrm> `disappear' <overwriter>
|
||||
# <overwriter-version>
|
||||
# for details, see http://www.debian.org/doc/debian-policy/ or
|
||||
# the debian-policy package
|
||||
|
||||
|
||||
case "$1" in
|
||||
purge|remove|upgrade|failed-upgrade|abort-install|abort-upgrade|disappear)
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "postrm called with unknown argument \`$1'" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# dh_installdeb will replace this with shell code automatically
|
||||
# generated by other debhelper scripts. Don't delete this!
|
||||
|
||||
#DEBHELPER#
|
||||
|
||||
exit 0
|
||||
|
||||
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
#!/bin/sh
|
||||
# preinst script for secondlife-viewer
|
||||
#
|
||||
# Delete this file if you don't need it.
|
||||
#
|
||||
# see: dh_installdeb(1)
|
||||
|
||||
set -e
|
||||
|
||||
# summary of how this script can be called:
|
||||
# * <new-preinst> `install'
|
||||
# * <new-preinst> `install' <old-version>
|
||||
# * <new-preinst> `upgrade' <old-version>
|
||||
# * <old-preinst> `abort-upgrade' <new-version>
|
||||
# for details, see http://www.debian.org/doc/debian-policy/ or
|
||||
# the debian-policy package
|
||||
|
||||
|
||||
case "$1" in
|
||||
install|upgrade)
|
||||
;;
|
||||
|
||||
abort-upgrade)
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "preinst called with unknown argument \`$1'" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# dh_installdeb will replace this with shell code automatically
|
||||
# generated by other debhelper scripts. Don't delete this!
|
||||
|
||||
#DEBHELPER#
|
||||
|
||||
exit 0
|
||||
|
||||
|
||||
|
|
@ -1,42 +0,0 @@
|
|||
#!/bin/sh
|
||||
# prerm script for secondlife-viewer
|
||||
#
|
||||
# Delete this file if you don't need it.
|
||||
#
|
||||
# see: dh_installdeb(1)
|
||||
|
||||
set -e
|
||||
|
||||
# summary of how this script can be called:
|
||||
# * <prerm> `remove'
|
||||
# * <old-prerm> `upgrade' <new-version>
|
||||
# * <new-prerm> `failed-upgrade' <old-version>
|
||||
# * <conflictor's-prerm> `remove' `in-favour' <package> <new-version>
|
||||
# * <deconfigured's-prerm> `deconfigure' `in-favour'
|
||||
# <package-being-installed> <version> `removing'
|
||||
# <conflicting-package> <version>
|
||||
# for details, see http://www.debian.org/doc/debian-policy/ or
|
||||
# the debian-policy package
|
||||
|
||||
|
||||
case "$1" in
|
||||
remove|upgrade|deconfigure)
|
||||
;;
|
||||
|
||||
failed-upgrade)
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "prerm called with unknown argument \`$1'" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# dh_installdeb will replace this with shell code automatically
|
||||
# generated by other debhelper scripts. Don't delete this!
|
||||
|
||||
#DEBHELPER#
|
||||
|
||||
exit 0
|
||||
|
||||
|
||||
|
|
@ -1,118 +0,0 @@
|
|||
#!/usr/bin/make -f
|
||||
# -*- makefile -*-
|
||||
# Sample debian/rules that uses debhelper.
|
||||
# This file was originally written by Joey Hess and Craig Small.
|
||||
# As a special exception, when this file is copied by dh-make into a
|
||||
# dh-make output file, you may use that output file without restriction.
|
||||
# This special exception was added by Craig Small in version 0.37 of dh-make.
|
||||
|
||||
# Uncomment this to turn on verbose mode.
|
||||
#export DH_VERBOSE=1
|
||||
|
||||
BASEDIR=opt/linden
|
||||
|
||||
VIEWER_PKG=secondlife-viewer
|
||||
VIEWER_PACKAGEDIR=build-linux-i686/newview/packaged
|
||||
VIEWER_DESTDIR=$(CURDIR)/debian/$(VIEWER_PKG)
|
||||
VIEWER_VERSION:=$(shell dpkg-parsechangelog | grep ^Version | sed 's/^Version: //')
|
||||
VIEWER_INSTALLDIR:=$(BASEDIR)/viewer/SecondLife-i686-$(VIEWER_VERSION)
|
||||
|
||||
configure: configure-stamp
|
||||
configure-stamp:
|
||||
dh_testdir
|
||||
# Add here commands to configure the package.
|
||||
|
||||
touch configure-stamp
|
||||
|
||||
build: build-stamp
|
||||
|
||||
build-stamp: configure-stamp
|
||||
dh_testdir
|
||||
|
||||
# Add here commands to compile the package.
|
||||
#$(MAKE)
|
||||
#docbook-to-man debian/secondlife-viewer.sgml > secondlife-viewer.1
|
||||
|
||||
touch $@
|
||||
|
||||
clean:
|
||||
dh_testdir
|
||||
dh_testroot
|
||||
rm -f build-stamp configure-stamp
|
||||
|
||||
# Add here commands to clean up after the build process.
|
||||
#-$(MAKE) clean
|
||||
|
||||
dh_clean
|
||||
|
||||
install: build
|
||||
dh_testdir
|
||||
dh_testroot
|
||||
dh_clean -k
|
||||
dh_installdirs
|
||||
|
||||
# Add here commands to install the package into debian/secondlife-viewer.
|
||||
for file in $$(find $(VIEWER_PACKAGEDIR) -type f -o -type l | sed 's~$(VIEWER_PACKAGEDIR)/~~'); do \
|
||||
# create containing directory \
|
||||
install -v -m 755 -o root -g root -d "$$(dirname "$(VIEWER_DESTDIR)/$(VIEWER_INSTALLDIR)/$$file")"; \
|
||||
PERM=644; \
|
||||
if [ -x "$(VIEWER_PACKAGEDIR)/$$file" ]; then \
|
||||
PERM=755; \
|
||||
fi; \
|
||||
if [ -L "$(VIEWER_PACKAGEDIR)/$$file" ]; then \
|
||||
REAL="$$( readlink -f $(VIEWER_PACKAGEDIR)/$$file )"; \
|
||||
RELATIVE="$$( echo $$REAL | sed 's~$(CURDIR)/$(VIEWER_PACKAGEDIR)/~~' )"; \
|
||||
echo dh_link -p $(VIEWER_PKG) "$(VIEWER_INSTALLDIR)/$$RELATIVE" "$(VIEWER_INSTALLDIR)/$$file" ; \
|
||||
dh_link -p $(VIEWER_PKG) "$(VIEWER_INSTALLDIR)/$$RELATIVE" "$(VIEWER_INSTALLDIR)/$$file" ; \
|
||||
else \
|
||||
install -v -m $$PERM -o root -g root "$(VIEWER_PACKAGEDIR)/$$file" "$(VIEWER_DESTDIR)/$(VIEWER_INSTALLDIR)/$$file"; \
|
||||
fi; \
|
||||
done
|
||||
dh_link -p $(VIEWER_PKG) /$(VIEWER_INSTALLDIR)/secondlife /usr/bin/secondlife
|
||||
dh_link -p $(VIEWER_PKG) $(BASEDIR)/viewer/SecondLife-i686-$(VIEWER_VERSION) $(BASEDIR)/viewer/SecondLife
|
||||
|
||||
|
||||
# Build architecture-independent files here.
|
||||
binary-indep: build install
|
||||
# We have nothing to do by default.
|
||||
|
||||
# Build architecture-dependent files here.
|
||||
binary-arch: build install
|
||||
dh_testdir
|
||||
dh_testroot
|
||||
dh_installchangelogs
|
||||
dh_installdocs
|
||||
dh_installexamples
|
||||
# dh_install
|
||||
# dh_installmenu
|
||||
# dh_installdebconf
|
||||
# dh_installlogrotate
|
||||
# dh_installemacsen
|
||||
# dh_installpam
|
||||
# dh_installmime
|
||||
# dh_python
|
||||
|
||||
# To add an init script, uncomment this line and edit debian/init.d and
|
||||
# customize debian/secondlife-viewer.default to suit your needs.
|
||||
# dh_installinit
|
||||
|
||||
# To add cron jobs, uncomment this line and make a crontab file named
|
||||
# debian/cron.d, and it will be installed in /etc/cron.d/
|
||||
# dh_installcron
|
||||
|
||||
# dh_installinfo
|
||||
dh_installman
|
||||
dh_link
|
||||
# dh_strip
|
||||
dh_compress
|
||||
# dh_fixperms
|
||||
# dh_perl
|
||||
# dh_makeshlibs
|
||||
dh_installdeb
|
||||
# dh_shlibdeps
|
||||
dh_gencontrol
|
||||
dh_md5sums
|
||||
dh_builddeb
|
||||
|
||||
binary: binary-indep binary-arch
|
||||
.PHONY: build clean binary-indep binary-arch binary install configure
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
# Linden packages install in opt/linden
|
||||
secondlife-viewer: dir-or-file-in-opt
|
||||
secondlife-viewer: section-is-dh_make-template
|
||||
secondlife-viewer: binary-without-manpage
|
||||
secondlife-viewer: maintainer-script-empty postrm
|
||||
secondlife-viewer: maintainer-script-empty preinst
|
||||
secondlife-viewer: maintainer-script-empty prerm
|
||||
secondlife-viewer: unstripped-binary-or-object
|
||||
|
|
@ -279,6 +279,7 @@ Beq Janus
|
|||
SL-13583
|
||||
SL-14766
|
||||
SL-14927
|
||||
SL-11300
|
||||
Beth Walcher
|
||||
Bezilon Kasei
|
||||
Biancaluce Robbiani
|
||||
|
|
@ -819,6 +820,7 @@ Jonathan Yap
|
|||
STORM-2142
|
||||
STORM-2145
|
||||
SL-10089
|
||||
BUG-229818
|
||||
Kadah Coba
|
||||
STORM-1060
|
||||
STORM-1843
|
||||
|
|
|
|||
Binary file not shown.
|
After Width: | Height: | Size: 9.4 KiB |
|
|
@ -82,7 +82,7 @@ if (WINDOWS)
|
|||
# CP changed to only append the flag for 32bit builds - on 64bit builds,
|
||||
# locally at least, the build output is spammed with 1000s of 'D9002'
|
||||
# warnings about this switch being ignored.
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP")
|
||||
# <FS:ND> Remove this, it's no option to cl.exe and causes a massive amount of warnings.
|
||||
#if( ADDRESS_SIZE EQUAL 32 )
|
||||
#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /p:PreferredToolArchitecture=x64")
|
||||
|
|
@ -165,6 +165,11 @@ endif (WINDOWS)
|
|||
if (LINUX)
|
||||
set(CMAKE_SKIP_RPATH TRUE)
|
||||
|
||||
|
||||
if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 10.0.0 )
|
||||
message( FATAL_ERROR "GCC greater 9.4.0 is not supported. Recompile boost for support of GCC 10.0.0 and up." )
|
||||
endif()
|
||||
|
||||
# <FS:ND/>
|
||||
# And another hack for FORTIFY_SOURCE. Some distributions (for example Gentoo) define FORTIFY_SOURCE by default.
|
||||
# Check if this is the case, if yes, do not define it again.
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ else (USESYSTEMLIBS)
|
|||
endif (USESYSTEMLIBS)
|
||||
|
||||
if (LINUX)
|
||||
set(CRYPTO_LIBRARIES crypto dl)
|
||||
set(CRYPTO_LIBRARIES crypto dl pthread)
|
||||
elseif (DARWIN)
|
||||
set(CRYPTO_LIBRARIES crypto)
|
||||
endif (LINUX)
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ if (EXISTS ${CMAKE_SOURCE_DIR}/Server.cmake)
|
|||
set(INSTALL_PROPRIETARY ON CACHE BOOL "Install proprietary binaries")
|
||||
endif (EXISTS ${CMAKE_SOURCE_DIR}/Server.cmake)
|
||||
set(TEMPLATE_VERIFIER_OPTIONS "" CACHE STRING "Options for scripts/template_verifier.py")
|
||||
set(TEMPLATE_VERIFIER_MASTER_URL "https://bitbucket.org/lindenlab/master-message-template-git/raw/HEAD/message_template.msg" CACHE STRING "Location of the master message template")
|
||||
set(TEMPLATE_VERIFIER_MASTER_URL "https://bitbucket.org/lindenlab/master-message-template-git/raw/master/message_template.msg" CACHE STRING "Location of the master message template")
|
||||
|
||||
if (NOT CMAKE_BUILD_TYPE)
|
||||
set(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
euclid 5/29/2020
|
||||
euclid 7/23/2020
|
||||
euclid 4/29/2021
|
||||
euclid 4/29/2021
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ BOOL LLViewerVisualParamInfo::parseXml(LLXmlTreeNode *node)
|
|||
static LLStdStringHandle wearable_string = LLXmlTree::addAttributeString("wearable");
|
||||
if( node->getFastAttributeString( wearable_string, wearable) )
|
||||
{
|
||||
mWearableType = LLWearableType::typeNameToType( wearable );
|
||||
mWearableType = LLWearableType::getInstance()->typeNameToType( wearable );
|
||||
}
|
||||
|
||||
static LLStdStringHandle edit_group_string = LLXmlTree::addAttributeString("edit_group");
|
||||
|
|
|
|||
|
|
@ -76,17 +76,17 @@ LLWearable::~LLWearable()
|
|||
|
||||
const std::string& LLWearable::getTypeLabel() const
|
||||
{
|
||||
return LLWearableType::getTypeLabel(mType);
|
||||
return LLWearableType::getInstance()->getTypeLabel(mType);
|
||||
}
|
||||
|
||||
const std::string& LLWearable::getTypeName() const
|
||||
{
|
||||
return LLWearableType::getTypeName(mType);
|
||||
return LLWearableType::getInstance()->getTypeName(mType);
|
||||
}
|
||||
|
||||
LLAssetType::EType LLWearable::getAssetType() const
|
||||
{
|
||||
return LLWearableType::getAssetType(mType);
|
||||
return LLWearableType::getInstance()->getAssetType(mType);
|
||||
}
|
||||
|
||||
BOOL LLWearable::exportFile(const std::string& filename) const
|
||||
|
|
|
|||
|
|
@ -241,10 +241,11 @@ BOOL LLWearableData::getWearableIndex(const LLWearable *wearable, U32& index_fou
|
|||
U32 LLWearableData::getClothingLayerCount() const
|
||||
{
|
||||
U32 count = 0;
|
||||
LLWearableType *wr_inst = LLWearableType::getInstance();
|
||||
for (S32 i = 0; i < LLWearableType::WT_COUNT; i++)
|
||||
{
|
||||
LLWearableType::EType type = (LLWearableType::EType)i;
|
||||
if (LLWearableType::getAssetType(type)==LLAssetType::AT_CLOTHING)
|
||||
if (wr_inst->getAssetType(type)==LLAssetType::AT_CLOTHING)
|
||||
{
|
||||
count += getWearableCount(type);
|
||||
}
|
||||
|
|
@ -254,7 +255,7 @@ U32 LLWearableData::getClothingLayerCount() const
|
|||
|
||||
BOOL LLWearableData::canAddWearable(const LLWearableType::EType type) const
|
||||
{
|
||||
LLAssetType::EType a_type = LLWearableType::getAssetType(type);
|
||||
LLAssetType::EType a_type = LLWearableType::getInstance()->getAssetType(type);
|
||||
if (a_type==LLAssetType::AT_CLOTHING)
|
||||
{
|
||||
if (type == LLWearableType::WT_PHYSICS) return (getWearableCount(type) < 1); // <FS:Ansariel> Don't add physics layer
|
||||
|
|
|
|||
|
|
@ -30,162 +30,101 @@
|
|||
#include "llinventorydefines.h"
|
||||
|
||||
|
||||
struct WearableEntry : public LLDictionaryEntry
|
||||
LLWearableType::LLWearableDictionary::LLWearableDictionary(LLTranslationBridge::ptr_t& trans)
|
||||
{
|
||||
WearableEntry(LLWearableType& wtype,
|
||||
const std::string &name,
|
||||
const std::string& default_new_name,
|
||||
LLAssetType::EType assetType,
|
||||
LLInventoryType::EIconName iconName,
|
||||
BOOL disable_camera_switch = FALSE,
|
||||
BOOL allow_multiwear = TRUE) :
|
||||
LLDictionaryEntry(name),
|
||||
mAssetType(assetType),
|
||||
mDefaultNewName(default_new_name),
|
||||
mLabel(wtype.mTrans->getString(name)),
|
||||
mIconName(iconName),
|
||||
mDisableCameraSwitch(disable_camera_switch),
|
||||
mAllowMultiwear(allow_multiwear)
|
||||
{
|
||||
|
||||
}
|
||||
const LLAssetType::EType mAssetType;
|
||||
const std::string mLabel;
|
||||
const std::string mDefaultNewName; //keep mLabel for backward compatibility
|
||||
LLInventoryType::EIconName mIconName;
|
||||
BOOL mDisableCameraSwitch;
|
||||
BOOL mAllowMultiwear;
|
||||
};
|
||||
|
||||
class LLWearableDictionary : public LLParamSingleton<LLWearableDictionary>,
|
||||
public LLDictionary<LLWearableType::EType, WearableEntry>
|
||||
{
|
||||
LLSINGLETON(LLWearableDictionary, LLWearableType&);
|
||||
|
||||
// [RLVa:KB] - Checked: 2010-03-03 (RLVa-1.2.0a) | Added: RLVa-1.2.0a
|
||||
protected:
|
||||
// The default implementation asserts on 'notFound()' and returns -1 which isn't a valid EWearableType
|
||||
virtual LLWearableType::EType notFound() const { return LLWearableType::WT_INVALID; }
|
||||
// [/RLVa:KB]
|
||||
};
|
||||
|
||||
LLWearableDictionary::LLWearableDictionary(LLWearableType& wtype)
|
||||
{
|
||||
addEntry(LLWearableType::WT_SHAPE, new WearableEntry(wtype, "shape", "New Shape", LLAssetType::AT_BODYPART, LLInventoryType::ICONNAME_BODYPART_SHAPE, FALSE, FALSE));
|
||||
addEntry(LLWearableType::WT_SKIN, new WearableEntry(wtype, "skin", "New Skin", LLAssetType::AT_BODYPART, LLInventoryType::ICONNAME_BODYPART_SKIN, FALSE, FALSE));
|
||||
addEntry(LLWearableType::WT_HAIR, new WearableEntry(wtype, "hair", "New Hair", LLAssetType::AT_BODYPART, LLInventoryType::ICONNAME_BODYPART_HAIR, FALSE, FALSE));
|
||||
addEntry(LLWearableType::WT_EYES, new WearableEntry(wtype, "eyes", "New Eyes", LLAssetType::AT_BODYPART, LLInventoryType::ICONNAME_BODYPART_EYES, FALSE, FALSE));
|
||||
addEntry(LLWearableType::WT_SHIRT, new WearableEntry(wtype, "shirt", "New Shirt", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_SHIRT, FALSE, TRUE));
|
||||
addEntry(LLWearableType::WT_PANTS, new WearableEntry(wtype, "pants", "New Pants", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_PANTS, FALSE, TRUE));
|
||||
addEntry(LLWearableType::WT_SHOES, new WearableEntry(wtype, "shoes", "New Shoes", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_SHOES, FALSE, TRUE));
|
||||
addEntry(LLWearableType::WT_SOCKS, new WearableEntry(wtype, "socks", "New Socks", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_SOCKS, FALSE, TRUE));
|
||||
addEntry(LLWearableType::WT_JACKET, new WearableEntry(wtype, "jacket", "New Jacket", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_JACKET, FALSE, TRUE));
|
||||
addEntry(LLWearableType::WT_GLOVES, new WearableEntry(wtype, "gloves", "New Gloves", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_GLOVES, FALSE, TRUE));
|
||||
addEntry(LLWearableType::WT_UNDERSHIRT, new WearableEntry(wtype, "undershirt", "New Undershirt", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_UNDERSHIRT, FALSE, TRUE));
|
||||
addEntry(LLWearableType::WT_UNDERPANTS, new WearableEntry(wtype, "underpants", "New Underpants", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_UNDERPANTS, FALSE, TRUE));
|
||||
addEntry(LLWearableType::WT_SKIRT, new WearableEntry(wtype, "skirt", "New Skirt", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_SKIRT, FALSE, TRUE));
|
||||
addEntry(LLWearableType::WT_ALPHA, new WearableEntry(wtype, "alpha", "New Alpha", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_ALPHA, FALSE, TRUE));
|
||||
addEntry(LLWearableType::WT_TATTOO, new WearableEntry(wtype, "tattoo", "New Tattoo", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_TATTOO, FALSE, TRUE));
|
||||
addEntry(LLWearableType::WT_UNIVERSAL, new WearableEntry(wtype, "universal", "New Universal", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_UNIVERSAL, FALSE, TRUE));
|
||||
addEntry(LLWearableType::WT_SHAPE, new WearableEntry(trans, "shape", "New Shape", LLAssetType::AT_BODYPART, LLInventoryType::ICONNAME_BODYPART_SHAPE, FALSE, FALSE));
|
||||
addEntry(LLWearableType::WT_SKIN, new WearableEntry(trans, "skin", "New Skin", LLAssetType::AT_BODYPART, LLInventoryType::ICONNAME_BODYPART_SKIN, FALSE, FALSE));
|
||||
addEntry(LLWearableType::WT_HAIR, new WearableEntry(trans, "hair", "New Hair", LLAssetType::AT_BODYPART, LLInventoryType::ICONNAME_BODYPART_HAIR, FALSE, FALSE));
|
||||
addEntry(LLWearableType::WT_EYES, new WearableEntry(trans, "eyes", "New Eyes", LLAssetType::AT_BODYPART, LLInventoryType::ICONNAME_BODYPART_EYES, FALSE, FALSE));
|
||||
addEntry(LLWearableType::WT_SHIRT, new WearableEntry(trans, "shirt", "New Shirt", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_SHIRT, FALSE, TRUE));
|
||||
addEntry(LLWearableType::WT_PANTS, new WearableEntry(trans, "pants", "New Pants", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_PANTS, FALSE, TRUE));
|
||||
addEntry(LLWearableType::WT_SHOES, new WearableEntry(trans, "shoes", "New Shoes", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_SHOES, FALSE, TRUE));
|
||||
addEntry(LLWearableType::WT_SOCKS, new WearableEntry(trans, "socks", "New Socks", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_SOCKS, FALSE, TRUE));
|
||||
addEntry(LLWearableType::WT_JACKET, new WearableEntry(trans, "jacket", "New Jacket", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_JACKET, FALSE, TRUE));
|
||||
addEntry(LLWearableType::WT_GLOVES, new WearableEntry(trans, "gloves", "New Gloves", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_GLOVES, FALSE, TRUE));
|
||||
addEntry(LLWearableType::WT_UNDERSHIRT, new WearableEntry(trans, "undershirt", "New Undershirt", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_UNDERSHIRT, FALSE, TRUE));
|
||||
addEntry(LLWearableType::WT_UNDERPANTS, new WearableEntry(trans, "underpants", "New Underpants", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_UNDERPANTS, FALSE, TRUE));
|
||||
addEntry(LLWearableType::WT_SKIRT, new WearableEntry(trans, "skirt", "New Skirt", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_SKIRT, FALSE, TRUE));
|
||||
addEntry(LLWearableType::WT_ALPHA, new WearableEntry(trans, "alpha", "New Alpha", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_ALPHA, FALSE, TRUE));
|
||||
addEntry(LLWearableType::WT_TATTOO, new WearableEntry(trans, "tattoo", "New Tattoo", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_TATTOO, FALSE, TRUE));
|
||||
addEntry(LLWearableType::WT_UNIVERSAL, new WearableEntry(trans, "universal", "New Universal", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_UNIVERSAL, FALSE, TRUE));
|
||||
|
||||
// [SL:KB] - Patch: Appearance-Misc | Checked: 2011-05-29 (Catznip-2.6)
|
||||
addEntry(LLWearableType::WT_PHYSICS, new WearableEntry(wtype, "physics", "New Physics", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_PHYSICS, TRUE, FALSE));
|
||||
addEntry(LLWearableType::WT_PHYSICS, new WearableEntry(trans, "physics", "New Physics", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_PHYSICS, TRUE, FALSE));
|
||||
// [/SL:KB]
|
||||
// addEntry(LLWearableType::WT_PHYSICS, new WearableEntry(wtype, "physics", "New Physics", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_PHYSICS, TRUE, TRUE));
|
||||
// addEntry(LLWearableType::WT_PHYSICS, new WearableEntry(trans, "physics", "New Physics", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_PHYSICS, TRUE, TRUE));
|
||||
|
||||
addEntry(LLWearableType::WT_INVALID, new WearableEntry(wtype, "invalid", "Invalid Wearable", LLAssetType::AT_NONE, LLInventoryType::ICONNAME_UNKNOWN, FALSE, FALSE));
|
||||
addEntry(LLWearableType::WT_NONE, new WearableEntry(wtype, "none", "Invalid Wearable", LLAssetType::AT_NONE, LLInventoryType::ICONNAME_NONE, FALSE, FALSE));
|
||||
addEntry(LLWearableType::WT_INVALID, new WearableEntry(trans, "invalid", "Invalid Wearable", LLAssetType::AT_NONE, LLInventoryType::ICONNAME_UNKNOWN, FALSE, FALSE));
|
||||
addEntry(LLWearableType::WT_NONE, new WearableEntry(trans, "none", "Invalid Wearable", LLAssetType::AT_NONE, LLInventoryType::ICONNAME_NONE, FALSE, FALSE));
|
||||
}
|
||||
|
||||
|
||||
// class LLWearableType
|
||||
|
||||
LLWearableType::LLWearableType(LLTranslationBridge* trans)
|
||||
LLWearableType::LLWearableType(LLTranslationBridge::ptr_t &trans)
|
||||
: mDictionary(trans)
|
||||
{
|
||||
// LLTranslationBridge exists, but is not ready at this point in time since strings.xml is not yet loaded
|
||||
mTrans = trans;
|
||||
}
|
||||
|
||||
LLWearableType::~LLWearableType()
|
||||
{
|
||||
delete mTrans;
|
||||
}
|
||||
|
||||
void LLWearableType::initSingleton()
|
||||
{
|
||||
// To make sure all wrapping functions will crash without initing LLWearableType;
|
||||
LLWearableDictionary::initParamSingleton(*this);
|
||||
|
||||
// Todo: consider merging LLWearableType and LLWearableDictionary
|
||||
}
|
||||
|
||||
// static
|
||||
LLWearableType::EType LLWearableType::typeNameToType(const std::string& type_name)
|
||||
{
|
||||
const LLWearableDictionary *dict = LLWearableDictionary::getInstance();
|
||||
const LLWearableType::EType wearable = dict->lookup(type_name);
|
||||
const LLWearableType::EType wearable = mDictionary.lookup(type_name);
|
||||
return wearable;
|
||||
}
|
||||
|
||||
// static
|
||||
const std::string& LLWearableType::getTypeName(LLWearableType::EType type)
|
||||
{
|
||||
const LLWearableDictionary *dict = LLWearableDictionary::getInstance();
|
||||
const WearableEntry *entry = dict->lookup(type);
|
||||
const WearableEntry *entry = mDictionary.lookup(type);
|
||||
if (!entry) return getTypeName(WT_INVALID);
|
||||
return entry->mName;
|
||||
}
|
||||
|
||||
//static
|
||||
const std::string& LLWearableType::getTypeDefaultNewName(LLWearableType::EType type)
|
||||
{
|
||||
const LLWearableDictionary *dict = LLWearableDictionary::getInstance();
|
||||
const WearableEntry *entry = dict->lookup(type);
|
||||
const WearableEntry *entry = mDictionary.lookup(type);
|
||||
if (!entry) return getTypeDefaultNewName(WT_INVALID);
|
||||
return entry->mDefaultNewName;
|
||||
}
|
||||
|
||||
// static
|
||||
const std::string& LLWearableType::getTypeLabel(LLWearableType::EType type)
|
||||
{
|
||||
const LLWearableDictionary *dict = LLWearableDictionary::getInstance();
|
||||
const WearableEntry *entry = dict->lookup(type);
|
||||
const WearableEntry *entry = mDictionary.lookup(type);
|
||||
if (!entry) return getTypeLabel(WT_INVALID);
|
||||
return entry->mLabel;
|
||||
}
|
||||
|
||||
// static
|
||||
LLAssetType::EType LLWearableType::getAssetType(LLWearableType::EType type)
|
||||
{
|
||||
const LLWearableDictionary *dict = LLWearableDictionary::getInstance();
|
||||
const WearableEntry *entry = dict->lookup(type);
|
||||
const WearableEntry *entry = mDictionary.lookup(type);
|
||||
if (!entry) return getAssetType(WT_INVALID);
|
||||
return entry->mAssetType;
|
||||
}
|
||||
|
||||
// static
|
||||
LLInventoryType::EIconName LLWearableType::getIconName(LLWearableType::EType type)
|
||||
{
|
||||
const LLWearableDictionary *dict = LLWearableDictionary::getInstance();
|
||||
const WearableEntry *entry = dict->lookup(type);
|
||||
const WearableEntry *entry = mDictionary.lookup(type);
|
||||
if (!entry) return getIconName(WT_INVALID);
|
||||
return entry->mIconName;
|
||||
}
|
||||
|
||||
// static
|
||||
BOOL LLWearableType::getDisableCameraSwitch(LLWearableType::EType type)
|
||||
{
|
||||
const LLWearableDictionary *dict = LLWearableDictionary::getInstance();
|
||||
const WearableEntry *entry = dict->lookup(type);
|
||||
const WearableEntry *entry = mDictionary.lookup(type);
|
||||
if (!entry) return FALSE;
|
||||
return entry->mDisableCameraSwitch;
|
||||
}
|
||||
|
||||
// static
|
||||
BOOL LLWearableType::getAllowMultiwear(LLWearableType::EType type)
|
||||
{
|
||||
const LLWearableDictionary *dict = LLWearableDictionary::getInstance();
|
||||
const WearableEntry *entry = dict->lookup(type);
|
||||
const WearableEntry *entry = mDictionary.lookup(type);
|
||||
if (!entry) return FALSE;
|
||||
return entry->mAllowMultiwear;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,10 +35,9 @@
|
|||
|
||||
class LLWearableType : public LLParamSingleton<LLWearableType>
|
||||
{
|
||||
LLSINGLETON(LLWearableType, LLTranslationBridge* trans);
|
||||
LLSINGLETON(LLWearableType, LLTranslationBridge::ptr_t &trans);
|
||||
~LLWearableType();
|
||||
void initSingleton();
|
||||
friend struct WearableEntry;
|
||||
public:
|
||||
enum EType
|
||||
{
|
||||
|
|
@ -67,20 +66,59 @@ public:
|
|||
|
||||
// Most methods are wrappers for dictionary, but if LLWearableType is not initialized,
|
||||
// they will crash. Whole LLWearableType is just wrapper for convinient calls.
|
||||
static const std::string& getTypeName(EType type);
|
||||
static const std::string& getTypeDefaultNewName(EType type);
|
||||
static const std::string& getTypeLabel(EType type);
|
||||
static LLAssetType::EType getAssetType(EType type);
|
||||
static EType typeNameToType(const std::string& type_name);
|
||||
static LLInventoryType::EIconName getIconName(EType type);
|
||||
static BOOL getDisableCameraSwitch(EType type);
|
||||
static BOOL getAllowMultiwear(EType type);
|
||||
const std::string& getTypeName(EType type);
|
||||
const std::string& getTypeDefaultNewName(EType type);
|
||||
const std::string& getTypeLabel(EType type);
|
||||
LLAssetType::EType getAssetType(EType type);
|
||||
EType typeNameToType(const std::string& type_name);
|
||||
LLInventoryType::EIconName getIconName(EType type);
|
||||
BOOL getDisableCameraSwitch(EType type);
|
||||
BOOL getAllowMultiwear(EType type);
|
||||
|
||||
static EType inventoryFlagsToWearableType(U32 flags);
|
||||
|
||||
protected:
|
||||
private:
|
||||
struct WearableEntry : public LLDictionaryEntry
|
||||
{
|
||||
WearableEntry(LLTranslationBridge::ptr_t& trans,
|
||||
const std::string &name,
|
||||
const std::string& default_new_name,
|
||||
LLAssetType::EType assetType,
|
||||
LLInventoryType::EIconName iconName,
|
||||
BOOL disable_camera_switch = FALSE,
|
||||
BOOL allow_multiwear = TRUE) :
|
||||
LLDictionaryEntry(name),
|
||||
mAssetType(assetType),
|
||||
mDefaultNewName(default_new_name),
|
||||
mLabel(trans->getString(name)),
|
||||
mIconName(iconName),
|
||||
mDisableCameraSwitch(disable_camera_switch),
|
||||
mAllowMultiwear(allow_multiwear)
|
||||
{
|
||||
|
||||
LLTranslationBridge* mTrans;
|
||||
}
|
||||
const LLAssetType::EType mAssetType;
|
||||
const std::string mLabel;
|
||||
const std::string mDefaultNewName;
|
||||
LLInventoryType::EIconName mIconName;
|
||||
BOOL mDisableCameraSwitch;
|
||||
BOOL mAllowMultiwear;
|
||||
};
|
||||
|
||||
class LLWearableDictionary : public LLDictionary<LLWearableType::EType, WearableEntry>
|
||||
{
|
||||
public:
|
||||
LLWearableDictionary(LLTranslationBridge::ptr_t& trans);
|
||||
~LLWearableDictionary() {}
|
||||
|
||||
// [RLVa:KB] - Checked: 2010-03-03 (RLVa-1.2.0a) | Added: RLVa-1.2.0a
|
||||
protected:
|
||||
// The default implementation asserts on 'notFound()' and returns -1 which isn't a valid EWearableType
|
||||
virtual LLWearableType::EType notFound() const { return LLWearableType::WT_INVALID; }
|
||||
// [/RLVa:KB]
|
||||
};
|
||||
|
||||
LLWearableDictionary mDictionary;
|
||||
};
|
||||
|
||||
#endif // LL_LLWEARABLETYPE_H
|
||||
|
|
|
|||
|
|
@ -72,7 +72,8 @@ mSystem(system),
|
|||
mCurrentInternetStreamp(NULL),
|
||||
mStreamGroup(NULL),
|
||||
mFMODInternetStreamChannelp(NULL),
|
||||
mGain(1.0f)
|
||||
mGain(1.0f),
|
||||
mWasAlreadyPlaying(false)
|
||||
{
|
||||
// Number of milliseconds of audio to buffer for the audio card.
|
||||
// Must be larger than the usual Second Life frame stutter time.
|
||||
|
|
@ -158,18 +159,14 @@ void LLStreamingAudio_FMODSTUDIO::update()
|
|||
if (Check_FMOD_Error(mCurrentInternetStreamp->getOpenState(open_state, &progress, &starving, &diskbusy), "FMOD::Sound::getOpenState"))
|
||||
{
|
||||
LL_WARNS() << "Internet stream openstate error: open_state = " << open_state << " - progress = " << progress << " - starving = " << starving << " - diskbusy = " << diskbusy << LL_ENDL;
|
||||
bool was_playing = mWasAlreadyPlaying;
|
||||
stop();
|
||||
return;
|
||||
}
|
||||
else if (open_state == FMOD_OPENSTATE_ERROR)
|
||||
{
|
||||
// Actually we might not get into this case at all since according to the
|
||||
// FMOD API doc, one should check the result of getOpenState for further
|
||||
// details, which most likely means if open_state is FMOD_OPENSTATE_ERROR,
|
||||
// calling getOpenState will return anything but FMOD_OK and we end up in
|
||||
// the if-case above.
|
||||
LL_WARNS() << "Internet stream openstate error: progress = " << progress << " - starving = " << starving << " - diskbusy = " << diskbusy << LL_ENDL;
|
||||
stop();
|
||||
// Try to restart previously playing stream on socket error
|
||||
if (open_state == FMOD_OPENSTATE_ERROR && was_playing)
|
||||
{
|
||||
LL_WARNS() << "Stream was playing before - trying to restart" << LL_ENDL;
|
||||
start(mURL);
|
||||
}
|
||||
return;
|
||||
}
|
||||
else if (open_state == FMOD_OPENSTATE_READY)
|
||||
|
|
@ -183,6 +180,14 @@ void LLStreamingAudio_FMODSTUDIO::update()
|
|||
// Reset volume to previously set volume
|
||||
setGain(getGain());
|
||||
Check_FMOD_Error(mFMODInternetStreamChannelp->setPaused(false), "FMOD::Channel::setPaused");
|
||||
mWasAlreadyPlaying = true;
|
||||
}
|
||||
}
|
||||
else if (open_state == FMOD_OPENSTATE_PLAYING)
|
||||
{
|
||||
if (!mWasAlreadyPlaying)
|
||||
{
|
||||
mWasAlreadyPlaying = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -317,6 +322,7 @@ void LLStreamingAudio_FMODSTUDIO::update()
|
|||
void LLStreamingAudio_FMODSTUDIO::stop()
|
||||
{
|
||||
mPendingURL.clear();
|
||||
mWasAlreadyPlaying = false;
|
||||
|
||||
if (mFMODInternetStreamChannelp)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -80,6 +80,8 @@ private:
|
|||
bool mNewMetadata;
|
||||
LLSD mMetadata;
|
||||
// </DKO> Streamtitle display
|
||||
|
||||
bool mWasAlreadyPlaying;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -208,9 +208,9 @@ set(llcommon_HEADER_FILES
|
|||
llqueuedthread.h
|
||||
llrand.h
|
||||
llrefcount.h
|
||||
llregex.h
|
||||
llregistry.h
|
||||
llrun.h
|
||||
llrefcount.h
|
||||
llsafehandle.h
|
||||
llsd.h
|
||||
llsdjson.h
|
||||
|
|
@ -256,13 +256,14 @@ set(llcommon_HEADER_FILES
|
|||
StackWalker.h
|
||||
)
|
||||
|
||||
# <FS:ND> Add all nd* files. memory pool, intrinsics, ...
|
||||
# <FS:Beq> Tracy Profiler support
|
||||
list(APPEND llcommon_SOURCE_FILES fstelemetry.cpp)
|
||||
if (USE_TRACY_PROFILER)
|
||||
list(APPEND llcommon_SOURCE_FILES fstracyclient.cpp)
|
||||
endif()
|
||||
|
||||
# <FS:Beq> Tracy Profiler support
|
||||
list(APPEND llcommon_SOURCE_FILES fstelemetry.cpp)
|
||||
if (USE_TRACY_PROFILER)
|
||||
list(APPEND llcommon_SOURCE_FILES fstracyclient.cpp)
|
||||
endif()
|
||||
# </FS:Beq> Tracy Profiler support
|
||||
|
||||
# <FS:ND> Add all nd* files. memory pool, intrinsics, ...
|
||||
SET( llcommon_ND_SOURCE_FILES
|
||||
nd/ndexceptions.cpp
|
||||
nd/ndlogthrottle.cpp
|
||||
|
|
|
|||
|
|
@ -0,0 +1,582 @@
|
|||
// Provides an efficient blocking version of moodycamel::ConcurrentQueue.
|
||||
// ©2015-2020 Cameron Desrochers. Distributed under the terms of the simplified
|
||||
// BSD license, available at the top of concurrentqueue.h.
|
||||
// Also dual-licensed under the Boost Software License (see LICENSE.md)
|
||||
// Uses Jeff Preshing's semaphore implementation (under the terms of its
|
||||
// separate zlib license, see lightweightsemaphore.h).
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "concurrentqueue.h"
|
||||
#include "lightweightsemaphore.h"
|
||||
|
||||
#include <type_traits>
|
||||
#include <cerrno>
|
||||
#include <memory>
|
||||
#include <chrono>
|
||||
#include <ctime>
|
||||
|
||||
namespace moodycamel
|
||||
{
|
||||
// This is a blocking version of the queue. It has an almost identical interface to
|
||||
// the normal non-blocking version, with the addition of various wait_dequeue() methods
|
||||
// and the removal of producer-specific dequeue methods.
|
||||
template<typename T, typename Traits = ConcurrentQueueDefaultTraits>
|
||||
class BlockingConcurrentQueue
|
||||
{
|
||||
private:
|
||||
typedef ::moodycamel::ConcurrentQueue<T, Traits> ConcurrentQueue;
|
||||
typedef ::moodycamel::LightweightSemaphore LightweightSemaphore;
|
||||
|
||||
public:
|
||||
typedef typename ConcurrentQueue::producer_token_t producer_token_t;
|
||||
typedef typename ConcurrentQueue::consumer_token_t consumer_token_t;
|
||||
|
||||
typedef typename ConcurrentQueue::index_t index_t;
|
||||
typedef typename ConcurrentQueue::size_t size_t;
|
||||
typedef typename std::make_signed<size_t>::type ssize_t;
|
||||
|
||||
static const size_t BLOCK_SIZE = ConcurrentQueue::BLOCK_SIZE;
|
||||
static const size_t EXPLICIT_BLOCK_EMPTY_COUNTER_THRESHOLD = ConcurrentQueue::EXPLICIT_BLOCK_EMPTY_COUNTER_THRESHOLD;
|
||||
static const size_t EXPLICIT_INITIAL_INDEX_SIZE = ConcurrentQueue::EXPLICIT_INITIAL_INDEX_SIZE;
|
||||
static const size_t IMPLICIT_INITIAL_INDEX_SIZE = ConcurrentQueue::IMPLICIT_INITIAL_INDEX_SIZE;
|
||||
static const size_t INITIAL_IMPLICIT_PRODUCER_HASH_SIZE = ConcurrentQueue::INITIAL_IMPLICIT_PRODUCER_HASH_SIZE;
|
||||
static const std::uint32_t EXPLICIT_CONSUMER_CONSUMPTION_QUOTA_BEFORE_ROTATE = ConcurrentQueue::EXPLICIT_CONSUMER_CONSUMPTION_QUOTA_BEFORE_ROTATE;
|
||||
static const size_t MAX_SUBQUEUE_SIZE = ConcurrentQueue::MAX_SUBQUEUE_SIZE;
|
||||
|
||||
public:
|
||||
// Creates a queue with at least `capacity` element slots; note that the
|
||||
// actual number of elements that can be inserted without additional memory
|
||||
// allocation depends on the number of producers and the block size (e.g. if
|
||||
// the block size is equal to `capacity`, only a single block will be allocated
|
||||
// up-front, which means only a single producer will be able to enqueue elements
|
||||
// without an extra allocation -- blocks aren't shared between producers).
|
||||
// This method is not thread safe -- it is up to the user to ensure that the
|
||||
// queue is fully constructed before it starts being used by other threads (this
|
||||
// includes making the memory effects of construction visible, possibly with a
|
||||
// memory barrier).
|
||||
explicit BlockingConcurrentQueue(size_t capacity = 6 * BLOCK_SIZE)
|
||||
: inner(capacity), sema(create<LightweightSemaphore, ssize_t, int>(0, (int)Traits::MAX_SEMA_SPINS), &BlockingConcurrentQueue::template destroy<LightweightSemaphore>)
|
||||
{
|
||||
assert(reinterpret_cast<ConcurrentQueue*>((BlockingConcurrentQueue*)1) == &((BlockingConcurrentQueue*)1)->inner && "BlockingConcurrentQueue must have ConcurrentQueue as its first member");
|
||||
if (!sema) {
|
||||
MOODYCAMEL_THROW(std::bad_alloc());
|
||||
}
|
||||
}
|
||||
|
||||
BlockingConcurrentQueue(size_t minCapacity, size_t maxExplicitProducers, size_t maxImplicitProducers)
|
||||
: inner(minCapacity, maxExplicitProducers, maxImplicitProducers), sema(create<LightweightSemaphore, ssize_t, int>(0, (int)Traits::MAX_SEMA_SPINS), &BlockingConcurrentQueue::template destroy<LightweightSemaphore>)
|
||||
{
|
||||
assert(reinterpret_cast<ConcurrentQueue*>((BlockingConcurrentQueue*)1) == &((BlockingConcurrentQueue*)1)->inner && "BlockingConcurrentQueue must have ConcurrentQueue as its first member");
|
||||
if (!sema) {
|
||||
MOODYCAMEL_THROW(std::bad_alloc());
|
||||
}
|
||||
}
|
||||
|
||||
// Disable copying and copy assignment
|
||||
BlockingConcurrentQueue(BlockingConcurrentQueue const&) MOODYCAMEL_DELETE_FUNCTION;
|
||||
BlockingConcurrentQueue& operator=(BlockingConcurrentQueue const&) MOODYCAMEL_DELETE_FUNCTION;
|
||||
|
||||
// Moving is supported, but note that it is *not* a thread-safe operation.
|
||||
// Nobody can use the queue while it's being moved, and the memory effects
|
||||
// of that move must be propagated to other threads before they can use it.
|
||||
// Note: When a queue is moved, its tokens are still valid but can only be
|
||||
// used with the destination queue (i.e. semantically they are moved along
|
||||
// with the queue itself).
|
||||
BlockingConcurrentQueue(BlockingConcurrentQueue&& other) MOODYCAMEL_NOEXCEPT
|
||||
: inner(std::move(other.inner)), sema(std::move(other.sema))
|
||||
{ }
|
||||
|
||||
inline BlockingConcurrentQueue& operator=(BlockingConcurrentQueue&& other) MOODYCAMEL_NOEXCEPT
|
||||
{
|
||||
return swap_internal(other);
|
||||
}
|
||||
|
||||
// Swaps this queue's state with the other's. Not thread-safe.
|
||||
// Swapping two queues does not invalidate their tokens, however
|
||||
// the tokens that were created for one queue must be used with
|
||||
// only the swapped queue (i.e. the tokens are tied to the
|
||||
// queue's movable state, not the object itself).
|
||||
inline void swap(BlockingConcurrentQueue& other) MOODYCAMEL_NOEXCEPT
|
||||
{
|
||||
swap_internal(other);
|
||||
}
|
||||
|
||||
private:
|
||||
BlockingConcurrentQueue& swap_internal(BlockingConcurrentQueue& other)
|
||||
{
|
||||
if (this == &other) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
inner.swap(other.inner);
|
||||
sema.swap(other.sema);
|
||||
return *this;
|
||||
}
|
||||
|
||||
public:
|
||||
// Enqueues a single item (by copying it).
|
||||
// Allocates memory if required. Only fails if memory allocation fails (or implicit
|
||||
// production is disabled because Traits::INITIAL_IMPLICIT_PRODUCER_HASH_SIZE is 0,
|
||||
// or Traits::MAX_SUBQUEUE_SIZE has been defined and would be surpassed).
|
||||
// Thread-safe.
|
||||
inline bool enqueue(T const& item)
|
||||
{
|
||||
if ((details::likely)(inner.enqueue(item))) {
|
||||
sema->signal();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Enqueues a single item (by moving it, if possible).
|
||||
// Allocates memory if required. Only fails if memory allocation fails (or implicit
|
||||
// production is disabled because Traits::INITIAL_IMPLICIT_PRODUCER_HASH_SIZE is 0,
|
||||
// or Traits::MAX_SUBQUEUE_SIZE has been defined and would be surpassed).
|
||||
// Thread-safe.
|
||||
inline bool enqueue(T&& item)
|
||||
{
|
||||
if ((details::likely)(inner.enqueue(std::move(item)))) {
|
||||
sema->signal();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Enqueues a single item (by copying it) using an explicit producer token.
|
||||
// Allocates memory if required. Only fails if memory allocation fails (or
|
||||
// Traits::MAX_SUBQUEUE_SIZE has been defined and would be surpassed).
|
||||
// Thread-safe.
|
||||
inline bool enqueue(producer_token_t const& token, T const& item)
|
||||
{
|
||||
if ((details::likely)(inner.enqueue(token, item))) {
|
||||
sema->signal();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Enqueues a single item (by moving it, if possible) using an explicit producer token.
|
||||
// Allocates memory if required. Only fails if memory allocation fails (or
|
||||
// Traits::MAX_SUBQUEUE_SIZE has been defined and would be surpassed).
|
||||
// Thread-safe.
|
||||
inline bool enqueue(producer_token_t const& token, T&& item)
|
||||
{
|
||||
if ((details::likely)(inner.enqueue(token, std::move(item)))) {
|
||||
sema->signal();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Enqueues several items.
|
||||
// Allocates memory if required. Only fails if memory allocation fails (or
|
||||
// implicit production is disabled because Traits::INITIAL_IMPLICIT_PRODUCER_HASH_SIZE
|
||||
// is 0, or Traits::MAX_SUBQUEUE_SIZE has been defined and would be surpassed).
|
||||
// Note: Use std::make_move_iterator if the elements should be moved instead of copied.
|
||||
// Thread-safe.
|
||||
template<typename It>
|
||||
inline bool enqueue_bulk(It itemFirst, size_t count)
|
||||
{
|
||||
if ((details::likely)(inner.enqueue_bulk(std::forward<It>(itemFirst), count))) {
|
||||
sema->signal((LightweightSemaphore::ssize_t)(ssize_t)count);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Enqueues several items using an explicit producer token.
|
||||
// Allocates memory if required. Only fails if memory allocation fails
|
||||
// (or Traits::MAX_SUBQUEUE_SIZE has been defined and would be surpassed).
|
||||
// Note: Use std::make_move_iterator if the elements should be moved
|
||||
// instead of copied.
|
||||
// Thread-safe.
|
||||
template<typename It>
|
||||
inline bool enqueue_bulk(producer_token_t const& token, It itemFirst, size_t count)
|
||||
{
|
||||
if ((details::likely)(inner.enqueue_bulk(token, std::forward<It>(itemFirst), count))) {
|
||||
sema->signal((LightweightSemaphore::ssize_t)(ssize_t)count);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Enqueues a single item (by copying it).
|
||||
// Does not allocate memory. Fails if not enough room to enqueue (or implicit
|
||||
// production is disabled because Traits::INITIAL_IMPLICIT_PRODUCER_HASH_SIZE
|
||||
// is 0).
|
||||
// Thread-safe.
|
||||
inline bool try_enqueue(T const& item)
|
||||
{
|
||||
if (inner.try_enqueue(item)) {
|
||||
sema->signal();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Enqueues a single item (by moving it, if possible).
|
||||
// Does not allocate memory (except for one-time implicit producer).
|
||||
// Fails if not enough room to enqueue (or implicit production is
|
||||
// disabled because Traits::INITIAL_IMPLICIT_PRODUCER_HASH_SIZE is 0).
|
||||
// Thread-safe.
|
||||
inline bool try_enqueue(T&& item)
|
||||
{
|
||||
if (inner.try_enqueue(std::move(item))) {
|
||||
sema->signal();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Enqueues a single item (by copying it) using an explicit producer token.
|
||||
// Does not allocate memory. Fails if not enough room to enqueue.
|
||||
// Thread-safe.
|
||||
inline bool try_enqueue(producer_token_t const& token, T const& item)
|
||||
{
|
||||
if (inner.try_enqueue(token, item)) {
|
||||
sema->signal();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Enqueues a single item (by moving it, if possible) using an explicit producer token.
|
||||
// Does not allocate memory. Fails if not enough room to enqueue.
|
||||
// Thread-safe.
|
||||
inline bool try_enqueue(producer_token_t const& token, T&& item)
|
||||
{
|
||||
if (inner.try_enqueue(token, std::move(item))) {
|
||||
sema->signal();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Enqueues several items.
|
||||
// Does not allocate memory (except for one-time implicit producer).
|
||||
// Fails if not enough room to enqueue (or implicit production is
|
||||
// disabled because Traits::INITIAL_IMPLICIT_PRODUCER_HASH_SIZE is 0).
|
||||
// Note: Use std::make_move_iterator if the elements should be moved
|
||||
// instead of copied.
|
||||
// Thread-safe.
|
||||
template<typename It>
|
||||
inline bool try_enqueue_bulk(It itemFirst, size_t count)
|
||||
{
|
||||
if (inner.try_enqueue_bulk(std::forward<It>(itemFirst), count)) {
|
||||
sema->signal((LightweightSemaphore::ssize_t)(ssize_t)count);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Enqueues several items using an explicit producer token.
|
||||
// Does not allocate memory. Fails if not enough room to enqueue.
|
||||
// Note: Use std::make_move_iterator if the elements should be moved
|
||||
// instead of copied.
|
||||
// Thread-safe.
|
||||
template<typename It>
|
||||
inline bool try_enqueue_bulk(producer_token_t const& token, It itemFirst, size_t count)
|
||||
{
|
||||
if (inner.try_enqueue_bulk(token, std::forward<It>(itemFirst), count)) {
|
||||
sema->signal((LightweightSemaphore::ssize_t)(ssize_t)count);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// Attempts to dequeue from the queue.
|
||||
// Returns false if all producer streams appeared empty at the time they
|
||||
// were checked (so, the queue is likely but not guaranteed to be empty).
|
||||
// Never allocates. Thread-safe.
|
||||
template<typename U>
|
||||
inline bool try_dequeue(U& item)
|
||||
{
|
||||
if (sema->tryWait()) {
|
||||
while (!inner.try_dequeue(item)) {
|
||||
continue;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Attempts to dequeue from the queue using an explicit consumer token.
|
||||
// Returns false if all producer streams appeared empty at the time they
|
||||
// were checked (so, the queue is likely but not guaranteed to be empty).
|
||||
// Never allocates. Thread-safe.
|
||||
template<typename U>
|
||||
inline bool try_dequeue(consumer_token_t& token, U& item)
|
||||
{
|
||||
if (sema->tryWait()) {
|
||||
while (!inner.try_dequeue(token, item)) {
|
||||
continue;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Attempts to dequeue several elements from the queue.
|
||||
// Returns the number of items actually dequeued.
|
||||
// Returns 0 if all producer streams appeared empty at the time they
|
||||
// were checked (so, the queue is likely but not guaranteed to be empty).
|
||||
// Never allocates. Thread-safe.
|
||||
template<typename It>
|
||||
inline size_t try_dequeue_bulk(It itemFirst, size_t max)
|
||||
{
|
||||
size_t count = 0;
|
||||
max = (size_t)sema->tryWaitMany((LightweightSemaphore::ssize_t)(ssize_t)max);
|
||||
while (count != max) {
|
||||
count += inner.template try_dequeue_bulk<It&>(itemFirst, max - count);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
// Attempts to dequeue several elements from the queue using an explicit consumer token.
|
||||
// Returns the number of items actually dequeued.
|
||||
// Returns 0 if all producer streams appeared empty at the time they
|
||||
// were checked (so, the queue is likely but not guaranteed to be empty).
|
||||
// Never allocates. Thread-safe.
|
||||
template<typename It>
|
||||
inline size_t try_dequeue_bulk(consumer_token_t& token, It itemFirst, size_t max)
|
||||
{
|
||||
size_t count = 0;
|
||||
max = (size_t)sema->tryWaitMany((LightweightSemaphore::ssize_t)(ssize_t)max);
|
||||
while (count != max) {
|
||||
count += inner.template try_dequeue_bulk<It&>(token, itemFirst, max - count);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Blocks the current thread until there's something to dequeue, then
|
||||
// dequeues it.
|
||||
// Never allocates. Thread-safe.
|
||||
template<typename U>
|
||||
inline void wait_dequeue(U& item)
|
||||
{
|
||||
while (!sema->wait()) {
|
||||
continue;
|
||||
}
|
||||
while (!inner.try_dequeue(item)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Blocks the current thread until either there's something to dequeue
|
||||
// or the timeout (specified in microseconds) expires. Returns false
|
||||
// without setting `item` if the timeout expires, otherwise assigns
|
||||
// to `item` and returns true.
|
||||
// Using a negative timeout indicates an indefinite timeout,
|
||||
// and is thus functionally equivalent to calling wait_dequeue.
|
||||
// Never allocates. Thread-safe.
|
||||
template<typename U>
|
||||
inline bool wait_dequeue_timed(U& item, std::int64_t timeout_usecs)
|
||||
{
|
||||
if (!sema->wait(timeout_usecs)) {
|
||||
return false;
|
||||
}
|
||||
while (!inner.try_dequeue(item)) {
|
||||
continue;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Blocks the current thread until either there's something to dequeue
|
||||
// or the timeout expires. Returns false without setting `item` if the
|
||||
// timeout expires, otherwise assigns to `item` and returns true.
|
||||
// Never allocates. Thread-safe.
|
||||
template<typename U, typename Rep, typename Period>
|
||||
inline bool wait_dequeue_timed(U& item, std::chrono::duration<Rep, Period> const& timeout)
|
||||
{
|
||||
return wait_dequeue_timed(item, std::chrono::duration_cast<std::chrono::microseconds>(timeout).count());
|
||||
}
|
||||
|
||||
// Blocks the current thread until there's something to dequeue, then
|
||||
// dequeues it using an explicit consumer token.
|
||||
// Never allocates. Thread-safe.
|
||||
template<typename U>
|
||||
inline void wait_dequeue(consumer_token_t& token, U& item)
|
||||
{
|
||||
while (!sema->wait()) {
|
||||
continue;
|
||||
}
|
||||
while (!inner.try_dequeue(token, item)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Blocks the current thread until either there's something to dequeue
|
||||
// or the timeout (specified in microseconds) expires. Returns false
|
||||
// without setting `item` if the timeout expires, otherwise assigns
|
||||
// to `item` and returns true.
|
||||
// Using a negative timeout indicates an indefinite timeout,
|
||||
// and is thus functionally equivalent to calling wait_dequeue.
|
||||
// Never allocates. Thread-safe.
|
||||
template<typename U>
|
||||
inline bool wait_dequeue_timed(consumer_token_t& token, U& item, std::int64_t timeout_usecs)
|
||||
{
|
||||
if (!sema->wait(timeout_usecs)) {
|
||||
return false;
|
||||
}
|
||||
while (!inner.try_dequeue(token, item)) {
|
||||
continue;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Blocks the current thread until either there's something to dequeue
|
||||
// or the timeout expires. Returns false without setting `item` if the
|
||||
// timeout expires, otherwise assigns to `item` and returns true.
|
||||
// Never allocates. Thread-safe.
|
||||
template<typename U, typename Rep, typename Period>
|
||||
inline bool wait_dequeue_timed(consumer_token_t& token, U& item, std::chrono::duration<Rep, Period> const& timeout)
|
||||
{
|
||||
return wait_dequeue_timed(token, item, std::chrono::duration_cast<std::chrono::microseconds>(timeout).count());
|
||||
}
|
||||
|
||||
// Attempts to dequeue several elements from the queue.
|
||||
// Returns the number of items actually dequeued, which will
|
||||
// always be at least one (this method blocks until the queue
|
||||
// is non-empty) and at most max.
|
||||
// Never allocates. Thread-safe.
|
||||
template<typename It>
|
||||
inline size_t wait_dequeue_bulk(It itemFirst, size_t max)
|
||||
{
|
||||
size_t count = 0;
|
||||
max = (size_t)sema->waitMany((LightweightSemaphore::ssize_t)(ssize_t)max);
|
||||
while (count != max) {
|
||||
count += inner.template try_dequeue_bulk<It&>(itemFirst, max - count);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
// Attempts to dequeue several elements from the queue.
|
||||
// Returns the number of items actually dequeued, which can
|
||||
// be 0 if the timeout expires while waiting for elements,
|
||||
// and at most max.
|
||||
// Using a negative timeout indicates an indefinite timeout,
|
||||
// and is thus functionally equivalent to calling wait_dequeue_bulk.
|
||||
// Never allocates. Thread-safe.
|
||||
template<typename It>
|
||||
inline size_t wait_dequeue_bulk_timed(It itemFirst, size_t max, std::int64_t timeout_usecs)
|
||||
{
|
||||
size_t count = 0;
|
||||
max = (size_t)sema->waitMany((LightweightSemaphore::ssize_t)(ssize_t)max, timeout_usecs);
|
||||
while (count != max) {
|
||||
count += inner.template try_dequeue_bulk<It&>(itemFirst, max - count);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
// Attempts to dequeue several elements from the queue.
|
||||
// Returns the number of items actually dequeued, which can
|
||||
// be 0 if the timeout expires while waiting for elements,
|
||||
// and at most max.
|
||||
// Never allocates. Thread-safe.
|
||||
template<typename It, typename Rep, typename Period>
|
||||
inline size_t wait_dequeue_bulk_timed(It itemFirst, size_t max, std::chrono::duration<Rep, Period> const& timeout)
|
||||
{
|
||||
return wait_dequeue_bulk_timed<It&>(itemFirst, max, std::chrono::duration_cast<std::chrono::microseconds>(timeout).count());
|
||||
}
|
||||
|
||||
// Attempts to dequeue several elements from the queue using an explicit consumer token.
|
||||
// Returns the number of items actually dequeued, which will
|
||||
// always be at least one (this method blocks until the queue
|
||||
// is non-empty) and at most max.
|
||||
// Never allocates. Thread-safe.
|
||||
template<typename It>
|
||||
inline size_t wait_dequeue_bulk(consumer_token_t& token, It itemFirst, size_t max)
|
||||
{
|
||||
size_t count = 0;
|
||||
max = (size_t)sema->waitMany((LightweightSemaphore::ssize_t)(ssize_t)max);
|
||||
while (count != max) {
|
||||
count += inner.template try_dequeue_bulk<It&>(token, itemFirst, max - count);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
// Attempts to dequeue several elements from the queue using an explicit consumer token.
|
||||
// Returns the number of items actually dequeued, which can
|
||||
// be 0 if the timeout expires while waiting for elements,
|
||||
// and at most max.
|
||||
// Using a negative timeout indicates an indefinite timeout,
|
||||
// and is thus functionally equivalent to calling wait_dequeue_bulk.
|
||||
// Never allocates. Thread-safe.
|
||||
template<typename It>
|
||||
inline size_t wait_dequeue_bulk_timed(consumer_token_t& token, It itemFirst, size_t max, std::int64_t timeout_usecs)
|
||||
{
|
||||
size_t count = 0;
|
||||
max = (size_t)sema->waitMany((LightweightSemaphore::ssize_t)(ssize_t)max, timeout_usecs);
|
||||
while (count != max) {
|
||||
count += inner.template try_dequeue_bulk<It&>(token, itemFirst, max - count);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
// Attempts to dequeue several elements from the queue using an explicit consumer token.
|
||||
// Returns the number of items actually dequeued, which can
|
||||
// be 0 if the timeout expires while waiting for elements,
|
||||
// and at most max.
|
||||
// Never allocates. Thread-safe.
|
||||
template<typename It, typename Rep, typename Period>
|
||||
inline size_t wait_dequeue_bulk_timed(consumer_token_t& token, It itemFirst, size_t max, std::chrono::duration<Rep, Period> const& timeout)
|
||||
{
|
||||
return wait_dequeue_bulk_timed<It&>(token, itemFirst, max, std::chrono::duration_cast<std::chrono::microseconds>(timeout).count());
|
||||
}
|
||||
|
||||
|
||||
// Returns an estimate of the total number of elements currently in the queue. This
|
||||
// estimate is only accurate if the queue has completely stabilized before it is called
|
||||
// (i.e. all enqueue and dequeue operations have completed and their memory effects are
|
||||
// visible on the calling thread, and no further operations start while this method is
|
||||
// being called).
|
||||
// Thread-safe.
|
||||
inline size_t size_approx() const
|
||||
{
|
||||
return (size_t)sema->availableApprox();
|
||||
}
|
||||
|
||||
|
||||
// Returns true if the underlying atomic variables used by
|
||||
// the queue are lock-free (they should be on most platforms).
|
||||
// Thread-safe.
|
||||
static bool is_lock_free()
|
||||
{
|
||||
return ConcurrentQueue::is_lock_free();
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
template<typename U, typename A1, typename A2>
|
||||
static inline U* create(A1&& a1, A2&& a2)
|
||||
{
|
||||
void* p = (Traits::malloc)(sizeof(U));
|
||||
return p != nullptr ? new (p) U(std::forward<A1>(a1), std::forward<A2>(a2)) : nullptr;
|
||||
}
|
||||
|
||||
template<typename U>
|
||||
static inline void destroy(U* p)
|
||||
{
|
||||
if (p != nullptr) {
|
||||
p->~U();
|
||||
}
|
||||
(Traits::free)(p);
|
||||
}
|
||||
|
||||
private:
|
||||
ConcurrentQueue inner;
|
||||
std::unique_ptr<LightweightSemaphore, void (*)(LightweightSemaphore*)> sema;
|
||||
};
|
||||
|
||||
|
||||
template<typename T, typename Traits>
|
||||
inline void swap(BlockingConcurrentQueue<T, Traits>& a, BlockingConcurrentQueue<T, Traits>& b) MOODYCAMEL_NOEXCEPT
|
||||
{
|
||||
a.swap(b);
|
||||
}
|
||||
|
||||
} // end namespace moodycamel
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -28,4 +28,5 @@
|
|||
namespace FSTelemetry
|
||||
{
|
||||
bool active{false};
|
||||
|
||||
}
|
||||
|
|
@ -43,9 +43,15 @@
|
|||
#define FSZoneN( name ) ZoneNamedN( ___tracy_scoped_zone, name, FSTelemetry::active)
|
||||
#define FSZoneC( color ) ZoneNamedC( ___tracy_scoped_zone, color, FSTelemetry::active)
|
||||
#define FSZoneNC( name, color ) ZoneNamedNC( ___tracy_scoped_zone, name, color, FSTelemetry::active)
|
||||
#define FSZoneText( text, size ) ZoneText( text, size )
|
||||
#define FSZoneValue( num_uint64 ) ZoneValue( num_uint64 )
|
||||
#define FSPlot( name, value ) TracyPlot( name, value)
|
||||
#define FSPlotSq( name, lastval, newval ) TracyPlot( name, lastval);TracyPlot( name, newval);
|
||||
#define FSFrameMark FrameMark
|
||||
#define FSFrameMarkStart( name ) FrameMarkStart( name )
|
||||
#define FSFrameMarkEnd( name ) FrameMarkEnd( name )
|
||||
#define FSThreadName( name ) tracy::SetThreadName( name )
|
||||
#define FSMessageL ( message ) tracy::Profiler::Message( message, 0 )
|
||||
#define FSTelemetryIsConnected TracyIsConnected
|
||||
|
||||
#else // (no telemetry)
|
||||
|
|
@ -57,15 +63,26 @@
|
|||
#define FSZoneN( name )
|
||||
#define FSZoneC( color )
|
||||
#define FSZoneNC( name, color )
|
||||
#define FSZoneText( text, size )
|
||||
#define FSZoneValue( num_uint64 )
|
||||
#define FSPlot( name, value )
|
||||
#define FSPlotSq( name, lastval, newval )
|
||||
#define FSFrameMark
|
||||
#define FSFrameMarkStart( name )
|
||||
#define FSFrameMarkEnd( name )
|
||||
#define FSThreadName( name )
|
||||
#define FSMessageL( message )
|
||||
#define FSTelemetryIsConnected
|
||||
#endif // TRACY_ENABLE
|
||||
|
||||
#include <chrono>
|
||||
#include <array>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace FSTelemetry
|
||||
{
|
||||
extern bool active;
|
||||
}
|
||||
|
||||
}// namespace FSTelemetry
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,411 @@
|
|||
// Provides an efficient implementation of a semaphore (LightweightSemaphore).
|
||||
// This is an extension of Jeff Preshing's sempahore implementation (licensed
|
||||
// under the terms of its separate zlib license) that has been adapted and
|
||||
// extended by Cameron Desrochers.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstddef> // For std::size_t
|
||||
#include <atomic>
|
||||
#include <type_traits> // For std::make_signed<T>
|
||||
|
||||
#if defined(_WIN32)
|
||||
// Avoid including windows.h in a header; we only need a handful of
|
||||
// items, so we'll redeclare them here (this is relatively safe since
|
||||
// the API generally has to remain stable between Windows versions).
|
||||
// I know this is an ugly hack but it still beats polluting the global
|
||||
// namespace with thousands of generic names or adding a .cpp for nothing.
|
||||
extern "C" {
|
||||
struct _SECURITY_ATTRIBUTES;
|
||||
__declspec(dllimport) void* __stdcall CreateSemaphoreW(_SECURITY_ATTRIBUTES* lpSemaphoreAttributes, long lInitialCount, long lMaximumCount, const wchar_t* lpName);
|
||||
__declspec(dllimport) int __stdcall CloseHandle(void* hObject);
|
||||
__declspec(dllimport) unsigned long __stdcall WaitForSingleObject(void* hHandle, unsigned long dwMilliseconds);
|
||||
__declspec(dllimport) int __stdcall ReleaseSemaphore(void* hSemaphore, long lReleaseCount, long* lpPreviousCount);
|
||||
}
|
||||
#elif defined(__MACH__)
|
||||
#include <mach/mach.h>
|
||||
#elif defined(__unix__)
|
||||
#include <semaphore.h>
|
||||
#endif
|
||||
|
||||
namespace moodycamel
|
||||
{
|
||||
namespace details
|
||||
{
|
||||
|
||||
// Code in the mpmc_sema namespace below is an adaptation of Jeff Preshing's
|
||||
// portable + lightweight semaphore implementations, originally from
|
||||
// https://github.com/preshing/cpp11-on-multicore/blob/master/common/sema.h
|
||||
// LICENSE:
|
||||
// Copyright (c) 2015 Jeff Preshing
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgement in the product documentation would be
|
||||
// appreciated but is not required.
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
// 3. This notice may not be removed or altered from any source distribution.
|
||||
#if defined(_WIN32)
|
||||
class Semaphore
|
||||
{
|
||||
private:
|
||||
void* m_hSema;
|
||||
|
||||
Semaphore(const Semaphore& other) MOODYCAMEL_DELETE_FUNCTION;
|
||||
Semaphore& operator=(const Semaphore& other) MOODYCAMEL_DELETE_FUNCTION;
|
||||
|
||||
public:
|
||||
Semaphore(int initialCount = 0)
|
||||
{
|
||||
assert(initialCount >= 0);
|
||||
const long maxLong = 0x7fffffff;
|
||||
m_hSema = CreateSemaphoreW(nullptr, initialCount, maxLong, nullptr);
|
||||
assert(m_hSema);
|
||||
}
|
||||
|
||||
~Semaphore()
|
||||
{
|
||||
CloseHandle(m_hSema);
|
||||
}
|
||||
|
||||
bool wait()
|
||||
{
|
||||
const unsigned long infinite = 0xffffffff;
|
||||
return WaitForSingleObject(m_hSema, infinite) == 0;
|
||||
}
|
||||
|
||||
bool try_wait()
|
||||
{
|
||||
return WaitForSingleObject(m_hSema, 0) == 0;
|
||||
}
|
||||
|
||||
bool timed_wait(std::uint64_t usecs)
|
||||
{
|
||||
return WaitForSingleObject(m_hSema, (unsigned long)(usecs / 1000)) == 0;
|
||||
}
|
||||
|
||||
void signal(int count = 1)
|
||||
{
|
||||
while (!ReleaseSemaphore(m_hSema, count, nullptr));
|
||||
}
|
||||
};
|
||||
#elif defined(__MACH__)
|
||||
//---------------------------------------------------------
|
||||
// Semaphore (Apple iOS and OSX)
|
||||
// Can't use POSIX semaphores due to http://lists.apple.com/archives/darwin-kernel/2009/Apr/msg00010.html
|
||||
//---------------------------------------------------------
|
||||
class Semaphore
|
||||
{
|
||||
private:
|
||||
semaphore_t m_sema;
|
||||
|
||||
Semaphore(const Semaphore& other) MOODYCAMEL_DELETE_FUNCTION;
|
||||
Semaphore& operator=(const Semaphore& other) MOODYCAMEL_DELETE_FUNCTION;
|
||||
|
||||
public:
|
||||
Semaphore(int initialCount = 0)
|
||||
{
|
||||
assert(initialCount >= 0);
|
||||
kern_return_t rc = semaphore_create(mach_task_self(), &m_sema, SYNC_POLICY_FIFO, initialCount);
|
||||
assert(rc == KERN_SUCCESS);
|
||||
(void)rc;
|
||||
}
|
||||
|
||||
~Semaphore()
|
||||
{
|
||||
semaphore_destroy(mach_task_self(), m_sema);
|
||||
}
|
||||
|
||||
bool wait()
|
||||
{
|
||||
return semaphore_wait(m_sema) == KERN_SUCCESS;
|
||||
}
|
||||
|
||||
bool try_wait()
|
||||
{
|
||||
return timed_wait(0);
|
||||
}
|
||||
|
||||
bool timed_wait(std::uint64_t timeout_usecs)
|
||||
{
|
||||
mach_timespec_t ts;
|
||||
ts.tv_sec = static_cast<unsigned int>(timeout_usecs / 1000000);
|
||||
ts.tv_nsec = static_cast<int>((timeout_usecs % 1000000) * 1000);
|
||||
|
||||
// added in OSX 10.10: https://developer.apple.com/library/prerelease/mac/documentation/General/Reference/APIDiffsMacOSX10_10SeedDiff/modules/Darwin.html
|
||||
kern_return_t rc = semaphore_timedwait(m_sema, ts);
|
||||
return rc == KERN_SUCCESS;
|
||||
}
|
||||
|
||||
void signal()
|
||||
{
|
||||
while (semaphore_signal(m_sema) != KERN_SUCCESS);
|
||||
}
|
||||
|
||||
void signal(int count)
|
||||
{
|
||||
while (count-- > 0)
|
||||
{
|
||||
while (semaphore_signal(m_sema) != KERN_SUCCESS);
|
||||
}
|
||||
}
|
||||
};
|
||||
#elif defined(__unix__)
|
||||
//---------------------------------------------------------
|
||||
// Semaphore (POSIX, Linux)
|
||||
//---------------------------------------------------------
|
||||
class Semaphore
|
||||
{
|
||||
private:
|
||||
sem_t m_sema;
|
||||
|
||||
Semaphore(const Semaphore& other) MOODYCAMEL_DELETE_FUNCTION;
|
||||
Semaphore& operator=(const Semaphore& other) MOODYCAMEL_DELETE_FUNCTION;
|
||||
|
||||
public:
|
||||
Semaphore(int initialCount = 0)
|
||||
{
|
||||
assert(initialCount >= 0);
|
||||
int rc = sem_init(&m_sema, 0, static_cast<unsigned int>(initialCount));
|
||||
assert(rc == 0);
|
||||
(void)rc;
|
||||
}
|
||||
|
||||
~Semaphore()
|
||||
{
|
||||
sem_destroy(&m_sema);
|
||||
}
|
||||
|
||||
bool wait()
|
||||
{
|
||||
// http://stackoverflow.com/questions/2013181/gdb-causes-sem-wait-to-fail-with-eintr-error
|
||||
int rc;
|
||||
do {
|
||||
rc = sem_wait(&m_sema);
|
||||
} while (rc == -1 && errno == EINTR);
|
||||
return rc == 0;
|
||||
}
|
||||
|
||||
bool try_wait()
|
||||
{
|
||||
int rc;
|
||||
do {
|
||||
rc = sem_trywait(&m_sema);
|
||||
} while (rc == -1 && errno == EINTR);
|
||||
return rc == 0;
|
||||
}
|
||||
|
||||
bool timed_wait(std::uint64_t usecs)
|
||||
{
|
||||
struct timespec ts;
|
||||
const int usecs_in_1_sec = 1000000;
|
||||
const int nsecs_in_1_sec = 1000000000;
|
||||
clock_gettime(CLOCK_REALTIME, &ts);
|
||||
ts.tv_sec += (time_t)(usecs / usecs_in_1_sec);
|
||||
ts.tv_nsec += (long)(usecs % usecs_in_1_sec) * 1000;
|
||||
// sem_timedwait bombs if you have more than 1e9 in tv_nsec
|
||||
// so we have to clean things up before passing it in
|
||||
if (ts.tv_nsec >= nsecs_in_1_sec) {
|
||||
ts.tv_nsec -= nsecs_in_1_sec;
|
||||
++ts.tv_sec;
|
||||
}
|
||||
|
||||
int rc;
|
||||
do {
|
||||
rc = sem_timedwait(&m_sema, &ts);
|
||||
} while (rc == -1 && errno == EINTR);
|
||||
return rc == 0;
|
||||
}
|
||||
|
||||
void signal()
|
||||
{
|
||||
while (sem_post(&m_sema) == -1);
|
||||
}
|
||||
|
||||
void signal(int count)
|
||||
{
|
||||
while (count-- > 0)
|
||||
{
|
||||
while (sem_post(&m_sema) == -1);
|
||||
}
|
||||
}
|
||||
};
|
||||
#else
|
||||
#error Unsupported platform! (No semaphore wrapper available)
|
||||
#endif
|
||||
|
||||
} // end namespace details
|
||||
|
||||
|
||||
//---------------------------------------------------------
|
||||
// LightweightSemaphore
|
||||
//---------------------------------------------------------
|
||||
class LightweightSemaphore
|
||||
{
|
||||
public:
|
||||
typedef std::make_signed<std::size_t>::type ssize_t;
|
||||
|
||||
private:
|
||||
std::atomic<ssize_t> m_count;
|
||||
details::Semaphore m_sema;
|
||||
int m_maxSpins;
|
||||
|
||||
bool waitWithPartialSpinning(std::int64_t timeout_usecs = -1)
|
||||
{
|
||||
ssize_t oldCount;
|
||||
int spin = m_maxSpins;
|
||||
while (--spin >= 0)
|
||||
{
|
||||
oldCount = m_count.load(std::memory_order_relaxed);
|
||||
if ((oldCount > 0) && m_count.compare_exchange_strong(oldCount, oldCount - 1, std::memory_order_acquire, std::memory_order_relaxed))
|
||||
return true;
|
||||
std::atomic_signal_fence(std::memory_order_acquire); // Prevent the compiler from collapsing the loop.
|
||||
}
|
||||
oldCount = m_count.fetch_sub(1, std::memory_order_acquire);
|
||||
if (oldCount > 0)
|
||||
return true;
|
||||
if (timeout_usecs < 0)
|
||||
{
|
||||
if (m_sema.wait())
|
||||
return true;
|
||||
}
|
||||
if (timeout_usecs > 0 && m_sema.timed_wait((std::uint64_t)timeout_usecs))
|
||||
return true;
|
||||
// At this point, we've timed out waiting for the semaphore, but the
|
||||
// count is still decremented indicating we may still be waiting on
|
||||
// it. So we have to re-adjust the count, but only if the semaphore
|
||||
// wasn't signaled enough times for us too since then. If it was, we
|
||||
// need to release the semaphore too.
|
||||
while (true)
|
||||
{
|
||||
oldCount = m_count.load(std::memory_order_acquire);
|
||||
if (oldCount >= 0 && m_sema.try_wait())
|
||||
return true;
|
||||
if (oldCount < 0 && m_count.compare_exchange_strong(oldCount, oldCount + 1, std::memory_order_relaxed, std::memory_order_relaxed))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
ssize_t waitManyWithPartialSpinning(ssize_t max, std::int64_t timeout_usecs = -1)
|
||||
{
|
||||
assert(max > 0);
|
||||
ssize_t oldCount;
|
||||
int spin = m_maxSpins;
|
||||
while (--spin >= 0)
|
||||
{
|
||||
oldCount = m_count.load(std::memory_order_relaxed);
|
||||
if (oldCount > 0)
|
||||
{
|
||||
ssize_t newCount = oldCount > max ? oldCount - max : 0;
|
||||
if (m_count.compare_exchange_strong(oldCount, newCount, std::memory_order_acquire, std::memory_order_relaxed))
|
||||
return oldCount - newCount;
|
||||
}
|
||||
std::atomic_signal_fence(std::memory_order_acquire);
|
||||
}
|
||||
oldCount = m_count.fetch_sub(1, std::memory_order_acquire);
|
||||
if (oldCount <= 0)
|
||||
{
|
||||
if ((timeout_usecs == 0) || (timeout_usecs < 0 && !m_sema.wait()) || (timeout_usecs > 0 && !m_sema.timed_wait((std::uint64_t)timeout_usecs)))
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
oldCount = m_count.load(std::memory_order_acquire);
|
||||
if (oldCount >= 0 && m_sema.try_wait())
|
||||
break;
|
||||
if (oldCount < 0 && m_count.compare_exchange_strong(oldCount, oldCount + 1, std::memory_order_relaxed, std::memory_order_relaxed))
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (max > 1)
|
||||
return 1 + tryWaitMany(max - 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
public:
|
||||
LightweightSemaphore(ssize_t initialCount = 0, int maxSpins = 10000) : m_count(initialCount), m_maxSpins(maxSpins)
|
||||
{
|
||||
assert(initialCount >= 0);
|
||||
assert(maxSpins >= 0);
|
||||
}
|
||||
|
||||
bool tryWait()
|
||||
{
|
||||
ssize_t oldCount = m_count.load(std::memory_order_relaxed);
|
||||
while (oldCount > 0)
|
||||
{
|
||||
if (m_count.compare_exchange_weak(oldCount, oldCount - 1, std::memory_order_acquire, std::memory_order_relaxed))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool wait()
|
||||
{
|
||||
return tryWait() || waitWithPartialSpinning();
|
||||
}
|
||||
|
||||
bool wait(std::int64_t timeout_usecs)
|
||||
{
|
||||
return tryWait() || waitWithPartialSpinning(timeout_usecs);
|
||||
}
|
||||
|
||||
// Acquires between 0 and (greedily) max, inclusive
|
||||
ssize_t tryWaitMany(ssize_t max)
|
||||
{
|
||||
assert(max >= 0);
|
||||
ssize_t oldCount = m_count.load(std::memory_order_relaxed);
|
||||
while (oldCount > 0)
|
||||
{
|
||||
ssize_t newCount = oldCount > max ? oldCount - max : 0;
|
||||
if (m_count.compare_exchange_weak(oldCount, newCount, std::memory_order_acquire, std::memory_order_relaxed))
|
||||
return oldCount - newCount;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Acquires at least one, and (greedily) at most max
|
||||
ssize_t waitMany(ssize_t max, std::int64_t timeout_usecs)
|
||||
{
|
||||
assert(max >= 0);
|
||||
ssize_t result = tryWaitMany(max);
|
||||
if (result == 0 && max > 0)
|
||||
result = waitManyWithPartialSpinning(max, timeout_usecs);
|
||||
return result;
|
||||
}
|
||||
|
||||
ssize_t waitMany(ssize_t max)
|
||||
{
|
||||
ssize_t result = waitMany(max, -1);
|
||||
assert(result > 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
void signal(ssize_t count = 1)
|
||||
{
|
||||
assert(count >= 0);
|
||||
ssize_t oldCount = m_count.fetch_add(count, std::memory_order_release);
|
||||
ssize_t toRelease = -oldCount < count ? -oldCount : count;
|
||||
if (toRelease > 0)
|
||||
{
|
||||
m_sema.signal((int)toRelease);
|
||||
}
|
||||
}
|
||||
|
||||
std::size_t availableApprox() const
|
||||
{
|
||||
ssize_t count = m_count.load(std::memory_order_relaxed);
|
||||
return count > 0 ? static_cast<std::size_t>(count) : 0;
|
||||
}
|
||||
};
|
||||
|
||||
} // end namespace moodycamel
|
||||
|
|
@ -134,6 +134,13 @@ LLCoros::LLCoros():
|
|||
|
||||
LLCoros::~LLCoros()
|
||||
{
|
||||
}
|
||||
|
||||
void LLCoros::cleanupSingleton()
|
||||
{
|
||||
// Some of the coroutines (like voice) will depend onto
|
||||
// origin singletons, so clean coros before deleting those
|
||||
|
||||
printActiveCoroutines("at entry to ~LLCoros()");
|
||||
// Other LLApp status-change listeners do things like close
|
||||
// work queues and inject the Stop exception into pending
|
||||
|
|
@ -149,6 +156,8 @@ LLCoros::~LLCoros()
|
|||
{
|
||||
// don't use llcoro::suspend() because that module depends
|
||||
// on this one
|
||||
// This will yield current(main) thread and will let active
|
||||
// corutines run once
|
||||
boost::this_fiber::yield();
|
||||
}
|
||||
printActiveCoroutines("after pumping");
|
||||
|
|
|
|||
|
|
@ -89,6 +89,8 @@ class LL_COMMON_API LLCoros: public LLSingleton<LLCoros>
|
|||
{
|
||||
LLSINGLETON(LLCoros);
|
||||
~LLCoros();
|
||||
|
||||
void cleanupSingleton();
|
||||
public:
|
||||
/// The viewer's use of the term "coroutine" became deeply embedded before
|
||||
/// the industry term "fiber" emerged to distinguish userland threads from
|
||||
|
|
|
|||
|
|
@ -481,6 +481,62 @@ namespace
|
|||
typedef std::vector<LLError::RecorderPtr> Recorders;
|
||||
typedef std::vector<LLError::CallSite*> CallSiteVector;
|
||||
|
||||
class SettingsConfig : public LLRefCount
|
||||
{
|
||||
friend class Globals;
|
||||
|
||||
public:
|
||||
virtual ~SettingsConfig();
|
||||
|
||||
LLError::ELevel mDefaultLevel;
|
||||
|
||||
bool mLogAlwaysFlush;
|
||||
|
||||
U32 mEnabledLogTypesMask;
|
||||
|
||||
LevelMap mFunctionLevelMap;
|
||||
LevelMap mClassLevelMap;
|
||||
LevelMap mFileLevelMap;
|
||||
LevelMap mTagLevelMap;
|
||||
std::map<std::string, unsigned int> mUniqueLogMessages;
|
||||
|
||||
LLError::FatalFunction mCrashFunction;
|
||||
LLError::TimeFunction mTimeFunction;
|
||||
|
||||
Recorders mRecorders;
|
||||
LLMutex mRecorderMutex;
|
||||
|
||||
int mShouldLogCallCounter;
|
||||
|
||||
private:
|
||||
SettingsConfig();
|
||||
};
|
||||
|
||||
typedef LLPointer<SettingsConfig> SettingsConfigPtr;
|
||||
|
||||
SettingsConfig::SettingsConfig()
|
||||
: LLRefCount(),
|
||||
mDefaultLevel(LLError::LEVEL_DEBUG),
|
||||
mLogAlwaysFlush(true),
|
||||
mEnabledLogTypesMask(255),
|
||||
mFunctionLevelMap(),
|
||||
mClassLevelMap(),
|
||||
mFileLevelMap(),
|
||||
mTagLevelMap(),
|
||||
mUniqueLogMessages(),
|
||||
mCrashFunction(NULL),
|
||||
mTimeFunction(NULL),
|
||||
mRecorders(),
|
||||
mRecorderMutex(),
|
||||
mShouldLogCallCounter(0)
|
||||
{
|
||||
}
|
||||
|
||||
SettingsConfig::~SettingsConfig()
|
||||
{
|
||||
mRecorders.clear();
|
||||
}
|
||||
|
||||
class Globals
|
||||
{
|
||||
public:
|
||||
|
|
@ -488,16 +544,28 @@ namespace
|
|||
protected:
|
||||
Globals();
|
||||
public:
|
||||
std::ostringstream messageStream;
|
||||
bool messageStreamInUse;
|
||||
std::string mFatalMessage;
|
||||
|
||||
void addCallSite(LLError::CallSite&);
|
||||
void invalidateCallSites();
|
||||
|
||||
SettingsConfigPtr getSettingsConfig();
|
||||
|
||||
void resetSettingsConfig();
|
||||
LLError::SettingsStoragePtr saveAndResetSettingsConfig();
|
||||
void restore(LLError::SettingsStoragePtr pSettingsStorage);
|
||||
private:
|
||||
CallSiteVector callSites;
|
||||
SettingsConfigPtr mSettingsConfig;
|
||||
};
|
||||
|
||||
Globals::Globals() {}
|
||||
Globals::Globals()
|
||||
: mSettingsConfig(new SettingsConfig())
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Globals* Globals::getInstance()
|
||||
{
|
||||
|
|
@ -525,120 +593,31 @@ namespace
|
|||
|
||||
callSites.clear();
|
||||
}
|
||||
}
|
||||
|
||||
namespace LLError
|
||||
{
|
||||
class SettingsConfig : public LLRefCount
|
||||
{
|
||||
friend class Settings;
|
||||
|
||||
public:
|
||||
virtual ~SettingsConfig();
|
||||
|
||||
LLError::ELevel mDefaultLevel;
|
||||
|
||||
bool mLogAlwaysFlush;
|
||||
|
||||
U32 mEnabledLogTypesMask;
|
||||
|
||||
LevelMap mFunctionLevelMap;
|
||||
LevelMap mClassLevelMap;
|
||||
LevelMap mFileLevelMap;
|
||||
LevelMap mTagLevelMap;
|
||||
std::map<std::string, unsigned int> mUniqueLogMessages;
|
||||
|
||||
LLError::FatalFunction mCrashFunction;
|
||||
LLError::TimeFunction mTimeFunction;
|
||||
|
||||
Recorders mRecorders;
|
||||
|
||||
int mShouldLogCallCounter;
|
||||
|
||||
private:
|
||||
SettingsConfig();
|
||||
};
|
||||
|
||||
typedef LLPointer<SettingsConfig> SettingsConfigPtr;
|
||||
|
||||
class Settings
|
||||
{
|
||||
public:
|
||||
static Settings* getInstance();
|
||||
protected:
|
||||
Settings();
|
||||
public:
|
||||
SettingsConfigPtr getSettingsConfig();
|
||||
|
||||
void reset();
|
||||
SettingsStoragePtr saveAndReset();
|
||||
void restore(SettingsStoragePtr pSettingsStorage);
|
||||
|
||||
private:
|
||||
SettingsConfigPtr mSettingsConfig;
|
||||
};
|
||||
|
||||
SettingsConfig::SettingsConfig()
|
||||
: LLRefCount(),
|
||||
mDefaultLevel(LLError::LEVEL_DEBUG),
|
||||
mLogAlwaysFlush(true),
|
||||
mEnabledLogTypesMask(255),
|
||||
mFunctionLevelMap(),
|
||||
mClassLevelMap(),
|
||||
mFileLevelMap(),
|
||||
mTagLevelMap(),
|
||||
mUniqueLogMessages(),
|
||||
mCrashFunction([](const std::string&){}),
|
||||
mTimeFunction(NULL),
|
||||
mRecorders(),
|
||||
mShouldLogCallCounter(0)
|
||||
{
|
||||
}
|
||||
|
||||
SettingsConfig::~SettingsConfig()
|
||||
{
|
||||
mRecorders.clear();
|
||||
}
|
||||
|
||||
Settings::Settings():
|
||||
mSettingsConfig(new SettingsConfig())
|
||||
{
|
||||
}
|
||||
|
||||
Settings* Settings::getInstance()
|
||||
SettingsConfigPtr Globals::getSettingsConfig()
|
||||
{
|
||||
// According to C++11 Function-Local Initialization
|
||||
// of static variables is supposed to be thread safe
|
||||
// without risk of deadlocks.
|
||||
static Settings inst;
|
||||
|
||||
return &inst;
|
||||
return mSettingsConfig;
|
||||
}
|
||||
|
||||
SettingsConfigPtr Settings::getSettingsConfig()
|
||||
{
|
||||
return mSettingsConfig;
|
||||
}
|
||||
void Globals::resetSettingsConfig()
|
||||
{
|
||||
invalidateCallSites();
|
||||
mSettingsConfig = new SettingsConfig();
|
||||
}
|
||||
|
||||
void Settings::reset()
|
||||
{
|
||||
Globals::getInstance()->invalidateCallSites();
|
||||
mSettingsConfig = new SettingsConfig();
|
||||
}
|
||||
LLError::SettingsStoragePtr Globals::saveAndResetSettingsConfig()
|
||||
{
|
||||
LLError::SettingsStoragePtr oldSettingsConfig(mSettingsConfig.get());
|
||||
resetSettingsConfig();
|
||||
return oldSettingsConfig;
|
||||
}
|
||||
|
||||
SettingsStoragePtr Settings::saveAndReset()
|
||||
{
|
||||
SettingsStoragePtr oldSettingsConfig(mSettingsConfig.get());
|
||||
reset();
|
||||
return oldSettingsConfig;
|
||||
}
|
||||
|
||||
void Settings::restore(SettingsStoragePtr pSettingsStorage)
|
||||
{
|
||||
Globals::getInstance()->invalidateCallSites();
|
||||
SettingsConfigPtr newSettingsConfig(dynamic_cast<SettingsConfig *>(pSettingsStorage.get()));
|
||||
mSettingsConfig = newSettingsConfig;
|
||||
}
|
||||
void Globals::restore(LLError::SettingsStoragePtr pSettingsStorage)
|
||||
{
|
||||
invalidateCallSites();
|
||||
SettingsConfigPtr newSettingsConfig(dynamic_cast<SettingsConfig *>(pSettingsStorage.get()));
|
||||
mSettingsConfig = newSettingsConfig;
|
||||
}
|
||||
}
|
||||
|
||||
namespace LLError
|
||||
|
|
@ -768,7 +747,7 @@ namespace
|
|||
|
||||
void commonInit(const std::string& user_dir, const std::string& app_dir, bool log_to_stderr = true)
|
||||
{
|
||||
LLError::Settings::getInstance()->reset();
|
||||
Globals::getInstance()->resetSettingsConfig();
|
||||
|
||||
LLError::setDefaultLevel(LLError::LEVEL_INFO);
|
||||
LLError::setAlwaysFlush(true);
|
||||
|
|
@ -809,13 +788,13 @@ namespace LLError
|
|||
|
||||
void setFatalFunction(const FatalFunction& f)
|
||||
{
|
||||
SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
|
||||
SettingsConfigPtr s = Globals::getInstance()->getSettingsConfig();
|
||||
s->mCrashFunction = f;
|
||||
}
|
||||
|
||||
FatalFunction getFatalFunction()
|
||||
{
|
||||
SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
|
||||
SettingsConfigPtr s = Globals::getInstance()->getSettingsConfig();
|
||||
return s->mCrashFunction;
|
||||
}
|
||||
|
||||
|
|
@ -826,72 +805,77 @@ namespace LLError
|
|||
|
||||
void setTimeFunction(TimeFunction f)
|
||||
{
|
||||
SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
|
||||
SettingsConfigPtr s = Globals::getInstance()->getSettingsConfig();
|
||||
s->mTimeFunction = f;
|
||||
}
|
||||
|
||||
void setDefaultLevel(ELevel level)
|
||||
{
|
||||
Globals::getInstance()->invalidateCallSites();
|
||||
SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
|
||||
Globals *g = Globals::getInstance();
|
||||
g->invalidateCallSites();
|
||||
SettingsConfigPtr s = g->getSettingsConfig();
|
||||
s->mDefaultLevel = level;
|
||||
}
|
||||
|
||||
ELevel getDefaultLevel()
|
||||
{
|
||||
SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
|
||||
SettingsConfigPtr s = Globals::getInstance()->getSettingsConfig();
|
||||
return s->mDefaultLevel;
|
||||
}
|
||||
|
||||
void setAlwaysFlush(bool flush)
|
||||
{
|
||||
SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
|
||||
SettingsConfigPtr s = Globals::getInstance()->getSettingsConfig();
|
||||
s->mLogAlwaysFlush = flush;
|
||||
}
|
||||
|
||||
bool getAlwaysFlush()
|
||||
{
|
||||
SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
|
||||
SettingsConfigPtr s = Globals::getInstance()->getSettingsConfig();
|
||||
return s->mLogAlwaysFlush;
|
||||
}
|
||||
|
||||
void setEnabledLogTypesMask(U32 mask)
|
||||
{
|
||||
SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
|
||||
SettingsConfigPtr s = Globals::getInstance()->getSettingsConfig();
|
||||
s->mEnabledLogTypesMask = mask;
|
||||
}
|
||||
|
||||
U32 getEnabledLogTypesMask()
|
||||
{
|
||||
SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
|
||||
SettingsConfigPtr s = Globals::getInstance()->getSettingsConfig();
|
||||
return s->mEnabledLogTypesMask;
|
||||
}
|
||||
|
||||
void setFunctionLevel(const std::string& function_name, ELevel level)
|
||||
{
|
||||
Globals::getInstance()->invalidateCallSites();
|
||||
SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
|
||||
Globals *g = Globals::getInstance();
|
||||
g->invalidateCallSites();
|
||||
SettingsConfigPtr s = g->getSettingsConfig();
|
||||
s->mFunctionLevelMap[function_name] = level;
|
||||
}
|
||||
|
||||
void setClassLevel(const std::string& class_name, ELevel level)
|
||||
{
|
||||
Globals::getInstance()->invalidateCallSites();
|
||||
SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
|
||||
Globals *g = Globals::getInstance();
|
||||
g->invalidateCallSites();
|
||||
SettingsConfigPtr s = g->getSettingsConfig();
|
||||
s->mClassLevelMap[class_name] = level;
|
||||
}
|
||||
|
||||
void setFileLevel(const std::string& file_name, ELevel level)
|
||||
{
|
||||
Globals::getInstance()->invalidateCallSites();
|
||||
SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
|
||||
Globals *g = Globals::getInstance();
|
||||
g->invalidateCallSites();
|
||||
SettingsConfigPtr s = g->getSettingsConfig();
|
||||
s->mFileLevelMap[file_name] = level;
|
||||
}
|
||||
|
||||
void setTagLevel(const std::string& tag_name, ELevel level)
|
||||
{
|
||||
Globals::getInstance()->invalidateCallSites();
|
||||
SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
|
||||
Globals *g = Globals::getInstance();
|
||||
g->invalidateCallSites();
|
||||
SettingsConfigPtr s = g->getSettingsConfig();
|
||||
s->mTagLevelMap[tag_name] = level;
|
||||
}
|
||||
|
||||
|
|
@ -936,8 +920,9 @@ namespace LLError
|
|||
{
|
||||
void configure(const LLSD& config)
|
||||
{
|
||||
Globals::getInstance()->invalidateCallSites();
|
||||
SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
|
||||
Globals *g = Globals::getInstance();
|
||||
g->invalidateCallSites();
|
||||
SettingsConfigPtr s = g->getSettingsConfig();
|
||||
|
||||
s->mFunctionLevelMap.clear();
|
||||
s->mClassLevelMap.clear();
|
||||
|
|
@ -1064,7 +1049,8 @@ namespace LLError
|
|||
{
|
||||
return;
|
||||
}
|
||||
SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
|
||||
SettingsConfigPtr s = Globals::getInstance()->getSettingsConfig();
|
||||
LLMutexLock lock(&s->mRecorderMutex);
|
||||
s->mRecorders.push_back(recorder);
|
||||
}
|
||||
|
||||
|
|
@ -1074,7 +1060,8 @@ namespace LLError
|
|||
{
|
||||
return;
|
||||
}
|
||||
SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
|
||||
SettingsConfigPtr s = Globals::getInstance()->getSettingsConfig();
|
||||
LLMutexLock lock(&s->mRecorderMutex);
|
||||
s->mRecorders.erase(std::remove(s->mRecorders.begin(), s->mRecorders.end(), recorder),
|
||||
s->mRecorders.end());
|
||||
}
|
||||
|
|
@ -1086,11 +1073,12 @@ namespace LLError
|
|||
// with a Recorders::iterator indicating the position of that entry in
|
||||
// mRecorders. The shared_ptr might be empty (operator!() returns true) if
|
||||
// there was no such RECORDER subclass instance in mRecorders.
|
||||
//
|
||||
// NOTE!!! Requires external mutex lock!!!
|
||||
template <typename RECORDER>
|
||||
std::pair<boost::shared_ptr<RECORDER>, Recorders::iterator>
|
||||
findRecorderPos()
|
||||
findRecorderPos(SettingsConfigPtr &s)
|
||||
{
|
||||
SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
|
||||
// Since we promise to return an iterator, use a classic iterator
|
||||
// loop.
|
||||
auto end{s->mRecorders.end()};
|
||||
|
|
@ -1121,7 +1109,9 @@ namespace LLError
|
|||
template <typename RECORDER>
|
||||
boost::shared_ptr<RECORDER> findRecorder()
|
||||
{
|
||||
return findRecorderPos<RECORDER>().first;
|
||||
SettingsConfigPtr s = Globals::getInstance()->getSettingsConfig();
|
||||
LLMutexLock lock(&s->mRecorderMutex);
|
||||
return findRecorderPos<RECORDER>(s).first;
|
||||
}
|
||||
|
||||
// Remove an entry from SettingsConfig::mRecorders whose RecorderPtr
|
||||
|
|
@ -1130,10 +1120,11 @@ namespace LLError
|
|||
template <typename RECORDER>
|
||||
bool removeRecorder()
|
||||
{
|
||||
auto found = findRecorderPos<RECORDER>();
|
||||
SettingsConfigPtr s = Globals::getInstance()->getSettingsConfig();
|
||||
LLMutexLock lock(&s->mRecorderMutex);
|
||||
auto found = findRecorderPos<RECORDER>(s);
|
||||
if (found.first)
|
||||
{
|
||||
SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
|
||||
s->mRecorders.erase(found.second);
|
||||
}
|
||||
return bool(found.first);
|
||||
|
|
@ -1231,10 +1222,11 @@ namespace
|
|||
void writeToRecorders(const LLError::CallSite& site, const std::string& message)
|
||||
{
|
||||
LLError::ELevel level = site.mLevel;
|
||||
LLError::SettingsConfigPtr s = LLError::Settings::getInstance()->getSettingsConfig();
|
||||
SettingsConfigPtr s = Globals::getInstance()->getSettingsConfig();
|
||||
|
||||
std::string escaped_message;
|
||||
|
||||
|
||||
LLMutexLock lock(&s->mRecorderMutex);
|
||||
for (Recorders::const_iterator i = s->mRecorders.begin();
|
||||
i != s->mRecorders.end();
|
||||
++i)
|
||||
|
|
@ -1376,7 +1368,8 @@ namespace LLError
|
|||
return false;
|
||||
}
|
||||
|
||||
SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
|
||||
Globals *g = Globals::getInstance();
|
||||
SettingsConfigPtr s = g->getSettingsConfig();
|
||||
|
||||
s->mShouldLogCallCounter++;
|
||||
|
||||
|
|
@ -1406,7 +1399,7 @@ namespace LLError
|
|||
: false);
|
||||
|
||||
site.mCached = true;
|
||||
Globals::getInstance()->addCallSite(site);
|
||||
g->addCallSite(site);
|
||||
return site.mShouldLog = site.mLevel >= compareLevel;
|
||||
}
|
||||
|
||||
|
|
@ -1420,7 +1413,7 @@ namespace LLError
|
|||
}
|
||||
|
||||
Globals* g = Globals::getInstance();
|
||||
SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
|
||||
SettingsConfigPtr s = g->getSettingsConfig();
|
||||
|
||||
std::string message = out.str();
|
||||
|
||||
|
|
@ -1465,12 +1458,12 @@ namespace LLError
|
|||
{
|
||||
SettingsStoragePtr saveAndResetSettings()
|
||||
{
|
||||
return Settings::getInstance()->saveAndReset();
|
||||
return Globals::getInstance()->saveAndResetSettingsConfig();
|
||||
}
|
||||
|
||||
void restoreSettings(SettingsStoragePtr pSettingsStorage)
|
||||
{
|
||||
return Settings::getInstance()->restore(pSettingsStorage);
|
||||
return Globals::getInstance()->restore(pSettingsStorage);
|
||||
}
|
||||
|
||||
std::string removePrefix(std::string& s, const std::string& p)
|
||||
|
|
@ -1516,7 +1509,7 @@ namespace LLError
|
|||
|
||||
int shouldLogCallCount()
|
||||
{
|
||||
SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
|
||||
SettingsConfigPtr s = Globals::getInstance()->getSettingsConfig();
|
||||
return s->mShouldLogCallCounter;
|
||||
}
|
||||
|
||||
|
|
@ -1628,8 +1621,8 @@ bool debugLoggingEnabled(const std::string& tag)
|
|||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
LLError::SettingsConfigPtr s = LLError::Settings::getInstance()->getSettingsConfig();
|
||||
|
||||
SettingsConfigPtr s = Globals::getInstance()->getSettingsConfig();
|
||||
LLError::ELevel level = LLError::LEVEL_DEBUG;
|
||||
bool res = checkLevelMap(s->mTagLevelMap, tag, level);
|
||||
return res;
|
||||
|
|
|
|||
|
|
@ -45,7 +45,6 @@
|
|||
#include <cctype>
|
||||
// external library headers
|
||||
#include <boost/range/iterator_range.hpp>
|
||||
#include <boost/make_shared.hpp>
|
||||
#if LL_WINDOWS
|
||||
#pragma warning (push)
|
||||
#pragma warning (disable : 4701) // compiler thinks might use uninitialized var, but no
|
||||
|
|
@ -285,7 +284,7 @@ LLEventPump::LLEventPump(const std::string& name, bool tweak):
|
|||
// Register every new instance with LLEventPumps
|
||||
mRegistry(LLEventPumps::instance().getHandle()),
|
||||
mName(mRegistry.get()->registerNew(*this, name, tweak)),
|
||||
mSignal(boost::make_shared<LLStandardSignal>()),
|
||||
mSignal(std::make_shared<LLStandardSignal>()),
|
||||
mEnabled(true)
|
||||
{}
|
||||
|
||||
|
|
@ -317,14 +316,24 @@ void LLEventPump::clear()
|
|||
{
|
||||
// Destroy the original LLStandardSignal instance, replacing it with a
|
||||
// whole new one.
|
||||
mSignal = boost::make_shared<LLStandardSignal>();
|
||||
mSignal = std::make_shared<LLStandardSignal>();
|
||||
mConnections.clear();
|
||||
}
|
||||
|
||||
void LLEventPump::reset()
|
||||
{
|
||||
mSignal.reset();
|
||||
// Resetting mSignal is supposed to disconnect everything on its own
|
||||
// But due to crash on 'reset' added explicit cleanup to get more data
|
||||
ConnectionMap::const_iterator iter = mConnections.begin();
|
||||
ConnectionMap::const_iterator end = mConnections.end();
|
||||
while (iter!=end)
|
||||
{
|
||||
iter->second.disconnect();
|
||||
iter++;
|
||||
}
|
||||
mConnections.clear();
|
||||
|
||||
mSignal.reset();
|
||||
//mDeps.clear();
|
||||
}
|
||||
|
||||
|
|
@ -543,7 +552,7 @@ bool LLEventStream::post(const LLSD& event)
|
|||
// *stack* instance of the shared_ptr, ensuring that our heap
|
||||
// LLStandardSignal object will live at least until post() returns, even
|
||||
// if 'this' gets destroyed during the call.
|
||||
boost::shared_ptr<LLStandardSignal> signal(mSignal);
|
||||
std::shared_ptr<LLStandardSignal> signal(mSignal);
|
||||
// Let caller know if any one listener handled the event. This is mostly
|
||||
// useful when using LLEventStream as a listener for an upstream
|
||||
// LLEventPump.
|
||||
|
|
|
|||
|
|
@ -49,8 +49,6 @@
|
|||
#endif
|
||||
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/enable_shared_from_this.hpp>
|
||||
#include <boost/utility.hpp> // noncopyable
|
||||
#include <boost/optional/optional.hpp>
|
||||
#include <boost/visit_each.hpp>
|
||||
|
|
@ -571,7 +569,7 @@ protected:
|
|||
const NameList& before);
|
||||
|
||||
/// implement the dispatching
|
||||
boost::shared_ptr<LLStandardSignal> mSignal;
|
||||
std::shared_ptr<LLStandardSignal> mSignal;
|
||||
|
||||
/// valve open?
|
||||
bool mEnabled;
|
||||
|
|
@ -745,14 +743,4 @@ private:
|
|||
LL_COMMON_API bool sendReply(const LLSD& reply, const LLSD& request,
|
||||
const std::string& replyKey="reply");
|
||||
|
||||
// Somewhat to my surprise, passing boost::bind(...boost::weak_ptr<T>...) to
|
||||
// listen() fails in Boost code trying to instantiate LLEventListener (i.e.
|
||||
// LLStandardSignal::slot_type) because the boost::get_pointer() utility function isn't
|
||||
// specialized for boost::weak_ptr. This remedies that omission.
|
||||
namespace boost
|
||||
{
|
||||
template <typename T>
|
||||
T* get_pointer(const weak_ptr<T>& ptr) { return shared_ptr<T>(ptr).get(); }
|
||||
}
|
||||
|
||||
#endif /* ! defined(LL_LLEVENTS_H) */
|
||||
|
|
|
|||
|
|
@ -40,6 +40,12 @@
|
|||
#define LL_BIG_ENDIAN 1
|
||||
#endif
|
||||
|
||||
//<FS:ND> FIRE-31221 workaround for newer glibc versions, patch from Lance Corrimal
|
||||
// Figure out GLIBC version - 2.34 needs an additional include as a build fix
|
||||
#if (__GLIBC__*1000 + __GLIBC_MINOR__) >= 2034
|
||||
#include <bits/pthread_stack_min.h>
|
||||
#endif
|
||||
// </FS:Nd>
|
||||
|
||||
// Per-compiler switches
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,89 @@
|
|||
/**
|
||||
* @file llregex.h
|
||||
*
|
||||
* $LicenseInfo:firstyear=2021&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2021, 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$
|
||||
*/
|
||||
|
||||
#ifndef LLREGEX_H
|
||||
#define LLREGEX_H
|
||||
#include <boost/regex.hpp>
|
||||
|
||||
template <typename S, typename M, typename R>
|
||||
LL_COMMON_API bool ll_regex_match(const S& string, M& match, const R& regex)
|
||||
{
|
||||
try
|
||||
{
|
||||
return boost::regex_match(string, match, regex);
|
||||
}
|
||||
catch (const std::runtime_error& e)
|
||||
{
|
||||
LL_WARNS() << "error matching with '" << regex.str() << "': "
|
||||
<< e.what() << ":\n'" << string << "'" << LL_ENDL;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename S, typename R>
|
||||
LL_COMMON_API bool ll_regex_match(const S& string, const R& regex)
|
||||
{
|
||||
try
|
||||
{
|
||||
return boost::regex_match(string, regex);
|
||||
}
|
||||
catch (const std::runtime_error& e)
|
||||
{
|
||||
LL_WARNS() << "error matching with '" << regex.str() << "': "
|
||||
<< e.what() << ":\n'" << string << "'" << LL_ENDL;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename S, typename M, typename R>
|
||||
bool ll_regex_search(const S& string, M& match, const R& regex)
|
||||
{
|
||||
try
|
||||
{
|
||||
return boost::regex_search(string, match, regex);
|
||||
}
|
||||
catch (const std::runtime_error& e)
|
||||
{
|
||||
LL_WARNS() << "error searching with '" << regex.str() << "': "
|
||||
<< e.what() << ":\n'" << string << "'" << LL_ENDL;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename S, typename R>
|
||||
bool ll_regex_search(const S& string, const R& regex)
|
||||
{
|
||||
try
|
||||
{
|
||||
return boost::regex_search(string, regex);
|
||||
}
|
||||
catch (const std::runtime_error& e)
|
||||
{
|
||||
LL_WARNS() << "error searching with '" << regex.str() << "': "
|
||||
<< e.what() << ":\n'" << string << "'" << LL_ENDL;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif // LLREGEX_H
|
||||
|
|
@ -43,12 +43,12 @@
|
|||
#include "llerrorcontrol.h"
|
||||
#include "llevents.h"
|
||||
#include "llformat.h"
|
||||
#include "llregex.h"
|
||||
#include "lltimer.h"
|
||||
#include "llsdserialize.h"
|
||||
#include "llsdutil.h"
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/circular_buffer.hpp>
|
||||
#include <boost/regex.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/range.hpp>
|
||||
|
|
@ -101,39 +101,6 @@ static const F32 MEM_INFO_THROTTLE = 20;
|
|||
// dropped below the login framerate, we'd have very little additional data.
|
||||
static const F32 MEM_INFO_WINDOW = 10*60;
|
||||
|
||||
// Wrap boost::regex_match() with a function that doesn't throw.
|
||||
template <typename S, typename M, typename R>
|
||||
static bool regex_match_no_exc(const S& string, M& match, const R& regex)
|
||||
{
|
||||
try
|
||||
{
|
||||
return boost::regex_match(string, match, regex);
|
||||
}
|
||||
catch (const std::runtime_error& e)
|
||||
{
|
||||
LL_WARNS("LLMemoryInfo") << "error matching with '" << regex.str() << "': "
|
||||
<< e.what() << ":\n'" << string << "'" << LL_ENDL;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Wrap boost::regex_search() with a function that doesn't throw.
|
||||
template <typename S, typename M, typename R>
|
||||
static bool regex_search_no_exc(const S& string, M& match, const R& regex)
|
||||
{
|
||||
try
|
||||
{
|
||||
return boost::regex_search(string, match, regex);
|
||||
}
|
||||
catch (const std::runtime_error& e)
|
||||
{
|
||||
LL_WARNS("LLMemoryInfo") << "error searching with '" << regex.str() << "': "
|
||||
<< e.what() << ":\n'" << string << "'" << LL_ENDL;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
LLOSInfo::LLOSInfo() :
|
||||
mMajorVer(0), mMinorVer(0), mBuild(0), mOSVersionString("")
|
||||
{
|
||||
|
|
@ -384,7 +351,7 @@ LLOSInfo::LLOSInfo() :
|
|||
boost::smatch matched;
|
||||
|
||||
std::string glibc_version(gnu_get_libc_version());
|
||||
if ( regex_match_no_exc(glibc_version, matched, os_version_parse) )
|
||||
if ( ll_regex_match(glibc_version, matched, os_version_parse) )
|
||||
{
|
||||
LL_INFOS("AppInit") << "Using glibc version '" << glibc_version << "' as OS version" << LL_ENDL;
|
||||
|
||||
|
|
@ -1061,7 +1028,7 @@ LLSD LLMemoryInfo::loadStatsMap()
|
|||
while (std::getline(meminfo, line))
|
||||
{
|
||||
LL_DEBUGS("LLMemoryInfo") << line << LL_ENDL;
|
||||
if (regex_match_no_exc(line, matched, stat_rx))
|
||||
if (ll_regex_match(line, matched, stat_rx))
|
||||
{
|
||||
// e.g. "MemTotal: 4108424 kB"
|
||||
LLSD::String key(matched[1].first, matched[1].second);
|
||||
|
|
|
|||
|
|
@ -580,6 +580,31 @@ namespace LLTrace
|
|||
return typename RelatedTypes<T>::fractional_t(getPeriodMeanPerSec(static_cast<const StatType<CountAccumulator>&>(stat), num_periods));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMedianPerSec(const StatType<T>& stat, S32 num_periods = S32_MAX)
|
||||
{
|
||||
num_periods = llmin(num_periods, getNumRecordedPeriods());
|
||||
|
||||
std::vector <typename RelatedTypes<typename T::value_t>::fractional_t> buf;
|
||||
for (S32 i = 1; i <= num_periods; i++)
|
||||
{
|
||||
Recording& recording = getPrevRecording(i);
|
||||
if (recording.getDuration() > (F32Seconds)0.f)
|
||||
{
|
||||
buf.push_back(recording.getPerSec(stat));
|
||||
}
|
||||
}
|
||||
std::sort(buf.begin(), buf.end());
|
||||
|
||||
return typename RelatedTypes<T>::fractional_t((buf.size() % 2 == 0) ? (buf[buf.size() / 2 - 1] + buf[buf.size() / 2]) / 2 : buf[buf.size() / 2]);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
typename RelatedTypes<T>::fractional_t getPeriodMedianPerSec(const CountStatHandle<T>& stat, S32 num_periods = S32_MAX)
|
||||
{
|
||||
return typename RelatedTypes<T>::fractional_t(getPeriodMedianPerSec(static_cast<const StatType<CountAccumulator>&>(stat), num_periods));
|
||||
}
|
||||
|
||||
//
|
||||
// PERIODIC STANDARD DEVIATION
|
||||
//
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@
|
|||
#include "lltimer.h"
|
||||
#include "llthread.h"
|
||||
#include "llmutex.h"
|
||||
|
||||
#include "fstelemetry.h"
|
||||
const LLUUID LLUUID::null;
|
||||
const LLTransactionID LLTransactionID::tnull;
|
||||
|
||||
|
|
@ -156,6 +156,7 @@ U32 janky_fast_random_seeded_bytes(U32 seed, U32 val)
|
|||
// Common to all UUID implementations
|
||||
void LLUUID::toString(std::string& out) const
|
||||
{
|
||||
FSZone;
|
||||
out = llformat(
|
||||
"%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
|
||||
(U8)(mData[0]),
|
||||
|
|
@ -218,6 +219,7 @@ BOOL LLUUID::set(const char* in_string, BOOL emit)
|
|||
|
||||
BOOL LLUUID::set(const std::string& in_string, BOOL emit)
|
||||
{
|
||||
FSZone;
|
||||
BOOL broken_format = FALSE;
|
||||
|
||||
// empty strings should make NULL uuid
|
||||
|
|
@ -1028,6 +1030,7 @@ LLUUID::LLUUID()
|
|||
// Copy constructor
|
||||
LLUUID::LLUUID(const LLUUID& rhs)
|
||||
{
|
||||
FSZone;
|
||||
// <FS> Fix for misaligned unsigned ints in LLUUID; by Sovereign Engineer / Shyotl Kuhr
|
||||
//U32 *tmp = (U32 *)mData;
|
||||
//U32 *rhstmp = (U32 *)rhs.mData;
|
||||
|
|
@ -1046,6 +1049,7 @@ LLUUID::LLUUID()
|
|||
// Assignment
|
||||
LLUUID& LLUUID::operator=(const LLUUID& rhs)
|
||||
{
|
||||
FSZone;
|
||||
// <FS> Fix for misaligned unsigned ints in LLUUID; by Sovereign Engineer / Shyotl Kuhr
|
||||
//// No need to check the case where this==&rhs. The branch is slower than the write.
|
||||
//U32 *tmp = (U32 *)mData;
|
||||
|
|
|
|||
|
|
@ -29,10 +29,11 @@
|
|||
#include <iostream>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
#include <cstring> // <FS:Beq> for std::memmove
|
||||
#include "stdtypes.h"
|
||||
#include "llpreprocessor.h"
|
||||
#include <boost/functional/hash.hpp>
|
||||
|
||||
#include "fstelemetry.h"
|
||||
class LLMutex;
|
||||
|
||||
const S32 UUID_BYTES = 16;
|
||||
|
|
@ -56,7 +57,9 @@ public:
|
|||
explicit LLUUID(const char *in_string); // Convert from string.
|
||||
explicit LLUUID(const std::string& in_string); // Convert from string.
|
||||
LLUUID(const LLUUID &in);
|
||||
LLUUID(LLUUID&& rhs) noexcept { FSZone; std::memmove(mData, rhs.mData, sizeof(mData));};
|
||||
LLUUID &operator=(const LLUUID &rhs);
|
||||
LLUUID &operator=(LLUUID &&rhs) noexcept {FSZone; std::memmove(mData, rhs.mData, sizeof(mData));return *this;};
|
||||
|
||||
~LLUUID();
|
||||
|
||||
|
|
@ -112,6 +115,61 @@ public:
|
|||
void toString(std::string& out) const;
|
||||
void toCompressedString(char *out) const; // Does not allocate memory, needs 17 characters (including \0)
|
||||
void toCompressedString(std::string& out) const;
|
||||
|
||||
// last 4 chars for quick ref - Very lightweight, no nul-term added - provide your own, ensure min 4 bytes.
|
||||
# define hexnybl(N) (N)>9?((N)-10)+'a':(N)+'0'
|
||||
inline char * toShortString(char *out) const
|
||||
{
|
||||
FSZone;
|
||||
out[0] = hexnybl(mData[14]>>4);
|
||||
out[1] = hexnybl(mData[14]&15);
|
||||
out[2] = hexnybl(mData[15]>>4);
|
||||
out[3] = hexnybl(mData[15]&15);
|
||||
return out;
|
||||
}
|
||||
// full uuid - Much lighterweight than default, no allocation, or nul-term added - provide your own, ensure min 36 bytes.
|
||||
inline char * toStringFast(char *out) const
|
||||
{
|
||||
FSZone;
|
||||
out[0] = hexnybl(mData[0]>>4);
|
||||
out[1] = hexnybl(mData[0]&15);
|
||||
out[2] = hexnybl(mData[1]>>4);
|
||||
out[3] = hexnybl(mData[1]&15);
|
||||
out[4] = hexnybl(mData[2]>>4);
|
||||
out[5] = hexnybl(mData[2]&15);
|
||||
out[6] = hexnybl(mData[3]>>4);
|
||||
out[7] = hexnybl(mData[3]&15);
|
||||
out[8] = '-';
|
||||
out[9] = hexnybl(mData[4]>>4);
|
||||
out[10] = hexnybl(mData[4]&15);
|
||||
out[11] = hexnybl(mData[5]>>4);
|
||||
out[12] = hexnybl(mData[5]&15);
|
||||
out[13] = '-';
|
||||
out[14] = hexnybl(mData[6]>>4);
|
||||
out[15] = hexnybl(mData[6]&15);
|
||||
out[16] = hexnybl(mData[7]>>4);
|
||||
out[17] = hexnybl(mData[7]&15);
|
||||
out[18] = '-';
|
||||
out[19] = hexnybl(mData[8]>>4);
|
||||
out[20] = hexnybl(mData[8]&15);
|
||||
out[21] = hexnybl(mData[9]>>4);
|
||||
out[22] = hexnybl(mData[9]&15);
|
||||
out[23] = '-';
|
||||
out[24] = hexnybl(mData[10]>>4);
|
||||
out[25] = hexnybl(mData[10]&15);
|
||||
out[26] = hexnybl(mData[11]>>4);
|
||||
out[27] = hexnybl(mData[11]&15);
|
||||
out[28] = hexnybl(mData[12]>>4);
|
||||
out[29] = hexnybl(mData[12]&15);
|
||||
out[30] = hexnybl(mData[13]>>4);
|
||||
out[31] = hexnybl(mData[13]&15);
|
||||
out[32] = hexnybl(mData[14]>>4);
|
||||
out[33] = hexnybl(mData[14]&15);
|
||||
out[34] = hexnybl(mData[15]>>4);
|
||||
out[35] = hexnybl(mData[15]&15);
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
std::string asString() const;
|
||||
std::string getString() const;
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@
|
|||
|
||||
#include "apr.h" // thread-related functions
|
||||
#include "_refcounted.h"
|
||||
#include "fstelemetry.h"
|
||||
|
||||
namespace LLCoreInt
|
||||
{
|
||||
|
|
@ -54,6 +55,10 @@ private:
|
|||
|
||||
void run()
|
||||
{ // THREAD CONTEXT
|
||||
// <FS:Beq> - Add threadnames
|
||||
LL_INFOS("THREAD") << "Started unnamed HTTP thread " << LL_ENDL;
|
||||
FSThreadName( "HTTP" );
|
||||
// </FS:Beq>
|
||||
|
||||
// Take out additional reference for the at_exit handler
|
||||
addRef();
|
||||
|
|
|
|||
|
|
@ -785,7 +785,7 @@ void LLCrashLogger::init_curl()
|
|||
}
|
||||
|
||||
CRYPTO_set_locking_callback(ssl_locking_callback);
|
||||
CRYPTO_THREADID_set_callback(ssl_thread_id_callback);
|
||||
(void)CRYPTO_THREADID_set_callback(ssl_thread_id_callback);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -343,6 +343,11 @@ const std::string &LLDir::getDumpDir() const
|
|||
return LLDir::sDumpDir;
|
||||
}
|
||||
|
||||
bool LLDir::dumpDirExists() const
|
||||
{
|
||||
return !sDumpDir.empty();
|
||||
}
|
||||
|
||||
const std::string &LLDir::getPerAccountChatLogsDir() const
|
||||
{
|
||||
return mPerAccountChatLogsDir;
|
||||
|
|
@ -953,6 +958,11 @@ std::string LLDir::getScrubbedFileName(const std::string uncleanFileName)
|
|||
return name;
|
||||
}
|
||||
|
||||
std::string LLDir::getDumpLogsDirPath(const std::string &file_name)
|
||||
{
|
||||
return gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "dump_logs", file_name);
|
||||
}
|
||||
|
||||
// static
|
||||
std::string LLDir::getForbiddenFileChars()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -128,6 +128,7 @@ class LLDir
|
|||
const std::string &getLindenUserDir() const; // Location of the Linden user dir.
|
||||
const std::string &getChatLogsDir() const; // Location of the chat logs dir.
|
||||
const std::string &getDumpDir() const; // Location of the per-run dump dir.
|
||||
bool dumpDirExists() const;
|
||||
const std::string &getPerAccountChatLogsDir() const; // Location of the per account chat logs dir.
|
||||
const std::string &getTempDir() const; // Common temporary directory
|
||||
const std::string getCacheDir(bool get_default = false) const; // Location of the cache.
|
||||
|
|
@ -218,6 +219,8 @@ class LLDir
|
|||
// random filename in common temporary directory
|
||||
std::string getTempFilename() const;
|
||||
|
||||
static std::string getDumpLogsDirPath(const std::string &file_name = "");
|
||||
|
||||
// For producing safe download file names from potentially unsafe ones
|
||||
static std::string getScrubbedFileName(const std::string uncleanFileName);
|
||||
static std::string getForbiddenFileChars();
|
||||
|
|
|
|||
|
|
@ -27,8 +27,8 @@
|
|||
#include "lldiriterator.h"
|
||||
|
||||
#include "fix_macros.h"
|
||||
#include "llregex.h"
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/regex.hpp>
|
||||
|
||||
namespace fs = boost::filesystem;
|
||||
|
||||
|
|
@ -131,7 +131,7 @@ bool LLDirIterator::Impl::next(std::string &fname)
|
|||
{
|
||||
boost::smatch match;
|
||||
std::string name = mIter->path().filename().string();
|
||||
found = boost::regex_match(name, match, mFilterExp);
|
||||
found = ll_regex_match(name, match, mFilterExp);
|
||||
if (found)
|
||||
{
|
||||
fname = name;
|
||||
|
|
|
|||
|
|
@ -1498,7 +1498,7 @@ bool LLImageRaw::scale( S32 new_width, S32 new_height, bool scale_image_data )
|
|||
setDataAndSize(new_data, new_width, new_height, components);
|
||||
}
|
||||
}
|
||||
else
|
||||
else try
|
||||
{
|
||||
// copy out existing image data
|
||||
S32 temp_data_size = old_width * old_height * components;
|
||||
|
|
@ -1532,6 +1532,11 @@ bool LLImageRaw::scale( S32 new_width, S32 new_height, bool scale_image_data )
|
|||
}
|
||||
}
|
||||
}
|
||||
catch (std::bad_alloc&) // for temp_buffer
|
||||
{
|
||||
LL_WARNS() << "Failed to allocate temporary image buffer" << LL_ENDL;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -395,7 +395,7 @@ bool LLSettingsBase::validate()
|
|||
|
||||
LLSD LLSettingsBase::settingValidation(LLSD &settings, validation_list_t &validations, bool partial)
|
||||
{
|
||||
static Validator validateName(SETTING_NAME, false, LLSD::TypeString, boost::bind(&Validator::verifyStringLength, _1, 63));
|
||||
static Validator validateName(SETTING_NAME, false, LLSD::TypeString, boost::bind(&Validator::verifyStringLength, _1, _2, 63));
|
||||
static Validator validateId(SETTING_ID, false, LLSD::TypeUUID);
|
||||
static Validator validateHash(SETTING_HASH, false, LLSD::TypeInteger);
|
||||
static Validator validateType(SETTING_TYPE, false, LLSD::TypeString);
|
||||
|
|
@ -534,7 +534,7 @@ bool LLSettingsBase::Validator::verify(LLSD &data, U32 flags)
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!mVerify.empty() && !mVerify(data[mName]))
|
||||
if (!mVerify.empty() && !mVerify(data[mName], flags))
|
||||
{
|
||||
LL_WARNS("SETTINGS") << "Setting '" << mName << "' fails validation." << LL_ENDL;
|
||||
return false;
|
||||
|
|
@ -543,17 +543,17 @@ bool LLSettingsBase::Validator::verify(LLSD &data, U32 flags)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool LLSettingsBase::Validator::verifyColor(LLSD &value)
|
||||
bool LLSettingsBase::Validator::verifyColor(LLSD &value, U32)
|
||||
{
|
||||
return (value.size() == 3 || value.size() == 4);
|
||||
}
|
||||
|
||||
bool LLSettingsBase::Validator::verifyVector(LLSD &value, S32 length)
|
||||
bool LLSettingsBase::Validator::verifyVector(LLSD &value, U32, S32 length)
|
||||
{
|
||||
return (value.size() == length);
|
||||
}
|
||||
|
||||
bool LLSettingsBase::Validator::verifyVectorNormalized(LLSD &value, S32 length)
|
||||
bool LLSettingsBase::Validator::verifyVectorNormalized(LLSD &value, U32, S32 length)
|
||||
{
|
||||
if (value.size() != length)
|
||||
return false;
|
||||
|
|
@ -596,7 +596,7 @@ bool LLSettingsBase::Validator::verifyVectorNormalized(LLSD &value, S32 length)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool LLSettingsBase::Validator::verifyVectorMinMax(LLSD &value, LLSD minvals, LLSD maxvals)
|
||||
bool LLSettingsBase::Validator::verifyVectorMinMax(LLSD &value, U32, LLSD minvals, LLSD maxvals)
|
||||
{
|
||||
for (S32 index = 0; index < value.size(); ++index)
|
||||
{
|
||||
|
|
@ -619,12 +619,12 @@ bool LLSettingsBase::Validator::verifyVectorMinMax(LLSD &value, LLSD minvals, LL
|
|||
return true;
|
||||
}
|
||||
|
||||
bool LLSettingsBase::Validator::verifyQuaternion(LLSD &value)
|
||||
bool LLSettingsBase::Validator::verifyQuaternion(LLSD &value, U32)
|
||||
{
|
||||
return (value.size() == 4);
|
||||
}
|
||||
|
||||
bool LLSettingsBase::Validator::verifyQuaternionNormal(LLSD &value)
|
||||
bool LLSettingsBase::Validator::verifyQuaternionNormal(LLSD &value, U32)
|
||||
{
|
||||
if (value.size() != 4)
|
||||
return false;
|
||||
|
|
@ -642,7 +642,7 @@ bool LLSettingsBase::Validator::verifyQuaternionNormal(LLSD &value)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool LLSettingsBase::Validator::verifyFloatRange(LLSD &value, LLSD range)
|
||||
bool LLSettingsBase::Validator::verifyFloatRange(LLSD &value, U32, LLSD range)
|
||||
{
|
||||
F64 real = value.asReal();
|
||||
|
||||
|
|
@ -655,7 +655,7 @@ bool LLSettingsBase::Validator::verifyFloatRange(LLSD &value, LLSD range)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool LLSettingsBase::Validator::verifyIntegerRange(LLSD &value, LLSD range)
|
||||
bool LLSettingsBase::Validator::verifyIntegerRange(LLSD &value, U32, LLSD range)
|
||||
{
|
||||
S32 ival = value.asInteger();
|
||||
|
||||
|
|
@ -668,7 +668,7 @@ bool LLSettingsBase::Validator::verifyIntegerRange(LLSD &value, LLSD range)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool LLSettingsBase::Validator::verifyStringLength(LLSD &value, S32 length)
|
||||
bool LLSettingsBase::Validator::verifyStringLength(LLSD &value, U32, S32 length)
|
||||
{
|
||||
std::string sval = value.asString();
|
||||
|
||||
|
|
|
|||
|
|
@ -270,7 +270,7 @@ public:
|
|||
public:
|
||||
static const U32 VALIDATION_PARTIAL;
|
||||
|
||||
typedef boost::function<bool(LLSD &)> verify_pr;
|
||||
typedef boost::function<bool(LLSD &, U32)> verify_pr;
|
||||
|
||||
Validator(std::string name, bool required, LLSD::Type type, verify_pr verify = verify_pr(), LLSD defval = LLSD()) :
|
||||
mName(name),
|
||||
|
|
@ -287,15 +287,15 @@ public:
|
|||
bool verify(LLSD &data, U32 flags);
|
||||
|
||||
// Some basic verifications
|
||||
static bool verifyColor(LLSD &value);
|
||||
static bool verifyVector(LLSD &value, S32 length);
|
||||
static bool verifyVectorMinMax(LLSD &value, LLSD minvals, LLSD maxvals);
|
||||
static bool verifyVectorNormalized(LLSD &value, S32 length);
|
||||
static bool verifyQuaternion(LLSD &value);
|
||||
static bool verifyQuaternionNormal(LLSD &value);
|
||||
static bool verifyFloatRange(LLSD &value, LLSD range);
|
||||
static bool verifyIntegerRange(LLSD &value, LLSD range);
|
||||
static bool verifyStringLength(LLSD &value, S32 length);
|
||||
static bool verifyColor(LLSD &value, U32 flags);
|
||||
static bool verifyVector(LLSD &value, U32 flags, S32 length);
|
||||
static bool verifyVectorMinMax(LLSD &value, U32 flags, LLSD minvals, LLSD maxvals);
|
||||
static bool verifyVectorNormalized(LLSD &value, U32 flags, S32 length);
|
||||
static bool verifyQuaternion(LLSD &value, U32 flags);
|
||||
static bool verifyQuaternionNormal(LLSD &value, U32 flags);
|
||||
static bool verifyFloatRange(LLSD &value, U32 flags, LLSD range);
|
||||
static bool verifyIntegerRange(LLSD &value, U32 flags, LLSD range);
|
||||
static bool verifyStringLength(LLSD &value, U32 flags, S32 length);
|
||||
|
||||
private:
|
||||
std::string mName;
|
||||
|
|
|
|||
|
|
@ -461,7 +461,7 @@ void LLSettingsDay::blend(const LLSettingsBase::ptr_t &other, F64 mix)
|
|||
|
||||
namespace
|
||||
{
|
||||
bool validateDayCycleTrack(LLSD &value)
|
||||
bool validateDayCycleTrack(LLSD &value, U32 flags)
|
||||
{
|
||||
// Trim extra tracks.
|
||||
while (value.size() > LLSettingsDay::TRACK_MAX)
|
||||
|
|
@ -532,7 +532,7 @@ namespace
|
|||
return true;
|
||||
}
|
||||
|
||||
bool validateDayCycleFrames(LLSD &value)
|
||||
bool validateDayCycleFrames(LLSD &value, U32 flags)
|
||||
{
|
||||
bool hasSky(false);
|
||||
bool hasWater(false);
|
||||
|
|
@ -545,7 +545,7 @@ namespace
|
|||
if (ftype == "sky")
|
||||
{
|
||||
LLSettingsSky::validation_list_t valid_sky = LLSettingsSky::validationList();
|
||||
LLSD res_sky = LLSettingsBase::settingValidation(frame, valid_sky);
|
||||
LLSD res_sky = LLSettingsBase::settingValidation(frame, valid_sky, flags);
|
||||
|
||||
if (res_sky["success"].asInteger() == 0)
|
||||
{
|
||||
|
|
@ -558,7 +558,7 @@ namespace
|
|||
else if (ftype == "water")
|
||||
{
|
||||
LLSettingsWater::validation_list_t valid_h2o = LLSettingsWater::validationList();
|
||||
LLSD res_h2o = LLSettingsBase::settingValidation(frame, valid_h2o);
|
||||
LLSD res_h2o = LLSettingsBase::settingValidation(frame, valid_h2o, flags);
|
||||
if (res_h2o["success"].asInteger() == 0)
|
||||
{
|
||||
LL_WARNS("SETTINGS") << "Water setting named '" << (*itf).first << "' validation failed!: " << res_h2o << LL_ENDL;
|
||||
|
|
@ -574,18 +574,20 @@ namespace
|
|||
}
|
||||
}
|
||||
|
||||
if (!hasSky)
|
||||
if ((flags & LLSettingsBase::Validator::VALIDATION_PARTIAL) == 0)
|
||||
{
|
||||
LL_WARNS("SETTINGS") << "No skies defined." << LL_ENDL;
|
||||
return false;
|
||||
}
|
||||
if (!hasSky)
|
||||
{
|
||||
LL_WARNS("SETTINGS") << "No skies defined." << LL_ENDL;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!hasWater)
|
||||
{
|
||||
LL_WARNS("SETTINGS") << "No waters defined." << LL_ENDL;
|
||||
return false;
|
||||
if (!hasWater)
|
||||
{
|
||||
LL_WARNS("SETTINGS") << "No waters defined." << LL_ENDL;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -156,29 +156,29 @@ LLSettingsSky::validation_list_t legacyHazeValidationList()
|
|||
if (legacyHazeValidation.empty())
|
||||
{
|
||||
legacyHazeValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_AMBIENT, false, LLSD::TypeArray,
|
||||
boost::bind(&LLSettingsBase::Validator::verifyVectorMinMax, _1,
|
||||
boost::bind(&LLSettingsBase::Validator::verifyVectorMinMax, _1, _2,
|
||||
LLSD(LLSDArray(0.0f)(0.0f)(0.0f)("*")),
|
||||
LLSD(LLSDArray(3.0f)(3.0f)(3.0f)("*")))));
|
||||
legacyHazeValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_BLUE_DENSITY, false, LLSD::TypeArray,
|
||||
boost::bind(&LLSettingsBase::Validator::verifyVectorMinMax, _1,
|
||||
boost::bind(&LLSettingsBase::Validator::verifyVectorMinMax, _1, _2,
|
||||
LLSD(LLSDArray(0.0f)(0.0f)(0.0f)("*")),
|
||||
LLSD(LLSDArray(3.0f)(3.0f)(3.0f)("*")))));
|
||||
legacyHazeValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_BLUE_HORIZON, false, LLSD::TypeArray,
|
||||
boost::bind(&LLSettingsBase::Validator::verifyVectorMinMax, _1,
|
||||
boost::bind(&LLSettingsBase::Validator::verifyVectorMinMax, _1, _2,
|
||||
LLSD(LLSDArray(0.0f)(0.0f)(0.0f)("*")),
|
||||
LLSD(LLSDArray(3.0f)(3.0f)(3.0f)("*")))));
|
||||
legacyHazeValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_HAZE_DENSITY, false, LLSD::TypeReal,
|
||||
boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(5.0f)))));
|
||||
boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.0f)(5.0f)))));
|
||||
legacyHazeValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_HAZE_HORIZON, false, LLSD::TypeReal,
|
||||
boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(5.0f)))));
|
||||
boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.0f)(5.0f)))));
|
||||
// <FS:Beq> FIRE-29682 Allow full range density multipliers
|
||||
// legacyHazeValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_MULTIPLIER, false, LLSD::TypeReal,
|
||||
// boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0001f)(2.0f)))));
|
||||
// boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.0001f)(2.0f)))));
|
||||
legacyHazeValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_MULTIPLIER, false, LLSD::TypeReal,
|
||||
boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0000001f)(2.0f)))));
|
||||
boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.0000001f)(2.0f)))));
|
||||
// </FS:Beq>
|
||||
legacyHazeValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DISTANCE_MULTIPLIER, false, LLSD::TypeReal,
|
||||
boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0001f)(1000.0f)))));
|
||||
boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.0001f)(1000.0f)))));
|
||||
}
|
||||
return legacyHazeValidation;
|
||||
}
|
||||
|
|
@ -189,19 +189,19 @@ LLSettingsSky::validation_list_t rayleighValidationList()
|
|||
if (rayleighValidation.empty())
|
||||
{
|
||||
rayleighValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_WIDTH, false, LLSD::TypeReal,
|
||||
boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(32768.0f)))));
|
||||
boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.0f)(32768.0f)))));
|
||||
|
||||
rayleighValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_EXP_TERM, false, LLSD::TypeReal,
|
||||
boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(2.0f)))));
|
||||
boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.0f)(2.0f)))));
|
||||
|
||||
rayleighValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_EXP_SCALE_FACTOR, false, LLSD::TypeReal,
|
||||
boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, LLSD(LLSDArray(-1.0f)(1.0f)))));
|
||||
boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(-1.0f)(1.0f)))));
|
||||
|
||||
rayleighValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_LINEAR_TERM, false, LLSD::TypeReal,
|
||||
boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(2.0f)))));
|
||||
boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.0f)(2.0f)))));
|
||||
|
||||
rayleighValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_CONSTANT_TERM, false, LLSD::TypeReal,
|
||||
boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(1.0f)))));
|
||||
boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.0f)(1.0f)))));
|
||||
}
|
||||
return rayleighValidation;
|
||||
}
|
||||
|
|
@ -212,19 +212,19 @@ LLSettingsSky::validation_list_t absorptionValidationList()
|
|||
if (absorptionValidation.empty())
|
||||
{
|
||||
absorptionValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_WIDTH, false, LLSD::TypeReal,
|
||||
boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(32768.0f)))));
|
||||
boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.0f)(32768.0f)))));
|
||||
|
||||
absorptionValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_EXP_TERM, false, LLSD::TypeReal,
|
||||
boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(2.0f)))));
|
||||
boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.0f)(2.0f)))));
|
||||
|
||||
absorptionValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_EXP_SCALE_FACTOR, false, LLSD::TypeReal,
|
||||
boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, LLSD(LLSDArray(-1.0f)(1.0f)))));
|
||||
boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(-1.0f)(1.0f)))));
|
||||
|
||||
absorptionValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_LINEAR_TERM, false, LLSD::TypeReal,
|
||||
boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(2.0f)))));
|
||||
boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.0f)(2.0f)))));
|
||||
|
||||
absorptionValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_CONSTANT_TERM, false, LLSD::TypeReal,
|
||||
boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(1.0f)))));
|
||||
boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.0f)(1.0f)))));
|
||||
}
|
||||
return absorptionValidation;
|
||||
}
|
||||
|
|
@ -235,31 +235,31 @@ LLSettingsSky::validation_list_t mieValidationList()
|
|||
if (mieValidation.empty())
|
||||
{
|
||||
mieValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_WIDTH, false, LLSD::TypeReal,
|
||||
boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(32768.0f)))));
|
||||
boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.0f)(32768.0f)))));
|
||||
|
||||
mieValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_EXP_TERM, false, LLSD::TypeReal,
|
||||
boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(2.0f)))));
|
||||
boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.0f)(2.0f)))));
|
||||
|
||||
mieValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_EXP_SCALE_FACTOR, false, LLSD::TypeReal,
|
||||
boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, LLSD(LLSDArray(-1.0f)(1.0f)))));
|
||||
boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(-1.0f)(1.0f)))));
|
||||
|
||||
mieValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_LINEAR_TERM, false, LLSD::TypeReal,
|
||||
boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(2.0f)))));
|
||||
boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.0f)(2.0f)))));
|
||||
|
||||
mieValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_CONSTANT_TERM, false, LLSD::TypeReal,
|
||||
boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(1.0f)))));
|
||||
boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.0f)(1.0f)))));
|
||||
|
||||
mieValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_MIE_ANISOTROPY_FACTOR, false, LLSD::TypeReal,
|
||||
boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(1.0f)))));
|
||||
boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.0f)(1.0f)))));
|
||||
}
|
||||
return mieValidation;
|
||||
}
|
||||
|
||||
bool validateLegacyHaze(LLSD &value)
|
||||
bool validateLegacyHaze(LLSD &value, U32 flags)
|
||||
{
|
||||
LLSettingsSky::validation_list_t legacyHazeValidations = legacyHazeValidationList();
|
||||
llassert(value.type() == LLSD::TypeMap);
|
||||
LLSD result = LLSettingsBase::settingValidation(value, legacyHazeValidations);
|
||||
LLSD result = LLSettingsBase::settingValidation(value, legacyHazeValidations, flags);
|
||||
if (result["errors"].size() > 0)
|
||||
{
|
||||
LL_WARNS("SETTINGS") << "Legacy Haze Config Validation errors: " << result["errors"] << LL_ENDL;
|
||||
|
|
@ -273,7 +273,7 @@ bool validateLegacyHaze(LLSD &value)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool validateRayleighLayers(LLSD &value)
|
||||
bool validateRayleighLayers(LLSD &value, U32 flags)
|
||||
{
|
||||
LLSettingsSky::validation_list_t rayleighValidations = rayleighValidationList();
|
||||
if (value.isArray())
|
||||
|
|
@ -284,24 +284,24 @@ bool validateRayleighLayers(LLSD &value)
|
|||
LLSD& layerConfig = (*itf);
|
||||
if (layerConfig.type() == LLSD::TypeMap)
|
||||
{
|
||||
if (!validateRayleighLayers(layerConfig))
|
||||
if (!validateRayleighLayers(layerConfig, flags))
|
||||
{
|
||||
allGood = false;
|
||||
}
|
||||
}
|
||||
else if (layerConfig.type() == LLSD::TypeArray)
|
||||
{
|
||||
return validateRayleighLayers(layerConfig);
|
||||
return validateRayleighLayers(layerConfig, flags);
|
||||
}
|
||||
else
|
||||
{
|
||||
return LLSettingsBase::settingValidation(value, rayleighValidations);
|
||||
return LLSettingsBase::settingValidation(value, rayleighValidations, flags);
|
||||
}
|
||||
}
|
||||
return allGood;
|
||||
}
|
||||
llassert(value.type() == LLSD::TypeMap);
|
||||
LLSD result = LLSettingsBase::settingValidation(value, rayleighValidations);
|
||||
LLSD result = LLSettingsBase::settingValidation(value, rayleighValidations, flags);
|
||||
if (result["errors"].size() > 0)
|
||||
{
|
||||
LL_WARNS("SETTINGS") << "Rayleigh Config Validation errors: " << result["errors"] << LL_ENDL;
|
||||
|
|
@ -315,7 +315,7 @@ bool validateRayleighLayers(LLSD &value)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool validateAbsorptionLayers(LLSD &value)
|
||||
bool validateAbsorptionLayers(LLSD &value, U32 flags)
|
||||
{
|
||||
LLSettingsBase::validation_list_t absorptionValidations = absorptionValidationList();
|
||||
if (value.isArray())
|
||||
|
|
@ -326,24 +326,24 @@ bool validateAbsorptionLayers(LLSD &value)
|
|||
LLSD& layerConfig = (*itf);
|
||||
if (layerConfig.type() == LLSD::TypeMap)
|
||||
{
|
||||
if (!validateAbsorptionLayers(layerConfig))
|
||||
if (!validateAbsorptionLayers(layerConfig, flags))
|
||||
{
|
||||
allGood = false;
|
||||
}
|
||||
}
|
||||
else if (layerConfig.type() == LLSD::TypeArray)
|
||||
{
|
||||
return validateAbsorptionLayers(layerConfig);
|
||||
return validateAbsorptionLayers(layerConfig, flags);
|
||||
}
|
||||
else
|
||||
{
|
||||
return LLSettingsBase::settingValidation(value, absorptionValidations);
|
||||
return LLSettingsBase::settingValidation(value, absorptionValidations, flags);
|
||||
}
|
||||
}
|
||||
return allGood;
|
||||
}
|
||||
llassert(value.type() == LLSD::TypeMap);
|
||||
LLSD result = LLSettingsBase::settingValidation(value, absorptionValidations);
|
||||
LLSD result = LLSettingsBase::settingValidation(value, absorptionValidations, flags);
|
||||
if (result["errors"].size() > 0)
|
||||
{
|
||||
LL_WARNS("SETTINGS") << "Absorption Config Validation errors: " << result["errors"] << LL_ENDL;
|
||||
|
|
@ -357,7 +357,7 @@ bool validateAbsorptionLayers(LLSD &value)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool validateMieLayers(LLSD &value)
|
||||
bool validateMieLayers(LLSD &value, U32 flags)
|
||||
{
|
||||
LLSettingsBase::validation_list_t mieValidations = mieValidationList();
|
||||
if (value.isArray())
|
||||
|
|
@ -368,23 +368,23 @@ bool validateMieLayers(LLSD &value)
|
|||
LLSD& layerConfig = (*itf);
|
||||
if (layerConfig.type() == LLSD::TypeMap)
|
||||
{
|
||||
if (!validateMieLayers(layerConfig))
|
||||
if (!validateMieLayers(layerConfig, flags))
|
||||
{
|
||||
allGood = false;
|
||||
}
|
||||
}
|
||||
else if (layerConfig.type() == LLSD::TypeArray)
|
||||
{
|
||||
return validateMieLayers(layerConfig);
|
||||
return validateMieLayers(layerConfig, flags);
|
||||
}
|
||||
else
|
||||
{
|
||||
return LLSettingsBase::settingValidation(value, mieValidations);
|
||||
return LLSettingsBase::settingValidation(value, mieValidations, flags);
|
||||
}
|
||||
}
|
||||
return allGood;
|
||||
}
|
||||
LLSD result = LLSettingsBase::settingValidation(value, mieValidations);
|
||||
LLSD result = LLSettingsBase::settingValidation(value, mieValidations, flags);
|
||||
if (result["errors"].size() > 0)
|
||||
{
|
||||
LL_WARNS("SETTINGS") << "Mie Config Validation errors: " << result["errors"] << LL_ENDL;
|
||||
|
|
@ -563,80 +563,80 @@ LLSettingsSky::validation_list_t LLSettingsSky::validationList()
|
|||
validation.push_back(Validator(SETTING_HALO_TEXTUREID, false, LLSD::TypeUUID));
|
||||
|
||||
validation.push_back(Validator(SETTING_CLOUD_COLOR, true, LLSD::TypeArray,
|
||||
boost::bind(&Validator::verifyVectorMinMax, _1,
|
||||
boost::bind(&Validator::verifyVectorMinMax, _1, _2,
|
||||
LLSD(LLSDArray(0.0f)(0.0f)(0.0f)("*")),
|
||||
LLSD(LLSDArray(1.0f)(1.0f)(1.0f)("*")))));
|
||||
validation.push_back(Validator(SETTING_CLOUD_POS_DENSITY1, true, LLSD::TypeArray,
|
||||
boost::bind(&Validator::verifyVectorMinMax, _1,
|
||||
boost::bind(&Validator::verifyVectorMinMax, _1, _2,
|
||||
LLSD(LLSDArray(0.0f)(0.0f)(0.0f)("*")),
|
||||
LLSD(LLSDArray(1.0f)(1.0f)(3.0f)("*")))));
|
||||
validation.push_back(Validator(SETTING_CLOUD_POS_DENSITY2, true, LLSD::TypeArray,
|
||||
boost::bind(&Validator::verifyVectorMinMax, _1,
|
||||
boost::bind(&Validator::verifyVectorMinMax, _1, _2,
|
||||
LLSD(LLSDArray(0.0f)(0.0f)(0.0f)("*")),
|
||||
LLSD(LLSDArray(1.0f)(1.0f)(1.0f)("*")))));
|
||||
validation.push_back(Validator(SETTING_CLOUD_SCALE, true, LLSD::TypeReal,
|
||||
boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.001f)(3.0f)))));
|
||||
boost::bind(&Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.001f)(3.0f)))));
|
||||
validation.push_back(Validator(SETTING_CLOUD_SCROLL_RATE, true, LLSD::TypeArray,
|
||||
boost::bind(&Validator::verifyVectorMinMax, _1,
|
||||
boost::bind(&Validator::verifyVectorMinMax, _1, _2,
|
||||
LLSD(LLSDArray(-50.0f)(-50.0f)),
|
||||
LLSD(LLSDArray(50.0f)(50.0f)))));
|
||||
validation.push_back(Validator(SETTING_CLOUD_SHADOW, true, LLSD::TypeReal,
|
||||
boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(1.0f)))));
|
||||
boost::bind(&Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.0f)(1.0f)))));
|
||||
validation.push_back(Validator(SETTING_CLOUD_TEXTUREID, false, LLSD::TypeUUID));
|
||||
validation.push_back(Validator(SETTING_CLOUD_VARIANCE, false, LLSD::TypeReal,
|
||||
boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(1.0f)))));
|
||||
boost::bind(&Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.0f)(1.0f)))));
|
||||
|
||||
validation.push_back(Validator(SETTING_DOME_OFFSET, false, LLSD::TypeReal,
|
||||
boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(1.0f)))));
|
||||
boost::bind(&Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.0f)(1.0f)))));
|
||||
validation.push_back(Validator(SETTING_DOME_RADIUS, false, LLSD::TypeReal,
|
||||
boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(1000.0f)(2000.0f)))));
|
||||
boost::bind(&Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(1000.0f)(2000.0f)))));
|
||||
validation.push_back(Validator(SETTING_GAMMA, true, LLSD::TypeReal,
|
||||
boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(20.0f)))));
|
||||
boost::bind(&Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.0f)(20.0f)))));
|
||||
validation.push_back(Validator(SETTING_GLOW, true, LLSD::TypeArray,
|
||||
boost::bind(&Validator::verifyVectorMinMax, _1,
|
||||
boost::bind(&Validator::verifyVectorMinMax, _1, _2,
|
||||
LLSD(LLSDArray(0.2f)("*")(-10.0f)("*")),
|
||||
LLSD(LLSDArray(40.0f)("*")(10.0f)("*")))));
|
||||
|
||||
validation.push_back(Validator(SETTING_MAX_Y, true, LLSD::TypeReal,
|
||||
boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(10000.0f)))));
|
||||
boost::bind(&Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.0f)(10000.0f)))));
|
||||
validation.push_back(Validator(SETTING_MOON_ROTATION, true, LLSD::TypeArray, &Validator::verifyQuaternionNormal));
|
||||
validation.push_back(Validator(SETTING_MOON_SCALE, false, LLSD::TypeReal,
|
||||
boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.25f)(20.0f))), LLSD::Real(1.0)));
|
||||
boost::bind(&Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.25f)(20.0f))), LLSD::Real(1.0)));
|
||||
validation.push_back(Validator(SETTING_MOON_TEXTUREID, false, LLSD::TypeUUID));
|
||||
validation.push_back(Validator(SETTING_MOON_BRIGHTNESS, false, LLSD::TypeReal,
|
||||
boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(1.0f)))));
|
||||
boost::bind(&Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.0f)(1.0f)))));
|
||||
|
||||
validation.push_back(Validator(SETTING_STAR_BRIGHTNESS, true, LLSD::TypeReal,
|
||||
boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(500.0f)))));
|
||||
boost::bind(&Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.0f)(500.0f)))));
|
||||
validation.push_back(Validator(SETTING_SUNLIGHT_COLOR, true, LLSD::TypeArray,
|
||||
boost::bind(&Validator::verifyVectorMinMax, _1,
|
||||
boost::bind(&Validator::verifyVectorMinMax, _1, _2,
|
||||
LLSD(LLSDArray(0.0f)(0.0f)(0.0f)("*")),
|
||||
LLSD(LLSDArray(3.0f)(3.0f)(3.0f)("*")))));
|
||||
validation.push_back(Validator(SETTING_SUN_ROTATION, true, LLSD::TypeArray, &Validator::verifyQuaternionNormal));
|
||||
validation.push_back(Validator(SETTING_SUN_SCALE, false, LLSD::TypeReal,
|
||||
boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.25f)(20.0f))), LLSD::Real(1.0)));
|
||||
boost::bind(&Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.25f)(20.0f))), LLSD::Real(1.0)));
|
||||
validation.push_back(Validator(SETTING_SUN_TEXTUREID, false, LLSD::TypeUUID));
|
||||
|
||||
validation.push_back(Validator(SETTING_PLANET_RADIUS, true, LLSD::TypeReal,
|
||||
boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(1000.0f)(32768.0f)))));
|
||||
boost::bind(&Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(1000.0f)(32768.0f)))));
|
||||
|
||||
validation.push_back(Validator(SETTING_SKY_BOTTOM_RADIUS, true, LLSD::TypeReal,
|
||||
boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(1000.0f)(32768.0f)))));
|
||||
boost::bind(&Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(1000.0f)(32768.0f)))));
|
||||
|
||||
validation.push_back(Validator(SETTING_SKY_TOP_RADIUS, true, LLSD::TypeReal,
|
||||
boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(1000.0f)(32768.0f)))));
|
||||
boost::bind(&Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(1000.0f)(32768.0f)))));
|
||||
|
||||
validation.push_back(Validator(SETTING_SUN_ARC_RADIANS, true, LLSD::TypeReal,
|
||||
boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(0.1f)))));
|
||||
boost::bind(&Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.0f)(0.1f)))));
|
||||
|
||||
validation.push_back(Validator(SETTING_SKY_MOISTURE_LEVEL, false, LLSD::TypeReal,
|
||||
boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(1.0f)))));
|
||||
boost::bind(&Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.0f)(1.0f)))));
|
||||
|
||||
validation.push_back(Validator(SETTING_SKY_DROPLET_RADIUS, false, LLSD::TypeReal,
|
||||
boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(5.0f)(1000.0f)))));
|
||||
boost::bind(&Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(5.0f)(1000.0f)))));
|
||||
|
||||
validation.push_back(Validator(SETTING_SKY_ICE_LEVEL, false, LLSD::TypeReal,
|
||||
boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(1.0f)))));
|
||||
boost::bind(&Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.0f)(1.0f)))));
|
||||
|
||||
validation.push_back(Validator(SETTING_RAYLEIGH_CONFIG, true, LLSD::TypeArray, &validateRayleighLayers));
|
||||
validation.push_back(Validator(SETTING_ABSORPTION_CONFIG, true, LLSD::TypeArray, &validateAbsorptionLayers));
|
||||
|
|
|
|||
|
|
@ -236,34 +236,34 @@ LLSettingsWater::validation_list_t LLSettingsWater::validationList()
|
|||
// in deeply nested arrays like this [[[[[[[[[[v1,v2,v3]]]]]]]]]]
|
||||
|
||||
validation.push_back(Validator(SETTING_BLUR_MULTIPLIER, true, LLSD::TypeReal,
|
||||
boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(-0.5f)(0.5f)))));
|
||||
boost::bind(&Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(-0.5f)(0.5f)))));
|
||||
validation.push_back(Validator(SETTING_FOG_COLOR, true, LLSD::TypeArray,
|
||||
boost::bind(&Validator::verifyVectorMinMax, _1,
|
||||
boost::bind(&Validator::verifyVectorMinMax, _1, _2,
|
||||
LLSD(LLSDArray(0.0f)(0.0f)(0.0f)(1.0f)),
|
||||
LLSD(LLSDArray(1.0f)(1.0f)(1.0f)(1.0f)))));
|
||||
validation.push_back(Validator(SETTING_FOG_DENSITY, true, LLSD::TypeReal,
|
||||
boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(-10.0f)(10.0f)))));
|
||||
boost::bind(&Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(-10.0f)(10.0f)))));
|
||||
validation.push_back(Validator(SETTING_FOG_MOD, true, LLSD::TypeReal,
|
||||
boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(20.0f)))));
|
||||
boost::bind(&Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.0f)(20.0f)))));
|
||||
validation.push_back(Validator(SETTING_FRESNEL_OFFSET, true, LLSD::TypeReal,
|
||||
boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(1.0f)))));
|
||||
boost::bind(&Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.0f)(1.0f)))));
|
||||
validation.push_back(Validator(SETTING_FRESNEL_SCALE, true, LLSD::TypeReal,
|
||||
boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(1.0f)))));
|
||||
boost::bind(&Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.0f)(1.0f)))));
|
||||
validation.push_back(Validator(SETTING_NORMAL_MAP, true, LLSD::TypeUUID));
|
||||
validation.push_back(Validator(SETTING_NORMAL_SCALE, true, LLSD::TypeArray,
|
||||
boost::bind(&Validator::verifyVectorMinMax, _1,
|
||||
boost::bind(&Validator::verifyVectorMinMax, _1, _2,
|
||||
LLSD(LLSDArray(0.0f)(0.0f)(0.0f)),
|
||||
LLSD(LLSDArray(10.0f)(10.0f)(10.0f)))));
|
||||
validation.push_back(Validator(SETTING_SCALE_ABOVE, true, LLSD::TypeReal,
|
||||
boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(3.0f)))));
|
||||
boost::bind(&Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.0f)(3.0f)))));
|
||||
validation.push_back(Validator(SETTING_SCALE_BELOW, true, LLSD::TypeReal,
|
||||
boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(3.0f)))));
|
||||
boost::bind(&Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.0f)(3.0f)))));
|
||||
validation.push_back(Validator(SETTING_WAVE1_DIR, true, LLSD::TypeArray,
|
||||
boost::bind(&Validator::verifyVectorMinMax, _1,
|
||||
boost::bind(&Validator::verifyVectorMinMax, _1, _2,
|
||||
LLSD(LLSDArray(-20.0f)(-20.0f)),
|
||||
LLSD(LLSDArray(20.0f)(20.0f)))));
|
||||
validation.push_back(Validator(SETTING_WAVE2_DIR, true, LLSD::TypeArray,
|
||||
boost::bind(&Validator::verifyVectorMinMax, _1,
|
||||
boost::bind(&Validator::verifyVectorMinMax, _1, _2,
|
||||
LLSD(LLSDArray(-20.0f)(-20.0f)),
|
||||
LLSD(LLSDArray(20.0f)(20.0f)))));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -172,6 +172,71 @@ BOOL LLDataPacker::unpackFixed(F32 &value, const char *name,
|
|||
return success;
|
||||
}
|
||||
|
||||
BOOL LLDataPacker::unpackU16s(U16 *values, S32 count, const char *name)
|
||||
{
|
||||
for (S32 idx = 0; idx < count; ++idx)
|
||||
{
|
||||
if (!unpackU16(values[idx], name))
|
||||
{
|
||||
LL_WARNS("DATAPACKER") << "Buffer overflow reading Unsigned 16s \"" << name << "\" at index " << idx << "!" << LL_ENDL;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL LLDataPacker::unpackS16s(S16 *values, S32 count, const char *name)
|
||||
{
|
||||
for (S32 idx = 0; idx < count; ++idx)
|
||||
{
|
||||
if (!unpackS16(values[idx], name))
|
||||
{
|
||||
LL_WARNS("DATAPACKER") << "Buffer overflow reading Signed 16s \"" << name << "\" at index " << idx << "!" << LL_ENDL;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL LLDataPacker::unpackF32s(F32 *values, S32 count, const char *name)
|
||||
{
|
||||
for (S32 idx = 0; idx < count; ++idx)
|
||||
{
|
||||
if (!unpackF32(values[idx], name))
|
||||
{
|
||||
LL_WARNS("DATAPACKER") << "Buffer overflow reading Float 32s \"" << name << "\" at index " << idx << "!" << LL_ENDL;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL LLDataPacker::unpackColor4Us(LLColor4U *values, S32 count, const char *name)
|
||||
{
|
||||
for (S32 idx = 0; idx < count; ++idx)
|
||||
{
|
||||
if (!unpackColor4U(values[idx], name))
|
||||
{
|
||||
LL_WARNS("DATAPACKER") << "Buffer overflow reading Float 32s \"" << name << "\" at index " << idx << "!" << LL_ENDL;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL LLDataPacker::unpackUUIDs(LLUUID *values, S32 count, const char *name)
|
||||
{
|
||||
for (S32 idx = 0; idx < count; ++idx)
|
||||
{
|
||||
if (!unpackUUID(values[idx], name))
|
||||
{
|
||||
LL_WARNS("DATAPACKER") << "Buffer overflow reading UUIDs \"" << name << "\" at index " << idx << "!" << LL_ENDL;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// LLDataPackerBinaryBuffer implementation
|
||||
//---------------------------------------------------------------------------
|
||||
|
|
@ -339,6 +404,29 @@ BOOL LLDataPackerBinaryBuffer::unpackU16(U16 &value, const char *name)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL LLDataPackerBinaryBuffer::packS16(const S16 value, const char *name)
|
||||
{
|
||||
BOOL success = verifyLength(sizeof(S16), name);
|
||||
|
||||
if (mWriteEnabled && success)
|
||||
{
|
||||
htolememcpy(mCurBufferp, &value, MVT_S16, 2);
|
||||
}
|
||||
mCurBufferp += 2;
|
||||
return success;
|
||||
}
|
||||
|
||||
BOOL LLDataPackerBinaryBuffer::unpackS16(S16 &value, const char *name)
|
||||
{
|
||||
BOOL success = verifyLength(sizeof(S16), name);
|
||||
|
||||
if (success)
|
||||
{
|
||||
htolememcpy(&value, mCurBufferp, MVT_S16, 2);
|
||||
}
|
||||
mCurBufferp += 2;
|
||||
return success;
|
||||
}
|
||||
|
||||
BOOL LLDataPackerBinaryBuffer::packU32(const U32 value, const char *name)
|
||||
{
|
||||
|
|
@ -939,6 +1027,52 @@ BOOL LLDataPackerAsciiBuffer::unpackU16(U16 &value, const char *name)
|
|||
return success;
|
||||
}
|
||||
|
||||
BOOL LLDataPackerAsciiBuffer::packS16(const S16 value, const char *name)
|
||||
{
|
||||
BOOL success = TRUE;
|
||||
writeIndentedName(name);
|
||||
int numCopied = 0;
|
||||
if (mWriteEnabled)
|
||||
{
|
||||
numCopied = snprintf(mCurBufferp, getBufferSize() - getCurrentSize(), "%d\n", value); /* Flawfinder: ignore */
|
||||
}
|
||||
else
|
||||
{
|
||||
numCopied = snprintf(DUMMY_BUFFER, sizeof(DUMMY_BUFFER), "%d\n", value); /* Flawfinder: ignore */
|
||||
}
|
||||
|
||||
// snprintf returns number of bytes that would have been written
|
||||
// had the output not being truncated. In that case, it will
|
||||
// return either -1 or value >= passed in size value . So a check needs to be added
|
||||
// to detect truncation, and if there is any, only account for the
|
||||
// actual number of bytes written..and not what could have been
|
||||
// written.
|
||||
if(numCopied < 0 || numCopied > getBufferSize() - getCurrentSize())
|
||||
{
|
||||
numCopied = getBufferSize() - getCurrentSize();
|
||||
LL_WARNS() << "LLDataPackerAsciiBuffer::packS16: val truncated: " << LL_ENDL;
|
||||
}
|
||||
|
||||
mCurBufferp += numCopied;
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
BOOL LLDataPackerAsciiBuffer::unpackS16(S16 &value, const char *name)
|
||||
{
|
||||
BOOL success = TRUE;
|
||||
char valuestr[DP_BUFSIZE]; /* Flawfinder: ignore */
|
||||
if (!getValueStr(name, valuestr, DP_BUFSIZE))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
S32 in_val;
|
||||
sscanf(valuestr, "%d", &in_val);
|
||||
value = in_val;
|
||||
return success;
|
||||
}
|
||||
|
||||
BOOL LLDataPackerAsciiBuffer::packU32(const U32 value, const char *name)
|
||||
{
|
||||
|
|
@ -1642,6 +1776,36 @@ BOOL LLDataPackerAsciiFile::unpackU16(U16 &value, const char *name)
|
|||
return success;
|
||||
}
|
||||
|
||||
BOOL LLDataPackerAsciiFile::packS16(const S16 value, const char *name)
|
||||
{
|
||||
BOOL success = TRUE;
|
||||
writeIndentedName(name);
|
||||
if (mFP)
|
||||
{
|
||||
fprintf(mFP, "%d\n", value);
|
||||
}
|
||||
else if (mOutputStream)
|
||||
{
|
||||
*mOutputStream << "" << value << "\n";
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
BOOL LLDataPackerAsciiFile::unpackS16(S16 &value, const char *name)
|
||||
{
|
||||
BOOL success = TRUE;
|
||||
char valuestr[DP_BUFSIZE]; /*Flawfinder: ignore */
|
||||
if (!getValueStr(name, valuestr, DP_BUFSIZE))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
S32 in_val;
|
||||
sscanf(valuestr, "%d", &in_val);
|
||||
value = in_val;
|
||||
return success;
|
||||
}
|
||||
|
||||
BOOL LLDataPackerAsciiFile::packU32(const U32 value, const char *name)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -62,6 +62,11 @@ public:
|
|||
|
||||
virtual BOOL packU16(const U16 value, const char *name) = 0;
|
||||
virtual BOOL unpackU16(U16 &value, const char *name) = 0;
|
||||
BOOL unpackU16s(U16 *value, S32 count, const char *name);
|
||||
|
||||
virtual BOOL packS16(const S16 value, const char *name) = 0;
|
||||
virtual BOOL unpackS16(S16 &value, const char *name) = 0;
|
||||
BOOL unpackS16s(S16 *value, S32 count, const char *name);
|
||||
|
||||
virtual BOOL packU32(const U32 value, const char *name) = 0;
|
||||
virtual BOOL unpackU32(U32 &value, const char *name) = 0;
|
||||
|
|
@ -71,6 +76,7 @@ public:
|
|||
|
||||
virtual BOOL packF32(const F32 value, const char *name) = 0;
|
||||
virtual BOOL unpackF32(F32 &value, const char *name) = 0;
|
||||
BOOL unpackF32s(F32 *values, S32 count, const char *name);
|
||||
|
||||
// Packs a float into an integer, using the given size
|
||||
// and picks the right U* data type to pack into.
|
||||
|
|
@ -84,6 +90,7 @@ public:
|
|||
|
||||
virtual BOOL packColor4U(const LLColor4U &value, const char *name) = 0;
|
||||
virtual BOOL unpackColor4U(LLColor4U &value, const char *name) = 0;
|
||||
BOOL unpackColor4Us(LLColor4U *values, S32 count, const char *name);
|
||||
|
||||
virtual BOOL packVector2(const LLVector2 &value, const char *name) = 0;
|
||||
virtual BOOL unpackVector2(LLVector2 &value, const char *name) = 0;
|
||||
|
|
@ -96,6 +103,7 @@ public:
|
|||
|
||||
virtual BOOL packUUID(const LLUUID &value, const char *name) = 0;
|
||||
virtual BOOL unpackUUID(LLUUID &value, const char *name) = 0;
|
||||
BOOL unpackUUIDs(LLUUID *values, S32 count, const char *name);
|
||||
U32 getPassFlags() const { return mPassFlags; }
|
||||
void setPassFlags(U32 flags) { mPassFlags = flags; }
|
||||
protected:
|
||||
|
|
@ -141,6 +149,9 @@ public:
|
|||
/*virtual*/ BOOL packU16(const U16 value, const char *name);
|
||||
/*virtual*/ BOOL unpackU16(U16 &value, const char *name);
|
||||
|
||||
/*virtual*/ BOOL packS16(const S16 value, const char *name);
|
||||
/*virtual*/ BOOL unpackS16(S16 &value, const char *name);
|
||||
|
||||
/*virtual*/ BOOL packU32(const U32 value, const char *name);
|
||||
/*virtual*/ BOOL unpackU32(U32 &value, const char *name);
|
||||
|
||||
|
|
@ -258,6 +269,9 @@ public:
|
|||
/*virtual*/ BOOL packU16(const U16 value, const char *name);
|
||||
/*virtual*/ BOOL unpackU16(U16 &value, const char *name);
|
||||
|
||||
/*virtual*/ BOOL packS16(const S16 value, const char *name);
|
||||
/*virtual*/ BOOL unpackS16(S16 &value, const char *name);
|
||||
|
||||
/*virtual*/ BOOL packU32(const U32 value, const char *name);
|
||||
/*virtual*/ BOOL unpackU32(U32 &value, const char *name);
|
||||
|
||||
|
|
@ -386,6 +400,9 @@ public:
|
|||
/*virtual*/ BOOL packU16(const U16 value, const char *name);
|
||||
/*virtual*/ BOOL unpackU16(U16 &value, const char *name);
|
||||
|
||||
/*virtual*/ BOOL packS16(const S16 value, const char *name);
|
||||
/*virtual*/ BOOL unpackS16(S16 &value, const char *name);
|
||||
|
||||
/*virtual*/ BOOL packU32(const U32 value, const char *name);
|
||||
/*virtual*/ BOOL unpackU32(U32 &value, const char *name);
|
||||
|
||||
|
|
|
|||
|
|
@ -281,6 +281,13 @@ char const* const _PREHASH_PricePerMeter = LLMessageStringTable::getInstance()->
|
|||
char const* const _PREHASH_RegionFlags = LLMessageStringTable::getInstance()->getString("RegionFlags");
|
||||
char const* const _PREHASH_RegionFlagsExtended = LLMessageStringTable::getInstance()->getString("RegionFlagsExtended");
|
||||
char const* const _PREHASH_RegionProtocols = LLMessageStringTable::getInstance()->getString("RegionProtocols");
|
||||
char const* const _PREHASH_ChatWhisperRange = LLMessageStringTable::getInstance()->getString("ChatWhisperRange");
|
||||
char const* const _PREHASH_ChatNormalRange = LLMessageStringTable::getInstance()->getString("ChatNormalRange");
|
||||
char const* const _PREHASH_ChatShoutRange = LLMessageStringTable::getInstance()->getString("ChatShoutRange");
|
||||
char const* const _PREHASH_ChatWhisperOffset = LLMessageStringTable::getInstance()->getString("ChatWhisperOffset");
|
||||
char const* const _PREHASH_ChatNormalOffset = LLMessageStringTable::getInstance()->getString("ChatNormalOffset");
|
||||
char const* const _PREHASH_ChatShoutOffset = LLMessageStringTable::getInstance()->getString("ChatShoutOffset");
|
||||
char const* const _PREHASH_ChatFlags = LLMessageStringTable::getInstance()->getString("ChatFlags");
|
||||
char const* const _PREHASH_VoteResult = LLMessageStringTable::getInstance()->getString("VoteResult");
|
||||
char const* const _PREHASH_ParcelDirFeeEstimate = LLMessageStringTable::getInstance()->getString("ParcelDirFeeEstimate");
|
||||
char const* const _PREHASH_ModifyBlock = LLMessageStringTable::getInstance()->getString("ModifyBlock");
|
||||
|
|
@ -309,6 +316,7 @@ char const* const _PREHASH_DuplicateFlags = LLMessageStringTable::getInstance()-
|
|||
char const* const _PREHASH_RegionInfo2 = LLMessageStringTable::getInstance()->getString("RegionInfo2");
|
||||
char const* const _PREHASH_RegionInfo3 = LLMessageStringTable::getInstance()->getString("RegionInfo3");
|
||||
char const* const _PREHASH_RegionInfo4 = LLMessageStringTable::getInstance()->getString("RegionInfo4");
|
||||
char const* const _PREHASH_RegionInfo5 = LLMessageStringTable::getInstance()->getString("RegionInfo5");
|
||||
char const* const _PREHASH_TextColor = LLMessageStringTable::getInstance()->getString("TextColor");
|
||||
char const* const _PREHASH_SlaveID = LLMessageStringTable::getInstance()->getString("SlaveID");
|
||||
char const* const _PREHASH_Charter = LLMessageStringTable::getInstance()->getString("Charter");
|
||||
|
|
|
|||
|
|
@ -281,6 +281,13 @@ extern char const* const _PREHASH_PricePerMeter;
|
|||
extern char const* const _PREHASH_RegionFlags;
|
||||
extern char const* const _PREHASH_RegionFlagsExtended;
|
||||
extern char const* const _PREHASH_RegionProtocols;
|
||||
extern char const* const _PREHASH_ChatWhisperRange;
|
||||
extern char const* const _PREHASH_ChatNormalRange;
|
||||
extern char const* const _PREHASH_ChatShoutRange;
|
||||
extern char const* const _PREHASH_ChatWhisperOffset;
|
||||
extern char const* const _PREHASH_ChatNormalOffset;
|
||||
extern char const* const _PREHASH_ChatShoutOffset;
|
||||
extern char const* const _PREHASH_ChatFlags;
|
||||
extern char const* const _PREHASH_VoteResult;
|
||||
extern char const* const _PREHASH_ParcelDirFeeEstimate;
|
||||
extern char const* const _PREHASH_ModifyBlock;
|
||||
|
|
@ -309,6 +316,7 @@ extern char const* const _PREHASH_DuplicateFlags;
|
|||
extern char const* const _PREHASH_RegionInfo2;
|
||||
extern char const* const _PREHASH_RegionInfo3;
|
||||
extern char const* const _PREHASH_RegionInfo4;
|
||||
extern char const* const _PREHASH_RegionInfo5;
|
||||
extern char const* const _PREHASH_TextColor;
|
||||
extern char const* const _PREHASH_SlaveID;
|
||||
extern char const* const _PREHASH_Charter;
|
||||
|
|
|
|||
|
|
@ -285,11 +285,6 @@ const LLUUID SND_STONE_DIRT_04 ("c8091652-e04b-4a11-84ba-15dba06e7a1b");
|
|||
const LLUUID SND_STONE_STONE_02 ("ba4ef5ac-7435-4240-b826-c24ba8fa5a78");
|
||||
const LLUUID SND_STONE_STONE_04 ("ea296329-0f09-4993-af1b-e6784bab1dc9");
|
||||
|
||||
// NaCl - Antispam Registry. The following sounds will be ignored for purposes of spam protection. They have been gathered from wiki documentation of frequent official sounds.
|
||||
const std::string COLLISION_SOUNDS[] ={"dce5fdd4-afe4-4ea1-822f-dd52cac46b08","51011582-fbca-4580-ae9e-1a5593f094ec","68d62208-e257-4d0c-bbe2-20c9ea9760bb","75872e8c-bc39-451b-9b0b-042d7ba36cba","6a45ba0b-5775-4ea8-8513-26008a17f873","992a6d1b-8c77-40e0-9495-4098ce539694","2de4da5a-faf8-46be-bac6-c4d74f1e5767","6e3fb0f7-6d9c-42ca-b86b-1122ff562d7d","14209133-4961-4acc-9649-53fc38ee1667","bc4a4348-cfcc-4e5e-908e-8a52a8915fe6","9e5c1297-6eed-40c0-825a-d9bcd86e3193","e534761c-1894-4b61-b20c-658a6fb68157","8761f73f-6cf9-4186-8aaa-0948ed002db1","874a26fd-142f-4173-8c5b-890cd846c74d","0e24a717-b97e-4b77-9c94-b59a5a88b2da","75cf3ade-9a5b-4c4d-bb35-f9799bda7fb2","153c8bf7-fb89-4d89-b263-47e58b1b4774","55c3e0ce-275a-46fa-82ff-e0465f5e8703","24babf58-7156-4841-9a3f-761bdbb8e237","aca261d8-e145-4610-9e20-9eff990f2c12","0642fba6-5dcf-4d62-8e7b-94dbb529d117","25a863e8-dc42-4e8a-a357-e76422ace9b5","9538f37c-456e-4047-81be-6435045608d4","8c0f84c3-9afd-4396-b5f5-9bca2c911c20","be582e5d-b123-41a2-a150-454c39e961c8","c70141d4-ba06-41ea-bcbc-35ea81cb8335","7d1826f4-24c4-4aac-8c2e-eff45df37783","063c97d3-033a-4e9b-98d8-05c8074922cb","00000000-0000-0000-0000-000000000120"};
|
||||
const int COLLISION_SOUNDS_SIZE=29;
|
||||
// NaCl End
|
||||
|
||||
|
||||
|
||||
// extra guids
|
||||
|
|
|
|||
|
|
@ -286,9 +286,4 @@ extern const LLUUID SND_STONE_DIRT_04;
|
|||
extern const LLUUID SND_STONE_STONE_02;
|
||||
extern const LLUUID SND_STONE_STONE_04;
|
||||
|
||||
// NaCl - Antispam Registry
|
||||
extern const std::string COLLISION_SOUNDS[];
|
||||
extern const int COLLISION_SOUNDS_SIZE;
|
||||
// NaCl End
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -696,6 +696,66 @@ bool LLPluginClassMedia::textInput(const std::string &text, MASK modifiers, LLSD
|
|||
return true;
|
||||
}
|
||||
|
||||
// This function injects a previously stored OpenID cookie into
|
||||
// each new media instance - see SL-15867 for details. It appears
|
||||
// that the way we use the cache, shared between multiple CEF
|
||||
// instances means that sometimes the OpenID cookie cannot be read
|
||||
// even though it appears to be there. The long term solution to
|
||||
// this is to create a separate cache directory for each instance
|
||||
// but that has its own set of problems. This short term approach
|
||||
// "forces" each new media instance to have a copy of the cookie
|
||||
// so that a page that needs it - e.g. Profiles - finds it and
|
||||
// can log in successfully.
|
||||
void LLPluginClassMedia::injectOpenIDCookie()
|
||||
{
|
||||
// can be called before we know who the user is at login
|
||||
// and there is no OpenID cookie at that point so no
|
||||
// need to try to set it (these values will all be empty)
|
||||
if (sOIDcookieName.length() && sOIDcookieValue.length())
|
||||
{
|
||||
setCookie(sOIDcookieUrl, sOIDcookieName,
|
||||
sOIDcookieValue, sOIDcookieHost, sOIDcookiePath, sOIDcookieHttpOnly, sOIDcookieSecure);
|
||||
}
|
||||
}
|
||||
|
||||
// We store each component of the OpenI cookie individuality here
|
||||
// because previously, there was some significant parsing to
|
||||
// break up the raw string into these components and we do not
|
||||
// want to have to do that again here. Stored as statics because
|
||||
// we want to share their value between all instances of this
|
||||
// class - the ones that receive it at login and any others
|
||||
// that open afterwards (e.g. the Profiles floater)
|
||||
std::string LLPluginClassMedia::sOIDcookieUrl = std::string();
|
||||
std::string LLPluginClassMedia::sOIDcookieName = std::string();
|
||||
std::string LLPluginClassMedia::sOIDcookieValue = std::string();
|
||||
std::string LLPluginClassMedia::sOIDcookieHost = std::string();
|
||||
std::string LLPluginClassMedia::sOIDcookiePath = std::string();
|
||||
bool LLPluginClassMedia::sOIDcookieHttpOnly = false;
|
||||
bool LLPluginClassMedia::sOIDcookieSecure = false;
|
||||
|
||||
// Once we receive the OpenID cookie, it is parsed/processed
|
||||
// in llViewerMedia::parseRawCookie() and then the component
|
||||
// values are stored here so that next time a new media
|
||||
// instance is created, we can use injectOpenIDCookie()
|
||||
// to "insist" that the cookie store remember its value.
|
||||
// One might ask why we need to go via LLViewerMedia (which
|
||||
// makes this call) - this is because the raw cookie arrives
|
||||
// here in this file but undergoes non-trivial processing
|
||||
// in LLViewerMedia.
|
||||
void LLPluginClassMedia::storeOpenIDCookie(const std::string url,
|
||||
const std::string name, const std::string value,
|
||||
const std::string host, const std::string path,
|
||||
bool httponly, bool secure)
|
||||
{
|
||||
sOIDcookieUrl = url;
|
||||
sOIDcookieName = name;
|
||||
sOIDcookieValue = value;
|
||||
sOIDcookieHost = host;
|
||||
sOIDcookiePath = path;
|
||||
sOIDcookieHttpOnly = httponly;
|
||||
sOIDcookieSecure = secure;
|
||||
}
|
||||
|
||||
void LLPluginClassMedia::setCookie(std::string uri, std::string name, std::string value, std::string domain, std::string path, bool httponly, bool secure)
|
||||
{
|
||||
LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "set_cookie");
|
||||
|
|
|
|||
|
|
@ -135,6 +135,20 @@ public:
|
|||
// Text may be unicode (utf8 encoded)
|
||||
bool textInput(const std::string &text, MASK modifiers, LLSD native_key_data);
|
||||
|
||||
static std::string sOIDcookieUrl;
|
||||
static std::string sOIDcookieName;
|
||||
static std::string sOIDcookieValue;
|
||||
static std::string sOIDcookieHost;
|
||||
static std::string sOIDcookiePath;
|
||||
static bool sOIDcookieHttpOnly;
|
||||
static bool sOIDcookieSecure;
|
||||
void storeOpenIDCookie(const std::string url,
|
||||
const std::string name, const std::string value,
|
||||
const std::string host, const std::string path,
|
||||
bool httponly, bool secure);
|
||||
|
||||
void injectOpenIDCookie();
|
||||
|
||||
void setCookie(std::string uri, std::string name, std::string value, std::string domain, std::string path, bool httponly, bool secure);
|
||||
|
||||
void loadURI(const std::string &uri);
|
||||
|
|
|
|||
|
|
@ -559,6 +559,23 @@ LLUUID LLMaterialTable::getCollisionSoundUUID(U8 mcode, U8 mcode2)
|
|||
}
|
||||
}
|
||||
|
||||
bool LLMaterialTable::isCollisionSound(const LLUUID &uuid)
|
||||
{
|
||||
for (U8 i = 0; i < LL_MCODE_END; i++)
|
||||
{
|
||||
for (U8 j = 0; j < LL_MCODE_END; j++)
|
||||
{
|
||||
i &= LL_MCODE_MASK;
|
||||
j &= LL_MCODE_MASK;
|
||||
if (mCollisionSoundMatrix[i * LL_MCODE_END + j] == uuid)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
LLUUID LLMaterialTable::getSlidingSoundUUID(U8 mcode, U8 mcode2)
|
||||
{
|
||||
mcode &= LL_MCODE_MASK;
|
||||
|
|
|
|||
|
|
@ -128,6 +128,8 @@ public:
|
|||
F32 getDamageMod(U8 mcode);
|
||||
F32 getEPMod(U8 mcode);
|
||||
|
||||
bool isCollisionSound(const LLUUID &uuid);
|
||||
|
||||
LLUUID getCollisionSoundUUID(U8 mcode, U8 mcode2);
|
||||
LLUUID getSlidingSoundUUID(U8 mcode, U8 mcode2);
|
||||
LLUUID getRollingSoundUUID(U8 mcode, U8 mcode2);
|
||||
|
|
|
|||
|
|
@ -27,8 +27,7 @@
|
|||
#include "linden_common.h"
|
||||
#include "llmediaentry.h"
|
||||
#include "lllslconstants.h"
|
||||
|
||||
#include <boost/regex.hpp>
|
||||
#include "llregex.h"
|
||||
|
||||
// LLSD key defines
|
||||
// DO NOT REORDER OR REMOVE THESE!
|
||||
|
|
@ -456,7 +455,7 @@ static bool pattern_match(const std::string &candidate_str, const std::string &p
|
|||
|
||||
// case-insensitive matching:
|
||||
boost::regex regexp(expression, boost::regex::perl|boost::regex::icase);
|
||||
return boost::regex_match(candidate_str, regexp);
|
||||
return ll_regex_match(candidate_str, regexp);
|
||||
}
|
||||
|
||||
bool LLMediaEntry::checkCandidateUrl(const std::string& url) const
|
||||
|
|
|
|||
|
|
@ -122,6 +122,35 @@ const char *SCULPT_DEFAULT_TEXTURE = "be293869-d0d9-0a69-5989-ad27f1946fd4"; //
|
|||
// can't be divided by 2. See DEV-19108
|
||||
const F32 TEXTURE_ROTATION_PACK_FACTOR = ((F32) 0x08000);
|
||||
|
||||
struct material_id_type // originally from llrendermaterialtable
|
||||
{
|
||||
material_id_type()
|
||||
{
|
||||
memset((void*)m_value, 0, sizeof(m_value));
|
||||
}
|
||||
|
||||
bool operator==(const material_id_type& other) const
|
||||
{
|
||||
return (memcmp(m_value, other.m_value, sizeof(m_value)) == 0);
|
||||
}
|
||||
|
||||
bool operator!=(const material_id_type& other) const
|
||||
{
|
||||
return !operator==(other);
|
||||
}
|
||||
|
||||
bool isNull() const
|
||||
{
|
||||
return (memcmp(m_value, s_null_id, sizeof(m_value)) == 0);
|
||||
}
|
||||
|
||||
U8 m_value[MATERIAL_ID_SIZE]; // server side this is MD5RAW_BYTES
|
||||
|
||||
static const U8 s_null_id[MATERIAL_ID_SIZE];
|
||||
};
|
||||
|
||||
const U8 material_id_type::s_null_id[] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 };
|
||||
|
||||
//static
|
||||
// LEGACY: by default we use the LLVolumeMgr::gVolumeMgr global
|
||||
// TODO -- eliminate this global from the codebase!
|
||||
|
|
@ -1092,50 +1121,85 @@ S32 LLPrimitive::packTEField(U8 *cur_ptr, U8 *data_ptr, U8 data_size, U8 last_fa
|
|||
return (S32)(cur_ptr - start_loc);
|
||||
}
|
||||
|
||||
S32 LLPrimitive::unpackTEField(U8 *cur_ptr, U8 *buffer_end, U8 *data_ptr, U8 data_size, U8 face_count, EMsgVariableType type)
|
||||
namespace
|
||||
{
|
||||
U8 *start_loc = cur_ptr;
|
||||
U64 i;
|
||||
htolememcpy(data_ptr,cur_ptr, type,data_size);
|
||||
cur_ptr += data_size;
|
||||
template< typename T >
|
||||
bool unpack_TEField(T dest[], U8 dest_count, U8 * &source, U8 *source_end, EMsgVariableType type)
|
||||
{
|
||||
const size_t size(sizeof(T));
|
||||
|
||||
for (i = 1; i < face_count; i++)
|
||||
{
|
||||
// Already unswizzled, don't need to unswizzle it again!
|
||||
memcpy(data_ptr+(i*data_size),data_ptr,data_size); /* Flawfinder: ignore */
|
||||
}
|
||||
|
||||
while ((cur_ptr < buffer_end) && (*cur_ptr != 0))
|
||||
{
|
||||
LL_DEBUGS("TEFieldDecode") << "TE exception" << LL_ENDL;
|
||||
i = 0;
|
||||
while (*cur_ptr & 0x80)
|
||||
{
|
||||
i |= ((*cur_ptr++) & 0x7F);
|
||||
i = i << 7;
|
||||
}
|
||||
LL_DEBUGS("TEXTUREENTRY") << "Request to read items of size " << size << " with swizzle " << type << " froum buffer sized " << (source_end - source) << LL_ENDL;
|
||||
|
||||
i |= *cur_ptr++;
|
||||
if ((source + size + 1) > source_end)
|
||||
{
|
||||
// we add 1 above to take into account the byte that we know must follow the value.
|
||||
LL_WARNS("TEXTUREENTRY") << "Buffer exhausted! Requires " << size << " + 1 bytes for default, " << (source_end - source) << " bytes remaning." << LL_ENDL;
|
||||
source = source_end;
|
||||
return false;
|
||||
}
|
||||
|
||||
for (S32 j = 0; j < face_count; j++)
|
||||
{
|
||||
if (i & 0x01)
|
||||
{
|
||||
htolememcpy(data_ptr+(j*data_size),cur_ptr,type,data_size);
|
||||
LL_DEBUGS("TEFieldDecode") << "Assigning " ;
|
||||
char foo[64];
|
||||
sprintf(foo,"%x %x",*(data_ptr+(j*data_size)), *(data_ptr+(j*data_size)+1));
|
||||
LL_CONT << foo << " to face " << j << LL_ENDL;
|
||||
}
|
||||
i = i >> 1;
|
||||
}
|
||||
cur_ptr += data_size;
|
||||
}
|
||||
llassert(cur_ptr <= buffer_end); // buffer underrun
|
||||
return (S32)(cur_ptr - start_loc);
|
||||
// Extract the default value and fill the array.
|
||||
htolememcpy(dest, source, type, size);
|
||||
source += size;
|
||||
for (S32 idx = 1; idx < dest_count; ++idx)
|
||||
{
|
||||
dest[idx] = dest[0];
|
||||
}
|
||||
|
||||
while (source < source_end)
|
||||
{
|
||||
U64 index_flags(0);
|
||||
U8 sbit(0);
|
||||
|
||||
// Unpack the variable length bitfield. Each bit represents whether the following
|
||||
// value will be placed at the corresponding array index.
|
||||
do
|
||||
{
|
||||
if (source >= source_end)
|
||||
{
|
||||
LL_WARNS("TEXTUREENTRY") << "Buffer exhausted! Reading index flags." << LL_ENDL;
|
||||
source = source_end;
|
||||
return false;
|
||||
}
|
||||
|
||||
sbit = *source++;
|
||||
index_flags <<= 7; // original code had this after?
|
||||
index_flags |= (sbit & 0x7F);
|
||||
} while (sbit & 0x80);
|
||||
|
||||
if (!index_flags)
|
||||
{ // We've hit the terminating 0 byte.
|
||||
break;
|
||||
}
|
||||
|
||||
if ((source + size + 1) > source_end)
|
||||
{
|
||||
// we add 1 above to take into account the byte that we know must follow the value.
|
||||
LL_WARNS("TEXTUREENTRY") << "Buffer exhausted! Requires " << size << " + 1 bytes for default, " << (source_end - source) << " bytes remaning." << LL_ENDL;
|
||||
source = source_end;
|
||||
return false;
|
||||
}
|
||||
|
||||
// get the value for the indexs.
|
||||
T value;
|
||||
htolememcpy(&value, source, type, size);
|
||||
source += size;
|
||||
|
||||
for (S32 idx = 0; idx < dest_count; idx++)
|
||||
{
|
||||
if (index_flags & 1ULL << idx)
|
||||
{
|
||||
dest[idx] = value;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Pack information about all texture entries into container:
|
||||
// { TextureEntry Variable 2 }
|
||||
// Includes information about image ID, color, scale S,T, offset S,T and rotation
|
||||
|
|
@ -1312,9 +1376,9 @@ BOOL LLPrimitive::packTEMessage(LLDataPacker &dp) const
|
|||
S32 LLPrimitive::parseTEMessage(LLMessageSystem* mesgsys, char const* block_name, const S32 block_num, LLTEContents& tec)
|
||||
{
|
||||
S32 retval = 0;
|
||||
// temp buffer for material ID processing
|
||||
// data will end up in tec.material_id[]
|
||||
U8 material_data[LLTEContents::MAX_TES*16];
|
||||
// temp buffer for material ID processing
|
||||
// data will end up in tec.material_id[]
|
||||
material_id_type material_data[LLTEContents::MAX_TES];
|
||||
|
||||
if (block_num < 0)
|
||||
{
|
||||
|
|
@ -1330,54 +1394,49 @@ S32 LLPrimitive::parseTEMessage(LLMessageSystem* mesgsys, char const* block_name
|
|||
tec.face_count = 0;
|
||||
return retval;
|
||||
}
|
||||
else if (tec.size >= LLTEContents::MAX_TE_BUFFER)
|
||||
{
|
||||
LL_WARNS("TEXTUREENTRY") << "Excessive buffer size detected in Texture Entry! Truncating." << LL_ENDL;
|
||||
tec.size = LLTEContents::MAX_TE_BUFFER - 1;
|
||||
}
|
||||
|
||||
if (block_num < 0)
|
||||
{
|
||||
mesgsys->getBinaryDataFast(block_name, _PREHASH_TextureEntry, tec.packed_buffer, 0, 0, LLTEContents::MAX_TE_BUFFER);
|
||||
}
|
||||
else
|
||||
{
|
||||
mesgsys->getBinaryDataFast(block_name, _PREHASH_TextureEntry, tec.packed_buffer, 0, block_num, LLTEContents::MAX_TE_BUFFER);
|
||||
}
|
||||
// if block_num < 0 ask for block 0
|
||||
mesgsys->getBinaryDataFast(block_name, _PREHASH_TextureEntry, tec.packed_buffer, 0, std::max(block_num, 0), LLTEContents::MAX_TE_BUFFER - 1);
|
||||
|
||||
|
||||
// The last field is not zero terminated.
|
||||
// Rather than special case the upack functions. Just make it 0x00 terminated.
|
||||
tec.packed_buffer[tec.size] = 0x00;
|
||||
++tec.size;
|
||||
|
||||
tec.face_count = llmin((U32)getNumTEs(),(U32)LLTEContents::MAX_TES);
|
||||
|
||||
U8 *cur_ptr = tec.packed_buffer;
|
||||
cur_ptr += unpackTEField(cur_ptr, tec.packed_buffer+tec.size, (U8 *)tec.image_data, 16, tec.face_count, MVT_LLUUID);
|
||||
cur_ptr++;
|
||||
cur_ptr += unpackTEField(cur_ptr, tec.packed_buffer+tec.size, (U8 *)tec.colors, 4, tec.face_count, MVT_U8);
|
||||
cur_ptr++;
|
||||
cur_ptr += unpackTEField(cur_ptr, tec.packed_buffer+tec.size, (U8 *)tec.scale_s, 4, tec.face_count, MVT_F32);
|
||||
cur_ptr++;
|
||||
cur_ptr += unpackTEField(cur_ptr, tec.packed_buffer+tec.size, (U8 *)tec.scale_t, 4, tec.face_count, MVT_F32);
|
||||
cur_ptr++;
|
||||
cur_ptr += unpackTEField(cur_ptr, tec.packed_buffer+tec.size, (U8 *)tec.offset_s, 2, tec.face_count, MVT_S16Array);
|
||||
cur_ptr++;
|
||||
cur_ptr += unpackTEField(cur_ptr, tec.packed_buffer+tec.size, (U8 *)tec.offset_t, 2, tec.face_count, MVT_S16Array);
|
||||
cur_ptr++;
|
||||
cur_ptr += unpackTEField(cur_ptr, tec.packed_buffer+tec.size, (U8 *)tec.image_rot, 2, tec.face_count, MVT_S16Array);
|
||||
cur_ptr++;
|
||||
cur_ptr += unpackTEField(cur_ptr, tec.packed_buffer+tec.size, (U8 *)tec.bump, 1, tec.face_count, MVT_U8);
|
||||
cur_ptr++;
|
||||
cur_ptr += unpackTEField(cur_ptr, tec.packed_buffer+tec.size, (U8 *)tec.media_flags, 1, tec.face_count, MVT_U8);
|
||||
cur_ptr++;
|
||||
cur_ptr += unpackTEField(cur_ptr, tec.packed_buffer+tec.size, (U8 *)tec.glow, 1, tec.face_count, MVT_U8);
|
||||
LL_DEBUGS("TEXTUREENTRY") << "Texture Entry with buffere sized: " << tec.size << LL_ENDL;
|
||||
U8 *buffer_end = tec.packed_buffer + tec.size;
|
||||
|
||||
if (cur_ptr < tec.packed_buffer + tec.size)
|
||||
if (!( unpack_TEField<LLUUID>(tec.image_data, tec.face_count, cur_ptr, buffer_end, MVT_LLUUID) &&
|
||||
unpack_TEField<LLColor4U>(tec.colors, tec.face_count, cur_ptr, buffer_end, MVT_U8) &&
|
||||
unpack_TEField<F32>(tec.scale_s, tec.face_count, cur_ptr, buffer_end, MVT_F32) &&
|
||||
unpack_TEField<F32>(tec.scale_t, tec.face_count, cur_ptr, buffer_end, MVT_F32) &&
|
||||
unpack_TEField<S16>(tec.offset_s, tec.face_count, cur_ptr, buffer_end, MVT_S16) &&
|
||||
unpack_TEField<S16>(tec.offset_t, tec.face_count, cur_ptr, buffer_end, MVT_S16) &&
|
||||
unpack_TEField<S16>(tec.image_rot, tec.face_count, cur_ptr, buffer_end, MVT_S16) &&
|
||||
unpack_TEField<U8>(tec.bump, tec.face_count, cur_ptr, buffer_end, MVT_U8) &&
|
||||
unpack_TEField<U8>(tec.media_flags, tec.face_count, cur_ptr, buffer_end, MVT_U8) &&
|
||||
unpack_TEField<U8>(tec.glow, tec.face_count, cur_ptr, buffer_end, MVT_U8)))
|
||||
{
|
||||
LL_WARNS("TEXTUREENTRY") << "Failure parsing Texture Entry Message due to malformed TE Field! Dropping changes on the floor. " << LL_ENDL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (cur_ptr >= buffer_end || !unpack_TEField<material_id_type>(material_data, tec.face_count, cur_ptr, buffer_end, MVT_LLUUID))
|
||||
{
|
||||
cur_ptr++;
|
||||
cur_ptr += unpackTEField(cur_ptr, tec.packed_buffer+tec.size, (U8 *)material_data, 16, tec.face_count, MVT_LLUUID);
|
||||
}
|
||||
else
|
||||
{
|
||||
memset(material_data, 0, sizeof(material_data));
|
||||
memset((void*)material_data, 0, sizeof(material_data));
|
||||
}
|
||||
|
||||
for (U32 i = 0; i < tec.face_count; i++)
|
||||
{
|
||||
tec.material_ids[i].set(&material_data[i * 16]);
|
||||
tec.material_ids[i].set(&(material_data[i]));
|
||||
}
|
||||
|
||||
retval = 1;
|
||||
|
|
@ -1389,7 +1448,6 @@ S32 LLPrimitive::applyParsedTEMessage(LLTEContents& tec)
|
|||
S32 retval = 0;
|
||||
|
||||
LLColor4 color;
|
||||
LLColor4U coloru;
|
||||
for (U32 i = 0; i < tec.face_count; i++)
|
||||
{
|
||||
LLUUID& req_id = ((LLUUID*)tec.image_data)[i];
|
||||
|
|
@ -1402,20 +1460,15 @@ S32 LLPrimitive::applyParsedTEMessage(LLTEContents& tec)
|
|||
retval |= setTEGlow(i, (F32)tec.glow[i] / (F32)0xFF);
|
||||
retval |= setTEMaterialID(i, tec.material_ids[i]);
|
||||
|
||||
coloru = LLColor4U(tec.colors + 4*i);
|
||||
|
||||
// Note: This is an optimization to send common colors (1.f, 1.f, 1.f, 1.f)
|
||||
// as all zeros. However, the subtraction and addition must be done in unsigned
|
||||
// byte space, not in float space, otherwise off-by-one errors occur. JC
|
||||
color.mV[VRED] = F32(255 - coloru.mV[VRED]) / 255.f;
|
||||
color.mV[VGREEN] = F32(255 - coloru.mV[VGREEN]) / 255.f;
|
||||
color.mV[VBLUE] = F32(255 - coloru.mV[VBLUE]) / 255.f;
|
||||
color.mV[VALPHA] = F32(255 - coloru.mV[VALPHA]) / 255.f;
|
||||
color.mV[VRED] = F32(255 - tec.colors[i].mV[VRED]) / 255.f;
|
||||
color.mV[VGREEN] = F32(255 - tec.colors[i].mV[VGREEN]) / 255.f;
|
||||
color.mV[VBLUE] = F32(255 - tec.colors[i].mV[VBLUE]) / 255.f;
|
||||
color.mV[VALPHA] = F32(255 - tec.colors[i].mV[VALPHA]) / 255.f;
|
||||
|
||||
retval |= setTEColor(i, color);
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
return retval;
|
||||
|
|
@ -1437,24 +1490,32 @@ S32 LLPrimitive::unpackTEMessage(LLDataPacker &dp)
|
|||
const U32 MAX_TES = 45;
|
||||
|
||||
// Avoid construction of 32 UUIDs per call
|
||||
static LLUUID image_ids[MAX_TES];
|
||||
static LLMaterialID material_ids[MAX_TES];
|
||||
|
||||
U8 image_data[MAX_TES*16];
|
||||
U8 colors[MAX_TES*4];
|
||||
F32 scale_s[MAX_TES];
|
||||
F32 scale_t[MAX_TES];
|
||||
S16 offset_s[MAX_TES];
|
||||
S16 offset_t[MAX_TES];
|
||||
S16 image_rot[MAX_TES];
|
||||
U8 bump[MAX_TES];
|
||||
U8 media_flags[MAX_TES];
|
||||
U8 glow[MAX_TES];
|
||||
U8 material_data[MAX_TES*16];
|
||||
const U32 MAX_TE_BUFFER = 4096;
|
||||
U8 packed_buffer[MAX_TE_BUFFER];
|
||||
memset((void*)packed_buffer, 0, MAX_TE_BUFFER);
|
||||
|
||||
const U32 MAX_TE_BUFFER = 4096;
|
||||
U8 packed_buffer[MAX_TE_BUFFER];
|
||||
U8 *cur_ptr = packed_buffer;
|
||||
LLUUID image_data[MAX_TES];
|
||||
LLColor4U colors[MAX_TES];
|
||||
F32 scale_s[MAX_TES];
|
||||
F32 scale_t[MAX_TES];
|
||||
S16 offset_s[MAX_TES];
|
||||
S16 offset_t[MAX_TES];
|
||||
S16 image_rot[MAX_TES];
|
||||
U8 bump[MAX_TES];
|
||||
U8 media_flags[MAX_TES];
|
||||
U8 glow[MAX_TES];
|
||||
material_id_type material_data[MAX_TES];
|
||||
|
||||
memset((void*)scale_s, 0, sizeof(scale_s));
|
||||
memset((void*)scale_t, 0, sizeof(scale_t));
|
||||
memset((void*)offset_s, 0, sizeof(offset_s));
|
||||
memset((void*)offset_t, 0, sizeof(offset_t));
|
||||
memset((void*)image_rot, 0, sizeof(image_rot));
|
||||
memset((void*)bump, 0, sizeof(bump));
|
||||
memset((void*)media_flags, 0, sizeof(media_flags));
|
||||
memset((void*)glow, 0, sizeof(glow));
|
||||
|
||||
S32 size;
|
||||
U32 face_count = 0;
|
||||
|
|
@ -1470,50 +1531,52 @@ S32 LLPrimitive::unpackTEMessage(LLDataPacker &dp)
|
|||
{
|
||||
return retval;
|
||||
}
|
||||
else if (size >= MAX_TE_BUFFER)
|
||||
{
|
||||
LL_WARNS("TEXTUREENTRY") << "Excessive buffer size detected in Texture Entry! Truncating." << LL_ENDL;
|
||||
size = MAX_TE_BUFFER - 1;
|
||||
}
|
||||
|
||||
// The last field is not zero terminated.
|
||||
// Rather than special case the upack functions. Just make it 0x00 terminated.
|
||||
packed_buffer[size] = 0x00;
|
||||
++size;
|
||||
face_count = llmin((U32) getNumTEs(), MAX_TES);
|
||||
U32 i;
|
||||
|
||||
cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)image_data, 16, face_count, MVT_LLUUID);
|
||||
cur_ptr++;
|
||||
cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)colors, 4, face_count, MVT_U8);
|
||||
cur_ptr++;
|
||||
cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)scale_s, 4, face_count, MVT_F32);
|
||||
cur_ptr++;
|
||||
cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)scale_t, 4, face_count, MVT_F32);
|
||||
cur_ptr++;
|
||||
cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)offset_s, 2, face_count, MVT_S16Array);
|
||||
cur_ptr++;
|
||||
cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)offset_t, 2, face_count, MVT_S16Array);
|
||||
cur_ptr++;
|
||||
cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)image_rot, 2, face_count, MVT_S16Array);
|
||||
cur_ptr++;
|
||||
cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)bump, 1, face_count, MVT_U8);
|
||||
cur_ptr++;
|
||||
cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)media_flags, 1, face_count, MVT_U8);
|
||||
cur_ptr++;
|
||||
cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)glow, 1, face_count, MVT_U8);
|
||||
if (cur_ptr < packed_buffer + size)
|
||||
U8 *cur_ptr = packed_buffer;
|
||||
LL_DEBUGS("TEXTUREENTRY") << "Texture Entry with buffer sized: " << size << LL_ENDL;
|
||||
U8 *buffer_end = packed_buffer + size;
|
||||
|
||||
if (!( unpack_TEField<LLUUID>(image_data, face_count, cur_ptr, buffer_end, MVT_LLUUID) &&
|
||||
unpack_TEField<LLColor4U>(colors, face_count, cur_ptr, buffer_end, MVT_U8) &&
|
||||
unpack_TEField<F32>(scale_s, face_count, cur_ptr, buffer_end, MVT_F32) &&
|
||||
unpack_TEField<F32>(scale_t, face_count, cur_ptr, buffer_end, MVT_F32) &&
|
||||
unpack_TEField<S16>(offset_s, face_count, cur_ptr, buffer_end, MVT_S16) &&
|
||||
unpack_TEField<S16>(offset_t, face_count, cur_ptr, buffer_end, MVT_S16) &&
|
||||
unpack_TEField<S16>(image_rot, face_count, cur_ptr, buffer_end, MVT_S16) &&
|
||||
unpack_TEField<U8>(bump, face_count, cur_ptr, buffer_end, MVT_U8) &&
|
||||
unpack_TEField<U8>(media_flags, face_count, cur_ptr, buffer_end, MVT_U8) &&
|
||||
unpack_TEField<U8>(glow, face_count, cur_ptr, buffer_end, MVT_U8)))
|
||||
{
|
||||
LL_WARNS("TEXTUREENTRY") << "Failure parsing Texture Entry Message due to malformed TE Field! Dropping changes on the floor. " << LL_ENDL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (cur_ptr >= buffer_end || !unpack_TEField<material_id_type>(material_data, face_count, cur_ptr, buffer_end, MVT_LLUUID))
|
||||
{
|
||||
cur_ptr++;
|
||||
cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)material_data, 16, face_count, MVT_LLUUID);
|
||||
}
|
||||
else
|
||||
{
|
||||
memset(material_data, 0, sizeof(material_data));
|
||||
memset((void*)material_data, 0, sizeof(material_data));
|
||||
}
|
||||
|
||||
for (i = 0; i < face_count; i++)
|
||||
{
|
||||
memcpy( image_ids[ i ].mData, &image_data[ i*UUID_BYTES ], UUID_BYTES ); /* Flawfinder: ignore */
|
||||
material_ids[ i ].set( &material_data[ i * UUID_BYTES ] );
|
||||
material_ids[i].set(&(material_data[i]));
|
||||
}
|
||||
|
||||
LLColor4 color;
|
||||
LLColor4U coloru;
|
||||
for (i = 0; i < face_count; i++)
|
||||
{
|
||||
retval |= setTETexture(i, image_ids[i]);
|
||||
retval |= setTETexture(i, ((LLUUID*)image_data)[i]);
|
||||
retval |= setTEScale(i, scale_s[i], scale_t[i]);
|
||||
retval |= setTEOffset(i, (F32)offset_s[i] / (F32)0x7FFF, (F32) offset_t[i] / (F32) 0x7FFF);
|
||||
retval |= setTERotation(i, ((F32)image_rot[i] / TEXTURE_ROTATION_PACK_FACTOR) * F_TWO_PI);
|
||||
|
|
@ -1521,15 +1584,14 @@ S32 LLPrimitive::unpackTEMessage(LLDataPacker &dp)
|
|||
retval |= setTEMediaTexGen(i, media_flags[i]);
|
||||
retval |= setTEGlow(i, (F32)glow[i] / (F32)0xFF);
|
||||
retval |= setTEMaterialID(i, material_ids[i]);
|
||||
coloru = LLColor4U(colors + 4*i);
|
||||
|
||||
// Note: This is an optimization to send common colors (1.f, 1.f, 1.f, 1.f)
|
||||
// as all zeros. However, the subtraction and addition must be done in unsigned
|
||||
// byte space, not in float space, otherwise off-by-one errors occur. JC
|
||||
color.mV[VRED] = F32(255 - coloru.mV[VRED]) / 255.f;
|
||||
color.mV[VGREEN] = F32(255 - coloru.mV[VGREEN]) / 255.f;
|
||||
color.mV[VBLUE] = F32(255 - coloru.mV[VBLUE]) / 255.f;
|
||||
color.mV[VALPHA] = F32(255 - coloru.mV[VALPHA]) / 255.f;
|
||||
color.mV[VRED] = F32(255 - colors[i].mV[VRED]) / 255.f;
|
||||
color.mV[VGREEN] = F32(255 - colors[i].mV[VGREEN]) / 255.f;
|
||||
color.mV[VBLUE] = F32(255 - colors[i].mV[VBLUE]) / 255.f;
|
||||
color.mV[VALPHA] = F32(255 - colors[i].mV[VALPHA]) / 255.f;
|
||||
|
||||
retval |= setTEColor(i, color);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -338,8 +338,8 @@ struct LLTEContents
|
|||
{
|
||||
static const U32 MAX_TES = 45;
|
||||
|
||||
U8 image_data[MAX_TES*16];
|
||||
U8 colors[MAX_TES*4];
|
||||
LLUUID image_data[MAX_TES];
|
||||
LLColor4U colors[MAX_TES];
|
||||
F32 scale_s[MAX_TES];
|
||||
F32 scale_t[MAX_TES];
|
||||
S16 offset_s[MAX_TES];
|
||||
|
|
@ -432,7 +432,6 @@ public:
|
|||
|
||||
void copyTEs(const LLPrimitive *primitive);
|
||||
S32 packTEField(U8 *cur_ptr, U8 *data_ptr, U8 data_size, U8 last_face_index, EMsgVariableType type) const;
|
||||
S32 unpackTEField(U8 *cur_ptr, U8 *buffer_end, U8 *data_ptr, U8 data_size, U8 face_count, EMsgVariableType type);
|
||||
BOOL packTEMessage(LLMessageSystem *mesgsys) const;
|
||||
BOOL packTEMessage(LLDataPacker &dp) const;
|
||||
S32 unpackTEMessage(LLMessageSystem* mesgsys, char const* block_name, const S32 block_num); // Variable num of blocks
|
||||
|
|
|
|||
|
|
@ -1065,6 +1065,43 @@ void LLComboBox::prearrangeList(std::string filter)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
// ll::ui::SearchableControl functions
|
||||
|
||||
//virtual
|
||||
std::string LLComboBox::_getSearchText() const
|
||||
{
|
||||
std::string res;
|
||||
if (mList)
|
||||
{
|
||||
// getAllData returns a full copy of content, might be a
|
||||
// better option to implement an mList->getSearchText(column)
|
||||
std::vector<LLScrollListItem*> data = mList->getAllData();
|
||||
std::vector<LLScrollListItem*>::iterator iter = data.begin();
|
||||
while (iter != data.end())
|
||||
{
|
||||
LLScrollListCell* cell = (*iter)->getColumn(0);
|
||||
if (cell)
|
||||
{
|
||||
std::string whitelist_url = cell->getValue().asString();
|
||||
res += cell->getValue().asString();
|
||||
}
|
||||
iter++;
|
||||
}
|
||||
}
|
||||
return res + getToolTip();
|
||||
}
|
||||
|
||||
//virtual
|
||||
void LLComboBox::onSetHighlight() const
|
||||
{
|
||||
if (mButton)
|
||||
{
|
||||
mButton->ll::ui::SearchableControl::setHighlighted(ll::ui::SearchableControl::getHighlighted());
|
||||
}
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
// LLCtrlListInterface functions
|
||||
|
||||
|
|
|
|||
|
|
@ -44,7 +44,9 @@ class LLFontGL;
|
|||
class LLViewBorder;
|
||||
|
||||
class LLComboBox
|
||||
: public LLUICtrl, public LLCtrlListInterface
|
||||
: public LLUICtrl
|
||||
, public LLCtrlListInterface
|
||||
, public ll::ui::SearchableControl
|
||||
{
|
||||
public:
|
||||
typedef enum e_preferred_position
|
||||
|
|
@ -101,6 +103,9 @@ protected:
|
|||
void initFromParams(const Params&);
|
||||
void prearrangeList(std::string filter = "");
|
||||
|
||||
virtual std::string _getSearchText() const;
|
||||
virtual void onSetHighlight() const;
|
||||
|
||||
public:
|
||||
// LLView interface
|
||||
virtual void onFocusLost();
|
||||
|
|
|
|||
|
|
@ -84,7 +84,6 @@
|
|||
#include <sstream>
|
||||
|
||||
#include <boost/utility.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/type_traits.hpp>
|
||||
#include <boost/signals2.hpp>
|
||||
#include <boost/range.hpp>
|
||||
|
|
@ -132,7 +131,7 @@ public:
|
|||
|
||||
typedef boost::function<void (const LLSD&, const LLSD&)> LLNotificationResponder;
|
||||
|
||||
typedef boost::shared_ptr<LLNotificationResponderInterface> LLNotificationResponderPtr;
|
||||
typedef std::shared_ptr<LLNotificationResponderInterface> LLNotificationResponderPtr;
|
||||
|
||||
typedef LLFunctorRegistry<LLNotificationResponder> LLNotificationFunctorRegistry;
|
||||
typedef LLFunctorRegistration<LLNotificationResponder> LLNotificationFunctorRegistration;
|
||||
|
|
@ -278,19 +277,19 @@ private:
|
|||
bool mInvertSetting;
|
||||
};
|
||||
|
||||
typedef boost::shared_ptr<LLNotificationForm> LLNotificationFormPtr;
|
||||
typedef std::shared_ptr<LLNotificationForm> LLNotificationFormPtr;
|
||||
|
||||
|
||||
struct LLNotificationTemplate;
|
||||
|
||||
// we want to keep a map of these by name, and it's best to manage them
|
||||
// with smart pointers
|
||||
typedef boost::shared_ptr<LLNotificationTemplate> LLNotificationTemplatePtr;
|
||||
typedef std::shared_ptr<LLNotificationTemplate> LLNotificationTemplatePtr;
|
||||
|
||||
|
||||
struct LLNotificationVisibilityRule;
|
||||
|
||||
typedef boost::shared_ptr<LLNotificationVisibilityRule> LLNotificationVisibilityRulePtr;
|
||||
typedef std::shared_ptr<LLNotificationVisibilityRule> LLNotificationVisibilityRulePtr;
|
||||
|
||||
/**
|
||||
* @class LLNotification
|
||||
|
|
@ -764,6 +763,10 @@ public:
|
|||
{}
|
||||
virtual ~LLNotificationChannelBase()
|
||||
{
|
||||
// explicit cleanup for easier issue detection
|
||||
mChanged.disconnect_all_slots();
|
||||
mPassedFilter.disconnect_all_slots();
|
||||
mFailedFilter.disconnect_all_slots();
|
||||
mItems.clear();
|
||||
}
|
||||
// you can also connect to a Channel, so you can be notified of
|
||||
|
|
|
|||
|
|
@ -31,7 +31,6 @@
|
|||
|
||||
#include "lleventapi.h"
|
||||
#include "llnotificationptr.h"
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
|
|
@ -61,7 +60,7 @@ private:
|
|||
static LLSD asLLSD(LLNotificationPtr);
|
||||
|
||||
class Forwarder;
|
||||
typedef std::map<std::string, boost::shared_ptr<Forwarder> > ForwarderMap;
|
||||
typedef std::map<std::string, std::shared_ptr<Forwarder> > ForwarderMap;
|
||||
ForwarderMap mForwarders;
|
||||
LLNotifications & mNotifications;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@
|
|||
#include "llinitparam.h"
|
||||
#include "llnotifications.h"
|
||||
|
||||
typedef boost::shared_ptr<LLNotificationForm> LLNotificationFormPtr;
|
||||
typedef std::shared_ptr<LLNotificationForm> LLNotificationFormPtr;
|
||||
|
||||
// This is the class of object read from the XML file (notifications.xml,
|
||||
// from the appropriate local language directory).
|
||||
|
|
|
|||
|
|
@ -54,6 +54,10 @@ LLScrollListCell* LLScrollListCell::create(const LLScrollListCell::Params& cell_
|
|||
{
|
||||
cell = new LLScrollListIconText(cell_p);
|
||||
}
|
||||
else if (cell_p.type() == "bar")
|
||||
{
|
||||
cell = new LLScrollListBar(cell_p);
|
||||
}
|
||||
else // default is "text"
|
||||
{
|
||||
cell = new LLScrollListText(cell_p);
|
||||
|
|
@ -165,6 +169,74 @@ void LLScrollListIcon::draw(const LLColor4& color, const LLColor4& highlight_col
|
|||
}
|
||||
}
|
||||
|
||||
//
|
||||
// LLScrollListBar
|
||||
//
|
||||
LLScrollListBar::LLScrollListBar(const LLScrollListCell::Params& p)
|
||||
: LLScrollListCell(p),
|
||||
mRatio(0),
|
||||
mColor(p.color),
|
||||
mBottom(1),
|
||||
mLeftPad(1),
|
||||
mRightPad(1)
|
||||
{}
|
||||
|
||||
LLScrollListBar::~LLScrollListBar()
|
||||
{
|
||||
}
|
||||
|
||||
/*virtual*/
|
||||
S32 LLScrollListBar::getHeight() const
|
||||
{
|
||||
return LLScrollListCell::getHeight();
|
||||
}
|
||||
|
||||
/*virtual*/
|
||||
const LLSD LLScrollListBar::getValue() const
|
||||
{
|
||||
return LLStringUtil::null;
|
||||
}
|
||||
|
||||
void LLScrollListBar::setValue(const LLSD& value)
|
||||
{
|
||||
if (value.has("ratio"))
|
||||
{
|
||||
mRatio = value["ratio"].asReal();
|
||||
}
|
||||
if (value.has("bottom"))
|
||||
{
|
||||
mBottom = value["bottom"].asInteger();
|
||||
}
|
||||
if (value.has("left_pad"))
|
||||
{
|
||||
mLeftPad = value["left_pad"].asInteger();
|
||||
}
|
||||
if (value.has("right_pad"))
|
||||
{
|
||||
mRightPad = value["right_pad"].asInteger();
|
||||
}
|
||||
}
|
||||
|
||||
void LLScrollListBar::setColor(const LLColor4& color)
|
||||
{
|
||||
mColor = color;
|
||||
}
|
||||
|
||||
S32 LLScrollListBar::getWidth() const
|
||||
{
|
||||
return LLScrollListCell::getWidth();
|
||||
}
|
||||
|
||||
|
||||
void LLScrollListBar::draw(const LLColor4& color, const LLColor4& highlight_color) const
|
||||
{
|
||||
S32 bar_width = getWidth() - mLeftPad - mRightPad;
|
||||
S32 left = bar_width - bar_width * mRatio;
|
||||
left = llclamp(left, mLeftPad, getWidth() - mRightPad - 1);
|
||||
|
||||
gl_rect_2d(left, mBottom, getWidth() - mRightPad, mBottom - 1, mColor);
|
||||
}
|
||||
|
||||
//
|
||||
// LLScrollListText
|
||||
//
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@
|
|||
#include "lluistring.h"
|
||||
#include "v4color.h"
|
||||
#include "llui.h"
|
||||
#include "llgltexture.h"
|
||||
|
||||
class LLCheckBoxCtrl;
|
||||
class LLSD;
|
||||
|
|
@ -153,6 +154,7 @@ public:
|
|||
|
||||
void setText(const LLStringExplicit& text);
|
||||
void setFontStyle(const U8 font_style);
|
||||
void setAlignment(LLFontGL::HAlign align) { mFontAlignment = align; }
|
||||
|
||||
protected:
|
||||
LLUIString mText;
|
||||
|
|
@ -192,6 +194,26 @@ private:
|
|||
LLFontGL::HAlign mAlignment;
|
||||
};
|
||||
|
||||
|
||||
class LLScrollListBar : public LLScrollListCell
|
||||
{
|
||||
public:
|
||||
LLScrollListBar(const LLScrollListCell::Params& p);
|
||||
/*virtual*/ ~LLScrollListBar();
|
||||
/*virtual*/ void draw(const LLColor4& color, const LLColor4& highlight_color) const;
|
||||
/*virtual*/ S32 getWidth() const;
|
||||
/*virtual*/ S32 getHeight() const;
|
||||
/*virtual*/ const LLSD getValue() const;
|
||||
/*virtual*/ void setColor(const LLColor4&);
|
||||
/*virtual*/ void setValue(const LLSD& value);
|
||||
|
||||
private:
|
||||
LLColor4 mColor;
|
||||
F32 mRatio;
|
||||
S32 mBottom;
|
||||
S32 mRightPad;
|
||||
S32 mLeftPad;
|
||||
};
|
||||
/*
|
||||
* An interactive cell containing a check box.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -206,6 +206,7 @@ LLTextBase::LLTextBase(const LLTextBase::Params &p)
|
|||
mFontShadow(p.font_shadow),
|
||||
mPopupMenuHandle(),
|
||||
mReadOnly(p.read_only),
|
||||
mSkipTripleClick(false),
|
||||
mSkipLinkUnderline(p.skip_link_underline),
|
||||
mSpellCheck(p.spellcheck),
|
||||
mSpellCheckStart(-1),
|
||||
|
|
@ -1092,6 +1093,11 @@ BOOL LLTextBase::handleMouseDown(S32 x, S32 y, MASK mask)
|
|||
// handle triple click
|
||||
if (!mTripleClickTimer.hasExpired())
|
||||
{
|
||||
if (mSkipTripleClick)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
S32 real_line = getLineNumFromDocIndex(mCursorPos, false);
|
||||
S32 line_start = -1;
|
||||
S32 line_end = -1;
|
||||
|
|
|
|||
|
|
@ -761,7 +761,7 @@ protected:
|
|||
bool mPlainText; // didn't use Image or Icon segments
|
||||
bool mAutoIndent;
|
||||
S32 mMaxTextByteLength; // Maximum length mText is allowed to be in bytes
|
||||
|
||||
bool mSkipTripleClick;
|
||||
bool mSkipLinkUnderline;
|
||||
|
||||
// support widgets
|
||||
|
|
|
|||
|
|
@ -45,7 +45,9 @@ LLTextBox::LLTextBox(const LLTextBox::Params& p)
|
|||
: LLTextBase(p),
|
||||
mClickedCallback(NULL),
|
||||
mShowCursorHand(true)
|
||||
{}
|
||||
{
|
||||
mSkipTripleClick = true;
|
||||
}
|
||||
|
||||
LLTextBox::~LLTextBox()
|
||||
{}
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@
|
|||
|
||||
#include "llavatarnamecache.h"
|
||||
#include "llcachename.h"
|
||||
#include "llregex.h"
|
||||
#include "lltrans.h"
|
||||
#include "lluicolortable.h"
|
||||
#include "message.h"
|
||||
|
|
@ -184,11 +185,51 @@ bool LLUrlEntryBase::isLinkDisabled() const
|
|||
return globally_disabled;
|
||||
}
|
||||
|
||||
bool LLUrlEntryBase::isWikiLinkCorrect(std::string url)
|
||||
bool LLUrlEntryBase::isWikiLinkCorrect(const std::string &labeled_url) const
|
||||
{
|
||||
LLWString label = utf8str_to_wstring(getLabelFromWikiLink(url));
|
||||
label.erase(std::remove(label.begin(), label.end(), L'\u200B'), label.end());
|
||||
return (LLUrlRegistry::instance().hasUrl(wstring_to_utf8str(label))) ? false : true;
|
||||
LLWString wlabel = utf8str_to_wstring(getLabelFromWikiLink(labeled_url));
|
||||
wlabel.erase(std::remove(wlabel.begin(), wlabel.end(), L'\u200B'), wlabel.end());
|
||||
|
||||
// Unicode URL validation, see SL-15243
|
||||
std::replace_if(wlabel.begin(),
|
||||
wlabel.end(),
|
||||
[](const llwchar &chr)
|
||||
{
|
||||
return (chr == L'\u2024') // "One Dot Leader"
|
||||
|| (chr == L'\uFE52') // "Small Full Stop"
|
||||
|| (chr == L'\uFF0E') // "Fullwidth Full Stop"
|
||||
// Not a decomposition, but suficiently similar
|
||||
|| (chr == L'\u05C5'); // "Hebrew Mark Lower Dot"
|
||||
},
|
||||
L'\u002E'); // Dot "Full Stop"
|
||||
|
||||
std::replace_if(wlabel.begin(),
|
||||
wlabel.end(),
|
||||
[](const llwchar &chr)
|
||||
{
|
||||
return (chr == L'\u02D0') // "Modifier Letter Colon"
|
||||
|| (chr == L'\uFF1A') // "Fullwidth Colon"
|
||||
|| (chr == L'\uFE55'); // "Small Colon"
|
||||
},
|
||||
L'\u003A'); // Colon
|
||||
|
||||
std::replace_if(wlabel.begin(),
|
||||
wlabel.end(),
|
||||
[](const llwchar &chr)
|
||||
{
|
||||
return (chr == L'\uFF0F'); // "Fullwidth Solidus"
|
||||
},
|
||||
L'\u002F'); // Solidus
|
||||
|
||||
std::string label = wstring_to_utf8str(wlabel);
|
||||
if ((label.find(".com") != std::string::npos
|
||||
|| label.find("www.") != std::string::npos)
|
||||
&& label.find("://") == std::string::npos)
|
||||
{
|
||||
label = "http://" + label;
|
||||
}
|
||||
|
||||
return (LLUrlRegistry::instance().hasUrl(label)) ? false : true;
|
||||
}
|
||||
|
||||
std::string LLUrlEntryBase::urlToLabelWithGreyQuery(const std::string &url) const
|
||||
|
|
@ -1603,7 +1644,7 @@ std::string LLUrlEntryIcon::getIcon(const std::string &url)
|
|||
// Grep icon info between <icon>...</icon> tags
|
||||
// matches[1] contains the icon name/path
|
||||
boost::match_results<std::string::const_iterator> matches;
|
||||
mIcon = (boost::regex_match(url, matches, mPattern) && matches[1].matched)
|
||||
mIcon = (ll_regex_match(url, matches, mPattern) && matches[1].matched)
|
||||
? matches[1]
|
||||
: LLStringUtil::null;
|
||||
LLStringUtil::trim(mIcon);
|
||||
|
|
|
|||
|
|
@ -105,7 +105,7 @@ public:
|
|||
|
||||
bool isLinkDisabled() const;
|
||||
|
||||
bool isWikiLinkCorrect(std::string url);
|
||||
bool isWikiLinkCorrect(const std::string &url) const;
|
||||
|
||||
virtual bool isSLURLvalid(const std::string &url) const { return TRUE; };
|
||||
|
||||
|
|
|
|||
|
|
@ -26,10 +26,10 @@
|
|||
*/
|
||||
|
||||
#include "linden_common.h"
|
||||
#include "llregex.h"
|
||||
#include "llurlregistry.h"
|
||||
#include "lluriparser.h"
|
||||
|
||||
#include <boost/regex.hpp>
|
||||
#include <boost/algorithm/string/find.hpp> //for boost::ifind_first -KC
|
||||
|
||||
// default dummy callback that ignores any label updates from the server
|
||||
|
|
@ -127,15 +127,7 @@ static bool matchRegex(const char *text, boost::regex regex, U32 &start, U32 &en
|
|||
boost::cmatch result;
|
||||
bool found;
|
||||
|
||||
// regex_search can potentially throw an exception, so check for it
|
||||
try
|
||||
{
|
||||
found = boost::regex_search(text, result, regex);
|
||||
}
|
||||
catch (std::runtime_error &)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
found = ll_regex_search(text, result, regex);
|
||||
|
||||
if (! found)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@
|
|||
LLNonInlineTextView *inputView;
|
||||
NSTimer *frameTimer;
|
||||
NSString *currentInputLanguage;
|
||||
std::string secondLogPath;
|
||||
}
|
||||
|
||||
@property (assign) IBOutlet LLNSWindow *window;
|
||||
|
|
|
|||
|
|
@ -504,7 +504,8 @@ attributedStringInfo getSegments(NSAttributedString *str)
|
|||
// e.g. OS Window for upload something or Input Window...
|
||||
// mModifiers instance variable is for insertText: or insertText:replacementRange: (by Pell Smit)
|
||||
mModifiers = [theEvent modifierFlags];
|
||||
bool acceptsText = mHasMarkedText ? false : callKeyDown(&eventData, keycode, mModifiers);
|
||||
|
||||
bool acceptsText = mHasMarkedText ? false : callKeyDown(&eventData, keycode, mModifiers, [[theEvent characters] characterAtIndex:0]);
|
||||
unichar ch;
|
||||
if (acceptsText &&
|
||||
!mMarkedTextAllowed &&
|
||||
|
|
@ -547,7 +548,7 @@ attributedStringInfo getSegments(NSAttributedString *str)
|
|||
if (mModifiers & mask)
|
||||
{
|
||||
eventData.mKeyEvent = NativeKeyEventData::KEYDOWN;
|
||||
callKeyDown(&eventData, [theEvent keyCode], 0);
|
||||
callKeyDown(&eventData, [theEvent keyCode], 0, [[theEvent characters] characterAtIndex:0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
|
|
@ -132,7 +132,7 @@ void setupInputWindow(NSWindowRef window, GLViewRef view);
|
|||
// These are all implemented in llwindowmacosx.cpp.
|
||||
// This is largely for easier interop between Obj-C and C++ (at least in the viewer's case due to the BOOL vs. BOOL conflict)
|
||||
bool callKeyUp(NSKeyEventRef event, unsigned short key, unsigned int mask);
|
||||
bool callKeyDown(NSKeyEventRef event, unsigned short key, unsigned int mask);
|
||||
bool callKeyDown(NSKeyEventRef event, unsigned short key, unsigned int mask, wchar_t character);
|
||||
void callResetKeys();
|
||||
bool callUnicodeCallback(wchar_t character, unsigned int mask);
|
||||
void callRightMouseDown(float *pos, unsigned int mask);
|
||||
|
|
|
|||
|
|
@ -217,8 +217,17 @@ bool callKeyUp(NSKeyEventRef event, unsigned short key, unsigned int mask)
|
|||
return retVal;
|
||||
}
|
||||
|
||||
bool callKeyDown(NSKeyEventRef event, unsigned short key, unsigned int mask)
|
||||
bool callKeyDown(NSKeyEventRef event, unsigned short key, unsigned int mask, wchar_t character)
|
||||
{
|
||||
if((key == gKeyboard->inverseTranslateKey('Z')) && (character == 'y'))
|
||||
{
|
||||
key = gKeyboard->inverseTranslateKey('Y');
|
||||
}
|
||||
else if ((key == gKeyboard->inverseTranslateKey('Y')) && (character == 'z'))
|
||||
{
|
||||
key = gKeyboard->inverseTranslateKey('Z');
|
||||
}
|
||||
|
||||
mRawKeyEvent = event;
|
||||
bool retVal = gKeyboard->handleKeyDown(key, mask);
|
||||
mRawKeyEvent = NULL;
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ project(media_plugin_cef)
|
|||
include(Boost)
|
||||
include(00-Common)
|
||||
include(LLCommon)
|
||||
include(LLImage)
|
||||
include(LLPlugin)
|
||||
include(LLMath)
|
||||
include(LLRender)
|
||||
|
|
@ -13,7 +12,6 @@ include(LLWindow)
|
|||
include(Linking)
|
||||
include(PluginAPI)
|
||||
include(MediaPluginBase)
|
||||
include(OpenGL)
|
||||
|
||||
include(CEFPlugin)
|
||||
|
||||
|
|
@ -22,7 +20,6 @@ include_directories(
|
|||
${MEDIA_PLUGIN_BASE_INCLUDE_DIRS}
|
||||
${LLCOMMON_INCLUDE_DIRS}
|
||||
${LLMATH_INCLUDE_DIRS}
|
||||
${LLIMAGE_INCLUDE_DIRS}
|
||||
${LLRENDER_INCLUDE_DIRS}
|
||||
${LLWINDOW_INCLUDE_DIRS}
|
||||
${CEF_INCLUDE_DIR}
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@
|
|||
#include "linden_common.h"
|
||||
#include "indra_constants.h" // for indra keyboard codes
|
||||
|
||||
#include "llgl.h"
|
||||
#include "llglheaders.h" // for GL_* constants
|
||||
#include "llsdutil.h"
|
||||
#include "llplugininstance.h"
|
||||
#include "llpluginmessage.h"
|
||||
|
|
@ -37,9 +37,6 @@
|
|||
#include "volume_catcher.h"
|
||||
#include "media_plugin_base.h"
|
||||
|
||||
#include <functional>
|
||||
#include <chrono>
|
||||
|
||||
#include "dullahan.h"
|
||||
#include "dullahan_version.h"
|
||||
|
||||
|
|
|
|||
|
|
@ -283,35 +283,16 @@ void MediaPluginLibVLC::playMedia()
|
|||
return;
|
||||
}
|
||||
|
||||
// A new call to play the media is received after the initial one. Typically
|
||||
// this is due to a size change request either as the media naturally resizes
|
||||
// to the size of the prim container, or else, as a 2D window is resized by the
|
||||
// user. Stopping the media, helps avoid a race condition where the media pixel
|
||||
// buffer size is out of sync with the declared size (width/height) for a frame
|
||||
// or two and the plugin crashes as VLC tries to decode a frame into unallocated
|
||||
// memory.
|
||||
if (mLibVLCMediaPlayer)
|
||||
{
|
||||
// stop listening to events while we reset things
|
||||
libvlc_event_manager_t* em = libvlc_media_player_event_manager(mLibVLCMediaPlayer);
|
||||
if (em)
|
||||
{
|
||||
libvlc_event_detach(em, libvlc_MediaPlayerOpening, eventCallbacks, NULL);
|
||||
libvlc_event_detach(em, libvlc_MediaPlayerPlaying, eventCallbacks, NULL);
|
||||
libvlc_event_detach(em, libvlc_MediaPlayerPaused, eventCallbacks, NULL);
|
||||
libvlc_event_detach(em, libvlc_MediaPlayerStopped, eventCallbacks, NULL);
|
||||
libvlc_event_detach(em, libvlc_MediaPlayerEndReached, eventCallbacks, NULL);
|
||||
libvlc_event_detach(em, libvlc_MediaPlayerEncounteredError, eventCallbacks, NULL);
|
||||
libvlc_event_detach(em, libvlc_MediaPlayerTimeChanged, eventCallbacks, NULL);
|
||||
libvlc_event_detach(em, libvlc_MediaPlayerPositionChanged, eventCallbacks, NULL);
|
||||
libvlc_event_detach(em, libvlc_MediaPlayerLengthChanged, eventCallbacks, NULL);
|
||||
libvlc_event_detach(em, libvlc_MediaPlayerTitleChanged, eventCallbacks, NULL);
|
||||
};
|
||||
|
||||
libvlc_media_player_stop(mLibVLCMediaPlayer);
|
||||
libvlc_media_player_release(mLibVLCMediaPlayer);
|
||||
|
||||
mLibVLCMediaPlayer = 0;
|
||||
}
|
||||
|
||||
if (mLibVLCMedia)
|
||||
{
|
||||
libvlc_media_release(mLibVLCMedia);
|
||||
|
||||
mLibVLCMedia = 0;
|
||||
}
|
||||
|
||||
mLibVLCMedia = libvlc_media_new_location(mLibVLC, mURL.c_str());
|
||||
|
|
@ -345,6 +326,9 @@ void MediaPluginLibVLC::playMedia()
|
|||
libvlc_event_attach(em, libvlc_MediaPlayerTitleChanged, eventCallbacks, this);
|
||||
}
|
||||
|
||||
libvlc_video_set_callbacks(mLibVLCMediaPlayer, lock, unlock, display, &mLibVLCCallbackContext);
|
||||
libvlc_video_set_format(mLibVLCMediaPlayer, "RV32", mWidth, mHeight, mWidth * mDepth);
|
||||
|
||||
mLibVLCCallbackContext.parent = this;
|
||||
mLibVLCCallbackContext.texture_pixels = mPixels;
|
||||
mLibVLCCallbackContext.mp = mLibVLCMediaPlayer;
|
||||
|
|
@ -366,14 +350,11 @@ void MediaPluginLibVLC::playMedia()
|
|||
|
||||
setStatus(STATUS_LOADED);
|
||||
|
||||
libvlc_video_set_callbacks(mLibVLCMediaPlayer, lock, unlock, display, &mLibVLCCallbackContext);
|
||||
libvlc_video_set_format(mLibVLCMediaPlayer, "RV32", mWidth, mHeight, mWidth * mDepth);
|
||||
|
||||
// note this relies on the "set_loop" message arriving before the "start" (play) one
|
||||
// but that appears to always be the case
|
||||
if (mIsLooping)
|
||||
{
|
||||
libvlc_media_add_option(mLibVLCMedia, "input-repeat=-1");
|
||||
libvlc_media_add_option(mLibVLCMedia, "input-repeat=65535");
|
||||
}
|
||||
|
||||
libvlc_media_player_play(mLibVLCMediaPlayer);
|
||||
|
|
|
|||
|
|
@ -397,9 +397,12 @@ set(viewer_SOURCE_FILES
|
|||
llfloaterpathfindinglinksets.cpp
|
||||
llfloaterpathfindingobjects.cpp
|
||||
llfloaterpay.cpp
|
||||
# llfloaterperformance.cpp <FS:Beq/> replaced with fs version due to large changes and likelihood that LL version will not release.
|
||||
fsfloaterperformance.cpp
|
||||
llfloaterperms.cpp
|
||||
llfloaterpostprocess.cpp
|
||||
llfloaterpreference.cpp
|
||||
# llfloaterpreferencesgraphicsadvanced.cpp
|
||||
llfloaterpreferenceviewadvanced.cpp
|
||||
llfloaterpreviewtrash.cpp
|
||||
llfloaterproperties.cpp
|
||||
|
|
@ -1176,9 +1179,12 @@ set(viewer_HEADER_FILES
|
|||
llfloaterpathfindinglinksets.h
|
||||
llfloaterpathfindingobjects.h
|
||||
llfloaterpay.h
|
||||
# llfloaterperformance.h <FS:Beq/> replaced with fs version due to large changes and likelihood that LL version will not release.
|
||||
fsfloaterperformance.h
|
||||
llfloaterperms.h
|
||||
llfloaterpostprocess.h
|
||||
llfloaterpreference.h
|
||||
# llfloaterpreferencesgraphicsadvanced.h
|
||||
llfloaterpreferenceviewadvanced.h
|
||||
llfloaterpreviewtrash.h
|
||||
llfloaterproperties.h
|
||||
|
|
@ -1678,6 +1684,10 @@ configure_file(
|
|||
list(APPEND viewer_HEADER_FILES ${CMAKE_CURRENT_BINARY_DIR}/fsversionvalues.h)
|
||||
# </FS:TS>
|
||||
|
||||
# <FS:Beq> Performance stast support
|
||||
list(APPEND viewer_SOURCE_FILES fsperfstats.cpp)
|
||||
list(APPEND viewer_HEADER_FILES fsperfstats.h)
|
||||
# </FS:Beq>
|
||||
source_group("CMake Rules" FILES ViewerInstall.cmake)
|
||||
|
||||
#build_data.json creation moved to viewer_manifest.py MAINT-6413
|
||||
|
|
@ -2562,7 +2572,7 @@ if (NOT ENABLE_MEDIA_PLUGINS)
|
|||
else (NOT ENABLE_MEDIA_PLUGINS)
|
||||
set(COPY_INPUT_DEPENDENCIES
|
||||
${VIEWER_BINARY_NAME}
|
||||
linux-crash-logger
|
||||
#linux-crash-logger
|
||||
SLPlugin
|
||||
media_plugin_cef
|
||||
#media_plugin_gstreamer010
|
||||
|
|
@ -2674,10 +2684,8 @@ if (DARWIN)
|
|||
# SIGH, as of 2018-05-24 (cmake 3.11.1) the INSTALL_RPATH property simply
|
||||
# does not work. Try this:
|
||||
LINK_FLAGS "-rpath @loader_path/../Frameworks"
|
||||
MACOSX_BUNDLE_INFO_PLIST
|
||||
# <FS:CR> Use Firestorm plist
|
||||
#"${CMAKE_CURRENT_SOURCE_DIR}/Info-SecondLife.plist"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/Info-Firestorm.plist"
|
||||
MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/Info-Firestorm.plist"
|
||||
XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER "${MACOSX_BUNDLE_GUI_IDENTIFIER}"
|
||||
)
|
||||
|
||||
set(VIEWER_APP_BUNDLE "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${product}.app")
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
<key>CFBundleIconFile</key>
|
||||
<string>${MACOSX_BUNDLE_ICON_FILE}</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>${MACOSX_BUNDLE_GUI_IDENTIFIER}</string>
|
||||
<string>${PRODUCT_BUNDLE_IDENTIFIER}</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleLongVersionString</key>
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
<key>CFBundleIconFile</key>
|
||||
<string>${MACOSX_BUNDLE_ICON_FILE}</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>${MACOSX_BUNDLE_GUI_IDENTIFIER}</string>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleLongVersionString</key>
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@
|
|||
#include "llviewerobjectlist.h"
|
||||
#include "llviewerregion.h"
|
||||
#include "llworld.h"
|
||||
#include "sound_ids.h"
|
||||
#include <time.h>
|
||||
#include <boost/regex.hpp>
|
||||
|
||||
|
|
@ -207,11 +206,6 @@ NACLAntiSpamRegistry::NACLAntiSpamRegistry() :
|
|||
{
|
||||
mQueues[queue] = new NACLAntiSpamQueue(mGlobalTime, mGlobalAmount);
|
||||
}
|
||||
|
||||
for (S32 i = 0; i < COLLISION_SOUNDS_SIZE; ++i)
|
||||
{
|
||||
mCollisionSounds.insert(LLUUID(COLLISION_SOUNDS[i]));
|
||||
}
|
||||
}
|
||||
|
||||
NACLAntiSpamRegistry::~NACLAntiSpamRegistry()
|
||||
|
|
@ -640,11 +634,6 @@ void NACLAntiSpamRegistry::purgeGlobalEntries()
|
|||
mGlobalEntries.clear();
|
||||
}
|
||||
|
||||
bool NACLAntiSpamRegistry::isCollisionSound(const LLUUID& sound_id)
|
||||
{
|
||||
return (mCollisionSounds.find(sound_id) != mCollisionSounds.end());
|
||||
}
|
||||
|
||||
void NACLAntiSpamRegistry::processObjectPropertiesFamily(LLMessageSystem* msg)
|
||||
{
|
||||
static LLCachedControl<bool> useAntiSpam(gSavedSettings, "UseAntiSpam");
|
||||
|
|
|
|||
|
|
@ -113,8 +113,6 @@ public:
|
|||
void clearAllQueues();
|
||||
void purgeAllQueues();
|
||||
|
||||
bool isCollisionSound(const LLUUID& sound_id);
|
||||
|
||||
void processObjectPropertiesFamily(LLMessageSystem* msg);
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
6.4.24
|
||||
6.5.1
|
||||
|
|
|
|||
|
|
@ -638,4 +638,14 @@
|
|||
is_running_function="Floater.IsOpen"
|
||||
is_running_parameters="my_environments"
|
||||
/>
|
||||
<command name="performance"
|
||||
available_in_toybox="true"
|
||||
icon="Command_Performance_Icon"
|
||||
label_ref="Command_Performance_Label"
|
||||
tooltip_ref="Command_Performance_Tooltip"
|
||||
execute_function="Floater.ToggleOrBringToFront"
|
||||
execute_parameters="performance"
|
||||
is_running_function="Floater.IsOpen"
|
||||
is_running_parameters="performance"
|
||||
/>
|
||||
</commands>
|
||||
|
|
|
|||
|
|
@ -3187,10 +3187,11 @@
|
|||
<key>Value</key>
|
||||
<real>1.0</real>
|
||||
</map>
|
||||
<key>CameraPreset</key> <!-- deprecated (see SL-12429) -->
|
||||
<key>CameraPreset</key>
|
||||
<!-- deprecated (see SL-12429) -->
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Preset camera position - view (0 - rear, 1 - front, 2 - group)</string>
|
||||
<string>(Deprecated) Preset camera position - view (0 - rear, 1 - front, 2 - group)</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
|
|
@ -4216,10 +4217,11 @@
|
|||
<key>Backup</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>DEPRECATED: DebugShowPrivateMem</key> <!-- deprecated (see MAINT-8091) -->
|
||||
<key>DebugShowPrivateMem</key>
|
||||
<!-- deprecated (see MAINT-8091) -->
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Show Private Mem Info</string>
|
||||
<string>(Deprecated) Show Private Mem Info</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
|
|
@ -5854,6 +5856,17 @@
|
|||
<key>Value</key>
|
||||
<integer>1</integer>
|
||||
</map>
|
||||
<key>EnableCollisionSounds</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Play sounds on collision</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>1</integer>
|
||||
</map>
|
||||
<key>EnableMouselook</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
|
|
@ -8171,7 +8184,7 @@
|
|||
<key>Comment</key>
|
||||
<string>Duration in seconds of the login SRV request timeout</string>
|
||||
<key>Persist</key>
|
||||
<integer>0</integer>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>F32</string>
|
||||
<key>Value</key>
|
||||
|
|
@ -8180,7 +8193,7 @@
|
|||
<key>LoginSRVPump</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Name of the message pump that handles SRV request (deprecated)</string>
|
||||
<string>(Deprecated) Name of the message pump that handles SRV request)</string>
|
||||
<key>Persist</key>
|
||||
<integer>0</integer>
|
||||
<key>Type</key>
|
||||
|
|
@ -9038,10 +9051,11 @@
|
|||
<key>Value</key>
|
||||
<real>600.0</real>
|
||||
</map>
|
||||
<key>MemoryPrivatePoolEnabled</key> <!-- deprecated (see MAINT-8091) -->
|
||||
<key>MemoryPrivatePoolEnabled</key>
|
||||
<!-- deprecated (see MAINT-8091) -->
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>DEPRECATED: Enable the private memory pool management</string>
|
||||
<string>(Deprecated) Enable the private memory pool management</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
|
|
@ -9051,10 +9065,11 @@
|
|||
<key>Backup</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>MemoryPrivatePoolSize</key> <!-- deprecated (see MAINT-8091) -->
|
||||
<key>MemoryPrivatePoolSize</key>
|
||||
<!-- deprecated (see MAINT-8091) -->
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>DEPRECATED: Size of the private memory pool in MB (min. value is 256)</string>
|
||||
<string>(Deprecated) Size of the private memory pool in MB (min. value is 256)</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
|
|
@ -11103,7 +11118,7 @@ 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>
|
||||
<integer>1</integer>
|
||||
</map>
|
||||
<key>QAMode</key>
|
||||
<map>
|
||||
|
|
@ -11119,7 +11134,7 @@ Change of this parameter will affect the layout of buttons in notification toast
|
|||
<key>QAModeEventHostPort</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>DEPRECATED: Port on which lleventhost should listen</string>
|
||||
<string>(Deprecated) Port on which lleventhost should listen</string>
|
||||
<key>Persist</key>
|
||||
<integer>0</integer>
|
||||
<key>Type</key>
|
||||
|
|
@ -15853,6 +15868,17 @@ Change of this parameter will affect the layout of buttons in notification toast
|
|||
<key>Backup</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>TextureSaveLocation</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Current location for bulk saving textures to disk</string>
|
||||
<key>Persist</key>
|
||||
<integer>0</integer>
|
||||
<key>Type</key>
|
||||
<string>String</string>
|
||||
<key>Value</key>
|
||||
<string />
|
||||
</map>
|
||||
<key>ThrottleBandwidthKBPS</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
|
|
@ -17577,10 +17603,11 @@ Change of this parameter will affect the layout of buttons in notification toast
|
|||
<key>Value</key>
|
||||
<string>Default</string>
|
||||
</map>
|
||||
<key>UseExternalBrowser</key> <!-- deprecated (see MAINT-4127) -->
|
||||
<key>UseExternalBrowser</key>
|
||||
<!-- deprecated (see MAINT-4127) -->
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Use default browser when opening web pages instead of in-world browser.</string>
|
||||
<string>(Deprecated) Use default browser when opening web pages instead of in-world browser.</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
|
|
@ -18087,6 +18114,7 @@ Change of this parameter will affect the layout of buttons in notification toast
|
|||
<integer>0</integer>
|
||||
</map>
|
||||
<key>VoiceCallsRejectGroup</key>
|
||||
<!-- deprecated (see SL-12871) -->
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Silently reject all incoming group voice calls.</string>
|
||||
|
|
@ -22504,17 +22532,6 @@ Change of this parameter will affect the layout of buttons in notification toast
|
|||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>FSPlayCollisionSounds</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Play collision sounds.</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>1</integer>
|
||||
</map>
|
||||
<key>FSFadeAudioStream</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
|
|
@ -25712,6 +25729,39 @@ Change of this parameter will affect the layout of buttons in notification toast
|
|||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>FSTargetFPS</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Desired minimum FPS</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>U32</string>
|
||||
<key>Value</key>
|
||||
<integer>25</integer>
|
||||
</map>
|
||||
<key>FSAutoTuneFPS</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Allow the viewer to adjust your settings to achieve target FPS</string>
|
||||
<key>Persist</key>
|
||||
<integer>0</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>FSPerfFloaterSmoothingPeriods</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Number of periods to smooth the stats over</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>U32</string>
|
||||
<key>Value</key>
|
||||
<integer>50</integer>
|
||||
</map>
|
||||
<key>FSAutoUnmuteSounds</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
|
|
@ -25734,5 +25784,115 @@ Change of this parameter will affect the layout of buttons in notification toast
|
|||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>RenderJellyDollsAsImpostors</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Use an impostor instead of a JellyDoll for better visuals (true)</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>1</integer>
|
||||
</map>
|
||||
<key>FSPerfStatsCaptureEnabled</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Enable/disable render time data to support autotune.</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>1</integer>
|
||||
</map>
|
||||
<key>FSAutoTuneImpostorByDistEnabled</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Enable/disable using MaxNonImpostor to limit avatar rendering by distance.</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>1</integer>
|
||||
</map>
|
||||
<key>FSAllowSelfImpostor</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Allow own render time to impostor your avatar.</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>FSShowTunedART</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Show the tuned render time in the avatar display.</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>FSRenderAvatarMaxART</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Render Time Limit in microseconds (0.0 = no limit)</string>
|
||||
<key>Persist</key>
|
||||
<integer>0</integer>
|
||||
<key>Type</key>
|
||||
<string>F32</string>
|
||||
<key>Value</key>
|
||||
<real>4.699</real>
|
||||
</map>
|
||||
<key>FSAutoTuneRenderFarClipMin</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>The lowest draw distance that auto tune is allowed to use</string>
|
||||
<key>Persist</key>
|
||||
<integer>0</integer>
|
||||
<key>Type</key>
|
||||
<string>F32</string>
|
||||
<key>Value</key>
|
||||
<real>32.0</real>
|
||||
</map>
|
||||
<key>FSAutoTuneRenderFarClipTarget</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>The draw distance that auto tune will try to achieve</string>
|
||||
<key>Persist</key>
|
||||
<integer>0</integer>
|
||||
<key>Type</key>
|
||||
<string>F32</string>
|
||||
<key>Value</key>
|
||||
<real>256.0</real>
|
||||
</map>
|
||||
<key>FSAutoTuneImpostorFarAwayDistance</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Avatars beyond this range will automatically be optimized</string>
|
||||
<key>Persist</key>
|
||||
<integer>0</integer>
|
||||
<key>Type</key>
|
||||
<string>F32</string>
|
||||
<key>Value</key>
|
||||
<real>64.0</real>
|
||||
</map>
|
||||
<key>FSTuningFPSStrategy</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Strategy to use when tuning FPS. 0=Tune avatar rendering only, 1=Tune both avatar and global scene settings.</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>U32</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
</map>
|
||||
</llsd>
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,98 @@
|
|||
/**
|
||||
* @file fsfloaterperformance.h
|
||||
*
|
||||
* This is forked directly from an early access release of llfloaterperformance.h
|
||||
*
|
||||
* $LicenseInfo:firstyear=2021&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2021, 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$
|
||||
*/
|
||||
|
||||
#ifndef FS_FLOATERPERFORMANCE_H
|
||||
#define FS_FLOATERPERFORMANCE_H
|
||||
|
||||
#include "llfloater.h"
|
||||
#include "lllistcontextmenu.h"
|
||||
|
||||
class LLCharacter;
|
||||
class LLNameListCtrl;
|
||||
class LLComboBox;
|
||||
|
||||
class FSFloaterPerformance : public LLFloater
|
||||
{
|
||||
public:
|
||||
FSFloaterPerformance(const LLSD& key);
|
||||
virtual ~FSFloaterPerformance();
|
||||
|
||||
/*virtual*/ BOOL postBuild();
|
||||
/*virtual*/ void draw();
|
||||
|
||||
void showSelectedPanel(LLPanel* selected_panel);
|
||||
void showMainPanel();
|
||||
void hidePanels();
|
||||
|
||||
void detachItem(const LLUUID& item_id);
|
||||
|
||||
void onAvatarListRightClick(LLUICtrl* ctrl, S32 x, S32 y);
|
||||
|
||||
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);
|
||||
|
||||
private:
|
||||
void initBackBtn(LLPanel* panel);
|
||||
void populateHUDList();
|
||||
void populateObjectList();
|
||||
void populateNearbyList();
|
||||
|
||||
void onChangeQuality(const LLSD& data);
|
||||
void onClickHideAvatars();
|
||||
void onClickExceptions();
|
||||
void onClickFocusAvatar();
|
||||
|
||||
void updateMaxComplexity();
|
||||
void updateComplexityText();
|
||||
void updateMaxRenderTime();
|
||||
void updateMaxRenderTimeText();
|
||||
|
||||
void getNearbyAvatars(std::vector<LLCharacter*> &valid_nearby_avs);
|
||||
|
||||
LLPanel* mMainPanel;
|
||||
LLPanel* mNearbyPanel;
|
||||
LLPanel* mComplexityPanel;
|
||||
LLPanel* mHUDsPanel;
|
||||
LLPanel* mSettingsPanel;
|
||||
LLPanel* mAutoTunePanel;
|
||||
LLNameListCtrl* mHUDList;
|
||||
LLNameListCtrl* mObjectList;
|
||||
LLNameListCtrl* mNearbyList;
|
||||
LLComboBox* mNearbyCombo;
|
||||
|
||||
LLListContextMenu* mContextMenu;
|
||||
|
||||
LLTimer* mUpdateTimer;
|
||||
|
||||
S32 mNearbyMaxComplexity;
|
||||
|
||||
boost::signals2::connection mComplexityChangedSignal;
|
||||
boost::signals2::connection mMaxARTChangedSignal;
|
||||
};
|
||||
|
||||
#endif // FS_FLOATERPERFORMANCE_H
|
||||
|
|
@ -0,0 +1,419 @@
|
|||
/**
|
||||
* @file fsperfstats.cpp
|
||||
* @brief Stats collection to support perf floater and auto tune
|
||||
*
|
||||
* $LicenseInfo:firstyear=2021&license=fsviewerlgpl$
|
||||
* Phoenix Firestorm Viewer Source Code
|
||||
* Copyright (C) 2021, The Phoenix Firestorm Project, 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
|
||||
*
|
||||
* The Phoenix Firestorm Project, Inc., 1831 Oakwood Drive, Fairmont, Minnesota 56031-3225 USA
|
||||
* http://www.firestormviewer.org
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#include "llviewerprecompiledheaders.h"
|
||||
#include "fsperfstats.h"
|
||||
#include "llcontrol.h"
|
||||
#include "pipeline.h"
|
||||
#include "llagentcamera.h"
|
||||
#include "llvoavatar.h"
|
||||
#include "llworld.h"
|
||||
|
||||
extern LLControlGroup gSavedSettings;
|
||||
|
||||
namespace FSPerfStats
|
||||
{
|
||||
#ifdef USAGE_TRACKING
|
||||
std::atomic<int64_t> inUse{0};
|
||||
std::atomic<int64_t> inUseAvatar{0};
|
||||
std::atomic<int64_t> inUseScene{0};
|
||||
std::atomic<int64_t> inUseAttachment{0};
|
||||
std::atomic<int64_t> inUseAttachmentRigged{0};
|
||||
std::atomic<int64_t> inUseAttachmentUnRigged{0};
|
||||
#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
|
||||
U32 fpsTuningStrategy{0}; // linked to FSTuningFPSStrategy
|
||||
U32 lastGlobalPrefChange{0};
|
||||
std::mutex bufferToggleLock{};
|
||||
bool autoTune{false};
|
||||
|
||||
std::atomic<int> StatsRecorder::writeBuffer{0};
|
||||
bool StatsRecorder::collectionEnabled{true};
|
||||
LLUUID StatsRecorder::focusAv{LLUUID::null};
|
||||
std::array<StatsRecorder::StatsTypeMatrix,2> StatsRecorder::statsDoubleBuffer{ {} };
|
||||
std::array<StatsRecorder::StatsSummaryArray,2> StatsRecorder::max{ {} };
|
||||
std::array<StatsRecorder::StatsSummaryArray,2> StatsRecorder::sum{ {} };
|
||||
|
||||
|
||||
StatsRecorder::StatsRecorder():q(1024*16),t(&StatsRecorder::run)
|
||||
{
|
||||
// create a queue
|
||||
// create a thread to consume from the queue
|
||||
|
||||
FSPerfStats::targetFPS = gSavedSettings.getU32("FSTargetFPS");
|
||||
FSPerfStats::autoTune = gSavedSettings.getBOOL("FSAutoTuneFPS");
|
||||
|
||||
updateRenderCostLimitFromSettings();
|
||||
|
||||
t.detach();
|
||||
}
|
||||
|
||||
// static
|
||||
void StatsRecorder::toggleBuffer()
|
||||
{
|
||||
FSZone;
|
||||
using ST = StatType_t;
|
||||
|
||||
bool unreliable{false};
|
||||
static LLCachedControl<U32> smoothingPeriods(gSavedSettings, "FSPerfFloaterSmoothingPeriods");
|
||||
|
||||
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];
|
||||
|
||||
static constexpr std::initializer_list<StatType_t> sceneStatsToAvg = {
|
||||
StatType_t::RENDER_FRAME,
|
||||
StatType_t::RENDER_DISPLAY,
|
||||
StatType_t::RENDER_HUDS,
|
||||
StatType_t::RENDER_UI,
|
||||
StatType_t::RENDER_SWAP,
|
||||
// RENDER_LFS,
|
||||
// RENDER_MESHREPO,
|
||||
StatType_t::RENDER_IDLE };
|
||||
|
||||
static constexpr std::initializer_list<StatType_t> avatarStatsToAvg = {
|
||||
StatType_t::RENDER_GEOMETRY,
|
||||
StatType_t::RENDER_SHADOWS,
|
||||
StatType_t::RENDER_COMBINED,
|
||||
StatType_t::RENDER_IDLE };
|
||||
|
||||
|
||||
if( sceneStats[static_cast<size_t>(StatType_t::RENDER_FPSLIMIT)] != 0 || sceneStats[static_cast<size_t>(StatType_t::RENDER_SLEEP)] != 0 )
|
||||
{
|
||||
unreliable = true;
|
||||
lastStats[static_cast<size_t>(StatType_t::RENDER_FPSLIMIT)] = sceneStats[static_cast<size_t>(StatType_t::RENDER_FPSLIMIT)];
|
||||
lastStats[static_cast<size_t>(StatType_t::RENDER_SLEEP)] = sceneStats[static_cast<size_t>(StatType_t::RENDER_SLEEP)];
|
||||
}
|
||||
|
||||
if(!unreliable)
|
||||
{
|
||||
// only use these stats when things are reliable.
|
||||
|
||||
for(auto & statEntry : sceneStatsToAvg)
|
||||
{
|
||||
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);
|
||||
// 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;
|
||||
}
|
||||
|
||||
auto& statsMap = statsDoubleBuffer[writeBuffer][static_cast<size_t>(ObjType_t::OT_ATTACHMENT)];
|
||||
for(auto& stat_entry : statsMap)
|
||||
{
|
||||
auto val = stat_entry.second[static_cast<size_t>(ST::RENDER_COMBINED)];
|
||||
if(val>smoothingPeriods){
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
auto& statsMapAv = statsDoubleBuffer[writeBuffer][static_cast<size_t>(ObjType_t::OT_AVATAR)];
|
||||
for(auto& stat_entry : statsMapAv)
|
||||
{
|
||||
for(auto& stat : avatarStatsToAvg)
|
||||
{
|
||||
auto val = stat_entry.second[static_cast<size_t>(stat)];
|
||||
if(val>smoothingPeriods)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// swap the buffers
|
||||
if(enabled())
|
||||
{
|
||||
std::lock_guard<std::mutex> lock{bufferToggleLock};
|
||||
writeBuffer ^= 1;
|
||||
}; // note we are relying on atomic updates here. The risk is low and would cause minor errors in the stats display.
|
||||
}
|
||||
|
||||
// clean the write maps in all cases.
|
||||
auto& statsTypeMatrix = statsDoubleBuffer[writeBuffer];
|
||||
for(auto& statsMap : statsTypeMatrix)
|
||||
{
|
||||
FSZoneN("Clear stats maps");
|
||||
for(auto& stat_entry : statsMap)
|
||||
{
|
||||
std::fill_n(stat_entry.second.begin() ,static_cast<size_t>(ST::STATS_COUNT),0);
|
||||
}
|
||||
statsMap.clear();
|
||||
}
|
||||
for(int i=0; i< static_cast<size_t>(ObjType_t::OT_COUNT); i++)
|
||||
{
|
||||
FSZoneN("clear max/sum");
|
||||
max[writeBuffer][i].fill(0);
|
||||
sum[writeBuffer][i].fill(0);
|
||||
}
|
||||
|
||||
// and now adjust the visuals.
|
||||
if(autoTune)
|
||||
{
|
||||
updateAvatarParams();
|
||||
}
|
||||
}
|
||||
|
||||
// clear buffers when we change region or need a hard reset.
|
||||
// static
|
||||
void StatsRecorder::clearStatsBuffers()
|
||||
{
|
||||
FSZone;
|
||||
using ST = StatType_t;
|
||||
|
||||
auto& statsTypeMatrix = statsDoubleBuffer[writeBuffer];
|
||||
for(auto& statsMap : statsTypeMatrix)
|
||||
{
|
||||
FSZoneN("Clear stats maps");
|
||||
for(auto& stat_entry : statsMap)
|
||||
{
|
||||
std::fill_n(stat_entry.second.begin() ,static_cast<size_t>(ST::STATS_COUNT),0);
|
||||
}
|
||||
statsMap.clear();
|
||||
}
|
||||
for(int i=0; i< static_cast<size_t>(ObjType_t::OT_COUNT); i++)
|
||||
{
|
||||
FSZoneN("clear max/sum");
|
||||
max[writeBuffer][i].fill(0);
|
||||
sum[writeBuffer][i].fill(0);
|
||||
}
|
||||
// swap the clean buffers in
|
||||
if(enabled())
|
||||
{
|
||||
std::lock_guard<std::mutex> lock{bufferToggleLock};
|
||||
writeBuffer ^= 1;
|
||||
};
|
||||
// repeat before we start processing new stuff
|
||||
for(auto& statsMap : statsTypeMatrix)
|
||||
{
|
||||
FSZoneN("Clear stats maps");
|
||||
for(auto& stat_entry : statsMap)
|
||||
{
|
||||
std::fill_n(stat_entry.second.begin() ,static_cast<size_t>(ST::STATS_COUNT),0);
|
||||
}
|
||||
statsMap.clear();
|
||||
}
|
||||
for(int i=0; i< static_cast<size_t>(ObjType_t::OT_COUNT); i++)
|
||||
{
|
||||
FSZoneN("clear max/sum");
|
||||
max[writeBuffer][i].fill(0);
|
||||
sum[writeBuffer][i].fill(0);
|
||||
}
|
||||
}
|
||||
|
||||
// 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)
|
||||
{
|
||||
const auto our_pos = gAgentCamera.getCameraPositionGlobal();
|
||||
|
||||
std::vector<LLVector3d> positions;
|
||||
uuid_vec_t avatar_ids;
|
||||
LLWorld::getInstance()->getAvatars(&avatar_ids, &positions, our_pos, distance);
|
||||
return positions.size();
|
||||
}
|
||||
|
||||
// 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");
|
||||
|
||||
if(impostorDistanceTuning)
|
||||
{
|
||||
// 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 )
|
||||
{
|
||||
gSavedSettings.setU32("IndirectMaxNonImpostors", (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;
|
||||
}
|
||||
}
|
||||
|
||||
auto av_render_max_raw = FSPerfStats::StatsRecorder::getMax(ObjType_t::OT_AVATAR, FSPerfStats::StatType_t::RENDER_COMBINED);
|
||||
// Is our target frame time lower than current? If so we need to take action to reduce draw overheads.
|
||||
// cumulative avatar time (includes idle processing, attachments and base av)
|
||||
auto tot_avatar_time_raw = FSPerfStats::StatsRecorder::getSum(ObjType_t::OT_AVATAR, FSPerfStats::StatType_t::RENDER_COMBINED);
|
||||
// sleep time is basically forced sleep when window out of focus
|
||||
auto tot_sleep_time_raw = FSPerfStats::StatsRecorder::getSceneStat(FSPerfStats::StatType_t::RENDER_SLEEP);
|
||||
// similar to sleep time, induced by FPS limit
|
||||
auto tot_limit_time_raw = FSPerfStats::StatsRecorder::getSceneStat(FSPerfStats::StatType_t::RENDER_FPSLIMIT);
|
||||
|
||||
|
||||
// the time spent this frame on the "doFrame" call. Treated as "tot time for frame"
|
||||
auto tot_frame_time_raw = FSPerfStats::StatsRecorder::getSceneStat(FSPerfStats::StatType_t::RENDER_FRAME);
|
||||
|
||||
if( tot_sleep_time_raw != 0 )
|
||||
{
|
||||
// Note: we do not average sleep
|
||||
// if at some point we need to, the averaging will need to take this into account or
|
||||
// we forever think we're in the background due to residuals.
|
||||
LL_DEBUGS() << "No tuning when not in focus" << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
|
||||
// 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));
|
||||
// LL_INFOS() << "Effective FPS(raw):" << tot_frame_time_raw << " Target:" << target_frame_time_raw << LL_ENDL;
|
||||
|
||||
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?
|
||||
if( target_frame_time_raw <= tot_frame_time_raw )
|
||||
{
|
||||
// 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.
|
||||
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(FSPerfStats::fpsTuningStrategy == 1)
|
||||
{
|
||||
// 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
|
||||
if(LLPipeline::RenderReflectionDetail != -2)
|
||||
{
|
||||
gSavedSettings.setS32("RenderReflectionDetail", -2);
|
||||
FSPerfStats::lastGlobalPrefChange = gFrameCount;
|
||||
return;
|
||||
}
|
||||
else // deliberately "else" here so we only do these in steps
|
||||
{
|
||||
// step down the DD by 10m per update
|
||||
auto new_dd = (drawDistance-10>userMinDrawDistance)?(drawDistance - 10) : userMinDrawDistance;
|
||||
if(new_dd != drawDistance)
|
||||
{
|
||||
gSavedSettings.setF32("RenderFarClip", new_dd);
|
||||
FSPerfStats::lastGlobalPrefChange = gFrameCount;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
target_avatar_time_raw = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 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};
|
||||
// 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
|
||||
{
|
||||
new_render_limit_ns = renderAvatarMaxART_ns;
|
||||
}
|
||||
new_render_limit_ns -= FSPerfStats::ART_MIN_ADJUST_DOWN_NANOS;
|
||||
|
||||
// bounce at the bottom to prevent "no limit"
|
||||
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;
|
||||
// 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 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;
|
||||
}
|
||||
if( drawDistance < userTargetDrawDistance )
|
||||
{
|
||||
gSavedSettings.setF32("RenderFarClip", 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.
|
||||
auto water = gSavedSettings.getS32("RenderReflectionDetail");
|
||||
gSavedSettings.setS32("RenderReflectionDetail", water+1);
|
||||
}
|
||||
}
|
||||
updateSettingsFromRenderCostLimit();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,498 @@
|
|||
#pragma once
|
||||
#ifndef FS_PERFSTATS_H_INCLUDED
|
||||
#define FS_PERFSTATS_H_INCLUDED
|
||||
/**
|
||||
* @file fsperfstats.h
|
||||
* @brief Statistics collection to support autotune and perf flaoter.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2021&license=fsviewerlgpl$
|
||||
* Phoenix Firestorm Viewer Source Code
|
||||
* Copyright (C) 2021, The Phoenix Firestorm Project, 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
|
||||
*
|
||||
* The Phoenix Firestorm Project, Inc., 1831 Oakwood Drive, Fairmont, Minnesota 56031-3225 USA
|
||||
* http://www.firestormviewer.org
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#include <atomic>
|
||||
#include <chrono>
|
||||
#include <array>
|
||||
#include <unordered_map>
|
||||
#include <mutex>
|
||||
#include "lluuid.h"
|
||||
#include "llfasttimer.h"
|
||||
#include "blockingconcurrentqueue.h"
|
||||
#include "llapp.h"
|
||||
#include "fstelemetry.h"
|
||||
#include "pipeline.h"
|
||||
|
||||
// Additional logging options. These can skew inworld numbers so onyl use for debugging and tracking issues
|
||||
#ifdef FS_HAS_TELEMETRY_SUPPORT
|
||||
// USAGE_TRACKING - displays overlapping stats that may imply double counting.
|
||||
// ATTACHMENT_TRACKING - displays detailed tracking info for Avatar and Attachment. very heavy overhead.
|
||||
// #define USAGE_TRACKING
|
||||
// #define ATTACHMENT_TRACKING
|
||||
#else
|
||||
#undef USAGE_TRACKING
|
||||
#undef ATTACHMENT_TRACKING
|
||||
#endif
|
||||
|
||||
extern U32 gFrameCount;
|
||||
extern LLUUID gAgentID;
|
||||
namespace FSPerfStats
|
||||
{
|
||||
#ifdef USAGE_TRACKING
|
||||
extern std::atomic<int64_t> inUse;
|
||||
extern std::atomic<int64_t> inUseAvatar;
|
||||
extern std::atomic<int64_t> inUseScene;
|
||||
extern std::atomic<int64_t> inUseAttachment;
|
||||
extern std::atomic<int64_t> inUseAttachmentRigged;
|
||||
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};
|
||||
|
||||
constexpr F32 PREFERRED_DD{180};
|
||||
|
||||
extern std::atomic<int64_t> tunedAvatars;
|
||||
extern U32 targetFPS; // desired FPS
|
||||
extern U64 renderAvatarMaxART_ns;
|
||||
extern U32 fpsTuningStrategy;
|
||||
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
|
||||
OT_AVATAR,
|
||||
OT_ATTACHMENT,
|
||||
OT_HUD,
|
||||
OT_COUNT
|
||||
};
|
||||
enum class StatType_t{
|
||||
RENDER_GEOMETRY=0,
|
||||
RENDER_SHADOWS,
|
||||
RENDER_HUDS,
|
||||
RENDER_UI,
|
||||
RENDER_COMBINED,
|
||||
RENDER_SWAP,
|
||||
RENDER_FRAME,
|
||||
RENDER_DISPLAY,
|
||||
RENDER_SLEEP,
|
||||
RENDER_LFS,
|
||||
RENDER_MESHREPO,
|
||||
RENDER_FPSLIMIT,
|
||||
RENDER_FPS,
|
||||
RENDER_IDLE,
|
||||
RENDER_DONE, // toggle buffer & clearbuffer (see processUpdate for hackery)
|
||||
STATS_COUNT
|
||||
};
|
||||
|
||||
struct StatsRecord
|
||||
{
|
||||
StatType_t statType;
|
||||
ObjType_t objType;
|
||||
LLUUID avID;
|
||||
LLUUID objID;
|
||||
uint64_t time;
|
||||
bool isRigged;
|
||||
bool isHUD;
|
||||
};
|
||||
|
||||
class StatsRecorder{
|
||||
using Queue = moodycamel::BlockingConcurrentQueue<StatsRecord>;
|
||||
public:
|
||||
|
||||
static inline StatsRecorder& getInstance()
|
||||
{
|
||||
static StatsRecorder instance;
|
||||
// volatile int dummy{};
|
||||
return instance;
|
||||
}
|
||||
static inline void setFocusAv(const LLUUID& avID){focusAv = avID;};
|
||||
static inline const LLUUID& getFocusAv(){return (focusAv);};
|
||||
static inline void send(StatsRecord&& u){StatsRecorder::getInstance().q.enqueue(u);};
|
||||
static void endFrame(){StatsRecorder::getInstance().q.enqueue(StatsRecord{StatType_t::RENDER_DONE, ObjType_t::OT_GENERAL, LLUUID::null, LLUUID::null, 0});};
|
||||
static void clearStats(){StatsRecorder::getInstance().q.enqueue(StatsRecord{StatType_t::RENDER_DONE, ObjType_t::OT_GENERAL, LLUUID::null, LLUUID::null, 1});};
|
||||
|
||||
static inline void setEnabled(bool on_or_off){collectionEnabled=on_or_off;};
|
||||
static inline void enable() { collectionEnabled=true; };
|
||||
static inline void disable() { collectionEnabled=false; };
|
||||
static inline bool enabled() { return(collectionEnabled); };
|
||||
|
||||
static inline int getReadBufferIndex() { return (writeBuffer ^ 1); };
|
||||
// static inline const StatsTypeMatrix& getCurrentStatsMatrix(){ return statsDoubleBuffer[getReadBufferIndex()];}
|
||||
static inline uint64_t get(ObjType_t otype, LLUUID id, StatType_t type)
|
||||
{
|
||||
return statsDoubleBuffer[getReadBufferIndex()][static_cast<size_t>(otype)][id][static_cast<size_t>(type)];
|
||||
}
|
||||
static inline uint64_t getSceneStat(StatType_t type)
|
||||
{
|
||||
return statsDoubleBuffer[getReadBufferIndex()][static_cast<size_t>(ObjType_t::OT_GENERAL)][LLUUID::null][static_cast<size_t>(type)];
|
||||
}
|
||||
|
||||
static inline uint64_t getSum(ObjType_t otype, StatType_t type)
|
||||
{
|
||||
return sum[getReadBufferIndex()][static_cast<size_t>(otype)][static_cast<size_t>(type)];
|
||||
}
|
||||
static inline uint64_t getMax(ObjType_t otype, StatType_t type)
|
||||
{
|
||||
return max[getReadBufferIndex()][static_cast<size_t>(otype)][static_cast<size_t>(type)];
|
||||
}
|
||||
static void updateSettingsFromRenderCostLimit();
|
||||
static void updateRenderCostLimitFromSettings();
|
||||
static void updateAvatarParams();
|
||||
private:
|
||||
StatsRecorder();
|
||||
|
||||
static int countNearbyAvatars(S32 distance);
|
||||
// StatsArray is a uint64_t for each possible statistic type.
|
||||
using StatsArray = std::array<uint64_t, static_cast<size_t>(FSPerfStats::StatType_t::STATS_COUNT)>;
|
||||
using StatsMap = std::unordered_map<LLUUID, StatsArray, FSUUIDHash>;
|
||||
using StatsTypeMatrix = std::array<StatsMap, static_cast<size_t>(FSPerfStats::ObjType_t::OT_COUNT)>;
|
||||
using StatsSummaryArray = std::array<StatsArray, static_cast<size_t>(FSPerfStats::ObjType_t::OT_COUNT)>;
|
||||
|
||||
static std::atomic<int> writeBuffer;
|
||||
static LLUUID focusAv;
|
||||
static std::array<StatsTypeMatrix,2> statsDoubleBuffer;
|
||||
static std::array<StatsSummaryArray,2> max;
|
||||
static std::array<StatsSummaryArray,2> sum;
|
||||
static bool collectionEnabled;
|
||||
|
||||
|
||||
void processUpdate(const StatsRecord& upd)
|
||||
{
|
||||
FSZone;
|
||||
// LL_INFOS("perfstats") << "processing update:" << LL_ENDL;
|
||||
using ST = StatType_t;
|
||||
// Note: nullptr is used as the key for global stats
|
||||
#ifdef FS_HAS_TELEMETRY_SUPPORT
|
||||
static char avstr[36];
|
||||
static char obstr[36];
|
||||
#endif
|
||||
|
||||
if(upd.statType == StatType_t::RENDER_DONE && upd.objType == ObjType_t::OT_GENERAL && upd.time == 0)
|
||||
{
|
||||
// LL_INFOS("perfstats") << "End of Frame Toggle Buffer:" << gFrameCount << LL_ENDL;
|
||||
toggleBuffer();
|
||||
return;
|
||||
}
|
||||
if(upd.statType == StatType_t::RENDER_DONE && upd.objType == ObjType_t::OT_GENERAL && upd.time == 1)
|
||||
{
|
||||
// LL_INFOS("perfstats") << "New region - clear buffers:" << gFrameCount << LL_ENDL;
|
||||
clearStatsBuffers();
|
||||
return;
|
||||
}
|
||||
|
||||
auto ot{upd.objType};
|
||||
auto& key{upd.objID};
|
||||
auto& avKey{upd.avID};
|
||||
auto type {upd.statType};
|
||||
auto val {upd.time};
|
||||
|
||||
#ifdef FS_HAS_TELEMETRY_SUPPORT
|
||||
FSZoneText(key.toStringFast(obstr),36);
|
||||
FSZoneText(avKey.toStringFast(avstr),36);
|
||||
FSZoneValue(val);
|
||||
#endif
|
||||
|
||||
if(ot == ObjType_t::OT_GENERAL)
|
||||
{
|
||||
// LL_INFOS("perfstats") << "General update:" << LL_ENDL;
|
||||
doUpd(key, ot, type,val);
|
||||
return;
|
||||
}
|
||||
|
||||
if(ot == ObjType_t::OT_AVATAR)
|
||||
{
|
||||
// LL_INFOS("perfstats") << "Avatar update:" << LL_ENDL;
|
||||
doUpd(avKey, ot, type, val);
|
||||
return;
|
||||
}
|
||||
|
||||
if(ot == ObjType_t::OT_ATTACHMENT)
|
||||
{
|
||||
if( !upd.isRigged && !upd.isHUD )
|
||||
{
|
||||
// For all attachments that are not rigged we add them to the avatar (for all avatars) cost.
|
||||
doUpd(avKey, ObjType_t::OT_AVATAR, type, val);
|
||||
}
|
||||
if( avKey == focusAv )
|
||||
{
|
||||
// For attachments that are for the focusAv (self for now) we record them for the attachment/complexity view
|
||||
if(upd.isHUD)
|
||||
{
|
||||
ot = ObjType_t::OT_HUD;
|
||||
}
|
||||
// LL_INFOS("perfstats") << "frame: " << gFrameCount << " Attachment update("<< (type==StatType_t::RENDER_GEOMETRY?"GEOMETRY":"SHADOW") << ": " << key.asString() << " = " << val << LL_ENDL;
|
||||
doUpd(key, ot, type, val);
|
||||
}
|
||||
else
|
||||
{
|
||||
// LL_INFOS("perfstats") << "frame: " << gFrameCount << " non-self Att update("<< (type==StatType_t::RENDER_GEOMETRY?"GEOMETRY":"SHADOW") << ": " << key.asString() << " = " << val << " for av " << avKey.asString() << LL_ENDL;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static inline void doUpd(const LLUUID& key, ObjType_t ot, StatType_t type, uint64_t val)
|
||||
{
|
||||
FSZone;
|
||||
using ST = StatType_t;
|
||||
StatsMap& stm {statsDoubleBuffer[writeBuffer][static_cast<size_t>(ot)]};
|
||||
auto& thisAsset = stm[key];
|
||||
|
||||
thisAsset[static_cast<size_t>(type)] += val;
|
||||
thisAsset[static_cast<size_t>(ST::RENDER_COMBINED)] += val;
|
||||
|
||||
sum[writeBuffer][static_cast<size_t>(ot)][static_cast<size_t>(type)] += val;
|
||||
sum[writeBuffer][static_cast<size_t>(ot)][static_cast<size_t>(ST::RENDER_COMBINED)] += val;
|
||||
|
||||
if(max[writeBuffer][static_cast<size_t>(ot)][static_cast<size_t>(type)] < thisAsset[static_cast<size_t>(type)])
|
||||
{
|
||||
max[writeBuffer][static_cast<size_t>(ot)][static_cast<size_t>(type)] = thisAsset[static_cast<size_t>(type)];
|
||||
}
|
||||
if(max[writeBuffer][static_cast<size_t>(ot)][static_cast<size_t>(ST::RENDER_COMBINED)] < thisAsset[static_cast<size_t>(ST::RENDER_COMBINED)])
|
||||
{
|
||||
max[writeBuffer][static_cast<size_t>(ot)][static_cast<size_t>(ST::RENDER_COMBINED)] = thisAsset[static_cast<size_t>(ST::RENDER_COMBINED)];
|
||||
}
|
||||
}
|
||||
|
||||
static void toggleBuffer();
|
||||
static void clearStatsBuffers();
|
||||
|
||||
// thread entry
|
||||
static void run()
|
||||
{
|
||||
StatsRecord upd[10];
|
||||
auto& instance {StatsRecorder::getInstance()};
|
||||
FSThreadName( "PerfStats" );
|
||||
|
||||
while( enabled() && !LLApp::isExiting() )
|
||||
{
|
||||
auto count = instance.q.wait_dequeue_bulk_timed(upd, 10, std::chrono::milliseconds(10));
|
||||
if(count)
|
||||
{
|
||||
// LL_INFOS("perfstats") << "processing " << count << " updates." << LL_ENDL;
|
||||
for(auto i =0; i < count; i++)
|
||||
{
|
||||
instance.processUpdate(upd[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Queue q;
|
||||
std::thread t;
|
||||
|
||||
~StatsRecorder() = default;
|
||||
StatsRecorder(const StatsRecorder&) = delete;
|
||||
StatsRecorder& operator=(const StatsRecorder&) = delete;
|
||||
|
||||
};
|
||||
|
||||
template <enum ObjType_t ObjTypeDiscriminator>
|
||||
class RecordTime
|
||||
{
|
||||
|
||||
private:
|
||||
RecordTime(const RecordTime&) = delete;
|
||||
RecordTime() = delete;
|
||||
U64 start;
|
||||
public:
|
||||
StatsRecord stat;
|
||||
|
||||
RecordTime( const LLUUID& av, const LLUUID& id, StatType_t type, bool isRiggedAtt=false, bool isHUDAtt=false):
|
||||
start{LLTrace::BlockTimer::getCPUClockCount64()},
|
||||
stat{type, ObjTypeDiscriminator, std::move(av), std::move(id), 0, isRiggedAtt, isHUDAtt}
|
||||
{
|
||||
FSZoneC(tracy::Color::Orange);
|
||||
#ifdef USAGE_TRACKING
|
||||
if(stat.objType == FSPerfStats::ObjType_t::OT_ATTACHMENT)
|
||||
{
|
||||
if(!stat.isRigged && FSPerfStats::inUseAvatar){FSZoneText("OVERLAP AVATAR",14);}
|
||||
|
||||
FSPlotSq("InUse", (int64_t)FSPerfStats::inUse, (int64_t)FSPerfStats::inUse+1);
|
||||
FSPerfStats::inUse++;
|
||||
FSPlotSq("InUseAttachment", (int64_t)FSPerfStats::inUseAttachment, (int64_t)FSPerfStats::inUseAttachment+1);
|
||||
FSPerfStats::inUseAttachment++;
|
||||
if (stat.isRigged)
|
||||
{
|
||||
FSPlotSq("InUseAttachmentRigged", (int64_t)FSPerfStats::inUseAttachmentRigged,(int64_t)FSPerfStats::inUseAttachmentRigged+1);
|
||||
FSPerfStats::inUseAttachmentRigged++;
|
||||
}
|
||||
else
|
||||
{
|
||||
FSPlotSq("InUseAttachmentUnRigged", (int64_t)FSPerfStats::inUseAttachmentUnRigged,(int64_t)FSPerfStats::inUseAttachmentUnRigged+1);
|
||||
FSPerfStats::inUseAttachmentUnRigged++;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
template < ObjType_t OD = ObjTypeDiscriminator,
|
||||
std::enable_if_t<OD == ObjType_t::OT_GENERAL> * = nullptr>
|
||||
RecordTime( StatType_t type ):RecordTime<ObjTypeDiscriminator>(LLUUID::null, LLUUID::null, type )
|
||||
{
|
||||
FSZone;
|
||||
#ifdef USAGE_TRACKING
|
||||
FSPlotSq("InUseScene", (int64_t)FSPerfStats::inUseScene, (int64_t)FSPerfStats::inUseScene+1);
|
||||
FSPerfStats::inUseScene++;
|
||||
FSPlotSq("InUse", (int64_t)FSPerfStats::inUse, (int64_t)FSPerfStats::inUse+1);
|
||||
FSPerfStats::inUse++;
|
||||
#endif
|
||||
};
|
||||
|
||||
template < ObjType_t OD = ObjTypeDiscriminator,
|
||||
std::enable_if_t<OD == ObjType_t::OT_AVATAR> * = nullptr>
|
||||
RecordTime( const LLUUID & av, StatType_t type ):RecordTime<ObjTypeDiscriminator>(std::move(av), LLUUID::null, type)
|
||||
{
|
||||
FSZoneC(tracy::Color::Purple);
|
||||
|
||||
#ifdef USAGE_TRACKING
|
||||
if(FSPerfStats::inUseAvatar){FSZoneText("OVERLAP AVATAR",14);}
|
||||
|
||||
FSPlotSq("InUseAv", (int64_t)FSPerfStats::inUseAvatar, (int64_t)FSPerfStats::inUseAvatar+1);
|
||||
FSPerfStats::inUseAvatar++;
|
||||
FSPlotSq("InUse", (int64_t)FSPerfStats::inUse, (int64_t)FSPerfStats::inUse+1);
|
||||
FSPerfStats::inUse++;
|
||||
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
~RecordTime()
|
||||
{
|
||||
if(!FSPerfStats::StatsRecorder::enabled())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
FSZoneC(tracy::Color::Red);
|
||||
|
||||
#ifdef USAGE_TRACKING
|
||||
FSPlotSq("InUse", (int64_t)FSPerfStats::inUse,(int64_t)FSPerfStats::inUse-1);
|
||||
--FSPerfStats::inUse;
|
||||
if (stat.objType == FSPerfStats::ObjType_t::OT_ATTACHMENT)
|
||||
{
|
||||
FSPlotSq("InUseAttachment", (int64_t)FSPerfStats::inUseAttachment,(int64_t)FSPerfStats::inUseAttachment-1);
|
||||
--FSPerfStats::inUseAttachment;
|
||||
if (stat.isRigged)
|
||||
{
|
||||
FSPlotSq("InUseAttachmentRigged", (int64_t)FSPerfStats::inUseAttachmentRigged,(int64_t)FSPerfStats::inUseAttachmentRigged-1);
|
||||
--FSPerfStats::inUseAttachmentRigged;
|
||||
}
|
||||
else
|
||||
{
|
||||
FSPlotSq("InUseAttachmentUnRigged", (int64_t)FSPerfStats::inUseAttachmentUnRigged,(int64_t)FSPerfStats::inUseAttachmentUnRigged-1);
|
||||
--FSPerfStats::inUseAttachmentUnRigged;
|
||||
}
|
||||
}
|
||||
if (stat.objType == FSPerfStats::ObjType_t::OT_GENERAL)
|
||||
{
|
||||
FSPlotSq("InUseScene", (int64_t)FSPerfStats::inUseScene,(int64_t)FSPerfStats::inUseScene-1);
|
||||
--FSPerfStats::inUseScene;
|
||||
}
|
||||
if( stat.objType == FSPerfStats::ObjType_t::OT_AVATAR )
|
||||
{
|
||||
FSPlotSq("InUseAv", (int64_t)FSPerfStats::inUseAvatar, (int64_t)FSPerfStats::inUseAvatar-1);
|
||||
--FSPerfStats::inUseAvatar;
|
||||
}
|
||||
#endif
|
||||
stat.time = LLTrace::BlockTimer::getCPUClockCount64() - start;
|
||||
|
||||
#ifdef ATTACHMENT_TRACKING
|
||||
static char obstr[36];
|
||||
static char avstr[36];
|
||||
FSZoneValue(static_cast<U64>(stat.objType));
|
||||
FSZoneText(stat.avID.toStringFast(avstr), 36);
|
||||
FSZoneText(stat.objID.toStringFast(obstr), 36);
|
||||
FSZoneValue(stat.time);
|
||||
#endif
|
||||
|
||||
StatsRecorder::send(std::move(stat));
|
||||
};
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
inline double raw_to_ns(U64 raw) { return (static_cast<double>(raw) * 1000000000.0) / (F64)LLTrace::BlockTimer::countsPerSecond(); };
|
||||
inline double raw_to_us(U64 raw) { return (static_cast<double>(raw) * 1000000.0) / (F64)LLTrace::BlockTimer::countsPerSecond(); };
|
||||
inline double raw_to_ms(U64 raw) { return (static_cast<double>(raw) * 1000.0) / (F64)LLTrace::BlockTimer::countsPerSecond(); };
|
||||
|
||||
using RecordSceneTime = RecordTime<ObjType_t::OT_GENERAL>;
|
||||
using RecordAvatarTime = RecordTime<ObjType_t::OT_AVATAR>;
|
||||
using RecordAttachmentTime = RecordTime<ObjType_t::OT_ATTACHMENT>;
|
||||
using RecordHudAttachmentTime = RecordTime<ObjType_t::OT_HUD>;
|
||||
|
||||
};// namespace FSPerfStats
|
||||
|
||||
// helper functions
|
||||
using RATptr = std::unique_ptr<FSPerfStats::RecordAttachmentTime>;
|
||||
|
||||
template <typename T>
|
||||
static inline void trackAttachments(const T * vobj, bool isRigged, RATptr* ratPtrp)
|
||||
{
|
||||
if( !vobj ){ ratPtrp->reset(); return;};
|
||||
|
||||
const T* rootAtt{vobj};
|
||||
if( rootAtt->isAttachment() )
|
||||
{
|
||||
FSZone;
|
||||
|
||||
while( !rootAtt->isRootEdit() )
|
||||
{
|
||||
rootAtt = (T*)(rootAtt->getParent());
|
||||
}
|
||||
|
||||
auto avPtr = (T*)(rootAtt->getParent());
|
||||
if(!avPtr){ratPtrp->reset(); return;}
|
||||
|
||||
auto& av = avPtr->getID();
|
||||
auto& obj = rootAtt->getAttachmentItemID();
|
||||
if(!*ratPtrp || (*ratPtrp)->stat.objID != obj || (*ratPtrp)->stat.avID != av )
|
||||
{
|
||||
#if TRACY_ENABLE && defined(ATTACHMENT_TRACKING)
|
||||
FSZoneNC( "trackAttachments:new", tracy::Color::Red );
|
||||
auto& str = rootAtt->getAttachmentItemName();
|
||||
FSZoneText(str.c_str(), str.size());
|
||||
FSZoneText(isRigged?"Rigged ":"Unrigged",8);
|
||||
static char avStr[36];
|
||||
av.toStringFast(avStr);
|
||||
static char obStr[4];
|
||||
obj.toShortString(obStr);
|
||||
FSZoneText( avStr, 36);
|
||||
FSZoneText( obStr, 4);
|
||||
#endif
|
||||
if(*ratPtrp){ratPtrp->reset();}; // deliberately reset to ensure destruction before construction of replacement.
|
||||
*ratPtrp = std::make_unique<FSPerfStats::RecordAttachmentTime>( av,
|
||||
obj,
|
||||
( (LLPipeline::sShadowRender)?FSPerfStats::StatType_t::RENDER_SHADOWS : FSPerfStats::StatType_t::RENDER_GEOMETRY ),
|
||||
isRigged,
|
||||
rootAtt->isHUDAttachment());
|
||||
}
|
||||
}
|
||||
return;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -638,7 +638,7 @@ Vivox SDK License
|
|||
|
||||
RSA Data Security, Inc. MD5 Message-Digest Algorithm
|
||||
|
||||
Audio coding: Polycom¨ Siren14TM (ITU-T Rec. G.722.1 Annex C)
|
||||
Audio coding: Polycom(R) Siren14TM (ITU-T Rec. G.722.1 Annex C)
|
||||
|
||||
Open Source Software Licensing
|
||||
Each open source software component utilized by this product is subject to its own copyright and licensing terms, as listed below.
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue