Merge branch 'master' into linux_fltk
commit
0953b6b646
|
|
@ -58,6 +58,7 @@ indra/newview/search_history.txt
|
|||
indra/newview/teleport_history.txt
|
||||
indra/newview/typed_locations.txt
|
||||
indra/newview/vivox-runtime
|
||||
indra/newview/skins/default/html/common/equirectangular/js
|
||||
indra/server-linux-*
|
||||
indra/temp
|
||||
indra/test/linden_file.dat
|
||||
|
|
|
|||
|
|
@ -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 ####
|
||||
|
|
|
|||
604
autobuild.xml
604
autobuild.xml
File diff suppressed because it is too large
Load Diff
50
build.sh
50
build.sh
|
|
@ -16,6 +16,29 @@
|
|||
# * The special style in which python is invoked is intentional to permit
|
||||
# use of a native python install on windows - which requires paths in DOS form
|
||||
|
||||
retry_cmd()
|
||||
{
|
||||
max_attempts="$1"; shift
|
||||
initial_wait="$1"; shift
|
||||
attempt_num=1
|
||||
echo "trying" "$@"
|
||||
until "$@"
|
||||
do
|
||||
if ((attempt_num==max_attempts))
|
||||
then
|
||||
echo "Last attempt $attempt_num failed"
|
||||
return 1
|
||||
else
|
||||
wait_time=$(($attempt_num*$initial_wait))
|
||||
echo "Attempt $attempt_num failed. Trying again in $wait_time seconds..."
|
||||
sleep $wait_time
|
||||
attempt_num=$(($attempt_num+1))
|
||||
fi
|
||||
done
|
||||
echo "succeeded"
|
||||
return 0
|
||||
}
|
||||
|
||||
build_dir_Darwin()
|
||||
{
|
||||
echo build-darwin-x86_64
|
||||
|
|
@ -275,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=
|
||||
|
|
@ -444,7 +483,7 @@ then
|
|||
succeeded=$build_coverity
|
||||
else
|
||||
# Upload base package.
|
||||
python_cmd "$helpers/codeticket.py" addoutput Installer "$package" \
|
||||
retry_cmd 4 30 python_cmd "$helpers/codeticket.py" addoutput Installer "$package" \
|
||||
|| fatal "Upload of installer failed"
|
||||
wait_for_codeticket
|
||||
|
||||
|
|
@ -454,7 +493,7 @@ then
|
|||
package=$(installer_$arch "$package_id")
|
||||
if [ x"$package" != x ]
|
||||
then
|
||||
python_cmd "$helpers/codeticket.py" addoutput "Installer $package_id" "$package" \
|
||||
retry_cmd 4 30 python_cmd "$helpers/codeticket.py" addoutput "Installer $package_id" "$package" \
|
||||
|| fatal "Upload of installer $package_id failed"
|
||||
wait_for_codeticket
|
||||
else
|
||||
|
|
@ -468,7 +507,7 @@ then
|
|||
if [ "${RELEASE_CRASH_REPORTING:-}" != "OFF" ]
|
||||
then
|
||||
# Upload crash reporter file
|
||||
python_cmd "$helpers/codeticket.py" addoutput "Symbolfile" "$VIEWER_SYMBOL_FILE" \
|
||||
retry_cmd 4 30 python_cmd "$helpers/codeticket.py" addoutput "Symbolfile" "$VIEWER_SYMBOL_FILE" \
|
||||
|| fatal "Upload of symbolfile failed"
|
||||
wait_for_codeticket
|
||||
fi
|
||||
|
|
@ -478,10 +517,7 @@ then
|
|||
if [ -r "$build_dir/llphysicsextensions_package" ]
|
||||
then
|
||||
llphysicsextensions_package=$(cat $build_dir/llphysicsextensions_package)
|
||||
# This next upload is a frequent failure; see if giving the last one some time helps
|
||||
# JJ is making changes to Codeticket that we hope will eliminate this failure soon
|
||||
sleep 300
|
||||
python_cmd "$helpers/codeticket.py" addoutput "Physics Extensions Package" "$llphysicsextensions_package" --private \
|
||||
retry_cmd 4 30 python_cmd "$helpers/codeticket.py" addoutput "Physics Extensions Package" "$llphysicsextensions_package" --private \
|
||||
|| fatal "Upload of physics extensions package failed"
|
||||
fi
|
||||
fi
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -228,8 +228,15 @@ Ansariel Hiller
|
|||
SL-13364
|
||||
SL-13858
|
||||
SL-13697
|
||||
SL-14939
|
||||
SL-14940
|
||||
SL-14941
|
||||
SL-13395
|
||||
SL-3136
|
||||
SL-15200
|
||||
SL-15226
|
||||
SL-15227
|
||||
SL-15398
|
||||
Aralara Rajal
|
||||
Arare Chantilly
|
||||
CHUIBUG-191
|
||||
|
|
@ -272,6 +279,7 @@ Beq Janus
|
|||
SL-13583
|
||||
SL-14766
|
||||
SL-14927
|
||||
SL-11300
|
||||
Beth Walcher
|
||||
Bezilon Kasei
|
||||
Biancaluce Robbiani
|
||||
|
|
@ -812,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 |
|
|
@ -154,18 +154,6 @@ if (USE_BUGSPLAT)
|
|||
endif (BUGSPLAT_DB)
|
||||
else (USE_BUGSPLAT)
|
||||
message(STATUS "Not building with BugSplat")
|
||||
if (LINUX)
|
||||
add_subdirectory(${VIEWER_PREFIX}linux_crash_logger)
|
||||
#<FS:TS> Huh? Where'd that target come from?
|
||||
#add_dependencies(viewer linux-crash-logger-strip-target)
|
||||
elseif (DARWIN)
|
||||
add_subdirectory(${VIEWER_PREFIX}mac_crash_logger)
|
||||
add_dependencies(viewer mac-crash-logger)
|
||||
elseif (WINDOWS)
|
||||
add_subdirectory(${VIEWER_PREFIX}win_crash_logger)
|
||||
# add_dependencies(viewer windows-setup windows-crash-logger)
|
||||
add_dependencies(viewer windows-crash-logger)
|
||||
endif (LINUX)
|
||||
endif (USE_BUGSPLAT)
|
||||
|
||||
add_subdirectory(${VIEWER_PREFIX}newview)
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ elseif (DARWIN)
|
|||
message(FATAL_ERROR "AppKit not found")
|
||||
endif()
|
||||
|
||||
FIND_LIBRARY(CEF_LIBRARY "Chromium Embedded Framework" ${ARCH_PREBUILT_DIRS_RELEASE})
|
||||
set(CEF_LIBRARY "'${ARCH_PREBUILT_DIRS_RELEASE}/Chromium\ Embedded\ Framework.framework'")
|
||||
if (NOT CEF_LIBRARY)
|
||||
message(FATAL_ERROR "CEF not found")
|
||||
endif()
|
||||
|
|
@ -33,7 +33,7 @@ elseif (DARWIN)
|
|||
${ARCH_PREBUILT_DIRS_RELEASE}/libcef_dll_wrapper.a
|
||||
${ARCH_PREBUILT_DIRS_RELEASE}/libdullahan.a
|
||||
${APPKIT_LIBRARY}
|
||||
${CEF_LIBRARY}
|
||||
"-F ${CEF_LIBRARY}"
|
||||
)
|
||||
|
||||
elseif (LINUX)
|
||||
|
|
|
|||
|
|
@ -30,7 +30,6 @@ set(cmake_SOURCE_FILES
|
|||
FindBerkeleyDB.cmake
|
||||
FindFMODSTUDIO.cmake
|
||||
FindGLH.cmake
|
||||
FindGoogleBreakpad.cmake
|
||||
FindHUNSPELL.cmake
|
||||
FindJsonCpp.cmake
|
||||
FindNDOF.cmake
|
||||
|
|
@ -45,7 +44,6 @@ set(cmake_SOURCE_FILES
|
|||
GLH.cmake
|
||||
GLOD.cmake
|
||||
## GStreamer010Plugin.cmake
|
||||
GoogleBreakpad.cmake
|
||||
GoogleMock.cmake
|
||||
Growl.cmake
|
||||
Havok.cmake
|
||||
|
|
|
|||
|
|
@ -56,8 +56,6 @@ if(WINDOWS)
|
|||
libapr-1.dll
|
||||
libaprutil-1.dll
|
||||
libapriconv-1.dll
|
||||
ssleay32.dll
|
||||
libeay32.dll
|
||||
nghttp2.dll
|
||||
glod.dll
|
||||
libhunspell.dll
|
||||
|
|
@ -70,6 +68,15 @@ if(WINDOWS)
|
|||
endif (NOT USE_KDU)
|
||||
# </FS:Ansariel>
|
||||
|
||||
# OpenSSL
|
||||
if(ADDRESS_SIZE EQUAL 64)
|
||||
set(release_files ${release_files} libcrypto-1_1-x64.dll)
|
||||
set(release_files ${release_files} libssl-1_1-x64.dll)
|
||||
else(ADDRESS_SIZE EQUAL 64)
|
||||
set(release_files ${release_files} libcrypto-1_1.dll)
|
||||
set(release_files ${release_files} libssl-1_1.dll)
|
||||
endif(ADDRESS_SIZE EQUAL 64)
|
||||
|
||||
# Filenames are different for 32/64 bit BugSplat file and we don't
|
||||
# have any control over them so need to branch.
|
||||
if (USE_BUGSPLAT)
|
||||
|
|
@ -190,7 +197,6 @@ elseif(DARWIN)
|
|||
libapr-1.dylib
|
||||
libaprutil-1.0.dylib
|
||||
libaprutil-1.dylib
|
||||
libexception_handler.dylib
|
||||
${EXPAT_COPY}
|
||||
libGLOD.dylib
|
||||
libhunspell-1.3.0.dylib
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
# -*- cmake -*-
|
||||
use_prebuilt_binary(cubemaptoequirectangular)
|
||||
|
||||
# Main JS file
|
||||
#configure_file("${AUTOBUILD_INSTALL_DIR}/js/CubemapToEquirectangular.js" "${CMAKE_SOURCE_DIR}/newview/skins/default/html/common/equirectangular/js/CubemapToEquirectangular.js" COPYONLY)
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
# -*- cmake -*-
|
||||
|
||||
# - Find Google BreakPad
|
||||
# Find the Google BreakPad includes and library
|
||||
# This module defines
|
||||
# BREAKPAD_EXCEPTION_HANDLER_INCLUDE_DIR, where to find exception_handler.h, etc.
|
||||
# BREAKPAD_EXCEPTION_HANDLER_LIBRARIES, the libraries needed to use Google BreakPad.
|
||||
# BREAKPAD_EXCEPTION_HANDLER_FOUND, If false, do not try to use Google BreakPad.
|
||||
# also defined, but not for general use are
|
||||
# BREAKPAD_EXCEPTION_HANDLER_LIBRARY, where to find the Google BreakPad library.
|
||||
|
||||
# LL code uses "google_breakpad" path prefix, while google breakpad headers don't use a prefix. Find and add both paths to the correct variable.
|
||||
FIND_PATH(BREAKPAD_EXCEPTION_HANDLER_INCLUDE_DIR google_breakpad/exception_handler.h)
|
||||
FIND_PATH(BREAKPAD_EXCEPTION_HANDLER_INCLUDE_DIRS exception_handler.h PATH_SUFFIXES google_breakpad)
|
||||
SET(BREAKPAD_INCLUDE_DIRECTORIES ${BREAKPAD_EXCEPTION_HANDLER_INCLUDE_DIR} ${BREAKPAD_EXCEPTION_HANDLER_INCLUDE_DIRS})
|
||||
|
||||
SET(BREAKPAD_EXCEPTION_HANDLER_NAMES ${BREAKPAD_EXCEPTION_HANDLER_NAMES} breakpad_client)
|
||||
FIND_LIBRARY(BREAKPAD_EXCEPTION_HANDLER_LIBRARY
|
||||
NAMES ${BREAKPAD_EXCEPTION_HANDLER_NAMES}
|
||||
)
|
||||
|
||||
IF (BREAKPAD_EXCEPTION_HANDLER_LIBRARY AND BREAKPAD_EXCEPTION_HANDLER_INCLUDE_DIR)
|
||||
SET(BREAKPAD_EXCEPTION_HANDLER_LIBRARIES ${BREAKPAD_EXCEPTION_HANDLER_LIBRARY})
|
||||
SET(BREAKPAD_EXCEPTION_HANDLER_FOUND "YES")
|
||||
ELSE (BREAKPAD_EXCEPTION_HANDLER_LIBRARY AND BREAKPAD_EXCEPTION_HANDLER_INCLUDE_DIR)
|
||||
SET(BREAKPAD_EXCEPTION_HANDLER_FOUND "NO")
|
||||
ENDIF (BREAKPAD_EXCEPTION_HANDLER_LIBRARY AND BREAKPAD_EXCEPTION_HANDLER_INCLUDE_DIR)
|
||||
|
||||
|
||||
IF (BREAKPAD_EXCEPTION_HANDLER_FOUND)
|
||||
IF (NOT BREAKPAD_EXCEPTION_HANDLER_FIND_QUIETLY)
|
||||
MESSAGE(STATUS "Found Google BreakPad: ${BREAKPAD_EXCEPTION_HANDLER_LIBRARIES}")
|
||||
MESSAGE(STATUS "Found Google BreakPad headers in: ${BREAKPAD_INCLUDE_DIRECTORIES}")
|
||||
ENDIF (NOT BREAKPAD_EXCEPTION_HANDLER_FIND_QUIETLY)
|
||||
ELSE (BREAKPAD_EXCEPTION_HANDLER_FOUND)
|
||||
IF (BREAKPAD_EXCEPTION_HANDLER_FIND_REQUIRED)
|
||||
MESSAGE(FATAL_ERROR "Could not find Google BreakPad library")
|
||||
ENDIF (BREAKPAD_EXCEPTION_HANDLER_FIND_REQUIRED)
|
||||
ENDIF (BREAKPAD_EXCEPTION_HANDLER_FOUND)
|
||||
|
||||
MARK_AS_ADVANCED(
|
||||
BREAKPAD_EXCEPTION_HANDLER_LIBRARY
|
||||
BREAKPAD_EXCEPTION_HANDLER_INCLUDE_DIR
|
||||
)
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
# -*- cmake -*-
|
||||
include(Prebuilt)
|
||||
|
||||
#if (USESYSTEMLIBS)
|
||||
# set(BREAKPAD_EXCEPTION_HANDLER_FIND_REQUIRED ON)
|
||||
# include(FindGoogleBreakpad)
|
||||
#else (USESYSTEMLIBS)
|
||||
use_prebuilt_binary(google_breakpad)
|
||||
if (DARWIN)
|
||||
set(BREAKPAD_EXCEPTION_HANDLER_LIBRARIES exception_handler)
|
||||
endif (DARWIN)
|
||||
if (LINUX)
|
||||
set(BREAKPAD_EXCEPTION_HANDLER_LIBRARIES breakpad_client)
|
||||
endif (LINUX)
|
||||
if (WINDOWS)
|
||||
set(BREAKPAD_EXCEPTION_HANDLER_LIBRARIES exception_handler crash_generation_client crash_generation_server common)
|
||||
endif (WINDOWS)
|
||||
# yes, this does look dumb, no, it's not incorrect
|
||||
#
|
||||
set(BREAKPAD_INCLUDE_DIRECTORIES "${LIBS_PREBUILT_DIR}/include/google_breakpad" "${LIBS_PREBUILT_DIR}/include/google_breakpad/google_breakpad")
|
||||
#endif (USESYSTEMLIBS)
|
||||
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
# -*- cmake -*-
|
||||
use_prebuilt_binary(jpegencoderbasic)
|
||||
|
||||
# Main JS file
|
||||
#configure_file("${AUTOBUILD_INSTALL_DIR}/js/jpeg_encoder_basic.js" "${CMAKE_SOURCE_DIR}/newview/skins/default/html/common/equirectangular/js/jpeg_encoder_basic.js" COPYONLY)
|
||||
|
|
@ -9,7 +9,7 @@ if (USESYSTEMLIBS)
|
|||
else (USESYSTEMLIBS)
|
||||
use_prebuilt_binary(openssl)
|
||||
if (WINDOWS)
|
||||
set(OPENSSL_LIBRARIES ssleay32 libeay32)
|
||||
set(OPENSSL_LIBRARIES libssl libcrypto)
|
||||
else (WINDOWS)
|
||||
set(OPENSSL_LIBRARIES ssl crypto)
|
||||
endif (WINDOWS)
|
||||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,8 @@
|
|||
# -*- cmake -*-
|
||||
use_prebuilt_binary(threejs)
|
||||
|
||||
# Main three.js file
|
||||
#configure_file("${AUTOBUILD_INSTALL_DIR}/js/three.min.js" "${CMAKE_SOURCE_DIR}/newview/skins/default/html/common/equirectangular/js/three.min.js" COPYONLY)
|
||||
|
||||
# Controls to move around the scene using mouse or keyboard
|
||||
#configure_file("${AUTOBUILD_INSTALL_DIR}/js/OrbitControls.js" "${CMAKE_SOURCE_DIR}/newview/skins/default/html/common/equirectangular/js/OrbitControls.js" COPYONLY)
|
||||
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ include(Linking)
|
|||
include(Boost)
|
||||
include(LLSharedLibs)
|
||||
include(JsonCpp)
|
||||
include(GoogleBreakpad)
|
||||
include(Copy3rdPartyLibs)
|
||||
include(ZLIB)
|
||||
include(URIPARSER)
|
||||
|
|
@ -19,7 +18,6 @@ include_directories(
|
|||
${LLCOMMON_INCLUDE_DIRS}
|
||||
${JSONCPP_INCLUDE_DIR}
|
||||
${ZLIB_INCLUDE_DIRS}
|
||||
${BREAKPAD_INCLUDE_DIRECTORIES}
|
||||
${URIPARSER_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
|
|
@ -210,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
|
||||
|
|
@ -258,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
|
||||
|
|
@ -329,7 +328,6 @@ endif(NOT WORD_SIZE EQUAL 32)
|
|||
|
||||
target_link_libraries(
|
||||
llcommon
|
||||
${BREAKPAD_EXCEPTION_HANDLER_LIBRARIES}
|
||||
${APRUTIL_LIBRARIES}
|
||||
${APR_LIBRARIES}
|
||||
${EXPAT_LIBRARIES}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -47,8 +47,6 @@
|
|||
#include "llstring.h"
|
||||
#include "lleventtimer.h"
|
||||
|
||||
#include "google_breakpad/exception_handler.h"
|
||||
|
||||
#include "stringize.h"
|
||||
#include "llcleanup.h"
|
||||
#include "llevents.h"
|
||||
|
|
@ -64,12 +62,6 @@
|
|||
|
||||
LONG WINAPI default_windows_exception_handler(struct _EXCEPTION_POINTERS *exception_infop);
|
||||
BOOL ConsoleCtrlHandler(DWORD fdwCtrlType);
|
||||
bool windows_post_minidump_callback(const wchar_t* dump_path,
|
||||
const wchar_t* minidump_id,
|
||||
void* context,
|
||||
EXCEPTION_POINTERS* exinfo,
|
||||
MDRawAssertionInfo* assertion,
|
||||
bool succeeded);
|
||||
#else
|
||||
# include <signal.h>
|
||||
# include <unistd.h> // for fork()
|
||||
|
|
@ -77,10 +69,6 @@ void setup_signals();
|
|||
void default_unix_signal_handler(int signum, siginfo_t *info, void *);
|
||||
|
||||
#if LL_LINUX
|
||||
#include "google_breakpad/minidump_descriptor.h"
|
||||
static bool unix_minidump_callback(const google_breakpad::MinidumpDescriptor& minidump_desc,
|
||||
void* context,
|
||||
bool succeeded);
|
||||
#else
|
||||
// Called by breakpad exception handler after the minidump has been generated.
|
||||
bool unix_post_minidump_callback(const char *dump_dir,
|
||||
|
|
@ -115,7 +103,8 @@ BOOL LLApp::sDisableCrashlogger = FALSE;
|
|||
BOOL LLApp::sLogInSignal = FALSE;
|
||||
|
||||
// static
|
||||
LLApp::EAppStatus LLApp::sStatus = LLApp::APP_STATUS_STOPPED; // Keeps track of application status
|
||||
// Keeps track of application status
|
||||
LLScalarCond<LLApp::EAppStatus> LLApp::sStatus{LLApp::APP_STATUS_STOPPED};
|
||||
LLAppErrorHandler LLApp::sErrorHandler = NULL;
|
||||
BOOL LLApp::sErrorThreadRunning = FALSE;
|
||||
|
||||
|
|
@ -148,8 +137,6 @@ void LLApp::commonCtor()
|
|||
|
||||
// Set the application to this instance.
|
||||
sApplication = this;
|
||||
|
||||
mExceptionHandler = 0;
|
||||
|
||||
// initialize the buffer to write the minidump filename to
|
||||
// (this is used to avoid allocating memory in the crash handler)
|
||||
|
|
@ -179,8 +166,6 @@ LLApp::~LLApp()
|
|||
delete mThreadErrorp;
|
||||
mThreadErrorp = NULL;
|
||||
}
|
||||
|
||||
if(mExceptionHandler != 0) delete mExceptionHandler;
|
||||
|
||||
SUBSYSTEM_CLEANUP_DBG(LLCommon);
|
||||
}
|
||||
|
|
@ -396,140 +381,18 @@ void LLApp::setupErrorHandling(bool second_instance)
|
|||
|
||||
#if LL_WINDOWS
|
||||
|
||||
#if LL_SEND_CRASH_REPORTS && ! defined(LL_BUGSPLAT)
|
||||
EnableCrashingOnCrashes();
|
||||
|
||||
// This sets a callback to handle w32 signals to the console window.
|
||||
// The viewer shouldn't be affected, sicne its a windowed app.
|
||||
SetConsoleCtrlHandler( (PHANDLER_ROUTINE) ConsoleCtrlHandler, TRUE);
|
||||
|
||||
// Install the Google Breakpad crash handler for Windows
|
||||
if(mExceptionHandler == 0)
|
||||
{
|
||||
if ( second_instance ) //BUG-5707 Firing teleport from a web browser causes second
|
||||
{
|
||||
mExceptionHandler = new google_breakpad::ExceptionHandler(
|
||||
L"C:\\Temp\\",
|
||||
0, //No filter
|
||||
windows_post_minidump_callback,
|
||||
0,
|
||||
google_breakpad::ExceptionHandler::HANDLER_ALL); //No custom client info.
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS() << "adding breakpad exception handler" << LL_ENDL;
|
||||
|
||||
std::wstring wpipe_name;
|
||||
wpipe_name = mCrashReportPipeStr + wstringize(getPid());
|
||||
|
||||
const std::wstring wdump_path(utf8str_to_utf16str(mDumpPath));
|
||||
|
||||
int retries = 30;
|
||||
for (; retries > 0; --retries)
|
||||
{
|
||||
if (mExceptionHandler != 0) delete mExceptionHandler;
|
||||
U32 maskMiniDumpType = MiniDumpNormal | MiniDumpFilterModulePaths;
|
||||
mExceptionHandler = new google_breakpad::ExceptionHandler(
|
||||
wdump_path,
|
||||
NULL, //No filter
|
||||
windows_post_minidump_callback,
|
||||
0,
|
||||
google_breakpad::ExceptionHandler::HANDLER_ALL,
|
||||
// MiniDumpNormal, //Generate a 'normal' minidump.
|
||||
(MINIDUMP_TYPE)maskMiniDumpType, // <FS:ND/> Pass custom minidump type from prefs to breakpad.
|
||||
wpipe_name.c_str(),
|
||||
NULL); //No custom client info.
|
||||
if (mExceptionHandler->IsOutOfProcess())
|
||||
{
|
||||
LL_INFOS("CRASHREPORT") << "Successfully attached to Out of Process exception handler." << LL_ENDL;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS("CRASHREPORT") << "Unable to attach to Out of Process exception handler. " << retries << " retries remaining." << LL_ENDL;
|
||||
::Sleep(100); //Wait a tick and try again.
|
||||
}
|
||||
}
|
||||
|
||||
if (retries == 0) LL_WARNS("CRASHREPORT") << "Unable to attach to Out of Process exception handler." << LL_ENDL;
|
||||
}
|
||||
|
||||
if (mExceptionHandler)
|
||||
{
|
||||
mExceptionHandler->set_handle_debug_exceptions(true);
|
||||
}
|
||||
}
|
||||
#endif // LL_SEND_CRASH_REPORTS && ! defined(LL_BUGSPLAT)
|
||||
#else // ! LL_WINDOWS
|
||||
|
||||
#if defined(LL_BUGSPLAT)
|
||||
// Don't install our own signal handlers -- BugSplat needs to hook them,
|
||||
// or it's completely ineffectual.
|
||||
bool installHandler = false;
|
||||
|
||||
#else // ! LL_BUGSPLAT
|
||||
//
|
||||
// Start up signal handling.
|
||||
//
|
||||
// There are two different classes of signals. Synchronous signals are delivered to a specific
|
||||
// thread, asynchronous signals can be delivered to any thread (in theory)
|
||||
//
|
||||
setup_signals();
|
||||
|
||||
// Add google breakpad exception handler configured for Darwin/Linux.
|
||||
bool installHandler = true;
|
||||
#if ! defined(LL_BUGSPLAT)
|
||||
//
|
||||
// Start up signal handling.
|
||||
//
|
||||
// There are two different classes of signals. Synchronous signals are delivered to a specific
|
||||
// thread, asynchronous signals can be delivered to any thread (in theory)
|
||||
//
|
||||
setup_signals();
|
||||
#endif // ! LL_BUGSPLAT
|
||||
|
||||
#if LL_DARWIN
|
||||
// For the special case of Darwin, we do not want to install the handler if
|
||||
// the process is being debugged as the app will exit with value ABRT (6) if
|
||||
// we do. Unfortunately, the code below which performs that test relies on
|
||||
// the structure kinfo_proc which has been tagged by apple as an unstable
|
||||
// API. We disable this test for shipping versions to avoid conflicts with
|
||||
// future releases of Darwin. This test is really only needed for developers
|
||||
// starting the app from a debugger anyway.
|
||||
#ifndef LL_RELEASE_FOR_DOWNLOAD
|
||||
int mib[4];
|
||||
mib[0] = CTL_KERN;
|
||||
mib[1] = KERN_PROC;
|
||||
mib[2] = KERN_PROC_PID;
|
||||
mib[3] = getpid();
|
||||
|
||||
struct kinfo_proc info;
|
||||
memset(&info, 0, sizeof(info));
|
||||
|
||||
size_t size = sizeof(info);
|
||||
int result = sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, NULL, 0);
|
||||
if((result == 0) || (errno == ENOMEM))
|
||||
{
|
||||
// P_TRACED flag is set, so this process is being debugged; do not install
|
||||
// the handler
|
||||
if(info.kp_proc.p_flag & P_TRACED) installHandler = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Failed to discover if the process is being debugged; default to
|
||||
// installing the handler.
|
||||
installHandler = true;
|
||||
}
|
||||
#endif // ! LL_RELEASE_FOR_DOWNLOAD
|
||||
|
||||
if(installHandler && (mExceptionHandler == 0))
|
||||
{
|
||||
mExceptionHandler = new google_breakpad::ExceptionHandler(mDumpPath, 0, &unix_post_minidump_callback, 0, true, 0);
|
||||
}
|
||||
#elif LL_LINUX
|
||||
if(installHandler && (mExceptionHandler == 0))
|
||||
{
|
||||
if (mDumpPath.empty())
|
||||
{
|
||||
mDumpPath = "/tmp";
|
||||
}
|
||||
google_breakpad::MinidumpDescriptor desc(mDumpPath);
|
||||
mExceptionHandler = new google_breakpad::ExceptionHandler(desc, NULL, unix_minidump_callback, NULL, true, -1);
|
||||
}
|
||||
#endif // LL_LINUX
|
||||
|
||||
#endif // ! LL_WINDOWS
|
||||
|
||||
#ifdef LL_BUGSPLAT
|
||||
|
|
@ -587,7 +450,8 @@ static std::map<LLApp::EAppStatus, const char*> statusDesc
|
|||
// static
|
||||
void LLApp::setStatus(EAppStatus status)
|
||||
{
|
||||
sStatus = status;
|
||||
// notify everyone waiting on sStatus any time its value changes
|
||||
sStatus.set_all(status);
|
||||
|
||||
// This can also happen very late in the application lifecycle -- don't
|
||||
// resurrect a deleted LLSingleton
|
||||
|
|
@ -617,29 +481,10 @@ void LLApp::setError()
|
|||
setStatus(APP_STATUS_ERROR);
|
||||
}
|
||||
|
||||
void LLApp::setMiniDumpDir(const std::string &path)
|
||||
// static
|
||||
bool LLApp::sleep(F32Milliseconds duration)
|
||||
{
|
||||
if (path.empty())
|
||||
{
|
||||
mDumpPath = "/tmp";
|
||||
}
|
||||
else
|
||||
{
|
||||
mDumpPath = path;
|
||||
}
|
||||
|
||||
if(mExceptionHandler == 0) return;
|
||||
#ifdef LL_WINDOWS
|
||||
std::wstring buffer(utf8str_to_utf16str(mDumpPath));
|
||||
if (buffer.size() > MAX_MINDUMP_PATH_LENGTH) buffer.resize(MAX_MINDUMP_PATH_LENGTH);
|
||||
mExceptionHandler->set_dump_path(buffer);
|
||||
#elif LL_LINUX
|
||||
//google_breakpad::MinidumpDescriptor desc("/tmp"); //path works in debug fails in production inside breakpad lib so linux gets a little less stack reporting until it is patched.
|
||||
google_breakpad::MinidumpDescriptor desc(mDumpPath); //path works in debug fails in production inside breakpad lib so linux gets a little less stack reporting until it is patched.
|
||||
mExceptionHandler->set_minidump_descriptor(desc);
|
||||
#else
|
||||
mExceptionHandler->set_dump_path(mDumpPath);
|
||||
#endif
|
||||
return ! sStatus.wait_for_unequal(duration, APP_STATUS_RUNNING);
|
||||
}
|
||||
|
||||
void LLApp::setDebugFileNames(const std::string &path)
|
||||
|
|
@ -650,8 +495,6 @@ void LLApp::setDebugFileNames(const std::string &path)
|
|||
|
||||
void LLApp::writeMiniDump()
|
||||
{
|
||||
if(mExceptionHandler == 0) return;
|
||||
mExceptionHandler->WriteMinidump();
|
||||
}
|
||||
|
||||
// static
|
||||
|
|
@ -676,28 +519,28 @@ void LLApp::setStopped()
|
|||
// static
|
||||
bool LLApp::isStopped()
|
||||
{
|
||||
return (APP_STATUS_STOPPED == sStatus);
|
||||
return (APP_STATUS_STOPPED == sStatus.get());
|
||||
}
|
||||
|
||||
|
||||
// static
|
||||
bool LLApp::isRunning()
|
||||
{
|
||||
return (APP_STATUS_RUNNING == sStatus);
|
||||
return (APP_STATUS_RUNNING == sStatus.get());
|
||||
}
|
||||
|
||||
|
||||
// static
|
||||
bool LLApp::isError()
|
||||
{
|
||||
return (APP_STATUS_ERROR == sStatus);
|
||||
return (APP_STATUS_ERROR == sStatus.get());
|
||||
}
|
||||
|
||||
|
||||
// static
|
||||
bool LLApp::isQuitting()
|
||||
{
|
||||
return (APP_STATUS_QUITTING == sStatus);
|
||||
return (APP_STATUS_QUITTING == sStatus.get());
|
||||
}
|
||||
|
||||
// static
|
||||
|
|
@ -708,13 +551,6 @@ bool LLApp::isExiting()
|
|||
|
||||
void LLApp::disableCrashlogger()
|
||||
{
|
||||
// Disable Breakpad exception handler.
|
||||
if (mExceptionHandler != 0)
|
||||
{
|
||||
delete mExceptionHandler;
|
||||
mExceptionHandler = 0;
|
||||
}
|
||||
|
||||
sDisableCrashlogger = TRUE;
|
||||
}
|
||||
|
||||
|
|
@ -1022,48 +858,6 @@ void default_unix_signal_handler(int signum, siginfo_t *info, void *)
|
|||
}
|
||||
}
|
||||
|
||||
#if LL_LINUX
|
||||
bool unix_minidump_callback(const google_breakpad::MinidumpDescriptor& minidump_desc, void* context, bool succeeded)
|
||||
{
|
||||
// Copy minidump file path into fixed buffer in the app instance to avoid
|
||||
// heap allocations in a crash handler.
|
||||
|
||||
// path format: <dump_dir>/<minidump_id>.dmp
|
||||
|
||||
//HACK: *path points to the buffer in getMiniDumpFilename which has already allocated space
|
||||
//to avoid doing allocation during crash.
|
||||
char * path = LLApp::instance()->getMiniDumpFilename();
|
||||
int dir_path_len = strlen(path);
|
||||
|
||||
// The path must not be truncated.
|
||||
S32 remaining = LLApp::MAX_MINDUMP_PATH_LENGTH - dir_path_len;
|
||||
|
||||
llassert( (remaining - strlen(minidump_desc.path())) > 5);
|
||||
|
||||
path += dir_path_len;
|
||||
|
||||
if (dir_path_len > 0 && path[-1] != '/')
|
||||
{
|
||||
*path++ = '/';
|
||||
--remaining;
|
||||
}
|
||||
|
||||
strncpy(path, minidump_desc.path(), remaining);
|
||||
|
||||
LL_INFOS("CRASHREPORT") << "generated minidump: " << LLApp::instance()->getMiniDumpFilename() << LL_ENDL;
|
||||
LLApp::runErrorHandler();
|
||||
|
||||
#ifndef LL_RELEASE_FOR_DOWNLOAD
|
||||
clear_signals();
|
||||
return false;
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
bool unix_post_minidump_callback(const char *dump_dir,
|
||||
const char *minidump_id,
|
||||
void *context, bool succeeded)
|
||||
|
|
@ -1108,129 +902,3 @@ bool unix_post_minidump_callback(const char *dump_dir,
|
|||
}
|
||||
#endif // !WINDOWS
|
||||
|
||||
#ifdef LL_WINDOWS
|
||||
|
||||
// <FS:ND> Helper function to convert a wchar_t string into an UTF8 buffer
|
||||
namespace nd
|
||||
{
|
||||
namespace strings
|
||||
{
|
||||
inline bool convertString( wchar_t const *aIn, char *&aOut, S32 &aLen )
|
||||
{
|
||||
char tmpBuffer[8];
|
||||
S32 i(0), j(0);
|
||||
|
||||
while( *aIn )
|
||||
{
|
||||
i = wchar_to_utf8chars( *aIn++, tmpBuffer );
|
||||
|
||||
if( i < aLen )
|
||||
{
|
||||
j = 0;
|
||||
while( j < i )
|
||||
{
|
||||
*aOut++ = tmpBuffer[ j++ ];
|
||||
--aLen;
|
||||
}
|
||||
}
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// </FS:ND>
|
||||
|
||||
bool windows_post_minidump_callback(const wchar_t* dump_path,
|
||||
const wchar_t* minidump_id,
|
||||
void* context,
|
||||
EXCEPTION_POINTERS* exinfo,
|
||||
MDRawAssertionInfo* assertion,
|
||||
bool succeeded)
|
||||
{
|
||||
// <FS:ND> Convert all path to UTF8 and not MBCS. Having some path in MBCS and some in UTF8 is a source of great joy
|
||||
// and bugs. Stick with one standard, that is UTF8.
|
||||
|
||||
// char * path = LLApp::instance()->getMiniDumpFilename();
|
||||
// S32 remaining = LLApp::MAX_MINDUMP_PATH_LENGTH;
|
||||
// size_t bytesUsed;
|
||||
|
||||
// LL_INFOS("MINIDUMPCALLBACK") << "Dump file was generated." << LL_ENDL;
|
||||
// bytesUsed = wcstombs(path, dump_path, static_cast<size_t>(remaining));
|
||||
// remaining -= bytesUsed;
|
||||
// path += bytesUsed;
|
||||
// if(remaining > 0 && bytesUsed > 0 && path[-1] != '\\')
|
||||
// {
|
||||
// *path++ = '\\';
|
||||
// --remaining;
|
||||
// }
|
||||
// if(remaining > 0)
|
||||
// {
|
||||
// bytesUsed = wcstombs(path, minidump_id, static_cast<size_t>(remaining));
|
||||
// remaining -= bytesUsed;
|
||||
// path += bytesUsed;
|
||||
// }
|
||||
// if(remaining > 0)
|
||||
// {
|
||||
// strncpy(path, ".dmp", remaining);
|
||||
// }
|
||||
|
||||
char *pOut( LLApp::instance()->getMiniDumpFilename() );
|
||||
bool hasOverflow( false );
|
||||
S32 bufferLength( LLApp::MAX_MINDUMP_PATH_LENGTH );
|
||||
|
||||
hasOverflow = nd::strings::convertString( dump_path, pOut, bufferLength );
|
||||
if( !hasOverflow && bufferLength < LLApp::MAX_MINDUMP_PATH_LENGTH && bufferLength > 1 && pOut[-1] != '\\' && pOut[-1] != '/' )
|
||||
{
|
||||
*pOut++ = '\\';
|
||||
--bufferLength;
|
||||
}
|
||||
|
||||
if( !hasOverflow )
|
||||
hasOverflow = nd::strings::convertString( minidump_id, pOut, bufferLength );
|
||||
|
||||
if( !hasOverflow && bufferLength >= 5 )
|
||||
{
|
||||
pOut[0] = '.';
|
||||
pOut[1] = 'd';
|
||||
pOut[2] = 'm';
|
||||
pOut[3] = 'p';
|
||||
pOut[4] = 0;
|
||||
}
|
||||
else if( hasOverflow )
|
||||
LLApp::instance()->getMiniDumpFilename()[ 0 ] = 0;
|
||||
|
||||
// </FS:ND>
|
||||
|
||||
LL_INFOS("CRASHREPORT") << "generated minidump: " << LLApp::instance()->getMiniDumpFilename() << LL_ENDL;
|
||||
// *NOTE:Mani - this code is stolen from LLApp, where its never actually used.
|
||||
//OSMessageBox("Attach Debugger Now", "Error", OSMB_OK);
|
||||
// *TODO: Translate the signals/exceptions into cross-platform stuff
|
||||
// Windows implementation
|
||||
LL_INFOS() << "Entering Windows Exception Handler..." << LL_ENDL;
|
||||
|
||||
if (LLApp::isError())
|
||||
{
|
||||
LL_WARNS() << "Got another fatal signal while in the error handler, die now!" << LL_ENDL;
|
||||
}
|
||||
|
||||
// Flag status to error, so thread_error starts its work
|
||||
LLApp::setError();
|
||||
|
||||
// Block in the exception handler until the app has stopped
|
||||
// This is pretty sketchy, but appears to work just fine
|
||||
while (!LLApp::isStopped())
|
||||
{
|
||||
ms_sleep(10);
|
||||
}
|
||||
|
||||
#ifndef LL_RELEASE_FOR_DOWNLOAD
|
||||
return false;
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -28,9 +28,11 @@
|
|||
#define LL_LLAPP_H
|
||||
|
||||
#include <map>
|
||||
#include "llcond.h"
|
||||
#include "llrun.h"
|
||||
#include "llsd.h"
|
||||
#include <atomic>
|
||||
#include <chrono>
|
||||
// Forward declarations
|
||||
class LLErrorThread;
|
||||
class LLLiveFile;
|
||||
|
|
@ -49,10 +51,6 @@ void clear_signals();
|
|||
|
||||
#endif
|
||||
|
||||
namespace google_breakpad {
|
||||
class ExceptionHandler; // See exception_handler.h
|
||||
}
|
||||
|
||||
class LL_COMMON_API LLApp
|
||||
{
|
||||
friend class LLErrorThread;
|
||||
|
|
@ -211,6 +209,36 @@ public:
|
|||
static bool isExiting(); // Either quitting or error (app is exiting, cleanly or not)
|
||||
static int getPid();
|
||||
|
||||
//
|
||||
// Sleep for specified time while still running
|
||||
//
|
||||
// For use by a coroutine or thread that performs some maintenance on a
|
||||
// periodic basis. (See also LLEventTimer.) This method supports the
|
||||
// pattern of an "infinite" loop that sleeps for some time, performs some
|
||||
// action, then sleeps again. The trouble with literally sleeping a worker
|
||||
// thread is that it could potentially sleep right through attempted
|
||||
// application shutdown. This method avoids that by returning false as
|
||||
// soon as the application status changes away from APP_STATUS_RUNNING
|
||||
// (isRunning()).
|
||||
//
|
||||
// sleep() returns true if it sleeps undisturbed for the entire specified
|
||||
// duration. The idea is that you can code 'while sleep(duration) ...',
|
||||
// which will break the loop once shutdown begins.
|
||||
//
|
||||
// Since any time-based LLUnit should be implicitly convertible to
|
||||
// F32Milliseconds, accept that specific type as a proxy.
|
||||
static bool sleep(F32Milliseconds duration);
|
||||
// Allow any duration defined in terms of <chrono>.
|
||||
// One can imagine a wonderfully general bidirectional conversion system
|
||||
// between any type derived from LLUnits::LLUnit<T, LLUnits::Seconds> and
|
||||
// any std::chrono::duration -- but that doesn't yet exist.
|
||||
template <typename Rep, typename Period>
|
||||
bool sleep(const std::chrono::duration<Rep, Period>& duration)
|
||||
{
|
||||
// wait_for_unequal() has the opposite bool return convention
|
||||
return ! sStatus.wait_for_unequal(duration, APP_STATUS_RUNNING);
|
||||
}
|
||||
|
||||
/** @name Error handling methods */
|
||||
//@{
|
||||
/**
|
||||
|
|
@ -236,13 +264,12 @@ public:
|
|||
static const U32 MAX_MINDUMP_PATH_LENGTH = 256;
|
||||
|
||||
// change the directory where Breakpad minidump files are written to
|
||||
void setMiniDumpDir(const std::string &path);
|
||||
void setDebugFileNames(const std::string &path);
|
||||
|
||||
// Return the Google Breakpad minidump filename after a crash.
|
||||
char *getMiniDumpFilename() { return mMinidumpPath; }
|
||||
std::string* getStaticDebugFile() { return &mStaticDebugFileName; }
|
||||
std::string* getDynamicDebugFile() { return &mDynamicDebugFileName; }
|
||||
std::string* getStaticDebugFile() { return &mStaticDebugFileName; }
|
||||
std::string* getDynamicDebugFile() { return &mDynamicDebugFileName; }
|
||||
|
||||
// Write out a Google Breakpad minidump file.
|
||||
void writeMiniDump();
|
||||
|
|
@ -270,7 +297,7 @@ public:
|
|||
protected:
|
||||
|
||||
static void setStatus(EAppStatus status); // Use this to change the application status.
|
||||
static EAppStatus sStatus; // Reflects current application status
|
||||
static LLScalarCond<EAppStatus> sStatus; // Reflects current application status
|
||||
static BOOL sErrorThreadRunning; // Set while the error thread is running
|
||||
static BOOL sDisableCrashlogger; // Let the OS handle crashes for us.
|
||||
std::wstring mCrashReportPipeStr; //Name of pipe to use for crash reporting.
|
||||
|
|
@ -316,9 +343,6 @@ private:
|
|||
private:
|
||||
// the static application instance if it was created.
|
||||
static LLApp* sApplication;
|
||||
|
||||
google_breakpad::ExceptionHandler * mExceptionHandler;
|
||||
|
||||
|
||||
#if !LL_WINDOWS
|
||||
friend void default_unix_signal_handler(int signum, siginfo_t *info, void *);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -27,7 +27,6 @@
|
|||
#ifndef LL_LLTHREAD_H
|
||||
#define LL_LLTHREAD_H
|
||||
|
||||
#include "llapp.h"
|
||||
#include "llapr.h"
|
||||
#include "boost/intrusive_ptr.hpp"
|
||||
#include "llrefcount.h"
|
||||
|
|
|
|||
|
|
@ -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
|
||||
//
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@
|
|||
#include <iphlpapi.h>
|
||||
#endif
|
||||
|
||||
#include "llapp.h"
|
||||
#include "lldefs.h"
|
||||
#include "llerror.h"
|
||||
|
||||
|
|
@ -44,7 +45,7 @@
|
|||
#include "lltimer.h"
|
||||
#include "llthread.h"
|
||||
#include "llmutex.h"
|
||||
|
||||
#include "fstelemetry.h"
|
||||
const LLUUID LLUUID::null;
|
||||
const LLTransactionID LLTransactionID::tnull;
|
||||
|
||||
|
|
@ -155,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]),
|
||||
|
|
@ -217,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
|
||||
|
|
@ -1027,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;
|
||||
|
|
@ -1045,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;
|
||||
|
|
|
|||
|
|
@ -181,7 +181,6 @@ if (DARWIN)
|
|||
set(copy_dylibs
|
||||
libapr-1.0.dylib
|
||||
libaprutil-1.0.dylib
|
||||
libexception_handler.dylib
|
||||
libnghttp2*.dylib
|
||||
liburiparser*.dylib
|
||||
${EXPAT_COPY}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -23,13 +23,6 @@
|
|||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
#if LL_WINDOWS
|
||||
#define SAFE_SSL 1
|
||||
#elif LL_DARWIN
|
||||
#define SAFE_SSL 1
|
||||
#else
|
||||
#define SAFE_SSL 1
|
||||
#endif
|
||||
|
||||
#include "linden_common.h" // Modifies curl/curl.h interfaces
|
||||
#include "httpcommon.h"
|
||||
|
|
@ -38,10 +31,6 @@
|
|||
#include <curl/curl.h>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#if SAFE_SSL
|
||||
#include <openssl/crypto.h>
|
||||
#include <functional> // std::hash
|
||||
#endif
|
||||
|
||||
|
||||
namespace LLCore
|
||||
|
|
@ -281,9 +270,6 @@ namespace LLHttp
|
|||
{
|
||||
namespace
|
||||
{
|
||||
typedef boost::shared_ptr<LLMutex> LLMutex_ptr;
|
||||
std::vector<LLMutex_ptr> sSSLMutex;
|
||||
|
||||
CURL *getCurlTemplateHandle()
|
||||
{
|
||||
static CURL *curlpTemplateHandle = NULL;
|
||||
|
|
@ -348,34 +334,6 @@ void deallocateEasyCurl(CURL *curlp)
|
|||
}
|
||||
|
||||
|
||||
#if SAFE_SSL
|
||||
//static
|
||||
void ssl_locking_callback(int mode, int type, const char *file, int line)
|
||||
{
|
||||
if (type >= sSSLMutex.size())
|
||||
{
|
||||
LL_WARNS() << "Attempt to get unknown MUTEX in SSL Lock." << LL_ENDL;
|
||||
}
|
||||
|
||||
if (mode & CRYPTO_LOCK)
|
||||
{
|
||||
sSSLMutex[type]->lock();
|
||||
}
|
||||
else
|
||||
{
|
||||
sSSLMutex[type]->unlock();
|
||||
}
|
||||
}
|
||||
|
||||
//static
|
||||
unsigned long ssl_thread_id(void)
|
||||
{
|
||||
// std::thread::id is very deliberately opaque, but we can hash it
|
||||
return std::hash<LLThread::id_t>()(LLThread::currentID());
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
}
|
||||
|
||||
void initialize()
|
||||
|
|
@ -387,27 +345,11 @@ void initialize()
|
|||
|
||||
check_curl_code(code, CURL_GLOBAL_ALL);
|
||||
|
||||
#if SAFE_SSL
|
||||
S32 mutex_count = CRYPTO_num_locks();
|
||||
for (S32 i = 0; i < mutex_count; i++)
|
||||
{
|
||||
sSSLMutex.push_back(LLMutex_ptr(new LLMutex()));
|
||||
}
|
||||
CRYPTO_set_id_callback(&ssl_thread_id);
|
||||
CRYPTO_set_locking_callback(&ssl_locking_callback);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
void cleanup()
|
||||
{
|
||||
#if SAFE_SSL
|
||||
CRYPTO_set_id_callback(NULL);
|
||||
CRYPTO_set_locking_callback(NULL);
|
||||
sSSLMutex.clear();
|
||||
#endif
|
||||
|
||||
curl_global_cleanup();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -726,7 +726,7 @@ bool LLCrashLogger::init()
|
|||
#if LL_WINDOWS
|
||||
Sleep(1000);
|
||||
#else
|
||||
sleep(1);
|
||||
::sleep(1);
|
||||
#endif
|
||||
locked = mKeyMaster.checkMaster();
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@
|
|||
*/
|
||||
|
||||
#include "linden_common.h"
|
||||
#include "llapp.h"
|
||||
#include "llassettype.h"
|
||||
#include "lldir.h"
|
||||
#include <boost/filesystem.hpp>
|
||||
|
|
@ -43,8 +44,6 @@
|
|||
static const char* subdirs = "0123456789abcdef";
|
||||
|
||||
LLDiskCache::LLDiskCache(const std::string cache_dir,
|
||||
// <FS:Ansariel> Fix integer overflow
|
||||
//const int max_size_bytes,
|
||||
const uintmax_t max_size_bytes,
|
||||
const bool enable_cache_debug_info) :
|
||||
mCacheDir(cache_dir),
|
||||
|
|
@ -69,6 +68,34 @@ LLDiskCache::LLDiskCache(const std::string cache_dir,
|
|||
// </FS:Beq>
|
||||
}
|
||||
|
||||
// WARNING: purge() is called by LLPurgeDiskCacheThread. As such it must
|
||||
// NOT touch any LLDiskCache data without introducing and locking a mutex!
|
||||
|
||||
// Interaction through the filesystem itself should be safe. Let’s say thread
|
||||
// A is accessing the cache file for reading/writing and thread B is trimming
|
||||
// the cache. Let’s also assume using llifstream to open a file and
|
||||
// boost::filesystem::remove are not atomic (which will be pretty much the
|
||||
// case).
|
||||
|
||||
// Now, A is trying to open the file using llifstream ctor. It does some
|
||||
// checks if the file exists and whatever else it might be doing, but has not
|
||||
// issued the call to the OS to actually open the file yet. Now B tries to
|
||||
// delete the file: If the file has been already marked as in use by the OS,
|
||||
// deleting the file will fail and B will continue with the next file. A can
|
||||
// safely continue opening the file. If the file has not yet been marked as in
|
||||
// use, B will delete the file. Now A actually wants to open it, operation
|
||||
// will fail, subsequent check via llifstream.is_open will fail, asset will
|
||||
// have to be re-requested. (Assuming here the viewer will actually handle
|
||||
// this situation properly, that can also happen if there is a file containing
|
||||
// garbage.)
|
||||
|
||||
// Other situation: B is trimming the cache and A wants to read a file that is
|
||||
// about to get deleted. boost::filesystem::remove does whatever it is doing
|
||||
// before actually deleting the file. If A opens the file before the file is
|
||||
// actually gone, the OS call from B to delete the file will fail since the OS
|
||||
// will prevent this. B continues with the next file. If the file is already
|
||||
// gone before A finally gets to open it, this operation will fail and the
|
||||
// asset will have to be re-requested.
|
||||
void LLDiskCache::purge()
|
||||
{
|
||||
if (mEnableCacheDebugInfo)
|
||||
|
|
@ -151,15 +178,12 @@ void LLDiskCache::purge()
|
|||
{
|
||||
del++; // Extra accounting to track the retention of static assets
|
||||
// </FS:Beq>
|
||||
// <FS:Ansariel> Do not crash if we cannot delete the file for some reason
|
||||
//boost::filesystem::remove(entry.second.second);
|
||||
boost::filesystem::remove(entry.second.second, ec);
|
||||
if (ec.failed())
|
||||
{
|
||||
LL_WARNS() << "Failed to delete cache file " << entry.second.second << ": " << ec.message() << LL_ENDL;
|
||||
}
|
||||
}
|
||||
// </FS:Ansariel>
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -431,8 +455,6 @@ void LLDiskCache::clearCache()
|
|||
{
|
||||
if (remove_entry.string().find(mCacheFilenamePrefix) != std::string::npos)
|
||||
{
|
||||
// <FS:Ansariel> Do not crash if we cannot delete the file for some reason
|
||||
//boost::filesystem::remove(entry);
|
||||
const boost::filesystem::path remove_path = remove_entry;
|
||||
++entry;
|
||||
boost::filesystem::remove(remove_path, ec);
|
||||
|
|
@ -440,7 +462,6 @@ void LLDiskCache::clearCache()
|
|||
{
|
||||
LL_WARNS() << "Failed to delete cache file " << remove_path.string() << ": " << ec.message() << LL_ENDL;
|
||||
}
|
||||
// </FS:Ansariel>
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -502,26 +523,17 @@ uintmax_t LLDiskCache::dirFileSize(const std::string dir)
|
|||
return total_file_size;
|
||||
}
|
||||
|
||||
// <FS:Ansariel> Regular disk cache cleanup
|
||||
FSPurgeDiskCacheThread::FSPurgeDiskCacheThread() :
|
||||
LLPurgeDiskCacheThread::LLPurgeDiskCacheThread() :
|
||||
LLThread("PurgeDiskCacheThread", nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
void FSPurgeDiskCacheThread::run()
|
||||
void LLPurgeDiskCacheThread::run()
|
||||
{
|
||||
constexpr F64 CHECK_INTERVAL = 60;
|
||||
mTimer.setTimerExpirySec(CHECK_INTERVAL);
|
||||
mTimer.start();
|
||||
constexpr std::chrono::seconds CHECK_INTERVAL{60};
|
||||
|
||||
do
|
||||
while (LLApp::instance()->sleep(CHECK_INTERVAL))
|
||||
{
|
||||
if (mTimer.checkExpirationAndReset(CHECK_INTERVAL))
|
||||
{
|
||||
LLDiskCache::instance().purge();
|
||||
}
|
||||
|
||||
ms_sleep(100);
|
||||
} while (!isQuitting());
|
||||
LLDiskCache::instance().purge();
|
||||
}
|
||||
}
|
||||
// </FS:Ansariel>
|
||||
|
|
|
|||
|
|
@ -86,8 +86,6 @@ class LLDiskCache :
|
|||
* The maximum size of the cache in bytes - Based on the
|
||||
* setting at 'CacheSize' and 'DiskCachePercentOfTotal'
|
||||
*/
|
||||
// <FS:Ansariel> Fix integer overflow
|
||||
//const int max_size_bytes,
|
||||
const uintmax_t max_size_bytes,
|
||||
/**
|
||||
* A flag that enables extra cache debugging so that
|
||||
|
|
@ -128,6 +126,13 @@ class LLDiskCache :
|
|||
/**
|
||||
* Purge the oldest items in the cache so that the combined size of all files
|
||||
* is no bigger than mMaxSizeBytes.
|
||||
*
|
||||
* WARNING: purge() is called by LLPurgeDiskCacheThread. As such it must
|
||||
* NOT touch any LLDiskCache data without introducing and locking a mutex!
|
||||
*
|
||||
* Purging the disk cache involves nontrivial work on the viewer's
|
||||
* filesystem. If called on the main thread, this causes a noticeable
|
||||
* freeze.
|
||||
*/
|
||||
void purge();
|
||||
|
||||
|
|
@ -200,17 +205,12 @@ class LLDiskCache :
|
|||
std::vector<std::string> mSkipList; // <FS:Beq/> Vector of "static" untouchable assets that should never be purged
|
||||
};
|
||||
|
||||
// <FS:Ansariel> Regular disk cache cleanup
|
||||
class FSPurgeDiskCacheThread : public LLThread
|
||||
class LLPurgeDiskCacheThread : public LLThread
|
||||
{
|
||||
public:
|
||||
FSPurgeDiskCacheThread();
|
||||
LLPurgeDiskCacheThread();
|
||||
|
||||
protected:
|
||||
void run() override;
|
||||
|
||||
private:
|
||||
LLTimer mTimer;
|
||||
};
|
||||
// </FS:Ansariel>
|
||||
#endif // _LLDISKCACHE
|
||||
|
|
|
|||
|
|
@ -48,6 +48,28 @@ LLFileSystem::LLFileSystem(const LLUUID& file_id, const LLAssetType::EType file_
|
|||
mPosition = 0;
|
||||
mBytesRead = 0;
|
||||
mMode = mode;
|
||||
|
||||
// This block of code was originally called in the read() method but after comments here:
|
||||
// https://bitbucket.org/lindenlab/viewer/commits/e28c1b46e9944f0215a13cab8ee7dded88d7fc90#comment-10537114
|
||||
// we decided to follow Henri's suggestion and move the code to update the last access time here.
|
||||
if (mode == LLFileSystem::READ)
|
||||
{
|
||||
// build the filename (TODO: we do this in a few places - perhaps we should factor into a single function)
|
||||
std::string id;
|
||||
mFileID.toString(id);
|
||||
const std::string extra_info = "";
|
||||
const std::string filename = LLDiskCache::getInstance()->metaDataToFilepath(id, mFileType, extra_info);
|
||||
|
||||
// update the last access time for the file if it exists - this is required
|
||||
// even though we are reading and not writing because this is the
|
||||
// way the cache works - it relies on a valid "last accessed time" for
|
||||
// each file so it knows how to remove the oldest, unused files
|
||||
bool exists = gDirUtilp->fileExists(filename);
|
||||
if (exists)
|
||||
{
|
||||
LLDiskCache::getInstance()->updateFileAccessTime(filename);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LLFileSystem::~LLFileSystem()
|
||||
|
|
@ -153,8 +175,6 @@ S32 LLFileSystem::getFileSize(const LLUUID& file_id, const LLAssetType::EType fi
|
|||
BOOL LLFileSystem::read(U8* buffer, S32 bytes)
|
||||
{
|
||||
FSZoneC(tracy::Color::Gold); // <FS:Beq> measure cache performance
|
||||
// <FS:Ansariel> Cache fixes
|
||||
//BOOL success = TRUE;
|
||||
BOOL success = FALSE;
|
||||
|
||||
std::string id;
|
||||
|
|
@ -182,9 +202,9 @@ BOOL LLFileSystem::read(U8* buffer, S32 bytes)
|
|||
// file.close();
|
||||
|
||||
// mPosition += mBytesRead;
|
||||
// if (!mBytesRead)
|
||||
// if (mBytesRead)
|
||||
// {
|
||||
// success = FALSE;
|
||||
// success = TRUE;
|
||||
// }
|
||||
//}
|
||||
LLFILE* file = LLFile::fopen(filename, "rb");
|
||||
|
|
@ -206,12 +226,6 @@ BOOL LLFileSystem::read(U8* buffer, S32 bytes)
|
|||
}
|
||||
// </FS:Ansariel>
|
||||
|
||||
// update the last access time for the file - this is required
|
||||
// even though we are reading and not writing because this is the
|
||||
// way the cache works - it relies on a valid "last accessed time" for
|
||||
// each file so it knows how to remove the oldest, unused files
|
||||
LLDiskCache::getInstance()->updateFileAccessTime(filename);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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)))));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,24 +52,28 @@ U32 LLBlowfishCipher::encrypt(const U8* src, U32 src_len, U8* dst, U32 dst_len)
|
|||
if (src_len > dst_len) return 0;
|
||||
|
||||
// OpenSSL uses "cipher contexts" to hold encryption parameters.
|
||||
EVP_CIPHER_CTX context;
|
||||
EVP_CIPHER_CTX_init(&context);
|
||||
EVP_CIPHER_CTX *context = EVP_CIPHER_CTX_new();
|
||||
if (!context)
|
||||
{
|
||||
LL_WARNS() << "LLBlowfishCipher::encrypt EVP_CIPHER_CTX initiation failure" << LL_ENDL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// We want a blowfish cyclic block chain cipher, but need to set
|
||||
// the key length before we pass in a key, so call EncryptInit
|
||||
// first with NULLs.
|
||||
EVP_EncryptInit_ex(&context, EVP_bf_cbc(), NULL, NULL, NULL);
|
||||
EVP_CIPHER_CTX_set_key_length(&context, (int)mSecretSize);
|
||||
EVP_EncryptInit_ex(context, EVP_bf_cbc(), NULL, NULL, NULL);
|
||||
EVP_CIPHER_CTX_set_key_length(context, (int)mSecretSize);
|
||||
|
||||
// Complete initialization. Per EVP_EncryptInit man page, the
|
||||
// cipher pointer must be NULL. Apparently initial_vector must
|
||||
// be 8 bytes for blowfish, as this is the block size.
|
||||
unsigned char initial_vector[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
EVP_EncryptInit_ex(&context, NULL, NULL, mSecret, initial_vector);
|
||||
EVP_EncryptInit_ex(context, NULL, NULL, mSecret, initial_vector);
|
||||
|
||||
int blocksize = EVP_CIPHER_CTX_block_size(&context);
|
||||
int keylen = EVP_CIPHER_CTX_key_length(&context);
|
||||
int iv_length = EVP_CIPHER_CTX_iv_length(&context);
|
||||
int blocksize = EVP_CIPHER_CTX_block_size(context);
|
||||
int keylen = EVP_CIPHER_CTX_key_length(context);
|
||||
int iv_length = EVP_CIPHER_CTX_iv_length(context);
|
||||
LL_DEBUGS() << "LLBlowfishCipher blocksize " << blocksize
|
||||
<< " keylen " << keylen
|
||||
<< " iv_len " << iv_length
|
||||
|
|
@ -77,7 +81,7 @@ U32 LLBlowfishCipher::encrypt(const U8* src, U32 src_len, U8* dst, U32 dst_len)
|
|||
|
||||
int output_len = 0;
|
||||
int temp_len = 0;
|
||||
if (!EVP_EncryptUpdate(&context,
|
||||
if (!EVP_EncryptUpdate(context,
|
||||
dst,
|
||||
&output_len,
|
||||
src,
|
||||
|
|
@ -89,18 +93,18 @@ U32 LLBlowfishCipher::encrypt(const U8* src, U32 src_len, U8* dst, U32 dst_len)
|
|||
|
||||
// There may be some final data left to encrypt if the input is
|
||||
// not an exact multiple of the block size.
|
||||
if (!EVP_EncryptFinal_ex(&context, (unsigned char*)(dst + output_len), &temp_len))
|
||||
if (!EVP_EncryptFinal_ex(context, (unsigned char*)(dst + output_len), &temp_len))
|
||||
{
|
||||
LL_WARNS() << "LLBlowfishCipher::encrypt EVP_EncryptFinal failure" << LL_ENDL;
|
||||
goto ERROR;
|
||||
}
|
||||
output_len += temp_len;
|
||||
|
||||
EVP_CIPHER_CTX_cleanup(&context);
|
||||
EVP_CIPHER_CTX_free(context);
|
||||
return output_len;
|
||||
|
||||
ERROR:
|
||||
EVP_CIPHER_CTX_cleanup(&context);
|
||||
EVP_CIPHER_CTX_free(context);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -113,18 +117,22 @@ U32 LLBlowfishCipher::decrypt(const U8* src, U32 src_len, U8* dst, U32 dst_len)
|
|||
if (!src || !src_len || !dst || !dst_len) return 0;
|
||||
if (src_len > dst_len) return 0;
|
||||
|
||||
EVP_CIPHER_CTX context;
|
||||
EVP_CIPHER_CTX_init(&context);
|
||||
|
||||
EVP_DecryptInit_ex(&context, EVP_bf_cbc(), NULL, NULL, NULL);
|
||||
EVP_CIPHER_CTX_set_key_length(&context, (int)mSecretSize);
|
||||
EVP_CIPHER_CTX *context = EVP_CIPHER_CTX_new();
|
||||
if (!context)
|
||||
{
|
||||
LL_WARNS() << "LLBlowfishCipher::encrypt EVP_CIPHER_CTX initiation failure" << LL_ENDL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
EVP_DecryptInit_ex(context, EVP_bf_cbc(), NULL, NULL, NULL);
|
||||
EVP_CIPHER_CTX_set_key_length(context, (int)mSecretSize);
|
||||
|
||||
unsigned char initial_vector[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
EVP_DecryptInit_ex(&context, NULL, NULL, mSecret, initial_vector);
|
||||
EVP_DecryptInit_ex(context, NULL, NULL, mSecret, initial_vector);
|
||||
|
||||
int blocksize = EVP_CIPHER_CTX_block_size(&context);
|
||||
int keylen = EVP_CIPHER_CTX_key_length(&context);
|
||||
int iv_length = EVP_CIPHER_CTX_iv_length(&context);
|
||||
int blocksize = EVP_CIPHER_CTX_block_size(context);
|
||||
int keylen = EVP_CIPHER_CTX_key_length(context);
|
||||
int iv_length = EVP_CIPHER_CTX_iv_length(context);
|
||||
LL_DEBUGS() << "LLBlowfishCipher blocksize " << blocksize
|
||||
<< " keylen " << keylen
|
||||
<< " iv_len " << iv_length
|
||||
|
|
@ -132,12 +140,12 @@ U32 LLBlowfishCipher::decrypt(const U8* src, U32 src_len, U8* dst, U32 dst_len)
|
|||
|
||||
int out_len = 0;
|
||||
int tmp_len = 0;
|
||||
if (!EVP_DecryptUpdate(&context, dst, &out_len, src, src_len))
|
||||
if (!EVP_DecryptUpdate(context, dst, &out_len, src, src_len))
|
||||
{
|
||||
LL_WARNS() << "LLBlowfishCipher::decrypt EVP_DecryptUpdate failure" << LL_ENDL;
|
||||
goto ERROR;
|
||||
}
|
||||
if (!EVP_DecryptFinal_ex(&context, dst + out_len, &tmp_len))
|
||||
if (!EVP_DecryptFinal_ex(context, dst + out_len, &tmp_len))
|
||||
{
|
||||
LL_WARNS() << "LLBlowfishCipher::decrypt EVP_DecryptFinal failure" << LL_ENDL;
|
||||
goto ERROR;
|
||||
|
|
@ -145,11 +153,11 @@ U32 LLBlowfishCipher::decrypt(const U8* src, U32 src_len, U8* dst, U32 dst_len)
|
|||
|
||||
out_len += tmp_len;
|
||||
|
||||
EVP_CIPHER_CTX_cleanup(&context);
|
||||
EVP_CIPHER_CTX_free(context);
|
||||
return out_len;
|
||||
|
||||
ERROR:
|
||||
EVP_CIPHER_CTX_cleanup(&context);
|
||||
EVP_CIPHER_CTX_free(context);
|
||||
return 0;
|
||||
// </FS:CR>
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@
|
|||
#include "apr_poll.h"
|
||||
|
||||
// linden library headers
|
||||
#include "llapp.h"
|
||||
#include "indra_constants.h"
|
||||
#include "lldir.h"
|
||||
#include "llerror.h"
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
@ -720,6 +780,15 @@ void LLPluginClassMedia::loadURI(const std::string &uri)
|
|||
sendMessage(message);
|
||||
}
|
||||
|
||||
void LLPluginClassMedia::executeJavaScript(const std::string &code)
|
||||
{
|
||||
LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "execute_javascript");
|
||||
|
||||
message.setValue("code", code);
|
||||
|
||||
sendMessage(message);
|
||||
}
|
||||
|
||||
const char* LLPluginClassMedia::priorityToString(EPriority priority)
|
||||
{
|
||||
const char* result = "UNKNOWN";
|
||||
|
|
@ -897,6 +966,19 @@ void LLPluginClassMedia::setJavascriptEnabled(const bool enabled)
|
|||
sendMessage(message);
|
||||
}
|
||||
|
||||
void LLPluginClassMedia::setWebSecurityDisabled(const bool disabled)
|
||||
{
|
||||
LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "web_security_disabled");
|
||||
message.setValueBoolean("disabled", disabled);
|
||||
sendMessage(message);
|
||||
}
|
||||
|
||||
void LLPluginClassMedia::setFileAccessFromFileUrlsEnabled(const bool enabled)
|
||||
{
|
||||
LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "file_access_from_file_urls");
|
||||
message.setValueBoolean("enabled", enabled);
|
||||
sendMessage(message);
|
||||
}
|
||||
|
||||
void LLPluginClassMedia::enableMediaPluginDebugging( bool enable )
|
||||
{
|
||||
|
|
|
|||
|
|
@ -135,10 +135,26 @@ 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);
|
||||
|
||||
void executeJavaScript(const std::string &code);
|
||||
|
||||
// "Loading" means uninitialized or any state prior to fully running (processing commands)
|
||||
bool isPluginLoading(void) { return mPlugin?mPlugin->isLoading():false; };
|
||||
|
||||
|
|
@ -199,6 +215,8 @@ public:
|
|||
void setLanguageCode(const std::string &language_code);
|
||||
void setPluginsEnabled(const bool enabled);
|
||||
void setJavascriptEnabled(const bool enabled);
|
||||
void setWebSecurityDisabled(const bool disabled);
|
||||
void setFileAccessFromFileUrlsEnabled(const bool enabled);
|
||||
void setTarget(const std::string &target);
|
||||
|
||||
///////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
|
||||
#include "linden_common.h"
|
||||
|
||||
#include "llapp.h"
|
||||
#include "llpluginprocessparent.h"
|
||||
#include "llpluginmessagepipe.h"
|
||||
#include "llpluginmessageclasses.h"
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -290,7 +290,8 @@ LLFloater::LLFloater(const LLSD& key, const LLFloater::Params& p)
|
|||
mDefaultRelativeX(p.rel_x),
|
||||
mDefaultRelativeY(p.rel_y),
|
||||
mMinimizeSignal(NULL),
|
||||
mHostedFloaterShowtitlebar(p.hosted_floater_show_titlebar) // <FS:Ansariel> MultiFloater without titlebar for hosted floater
|
||||
mHostedFloaterShowtitlebar(p.hosted_floater_show_titlebar), // <FS:Ansariel> MultiFloater without titlebar for hosted floater
|
||||
mShiftPressed(false) // <FS:Ansariel> FIRE-24125: Add option to close all floaters of a group
|
||||
// mNotificationContext(NULL)
|
||||
{
|
||||
mPosition.setFloater(*this);
|
||||
|
|
@ -1717,6 +1718,30 @@ BOOL LLFloater::handleDoubleClick(S32 x, S32 y, MASK mask)
|
|||
return was_minimized || LLPanel::handleDoubleClick(x, y, mask);
|
||||
}
|
||||
|
||||
// <FS:Ansariel> FIRE-24125: Add option to close all floaters of a group
|
||||
//virtual
|
||||
BOOL LLFloater::handleKeyHere(KEY key, MASK mask)
|
||||
{
|
||||
if (mask == MASK_SHIFT)
|
||||
{
|
||||
mShiftPressed = true;
|
||||
}
|
||||
|
||||
return LLPanel::handleKeyHere(key, mask);
|
||||
}
|
||||
|
||||
//virtual
|
||||
BOOL LLFloater::handleKeyUpHere(KEY key, MASK mask)
|
||||
{
|
||||
if (mask == MASK_SHIFT)
|
||||
{
|
||||
mShiftPressed = false;
|
||||
}
|
||||
|
||||
return LLPanel::handleKeyUpHere(key, mask);
|
||||
}
|
||||
// </FS:Ansariel>
|
||||
|
||||
void LLFloater::bringToFront( S32 x, S32 y )
|
||||
{
|
||||
if (getVisible() && pointInView(x, y))
|
||||
|
|
@ -1965,6 +1990,20 @@ void LLFloater::onClickClose( LLFloater* self )
|
|||
|
||||
void LLFloater::onClickCloseBtn(bool app_quitting)
|
||||
{
|
||||
// <FS:Ansariel> FIRE-24125: Add option to close all floaters of a group
|
||||
if (mShiftPressed)
|
||||
{
|
||||
auto floaterlist = LLFloaterReg::getAllFloatersInGroup(this);
|
||||
for (auto floater : floaterlist)
|
||||
{
|
||||
if (floater != this)
|
||||
{
|
||||
floater->closeFloater();
|
||||
}
|
||||
}
|
||||
}
|
||||
// </FS:Ansariel>
|
||||
|
||||
closeFloater(false);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -310,7 +310,12 @@ public:
|
|||
virtual BOOL handleMiddleMouseDown(S32 x, S32 y, MASK mask);
|
||||
|
||||
virtual BOOL handleScrollWheel(S32 x, S32 y, S32 mask);
|
||||
|
||||
|
||||
// <FS:Ansariel> FIRE-24125: Add option to close all floaters of a group
|
||||
virtual BOOL handleKeyHere(KEY key, MASK mask);
|
||||
virtual BOOL handleKeyUpHere(KEY key, MASK mask);
|
||||
// </FS:Ansariel>
|
||||
|
||||
virtual void draw();
|
||||
virtual void drawShadow(LLPanel* panel);
|
||||
|
||||
|
|
@ -555,6 +560,9 @@ private:
|
|||
|
||||
// <FS:Ansariel> MultiFloater without titlebar for hosted floater
|
||||
bool mHostedFloaterShowtitlebar;
|
||||
|
||||
// <FS:Ansariel> FIRE-24125: Add option to close all floaters of a group
|
||||
bool mShiftPressed;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -103,6 +103,37 @@ LLFloater* LLFloaterReg::getLastFloaterInGroup(const std::string& name)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
// <FS:Ansariel> FIRE-24125: Add option to close all floaters of a group
|
||||
//static
|
||||
LLFloaterReg::instance_list_t LLFloaterReg::getAllFloatersInGroup(LLFloater* floater)
|
||||
{
|
||||
if (floater)
|
||||
{
|
||||
for (const auto& group : sGroupMap)
|
||||
{
|
||||
const std::string& group_name = group.second;
|
||||
|
||||
if (group_name.empty())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
instance_list_t& instances = sInstanceMap[group_name];
|
||||
|
||||
for (auto instance : instances)
|
||||
{
|
||||
if (instance == floater)
|
||||
{
|
||||
return sInstanceMap[group_name];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
// </FS:Ansariel>
|
||||
|
||||
LLFloater* LLFloaterReg::getLastFloaterCascading()
|
||||
{
|
||||
LLRect candidate_rect;
|
||||
|
|
|
|||
|
|
@ -114,6 +114,7 @@ public:
|
|||
// Helpers
|
||||
static LLFloater* getLastFloaterInGroup(const std::string& name);
|
||||
static LLFloater* getLastFloaterCascading();
|
||||
static instance_list_t getAllFloatersInGroup(LLFloater* floater); // <FS:Ansariel> FIRE-24125: Add option to close all floaters of a group
|
||||
|
||||
// Find / get (create) / remove / destroy
|
||||
static LLFloater* findInstance(const std::string& name, const LLSD& key = LLSD());
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -3709,7 +3709,8 @@ BOOL LLScrollListCtrl::operateOnAll(EOperation op)
|
|||
void LLScrollListCtrl::setFocus(BOOL b)
|
||||
{
|
||||
// for tabbing into pristine scroll lists (Finder)
|
||||
if (!getFirstSelected())
|
||||
//if (!getFirstSelected())
|
||||
if (!getFirstSelected() && !getEnabled()) // <FS:LO> make disabled lists not jump to the top on clicking an element in them.
|
||||
{
|
||||
selectFirstItem();
|
||||
//onCommit(); // SJB: selectFirstItem() will call onCommit() if appropriate
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue