diff options
| author | Nat Goodspeed <nat@lindenlab.com> | 2018-06-14 18:20:55 -0400 | 
|---|---|---|
| committer | Nat Goodspeed <nat@lindenlab.com> | 2018-06-14 18:20:55 -0400 | 
| commit | 4dba69b04ab9825f1cd4b8dbf855494a3897ffd7 (patch) | |
| tree | 2f3a5324daf25ccea323ce5caa8dc238b6e37bbe /indra | |
| parent | 9b7640d70ae820a954634ecf0dae43dfb33c0d3a (diff) | |
| parent | 67f6625c56406604197507c842496f031eb0986f (diff) | |
Automated merge with file:///Users/nat/linden/viewer-no-vstool
Diffstat (limited to 'indra')
73 files changed, 1743 insertions, 728 deletions
| diff --git a/indra/cmake/CMakeLists.txt b/indra/cmake/CMakeLists.txt index 4a3ebe4835..84e1c5d6fd 100644 --- a/indra/cmake/CMakeLists.txt +++ b/indra/cmake/CMakeLists.txt @@ -12,6 +12,7 @@ set(cmake_SOURCE_FILES      Audio.cmake      BerkeleyDB.cmake      Boost.cmake +    bugsplat.cmake      BuildVersion.cmake      CEFPlugin.cmake      CEFPlugin.cmake diff --git a/indra/cmake/Copy3rdPartyLibs.cmake b/indra/cmake/Copy3rdPartyLibs.cmake index 09a97fc03e..c9519b0e1d 100644 --- a/indra/cmake/Copy3rdPartyLibs.cmake +++ b/indra/cmake/Copy3rdPartyLibs.cmake @@ -49,6 +49,20 @@ if(WINDOWS)          libhunspell.dll          ) +    # Filenames are different for 32/64 bit BugSplat file and we don't +    # have any control over them so need to branch. +    if (DEFINED ENV{BUGSPLAT_DB}) +      if(ADDRESS_SIZE EQUAL 32) +        set(release_files ${release_files} BugSplat.dll) +        set(release_files ${release_files} BugSplatRc.dll) +        set(release_files ${release_files} BsSndRpt.exe) +      else(ADDRESS_SIZE EQUAL 32) +        set(release_files ${release_files} BugSplat64.dll) +        set(release_files ${release_files} BugSplatRc64.dll) +        set(release_files ${release_files} BsSndRpt64.exe) +      endif(ADDRESS_SIZE EQUAL 32) +    endif (DEFINED ENV{BUGSPLAT_DB}) +      if (FMODEX)          if(ADDRESS_SIZE EQUAL 32) diff --git a/indra/cmake/Variables.cmake b/indra/cmake/Variables.cmake index bd69c49856..b913d6398e 100644 --- a/indra/cmake/Variables.cmake +++ b/indra/cmake/Variables.cmake @@ -209,7 +209,6 @@ set(SIGNING_IDENTITY "" CACHE STRING "Specifies the signing identity to use, if  set(VERSION_BUILD "0" CACHE STRING "Revision number passed in from the outside")  set(USESYSTEMLIBS OFF CACHE BOOL "Use libraries from your system rather than Linden-supplied prebuilt libraries.") -set(UNATTENDED OFF CACHE BOOL "Should be set to ON for building with VC Express editions.")  set(USE_PRECOMPILED_HEADERS ON CACHE BOOL "Enable use of precompiled header directives where supported.") diff --git a/indra/cmake/bugsplat.cmake b/indra/cmake/bugsplat.cmake new file mode 100644 index 0000000000..eb5808b1fb --- /dev/null +++ b/indra/cmake/bugsplat.cmake @@ -0,0 +1,26 @@ +# BugSplat is engaged by setting environment variable BUGSPLAT_DB to the +# target BugSplat database name prior to running CMake (and during autobuild +# build). +if (DEFINED ENV{BUGSPLAT_DB}) +  if (USESYSTEMLIBS) +    message(STATUS "Looking for system BugSplat") +    set(BUGSPLAT_FIND_QUIETLY ON) +    set(BUGSPLAT_FIND_REQUIRED ON) +    include(FindBUGSPLAT) +  else (USESYSTEMLIBS) +    message(STATUS "Engaging autobuild BugSplat") +    include(Prebuilt) +    use_prebuilt_binary(bugsplat) +    if (WINDOWS) +      set(BUGSPLAT_LIBRARIES  +        ${ARCH_PREBUILT_DIRS_RELEASE}/bugsplat.lib +        ) +    elseif (DARWIN) +      find_library(BUGSPLAT_LIBRARIES BugsplatMac +        PATHS "${ARCH_PREBUILT_DIRS_RELEASE}") +    else (WINDOWS) + +    endif (WINDOWS) +    set(BUGSPLAT_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include/bugsplat) +  endif (USESYSTEMLIBS) +endif (DEFINED ENV{BUGSPLAT_DB}) diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index d9eb13d65a..8977acb873 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -255,6 +255,11 @@ set(llcommon_HEADER_FILES  set_source_files_properties(${llcommon_HEADER_FILES}                              PROPERTIES HEADER_FILE_ONLY TRUE) +if (DEFINED ENV{BUGSPLAT_DB}) +  set_source_files_properties(llapp.cpp +    PROPERTIES COMPILE_DEFINITIONS "LL_BUGSPLAT") +endif (DEFINED ENV{BUGSPLAT_DB}) +  list(APPEND llcommon_SOURCE_FILES ${llcommon_HEADER_FILES})  if(LLCOMMON_LINK_SHARED) diff --git a/indra/llcommon/llapp.cpp b/indra/llcommon/llapp.cpp index 6cc9e804d4..421af3006e 100644 --- a/indra/llcommon/llapp.cpp +++ b/indra/llcommon/llapp.cpp @@ -392,7 +392,7 @@ void LLApp::setupErrorHandling(bool second_instance)  #if LL_WINDOWS -#if LL_SEND_CRASH_REPORTS +#if LL_SEND_CRASH_REPORTS && ! defined(LL_BUGSPLAT)  	EnableCrashingOnCrashes();  	// This sets a callback to handle w32 signals to the console window. @@ -454,8 +454,15 @@ void LLApp::setupErrorHandling(bool second_instance)  			mExceptionHandler->set_handle_debug_exceptions(true);  		}  	} -#endif -#else +#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.  	// @@ -463,9 +470,11 @@ void LLApp::setupErrorHandling(bool second_instance)  	// 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; +#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 @@ -498,7 +507,7 @@ void LLApp::setupErrorHandling(bool second_instance)  		// installing the handler.  		installHandler = true;  	} -	#endif +	#endif // ! LL_RELEASE_FOR_DOWNLOAD  	if(installHandler && (mExceptionHandler == 0))  	{ @@ -514,9 +523,9 @@ void LLApp::setupErrorHandling(bool second_instance)  		google_breakpad::MinidumpDescriptor desc(mDumpPath);  	    mExceptionHandler = new google_breakpad::ExceptionHandler(desc, NULL, unix_minidump_callback, NULL, true, -1);  	} -#endif +#endif // LL_LINUX -#endif +#endif // ! LL_WINDOWS  	startErrorThread();  } diff --git a/indra/llcommon/llpreprocessor.h b/indra/llcommon/llpreprocessor.h index 2879038c36..ef015fdce4 100644 --- a/indra/llcommon/llpreprocessor.h +++ b/indra/llcommon/llpreprocessor.h @@ -198,6 +198,8 @@  #define LL_TO_STRING_HELPER(x) #x  #define LL_TO_STRING(x) LL_TO_STRING_HELPER(x) +#define LL_TO_WSTRING_HELPER(x) L#x +#define LL_TO_WSTRING(x) LL_TO_WSTRING_HELPER(x)  #define LL_FILE_LINENO_MSG(msg) __FILE__ "(" LL_TO_STRING(__LINE__) ") : " msg  #define LL_GLUE_IMPL(x, y) x##y  #define LL_GLUE_TOKENS(x, y) LL_GLUE_IMPL(x, y) diff --git a/indra/llcommon/stringize.h b/indra/llcommon/stringize.h index a5a90d7297..38dd198ad3 100644 --- a/indra/llcommon/stringize.h +++ b/indra/llcommon/stringize.h @@ -30,7 +30,6 @@  #define LL_STRINGIZE_H  #include <sstream> -#include <boost/phoenix/phoenix.hpp>  #include <llstring.h>  /** @@ -53,12 +52,7 @@ std::basic_string<CHARTYPE> gstringize(const T& item)   */  inline std::string stringize(const std::wstring& item)  { -    LL_WARNS() << "WARNING:  Possible narrowing" << LL_ENDL; -     -    std::string s; -     -    s = wstring_to_utf8str(item); -    return gstringize<char>(s); +    return wstring_to_utf8str(item);  }  /** @@ -76,7 +70,10 @@ std::string stringize(const T& item)   */  inline std::wstring wstringize(const std::string& item)  { -    return gstringize<wchar_t>(item.c_str()); +    // utf8str_to_wstring() returns LLWString, which isn't necessarily the +    // same as std::wstring +    LLWString s(utf8str_to_wstring(item)); +    return std::wstring(s.begin(), s.end());  }  /** @@ -91,10 +88,10 @@ std::wstring wstringize(const T& item)  /**   * stringize_f(functor)   */ -template <typename Functor> -std::string stringize_f(Functor const & f) +template <typename CHARTYPE, typename Functor> +std::basic_string<CHARTYPE> stringize_f(Functor const & f)  { -    std::ostringstream out; +    std::basic_ostringstream<CHARTYPE> out;      f(out);      return out.str();  } @@ -108,31 +105,37 @@ std::string stringize_f(Functor const & f)   * return out.str();   * @endcode   */ -#define STRINGIZE(EXPRESSION) (stringize_f(boost::phoenix::placeholders::arg1 << EXPRESSION)) +#define STRINGIZE(EXPRESSION) (stringize_f<char>([&](std::ostream& out){ out << EXPRESSION; })) +/** + * WSTRINGIZE() is the wstring equivalent of STRINGIZE() + */ +#define WSTRINGIZE(EXPRESSION) (stringize_f<wchar_t>([&](std::wostream& out){ out << EXPRESSION; }))  /**   * destringize(str)   * defined for symmetry with stringize - * *NOTE - this has distinct behavior from boost::lexical_cast<T> regarding + * @NOTE - this has distinct behavior from boost::lexical_cast<T> regarding   * leading/trailing whitespace and handling of bad_lexical_cast exceptions + * @NOTE - no need for dewstringize(), since passing std::wstring will Do The + * Right Thing   */ -template <typename T> -T destringize(std::string const & str) +template <typename T, typename CHARTYPE> +T destringize(std::basic_string<CHARTYPE> const & str)  { -	T val; -    std::istringstream in(str); -	in >> val; +    T val; +    std::basic_istringstream<CHARTYPE> in(str); +    in >> val;      return val;  }  /**   * destringize_f(str, functor)   */ -template <typename Functor> -void destringize_f(std::string const & str, Functor const & f) +template <typename CHARTYPE, typename Functor> +void destringize_f(std::basic_string<CHARTYPE> const & str, Functor const & f)  { -    std::istringstream in(str); +    std::basic_istringstream<CHARTYPE> in(str);      f(in);  } @@ -143,8 +146,11 @@ void destringize_f(std::string const & str, Functor const & f)   * std::istringstream in(str);   * in >> item1 >> item2 >> item3 ... ;   * @endcode + * @NOTE - once we get generic lambdas, we shouldn't need DEWSTRINGIZE() any + * more since DESTRINGIZE() should do the right thing with a std::wstring. But + * until then, the lambda we pass must accept the right std::basic_istream.   */ -#define DESTRINGIZE(STR, EXPRESSION) (destringize_f((STR), (boost::phoenix::placeholders::arg1 >> EXPRESSION))) - +#define DESTRINGIZE(STR, EXPRESSION) (destringize_f((STR), [&](std::istream& in){in >> EXPRESSION;})) +#define DEWSTRINGIZE(STR, EXPRESSION) (destringize_f((STR), [&](std::wistream& in){in >> EXPRESSION;}))  #endif /* ! defined(LL_STRINGIZE_H) */ diff --git a/indra/llcommon/tests/wrapllerrs.h b/indra/llcommon/tests/wrapllerrs.h index 9a4bbbd630..08fbf19b1c 100644 --- a/indra/llcommon/tests/wrapllerrs.h +++ b/indra/llcommon/tests/wrapllerrs.h @@ -109,6 +109,12 @@ public:          mMessages.push_back(message);      } +    friend inline +    std::ostream& operator<<(std::ostream& out, const CaptureLogRecorder& log) +    { +        return log.streamto(out); +    } +      /// Don't assume the message we want is necessarily the LAST log message      /// emitted by the underlying code; search backwards through all messages      /// for the sought string. @@ -126,7 +132,7 @@ public:          throw tut::failure(STRINGIZE("failed to find '" << search                                       << "' in captured log messages:\n" -                                     << boost::ref(*this))); +                                     << *this));      }      std::ostream& streamto(std::ostream& out) const @@ -200,10 +206,4 @@ private:  	LLError::RecorderPtr mRecorder;  }; -inline -std::ostream& operator<<(std::ostream& out, const CaptureLogRecorder& log) -{ -    return log.streamto(out); -} -  #endif /* ! defined(LL_WRAPLLERRS_H) */ diff --git a/indra/llcorehttp/CMakeLists.txt b/indra/llcorehttp/CMakeLists.txt index bff329f4a5..9dbc6f447e 100644 --- a/indra/llcorehttp/CMakeLists.txt +++ b/indra/llcorehttp/CMakeLists.txt @@ -167,29 +167,26 @@ if (DARWIN)      COMMENT "Creating Resources directory in app bundle."    ) -  # Copy the required libraries to the package app -  add_custom_command(TARGET INTEGRATION_TEST_llcorehttp PRE_BUILD -    COMMAND ${CMAKE_COMMAND} -E copy ${AUTOBUILD_INSTALL_DIR}/lib/release/libapr-1.0.dylib ${LL_TEST_DESTINATION_DIR} -    DEPENDS ${AUTOBUILD_INSTALL_DIR}/lib/release/libapr-1.0.dylib -  ) -  add_custom_command(TARGET INTEGRATION_TEST_llcorehttp PRE_BUILD -    COMMAND ${CMAKE_COMMAND} -E copy ${AUTOBUILD_INSTALL_DIR}/lib/release/libaprutil-1.0.dylib ${LL_TEST_DESTINATION_DIR} -    DEPENDS ${AUTOBUILD_INSTALL_DIR}/lib/release/libaprutil-1.0.dylib -  ) -  add_custom_command(TARGET INTEGRATION_TEST_llcorehttp PRE_BUILD -    COMMAND ${CMAKE_COMMAND} -E copy ${AUTOBUILD_INSTALL_DIR}/lib/release/libexception_handler.dylib ${LL_TEST_DESTINATION_DIR} -    DEPENDS ${AUTOBUILD_INSTALL_DIR}/lib/release/libexception_handler.dylib -  ) +  # Copy the required libraries to the package app. We used to use a sequence +  # of '${CMAKE_COMMAND} -E copy' commands, but 'cmake -E copy' does only a +  # single file at a time: it doesn't understand wildcards. 'cmake -E copy' is +  # for portability. This operation is Darwin-specific. We can count on the +  # 'cp' command. +  set(copy_dylibs +    libapr-1.0.dylib +    libaprutil-1.0.dylib +    libexception_handler.dylib +    libnghttp2*.dylib +    ${EXPAT_COPY} +    ) +    add_custom_command(TARGET INTEGRATION_TEST_llcorehttp PRE_BUILD -    COMMAND ${CMAKE_COMMAND} -E copy ${AUTOBUILD_INSTALL_DIR}/lib/release/libnghttp2*.dylib ${LL_TEST_DESTINATION_DIR} -    DEPENDS ${AUTOBUILD_INSTALL_DIR}/lib/release/libnghttp2.dylib +    WORKING_DIRECTORY "${AUTOBUILD_INSTALL_DIR}/lib/release" +    COMMAND cp -v +    ${copy_dylibs} +    ${LL_TEST_DESTINATION_DIR} +    DEPENDS ${copy_dylibs}    ) -  foreach(expat ${EXPAT_COPY}) -    add_custom_command(TARGET INTEGRATION_TEST_llcorehttp PRE_BUILD -      COMMAND ${CMAKE_COMMAND} -E copy ${AUTOBUILD_INSTALL_DIR}/lib/release/${expat} ${LL_TEST_DESTINATION_DIR} -      DEPENDS ${AUTOBUILD_INSTALL_DIR}/lib/release/${expat} -    ) -  endforeach(expat)  endif (DARWIN) diff --git a/indra/llkdu/tests/llimagej2ckdu_test.cpp b/indra/llkdu/tests/llimagej2ckdu_test.cpp index e386a9f71b..79ed566d00 100644 --- a/indra/llkdu/tests/llimagej2ckdu_test.cpp +++ b/indra/llkdu/tests/llimagej2ckdu_test.cpp @@ -119,6 +119,10 @@ bool LLKDUMemIn::get(int, kdu_core::kdu_line_buf&, int) { return false; }  // Stub Kakadu Library calls  // they're all namespaced now +namespace kdu_core_local +{ +    class kd_coremem; +}  namespace kdu_core {  kdu_tile_comp kdu_tile::access_component(int ) { kdu_tile_comp a; return a; }  kdu_block_encoder::kdu_block_encoder() { } @@ -140,7 +144,8 @@ void kdu_resolution::get_dims(kdu_dims& ) { }  int kdu_resolution::which() { return 0; }  int kdu_resolution::get_valid_band_indices(int &) { return 1; }  kdu_synthesis::kdu_synthesis(kdu_resolution, kdu_sample_allocator*, bool, float, kdu_thread_env*, kdu_thread_queue*) { } -kdu_params::kdu_params(const char*, bool, bool, bool, bool, bool) { } +//kdu_params::kdu_params(const char*, bool, bool, bool, bool, bool) { } +kdu_params::kdu_params(const char*, bool, bool, bool, bool, bool, kd_core_local::kd_coremem*) {}  kdu_params::~kdu_params() { }  void kdu_params::set(const char* , int , int , bool ) { }  void kdu_params::set(const char* , int , int , int ) { } @@ -164,39 +169,61 @@ void kdu_codestream::destroy() { }  void kdu_codestream::collect_timing_stats(int ) { }  void kdu_codestream::set_max_bytes(kdu_long, bool, bool ) { }  void kdu_codestream::get_valid_tiles(kdu_dims& ) { } -void kdu_codestream::create(kdu_compressed_source*, kdu_thread_env*) { } +void kdu_codestream::create( +    siz_params*, +    kdu_compressed_target*, +    kdu_dims*, +    int, +    kdu_long, +    kdu_thread_env*, +    kdu_membroker*) {} +void kdu_codestream::create(kdu_compressed_source *,kdu_thread_env *, kdu_membroker *) {}  void kdu_codestream::apply_input_restrictions(int, int, int, int, kdu_dims const *, kdu_component_access_mode, kdu_thread_env *, kdu_quality_limiter const *) {}  void kdu_codestream::get_subsampling(int , kdu_coords&, bool ) { }  void kdu_codestream::flush(kdu_long *, int, kdu_uint16 *, bool, bool, double, kdu_thread_env*, int) { }  void kdu_codestream::set_resilient(bool ) { }  int kdu_codestream::get_num_components(bool ) { return 0; }  kdu_long kdu_codestream::get_total_bytes(bool ) { return 0; } -kdu_long kdu_codestream::get_compressed_data_memory(bool ) {return 0; } +kdu_long kdu_codestream::get_compressed_data_memory(bool ) const {return 0; }  void kdu_codestream::share_buffering(kdu_codestream ) { }  int kdu_codestream::get_num_tparts() { return 0; }  int kdu_codestream::trans_out(kdu_long, kdu_long*, int, bool, kdu_thread_env* ) { return 0; }  bool kdu_codestream::ready_for_flush(kdu_thread_env*) { return false; }  siz_params* kdu_codestream::access_siz() { return NULL; }  kdu_tile kdu_codestream::open_tile(kdu_coords , kdu_thread_env* ) { kdu_tile a; return a; } -kdu_codestream_comment kdu_codestream::add_comment() { kdu_codestream_comment a; return a; } +kdu_codestream_comment kdu_codestream::add_comment(kdu_thread_env*) { kdu_codestream_comment a; return a; }  void kdu_subband::close_block(kdu_block*, kdu_thread_env*) { }  void kdu_subband::get_valid_blocks(kdu_dims &indices) const { }  kdu_block * kdu_subband::open_block(kdu_coords, int *, kdu_thread_env *, int, bool) { return NULL; }  bool kdu_codestream_comment::put_text(const char*) { return false; }  void kdu_customize_warnings(kdu_message*) { }  void kdu_customize_errors(kdu_message*) { } -kdu_long kdu_multi_analysis::create(kdu_codestream, kdu_tile, kdu_thread_env *,kdu_thread_queue *, int, kdu_roi_image *, int, kdu_sample_allocator *, kdu_push_pull_params const *) { return kdu_long(0); } +kdu_long kdu_multi_analysis::create( +    kdu_codestream, +    kdu_tile, +    kdu_thread_env*, +    kdu_thread_queue*, +    int, +    kdu_roi_image*, +    int, +    kdu_sample_allocator*, +    const kdu_push_pull_params*, +    kdu_membroker*) { return kdu_long(0); }  void kdu_multi_analysis::destroy(kdu_thread_env *) {} -siz_params::siz_params() : kdu_params(NULL, false, false, false, false, false) { } +siz_params::siz_params(kd_core_local::kd_coremem*) : kdu_params(NULL, false, false, false, false, false) { }  siz_params::~siz_params() {}  void siz_params::finalize(bool ) { }  void siz_params::copy_with_xforms(kdu_params*, int, int, bool, bool, bool) { }  int siz_params::write_marker_segment(kdu_output*, kdu_params*, int) { return 0; }  bool siz_params::check_marker_segment(kdu_uint16, int, kdu_byte a[], int&) { return false; }  bool siz_params::read_marker_segment(kdu_uint16, int, kdu_byte a[], int) { return false; } - -kdu_decoder::kdu_decoder(kdu_subband , kdu_sample_allocator*, bool , float, int, kdu_thread_env*, kdu_thread_queue*, int) { } -void kdu_codestream::create(siz_params*, kdu_compressed_target*, kdu_dims*, int, kdu_long, kdu_thread_env* ) { } +kdu_decoder::kdu_decoder( +    kdu_subband subband, +    kdu_sample_allocator*, +    bool, float, int, +    kdu_thread_env*, +    kdu_thread_queue*, +    int, float*) {}  kdu_sample_allocator::~kdu_sample_allocator() {}  void kdu_sample_allocator::do_finalize(kdu_codestream) {}  void (*kdu_convert_ycc_to_rgb_rev16)(kdu_int16*,kdu_int16*,kdu_int16*,int); @@ -205,6 +232,8 @@ void (*kdu_convert_ycc_to_rgb_rev32)(kdu_int32*,kdu_int32*,kdu_int32*,int);  void (*kdu_convert_ycc_to_rgb_irrev32)(float*,float*,float*,int);  bool kdu_core_sample_alignment_checker(int, int, int, int, bool, bool) { return false; }  void kdu_pull_ifc::destroy() {} +void kdu_sample_allocator::advance_pre_frag() {} +void kdu_params::operator delete(void *) {}  } // namespace kdu_core  // ------------------------------------------------------------------------------------------- diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index 648f9a8d93..6b6cd65ce2 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -545,7 +545,7 @@ void LLProfile::genNGon(const LLProfileParams& params, S32 sides, F32 offset, F3  {  	// Generate an n-sided "circular" path.  	// 0 is (1,0), and we go counter-clockwise along a circular path from there. -	const F32 tableScale[] = { 1, 1, 1, 0.5f, 0.707107f, 0.53f, 0.525f, 0.5f }; +	static const F32 tableScale[] = { 1, 1, 1, 0.5f, 0.707107f, 0.53f, 0.525f, 0.5f };  	F32 scale = 0.5f;  	F32 t, t_step, t_first, t_fraction, ang, ang_step;  	LLVector4a pt1,pt2; @@ -1304,7 +1304,7 @@ S32 LLPath::getNumNGonPoints(const LLPathParams& params, S32 sides, F32 startOff  void LLPath::genNGon(const LLPathParams& params, S32 sides, F32 startOff, F32 end_scale, F32 twist_scale)  {  	// Generates a circular path, starting at (1, 0, 0), counterclockwise along the xz plane. -	const F32 tableScale[] = { 1, 1, 1, 0.5f, 0.707107f, 0.53f, 0.525f, 0.5f }; +	static const F32 tableScale[] = { 1, 1, 1, 0.5f, 0.707107f, 0.53f, 0.525f, 0.5f };  	F32 revolutions = params.getRevolutions();  	F32 skew		= params.getSkew(); @@ -1602,7 +1602,8 @@ BOOL LLPath::generate(const LLPathParams& params, F32 detail, S32 split,  			if (is_sculpted)  				sides = llmax(sculpt_size, 1); -			genNGon(params, sides); +			if (0 < sides) +				genNGon(params, sides);  		}  		break; diff --git a/indra/llmath/llvolume.h b/indra/llmath/llvolume.h index 4357b69b90..d3c1ac46fe 100644 --- a/indra/llmath/llvolume.h +++ b/indra/llmath/llvolume.h @@ -1089,7 +1089,7 @@ public:  	F32 mSurfaceArea; //unscaled surface area  	BOOL mIsMeshAssetLoaded; -	LLVolumeParams mParams; +	const LLVolumeParams mParams;  	LLPath *mPathp;  	LLProfile *mProfilep;  	LLAlignedArray<LLVector4a,64> mMesh; diff --git a/indra/llprimitive/llmaterialid.cpp b/indra/llprimitive/llmaterialid.cpp index 820f62c43c..f88a607c4f 100644 --- a/indra/llprimitive/llmaterialid.cpp +++ b/indra/llprimitive/llmaterialid.cpp @@ -61,6 +61,11 @@ LLMaterialID::LLMaterialID(const LLMaterialID& pOtherMaterialID)  	copyFromOtherMaterialID(pOtherMaterialID);  } +LLMaterialID::LLMaterialID(const LLUUID& lluid) +{ +	set(lluid.mData); +} +  LLMaterialID::~LLMaterialID()  {  } diff --git a/indra/llprimitive/llmaterialid.h b/indra/llprimitive/llmaterialid.h index b4c82d3b7b..ee663f8f99 100644 --- a/indra/llprimitive/llmaterialid.h +++ b/indra/llprimitive/llmaterialid.h @@ -40,6 +40,7 @@ public:  	LLMaterialID(const LLSD::Binary& pMaterialID);  	LLMaterialID(const void* pMemory);  	LLMaterialID(const LLMaterialID& pOtherMaterialID); +	LLMaterialID(const LLUUID& lluid);  	~LLMaterialID();  	bool          operator == (const LLMaterialID& pOtherMaterialID) const; diff --git a/indra/llprimitive/llprimitive.cpp b/indra/llprimitive/llprimitive.cpp index bfa65666b5..edf7c41e40 100644 --- a/indra/llprimitive/llprimitive.cpp +++ b/indra/llprimitive/llprimitive.cpp @@ -732,6 +732,16 @@ S32	face_index_from_id(LLFaceID face_ID, const std::vector<LLProfile::Face>& fac  BOOL LLPrimitive::setVolume(const LLVolumeParams &volume_params, const S32 detail, bool unique_volume)  { +	if (NO_LOD == detail) +	{ +		// build the new object +		setChanged(GEOMETRY); +		sVolumeManager->unrefVolume(mVolumep); +		mVolumep = new LLVolume(volume_params, 1, TRUE, TRUE); +		setNumTEs(mVolumep->getNumFaces()); +		return FALSE; +	} +  	LLVolume *volumep;  	if (unique_volume)  	{ diff --git a/indra/llprimitive/llprimitive.h b/indra/llprimitive/llprimitive.h index 19d9d52817..99a32e614c 100644 --- a/indra/llprimitive/llprimitive.h +++ b/indra/llprimitive/llprimitive.h @@ -489,6 +489,11 @@ protected:  public:  	static LLVolumeMgr* sVolumeManager; + +	enum +	{ +		NO_LOD = -1 +	};  };  inline BOOL LLPrimitive::isAvatar() const diff --git a/indra/llrender/CMakeLists.txt b/indra/llrender/CMakeLists.txt index 331f988382..07a0d8c402 100644 --- a/indra/llrender/CMakeLists.txt +++ b/indra/llrender/CMakeLists.txt @@ -51,6 +51,7 @@ set(llrender_SOURCE_FILES      lltexture.cpp      lluiimage.cpp      llvertexbuffer.cpp +    llglcommonfunc.cpp      )  set(llrender_HEADER_FILES @@ -78,6 +79,7 @@ set(llrender_HEADER_FILES      lltexture.h      lluiimage.h      llvertexbuffer.h +    llglcommonfunc.h      )  set_source_files_properties(${llrender_HEADER_FILES} diff --git a/indra/llrender/llgl.h b/indra/llrender/llgl.h index aa98b3f6bc..4c4302d05b 100644 --- a/indra/llrender/llgl.h +++ b/indra/llrender/llgl.h @@ -256,6 +256,9 @@ void clear_glerror();  	if the existing GL state does not match the expected GL state.  */ + +#include "boost/function.hpp" +  class LLGLState  {  public: @@ -297,6 +300,20 @@ public:  	LLGLEnableAlphaReject(bool enable);  }; +// Enable with functor +class LLGLEnableFunc : LLGLState +{ +public: +	LLGLEnableFunc(LLGLenum state, bool enable, boost::function<void()> func) +		: LLGLState(state, enable) +	{ +		if (enable) +		{ +			func(); +		} +	} +}; +  /// TODO: Being deprecated.  class LLGLEnable : public LLGLState  { diff --git a/indra/llrender/llglcommonfunc.cpp b/indra/llrender/llglcommonfunc.cpp new file mode 100644 index 0000000000..e9ec28927f --- /dev/null +++ b/indra/llrender/llglcommonfunc.cpp @@ -0,0 +1,37 @@ +/** +* @file llglcommonfunc.cpp +* @brief Implementation of the LLGLCommonFunc. +* +* $LicenseInfo:firstyear=2001&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2010, Linden Research, Inc. +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; +* version 2.1 of the License only. +* +* This library is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA +* +* Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA +* $/LicenseInfo$ +*/ + +#include "llglheaders.h" +#include "llglcommonfunc.h" + +namespace LLGLCommonFunc  +{ +	void selected_stencil_test() +	{ +		glStencilFunc(GL_ALWAYS, 2, 0xffff); +		glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); +	} +} diff --git a/indra/llrender/llglcommonfunc.h b/indra/llrender/llglcommonfunc.h new file mode 100644 index 0000000000..f1f8ff7bc4 --- /dev/null +++ b/indra/llrender/llglcommonfunc.h @@ -0,0 +1,30 @@ +/** +* @file llphoenixfunc.h +* @brief File include common opengl code snippets +* +* $LicenseInfo:firstyear=2003&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2010, Linden Research, Inc. +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; +* version 2.1 of the License only. +* +* This library is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA +* +* Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA +* $/LicenseInfo$ +*/ + +namespace LLGLCommonFunc +{ +	void selected_stencil_test(); +} diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp index 970502f2d6..4702042ab9 100644 --- a/indra/llrender/llglslshader.cpp +++ b/indra/llrender/llglslshader.cpp @@ -537,7 +537,11 @@ BOOL LLGLSLShader::mapAttributes(const std::vector<LLStaticHashedString> * attri      mAttribute.clear();      U32 numAttributes = (attributes == NULL) ? 0 : attributes->size(); +#if LL_RELEASE_WITH_DEBUG_INFO +    mAttribute.resize(LLShaderMgr::instance()->mReservedAttribs.size() + numAttributes, { -1, NULL }); +#else      mAttribute.resize(LLShaderMgr::instance()->mReservedAttribs.size() + numAttributes, -1); +#endif      if (res)      { //read back channel locations @@ -551,7 +555,11 @@ BOOL LLGLSLShader::mapAttributes(const std::vector<LLStaticHashedString> * attri              S32 index = glGetAttribLocationARB(mProgramObject, (const GLcharARB *)name);              if (index != -1)              { +#if LL_RELEASE_WITH_DEBUG_INFO +                mAttribute[i] = { index, name }; +#else                  mAttribute[i] = index; +#endif                  mAttributeMask |= 1 << i;                  LL_DEBUGS("ShaderLoading") << "Attribute " << name << " assigned to channel " << index << LL_ENDL;              } @@ -744,24 +752,25 @@ BOOL LLGLSLShader::mapUniforms(const vector<LLStaticHashedString> * uniforms)  	, even if the "diffuseMap" will be appear and use first in shader code.  	As example where this situation appear see: "Deferred Material Shader 28/29/30/31" -	And tickets: MAINT-4165, MAINT-4839, MAINT-3568 +	And tickets: MAINT-4165, MAINT-4839, MAINT-3568, MAINT-6437  	*/  	S32 diffuseMap = glGetUniformLocationARB(mProgramObject, "diffuseMap"); +	S32 specularMap = glGetUniformLocationARB(mProgramObject, "specularMap");  	S32 bumpMap = glGetUniformLocationARB(mProgramObject, "bumpMap");  	S32 environmentMap = glGetUniformLocationARB(mProgramObject, "environmentMap");  	std::set<S32> skip_index; -	if (-1 != diffuseMap && (-1 != bumpMap || -1 != environmentMap)) +	if (-1 != diffuseMap && (-1 != specularMap || -1 != bumpMap || -1 != environmentMap))  	{  		GLenum type;  		GLsizei length;  		GLint size = -1;  		char name[1024]; -		diffuseMap = bumpMap = environmentMap = -1; +		diffuseMap = specularMap = bumpMap = environmentMap = -1;  		for (S32 i = 0; i < activeCount; i++)  		{ @@ -775,6 +784,18 @@ BOOL LLGLSLShader::mapUniforms(const vector<LLStaticHashedString> * uniforms)  				continue;  			} +			if (-1 == specularMap && std::string(name) == "specularMap") +			{ +				specularMap = i; +				continue; +			} + +			if (-1 == specularMap && std::string(name) == "specularMap") +			{ +				specularMap = i; +				continue; +			} +  			if (-1 == bumpMap && std::string(name) == "bumpMap")  			{  				bumpMap = i; @@ -788,34 +809,29 @@ BOOL LLGLSLShader::mapUniforms(const vector<LLStaticHashedString> * uniforms)  			}  		} +		bool specularDiff = specularMap < diffuseMap && -1 != specularMap;  		bool bumpLessDiff = bumpMap < diffuseMap && -1 != bumpMap;  		bool envLessDiff = environmentMap < diffuseMap && -1 != environmentMap; -		if (bumpLessDiff && envLessDiff) +		if (specularDiff || bumpLessDiff || envLessDiff)  		{  			mapUniform(diffuseMap, uniforms); -			mapUniform(bumpMap, uniforms); -			mapUniform(environmentMap, uniforms); -  			skip_index.insert(diffuseMap); -			skip_index.insert(bumpMap); -			skip_index.insert(environmentMap); -		} -		else if (bumpLessDiff) -		{ -			mapUniform(diffuseMap, uniforms); -			mapUniform(bumpMap, uniforms); -			skip_index.insert(diffuseMap); -			skip_index.insert(bumpMap); -		} -		else if (envLessDiff) -		{ -			mapUniform(diffuseMap, uniforms); -			mapUniform(environmentMap, uniforms); +			if (-1 != specularMap) { +				mapUniform(specularMap, uniforms); +				skip_index.insert(specularMap); +			} -			skip_index.insert(diffuseMap); -			skip_index.insert(environmentMap); +			if (-1 != bumpMap) { +				mapUniform(bumpMap, uniforms); +				skip_index.insert(bumpMap); +			} + +			if (-1 != environmentMap) { +				mapUniform(environmentMap, uniforms); +				skip_index.insert(environmentMap); +			}  		}  	} diff --git a/indra/llrender/llglslshader.h b/indra/llrender/llglslshader.h index 6f10d122cb..b56b914013 100644 --- a/indra/llrender/llglslshader.h +++ b/indra/llrender/llglslshader.h @@ -167,7 +167,18 @@ public:  	U32 mLightHash;  	GLhandleARB mProgramObject; +#if LL_RELEASE_WITH_DEBUG_INFO +	struct attr_name +	{ +		GLint loc; +		const char *name; +		void operator = (GLint _loc) { loc = _loc; } +		operator GLint () { return loc; } +	}; +	std::vector<attr_name> mAttribute; //lookup table of attribute enum to attribute channel +#else  	std::vector<GLint> mAttribute; //lookup table of attribute enum to attribute channel +#endif  	U32 mAttributeMask;  //mask of which reserved attributes are set (lines up with LLVertexBuffer::getTypeMask())  	std::vector<GLint> mUniform;   //lookup table of uniform enum to uniform location  	LLStaticStringTable<GLint> mUniformMap; //lookup map of uniform name to uniform location diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index a55ca5ed9c..e3e605d040 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -327,7 +327,7 @@ void LLVBOPool::cleanup()  //NOTE: each component must be AT LEAST 4 bytes in size to avoid a performance penalty on AMD hardware -S32 LLVertexBuffer::sTypeSize[LLVertexBuffer::TYPE_MAX] = +const S32 LLVertexBuffer::sTypeSize[LLVertexBuffer::TYPE_MAX] =  {  	sizeof(LLVector4), // TYPE_VERTEX,  	sizeof(LLVector4), // TYPE_NORMAL, @@ -344,7 +344,7 @@ S32 LLVertexBuffer::sTypeSize[LLVertexBuffer::TYPE_MAX] =  	sizeof(LLVector4), // TYPE_TEXTURE_INDEX (actually exists as position.w), no extra data, but stride is 16 bytes  }; -static std::string vb_type_name[] = +static const std::string vb_type_name[] =  {  	"TYPE_VERTEX",  	"TYPE_NORMAL", @@ -363,7 +363,7 @@ static std::string vb_type_name[] =  	"TYPE_INDEX",	  }; -U32 LLVertexBuffer::sGLMode[LLRender::NUM_MODES] =  +const U32 LLVertexBuffer::sGLMode[LLRender::NUM_MODES] =  {  	GL_TRIANGLES,  	GL_TRIANGLE_STRIP, @@ -512,7 +512,7 @@ void LLVertexBuffer::setupClientArrays(U32 data_mask)  				}  			} -			U32 map_tc[] =  +			static const U32 map_tc[] =   			{  				MAP_TEXCOORD1,  				MAP_TEXCOORD2, @@ -1382,7 +1382,7 @@ void LLVertexBuffer::setupVertexArray()  #endif  	sGLRenderArray = mGLArray; -	U32 attrib_size[] =  +	static const U32 attrib_size[] =   	{  		3, //TYPE_VERTEX,  		3, //TYPE_NORMAL, @@ -1399,7 +1399,7 @@ void LLVertexBuffer::setupVertexArray()  		1, //TYPE_TEXTURE_INDEX  	}; -	U32 attrib_type[] = +	static const U32 attrib_type[] =  	{  		GL_FLOAT, //TYPE_VERTEX,  		GL_FLOAT, //TYPE_NORMAL, @@ -1416,7 +1416,7 @@ void LLVertexBuffer::setupVertexArray()  		GL_UNSIGNED_INT, //TYPE_TEXTURE_INDEX  	}; -	bool attrib_integer[] =  +	static const bool attrib_integer[] =  	{  		false, //TYPE_VERTEX,  		false, //TYPE_NORMAL, @@ -1433,7 +1433,7 @@ void LLVertexBuffer::setupVertexArray()  		true, //TYPE_TEXTURE_INDEX  	}; -	U32 attrib_normalized[] = +	static const U32 attrib_normalized[] =  	{  		GL_FALSE, //TYPE_VERTEX,  		GL_FALSE, //TYPE_NORMAL, diff --git a/indra/llrender/llvertexbuffer.h b/indra/llrender/llvertexbuffer.h index bd27296eb6..c89d7e3958 100644 --- a/indra/llrender/llvertexbuffer.h +++ b/indra/llrender/llvertexbuffer.h @@ -341,8 +341,8 @@ public:  	static bool sDisableVBOMapping; //disable glMapBufferARB  	static bool sEnableVBOs; -	static S32 sTypeSize[TYPE_MAX]; -	static U32 sGLMode[LLRender::NUM_MODES]; +	static const S32 sTypeSize[TYPE_MAX]; +	static const U32 sGLMode[LLRender::NUM_MODES];  	static U32 sGLRenderBuffer;  	static U32 sGLRenderArray;  	static U32 sGLRenderIndices; diff --git a/indra/llxml/llcontrol.h b/indra/llxml/llcontrol.h index 77065dcf8d..8136a3e88a 100644 --- a/indra/llxml/llcontrol.h +++ b/indra/llxml/llcontrol.h @@ -357,7 +357,8 @@ private:  		mCachedValue = convert_from_llsd<T>(controlp->get(), mType, name);  		// Add a listener to the controls signal... -		mConnection = controlp->getSignal()->connect( +		// NOTE: All listeners connected to 0 group, for guaranty that variable handlers (gSavedSettings) call last +		mConnection = controlp->getSignal()->connect(0,  			boost::bind(&LLControlCache<T>::handleValueChange, this, _2)  			);  		mType = controlp->type(); diff --git a/indra/newview/Info-SecondLife.plist b/indra/newview/Info-SecondLife.plist index af4cf26ac6..8aabd6818b 100644 --- a/indra/newview/Info-SecondLife.plist +++ b/indra/newview/Info-SecondLife.plist @@ -21,7 +21,7 @@  	<key>CFBundlePackageType</key>  	<string>APPL</string>  	<key>CFBundleShortVersionString</key> -	<string>${MACOSX_BUNDLE_LONG_VERSION_STRING}</string> +	<string>${MACOSX_BUNDLE_SHORT_VERSION_STRING}</string>  	<key>CFBundleSignature</key>  	<string>????</string>  	<key>CFBundleVersion</key> diff --git a/indra/newview/VIEWER_VERSION.txt b/indra/newview/VIEWER_VERSION.txt index 220d8e0a46..8710cfdff2 100644 --- a/indra/newview/VIEWER_VERSION.txt +++ b/indra/newview/VIEWER_VERSION.txt @@ -1 +1 @@ -5.1.5 +5.1.6 diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index bbd7f65383..b2b3b6bb05 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -4646,6 +4646,17 @@        <key>Value</key>        <integer>1</integer>      </map> +    <key>IgnoreFOVZoomForLODs</key> +    <map> +      <key>Comment</key> +      <string>Ignore zoom effect(CTRL+0) when calculating lods.</string> +      <key>Persist</key> +      <integer>1</integer> +      <key>Type</key> +      <string>Boolean</string> +      <key>Value</key> +      <integer>0</integer> +    </map>      <key>IgnoreAllNotifications</key>      <map>        <key>Comment</key> @@ -10170,9 +10181,9 @@    <key>RenderAutoMuteByteLimit</key>    <map>      <key>Comment</key> -    <string>OBSOLETE and UNUSED.</string> +    <string>If avatar attachment size exceed this value (in bytes) attachment will not be rendered. Excludes attachments worn by own avatar.</string>      <key>Persist</key> -    <integer>0</integer> +    <integer>1</integer>      <key>Type</key>      <string>U32</string>      <key>Value</key> diff --git a/indra/newview/llappdelegate-objc.mm b/indra/newview/llappdelegate-objc.mm index aebae4c434..8e1ad169c9 100644 --- a/indra/newview/llappdelegate-objc.mm +++ b/indra/newview/llappdelegate-objc.mm @@ -25,6 +25,9 @@   */  #import "llappdelegate-objc.h" +#if defined(LL_BUGSPLAT) +@import BugsplatMac; +#endif  #include "llwindowmacosx-objc.h"  #include <Carbon/Carbon.h> // Used for Text Input Services ("Safe" API - it's supported) @@ -64,6 +67,13 @@  	[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(languageUpdated) name:@"NSTextInputContextKeyboardSelectionDidChangeNotification" object:nil];   //   [[NSAppleEventManager sharedAppleEventManager] setEventHandler:self andSelector:@selector(handleGetURLEvent:withReplyEvent:) forEventClass:kInternetEventClass andEventID:kAEGetURL]; + +#if defined(LL_BUGSPLAT) +	// https://www.bugsplat.com/docs/platforms/os-x#initialization +//	[BugsplatStartupManager sharedManager].autoSubmitCrashReport = YES; +//	[BugsplatStartupManager sharedManager].askUserDetails = NO; +	[[BugsplatStartupManager sharedManager] start]; +#endif  }  - (void) handleGetURLEvent:(NSAppleEventDescriptor *)event withReplyEvent:(NSAppleEventDescriptor *)replyEvent { @@ -179,4 +189,21 @@      return true;  } +#if 0 // defined(LL_BUGSPLAT) + +@implementation BugsplatStartupManagerDelegate + +- (BugsplatAttachment *)attachmentForBugsplatStartupManager:(BugsplatStartupManager *)bugsplatStartupManager { +    NSURL *fileURL = [[NSBundle mainBundle] URLForResource:@"example" withExtension:@"json"]; +    NSData *data = [NSData dataWithContentsOfURL:fileURL]; +     +    BugsplatAttachment *attachment =  +        [[BugsplatAttachment alloc] initWithFilename:@"example.json" +                                      attachmentData:data +                                         contentType:@"application/json"]; +    return attachment; +} + +#endif // LL_BUGSPLAT +  @end diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp index 48b3a1c485..4701e7bbed 100644 --- a/indra/newview/llappviewerwin32.cpp +++ b/indra/newview/llappviewerwin32.cpp @@ -66,8 +66,70 @@  #endif  #include "stringize.h" +#include "lldir.h" +#include <fstream>  #include <exception> + +// Bugsplat (http://bugsplat.com) crash reporting tool +#ifdef LL_BUGSPLAT +#include "BugSplat.h" +#include "reader.h" // JsonCpp + +namespace +{ +    // MiniDmpSender's constructor is defined to accept __wchar_t* instead of +    // plain wchar_t*. That said, wunder() returns std::basic_string<__wchar_t>, +    // NOT plain __wchar_t*, despite the apparent convenience. Calling +    // wunder(something).c_str() as an argument expression is fine: that +    // std::basic_string instance will survive until the function returns. +    // Calling c_str() on a std::basic_string local to wunder() would be +    // Undefined Behavior: we'd be left with a pointer into a destroyed +    // std::basic_string instance. + +    // It would be nice if, when wchar_t is the same as __wchar_t, this whole +    // function would optimize away. However, we use it only for the arguments +    // to make exactly one call to initialize BugSplat. +    inline std::basic_string<__wchar_t> wunder(const std::wstring& str) +    { +        return { str.begin(), str.end() }; +    } + +    // when what we have in hand is a std::string, convert from UTF-8 using +    // specific wstringize() overload +    inline std::basic_string<__wchar_t> wunder(const std::string& str) +    { +        return wunder(wstringize(str)); +    } + +    // Irritatingly, MiniDmpSender::setCallback() is defined to accept a +    // classic-C function pointer instead of an arbitrary C++ callable. If it +    // did accept a modern callable, we could pass a lambda that binds our +    // MiniDmpSender pointer. As things stand, though, we must define an +    // actual function and store the pointer statically. +    static MiniDmpSender *sBugSplatSender = nullptr; + +    bool bugsplatSendLog(UINT nCode, LPVOID lpVal1, LPVOID lpVal2) +    { +        // If we haven't yet initialized LLDir, don't bother trying to +        // find our log file. +        // Alternatively -- if we might encounter trouble trying to query +        // LLDir during crash cleanup -- consider making gDirUtilp an +        // LLPounceable, and attach a callback that stores the pathname to +        // the log file here. +        if (nCode == MDSCB_EXCEPTIONCODE && gDirUtilp) +        { +            // send the main viewer log file +            // widen to wstring, convert to __wchar_t, then pass c_str() +            sBugSplatSender->sendAdditionalFile( +                wunder(gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "SecondLife.log")).c_str()); +        } + +        return false; +    } +} +#endif // LL_BUGSPLAT +  namespace  {      void (*gOldTerminateHandler)() = NULL; @@ -495,15 +557,72 @@ bool LLAppViewerWin32::init()  	LLWinDebug::instance();  #endif -#if LL_WINDOWS  #if LL_SEND_CRASH_REPORTS - +#if ! defined(LL_BUGSPLAT)  	LLAppViewer* pApp = LLAppViewer::instance();  	pApp->initCrashReporting(); -#endif -#endif +#else // LL_BUGSPLAT + +	if (! gDirUtilp) +	{ +		LL_WARNS() << "Can't initialize BugSplat, gDirUtilp not yet set" << LL_ENDL; +	} +	else +	{ +		std::string build_data_fname( +			gDirUtilp->getExpandedFilename(LL_PATH_EXECUTABLE, "build_data.json")); +		std::ifstream inf(build_data_fname.c_str()); +		if (! inf.is_open()) +		{ +			LL_WARNS() << "Can't initialize BugSplat, can't read '" << build_data_fname +					   << "'" << LL_ENDL; +		} +		else +		{ +			Json::Reader reader; +			Json::Value build_data; +			if (! reader.parse(inf, build_data, false)) // don't collect comments +			{ +				// gah, the typo is baked into their API +				LL_WARNS() << "Can't initialize BugSplat, can't parse '" << build_data_fname +						   << "': " << reader.getFormatedErrorMessages() << LL_ENDL; +			} +			else +			{ +				Json::Value BugSplat_DB = build_data["BugSplat DB"]; +				if (! BugSplat_DB) +				{ +					LL_WARNS() << "Can't initialize BugSplat, no 'BugSplat DB' entry in '" +							   << build_data_fname << "'" << LL_ENDL; +				} +				else +				{ +					// Got BugSplat_DB, onward! +					std::wstring version_string(WSTRINGIZE(LL_VIEWER_VERSION_MAJOR << '.' << +														   LL_VIEWER_VERSION_MINOR << '.' << +														   LL_VIEWER_VERSION_PATCH << '.' << +														   LL_VIEWER_VERSION_BUILD)); + +					// have to convert normal wide strings to strings of __wchar_t +					sBugSplatSender = new MiniDmpSender( +						wunder(BugSplat_DB.asString()).c_str(), +						wunder(LL_TO_WSTRING(LL_VIEWER_CHANNEL)).c_str(), +						wunder(version_string).c_str(), +						nullptr); +					sBugSplatSender->setCallback(bugsplatSendLog); + +					// engage stringize() overload that converts from wstring +					LL_INFOS() << "Engaged BugSplat(" << LL_TO_STRING(LL_VIEWER_CHANNEL) +							   << stringize(version_string) << ')' << LL_ENDL; +				} // got BugSplat_DB +			} // parsed build_data.json +		} // opened build_data.json +	}  // gDirUtilp set + +#endif // LL_BUGSPLAT +#endif // LL_SEND_CRASH_REPORTS  	bool success = LLAppViewer::init(); diff --git a/indra/newview/lldrawable.cpp b/indra/newview/lldrawable.cpp index f956023358..6ca8f1ae9c 100644 --- a/indra/newview/lldrawable.cpp +++ b/indra/newview/lldrawable.cpp @@ -50,6 +50,7 @@  #include "llviewerobjectlist.h"  #include "llviewerwindow.h"  #include "llvocache.h" +#include "lldrawpoolavatar.h"  const F32 MIN_INTERPOLATE_DISTANCE_SQUARED = 0.001f * 0.001f;  const F32 MAX_INTERPOLATE_DISTANCE_SQUARED = 10.f * 10.f; @@ -143,6 +144,28 @@ void LLDrawable::init(bool new_entry)  	initVisible(sCurVisible - 2);//invisible for the current frame and the last frame.  } +void LLDrawable::unload() +{ +	LLVOVolume *pVVol = getVOVolume(); +	pVVol->setNoLOD(); + +	for (S32 i = 0; i < getNumFaces(); i++) +	{ +		LLFace* facep = getFace(i); +		if (facep->isState(LLFace::RIGGED)) +		{ +			LLDrawPoolAvatar* pool = (LLDrawPoolAvatar*)facep->getPool(); +			if (pool) { +				pool->removeRiggedFace(facep); +			} +			facep->setVertexBuffer(NULL); +		} +		facep->clearState(LLFace::RIGGED); +	} + +	pVVol->markForUpdate(TRUE); +} +  // static  void LLDrawable::initClass()  { @@ -595,7 +618,7 @@ F32 LLDrawable::updateXform(BOOL undamped)  	BOOL damped = !undamped;  	// Position -	LLVector3 old_pos(mXform.getPosition()); +	const LLVector3 old_pos(mXform.getPosition());  	LLVector3 target_pos;  	if (mXform.isRoot())  	{ @@ -609,7 +632,7 @@ F32 LLDrawable::updateXform(BOOL undamped)  	}  	// Rotation -	LLQuaternion old_rot(mXform.getRotation()); +	const LLQuaternion old_rot(mXform.getRotation());  	LLQuaternion target_rot = mVObjp->getRotation();  	//scaling  	LLVector3 target_scale = mVObjp->getScale(); @@ -644,6 +667,9 @@ F32 LLDrawable::updateXform(BOOL undamped)  		{  			// snap to final position (only if no target omega is applied)  			dist_squared = 0.0f; +			//set target scale here, because of dist_squared = 0.0f remove object from move list +			mCurrentScale = target_scale; +  			if (getVOVolume() && !isRoot())  			{ //child prim snapping to some position, needs a rebuild  				gPipeline.markRebuild(this, LLDrawable::REBUILD_POSITION, TRUE); @@ -660,11 +686,16 @@ F32 LLDrawable::updateXform(BOOL undamped)  		//dist_squared += dist_vec_squared(old_scale, target_scale);  	} -	LLVector3 vec = mCurrentScale-target_scale; +	const LLVector3 vec = mCurrentScale-target_scale; +	 +	//It's a very important on each cycle on Drawable::update form(), when object remained in move +	//, list update the CurrentScale member, because if do not do that, it remained in this list forever  +	//or when the delta time between two frames a become a sufficiently large (due to interpolation)  +	//for overcome the MIN_INTERPOLATE_DISTANCE_SQUARED. +	mCurrentScale = target_scale;  	if (vec*vec > MIN_INTERPOLATE_DISTANCE_SQUARED)  	{ //scale change requires immediate rebuild -		mCurrentScale = target_scale;  		gPipeline.markRebuild(this, LLDrawable::REBUILD_POSITION, TRUE);  	}  	else if (!isRoot() &&  @@ -979,9 +1010,7 @@ void LLDrawable::updateSpatialExtents()  	if (mVObjp)  	{  		const LLVector4a* exts = getSpatialExtents(); -		LLVector4a extents[2]; -		extents[0] = exts[0]; -		extents[1] = exts[1]; +		LLVector4a extents[2] = { exts[0], exts[1] };  		mVObjp->updateSpatialExtents(extents[0], extents[1]);  		setSpatialExtents(extents[0], extents[1]); diff --git a/indra/newview/lldrawable.h b/indra/newview/lldrawable.h index a3461d4c01..14d782d6f2 100644 --- a/indra/newview/lldrawable.h +++ b/indra/newview/lldrawable.h @@ -84,6 +84,7 @@ public:  	void markDead();			// Mark this drawable as dead  	BOOL isDead() const			{ return isState(DEAD); }  	BOOL isNew() const			{ return !isState(BUILT); } +	BOOL isUnload() const		{ return isState(FOR_UNLOAD); }  	BOOL isLight() const; @@ -141,6 +142,7 @@ public:  	void				mergeFaces(LLDrawable* src);  	void init(bool new_entry); +	void unload();  	void destroy();  	void update(); @@ -282,6 +284,7 @@ public:  		PARTITION_MOVE	= 0x10000000,  		ANIMATED_CHILD  = 0x20000000,  		ACTIVE_CHILD	= 0x40000000, +		FOR_UNLOAD		= 0x80000000, //should be unload from memory  	} EDrawableFlags;  public: diff --git a/indra/newview/lldrawpool.cpp b/indra/newview/lldrawpool.cpp index f74164aea6..075375082d 100644 --- a/indra/newview/lldrawpool.cpp +++ b/indra/newview/lldrawpool.cpp @@ -49,6 +49,7 @@  #include "llviewercamera.h"  #include "lldrawpoolwlsky.h"  #include "llglslshader.h" +#include "llglcommonfunc.h"  S32 LLDrawPool::sNumDrawPools = 0; @@ -504,7 +505,9 @@ void LLRenderPass::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, BOOL ba  		{  			params.mGroup->rebuildMesh();  		} -		 + +		LLGLEnableFunc stencil_test(GL_STENCIL_TEST, params.mSelected, &LLGLCommonFunc::selected_stencil_test); +	  		params.mVertexBuffer->setBuffer(mask);  		params.mVertexBuffer->drawRange(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset);  		gPipeline.addTrianglesDrawn(params.mCount, params.mDrawMode); diff --git a/indra/newview/lldrawpoolalpha.cpp b/indra/newview/lldrawpoolalpha.cpp index 60056ac21d..32630237ce 100644 --- a/indra/newview/lldrawpoolalpha.cpp +++ b/indra/newview/lldrawpoolalpha.cpp @@ -47,6 +47,7 @@  #include "llviewerregion.h"  #include "lldrawpoolwater.h"  #include "llspatialpartition.h" +#include "llglcommonfunc.h"  BOOL LLDrawPoolAlpha::sShowDebugAlpha = FALSE; @@ -583,11 +584,14 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, S32 pass)  				{  					LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_PUSH); -    gGL.blendFunc((LLRender::eBlendFactor) params.mBlendFuncSrc, (LLRender::eBlendFactor) params.mBlendFuncDst, mAlphaSFactor, mAlphaDFactor);					 -				params.mVertexBuffer->setBuffer(mask & ~(params.mFullbright ? (LLVertexBuffer::MAP_TANGENT | LLVertexBuffer::MAP_TEXCOORD1 | LLVertexBuffer::MAP_TEXCOORD2) : 0)); -                 -				params.mVertexBuffer->drawRange(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset); -				gPipeline.addTrianglesDrawn(params.mCount, params.mDrawMode); + +					LLGLEnableFunc stencil_test(GL_STENCIL_TEST, params.mSelected, &LLGLCommonFunc::selected_stencil_test); + +					gGL.blendFunc((LLRender::eBlendFactor) params.mBlendFuncSrc, (LLRender::eBlendFactor) params.mBlendFuncDst, mAlphaSFactor, mAlphaDFactor); +					params.mVertexBuffer->setBuffer(mask & ~(params.mFullbright ? (LLVertexBuffer::MAP_TANGENT | LLVertexBuffer::MAP_TEXCOORD1 | LLVertexBuffer::MAP_TEXCOORD2) : 0)); + +					params.mVertexBuffer->drawRange(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset); +					gPipeline.addTrianglesDrawn(params.mCount, params.mDrawMode);  				}  				// If this alpha mesh has glow, then draw it a second time to add the destination-alpha (=glow).  Interleaving these state-changing calls could be expensive, but glow must be drawn Z-sorted with alpha. @@ -597,7 +601,7 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, S32 pass)  				{  					// install glow-accumulating blend mode  					gGL.blendFunc(LLRender::BF_ZERO, LLRender::BF_ONE, // don't touch color -						      LLRender::BF_ONE, LLRender::BF_ONE); // add to alpha (glow) +					LLRender::BF_ONE, LLRender::BF_ONE); // add to alpha (glow)  					emissive_shader->bind(); diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp index 8128790eb6..ef69990170 100644 --- a/indra/newview/lldrawpoolavatar.cpp +++ b/indra/newview/lldrawpoolavatar.cpp @@ -1574,6 +1574,11 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(  	LLPointer<LLVertexBuffer> buffer = face->getVertexBuffer();  	LLDrawable* drawable = face->getDrawable(); +	if (drawable->getVOVolume() && drawable->getVOVolume()->isNoLOD()) +	{ +		return; +	} +  	U32 data_mask = face->getRiggedVertexBufferDataMask();      if (!vol_face.mWeightsScrubbed) @@ -1621,7 +1626,9 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(  		return;  	} -	if (sShaderLevel <= 0 && face->mLastSkinTime < avatar->getLastSkinTime()) +	if (!buffer.isNull() &&  +		sShaderLevel <= 0 &&  +		face->mLastSkinTime < avatar->getLastSkinTime())  	{  		//perform software vertex skinning for this face  		LLStrider<LLVector3> position; @@ -1914,7 +1921,7 @@ void LLDrawPoolAvatar::updateRiggedVertexBuffers(LLVOAvatar* avatar)  			LLVOVolume* vobj = drawable->getVOVolume(); -			if (!vobj) +			if (!vobj || vobj->isNoLOD())  			{  				continue;  			} diff --git a/indra/newview/lldrawpoolmaterials.cpp b/indra/newview/lldrawpoolmaterials.cpp index f92320490a..63e96a93b5 100644 --- a/indra/newview/lldrawpoolmaterials.cpp +++ b/indra/newview/lldrawpoolmaterials.cpp @@ -30,6 +30,7 @@  #include "lldrawpoolmaterials.h"  #include "llviewershadermgr.h"  #include "pipeline.h" +#include "llglcommonfunc.h"  S32 diffuse_channel = -1; @@ -211,6 +212,9 @@ void LLDrawPoolMaterials::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture,  	{  		params.mGroup->rebuildMesh();  	} + +	LLGLEnableFunc stencil_test(GL_STENCIL_TEST, params.mSelected, &LLGLCommonFunc::selected_stencil_test); +  	params.mVertexBuffer->setBuffer(mask);  	params.mVertexBuffer->drawRange(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset);  	gPipeline.addTrianglesDrawn(params.mCount, params.mDrawMode); diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp index 50a4925c37..7f7d7f3dcc 100644 --- a/indra/newview/llface.cpp +++ b/indra/newview/llface.cpp @@ -53,6 +53,7 @@  #include "llviewershadermgr.h"  #include "llviewertexture.h"  #include "llvoavatar.h" +#include "llsculptidsize.h"  #if LL_LINUX  // Work-around spurious used before init warning on Vector4a @@ -2650,12 +2651,27 @@ LLViewerTexture* LLFace::getTexture(U32 ch) const  void LLFace::setVertexBuffer(LLVertexBuffer* buffer)  { +	if (buffer) +	{ +		LLSculptIDSize::instance().inc(mDrawablep, buffer->getSize() + buffer->getIndicesSize()); +	} + +	if (mVertexBuffer) +	{ +		LLSculptIDSize::instance().dec(mDrawablep); +	} +  	mVertexBuffer = buffer;  	llassert(verify());  }  void LLFace::clearVertexBuffer()  { +	if (mVertexBuffer) +	{ +		LLSculptIDSize::instance().dec(mDrawablep); +	} +  	mVertexBuffer = NULL;  } diff --git a/indra/newview/llmaniprotate.cpp b/indra/newview/llmaniprotate.cpp index 7bd5e4cba2..f158aae3d2 100644 --- a/indra/newview/llmaniprotate.cpp +++ b/indra/newview/llmaniprotate.cpp @@ -283,6 +283,7 @@ void LLManipRotate::render()  			LLGLEnable cull_face(GL_CULL_FACE);  			LLGLEnable clip_plane0(GL_CLIP_PLANE0);  			LLGLDepthTest gls_depth(GL_FALSE); +			LLGLDisable gls_stencil(GL_STENCIL_TEST);  			// First pass: centers. Second pass: sides.  			for( S32 i=0; i<2; i++ ) diff --git a/indra/newview/llmanipscale.cpp b/indra/newview/llmanipscale.cpp index 8b2ac4f303..9a8222d941 100644 --- a/indra/newview/llmanipscale.cpp +++ b/indra/newview/llmanipscale.cpp @@ -754,6 +754,7 @@ void LLManipScale::renderBoxHandle( F32 x, F32 y, F32 z )  {  	gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);  	LLGLDepthTest gls_depth(GL_FALSE); +	LLGLDisable gls_stencil(GL_STENCIL_TEST);  	gGL.pushMatrix();  	{ diff --git a/indra/newview/llmaniptranslate.cpp b/indra/newview/llmaniptranslate.cpp index 785022792b..92a09357c8 100644 --- a/indra/newview/llmaniptranslate.cpp +++ b/indra/newview/llmaniptranslate.cpp @@ -1060,6 +1060,7 @@ void LLManipTranslate::render()  		renderGuidelines();  	}  	{ +		LLGLDisable gls_stencil(GL_STENCIL_TEST);  		renderTranslationHandles();  		renderSnapGuides();  	} @@ -1638,8 +1639,8 @@ void LLManipTranslate::highlightIntersection(LLVector3 normal,  	LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr; -	U32 types[] = { LLRenderPass::PASS_SIMPLE, LLRenderPass::PASS_ALPHA, LLRenderPass::PASS_FULLBRIGHT, LLRenderPass::PASS_SHINY }; -	U32 num_types = LL_ARRAY_SIZE(types); +	static const U32 types[] = { LLRenderPass::PASS_SIMPLE, LLRenderPass::PASS_ALPHA, LLRenderPass::PASS_FULLBRIGHT, LLRenderPass::PASS_SHINY }; +	static const U32 num_types = LL_ARRAY_SIZE(types);  	GLuint stencil_mask = 0xFFFFFFFF;  	//stencil in volumes diff --git a/indra/newview/llmaterialmgr.cpp b/indra/newview/llmaterialmgr.cpp index d9fc489b4e..52b9fb40ae 100644 --- a/indra/newview/llmaterialmgr.cpp +++ b/indra/newview/llmaterialmgr.cpp @@ -350,6 +350,25 @@ void LLMaterialMgr::remove(const LLUUID& object_id, const U8 te)  	put(object_id, te, LLMaterial::null);  } +void LLMaterialMgr::setLocalMaterial(const LLUUID& region_id, LLMaterialPtr material_ptr) +{ +	LLUUID uuid; +	uuid.generate(); +	LLMaterialID material_id(uuid); +	while (mMaterials.end() != mMaterials.find(material_id))  +	{ //probability that this loop will executed is very, very low (one in a billion chance) +		uuid.generate(); +		material_id.set(uuid.mData); +	}	 + +	LL_DEBUGS("Materials") << "region " << region_id << "new local material id " << material_id << LL_ENDL; +	mMaterials.insert(std::pair<LLMaterialID, LLMaterialPtr>(material_id, material_ptr)); + +	setMaterialCallbacks(material_id, material_ptr); + +	mGetPending.erase(pending_material_t(region_id, material_id)); +} +  const LLMaterialPtr LLMaterialMgr::setMaterial(const LLUUID& region_id, const LLMaterialID& material_id, const LLSD& material_data)  {  	LL_DEBUGS("Materials") << "region " << region_id << " material id " << material_id << LL_ENDL; @@ -362,17 +381,26 @@ const LLMaterialPtr LLMaterialMgr::setMaterial(const LLUUID& region_id, const LL  		itMaterial = ret.first;  	} +	setMaterialCallbacks(material_id, itMaterial->second); + +	mGetPending.erase(pending_material_t(region_id, material_id)); + +	return itMaterial->second; +} + +void LLMaterialMgr::setMaterialCallbacks(const LLMaterialID& material_id, const LLMaterialPtr material_ptr) +{  	TEMaterialPair te_mat_pair;  	te_mat_pair.materialID = material_id;  	U32 i = 0; -	while (i < LLTEContents::MAX_TES) +	while (i < LLTEContents::MAX_TES && !mGetTECallbacks.empty())  	{  		te_mat_pair.te = i++;  		get_callback_te_map_t::iterator itCallbackTE = mGetTECallbacks.find(te_mat_pair);  		if (itCallbackTE != mGetTECallbacks.end())  		{ -			(*itCallbackTE->second)(material_id, itMaterial->second, te_mat_pair.te); +			(*itCallbackTE->second)(material_id, material_ptr, te_mat_pair.te);  			delete itCallbackTE->second;  			mGetTECallbacks.erase(itCallbackTE);  		} @@ -381,15 +409,11 @@ const LLMaterialPtr LLMaterialMgr::setMaterial(const LLUUID& region_id, const LL  	get_callback_map_t::iterator itCallback = mGetCallbacks.find(material_id);  	if (itCallback != mGetCallbacks.end())  	{ -		(*itCallback->second)(material_id, itMaterial->second); +		(*itCallback->second)(material_id, material_ptr);  		delete itCallback->second;  		mGetCallbacks.erase(itCallback);  	} - -	mGetPending.erase(pending_material_t(region_id, material_id)); - -	return itMaterial->second;  }  void LLMaterialMgr::onGetResponse(bool success, const LLSD& content, const LLUUID& region_id) diff --git a/indra/newview/llmaterialmgr.h b/indra/newview/llmaterialmgr.h index 60b58d17de..843dc66fbc 100644 --- a/indra/newview/llmaterialmgr.h +++ b/indra/newview/llmaterialmgr.h @@ -56,6 +56,9 @@ public:  	boost::signals2::connection getAll(const LLUUID& region_id, getall_callback_t::slot_type cb);  	void put(const LLUUID& object_id, const U8 te, const LLMaterial& material);  	void remove(const LLUUID& object_id, const U8 te); +	 +	//explicitly add new material to material manager +	void setLocalMaterial(const LLUUID& region_id, LLMaterialPtr material_ptr);  private:  	void clearGetQueues(const LLUUID& region_id); @@ -63,7 +66,8 @@ private:  	bool isGetAllPending(const LLUUID& region_id) const;  	void markGetPending(const LLUUID& region_id, const LLMaterialID& material_id);  	const LLMaterialPtr setMaterial(const LLUUID& region_id, const LLMaterialID& material_id, const LLSD& material_data); - +	void setMaterialCallbacks(const LLMaterialID& material_id, const LLMaterialPtr material_ptr); +	  	static void onIdle(void*);      static void CapsRecvForRegion(const LLUUID& regionId, LLUUID regionTest, std::string pumpname); diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp index 71a161198a..5b6720c3c7 100644 --- a/indra/newview/llmeshrepository.cpp +++ b/indra/newview/llmeshrepository.cpp @@ -4027,7 +4027,7 @@ void LLMeshRepository::uploadModel(std::vector<LLModelInstance>& data, LLVector3  S32 LLMeshRepository::getMeshSize(const LLUUID& mesh_id, S32 lod)  { -	if (mThread && mesh_id.notNull()) +	if (mThread && mesh_id.notNull() && LLPrimitive::NO_LOD != lod)  	{  		LLMutexLock lock(mThread->mHeaderMutex);  		LLMeshRepoThread::mesh_header_map::iterator iter = mThread->mMeshHeader.find(mesh_id); diff --git a/indra/newview/llsculptidsize.cpp b/indra/newview/llsculptidsize.cpp new file mode 100644 index 0000000000..9edd78bff0 --- /dev/null +++ b/indra/newview/llsculptidsize.cpp @@ -0,0 +1,154 @@ +/** +* @file llsculptidsize.cpp +* @brief LLSculptIDSize class implementation +* +* $LicenseInfo:firstyear=2002&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2010, Linden Research, Inc. +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; +* version 2.1 of the License only. +* +* This library is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA +* +* Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA +* $/LicenseInfo$ +*/ + +#include "llviewerprecompiledheaders.h" +#include "llsculptidsize.h" +#include "llvovolume.h" +#include "lldrawable.h" +#include "llvoavatar.h" +//boost +#include "boost/make_shared.hpp" + +//........... + +extern LLControlGroup gSavedSettings; + +//........... + +typedef std::pair<LLSculptIDSize::container_BY_SCULPT_ID_view::iterator, LLSculptIDSize::container_BY_SCULPT_ID_view::iterator> pair_iter_iter_BY_SCULPT_ID_t; + +//........... + +void _nothing_to_do_func(int) { /*nothing todo here because of the size it's a shared member*/ } + +void LLSculptIDSize::inc(const LLDrawable *pdrawable, int sz) +{ +	llassert(sz >= 0); + +	if (!pdrawable) return; +	LLVOVolume* vvol = pdrawable->getVOVolume(); +	if (!vvol) return; +	if (!vvol->isAttachment()) return; +	if (!vvol->getAvatar()) return; +	if (vvol->getAvatar()->isSelf()) return; +	LLVolume *vol = vvol->getVolume(); +	if (!vol) return; + +	const LLUUID &sculptId = vol->getParams().getSculptID(); +	if (sculptId.isNull()) return; + +	unsigned int total_size = 0; + +	pair_iter_iter_BY_SCULPT_ID_t itLU = mSizeInfo.get<tag_BY_SCULPT_ID>().equal_range(sculptId); +	if (itLU.first == itLU.second) +	{ //register +		llassert(mSizeInfo.get<tag_BY_DRAWABLE>().end() == mSizeInfo.get<tag_BY_DRAWABLE>().find(pdrawable)); +		mSizeInfo.get<tag_BY_DRAWABLE>().insert(Info(pdrawable, sz, boost::make_shared<SizeSum>(sz), sculptId)); +		total_size = sz; +	} +	else +	{ //update + register +		Info &nfo = const_cast<Info &>(*itLU.first); +		//calc new size +		total_size = nfo.getSizeSum() + sz; +		nfo.mSharedSizeSum->mSizeSum = total_size; +		nfo.mSize = sz; +		//update size for all LLDrwable in range of sculptId +		for (pair_iter_iter_BY_SCULPT_ID_t::first_type it = itLU.first; it != itLU.second; ++it) +		{ +			mSizeInfo.get<tag_BY_SIZE>().modify_key(mSizeInfo.project<tag_BY_SIZE>(it), boost::bind(&_nothing_to_do_func, _1)); +		} + +		//trying insert the LLDrawable +		mSizeInfo.get<tag_BY_DRAWABLE>().insert(Info(pdrawable, sz, nfo.mSharedSizeSum, sculptId)); +	} + +	static LLCachedControl<U32> render_auto_mute_byte_limit(gSavedSettings, "RenderAutoMuteByteLimit", 0U); + +	if (0 != render_auto_mute_byte_limit && total_size > render_auto_mute_byte_limit) +	{ +		pair_iter_iter_BY_SCULPT_ID_t it_eqr = mSizeInfo.get<tag_BY_SCULPT_ID>().equal_range(sculptId); +		for (; it_eqr.first != it_eqr.second; ++it_eqr.first) +		{ +			const Info &i = *it_eqr.first; +			LLVOVolume *pVVol = i.mDrawable->getVOVolume(); +			if (pVVol +				&& !pVVol->isDead() +				&& pVVol->isAttachment() +				&& !pVVol->getAvatar()->isSelf() +				&& LLVOVolume::NO_LOD != pVVol->getLOD() +				) +			{ +				addToUnloaded(sculptId); +				//immediately +				const_cast<LLDrawable*>(i.mDrawable)->unload(); +			} +		} +	} +} + +void LLSculptIDSize::dec(const LLDrawable *pdrawable) +{ +	container_BY_DRAWABLE_view::iterator it = mSizeInfo.get<tag_BY_DRAWABLE>().find(pdrawable); +	if (mSizeInfo.get<tag_BY_DRAWABLE>().end() == it) return; + +	unsigned int size = it->getSizeSum() - it->getSize(); + +	if (0 == size) +	{ +		mSizeInfo.get<tag_BY_SCULPT_ID>().erase(it->getSculptId()); +	} +	else +	{ +		Info &nfo = const_cast<Info &>(*it); +		nfo.mSize = 0; +		pair_iter_iter_BY_SCULPT_ID_t itLU = mSizeInfo.get<tag_BY_SCULPT_ID>().equal_range(it->getSculptId()); +		it->mSharedSizeSum->mSizeSum = size; +		for (pair_iter_iter_BY_SCULPT_ID_t::first_type it = itLU.first; it != itLU.second; ++it) +		{ +			mSizeInfo.get<tag_BY_SIZE>().modify_key(mSizeInfo.project<tag_BY_SIZE>(it), boost::bind(&_nothing_to_do_func, _1)); +		} +	} +} + +void LLSculptIDSize::rem(const LLUUID &sculptId) +{ +	mSizeInfo.get<tag_BY_SCULPT_ID>().erase(sculptId); +} + +void LLSculptIDSize::resetSizeSum(const LLUUID &sculptId) +{ +	const pair_iter_iter_BY_SCULPT_ID_t itLU = mSizeInfo.get<tag_BY_SCULPT_ID>().equal_range(sculptId); + +	if (itLU.first != itLU.second) { +		itLU.first->mSharedSizeSum->mSizeSum = 0; +	} + +	for (pair_iter_iter_BY_SCULPT_ID_t::first_type it = itLU.first, itE = itLU.second; it != itE; ++it) +	{ +		mSizeInfo.get<tag_BY_SIZE>().modify_key(mSizeInfo.project<tag_BY_SIZE>(it), boost::bind(&_nothing_to_do_func, _1)); +	} +} diff --git a/indra/newview/llsculptidsize.h b/indra/newview/llsculptidsize.h new file mode 100644 index 0000000000..87ee417b86 --- /dev/null +++ b/indra/newview/llsculptidsize.h @@ -0,0 +1,134 @@ +/** +* @file llsculptidsize.h +* @brief LLSculptIDSize class definition +* +* $LicenseInfo:firstyear=2009&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2010, Linden Research, Inc. +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; +* version 2.1 of the License only. +* +* This library is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA +* +* Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA +* $/LicenseInfo$ +*/ + +#ifndef LL_LLSCULPTIDSIZE_H +#define LL_LLSCULPTIDSIZE_H + +#include "lluuid.h" + +//std +#include <set> +//boost +#include "boost/multi_index_container.hpp" +#include "boost/multi_index/ordered_index.hpp" +#include "boost/multi_index/mem_fun.hpp" + +class LLDrawable; + + +class LLSculptIDSize +{ +public: +	struct SizeSum +	{ +		SizeSum(int size)  +			: mSizeSum(size) +		{} +		unsigned int mSizeSum; +	}; + +	struct Info +	{ +		typedef boost::shared_ptr<SizeSum> PtrSizeSum; + +		Info(const LLDrawable *drawable, int size, PtrSizeSum sizeInfo, LLUUID sculptId) +			: mDrawable(drawable) +			, mSize(size) +			, mSharedSizeSum(sizeInfo) +			, mSculptId(sculptId) +		{} + +		const LLDrawable *mDrawable; +		unsigned int mSize; +		PtrSizeSum	mSharedSizeSum; +		LLUUID mSculptId; + +		inline const LLDrawable*	getPtrLLDrawable() const { return mDrawable; } +		inline unsigned int			getSize() const { return mSize; } +		inline unsigned int			getSizeSum() const { return mSharedSizeSum->mSizeSum; } +		inline LLUUID				getSculptId() const { return mSculptId; } +		PtrSizeSum					getSizeInfo() { return mSharedSizeSum; } +	}; + +public: +	//tags +	struct tag_BY_DRAWABLE {}; +	struct tag_BY_SCULPT_ID {}; +	struct tag_BY_SIZE {}; + +	//container +	typedef boost::multi_index_container < +		Info, +		boost::multi_index::indexed_by < +		boost::multi_index::ordered_unique< boost::multi_index::tag<tag_BY_DRAWABLE> +		, boost::multi_index::const_mem_fun<Info, const LLDrawable*, &Info::getPtrLLDrawable> +		> +		, boost::multi_index::ordered_non_unique<boost::multi_index::tag<tag_BY_SCULPT_ID> +		, boost::multi_index::const_mem_fun<Info, LLUUID, &Info::getSculptId> +		> +		, boost::multi_index::ordered_non_unique < boost::multi_index::tag<tag_BY_SIZE> +		, boost::multi_index::const_mem_fun < Info, unsigned int, &Info::getSizeSum > +		> +		> +	> container; + +	//views +	typedef container::index<tag_BY_DRAWABLE>::type			container_BY_DRAWABLE_view; +	typedef container::index<tag_BY_SCULPT_ID>::type		container_BY_SCULPT_ID_view; +	typedef container::index<tag_BY_SIZE>::type				container_BY_SIZE_view; + +private: +	LLSculptIDSize() +	{} + +public: +	static LLSculptIDSize & instance()  +	{ +		static LLSculptIDSize inst; +		return inst; +	} + +public: +	void inc(const LLDrawable *pdrawable, int sz); +	void dec(const LLDrawable *pdrawable); +	void rem(const LLUUID &sculptId); + +	inline void addToUnloaded(const LLUUID &sculptId) { mMarkAsUnloaded.insert(sculptId); } +	inline void remFromUnloaded(const LLUUID &sculptId) { mMarkAsUnloaded.erase(sculptId); } +	inline bool isUnloaded(const LLUUID &sculptId) const { return mMarkAsUnloaded.end() != mMarkAsUnloaded.find(sculptId); } +	inline void clearUnloaded() { mMarkAsUnloaded.clear(); } +	 +	void resetSizeSum(const LLUUID &sculptId); + +	inline const container & getSizeInfo() const { return mSizeInfo; } + +private: +	container mSizeInfo; +	typedef std::set<LLUUID> std_LLUUID; +	std_LLUUID mMarkAsUnloaded; +}; + +#endif diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp index c44aca6fa5..ddae109030 100644 --- a/indra/newview/llselectmgr.cpp +++ b/indra/newview/llselectmgr.cpp @@ -6271,92 +6271,107 @@ void pushWireframe(LLDrawable* drawable)  void LLSelectNode::renderOneWireframe(const LLColor4& color)  { -	//Need to because crash on ATI 3800 (and similar cards) MAINT-5018  -	LLGLDisable multisample(LLPipeline::RenderFSAASamples > 0 ? GL_MULTISAMPLE_ARB : 0); +    //Need to because crash on ATI 3800 (and similar cards) MAINT-5018  +    LLGLDisable multisample(LLPipeline::RenderFSAASamples > 0 ? GL_MULTISAMPLE_ARB : 0); -	LLViewerObject* objectp = getObject(); -	if (!objectp) -	{ -		return; -	} +    LLViewerObject* objectp = getObject(); +    if (!objectp) +    { +        return; +    } -	LLDrawable* drawable = objectp->mDrawable; -	if(!drawable) -	{ -		return; -	} +    LLDrawable* drawable = objectp->mDrawable; +    if (!drawable) +    { +        return; +    } -	LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr; +    LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr; -	if (shader) -	{ -		gDebugProgram.bind(); -	} +    if (shader) +    { +        gDebugProgram.bind(); +    } -	gGL.matrixMode(LLRender::MM_MODELVIEW); -	gGL.pushMatrix(); -	 -	BOOL is_hud_object = objectp->isHUDAttachment(); +    gGL.matrixMode(LLRender::MM_MODELVIEW); +    gGL.pushMatrix(); -	if (drawable->isActive()) -	{ -		gGL.loadMatrix(gGLModelView); -		gGL.multMatrix((F32*) objectp->getRenderMatrix().mMatrix); -	} -	else if (!is_hud_object) -	{ -		gGL.loadIdentity(); -		gGL.multMatrix(gGLModelView); -		LLVector3 trans = objectp->getRegion()->getOriginAgent();		 -		gGL.translatef(trans.mV[0], trans.mV[1], trans.mV[2]);		 -	} -	 -	glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); -	 -	if (LLSelectMgr::sRenderHiddenSelections) // && gFloaterTools && gFloaterTools->getVisible()) -	{ -		gGL.blendFunc(LLRender::BF_SOURCE_COLOR, LLRender::BF_ONE); -		LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE, GL_GEQUAL); -		if (shader) -		{ -			gGL.diffuseColor4f(color.mV[VRED], color.mV[VGREEN], color.mV[VBLUE], 0.4f); -			pushWireframe(drawable); -		} -		else -		{ -			LLGLEnable fog(GL_FOG); -			glFogi(GL_FOG_MODE, GL_LINEAR); -			float d = (LLViewerCamera::getInstance()->getPointOfInterest()-LLViewerCamera::getInstance()->getOrigin()).magVec(); -			LLColor4 fogCol = color * (F32)llclamp((LLSelectMgr::getInstance()->getSelectionCenterGlobal()-gAgentCamera.getCameraPositionGlobal()).magVec()/(LLSelectMgr::getInstance()->getBBoxOfSelection().getExtentLocal().magVec()*4), 0.0, 1.0); -			glFogf(GL_FOG_START, d); -			glFogf(GL_FOG_END, d*(1 + (LLViewerCamera::getInstance()->getView() / LLViewerCamera::getInstance()->getDefaultFOV()))); -			glFogfv(GL_FOG_COLOR, fogCol.mV); +    BOOL is_hud_object = objectp->isHUDAttachment(); -			gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); -			{ -				gGL.diffuseColor4f(color.mV[VRED], color.mV[VGREEN], color.mV[VBLUE], 0.4f); -				pushWireframe(drawable); -			} -		} -	} +    if (drawable->isActive()) +    { +        gGL.loadMatrix(gGLModelView); +        gGL.multMatrix((F32*)objectp->getRenderMatrix().mMatrix); +    } +    else if (!is_hud_object) +    { +        gGL.loadIdentity(); +        gGL.multMatrix(gGLModelView); +        LLVector3 trans = objectp->getRegion()->getOriginAgent(); +        gGL.translatef(trans.mV[0], trans.mV[1], trans.mV[2]); +    } -	gGL.flush(); -	gGL.setSceneBlendType(LLRender::BT_ALPHA); +    glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); -	gGL.diffuseColor4f(color.mV[VRED]*2, color.mV[VGREEN]*2, color.mV[VBLUE]*2, LLSelectMgr::sHighlightAlpha*2); -	 -	LLGLEnable offset(GL_POLYGON_OFFSET_LINE); -	glPolygonOffset(3.f, 3.f); -	glLineWidth(3.f); -	pushWireframe(drawable); -	glLineWidth(1.f); -	glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); -	gGL.popMatrix(); +    if (LLSelectMgr::sRenderHiddenSelections) // && gFloaterTools && gFloaterTools->getVisible()) +    { +        gGL.blendFunc(LLRender::BF_SOURCE_COLOR, LLRender::BF_ONE); +        LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE, GL_GEQUAL); +        if (shader) +        { +            gGL.diffuseColor4f(color.mV[VRED], color.mV[VGREEN], color.mV[VBLUE], 0.4f); +            pushWireframe(drawable); +        } +        else +        { +            LLGLEnable fog(GL_FOG); +            glFogi(GL_FOG_MODE, GL_LINEAR); +            float d = (LLViewerCamera::getInstance()->getPointOfInterest() - LLViewerCamera::getInstance()->getOrigin()).magVec(); +            LLColor4 fogCol = color * (F32)llclamp((LLSelectMgr::getInstance()->getSelectionCenterGlobal() - gAgentCamera.getCameraPositionGlobal()).magVec() / (LLSelectMgr::getInstance()->getBBoxOfSelection().getExtentLocal().magVec() * 4), 0.0, 1.0); +            glFogf(GL_FOG_START, d); +            glFogf(GL_FOG_END, d*(1 + (LLViewerCamera::getInstance()->getView() / LLViewerCamera::getInstance()->getDefaultFOV()))); +            glFogfv(GL_FOG_COLOR, fogCol.mV); + +            gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); +            { +                gGL.diffuseColor4f(color.mV[VRED], color.mV[VGREEN], color.mV[VBLUE], 0.4f); +                pushWireframe(drawable); +            } +        } +    } -	if (shader) -	{ -		shader->bind(); -	} +    gGL.flush(); +    gGL.setSceneBlendType(LLRender::BT_ALPHA); + +    gGL.diffuseColor4f(color.mV[VRED] * 2, color.mV[VGREEN] * 2, color.mV[VBLUE] * 2, LLSelectMgr::sHighlightAlpha * 2); + +    { +        bool wireframe_selection = gFloaterTools && gFloaterTools->getVisible(); + +        LLGLDisable depth(wireframe_selection ? 0 : GL_BLEND); +        LLGLEnable stencil(wireframe_selection ? 0 : GL_STENCIL_TEST); + +        if (!wireframe_selection) +        { //modify wireframe into outline selection mode +            glStencilFunc(GL_NOTEQUAL, 2, 0xffff); +            glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); +        } + +        LLGLEnable offset(GL_POLYGON_OFFSET_LINE); +        glPolygonOffset(3.f, 3.f); +        glLineWidth(5.f); +        glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); +        pushWireframe(drawable); +    } + +    glLineWidth(1.f); +    glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); +    gGL.popMatrix(); + +    if (shader) +    { +        shader->bind(); +    }  }  //----------------------------------------------------------------------------- diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp index d2a87ee2af..9791f4a921 100644 --- a/indra/newview/llspatialpartition.cpp +++ b/indra/newview/llspatialpartition.cpp @@ -3941,6 +3941,7 @@ LLDrawable* LLSpatialPartition::lineSegmentIntersect(const LLVector4a& start, co  LLDrawInfo::LLDrawInfo(U16 start, U16 end, U32 count, U32 offset,   					   LLViewerTexture* texture, LLVertexBuffer* buffer, +					   bool selected,  					   BOOL fullbright, U8 bump, BOOL particle, F32 part_size)  :	LLTrace::MemTrackableNonVirtual<LLDrawInfo, 16>("LLDrawInfo"),  	mVertexBuffer(buffer), @@ -3968,7 +3969,8 @@ LLDrawInfo::LLDrawInfo(U16 start, U16 end, U32 count, U32 offset,  	mHasGlow(FALSE),  	mEnvIntensity(0.0f),  	mAlphaMaskCutoff(0.5f), -	mDiffuseAlphaMode(0) +	mDiffuseAlphaMode(0), +	mSelected(selected)  {  	mVertexBuffer->validateRange(mStart, mEnd, mCount, mOffset); diff --git a/indra/newview/llspatialpartition.h b/indra/newview/llspatialpartition.h index 7633e46200..6104b92d43 100644 --- a/indra/newview/llspatialpartition.h +++ b/indra/newview/llspatialpartition.h @@ -75,6 +75,7 @@ public:  	LLDrawInfo(U16 start, U16 end, U32 count, U32 offset,   				LLViewerTexture* image, LLVertexBuffer* buffer,  +				bool selected,  				BOOL fullbright = FALSE, U8 bump = 0, BOOL particle = FALSE, F32 part_size = 0); @@ -117,6 +118,7 @@ public:  	F32  mEnvIntensity;  	F32  mAlphaMaskCutoff;  	U8   mDiffuseAlphaMode; +	bool mSelected;  	struct CompareTexture @@ -646,7 +648,7 @@ class LLVolumeGeometryManager: public LLGeometryManager  	virtual void rebuildGeom(LLSpatialGroup* group);  	virtual void rebuildMesh(LLSpatialGroup* group);  	virtual void getGeometry(LLSpatialGroup* group); -	void genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace** faces, U32 face_count, BOOL distance_sort = FALSE, BOOL batch_textures = FALSE, BOOL no_materials = FALSE); +	U32 genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace** faces, U32 face_count, BOOL distance_sort = FALSE, BOOL batch_textures = FALSE, BOOL no_materials = FALSE);  	void registerFace(LLSpatialGroup* group, LLFace* facep, U32 type);  private: diff --git a/indra/newview/llversioninfo.cpp b/indra/newview/llversioninfo.cpp index 375dce485d..4e07223784 100644 --- a/indra/newview/llversioninfo.cpp +++ b/indra/newview/llversioninfo.cpp @@ -101,14 +101,11 @@ namespace  {  	// LL_VIEWER_CHANNEL is a macro defined on the compiler command line. The  	// macro expands to the string name of the channel, but without quotes. We -	// need to turn it into a quoted string. This macro trick does that. -#define stringize_inner(x) #x -#define stringize_outer(x) stringize_inner(x) - +	// need to turn it into a quoted string. LL_TO_STRING() does that.  	/// Storage of the channel name the viewer is using.  	//  The channel name is set by hardcoded constant,   	//  or by calling LLVersionInfo::resetChannel() -	std::string sWorkingChannelName(stringize_outer(LL_VIEWER_CHANNEL)); +	std::string sWorkingChannelName(LL_TO_STRING(LL_VIEWER_CHANNEL));  	// Storage for the "version and channel" string.  	// This will get reset too. diff --git a/indra/newview/llviewercamera.cpp b/indra/newview/llviewercamera.cpp index 57a0195d23..778e275727 100644 --- a/indra/newview/llviewercamera.cpp +++ b/indra/newview/llviewercamera.cpp @@ -113,6 +113,7 @@ LLViewerCamera::LLViewerCamera() : LLCamera()  {  	calcProjection(getFar());  	mCameraFOVDefault = DEFAULT_FIELD_OF_VIEW; +	mPrevCameraFOVDefault = DEFAULT_FIELD_OF_VIEW;  	mCosHalfCameraFOV = cosf(mCameraFOVDefault * 0.5f);  	mPixelMeterRatio = 0.f;  	mScreenPixelArea = 0; @@ -882,6 +883,15 @@ void LLViewerCamera::setDefaultFOV(F32 vertical_fov_rads)  	mCosHalfCameraFOV = cosf(mCameraFOVDefault * 0.5f);  } +BOOL LLViewerCamera::isDefaultFOVChanged() +{ +	if(mPrevCameraFOVDefault != mCameraFOVDefault) +	{ +		mPrevCameraFOVDefault = mCameraFOVDefault; +		return !gSavedSettings.getBOOL("IgnoreFOVZoomForLODs"); +	} +	return FALSE; +}  // static  void LLViewerCamera::updateCameraAngle( void* user_data, const LLSD& value) diff --git a/indra/newview/llviewercamera.h b/indra/newview/llviewercamera.h index f8c973690a..5901de289f 100644 --- a/indra/newview/llviewercamera.h +++ b/indra/newview/llviewercamera.h @@ -115,6 +115,8 @@ public:  	void setDefaultFOV(F32 fov) ;  	F32 getDefaultFOV() { return mCameraFOVDefault; } +	BOOL isDefaultFOVChanged(); +  	BOOL cameraUnderWater() const;  	BOOL areVertsVisible(LLViewerObject* volumep, BOOL all_verts); @@ -138,6 +140,7 @@ protected:  	mutable LLMatrix4	mProjectionMatrix;	// Cache of perspective matrix  	mutable LLMatrix4	mModelviewMatrix;  	F32					mCameraFOVDefault; +	F32					mPrevCameraFOVDefault;  	F32					mCosHalfCameraFOV;  	LLVector3			mLastPointOfInterest;  	F32					mPixelMeterRatio; // Divide by distance from camera to get pixels per meter at that distance. diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp index 63c62fc990..88984d518a 100644 --- a/indra/newview/llviewercontrol.cpp +++ b/indra/newview/llviewercontrol.cpp @@ -592,6 +592,7 @@ bool toggle_show_object_render_cost(const LLSD& newvalue)  	return true;  } +void handleRenderAutoMuteByteLimitChanged(const LLSD& new_value);  ////////////////////////////////////////////////////////////////////////////  void settings_setup_listeners() @@ -745,6 +746,7 @@ void settings_setup_listeners()  	gSavedSettings.getControl("SpellCheckDictionary")->getSignal()->connect(boost::bind(&handleSpellCheckChanged));  	gSavedSettings.getControl("LoginLocation")->getSignal()->connect(boost::bind(&handleLoginLocationChanged));  	gSavedSettings.getControl("DebugAvatarJoints")->getCommitSignal()->connect(boost::bind(&handleDebugAvatarJointsChanged, _2)); +	gSavedSettings.getControl("RenderAutoMuteByteLimit")->getSignal()->connect(boost::bind(&handleRenderAutoMuteByteLimitChanged, _2));  	gSavedPerAccountSettings.getControl("AvatarHoverOffsetZ")->getCommitSignal()->connect(boost::bind(&handleAvatarHoverOffsetChanged, _2));  } diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp index 96ef160c72..86a9e7e2ad 100644 --- a/indra/newview/llviewerdisplay.cpp +++ b/indra/newview/llviewerdisplay.cpp @@ -1005,7 +1005,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)  															  gPipeline.mDeferredScreen.getHeight(), 0, 0,   															  gPipeline.mDeferredScreen.getWidth(),   															  gPipeline.mDeferredScreen.getHeight(),  -															  GL_DEPTH_BUFFER_BIT, GL_NEAREST); +															  GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST);  				}  			}  			else @@ -1017,7 +1017,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)  															  gPipeline.mScreen.getHeight(), 0, 0,   															  gPipeline.mScreen.getWidth(),   															  gPipeline.mScreen.getHeight(),  -															  GL_DEPTH_BUFFER_BIT, GL_NEAREST); +															  GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST);  				}  			}  		} diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index 624c48e945..239e357cdd 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -5894,6 +5894,14 @@ void LLViewerObject::markForUpdate(BOOL priority)  	}  } +void LLViewerObject::markForUnload(BOOL priority) +{ +	if (mDrawable.notNull()) +	{ +		gPipeline.markRebuild(mDrawable, LLDrawable::FOR_UNLOAD, priority); +	} +} +  bool LLViewerObject::isPermanentEnforced() const  {  	return flagObjectPermanent() && (mRegionp != gAgent.getRegion()) && !gAgent.isGodlike(); diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h index 21c95d5533..d61832c2ad 100644 --- a/indra/newview/llviewerobject.h +++ b/indra/newview/llviewerobject.h @@ -412,6 +412,7 @@ public:  	void clearIcon();  	void markForUpdate(BOOL priority); +	void markForUnload(BOOL priority);  	void updateVolume(const LLVolumeParams& volume_params);  	virtual	void updateSpatialExtents(LLVector4a& min, LLVector4a& max);  	virtual F32 getBinRadius(); diff --git a/indra/newview/llvieweroctree.cpp b/indra/newview/llvieweroctree.cpp index 023f1b92ba..5f0e21db71 100644 --- a/indra/newview/llvieweroctree.cpp +++ b/indra/newview/llvieweroctree.cpp @@ -465,7 +465,7 @@ LLViewerOctreeGroup::LLViewerOctreeGroup(OctreeNode* node)  {  	LLVector4a tmp;  	tmp.splat(0.f); -	mExtents[0] = mExtents[1] = mObjectBounds[0] = mObjectBounds[0] = mObjectBounds[1] =  +	mExtents[0] = mExtents[1] = mObjectBounds[0] = mObjectBounds[1] =  		mObjectExtents[0] = mObjectExtents[1] = tmp;  	mBounds[0] = node->getCenter(); diff --git a/indra/newview/llviewerpartsim.cpp b/indra/newview/llviewerpartsim.cpp index 25cf082751..e5265f1dcd 100644 --- a/indra/newview/llviewerpartsim.cpp +++ b/indra/newview/llviewerpartsim.cpp @@ -662,9 +662,6 @@ void LLViewerPartSim::updateSimulation()  {  	static LLFrameTimer update_timer; -	//reset VBO cursor -	LLVOPartGroup::sVBSlotCursor = 0; -  	const F32 dt = llmin(update_timer.getElapsedTimeAndResetF32(), 0.1f);   	if (!(gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_PARTICLES))) diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index 3e0cec0f09..ff7647a7e4 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -2811,6 +2811,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()  			gSkinnedObjectSimpleWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;  			gSkinnedObjectSimpleWaterProgram.mFeatures.hasObjectSkinning = true;  			gSkinnedObjectSimpleWaterProgram.mFeatures.disableTextureIndex = true; +			gSkinnedObjectSimpleWaterProgram.mFeatures.hasAlphaMask = true;  			gSkinnedObjectSimpleWaterProgram.mShaderFiles.clear();  			gSkinnedObjectSimpleWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleSkinnedV.glsl", GL_VERTEX_SHADER_ARB));  			gSkinnedObjectSimpleWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); diff --git a/indra/newview/llvograss.cpp b/indra/newview/llvograss.cpp index de63a3963c..b5c90a8f60 100644 --- a/indra/newview/llvograss.cpp +++ b/indra/newview/llvograss.cpp @@ -741,7 +741,7 @@ void LLGrassPartition::getGeometry(LLSpatialGroup* group)  			U32 count = facep->getIndicesCount();  			LLDrawInfo* info = new LLDrawInfo(start,end,count,offset,facep->getTexture(),   				//facep->getTexture(), -				buffer, fullbright);  +				buffer, object->isSelected(), fullbright);  			const LLVector4a* exts = group->getObjectExtents();  			info->mExtents[0] = exts[0]; diff --git a/indra/newview/llvopartgroup.cpp b/indra/newview/llvopartgroup.cpp index f7b21338f8..b31afca61d 100644 --- a/indra/newview/llvopartgroup.cpp +++ b/indra/newview/llvopartgroup.cpp @@ -47,11 +47,17 @@  extern U64MicrosecondsImplicit gFrameTime;  LLPointer<LLVertexBuffer> LLVOPartGroup::sVB = NULL; -S32 LLVOPartGroup::sVBSlotCursor = 0; +S32 LLVOPartGroup::sVBSlotFree[]; +S32* LLVOPartGroup::sVBSlotCursor = NULL;  void LLVOPartGroup::initClass()  { +	for (S32 i = 0; i < LL_MAX_PARTICLE_COUNT; ++i) +	{ +		sVBSlotFree[i] = i; +	} +	sVBSlotCursor = sVBSlotFree;  }  //static @@ -124,12 +130,14 @@ void LLVOPartGroup::destroyGL()  //static  S32 LLVOPartGroup::findAvailableVBSlot()  { -	if (sVBSlotCursor >= LL_MAX_PARTICLE_COUNT) +	if (sVBSlotCursor >= sVBSlotFree + LL_MAX_PARTICLE_COUNT)  	{ //no more available slots  		return -1;  	} -	return sVBSlotCursor++; +	S32 ret = *sVBSlotCursor; +	sVBSlotCursor++; +	return ret;  }  bool ll_is_part_idx_allocated(S32 idx, S32* start, S32* end) @@ -150,7 +158,7 @@ bool ll_is_part_idx_allocated(S32 idx, S32* start, S32* end)  //static  void LLVOPartGroup::freeVBSlot(S32 idx)  { -	/*llassert(idx < LL_MAX_PARTICLE_COUNT && idx >= 0); +	llassert(idx < LL_MAX_PARTICLE_COUNT && idx >= 0);  	//llassert(sVBSlotCursor > sVBSlotFree);  	//llassert(ll_is_part_idx_allocated(idx, sVBSlotCursor, sVBSlotFree+LL_MAX_PARTICLE_COUNT)); @@ -158,7 +166,7 @@ void LLVOPartGroup::freeVBSlot(S32 idx)  	{  		sVBSlotCursor--;  		*sVBSlotCursor = idx; -	}*/ +	}  }  LLVOPartGroup::LLVOPartGroup(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp) @@ -870,7 +878,7 @@ void LLParticlePartition::getGeometry(LLSpatialGroup* group)  		LLFace* facep = *i;  		LLAlphaObject* object = (LLAlphaObject*) facep->getViewerObject(); -		//if (!facep->isState(LLFace::PARTICLE)) +		if (!facep->isState(LLFace::PARTICLE))  		{ //set the indices of this face  			S32 idx = LLVOPartGroup::findAvailableVBSlot();  			if (idx >= 0) @@ -879,7 +887,7 @@ void LLParticlePartition::getGeometry(LLSpatialGroup* group)  				facep->setIndicesIndex(idx*6);  				facep->setVertexBuffer(LLVOPartGroup::sVB);  				facep->setPoolType(LLDrawPool::POOL_ALPHA); -				//facep->setState(LLFace::PARTICLE); +				facep->setState(LLFace::PARTICLE);  			}  			else  			{ @@ -964,7 +972,7 @@ void LLParticlePartition::getGeometry(LLSpatialGroup* group)  			U32 count = facep->getIndicesCount();  			LLDrawInfo* info = new LLDrawInfo(start,end,count,offset,facep->getTexture(),   				//facep->getTexture(), -				buffer, fullbright);  +				buffer, object->isSelected(), fullbright);  			const LLVector4a* exts = group->getObjectExtents();  			info->mExtents[0] = exts[0]; diff --git a/indra/newview/llvopartgroup.h b/indra/newview/llvopartgroup.h index 2ef8b1c848..4e4d6e609d 100644 --- a/indra/newview/llvopartgroup.h +++ b/indra/newview/llvopartgroup.h @@ -42,7 +42,8 @@ public:  	//vertex buffer for holding all particles  	static LLPointer<LLVertexBuffer> sVB; -	static S32 sVBSlotCursor; +	static S32 sVBSlotFree[LL_MAX_PARTICLE_COUNT]; +	static S32 *sVBSlotCursor;  	static void initClass();  	static void restoreGL(); diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index c1ecfd07c1..7d6881f8a8 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -78,6 +78,7 @@  #include "llvoavatar.h"  #include "llvocache.h"  #include "llmaterialmgr.h" +#include "llsculptidsize.h"  const F32 FORCE_SIMPLE_RENDER_AREA = 512.f;  const F32 FORCE_CULL_AREA = 8.f; @@ -249,6 +250,8 @@ void LLVOVolume::markDead()  {  	if (!mDead)  	{ +		LLSculptIDSize::instance().rem(getVolume()->getParams().getSculptID()); +  		if(getMDCImplCount() > 0)  		{  			LLMediaDataClientObject::ptr_t obj = new LLMediaDataClientObjectImpl(const_cast<LLVOVolume*>(this), false); @@ -956,13 +959,14 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams ¶ms_in, const S32 detail, bo  		// if it's a mesh  		if ((volume_params.getSculptType() & LL_SCULPT_TYPE_MASK) == LL_SCULPT_TYPE_MESH)  		{ //meshes might not have all LODs, get the force detail to best existing LOD -			LLUUID mesh_id = volume_params.getSculptID(); - -			lod = gMeshRepo.getActualMeshLOD(volume_params, lod); -			if (lod == -1) +			if (NO_LOD != lod)  			{ -				is404 = TRUE; -				lod = 0; +				lod = gMeshRepo.getActualMeshLOD(volume_params, lod); +				if (lod == -1) +				{ +					is404 = TRUE; +					lod = 0; +				}  			}  		}  	} @@ -1059,12 +1063,13 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams ¶ms_in, const S32 detail, bo  				LLFace::cacheFaceInVRAM(face);  			}  		} -		  		return TRUE;  	} - - +	else if (NO_LOD == lod)  +	{ +		LLSculptIDSize::instance().resetSizeSum(volume_params.getSculptID()); +	}  	return FALSE;  } @@ -1219,18 +1224,18 @@ void LLVOVolume::sculpt()  	}  } -S32	LLVOVolume::computeLODDetail(F32 distance, F32 radius) +S32	LLVOVolume::computeLODDetail(F32 distance, F32 radius, F32 lod_factor)  {  	S32	cur_detail;  	if (LLPipeline::sDynamicLOD)  	{  		// We've got LOD in the profile, and in the twist.  Use radius. -		F32 tan_angle = (LLVOVolume::sLODFactor*radius)/distance; +		F32 tan_angle = (lod_factor*radius)/distance;  		cur_detail = LLVolumeLODGroup::getDetailFromTan(ll_round(tan_angle, 0.01f));  	}  	else  	{ -		cur_detail = llclamp((S32) (sqrtf(radius)*LLVOVolume::sLODFactor*4.f), 0, 3);		 +		cur_detail = llclamp((S32) (sqrtf(radius)*lod_factor*4.f), 0, 3);  	}  	return cur_detail;  } @@ -1246,6 +1251,7 @@ BOOL LLVOVolume::calcLOD()  	F32 radius;  	F32 distance; +	F32 lod_factor = LLVOVolume::sLODFactor;  	if (mDrawable->isState(LLDrawable::RIGGED))  	{ @@ -1281,12 +1287,18 @@ BOOL LLVOVolume::calcLOD()  		distance *= rampDist;  	} -	// DON'T Compensate for field of view changing on FOV zoom. +  	distance *= F_PI/3.f; -	cur_detail = computeLODDetail(ll_round(distance, 0.01f),  -									ll_round(radius, 0.01f)); +	static LLCachedControl<bool> ignore_fov_zoom(gSavedSettings,"IgnoreFOVZoomForLODs"); +	if(!ignore_fov_zoom) +	{ +		lod_factor *= DEFAULT_FIELD_OF_VIEW / LLViewerCamera::getInstance()->getDefaultFOV(); +	} +	cur_detail = computeLODDetail(ll_round(distance, 0.01f),  +									ll_round(radius, 0.01f), +									lod_factor);  	if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_LOD_INFO) &&  		mDrawable->getFace(0)) @@ -1299,7 +1311,8 @@ BOOL LLVOVolume::calcLOD()  	if (cur_detail != mLOD)  	{  		mAppAngle = ll_round((F32) atan2( mDrawable->getRadius(), mDrawable->mDistanceWRTCamera) * RAD_TO_DEG, 0.01f); -		mLOD = cur_detail;		 +		mLOD = cur_detail; +  		return TRUE;  	} @@ -1313,7 +1326,16 @@ BOOL LLVOVolume::updateLOD()  		return FALSE;  	} -	BOOL lod_changed = calcLOD(); +	BOOL lod_changed = FALSE; + +	if (!LLSculptIDSize::instance().isUnloaded(getVolume()->getParams().getSculptID()))  +	{ +		lod_changed = calcLOD(); +	} +	else +	{ +		return FALSE; +	}  	if (lod_changed)  	{ @@ -1483,7 +1505,6 @@ BOOL LLVOVolume::genBBoxes(BOOL force_global)  		res &= face->genVolumeBBoxes(*volume, i,  										mRelativeXform,   										(mVolumeImpl && mVolumeImpl->isVolumeGlobal()) || force_global); -		  		if (rebuild)  		{  			if (i == 0) @@ -1759,6 +1780,11 @@ BOOL LLVOVolume::updateGeometry(LLDrawable *drawable)  		dirtySpatialGroup(drawable->isState(LLDrawable::IN_REBUILD_Q1));  		compiled = TRUE;  		lodOrSculptChanged(drawable, compiled); +		 +		if(drawable->isState(LLDrawable::REBUILD_RIGGED | LLDrawable::RIGGED))  +		{ +			updateRiggedVolume(false); +		}  		genBBoxes(FALSE);  	}  	// it has its own drawable (it's moved) or it has changed UVs or it has changed xforms from global<->local @@ -2177,7 +2203,7 @@ bool LLVOVolume::notifyAboutMissingAsset(LLViewerTexture *texture)  	//setup new materials  	for(map_te_material::const_iterator it = new_material.begin(), end = new_material.end(); it != end; ++it)  	{ -		LLMaterialMgr::getInstance()->put(getID(), it->first, *it->second); +		LLMaterialMgr::getInstance()->setLocalMaterial(getRegion()->getRegionID(), it->second);  		LLViewerObject::setTEMaterialParams(it->first, it->second);  	} @@ -2280,7 +2306,7 @@ S32 LLVOVolume::setTEMaterialParams(const U8 te, const LLMaterialPtr pMaterialPa  		if(new_material) {  			pMaterial = new_material; -			LLMaterialMgr::getInstance()->put(getID(),te,*pMaterial); +			LLMaterialMgr::getInstance()->setLocalMaterial(getRegion()->getRegionID(), pMaterial);  		}  	} @@ -4225,7 +4251,7 @@ void LLRiggedVolume::update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, cons  			LLVector4a* pos = dst_face.mPositions; -			if( pos && weight && dst_face.mExtents ) +			if (pos && dst_face.mExtents)  			{  				LL_RECORD_BLOCK_TIME(FTM_SKIN_RIGGED); @@ -4411,7 +4437,9 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep,  		LL_WARNS_ONCE("RenderMaterials") << "Oh no! No binormals for this alpha blended face!" << LL_ENDL;  	} -	if (facep->getViewerObject()->isSelected() && LLSelectMgr::getInstance()->mHideSelectedObjects) +	bool selected = facep->getViewerObject()->isSelected(); + +	if (selected && LLSelectMgr::getInstance()->mHideSelectedObjects)  	{  		return;  	} @@ -4508,7 +4536,7 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep,  			batchable = true;  		}  	} -	 +  	if (idx >= 0 &&   		draw_vec[idx]->mVertexBuffer == facep->getVertexBuffer() &&  		draw_vec[idx]->mEnd == facep->getGeomIndex()-1 && @@ -4524,7 +4552,8 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep,  		(!mat || (draw_vec[idx]->mShiny == shiny)) && // need to break batches when a material is shared, but legacy settings are different  		draw_vec[idx]->mTextureMatrix == tex_mat &&  		draw_vec[idx]->mModelMatrix == model_mat && -		draw_vec[idx]->mShaderMask == shader_mask) +		draw_vec[idx]->mShaderMask == shader_mask && +		draw_vec[idx]->mSelected == selected)  	{  		draw_vec[idx]->mCount += facep->getIndicesCount();  		draw_vec[idx]->mEnd += facep->getGeomCount(); @@ -4546,7 +4575,7 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep,  		U32 offset = facep->getIndicesStart();  		U32 count = facep->getIndicesCount();  		LLPointer<LLDrawInfo> draw_info = new LLDrawInfo(start,end,count,offset, tex,  -			facep->getVertexBuffer(), fullbright, bump);  +			facep->getVertexBuffer(), selected, fullbright, bump);  		draw_info->mGroup = group;  		draw_info->mVSize = facep->getVirtualSize();  		draw_vec.push_back(draw_info); @@ -4573,26 +4602,25 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep,  		if (mat)  		{ -				draw_info->mMaterialID = mat_id; +			draw_info->mMaterialID = mat_id; -				// We have a material.  Update our draw info accordingly. +			// We have a material.  Update our draw info accordingly. -				if (!mat->getSpecularID().isNull()) -				{ -					LLVector4 specColor; -					specColor.mV[0] = mat->getSpecularLightColor().mV[0] * (1.f / 255.f); -					specColor.mV[1] = mat->getSpecularLightColor().mV[1] * (1.f / 255.f); -					specColor.mV[2] = mat->getSpecularLightColor().mV[2] * (1.f / 255.f); -					specColor.mV[3] = mat->getSpecularLightExponent() * (1.f / 255.f); -					draw_info->mSpecColor = specColor; -					draw_info->mEnvIntensity = mat->getEnvironmentIntensity() * (1.f / 255.f); -					draw_info->mSpecularMap = facep->getViewerObject()->getTESpecularMap(facep->getTEOffset()); -				} +			if (!mat->getSpecularID().isNull()) +			{ +				LLVector4 specColor; +				specColor.mV[0] = mat->getSpecularLightColor().mV[0] * (1.f / 255.f); +				specColor.mV[1] = mat->getSpecularLightColor().mV[1] * (1.f / 255.f); +				specColor.mV[2] = mat->getSpecularLightColor().mV[2] * (1.f / 255.f); +				specColor.mV[3] = mat->getSpecularLightExponent() * (1.f / 255.f); +				draw_info->mSpecColor = specColor; +				draw_info->mEnvIntensity = mat->getEnvironmentIntensity() * (1.f / 255.f); +				draw_info->mSpecularMap = facep->getViewerObject()->getTESpecularMap(facep->getTEOffset()); +			} -				draw_info->mAlphaMaskCutoff = mat->getAlphaMaskCutoff() * (1.f / 255.f); -				draw_info->mDiffuseAlphaMode = mat->getDiffuseAlphaMode(); -				draw_info->mNormalMap = facep->getViewerObject()->getTENormalMap(facep->getTEOffset()); -				 +			draw_info->mAlphaMaskCutoff = mat->getAlphaMaskCutoff() * (1.f / 255.f); +			draw_info->mDiffuseAlphaMode = mat->getDiffuseAlphaMode(); +			draw_info->mNormalMap = facep->getViewerObject()->getTENormalMap(facep->getTEOffset());  		}  		else   		{ @@ -4663,10 +4691,83 @@ static LLDrawPoolAvatar* get_avatar_drawpool(LLViewerObject* vobj)  	return NULL;  } -void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) +void handleRenderAutoMuteByteLimitChanged(const LLSD& new_value)  { -	 +	static LLCachedControl<U32> render_auto_mute_byte_limit(gSavedSettings, "RenderAutoMuteByteLimit", 0U); +	if (0 != render_auto_mute_byte_limit) +	{ +		//for unload +		LLSculptIDSize::container_BY_SIZE_view::iterator +			itL = LLSculptIDSize::instance().getSizeInfo().get<LLSculptIDSize::tag_BY_SIZE>().lower_bound(render_auto_mute_byte_limit), +			itU = LLSculptIDSize::instance().getSizeInfo().get<LLSculptIDSize::tag_BY_SIZE>().end(); + +		for (; itL != itU; ++itL) +		{ +			const LLSculptIDSize::Info &nfo = *itL; +			LLVOVolume *pVVol = nfo.getPtrLLDrawable()->getVOVolume(); +			if (pVVol +				&& !pVVol->isDead() +				&& pVVol->isAttachment() +				&& !pVVol->getAvatar()->isSelf() +				&& LLVOVolume::NO_LOD != pVVol->getLOD() +				) +			{ +				//postponed +				pVVol->markForUnload(); +				LLSculptIDSize::instance().addToUnloaded(nfo.getSculptId()); +			} +		} + +		//for load if it was unload +		itL = LLSculptIDSize::instance().getSizeInfo().get<LLSculptIDSize::tag_BY_SIZE>().begin(); +		itU = LLSculptIDSize::instance().getSizeInfo().get<LLSculptIDSize::tag_BY_SIZE>().upper_bound(render_auto_mute_byte_limit); + +		for (; itL != itU; ++itL) +		{ +			const LLSculptIDSize::Info &nfo = *itL; +			LLVOVolume *pVVol = nfo.getPtrLLDrawable()->getVOVolume(); +			if (pVVol +				&& !pVVol->isDead() +				&& pVVol->isAttachment() +				&& !pVVol->getAvatar()->isSelf() +				&& LLVOVolume::NO_LOD == pVVol->getLOD() +				) +			{ +				LLSculptIDSize::instance().remFromUnloaded(nfo.getSculptId()); +				pVVol->updateLOD(); +				pVVol->markForUpdate(TRUE); +			} +		} +	} +	else +	{ +		LLSculptIDSize::instance().clearUnloaded(); + +		LLSculptIDSize::container_BY_SIZE_view::iterator +			itL = LLSculptIDSize::instance().getSizeInfo().get<LLSculptIDSize::tag_BY_SIZE>().begin(), +			itU = LLSculptIDSize::instance().getSizeInfo().get<LLSculptIDSize::tag_BY_SIZE>().end(); + +		for (; itL != itU; ++itL) +		{ +			const LLSculptIDSize::Info &nfo = *itL; +			LLVOVolume *pVVol = nfo.getPtrLLDrawable()->getVOVolume(); +			if (pVVol +				&& !pVVol->isDead() +				&& pVVol->isAttachment() +				&& !pVVol->getAvatar()->isSelf() +				&& LLVOVolume::NO_LOD == pVVol->getLOD() +				)  +			{ +				pVVol->updateLOD(); +				pVVol->markForUpdate(TRUE); +			} +		} +	} +} + +void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) +{  	if (group->changeLOD())  	{  		group->mLastUpdateDistance = group->mDistance; @@ -5227,13 +5328,19 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)  		fullbright_mask = fullbright_mask | LLVertexBuffer::MAP_TEXTURE_INDEX;  	} -	genDrawInfo(group, simple_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sSimpleFaces, simple_count, FALSE, batch_textures, FALSE); -	genDrawInfo(group, fullbright_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sFullbrightFaces, fullbright_count, FALSE, batch_textures); -	genDrawInfo(group, alpha_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sAlphaFaces, alpha_count, TRUE, batch_textures); -	genDrawInfo(group, bump_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sBumpFaces, bump_count, FALSE, FALSE); -	genDrawInfo(group, norm_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sNormFaces, norm_count, FALSE, FALSE); -	genDrawInfo(group, spec_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sSpecFaces, spec_count, FALSE, FALSE); -	genDrawInfo(group, normspec_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sNormSpecFaces, normspec_count, FALSE, FALSE); +	group->mGeometryBytes = 0; + +	U32 geometryBytes = 0; + +	geometryBytes += genDrawInfo(group, simple_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sSimpleFaces, simple_count, FALSE, batch_textures, FALSE); +	geometryBytes += genDrawInfo(group, fullbright_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sFullbrightFaces, fullbright_count, FALSE, batch_textures); +	geometryBytes += genDrawInfo(group, alpha_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sAlphaFaces, alpha_count, TRUE, batch_textures); +	geometryBytes += genDrawInfo(group, bump_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sBumpFaces, bump_count, FALSE, FALSE); +	geometryBytes += genDrawInfo(group, norm_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sNormFaces, norm_count, FALSE, FALSE); +	geometryBytes += genDrawInfo(group, spec_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sSpecFaces, spec_count, FALSE, FALSE); +	geometryBytes += genDrawInfo(group, normspec_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sNormSpecFaces, normspec_count, FALSE, FALSE); + +	group->mGeometryBytes = geometryBytes;  	if (!LLPipeline::sDelayVBUpdate)  	{ @@ -5291,6 +5398,8 @@ void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group)  			if (drawablep && !drawablep->isDead() && drawablep->isState(LLDrawable::REBUILD_ALL) && !drawablep->isState(LLDrawable::RIGGED) )  			{  				LLVOVolume* vobj = drawablep->getVOVolume(); +				if (vobj->isNoLOD()) continue; +  				vobj->preRebuild();  				if (drawablep->isState(LLDrawable::ANIMATED_CHILD)) @@ -5423,10 +5532,11 @@ static LLTrace::BlockTimerStatHandle FTM_GEN_DRAW_INFO_RESIZE_VB("Resize VB"); -void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace** faces, U32 face_count, BOOL distance_sort, BOOL batch_textures, BOOL no_materials) +U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace** faces, U32 face_count, BOOL distance_sort, BOOL batch_textures, BOOL no_materials)  {  	LL_RECORD_BLOCK_TIME(FTM_REBUILD_VOLUME_GEN_DRAW_INFO); +	U32 geometryBytes = 0;  	U32 buffer_usage = group->mBufferUsage;  	static LLCachedControl<bool> use_transform_feedback(gSavedSettings, "RenderUseTransformFeedback", false); @@ -5676,7 +5786,7 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFac  		if (buffer)  		{ -			group->mGeometryBytes += buffer->getSize() + buffer->getIndicesSize(); +			geometryBytes += buffer->getSize() + buffer->getIndicesSize();  			buffer_map[mask][*face_iter].push_back(buffer);  		} @@ -5964,7 +6074,7 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFac  					}  					else  					{ -					registerFace(group, facep, LLRenderPass::PASS_FULLBRIGHT); +						registerFace(group, facep, LLRenderPass::PASS_FULLBRIGHT);  					}  					if (LLPipeline::sRenderDeferred && !hud_group && LLPipeline::sRenderBump && use_legacy_bump)  					{ //if this is the deferred render and a bump map is present, register in post deferred bump @@ -5986,8 +6096,8 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFac  						}  						else  						{ -						registerFace(group, facep, LLRenderPass::PASS_SIMPLE); -					} +							registerFace(group, facep, LLRenderPass::PASS_SIMPLE); +						}  				}  				} @@ -6032,6 +6142,8 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFac  	{  		group->mBufferMap[mask][i->first] = i->second;  	} + +	return geometryBytes;  }  void LLGeometryManager::addGeometryCount(LLSpatialGroup* group, U32 &vertex_count, U32 &index_count) @@ -6098,4 +6210,3 @@ void LLHUDPartition::shift(const LLVector4a &offset)  {  	//HUD objects don't shift with region crossing.  That would be silly.  } - diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h index 1a7e49d198..a0342d31a2 100644 --- a/indra/newview/llvovolume.h +++ b/indra/newview/llvovolume.h @@ -35,6 +35,8 @@  #include "m3math.h"		// LLMatrix3  #include "m4math.h"		// LLMatrix4  #include <map> +#include <set> +  class LLViewerTextureAnim;  class LLDrawPool; @@ -125,7 +127,9 @@ public:  				void	generateSilhouette(LLSelectNode* nodep, const LLVector3& view_point);  	/*virtual*/	BOOL	setParent(LLViewerObject* parent); -				S32		getLOD() const							{ return mLOD; } +				S32		getLOD() const						{ return mLOD; } +				void	setNoLOD()							{ mLOD = NO_LOD; mLODChanged = TRUE; } +				bool	isNoLOD() const						{ return NO_LOD == mLOD; }  	const LLVector3		getPivotPositionAgent() const;  	const LLMatrix4&	getRelativeXform() const				{ return mRelativeXform; }  	const LLMatrix3&	getRelativeXformInvTrans() const		{ return mRelativeXformInvTrans; } @@ -160,6 +164,7 @@ public:  				const LLMatrix4& getWorldMatrix(LLXformMatrix* xform) const;  				void	markForUpdate(BOOL priority)			{ LLViewerObject::markForUpdate(priority); mVolumeChanged = TRUE; } +				void	markForUnload()							{ LLViewerObject::markForUnload(TRUE); mVolumeChanged = TRUE; }  				void    faceMappingChanged()                    { mFaceMappingChanged=TRUE; };  	/*virtual*/ void	onShift(const LLVector4a &shift_vector); // Called when the drawable shifts @@ -327,7 +332,7 @@ public:  	void clearRiggedVolume();  protected: -	S32	computeLODDetail(F32	distance, F32 radius); +	S32	computeLODDetail(F32	distance, F32 radius, F32 lod_factor);  	BOOL calcLOD();  	LLFace* addFace(S32 face_index);  	void updateTEData(); diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 1d083bb2fd..e541c1054e 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -2656,7 +2656,7 @@ void LLPipeline::downsampleDepthBuffer(LLRenderTarget& source, LLRenderTarget& d  	{  		scratch_space->copyContents(source,   									0, 0, source.getWidth(), source.getHeight(),  -									0, 0, scratch_space->getWidth(), scratch_space->getHeight(), GL_DEPTH_BUFFER_BIT, GL_NEAREST); +									0, 0, scratch_space->getWidth(), scratch_space->getHeight(), GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST);  	}  	dest.bindTarget(); @@ -3031,6 +3031,12 @@ void LLPipeline::updateGeom(F32 max_dtime)  				}  			} +			if (drawablep->isUnload()) +			{ +				drawablep->unload(); +				drawablep->clearState(LLDrawable::FOR_UNLOAD); +			} +  			if (updateDrawableGeom(drawablep, TRUE))  			{  				drawablep->clearState(LLDrawable::IN_REBUILD_Q1); @@ -3424,6 +3430,7 @@ void LLPipeline::stateSort(LLCamera& camera, LLCullResult &result)  	if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD)  	{  		LLSpatialGroup* last_group = NULL; +		BOOL fov_changed = LLViewerCamera::getInstance()->isDefaultFOVChanged();  		for (LLCullResult::bridge_iterator i = sCull->beginVisibleBridge(); i != sCull->endVisibleBridge(); ++i)  		{  			LLCullResult::bridge_iterator cur_iter = i; @@ -3437,7 +3444,7 @@ void LLPipeline::stateSort(LLCamera& camera, LLCullResult &result)  			if (!bridge->isDead() && group && !group->isOcclusionState(LLSpatialGroup::OCCLUDED))  			{ -				stateSort(bridge, camera); +				stateSort(bridge, camera, fov_changed);  			}  			if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD && @@ -3509,9 +3516,9 @@ void LLPipeline::stateSort(LLSpatialGroup* group, LLCamera& camera)  } -void LLPipeline::stateSort(LLSpatialBridge* bridge, LLCamera& camera) +void LLPipeline::stateSort(LLSpatialBridge* bridge, LLCamera& camera, BOOL fov_changed)  { -	if (bridge->getSpatialGroup()->changeLOD()) +	if (bridge->getSpatialGroup()->changeLOD() || fov_changed)  	{  		bool force_update = false;  		bridge->updateDistance(camera, force_update); @@ -4577,12 +4584,6 @@ void LLPipeline::renderGeomDeferred(LLCamera& camera)  	LLGLEnable cull(GL_CULL_FACE); -	LLGLEnable stencil(GL_STENCIL_TEST); -	glStencilFunc(GL_ALWAYS, 1, 0xFFFFFFFF); -	stop_glerror(); -	glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); -	stop_glerror(); -  	for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter)  	{  		LLDrawPool *poolp = *iter; @@ -8138,7 +8139,7 @@ void LLPipeline::renderBloom(bool for_snapshot, F32 zoom_factor, int subfield)  	if (LLRenderTarget::sUseFBO)  	{ //copy depth buffer from mScreen to framebuffer  		LLRenderTarget::copyContentsToFramebuffer(mScreen, 0, 0, mScreen.getWidth(), mScreen.getHeight(),  -			0, 0, mScreen.getWidth(), mScreen.getHeight(), GL_DEPTH_BUFFER_BIT, GL_NEAREST); +			0, 0, mScreen.getWidth(), mScreen.getHeight(), GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST);  	} @@ -9019,7 +9020,7 @@ void LLPipeline::renderDeferredLightingToRT(LLRenderTarget* target)  		{  			LLGLDepthTest depth(GL_TRUE);  			mDeferredDepth.copyContents(mDeferredScreen, 0, 0, mDeferredScreen.getWidth(), mDeferredScreen.getHeight(), -							0, 0, mDeferredDepth.getWidth(), mDeferredDepth.getHeight(), GL_DEPTH_BUFFER_BIT, GL_NEAREST);	 +							0, 0, mDeferredDepth.getWidth(), mDeferredDepth.getHeight(), GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST);	  		}  		LLGLEnable multisample(RenderFSAASamples > 0 ? GL_MULTISAMPLE_ARB : 0); @@ -9994,7 +9995,19 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in)  				}  				else  				{ -				renderGeom(camera); +					renderGeom(camera); + +					if (LLGLSLShader::sNoFixedFunction) +					{ +						gUIProgram.bind(); +					} +					 +					LLWorld::getInstance()->renderPropertyLines(); +					 +					if (LLGLSLShader::sNoFixedFunction) +					{ +						gUIProgram.unbind(); +					}  				}  				if (LLPipeline::sRenderDeferred && materials_in_water) @@ -10117,7 +10130,7 @@ void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera  	}  	LLPipeline::sShadowRender = true; -	U32 types[] = {  +	static const U32 types[] = {   		LLRenderPass::PASS_SIMPLE,   		LLRenderPass::PASS_FULLBRIGHT,   		LLRenderPass::PASS_SHINY,  @@ -11622,7 +11635,7 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar)  	avatar->setImpostorDim(tdim); -	LLVOAvatar::sUseImpostors = true; // @TODO ??? +	LLVOAvatar::sUseImpostors = (0 != LLVOAvatar::sMaxNonImpostors);  	sUseOcclusion = occlusion;  	sReflectionRender = false;  	sImpostorRender = false; diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index c9670a60f2..f43607ccb0 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -254,7 +254,7 @@ public:  	void stateSort(LLCamera& camera, LLCullResult& result);  	void stateSort(LLSpatialGroup* group, LLCamera& camera); -	void stateSort(LLSpatialBridge* bridge, LLCamera& camera); +	void stateSort(LLSpatialBridge* bridge, LLCamera& camera, BOOL fov_changed = FALSE);  	void stateSort(LLDrawable* drawablep, LLCamera& camera);  	void postSort(LLCamera& camera);  	void forAllVisibleDrawables(void (*func)(LLDrawable*)); diff --git a/indra/newview/tests/lldateutil_test.cpp b/indra/newview/tests/lldateutil_test.cpp index 47353962e1..62158d8f66 100644 --- a/indra/newview/tests/lldateutil_test.cpp +++ b/indra/newview/tests/lldateutil_test.cpp @@ -45,7 +45,7 @@ std::map< std::string, std::string > gString;  typedef std::pair< std::string, int > count_string_t;  std::map< count_string_t, std::string > gCountString; -std::string LLTrans::getString(const std::string &xml_desc, const LLStringUtil::format_map_t& args) +std::string LLTrans::getString(const std::string &xml_desc, const LLStringUtil::format_map_t& args, bool def_string)  {  	std::string text = gString[xml_desc];  	LLStringUtil::format(text, args); diff --git a/indra/newview/tests/llsechandler_basic_test.cpp b/indra/newview/tests/llsechandler_basic_test.cpp index 3d01c5378f..63967fae37 100644 --- a/indra/newview/tests/llsechandler_basic_test.cpp +++ b/indra/newview/tests/llsechandler_basic_test.cpp @@ -210,133 +210,139 @@ namespace tut          "-----END CERTIFICATE-----\n"                                     ); +    /* +     * The following certificates were generated using the instructions at +     * https://jamielinux.com/docs/openssl-certificate-authority/sign-server-and-client-certificates.html +     * with the exception that the server certificate has a longer expiration time, and the full text +     * expansion was included in the certificates. +     */      const std::string mPemRootCert(          "Certificate:\n"          "    Data:\n"          "        Version: 3 (0x2)\n"          "        Serial Number:\n" -        "            bb:28:84:73:42:18:8b:67\n" +        "            82:2f:8f:eb:8d:06:24:b0\n"          "    Signature Algorithm: sha256WithRSAEncryption\n"          "        Issuer: C=US, ST=California, L=San Francisco, O=Linden Lab, OU=Second Life Engineering, CN=Integration Test Root CA/emailAddress=noreply@lindenlab.com\n"          "        Validity\n" -        "            Not Before: Apr 10 19:28:59 2017 GMT\n" -        "            Not After : Apr  5 19:28:59 2037 GMT\n" +        "            Not Before: May 22 22:19:45 2018 GMT\n" +        "            Not After : May 17 22:19:45 2038 GMT\n"          "        Subject: C=US, ST=California, L=San Francisco, O=Linden Lab, OU=Second Life Engineering, CN=Integration Test Root CA/emailAddress=noreply@lindenlab.com\n"          "        Subject Public Key Info:\n"          "            Public Key Algorithm: rsaEncryption\n"          "                Public-Key: (4096 bit)\n"          "                Modulus:\n" -        "                    00:af:ea:5d:a6:b3:e2:28:d6:98:48:69:4e:10:b8:\n" -        "                    03:3e:5c:6b:af:e3:d6:f5:e6:1e:b5:6e:77:f0:eb:\n" -        "                    9c:72:2a:ba:f0:9e:f9:a9:d3:7f:9d:64:5c:a5:f2:\n" -        "                    16:99:7c:96:67:69:aa:f1:3e:27:b6:03:c3:f6:8e:\n" -        "                    c1:f9:01:3e:35:04:bf:a4:ff:12:78:77:4b:39:e7:\n" -        "                    e4:93:09:e7:74:b3:3a:07:47:a2:9c:d2:1d:8c:e8:\n" -        "                    77:d9:c2:1c:4e:eb:51:dd:28:82:d4:e0:22:6d:32:\n" -        "                    4a:2e:25:53:b1:46:ff:49:18:99:8d:d6:ad:db:16:\n" -        "                    a5:0d:4a:d1:7c:19:d6:c7:08:7e:d2:90:1f:f9:e1:\n" -        "                    9c:54:bd:bd:c4:75:4f:10:01:78:09:35:5a:f2:2f:\n" -        "                    e5:42:36:76:17:cf:42:c9:ab:ef:aa:23:1e:50:3d:\n" -        "                    f2:9d:17:d1:d0:e9:6c:94:8e:a8:5d:d1:a1:8b:13:\n" -        "                    be:45:cc:77:6b:cb:4b:ad:23:87:1d:16:4a:ac:9d:\n" -        "                    e2:b8:07:c4:17:2b:53:ca:87:7b:81:dd:ad:5c:0a:\n" -        "                    87:00:8a:87:ae:84:cb:81:e2:9f:75:49:2b:e5:b7:\n" -        "                    78:63:be:68:fd:2f:f1:ee:10:f9:51:ef:7f:f1:59:\n" -        "                    f1:43:8d:c3:6d:33:29:4a:e5:25:cb:e1:0f:2a:e7:\n" -        "                    e5:8a:92:cf:5e:56:25:79:92:5e:70:d7:5f:de:55:\n" -        "                    a5:09:77:cf:06:26:62:2d:f6:86:a8:39:02:1d:0b:\n" -        "                    2d:d6:06:d1:68:2e:03:cf:7f:a5:2a:bb:b2:f5:48:\n" -        "                    22:57:bc:1a:18:f0:f9:33:99:f7:20:b7:ac:b7:06:\n" -        "                    01:5d:0b:62:7e:83:f0:00:a0:96:51:9b:0d:1d:23:\n" -        "                    c5:62:b9:27:ba:f8:bd:16:45:cf:13:31:79:6d:5f:\n" -        "                    a9:8b:59:f5:74:97:30:ac:a8:e8:05:fa:72:e5:f0:\n" -        "                    c7:33:8d:20:3d:4c:f3:6b:8e:43:3e:0e:51:9a:2e:\n" -        "                    e2:1d:e6:29:f2:d7:bc:a2:5d:54:e8:90:d3:07:20:\n" -        "                    b0:6e:71:3f:13:ef:c3:7e:9a:cb:57:83:1b:f6:32:\n" -        "                    82:65:cd:69:73:9c:ab:95:76:97:47:2f:ab:b5:3c:\n" -        "                    eb:90:a9:5c:0c:03:24:02:0f:3a:00:08:37:ee:b4:\n" -        "                    e9:21:af:92:cd:a2:49:fe:d5:f3:8f:89:5d:2b:53:\n" -        "                    66:cf:bc:78:d0:37:76:b8:16:d5:8d:21:bf:8f:98:\n" -        "                    b5:43:29:a1:32:ec:8c:58:9b:6b:3a:52:12:89:d1:\n" -        "                    3f:63:01:5f:e5:1b:d2:be:75:d9:65:29:9e:12:a1:\n" -        "                    c4:de:3a:a9:25:94:94:32:d7:e8:ca:d3:02:9b:2f:\n" -        "                    92:9a:11\n" +        "                    00:bd:e0:79:dd:3b:a6:ac:87:d0:39:f0:58:c7:a4:\n" +        "                    42:42:f6:5f:93:b0:36:04:b5:e2:d5:f7:2a:c0:6c:\n" +        "                    a0:13:d2:1e:02:81:57:02:50:4c:57:b7:ef:27:9e:\n" +        "                    f6:f1:f1:30:30:72:1e:57:34:e5:3f:82:3c:21:c4:\n" +        "                    66:d2:73:63:6c:91:e6:dd:49:9e:9c:b1:34:6a:81:\n" +        "                    45:a1:6e:c4:50:28:f2:d8:e3:fe:80:2f:83:aa:28:\n" +        "                    91:b4:8c:57:c9:f1:16:d9:0c:87:3c:25:80:a0:81:\n" +        "                    8d:71:f2:96:e2:16:f1:97:c4:b0:d8:53:bb:13:6c:\n" +        "                    73:54:2f:29:94:85:cf:86:6e:75:71:ad:39:e3:fc:\n" +        "                    39:12:53:93:1c:ce:39:e0:33:da:49:b7:3d:af:b0:\n" +        "                    37:ce:77:09:03:27:32:70:c0:9c:7f:9c:89:ce:90:\n" +        "                    45:b0:7d:94:8b:ff:13:27:ba:88:7f:ae:c4:aa:73:\n" +        "                    d5:47:b8:87:69:89:80:0c:c1:22:18:78:c2:0d:47:\n" +        "                    d9:10:ff:80:79:0d:46:71:ec:d9:ba:c9:f3:77:fd:\n" +        "                    92:6d:1f:0f:d9:54:18:6d:f6:72:24:5c:5c:3d:43:\n" +        "                    49:35:3e:1c:28:de:7e:44:dc:29:c3:9f:62:04:46:\n" +        "                    aa:c4:e6:69:6a:15:f8:e3:74:1c:14:e9:f4:97:7c:\n" +        "                    30:6c:d4:28:fc:2a:0e:1d:6d:39:2e:1d:f9:17:43:\n" +        "                    35:5d:23:e7:ba:e3:a8:e9:97:6b:3c:3e:23:ef:d8:\n" +        "                    bc:fb:7a:57:37:39:93:59:03:fc:78:ca:b1:31:ef:\n" +        "                    26:19:ed:56:e1:63:c3:ad:99:80:5b:47:b5:03:35:\n" +        "                    5f:fe:6a:a6:21:63:ec:50:fb:4e:c9:f9:ae:a5:66:\n" +        "                    d0:55:33:8d:e6:c5:50:5a:c6:8f:5c:34:45:a7:72:\n" +        "                    da:50:f6:66:4c:19:f5:d1:e4:fb:11:8b:a1:b5:4e:\n" +        "                    09:43:81:3d:39:28:86:3b:fe:07:28:97:02:b5:3a:\n" +        "                    07:5f:4a:20:80:1a:7d:a4:8c:f7:6c:f6:c5:9b:f6:\n" +        "                    61:e5:c7:b0:c3:d5:58:38:7b:bb:47:1e:34:d6:16:\n" +        "                    55:c5:d2:6c:b0:93:77:b1:90:69:06:b1:53:cb:1b:\n" +        "                    84:71:cf:b8:87:1b:1e:44:35:b4:2b:bb:04:59:58:\n" +        "                    0b:e8:93:d8:ae:21:9b:b1:1c:89:30:ae:11:80:77:\n" +        "                    cc:16:f3:d6:35:ed:a1:b3:70:b3:4f:cd:a1:56:99:\n" +        "                    ee:0e:c0:00:a4:09:70:c3:5b:0b:be:a1:07:18:dd:\n" +        "                    c6:f4:6d:8b:58:bc:f9:bb:4b:01:2c:f6:cc:2c:9b:\n" +        "                    87:0e:b1:4f:9c:10:be:fc:45:e2:a4:ec:7e:fc:ff:\n" +        "                    45:b8:53\n"          "                Exponent: 65537 (0x10001)\n"          "        X509v3 extensions:\n"          "            X509v3 Subject Key Identifier: \n" -        "                CC:4E:CF:A0:E2:60:4F:BE:F2:77:51:1D:6E:3E:C6:B6:5A:38:23:A8\n" +        "                8A:22:C6:9C:2E:11:F3:40:0C:CE:82:0C:22:59:FF:F8:7F:D0:B9:13\n"          "            X509v3 Authority Key Identifier: \n" -        "                keyid:CC:4E:CF:A0:E2:60:4F:BE:F2:77:51:1D:6E:3E:C6:B6:5A:38:23:A8\n" +        "                keyid:8A:22:C6:9C:2E:11:F3:40:0C:CE:82:0C:22:59:FF:F8:7F:D0:B9:13\n"          "\n"          "            X509v3 Basic Constraints: critical\n"          "                CA:TRUE\n"          "            X509v3 Key Usage: critical\n"          "                Digital Signature, Certificate Sign, CRL Sign\n"          "    Signature Algorithm: sha256WithRSAEncryption\n" -        "         68:b8:c5:d6:dd:e2:2f:5d:29:0b:aa:9f:10:66:88:fd:61:5d:\n" -        "         3a:0a:e0:aa:29:7f:42:4f:db:86:57:c3:96:e3:97:ff:bd:e7:\n" -        "         1e:c5:4d:00:87:64:3c:80:68:d6:f9:61:00:47:5e:f1:92:7f:\n" -        "         6f:0c:c7:8a:87:2b:b3:10:ff:22:8c:0a:8f:9f:5d:14:88:90:\n" -        "         52:12:a0:32:29:ea:8c:21:90:ed:0c:6a:70:26:43:81:bb:6e:\n" -        "         e2:36:4f:72:10:36:87:61:5d:27:f6:19:d9:83:ad:4b:51:7f:\n" -        "         5c:33:64:fd:2e:ac:86:80:95:bc:12:c6:26:02:06:9a:46:8b:\n" -        "         76:d9:89:e4:d6:02:bc:34:7c:f5:9a:51:e1:14:42:c9:7e:68:\n" -        "         16:be:b3:50:e1:42:4b:05:32:8c:d0:2d:44:df:3e:d2:86:a7:\n" -        "         89:20:b6:ee:bd:c8:dd:ad:f9:96:a2:1b:84:ad:51:87:23:66:\n" -        "         c0:fa:09:df:c0:d1:72:5e:a8:28:60:3f:6d:75:1d:6b:bc:a6:\n" -        "         d1:10:d7:be:d9:ac:26:b4:df:58:10:6e:09:33:6b:42:c8:79:\n" -        "         f5:38:53:4d:56:11:15:b8:39:2c:97:e4:7e:a9:63:b7:9a:b4:\n" -        "         b1:ab:7d:4c:3e:80:97:47:f8:dd:2e:74:e2:43:ad:6c:b4:88:\n" -        "         26:2c:1f:f2:88:ab:49:35:bc:65:27:db:59:c2:e6:1a:e5:ad:\n" -        "         f1:c3:44:fb:92:8a:1c:0e:b5:11:7a:00:26:90:e7:73:ee:c0:\n" -        "         8b:d6:b8:fd:ec:e7:80:a7:d2:6f:68:8c:bc:4d:4c:90:20:97:\n" -        "         85:33:7e:03:1b:88:8a:4d:5e:3c:00:f7:78:ec:2d:80:ec:09:\n" -        "         37:27:50:62:54:da:48:64:c9:30:1c:8a:3e:de:08:82:60:8b:\n" -        "         19:da:e2:a7:19:fb:0e:1f:95:b7:cd:1c:c2:cb:07:06:97:c0:\n" -        "         03:65:d5:a0:6f:03:66:22:11:e8:23:c9:98:83:d4:0e:a4:4b:\n" -        "         e5:62:02:62:67:b6:bd:3c:80:92:60:20:2e:0f:0a:59:75:7e:\n" -        "         b1:8e:0c:53:08:bd:12:09:2f:a0:53:dc:8d:46:77:68:bc:99:\n" -        "         7d:1d:41:66:f6:93:86:d4:64:f7:f6:5e:97:8c:4a:1d:93:38:\n" -        "         9c:3b:7c:4e:e9:69:e8:83:c8:0f:f3:3a:42:b5:44:d1:5f:d2:\n" -        "         9a:33:e3:be:1b:8f:74:23:c4:4e:ca:cf:91:38:d6:ee:67:32:\n" -        "         25:62:4f:a1:64:1a:b9:52:98:39:c2:a0:e0:7f:b9:51:74:78:\n" -        "         cc:af:55:08:d6:86:11:62:80:7f:b6:39:a2:60:ee:b7:99:a6:\n" -        "         59:04:76:51:85:e3:ba:59\n" +        "         b3:cb:33:eb:0e:02:64:f4:55:9a:3d:03:9a:cf:6a:4c:18:43:\n" +        "         f7:42:cb:65:dc:61:52:e5:9f:2f:42:97:3c:93:16:22:d4:af:\n" +        "         ae:b2:0f:c3:9b:ef:e0:cc:ee:b6:b1:69:a3:d8:da:26:c3:ad:\n" +        "         3b:c5:64:dc:9f:d4:c2:53:4b:91:6d:c4:92:09:0b:ac:f0:99:\n" +        "         be:6f:b9:3c:03:4a:6d:9f:01:5d:ec:5a:9a:f3:a7:e5:3b:2c:\n" +        "         99:57:7d:7e:25:15:68:20:12:30:96:16:86:f5:db:74:90:60:\n" +        "         fe:8b:df:99:f6:f7:62:49:9f:bc:8d:45:23:0a:c8:73:b8:79:\n" +        "         80:3c:b9:e5:72:85:4b:b3:81:66:74:a2:72:92:4c:44:fd:7b:\n" +        "         46:2e:21:a2:a9:81:a2:f3:26:4d:e3:89:7d:78:b0:c6:6f:b5:\n" +        "         87:cb:ee:25:ed:27:1f:75:13:fa:6d:e9:37:73:ad:07:bb:af:\n" +        "         d3:6c:87:ea:02:01:70:bd:53:aa:ce:39:2c:d4:66:39:33:aa:\n" +        "         d1:9c:ee:67:e3:a9:45:d2:7b:2e:54:09:af:70:5f:3f:5a:67:\n" +        "         2e:6c:72:ef:e0:9d:92:28:4a:df:ba:0b:b7:23:ca:5b:04:11:\n" +        "         45:d1:51:e9:ea:c9:ec:54:fa:34:46:ae:fc:dc:6c:f8:1e:2c:\n" +        "         9e:f4:71:51:8d:b5:a1:26:9a:13:30:be:1e:41:25:59:58:05:\n" +        "         2c:64:c8:f9:5e:38:ae:dc:93:b0:8a:d6:38:74:02:cb:ce:ce:\n" +        "         95:31:76:f6:7c:bf:a4:a1:8e:27:fd:ca:74:82:d1:e1:4d:b6:\n" +        "         48:51:fa:c5:17:59:22:a3:84:be:82:c8:83:ec:61:a0:f4:ee:\n" +        "         2c:e3:a3:ea:e5:51:c9:d3:4f:db:85:bd:ba:7a:52:14:b6:03:\n" +        "         ed:43:17:d8:d7:1c:22:5e:c9:56:d9:d6:81:96:11:e3:5e:01:\n" +        "         40:91:30:09:da:a3:5f:d3:27:60:e5:9d:6c:da:d0:f0:39:01:\n" +        "         23:4a:a6:15:7a:4a:82:eb:ec:72:4a:1d:36:dc:6f:83:c4:85:\n" +        "         84:b5:8d:cd:09:e5:12:63:f3:21:56:c8:64:6b:db:b8:cf:d4:\n" +        "         df:ca:a8:24:8e:df:8d:63:a5:96:84:bf:ff:8b:7e:46:7a:f0:\n" +        "         c7:73:7c:70:8a:f5:17:d0:ac:c8:89:1e:d7:89:42:0f:4d:66:\n" +        "         c4:d8:bb:36:a8:ae:ca:e1:cf:e2:88:f6:cf:b0:44:4a:5f:81:\n" +        "         50:4b:d6:28:81:cd:6c:f0:ec:e6:09:08:f2:59:91:a2:69:ac:\n" +        "         c7:81:fa:ab:61:3e:db:6f:f6:7f:db:1a:9e:b9:5d:cc:cc:33:\n" +        "         fa:95:c6:f7:8d:4b:30:f3\n"          "-----BEGIN CERTIFICATE-----\n" -        "MIIGXDCCBESgAwIBAgIJALsohHNCGItnMA0GCSqGSIb3DQEBCwUAMIG6MQswCQYD\n" +        "MIIGXDCCBESgAwIBAgIJAIIvj+uNBiSwMA0GCSqGSIb3DQEBCwUAMIG6MQswCQYD\n"          "VQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNU2FuIEZyYW5j\n"          "aXNjbzETMBEGA1UECgwKTGluZGVuIExhYjEgMB4GA1UECwwXU2Vjb25kIExpZmUg\n"          "RW5naW5lZXJpbmcxITAfBgNVBAMMGEludGVncmF0aW9uIFRlc3QgUm9vdCBDQTEk\n" -        "MCIGCSqGSIb3DQEJARYVbm9yZXBseUBsaW5kZW5sYWIuY29tMB4XDTE3MDQxMDE5\n" -        "Mjg1OVoXDTM3MDQwNTE5Mjg1OVowgboxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApD\n" +        "MCIGCSqGSIb3DQEJARYVbm9yZXBseUBsaW5kZW5sYWIuY29tMB4XDTE4MDUyMjIy\n" +        "MTk0NVoXDTM4MDUxNzIyMTk0NVowgboxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApD\n"          "YWxpZm9ybmlhMRYwFAYDVQQHDA1TYW4gRnJhbmNpc2NvMRMwEQYDVQQKDApMaW5k\n"          "ZW4gTGFiMSAwHgYDVQQLDBdTZWNvbmQgTGlmZSBFbmdpbmVlcmluZzEhMB8GA1UE\n"          "AwwYSW50ZWdyYXRpb24gVGVzdCBSb290IENBMSQwIgYJKoZIhvcNAQkBFhVub3Jl\n"          "cGx5QGxpbmRlbmxhYi5jb20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC\n" -        "AQCv6l2ms+Io1phIaU4QuAM+XGuv49b15h61bnfw65xyKrrwnvmp03+dZFyl8haZ\n" -        "fJZnaarxPie2A8P2jsH5AT41BL+k/xJ4d0s55+STCed0szoHR6Kc0h2M6HfZwhxO\n" -        "61HdKILU4CJtMkouJVOxRv9JGJmN1q3bFqUNStF8GdbHCH7SkB/54ZxUvb3EdU8Q\n" -        "AXgJNVryL+VCNnYXz0LJq++qIx5QPfKdF9HQ6WyUjqhd0aGLE75FzHdry0utI4cd\n" -        "FkqsneK4B8QXK1PKh3uB3a1cCocAioeuhMuB4p91SSvlt3hjvmj9L/HuEPlR73/x\n" -        "WfFDjcNtMylK5SXL4Q8q5+WKks9eViV5kl5w11/eVaUJd88GJmIt9oaoOQIdCy3W\n" -        "BtFoLgPPf6Uqu7L1SCJXvBoY8Pkzmfcgt6y3BgFdC2J+g/AAoJZRmw0dI8ViuSe6\n" -        "+L0WRc8TMXltX6mLWfV0lzCsqOgF+nLl8MczjSA9TPNrjkM+DlGaLuId5iny17yi\n" -        "XVTokNMHILBucT8T78N+mstXgxv2MoJlzWlznKuVdpdHL6u1POuQqVwMAyQCDzoA\n" -        "CDfutOkhr5LNokn+1fOPiV0rU2bPvHjQN3a4FtWNIb+PmLVDKaEy7IxYm2s6UhKJ\n" -        "0T9jAV/lG9K+ddllKZ4SocTeOqkllJQy1+jK0wKbL5KaEQIDAQABo2MwYTAdBgNV\n" -        "HQ4EFgQUzE7PoOJgT77yd1Edbj7Gtlo4I6gwHwYDVR0jBBgwFoAUzE7PoOJgT77y\n" -        "d1Edbj7Gtlo4I6gwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwDQYJ\n" -        "KoZIhvcNAQELBQADggIBAGi4xdbd4i9dKQuqnxBmiP1hXToK4Kopf0JP24ZXw5bj\n" -        "l/+95x7FTQCHZDyAaNb5YQBHXvGSf28Mx4qHK7MQ/yKMCo+fXRSIkFISoDIp6owh\n" -        "kO0ManAmQ4G7buI2T3IQNodhXSf2GdmDrUtRf1wzZP0urIaAlbwSxiYCBppGi3bZ\n" -        "ieTWArw0fPWaUeEUQsl+aBa+s1DhQksFMozQLUTfPtKGp4kgtu69yN2t+ZaiG4St\n" -        "UYcjZsD6Cd/A0XJeqChgP211HWu8ptEQ177ZrCa031gQbgkza0LIefU4U01WERW4\n" -        "OSyX5H6pY7eatLGrfUw+gJdH+N0udOJDrWy0iCYsH/KIq0k1vGUn21nC5hrlrfHD\n" -        "RPuSihwOtRF6ACaQ53PuwIvWuP3s54Cn0m9ojLxNTJAgl4UzfgMbiIpNXjwA93js\n" -        "LYDsCTcnUGJU2khkyTAcij7eCIJgixna4qcZ+w4flbfNHMLLBwaXwANl1aBvA2Yi\n" -        "EegjyZiD1A6kS+ViAmJntr08gJJgIC4PCll1frGODFMIvRIJL6BT3I1Gd2i8mX0d\n" -        "QWb2k4bUZPf2XpeMSh2TOJw7fE7paeiDyA/zOkK1RNFf0poz474bj3QjxE7Kz5E4\n" -        "1u5nMiViT6FkGrlSmDnCoOB/uVF0eMyvVQjWhhFigH+2OaJg7reZplkEdlGF47pZ\n" +        "AQC94HndO6ash9A58FjHpEJC9l+TsDYEteLV9yrAbKAT0h4CgVcCUExXt+8nnvbx\n" +        "8TAwch5XNOU/gjwhxGbSc2NskebdSZ6csTRqgUWhbsRQKPLY4/6AL4OqKJG0jFfJ\n" +        "8RbZDIc8JYCggY1x8pbiFvGXxLDYU7sTbHNULymUhc+GbnVxrTnj/DkSU5Mczjng\n" +        "M9pJtz2vsDfOdwkDJzJwwJx/nInOkEWwfZSL/xMnuoh/rsSqc9VHuIdpiYAMwSIY\n" +        "eMINR9kQ/4B5DUZx7Nm6yfN3/ZJtHw/ZVBht9nIkXFw9Q0k1Phwo3n5E3CnDn2IE\n" +        "RqrE5mlqFfjjdBwU6fSXfDBs1Cj8Kg4dbTkuHfkXQzVdI+e646jpl2s8PiPv2Lz7\n" +        "elc3OZNZA/x4yrEx7yYZ7VbhY8OtmYBbR7UDNV/+aqYhY+xQ+07J+a6lZtBVM43m\n" +        "xVBaxo9cNEWnctpQ9mZMGfXR5PsRi6G1TglDgT05KIY7/gcolwK1OgdfSiCAGn2k\n" +        "jPds9sWb9mHlx7DD1Vg4e7tHHjTWFlXF0mywk3exkGkGsVPLG4Rxz7iHGx5ENbQr\n" +        "uwRZWAvok9iuIZuxHIkwrhGAd8wW89Y17aGzcLNPzaFWme4OwACkCXDDWwu+oQcY\n" +        "3cb0bYtYvPm7SwEs9swsm4cOsU+cEL78ReKk7H78/0W4UwIDAQABo2MwYTAdBgNV\n" +        "HQ4EFgQUiiLGnC4R80AMzoIMIln/+H/QuRMwHwYDVR0jBBgwFoAUiiLGnC4R80AM\n" +        "zoIMIln/+H/QuRMwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwDQYJ\n" +        "KoZIhvcNAQELBQADggIBALPLM+sOAmT0VZo9A5rPakwYQ/dCy2XcYVLlny9ClzyT\n" +        "FiLUr66yD8Ob7+DM7raxaaPY2ibDrTvFZNyf1MJTS5FtxJIJC6zwmb5vuTwDSm2f\n" +        "AV3sWprzp+U7LJlXfX4lFWggEjCWFob123SQYP6L35n292JJn7yNRSMKyHO4eYA8\n" +        "ueVyhUuzgWZ0onKSTET9e0YuIaKpgaLzJk3jiX14sMZvtYfL7iXtJx91E/pt6Tdz\n" +        "rQe7r9Nsh+oCAXC9U6rOOSzUZjkzqtGc7mfjqUXSey5UCa9wXz9aZy5scu/gnZIo\n" +        "St+6C7cjylsEEUXRUenqyexU+jRGrvzcbPgeLJ70cVGNtaEmmhMwvh5BJVlYBSxk\n" +        "yPleOK7ck7CK1jh0AsvOzpUxdvZ8v6Shjif9ynSC0eFNtkhR+sUXWSKjhL6CyIPs\n" +        "YaD07izjo+rlUcnTT9uFvbp6UhS2A+1DF9jXHCJeyVbZ1oGWEeNeAUCRMAnao1/T\n" +        "J2DlnWza0PA5ASNKphV6SoLr7HJKHTbcb4PEhYS1jc0J5RJj8yFWyGRr27jP1N/K\n" +        "qCSO341jpZaEv/+LfkZ68MdzfHCK9RfQrMiJHteJQg9NZsTYuzaorsrhz+KI9s+w\n" +        "REpfgVBL1iiBzWzw7OYJCPJZkaJprMeB+qthPttv9n/bGp65XczMM/qVxveNSzDz\n"          "-----END CERTIFICATE-----\n"                                     );             @@ -348,124 +354,124 @@ namespace tut          "    Signature Algorithm: sha256WithRSAEncryption\n"          "        Issuer: C=US, ST=California, L=San Francisco, O=Linden Lab, OU=Second Life Engineering, CN=Integration Test Root CA/emailAddress=noreply@lindenlab.com\n"          "        Validity\n" -        "            Not Before: Apr 10 20:24:52 2017 GMT\n" -        "            Not After : Apr  8 20:24:52 2027 GMT\n" +        "            Not Before: May 22 22:39:08 2018 GMT\n" +        "            Not After : May 19 22:39:08 2028 GMT\n"          "        Subject: C=US, ST=California, O=Linden Lab, OU=Second Life Engineering, CN=Integration Test Intermediate CA/emailAddress=noreply@lindenlab.com\n"          "        Subject Public Key Info:\n"          "            Public Key Algorithm: rsaEncryption\n"          "                Public-Key: (4096 bit)\n"          "                Modulus:\n" -        "                    00:b4:9b:29:c6:22:c4:de:78:71:ed:2d:0d:90:32:\n" -        "                    fc:da:e7:8c:51:51:d2:fe:ec:e4:ca:5c:c8:5e:e0:\n" -        "                    c2:97:50:b7:c2:bd:22:91:35:4b:fd:b4:ac:20:21:\n" -        "                    b0:59:15:49:40:ff:91:9e:94:22:91:59:68:f4:ed:\n" -        "                    84:81:8d:be:15:67:02:8e:bf:6d:86:39:7e:42:3a:\n" -        "                    ea:72:9e:ca:5b:ef:1e:96:6c:bc:30:65:c1:73:f6:\n" -        "                    87:92:1f:24:f7:fb:39:77:b1:49:6b:27:5c:21:ba:\n" -        "                    f6:f9:1d:d5:6d:cc:58:8e:6d:d1:6b:fe:ec:89:34:\n" -        "                    34:80:d9:03:27:d5:6f:bc:7f:c7:b3:8c:63:4d:34:\n" -        "                    37:61:d0:f9:54:2e:2a:a8:85:03:04:22:b7:19:5b:\n" -        "                    a3:57:e4:43:a1:88:3c:42:04:c8:c3:fb:ef:0c:78:\n" -        "                    da:76:8c:e1:27:90:b1:b4:e2:c5:f3:b0:7c:0c:95:\n" -        "                    3e:cd:ed:ee:f8:28:28:c0:ba:64:e9:b5:0a:42:f3:\n" -        "                    8f:b1:dd:cc:41:58:a7:e7:a1:b0:2c:8e:58:55:3e:\n" -        "                    8c:d7:db:f2:51:38:96:4f:ae:1d:8e:ae:e3:87:1a:\n" -        "                    6c:8f:6b:3b:5a:1a:a9:49:bc:69:79:9f:28:6f:e2:\n" -        "                    ac:08:40:52:d9:87:c9:f2:27:d7:fb:62:85:5f:7f:\n" -        "                    09:a9:64:07:7b:7a:0e:ba:a5:58:18:23:aa:b2:df:\n" -        "                    66:77:f6:6a:ee:f7:79:18:30:12:b2:cf:60:79:af:\n" -        "                    86:d5:b8:db:ee:a0:13:2f:80:e1:69:0d:67:14:e5:\n" -        "                    9a:99:4c:10:2d:b1:26:6c:b8:3c:10:2f:8e:db:cb:\n" -        "                    4a:9e:9e:50:a2:98:76:49:7b:26:c1:8f:bf:50:00:\n" -        "                    f3:af:06:98:0a:af:78:03:84:5d:56:41:e0:90:7c:\n" -        "                    9a:a7:4d:5a:62:4d:8f:6a:cd:0e:27:c3:0c:4a:ba:\n" -        "                    68:8c:ff:e5:b9:21:a1:60:a3:d6:7b:2c:5c:09:3d:\n" -        "                    46:ec:4d:c9:b3:09:72:2a:ce:9b:65:f9:56:5e:6e:\n" -        "                    2e:24:64:4a:29:7f:17:1d:92:1d:bd:6e:d7:ce:73:\n" -        "                    cf:57:23:00:1d:db:bc:77:d4:fe:b1:ea:40:34:5c:\n" -        "                    01:94:ee:c5:6a:5e:ce:63:d2:61:c9:55:ca:13:93:\n" -        "                    e8:be:0f:00:0a:f5:6c:fc:31:e3:08:05:a4:9a:b2:\n" -        "                    8e:85:b5:0d:fd:fd:6f:d9:10:e4:68:8a:1b:81:27:\n" -        "                    da:14:c6:08:5a:bd:f1:ec:c6:41:ac:05:d7:cc:63:\n" -        "                    4e:e8:e0:18:7e:f3:ed:4b:60:81:dd:07:fe:5d:ad:\n" -        "                    9a:7c:80:99:6b:06:0f:ae:f6:7d:27:27:a0:3d:05:\n" -        "                    c6:cb:dd\n" +        "                    00:ce:a3:70:e2:c4:fb:4b:97:90:a1:30:bb:c1:1b:\n" +        "                    13:b9:aa:7e:46:17:a3:26:8d:69:3f:5e:73:95:e8:\n" +        "                    6a:b1:0a:b4:8f:50:65:e3:c6:5c:39:24:34:df:0b:\n" +        "                    b7:cc:ce:62:0c:36:5a:12:2c:fe:35:4c:e9:1c:ac:\n" +        "                    80:5e:24:99:d7:aa:bd:be:48:c0:62:64:77:36:88:\n" +        "                    66:ce:f4:a8:dd:d2:76:24:62:90:55:41:fc:1d:13:\n" +        "                    4e:a7:4e:57:bc:a8:a4:59:4b:2c:5a:1c:d8:cc:16:\n" +        "                    de:e8:88:30:c9:95:df:2f:a6:14:28:0f:eb:34:46:\n" +        "                    12:58:ba:da:0e:e6:de:9c:15:f6:f4:e3:9f:74:aa:\n" +        "                    70:89:79:8b:e9:5a:7b:18:54:15:94:3a:23:0a:65:\n" +        "                    78:05:d9:33:90:2a:ce:15:18:0d:52:fc:5c:31:65:\n" +        "                    20:d0:12:37:8c:11:80:ba:d4:b0:82:73:00:4b:49:\n" +        "                    be:cb:d6:bc:e7:cd:61:f3:00:98:99:74:5a:37:81:\n" +        "                    49:96:7e:14:01:1b:86:d2:d0:06:94:40:63:63:46:\n" +        "                    11:fc:33:5c:bd:3a:5e:d4:e5:44:47:64:50:bd:a6:\n" +        "                    97:55:70:64:9b:26:cc:de:20:82:90:6a:83:41:9c:\n" +        "                    6f:71:47:14:be:cb:68:7c:85:be:ef:2e:76:12:19:\n" +        "                    d3:c9:87:32:b4:ac:60:20:16:28:2d:af:bc:e8:01:\n" +        "                    c6:7f:fb:d8:11:d5:f4:b7:14:bd:27:08:5b:72:be:\n" +        "                    09:e0:91:c8:9c:7b:b4:b3:12:ef:32:36:be:b1:b9:\n" +        "                    a2:b7:e3:69:47:30:76:ba:9c:9b:19:99:4d:53:dd:\n" +        "                    5c:e8:2c:f1:b2:64:69:cf:15:bd:f8:bb:58:95:73:\n" +        "                    58:38:95:b4:7a:cf:84:29:a6:c2:db:f0:bd:ef:97:\n" +        "                    26:d4:99:ac:d7:c7:be:b0:0d:11:f4:26:86:2d:77:\n" +        "                    42:52:25:d7:56:c7:e3:97:b1:36:5c:97:71:d0:9b:\n" +        "                    f5:b5:50:8d:f9:ff:fb:10:77:3c:b5:53:6d:a1:43:\n" +        "                    35:a9:03:32:05:ab:d7:f5:d1:19:bd:5f:92:a3:00:\n" +        "                    2a:79:37:a4:76:4f:e9:32:0d:e4:86:bb:ea:c3:1a:\n" +        "                    c5:33:e8:16:d4:a5:d8:e0:e8:bb:c2:f0:22:15:e2:\n" +        "                    d9:8c:ae:ac:7d:2b:bf:eb:a3:4c:3b:29:1d:94:ac:\n" +        "                    a3:bb:6d:ba:6d:03:91:03:cf:46:12:c4:66:21:c5:\n" +        "                    c6:67:d8:11:19:79:01:0e:6e:84:1c:76:6f:11:3d:\n" +        "                    eb:94:89:c5:6a:26:1f:cd:e0:11:8b:51:ee:99:35:\n" +        "                    69:e5:7f:0b:77:2a:94:e4:4b:64:b9:83:04:30:05:\n" +        "                    e4:a2:e3\n"          "                Exponent: 65537 (0x10001)\n"          "        X509v3 extensions:\n"          "            X509v3 Subject Key Identifier: \n" -        "                CC:57:77:7A:16:10:AE:94:99:A1:9F:AB:2F:79:42:74:D7:BE:8E:63\n" +        "                83:21:DE:EC:C0:79:03:6D:1E:83:F3:E5:97:29:D5:5A:C0:96:40:FA\n"          "            X509v3 Authority Key Identifier: \n" -        "                keyid:CC:4E:CF:A0:E2:60:4F:BE:F2:77:51:1D:6E:3E:C6:B6:5A:38:23:A8\n" +        "                keyid:8A:22:C6:9C:2E:11:F3:40:0C:CE:82:0C:22:59:FF:F8:7F:D0:B9:13\n"          "\n"          "            X509v3 Basic Constraints: critical\n"          "                CA:TRUE, pathlen:0\n"          "            X509v3 Key Usage: critical\n"          "                Digital Signature, Certificate Sign, CRL Sign\n"          "    Signature Algorithm: sha256WithRSAEncryption\n" -        "         41:78:c6:7d:0f:1f:0e:82:c8:7e:3a:56:7d:f7:a6:5e:c3:dc:\n" -        "         88:9e:e5:77:7d:c5:3c:70:2f:8a:cf:93:59:92:8f:17:04:5b:\n" -        "         d7:d5:58:d9:cc:d6:df:77:0b:5f:db:ea:54:b6:3b:ec:d6:c4:\n" -        "         26:4f:63:54:06:ae:bc:5f:c3:b5:00:52:6f:2a:f6:c0:84:0b:\n" -        "         3e:fd:fe:82:87:82:40:5f:f7:08:5b:17:42:5e:46:60:66:77:\n" -        "         8f:04:2d:c0:7a:50:c2:58:42:10:fc:99:f8:30:3a:c6:ba:fa:\n" -        "         13:a5:ee:19:f8:4c:c8:72:37:64:16:16:ef:7e:a1:cb:df:af:\n" -        "         26:c5:ff:88:46:30:04:80:4c:cd:1a:56:f6:7a:4a:7b:c2:5e:\n" -        "         58:3b:ec:84:30:92:9c:7c:83:39:59:7f:57:f2:e7:1a:2c:ed:\n" -        "         d9:e4:8a:1f:7e:ce:92:25:d9:78:c5:1b:f4:c6:31:10:79:3d:\n" -        "         8b:1d:e9:50:6d:87:2d:01:55:e0:59:c1:45:cd:ad:de:68:00:\n" -        "         91:9b:2a:9d:f5:aa:56:8d:48:9a:bf:aa:46:57:90:ba:4b:5d:\n" -        "         70:cf:1b:b2:9d:5d:21:8d:5d:b5:9e:35:96:e5:34:2b:37:52:\n" -        "         ec:f7:03:9e:ca:e4:80:dd:1c:e3:89:e4:cd:67:5e:45:5e:88:\n" -        "         3b:2c:28:19:f2:ae:d2:51:7d:9b:12:5a:74:64:ea:41:b4:98:\n" -        "         6c:85:87:58:45:01:29:c3:0f:e7:1a:76:72:0f:d1:2a:c8:62:\n" -        "         b6:2d:67:42:3c:0b:bf:1d:2a:ab:85:19:aa:7c:42:b3:0f:c1:\n" -        "         9f:1b:b7:b5:ff:19:cb:2e:d8:98:b7:99:35:a3:34:ba:31:0a:\n" -        "         ba:59:fd:fe:72:53:3d:19:a7:36:4f:e1:a5:51:dd:ff:9f:6d:\n" -        "         a1:22:64:01:dc:f4:8a:19:d3:5a:95:b6:a0:59:f8:28:f8:a1:\n" -        "         bc:50:41:f5:f7:1a:42:e2:a1:aa:cc:44:36:64:ba:eb:b0:06:\n" -        "         05:58:2c:92:57:cd:8f:6a:ac:04:ba:4f:4d:71:4b:d4:c4:0d:\n" -        "         13:a2:75:de:48:c7:af:ef:1a:0d:d1:ac:94:53:68:c4:b8:2b:\n" -        "         88:4f:9d:78:b0:9b:a7:c4:a6:57:ad:3d:f5:1e:b4:fe:1d:d7:\n" -        "         42:6c:c4:c5:f6:8c:29:5c:92:3a:7d:79:f2:0d:01:ff:3c:29:\n" -        "         01:b9:91:59:7a:ea:e3:59:bd:67:28:3b:46:60:2c:e4:fd:61:\n" -        "         49:8d:3d:7f:ce:c2:d7:1d:2f:da:74:2f:38:e6:b2:f0:1f:5f:\n" -        "         43:dc:43:6c:e2:e3:c8:25:e6:6e:72:6b:90:50:f8:5c:9a:98:\n" -        "         20:0e:04:e2:b3:59:c9:3a\n" +        "         a3:6c:85:9a:2e:4e:7e:5d:83:63:0f:f5:4f:a9:7d:ec:0e:6f:\n" +        "         ae:d7:ba:df:64:e0:46:0e:3d:da:18:15:2c:f3:73:ca:81:b1:\n" +        "         10:d9:53:14:21:7d:72:5c:94:88:a5:9d:ad:ab:45:42:c6:64:\n" +        "         a9:d9:2e:4e:29:47:2c:b1:95:07:b7:62:48:68:1f:68:13:1c:\n" +        "         d2:a0:fb:5e:38:24:4a:82:0a:87:c9:93:20:43:7e:e9:f9:79:\n" +        "         ef:03:a2:bd:9e:24:6b:0a:01:5e:4a:36:c5:7d:7a:fe:d6:aa:\n" +        "         2f:c2:8c:38:8a:99:3c:b0:6a:e5:60:be:56:d6:eb:60:03:55:\n" +        "         24:42:a0:1a:fa:91:24:a3:53:15:75:5d:c8:eb:7c:1e:68:5a:\n" +        "         7e:13:34:e3:85:37:1c:76:3f:77:67:1b:ed:1b:52:17:fc:4a:\n" +        "         a3:e2:74:84:80:2c:69:fc:dd:7d:26:97:c4:2a:69:7d:9c:dc:\n" +        "         61:97:70:29:a7:3f:2b:5b:2b:22:51:fd:fe:6a:5d:f9:e7:14:\n" +        "         48:b7:2d:c8:33:58:fc:f2:5f:27:f7:26:16:be:be:b5:aa:a2:\n" +        "         64:53:3c:69:e8:b5:61:eb:ab:91:a5:b4:09:9b:f6:98:b8:5c:\n" +        "         5b:24:2f:93:f5:2b:9c:8c:58:fb:26:3f:67:53:d7:42:64:e8:\n" +        "         79:77:73:41:4e:e3:02:39:0b:b6:68:97:8b:84:e8:1d:83:a8:\n" +        "         15:f1:06:46:47:80:42:5e:14:e2:61:8a:76:84:d5:d4:71:7f:\n" +        "         4e:ff:d9:74:87:ff:32:c5:87:20:0a:d4:59:40:3e:d8:17:ef:\n" +        "         da:65:e9:0a:51:fe:1e:c3:46:91:d2:ee:e4:23:57:97:87:d4:\n" +        "         a6:a5:eb:ef:81:6a:d8:8c:d6:1f:8e:b1:18:4c:6b:89:32:55:\n" +        "         53:68:26:9e:bb:03:be:2c:e9:8b:ff:97:9c:1c:ac:28:c3:9f:\n" +        "         0b:b7:93:23:24:31:63:e4:19:13:f2:bb:08:71:b7:c5:c5:c4:\n" +        "         10:ff:dc:fc:33:54:a4:5e:ec:a3:fe:0a:80:ca:9c:bc:95:6f:\n" +        "         5f:39:91:3b:61:69:16:94:0f:57:4b:fc:4b:b1:be:72:98:5d:\n" +        "         10:f9:08:a7:d6:e0:e8:3d:5d:54:7d:fa:4b:6a:dd:98:41:ed:\n" +        "         84:a1:39:67:5c:6c:7f:0c:b0:e1:98:c1:14:ed:fe:1e:e8:05:\n" +        "         8d:7f:6a:24:cb:1b:05:42:0d:7f:13:ba:ca:b5:91:db:a5:f0:\n" +        "         40:2b:70:7a:2a:a5:5d:ed:56:0c:f0:c2:72:ee:63:dd:cb:5d:\n" +        "         76:f6:08:e6:e6:30:ef:3a:b2:16:34:41:a4:e1:30:14:bc:c7:\n" +        "         f9:23:3a:1a:70:df:b8:cc\n"          "-----BEGIN CERTIFICATE-----\n"          "MIIGSDCCBDCgAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwgboxCzAJBgNVBAYTAlVT\n"          "MRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1TYW4gRnJhbmNpc2NvMRMw\n"          "EQYDVQQKDApMaW5kZW4gTGFiMSAwHgYDVQQLDBdTZWNvbmQgTGlmZSBFbmdpbmVl\n"          "cmluZzEhMB8GA1UEAwwYSW50ZWdyYXRpb24gVGVzdCBSb290IENBMSQwIgYJKoZI\n" -        "hvcNAQkBFhVub3JlcGx5QGxpbmRlbmxhYi5jb20wHhcNMTcwNDEwMjAyNDUyWhcN\n" -        "MjcwNDA4MjAyNDUyWjCBqjELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3Ju\n" +        "hvcNAQkBFhVub3JlcGx5QGxpbmRlbmxhYi5jb20wHhcNMTgwNTIyMjIzOTA4WhcN\n" +        "MjgwNTE5MjIzOTA4WjCBqjELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3Ju\n"          "aWExEzARBgNVBAoMCkxpbmRlbiBMYWIxIDAeBgNVBAsMF1NlY29uZCBMaWZlIEVu\n"          "Z2luZWVyaW5nMSkwJwYDVQQDDCBJbnRlZ3JhdGlvbiBUZXN0IEludGVybWVkaWF0\n"          "ZSBDQTEkMCIGCSqGSIb3DQEJARYVbm9yZXBseUBsaW5kZW5sYWIuY29tMIICIjAN\n" -        "BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAtJspxiLE3nhx7S0NkDL82ueMUVHS\n" -        "/uzkylzIXuDCl1C3wr0ikTVL/bSsICGwWRVJQP+RnpQikVlo9O2EgY2+FWcCjr9t\n" -        "hjl+Qjrqcp7KW+8elmy8MGXBc/aHkh8k9/s5d7FJaydcIbr2+R3VbcxYjm3Ra/7s\n" -        "iTQ0gNkDJ9VvvH/Hs4xjTTQ3YdD5VC4qqIUDBCK3GVujV+RDoYg8QgTIw/vvDHja\n" -        "dozhJ5CxtOLF87B8DJU+ze3u+CgowLpk6bUKQvOPsd3MQVin56GwLI5YVT6M19vy\n" -        "UTiWT64djq7jhxpsj2s7WhqpSbxpeZ8ob+KsCEBS2YfJ8ifX+2KFX38JqWQHe3oO\n" -        "uqVYGCOqst9md/Zq7vd5GDASss9gea+G1bjb7qATL4DhaQ1nFOWamUwQLbEmbLg8\n" -        "EC+O28tKnp5Qoph2SXsmwY+/UADzrwaYCq94A4RdVkHgkHyap01aYk2Pas0OJ8MM\n" -        "SrpojP/luSGhYKPWeyxcCT1G7E3JswlyKs6bZflWXm4uJGRKKX8XHZIdvW7XznPP\n" -        "VyMAHdu8d9T+sepANFwBlO7Fal7OY9JhyVXKE5Povg8ACvVs/DHjCAWkmrKOhbUN\n" -        "/f1v2RDkaIobgSfaFMYIWr3x7MZBrAXXzGNO6OAYfvPtS2CB3Qf+Xa2afICZawYP\n" -        "rvZ9JyegPQXGy90CAwEAAaNmMGQwHQYDVR0OBBYEFMxXd3oWEK6UmaGfqy95QnTX\n" -        "vo5jMB8GA1UdIwQYMBaAFMxOz6DiYE++8ndRHW4+xrZaOCOoMBIGA1UdEwEB/wQI\n" -        "MAYBAf8CAQAwDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4ICAQBBeMZ9\n" -        "Dx8Ogsh+OlZ996Zew9yInuV3fcU8cC+Kz5NZko8XBFvX1VjZzNbfdwtf2+pUtjvs\n" -        "1sQmT2NUBq68X8O1AFJvKvbAhAs+/f6Ch4JAX/cIWxdCXkZgZnePBC3AelDCWEIQ\n" -        "/Jn4MDrGuvoTpe4Z+EzIcjdkFhbvfqHL368mxf+IRjAEgEzNGlb2ekp7wl5YO+yE\n" -        "MJKcfIM5WX9X8ucaLO3Z5Ioffs6SJdl4xRv0xjEQeT2LHelQbYctAVXgWcFFza3e\n" -        "aACRmyqd9apWjUiav6pGV5C6S11wzxuynV0hjV21njWW5TQrN1Ls9wOeyuSA3Rzj\n" -        "ieTNZ15FXog7LCgZ8q7SUX2bElp0ZOpBtJhshYdYRQEpww/nGnZyD9EqyGK2LWdC\n" -        "PAu/HSqrhRmqfEKzD8GfG7e1/xnLLtiYt5k1ozS6MQq6Wf3+clM9Gac2T+GlUd3/\n" -        "n22hImQB3PSKGdNalbagWfgo+KG8UEH19xpC4qGqzEQ2ZLrrsAYFWCySV82PaqwE\n" -        "uk9NcUvUxA0TonXeSMev7xoN0ayUU2jEuCuIT514sJunxKZXrT31HrT+HddCbMTF\n" -        "9owpXJI6fXnyDQH/PCkBuZFZeurjWb1nKDtGYCzk/WFJjT1/zsLXHS/adC845rLw\n" -        "H19D3ENs4uPIJeZucmuQUPhcmpggDgTis1nJOg==\n" +        "BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAzqNw4sT7S5eQoTC7wRsTuap+Rhej\n" +        "Jo1pP15zlehqsQq0j1Bl48ZcOSQ03wu3zM5iDDZaEiz+NUzpHKyAXiSZ16q9vkjA\n" +        "YmR3NohmzvSo3dJ2JGKQVUH8HRNOp05XvKikWUssWhzYzBbe6IgwyZXfL6YUKA/r\n" +        "NEYSWLraDubenBX29OOfdKpwiXmL6Vp7GFQVlDojCmV4BdkzkCrOFRgNUvxcMWUg\n" +        "0BI3jBGAutSwgnMAS0m+y9a8581h8wCYmXRaN4FJln4UARuG0tAGlEBjY0YR/DNc\n" +        "vTpe1OVER2RQvaaXVXBkmybM3iCCkGqDQZxvcUcUvstofIW+7y52EhnTyYcytKxg\n" +        "IBYoLa+86AHGf/vYEdX0txS9Jwhbcr4J4JHInHu0sxLvMja+sbmit+NpRzB2upyb\n" +        "GZlNU91c6CzxsmRpzxW9+LtYlXNYOJW0es+EKabC2/C975cm1Jms18e+sA0R9CaG\n" +        "LXdCUiXXVsfjl7E2XJdx0Jv1tVCN+f/7EHc8tVNtoUM1qQMyBavX9dEZvV+SowAq\n" +        "eTekdk/pMg3khrvqwxrFM+gW1KXY4Oi7wvAiFeLZjK6sfSu/66NMOykdlKyju226\n" +        "bQORA89GEsRmIcXGZ9gRGXkBDm6EHHZvET3rlInFaiYfzeARi1HumTVp5X8LdyqU\n" +        "5EtkuYMEMAXkouMCAwEAAaNmMGQwHQYDVR0OBBYEFIMh3uzAeQNtHoPz5Zcp1VrA\n" +        "lkD6MB8GA1UdIwQYMBaAFIoixpwuEfNADM6CDCJZ//h/0LkTMBIGA1UdEwEB/wQI\n" +        "MAYBAf8CAQAwDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4ICAQCjbIWa\n" +        "Lk5+XYNjD/VPqX3sDm+u17rfZOBGDj3aGBUs83PKgbEQ2VMUIX1yXJSIpZ2tq0VC\n" +        "xmSp2S5OKUcssZUHt2JIaB9oExzSoPteOCRKggqHyZMgQ37p+XnvA6K9niRrCgFe\n" +        "SjbFfXr+1qovwow4ipk8sGrlYL5W1utgA1UkQqAa+pEko1MVdV3I63weaFp+EzTj\n" +        "hTccdj93ZxvtG1IX/Eqj4nSEgCxp/N19JpfEKml9nNxhl3Appz8rWysiUf3+al35\n" +        "5xRIty3IM1j88l8n9yYWvr61qqJkUzxp6LVh66uRpbQJm/aYuFxbJC+T9SucjFj7\n" +        "Jj9nU9dCZOh5d3NBTuMCOQu2aJeLhOgdg6gV8QZGR4BCXhTiYYp2hNXUcX9O/9l0\n" +        "h/8yxYcgCtRZQD7YF+/aZekKUf4ew0aR0u7kI1eXh9SmpevvgWrYjNYfjrEYTGuJ\n" +        "MlVTaCaeuwO+LOmL/5ecHKwow58Lt5MjJDFj5BkT8rsIcbfFxcQQ/9z8M1SkXuyj\n" +        "/gqAypy8lW9fOZE7YWkWlA9XS/xLsb5ymF0Q+Qin1uDoPV1UffpLat2YQe2EoTln\n" +        "XGx/DLDhmMEU7f4e6AWNf2okyxsFQg1/E7rKtZHbpfBAK3B6KqVd7VYM8MJy7mPd\n" +        "y1129gjm5jDvOrIWNEGk4TAUvMf5IzoacN+4zA==\n"          "-----END CERTIFICATE-----\n"                                             ); @@ -477,31 +483,31 @@ namespace tut          "    Signature Algorithm: sha256WithRSAEncryption\n"          "        Issuer: C=US, ST=California, O=Linden Lab, OU=Second Life Engineering, CN=Integration Test Intermediate CA/emailAddress=noreply@lindenlab.com\n"          "        Validity\n" -        "            Not Before: Apr 10 21:35:07 2017 GMT\n" -        "            Not After : Apr 20 21:35:07 2018 GMT\n" +        "            Not Before: May 22 22:58:15 2018 GMT\n" +        "            Not After : Jul 19 22:58:15 2024 GMT\n"          "        Subject: C=US, ST=California, L=San Francisco, O=Linden Lab, OU=Second Life Engineering, CN=Integration Test Server Cert/emailAddress=noreply@lindenlab.com\n"          "        Subject Public Key Info:\n"          "            Public Key Algorithm: rsaEncryption\n"          "                Public-Key: (2048 bit)\n"          "                Modulus:\n" -        "                    00:ba:51:fb:01:57:44:2f:99:03:36:82:c0:6a:d2:\n" -        "                    17:1d:f9:e1:49:71:b1:d1:61:c4:90:61:40:99:aa:\n" -        "                    8e:78:99:40:c8:b7:f5:bd:78:a5:7a:c8:fb:73:33:\n" -        "                    74:c0:78:ee:2d:55:08:78:6c:e4:e0:87:4a:34:df:\n" -        "                    6a:25:f7:8c:86:87:0e:f6:df:00:a7:42:4f:89:e3:\n" -        "                    b1:c0:db:2a:9d:96:2b:6f:47:66:04:9b:e8:f0:18:\n" -        "                    ce:7b:4b:bf:8b:6e:24:7e:df:89:07:b4:f5:69:1d:\n" -        "                    4e:9d:9d:c1:6b:19:51:60:56:3e:4a:b8:c2:c0:9d:\n" -        "                    67:fb:fe:d7:73:fa:61:38:85:9b:b0:5f:80:db:a1:\n" -        "                    57:5e:9f:90:af:7d:33:31:7d:bd:73:0b:a2:d5:1e:\n" -        "                    ff:10:a5:6d:fb:c7:55:e6:a0:81:21:f5:d7:23:e5:\n" -        "                    9c:c1:f2:29:8a:aa:83:9f:75:9f:84:fc:65:4c:29:\n" -        "                    b3:98:1f:a6:05:0b:1a:a8:0d:68:2e:20:47:2d:06:\n" -        "                    46:de:92:3d:eb:02:a3:b2:9f:65:66:44:7c:b0:da:\n" -        "                    55:77:f5:5a:9f:c0:58:b6:ff:7d:31:41:72:cc:bd:\n" -        "                    7a:1d:58:36:a8:f2:ca:6a:ca:6b:03:29:ac:94:ad:\n" -        "                    93:f4:7a:14:52:b3:ce:61:e1:7e:6c:8f:08:ad:a9:\n" -        "                    5d:37\n" +        "                    00:bf:a1:1c:76:82:4a:10:1d:25:0e:02:e2:7a:64:\n" +        "                    54:c7:94:c5:c0:98:d5:35:f3:cb:cb:30:ba:31:9c:\n" +        "                    bd:4c:2f:4a:4e:24:03:4b:87:5c:c1:5c:fe:d9:89:\n" +        "                    3b:cb:01:bc:eb:a5:b7:78:dc:b3:58:e5:78:a7:15:\n" +        "                    34:50:30:aa:16:3a:b2:94:17:6d:1e:7f:b2:70:1e:\n" +        "                    96:41:bb:1d:e3:22:80:fa:dc:00:6a:fb:34:3e:67:\n" +        "                    e7:c2:21:2f:1b:d3:af:04:49:91:eb:bb:60:e0:26:\n" +        "                    52:75:28:8a:08:5b:91:56:4e:51:50:40:51:70:af:\n" +        "                    cb:80:66:c8:59:e9:e2:48:a8:62:d0:26:67:80:0a:\n" +        "                    12:16:d1:f6:15:9e:1f:f5:92:37:f3:c9:2f:03:9e:\n" +        "                    22:f6:60:5a:76:45:8c:01:2c:99:54:72:19:db:b7:\n" +        "                    72:e6:5a:69:f3:e9:31:65:5d:0f:c7:5c:9c:17:29:\n" +        "                    71:14:7f:db:47:c9:1e:65:a2:41:b0:2f:14:17:ec:\n" +        "                    4b:25:f2:43:8f:b4:a3:8d:37:1a:07:34:b3:29:bb:\n" +        "                    8a:44:8e:84:08:a2:1b:76:7a:cb:c2:39:2f:6e:e3:\n" +        "                    fc:d6:91:b5:1f:ce:58:91:57:70:35:6e:25:a9:48:\n" +        "                    0e:07:cf:4e:dd:16:42:65:cf:8a:42:b3:27:e6:fe:\n" +        "                    6a:e3\n"          "                Exponent: 65537 (0x10001)\n"          "        X509v3 extensions:\n"          "            X509v3 Basic Constraints: \n" @@ -511,9 +517,9 @@ namespace tut          "            Netscape Comment: \n"          "                OpenSSL Generated Server Certificate\n"          "            X509v3 Subject Key Identifier: \n" -        "                6B:69:AA:91:99:C8:8C:01:72:58:D3:1F:F8:29:73:9C:98:F7:3F:5F\n" +        "                BB:59:9F:DE:6B:51:A7:6C:B3:6D:5B:8B:42:F7:B1:65:77:17:A4:E4\n"          "            X509v3 Authority Key Identifier: \n" -        "                keyid:CC:57:77:7A:16:10:AE:94:99:A1:9F:AB:2F:79:42:74:D7:BE:8E:63\n" +        "                keyid:83:21:DE:EC:C0:79:03:6D:1E:83:F3:E5:97:29:D5:5A:C0:96:40:FA\n"          "                DirName:/C=US/ST=California/L=San Francisco/O=Linden Lab/OU=Second Life Engineering/CN=Integration Test Root CA/emailAddress=noreply@lindenlab.com\n"          "                serial:10:00\n"          "\n" @@ -522,71 +528,71 @@ namespace tut          "            X509v3 Extended Key Usage: \n"          "                TLS Web Server Authentication\n"          "    Signature Algorithm: sha256WithRSAEncryption\n" -        "         ac:35:1a:96:65:28:7c:ed:c5:e3:b9:ef:52:9e:66:b8:63:2e:\n" -        "         de:73:97:3c:91:d5:02:a3:62:9e:c6:5f:f7:18:ed:7f:f8:a1:\n" -        "         66:d2:bc:12:fd:90:b8:fb:ef:ce:fe:e4:21:5e:b9:d1:c9:65:\n" -        "         13:4b:d0:e5:d0:9a:9b:f3:d6:79:bd:9b:af:25:93:01:32:5c:\n" -        "         14:48:03:c1:f7:c6:19:80:d4:1b:f7:e3:82:59:0c:50:0d:85:\n" -        "         97:64:e5:4e:2f:5e:cb:b6:dc:a0:44:64:32:ba:57:ee:45:26:\n" -        "         58:c2:36:71:a8:90:3a:37:48:33:75:79:8e:4f:b1:2d:65:6e:\n" -        "         04:9f:35:28:40:97:f3:80:c1:c8:bb:b9:cd:a2:aa:42:a9:9a:\n" -        "         c6:ab:ac:48:a4:eb:0a:17:19:a0:44:9d:8a:7f:b1:21:a1:14:\n" -        "         ac:0f:71:e0:e8:28:07:44:8a:e7:70:c9:af:19:08:8f:be:2c:\n" -        "         79:af:62:af:9f:8e:d8:4a:c5:09:d5:27:1a:29:c3:2a:f1:b9:\n" -        "         a2:df:0b:e4:22:22:4e:26:11:ad:3d:39:4c:e6:53:49:d5:65:\n" -        "         8c:e8:68:98:91:50:40:ff:fd:ac:ef:71:12:28:a8:b3:5f:f7:\n" -        "         b3:26:2e:eb:f4:d0:d4:68:31:ee:4a:78:b3:85:60:37:1b:21:\n" -        "         2d:e9:f2:67:5a:64:17:e5:30:fc:2d:ed:59:a0:06:8d:90:ea:\n" -        "         ba:26:2f:d8:ac:68:98:db:42:87:39:65:64:b6:08:9f:70:dc:\n" -        "         74:8d:ac:26:ce:8e:a7:dc:1d:41:de:82:7c:00:46:d0:23:74:\n" -        "         b5:5a:4c:91:e4:92:11:a4:13:fd:50:05:86:89:c4:fd:11:ce:\n" -        "         17:44:8f:35:ea:c8:4e:8c:a5:e1:ed:62:32:ff:2f:f7:92:f3:\n" -        "         f7:5c:d2:e7:27:d8:ff:f7:92:7d:dc:a6:ca:d9:e0:92:9d:db:\n" -        "         34:9e:6e:c8:f4:f1:d0:d8:30:c2:85:87:c5:f6:ed:0b:d4:b1:\n" -        "         a6:7c:c1:cd:55:41:c0:e4:cf:06:62:31:fd:4e:b1:eb:45:71:\n" -        "         5b:7c:42:02:4c:ee:74:27:8a:81:11:f1:32:89:40:c9:85:03:\n" -        "         bb:e8:73:55:53:f0:73:eb:47:68:4c:34:9a:1d:7d:cb:54:50:\n" -        "         59:c7:82:3e:42:5c:81:51:7a:01:71:86:a1:b0:da:e6:09:3a:\n" -        "         29:ee:e9:9e:58:19:d7:81:69:bd:3c:5a:02:49:6f:3c:03:0e:\n" -        "         4a:79:06:50:40:8a:60:11:35:6b:56:fc:34:46:52:68:ca:d3:\n" -        "         3a:c1:85:bc:e4:25:57:70:b4:ab:36:d8:8b:0a:6b:8d:7b:b7:\n" -        "         88:7d:10:33:6e:be:83:e6\n" +        "         18:a6:58:55:9b:d4:af:7d:8a:27:d3:28:3a:4c:4b:42:4e:f0:\n" +        "         30:d6:d9:95:11:48:12:0a:96:40:d9:2b:21:39:c5:d4:8d:e5:\n" +        "         10:bc:68:78:69:0b:9f:15:4a:0b:f1:ab:99:45:0c:20:5f:27:\n" +        "         df:e7:14:2d:4a:30:f2:c2:8d:37:73:36:1a:27:55:5a:08:5f:\n" +        "         71:a1:5e:05:83:b2:59:fe:02:5e:d7:4a:30:15:23:58:04:cf:\n" +        "         48:cc:b0:71:88:9c:6b:57:f0:04:0a:d3:a0:64:6b:ee:f3:5f:\n" +        "         ea:ac:e1:2b:b9:7f:79:b8:db:ce:72:48:72:db:c8:5c:38:72:\n" +        "         31:55:d0:ff:6b:bd:73:23:a7:30:18:5d:ed:47:18:0a:67:8e:\n" +        "         53:32:0e:99:9b:96:72:45:7f:c6:00:2c:5d:1a:97:53:75:3a:\n" +        "         0b:49:3d:3a:00:37:14:67:0c:28:97:34:87:aa:c5:32:e4:ae:\n" +        "         34:83:12:4a:10:f7:0e:74:d4:5f:73:bd:ef:0c:b7:d8:0a:7d:\n" +        "         8e:8d:5a:48:bd:f4:8e:7b:f9:4a:15:3b:61:c9:5e:40:59:6e:\n" +        "         c7:a8:a4:02:28:72:c5:54:8c:77:f4:55:a7:86:c0:38:a0:68:\n" +        "         19:da:0f:72:5a:a9:7e:69:9f:9c:3a:d6:66:aa:e1:f4:fd:f9:\n" +        "         b8:4b:6c:71:9e:f0:38:02:c7:6a:9e:dc:e6:fb:ef:23:59:4f:\n" +        "         5c:84:0a:df:ea:86:1f:fd:0e:5c:fa:c4:e5:50:1c:10:cf:89:\n" +        "         4e:08:0e:4c:4b:61:1a:49:12:f7:e9:4b:17:71:43:7b:6d:b6:\n" +        "         b5:9f:d4:3b:c7:88:53:48:63:b6:00:80:8f:49:0a:c5:7e:58:\n" +        "         ac:78:d8:b9:06:b0:bc:86:e2:2e:48:5b:c3:24:fa:aa:72:d8:\n" +        "         ec:f6:c7:91:9f:0f:c8:b5:fd:2b:b2:a7:bc:2f:40:20:2b:47:\n" +        "         e0:d1:1d:94:52:6f:6b:be:12:b6:8c:dc:11:db:71:e6:19:ef:\n" +        "         a8:71:8b:ad:d3:32:c0:1c:a4:3f:b3:0f:af:e5:50:e1:ff:41:\n" +        "         a4:b7:6f:57:71:af:fd:16:4c:e8:24:b3:99:1b:cf:12:8f:43:\n" +        "         05:80:ba:18:19:0a:a5:ec:49:81:41:4c:7e:28:b2:21:f2:59:\n" +        "         6e:4a:ed:de:f9:fa:99:85:60:1f:e6:c2:42:5c:08:00:3c:84:\n" +        "         06:a9:24:d4:cf:7b:6e:1b:59:1d:f4:70:16:03:a1:e0:0b:00:\n" +        "         95:5c:39:03:fc:9d:1c:8e:f7:59:0c:61:47:f6:7f:07:22:48:\n" +        "         83:40:ac:e1:98:5f:c7:be:05:d5:29:2b:bf:0d:03:0e:e9:5e:\n" +        "         2b:dd:09:18:fe:5e:30:61\n"          "-----BEGIN CERTIFICATE-----\n"          "MIIGbjCCBFagAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwgaoxCzAJBgNVBAYTAlVT\n"          "MRMwEQYDVQQIDApDYWxpZm9ybmlhMRMwEQYDVQQKDApMaW5kZW4gTGFiMSAwHgYD\n"          "VQQLDBdTZWNvbmQgTGlmZSBFbmdpbmVlcmluZzEpMCcGA1UEAwwgSW50ZWdyYXRp\n"          "b24gVGVzdCBJbnRlcm1lZGlhdGUgQ0ExJDAiBgkqhkiG9w0BCQEWFW5vcmVwbHlA\n" -        "bGluZGVubGFiLmNvbTAeFw0xNzA0MTAyMTM1MDdaFw0xODA0MjAyMTM1MDdaMIG+\n" +        "bGluZGVubGFiLmNvbTAeFw0xODA1MjIyMjU4MTVaFw0yNDA3MTkyMjU4MTVaMIG+\n"          "MQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNU2Fu\n"          "IEZyYW5jaXNjbzETMBEGA1UECgwKTGluZGVuIExhYjEgMB4GA1UECwwXU2Vjb25k\n"          "IExpZmUgRW5naW5lZXJpbmcxJTAjBgNVBAMMHEludGVncmF0aW9uIFRlc3QgU2Vy\n"          "dmVyIENlcnQxJDAiBgkqhkiG9w0BCQEWFW5vcmVwbHlAbGluZGVubGFiLmNvbTCC\n" -        "ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALpR+wFXRC+ZAzaCwGrSFx35\n" -        "4UlxsdFhxJBhQJmqjniZQMi39b14pXrI+3MzdMB47i1VCHhs5OCHSjTfaiX3jIaH\n" -        "DvbfAKdCT4njscDbKp2WK29HZgSb6PAYzntLv4tuJH7fiQe09WkdTp2dwWsZUWBW\n" -        "Pkq4wsCdZ/v+13P6YTiFm7BfgNuhV16fkK99MzF9vXMLotUe/xClbfvHVeaggSH1\n" -        "1yPlnMHyKYqqg591n4T8ZUwps5gfpgULGqgNaC4gRy0GRt6SPesCo7KfZWZEfLDa\n" -        "VXf1Wp/AWLb/fTFBcsy9eh1YNqjyymrKawMprJStk/R6FFKzzmHhfmyPCK2pXTcC\n" +        "ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL+hHHaCShAdJQ4C4npkVMeU\n" +        "xcCY1TXzy8swujGcvUwvSk4kA0uHXMFc/tmJO8sBvOult3jcs1jleKcVNFAwqhY6\n" +        "spQXbR5/snAelkG7HeMigPrcAGr7ND5n58IhLxvTrwRJkeu7YOAmUnUoighbkVZO\n" +        "UVBAUXCvy4BmyFnp4kioYtAmZ4AKEhbR9hWeH/WSN/PJLwOeIvZgWnZFjAEsmVRy\n" +        "Gdu3cuZaafPpMWVdD8dcnBcpcRR/20fJHmWiQbAvFBfsSyXyQ4+0o403Ggc0sym7\n" +        "ikSOhAiiG3Z6y8I5L27j/NaRtR/OWJFXcDVuJalIDgfPTt0WQmXPikKzJ+b+auMC\n"          "AwEAAaOCAYYwggGCMAkGA1UdEwQCMAAwEQYJYIZIAYb4QgEBBAQDAgZAMDMGCWCG\n"          "SAGG+EIBDQQmFiRPcGVuU1NMIEdlbmVyYXRlZCBTZXJ2ZXIgQ2VydGlmaWNhdGUw\n" -        "HQYDVR0OBBYEFGtpqpGZyIwBcljTH/gpc5yY9z9fMIHoBgNVHSMEgeAwgd2AFMxX\n" -        "d3oWEK6UmaGfqy95QnTXvo5joYHApIG9MIG6MQswCQYDVQQGEwJVUzETMBEGA1UE\n" +        "HQYDVR0OBBYEFLtZn95rUadss21bi0L3sWV3F6TkMIHoBgNVHSMEgeAwgd2AFIMh\n" +        "3uzAeQNtHoPz5Zcp1VrAlkD6oYHApIG9MIG6MQswCQYDVQQGEwJVUzETMBEGA1UE\n"          "CAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNU2FuIEZyYW5jaXNjbzETMBEGA1UECgwK\n"          "TGluZGVuIExhYjEgMB4GA1UECwwXU2Vjb25kIExpZmUgRW5naW5lZXJpbmcxITAf\n"          "BgNVBAMMGEludGVncmF0aW9uIFRlc3QgUm9vdCBDQTEkMCIGCSqGSIb3DQEJARYV\n"          "bm9yZXBseUBsaW5kZW5sYWIuY29tggIQADAOBgNVHQ8BAf8EBAMCBaAwEwYDVR0l\n" -        "BAwwCgYIKwYBBQUHAwEwDQYJKoZIhvcNAQELBQADggIBAKw1GpZlKHztxeO571Ke\n" -        "ZrhjLt5zlzyR1QKjYp7GX/cY7X/4oWbSvBL9kLj7787+5CFeudHJZRNL0OXQmpvz\n" -        "1nm9m68lkwEyXBRIA8H3xhmA1Bv344JZDFANhZdk5U4vXsu23KBEZDK6V+5FJljC\n" -        "NnGokDo3SDN1eY5PsS1lbgSfNShAl/OAwci7uc2iqkKpmsarrEik6woXGaBEnYp/\n" -        "sSGhFKwPceDoKAdEiudwya8ZCI++LHmvYq+fjthKxQnVJxopwyrxuaLfC+QiIk4m\n" -        "Ea09OUzmU0nVZYzoaJiRUED//azvcRIoqLNf97MmLuv00NRoMe5KeLOFYDcbIS3p\n" -        "8mdaZBflMPwt7VmgBo2Q6romL9isaJjbQoc5ZWS2CJ9w3HSNrCbOjqfcHUHegnwA\n" -        "RtAjdLVaTJHkkhGkE/1QBYaJxP0RzhdEjzXqyE6MpeHtYjL/L/eS8/dc0ucn2P/3\n" -        "kn3cpsrZ4JKd2zSebsj08dDYMMKFh8X27QvUsaZ8wc1VQcDkzwZiMf1OsetFcVt8\n" -        "QgJM7nQnioER8TKJQMmFA7voc1VT8HPrR2hMNJodfctUUFnHgj5CXIFRegFxhqGw\n" -        "2uYJOinu6Z5YGdeBab08WgJJbzwDDkp5BlBAimARNWtW/DRGUmjK0zrBhbzkJVdw\n" -        "tKs22IsKa417t4h9EDNuvoPm\n" +        "BAwwCgYIKwYBBQUHAwEwDQYJKoZIhvcNAQELBQADggIBABimWFWb1K99iifTKDpM\n" +        "S0JO8DDW2ZURSBIKlkDZKyE5xdSN5RC8aHhpC58VSgvxq5lFDCBfJ9/nFC1KMPLC\n" +        "jTdzNhonVVoIX3GhXgWDsln+Al7XSjAVI1gEz0jMsHGInGtX8AQK06Bka+7zX+qs\n" +        "4Su5f3m4285ySHLbyFw4cjFV0P9rvXMjpzAYXe1HGApnjlMyDpmblnJFf8YALF0a\n" +        "l1N1OgtJPToANxRnDCiXNIeqxTLkrjSDEkoQ9w501F9zve8Mt9gKfY6NWki99I57\n" +        "+UoVO2HJXkBZbseopAIocsVUjHf0VaeGwDigaBnaD3JaqX5pn5w61maq4fT9+bhL\n" +        "bHGe8DgCx2qe3Ob77yNZT1yECt/qhh/9Dlz6xOVQHBDPiU4IDkxLYRpJEvfpSxdx\n" +        "Q3tttrWf1DvHiFNIY7YAgI9JCsV+WKx42LkGsLyG4i5IW8Mk+qpy2Oz2x5GfD8i1\n" +        "/Suyp7wvQCArR+DRHZRSb2u+EraM3BHbceYZ76hxi63TMsAcpD+zD6/lUOH/QaS3\n" +        "b1dxr/0WTOgks5kbzxKPQwWAuhgZCqXsSYFBTH4osiHyWW5K7d75+pmFYB/mwkJc\n" +        "CAA8hAapJNTPe24bWR30cBYDoeALAJVcOQP8nRyO91kMYUf2fwciSINArOGYX8e+\n" +        "BdUpK78NAw7pXivdCRj+XjBh\n"          "-----END CERTIFICATE-----\n"                                      ); @@ -704,8 +710,8 @@ namespace tut  			   (std::string)llsd_cert["subject_name_string"],                        "emailAddress=noreply@lindenlab.com,CN=Integration Test Server Cert,OU=Second Life Engineering,O=Linden Lab,L=San Francisco,ST=California,C=US");  		ensure_equals("serial number", (std::string)llsd_cert["serial_number"], "1000"); -		ensure_equals("valid from", (std::string)llsd_cert["valid_from"], "2017-04-10T21:35:07Z"); -		ensure_equals("valid to", (std::string)llsd_cert["valid_to"], "2018-04-20T21:35:07Z"); +		ensure_equals("valid from", (std::string)llsd_cert["valid_from"], "2018-05-22T22:58:15Z"); +		ensure_equals("valid to", (std::string)llsd_cert["valid_to"], "2024-07-19T22:58:15Z");  		LLSD expectedKeyUsage = LLSD::emptyArray();  		expectedKeyUsage.append(LLSD((std::string)"digitalSignature"));  		expectedKeyUsage.append(LLSD((std::string)"keyEncipherment")); @@ -1024,7 +1030,7 @@ namespace tut  		//validate find  		LLSD find_info = LLSD::emptyMap(); -		find_info["subjectKeyIdentifier"] = "6b:69:aa:91:99:c8:8c:01:72:58:d3:1f:f8:29:73:9c:98:f7:3f:5f"; +		find_info["subjectKeyIdentifier"] = "bb:59:9f:de:6b:51:a7:6c:b3:6d:5b:8b:42:f7:b1:65:77:17:a4:e4";  		LLBasicCertificateVector::iterator found_cert = test_vector->find(find_info);  		ensure("found some cert", found_cert != test_vector->end());          X509* found_x509 = (*found_cert).get()->getOpenSSLX509(); diff --git a/indra/newview/tests/llslurl_test.cpp b/indra/newview/tests/llslurl_test.cpp index 4694f657b6..d0f44dcda1 100644 --- a/indra/newview/tests/llslurl_test.cpp +++ b/indra/newview/tests/llslurl_test.cpp @@ -46,10 +46,10 @@ static const char * const TEST_FILENAME("llslurl_test.xml");  class LLTrans  {  public: -	static std::string getString(const std::string &xml_desc, const LLStringUtil::format_map_t& args); +	static std::string getString(const std::string &xml_desc, const LLStringUtil::format_map_t& args, bool def_string);  }; -std::string LLTrans::getString(const std::string &xml_desc, const LLStringUtil::format_map_t& args) +std::string LLTrans::getString(const std::string &xml_desc, const LLStringUtil::format_map_t& args, bool def_string)  {  	return std::string();  } diff --git a/indra/newview/tests/llversioninfo_test.cpp b/indra/newview/tests/llversioninfo_test.cpp index 2f7a4e9601..58f0469552 100644 --- a/indra/newview/tests/llversioninfo_test.cpp +++ b/indra/newview/tests/llversioninfo_test.cpp @@ -33,10 +33,8 @@  // LL_VIEWER_CHANNEL is a macro defined on the compiler command line. The  // macro expands to the string name of the channel, but without quotes. We -// need to turn it into a quoted string. This macro trick does that. -#define stringize_inner(x) #x -#define stringize_outer(x) stringize_inner(x) -#define ll_viewer_channel stringize_outer(LL_VIEWER_CHANNEL) +// need to turn it into a quoted string. LL_TO_STRING() does that. +#define ll_viewer_channel LL_TO_STRING(LL_VIEWER_CHANNEL)  namespace tut  { diff --git a/indra/newview/tests/llviewernetwork_test.cpp b/indra/newview/tests/llviewernetwork_test.cpp index e68da14fe9..2aedb2eb4f 100644 --- a/indra/newview/tests/llviewernetwork_test.cpp +++ b/indra/newview/tests/llviewernetwork_test.cpp @@ -45,10 +45,10 @@ static const char * const TEST_FILENAME("llviewernetwork_test.xml");  class LLTrans  {  public: -	static std::string getString(const std::string &xml_desc, const LLStringUtil::format_map_t& args); +	static std::string getString(const std::string &xml_desc, const LLStringUtil::format_map_t& args, bool def_string=false);  }; -std::string LLTrans::getString(const std::string &xml_desc, const LLStringUtil::format_map_t& args) +std::string LLTrans::getString(const std::string &xml_desc, const LLStringUtil::format_map_t& args, bool def_string)  {  	std::string grid_label = std::string();  	if(xml_desc == "AgniGridLabel") diff --git a/indra/newview/tests/llworldmap_test.cpp b/indra/newview/tests/llworldmap_test.cpp index 84194adb5d..f1dd8acccf 100644 --- a/indra/newview/tests/llworldmap_test.cpp +++ b/indra/newview/tests/llworldmap_test.cpp @@ -66,7 +66,7 @@ void LLWorldMipmap::equalizeBoostLevels() { }  LLPointer<LLViewerFetchedTexture> LLWorldMipmap::getObjectsTile(U32 grid_x, U32 grid_y, S32 level, bool load) { return NULL; }  // Stub other stuff -std::string LLTrans::getString(const std::string &, const LLStringUtil::format_map_t& ) { return std::string("test_trans"); } +std::string LLTrans::getString(const std::string &, const LLStringUtil::format_map_t&, bool def_string) { return std::string("test_trans"); }  void LLUIString::updateResult() const { }  void LLUIString::setArg(const std::string& , const std::string& ) { }  void LLUIString::assign(const std::string& ) { } diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index 541112a765..49dc732457 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -26,19 +26,20 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA  Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA  $/LicenseInfo$  """ -import sys -import os -import os.path -import shutil  import errno  import json +import os +import os.path  import plistlib  import random  import re +import shutil  import stat  import subprocess +import sys  import tarfile  import time +import zipfile  viewer_dir = os.path.dirname(__file__)  # Add indra/lib/python to our path so we don't have to muck with PYTHONPATH. @@ -186,6 +187,11 @@ class ViewerManifest(LLManifest):                              "Address Size":self.address_size,                              "Update Service":"https://update.secondlife.com/update",                              } +            try: +                build_data_dict["BugSplat DB"] = os.environ["BUGSPLAT_DB"] +            except KeyError: +                # skip the assignment if there's no BUGSPLAT_DB variable +                pass              build_data_dict = self.finish_build_data_dict(build_data_dict)              with open(os.path.join(os.pardir,'build_data.json'), 'w') as build_data_handle:                  json.dump(build_data_dict,build_data_handle) @@ -580,6 +586,16 @@ class WindowsManifest(ViewerManifest):              # Hunspell              self.path("libhunspell.dll") +            # BugSplat +            if(self.address_size == 64): +                self.path("BsSndRpt64.exe") +                self.path("BugSplat64.dll") +                self.path("BugSplatRc64.dll") +            else: +                self.path("BsSndRpt.exe") +                self.path("BugSplat.dll") +                self.path("BugSplatRc.dll") +              # For google-perftools tcmalloc allocator.              try:                  if self.args['configuration'].lower() == 'debug': @@ -589,7 +605,6 @@ class WindowsManifest(ViewerManifest):              except:                  print "Skipping libtcmalloc_minimal.dll" -          self.path(src="licenses-win32.txt", dst="licenses.txt")          self.path("featuretable.txt") @@ -597,106 +612,107 @@ class WindowsManifest(ViewerManifest):              self.path("ca-bundle.crt")          # Media plugins - CEF -        with self.prefix(src='../media_plugins/cef/%s' % self.args['configuration'], dst="llplugin"): -            self.path("media_plugin_cef.dll") - -        # Media plugins - LibVLC -        with self.prefix(src='../media_plugins/libvlc/%s' % self.args['configuration'], dst="llplugin"): -            self.path("media_plugin_libvlc.dll") - -        # Media plugins - Example (useful for debugging - not shipped with release viewer) -        if self.channel_type() != 'release': -            with self.prefix(src='../media_plugins/example/%s' % self.args['configuration'], dst="llplugin"): -                self.path("media_plugin_example.dll") - -        # CEF runtime files - debug -        # CEF runtime files - not debug (release, relwithdebinfo etc.) -        config = 'debug' if self.args['configuration'].lower() == 'debug' else 'release' -        with self.prefix(src=os.path.join(pkgdir, 'bin', config), dst="llplugin"): -            self.path("chrome_elf.dll") -            self.path("d3dcompiler_43.dll") -            self.path("d3dcompiler_47.dll") -            self.path("libcef.dll") -            self.path("libEGL.dll") -            self.path("libGLESv2.dll") -            self.path("dullahan_host.exe") -            self.path("natives_blob.bin") -            self.path("snapshot_blob.bin") -            self.path("widevinecdmadapter.dll") - -        # MSVC DLLs needed for CEF and have to be in same directory as plugin -        with self.prefix(src=os.path.join(os.pardir, 'sharedlibs', 'Release'), dst="llplugin"): -            self.path("msvcp120.dll") -            self.path("msvcr120.dll") - -        # CEF files common to all configurations -        with self.prefix(src=os.path.join(pkgdir, 'resources'), dst="llplugin"): -            self.path("cef.pak") -            self.path("cef_100_percent.pak") -            self.path("cef_200_percent.pak") -            self.path("cef_extensions.pak") -            self.path("devtools_resources.pak") -            self.path("icudtl.dat") - -        with self.prefix(src=os.path.join(pkgdir, 'resources', 'locales'), dst=os.path.join('llplugin', 'locales')): -            self.path("am.pak") -            self.path("ar.pak") -            self.path("bg.pak") -            self.path("bn.pak") -            self.path("ca.pak") -            self.path("cs.pak") -            self.path("da.pak") -            self.path("de.pak") -            self.path("el.pak") -            self.path("en-GB.pak") -            self.path("en-US.pak") -            self.path("es-419.pak") -            self.path("es.pak") -            self.path("et.pak") -            self.path("fa.pak") -            self.path("fi.pak") -            self.path("fil.pak") -            self.path("fr.pak") -            self.path("gu.pak") -            self.path("he.pak") -            self.path("hi.pak") -            self.path("hr.pak") -            self.path("hu.pak") -            self.path("id.pak") -            self.path("it.pak") -            self.path("ja.pak") -            self.path("kn.pak") -            self.path("ko.pak") -            self.path("lt.pak") -            self.path("lv.pak") -            self.path("ml.pak") -            self.path("mr.pak") -            self.path("ms.pak") -            self.path("nb.pak") -            self.path("nl.pak") -            self.path("pl.pak") -            self.path("pt-BR.pak") -            self.path("pt-PT.pak") -            self.path("ro.pak") -            self.path("ru.pak") -            self.path("sk.pak") -            self.path("sl.pak") -            self.path("sr.pak") -            self.path("sv.pak") -            self.path("sw.pak") -            self.path("ta.pak") -            self.path("te.pak") -            self.path("th.pak") -            self.path("tr.pak") -            self.path("uk.pak") -            self.path("vi.pak") -            self.path("zh-CN.pak") -            self.path("zh-TW.pak") - -        with self.prefix(src=os.path.join(pkgdir, 'bin', 'release'), dst="llplugin"): -            self.path("libvlc.dll") -            self.path("libvlccore.dll") -            self.path("plugins/") +        with self.prefix(dst="llplugin"): +            with self.prefix(src='../media_plugins/cef/%s' % self.args['configuration']): +                self.path("media_plugin_cef.dll") + +            # Media plugins - LibVLC +            with self.prefix(src='../media_plugins/libvlc/%s' % self.args['configuration']): +                self.path("media_plugin_libvlc.dll") + +            # Media plugins - Example (useful for debugging - not shipped with release viewer) +            if self.channel_type() != 'release': +                with self.prefix(src='../media_plugins/example/%s' % self.args['configuration']): +                    self.path("media_plugin_example.dll") + +            # CEF runtime files - debug +            # CEF runtime files - not debug (release, relwithdebinfo etc.) +            config = 'debug' if self.args['configuration'].lower() == 'debug' else 'release' +            with self.prefix(src=os.path.join(pkgdir, 'bin', config)): +                self.path("chrome_elf.dll") +                self.path("d3dcompiler_43.dll") +                self.path("d3dcompiler_47.dll") +                self.path("libcef.dll") +                self.path("libEGL.dll") +                self.path("libGLESv2.dll") +                self.path("dullahan_host.exe") +                self.path("natives_blob.bin") +                self.path("snapshot_blob.bin") +                self.path("widevinecdmadapter.dll") + +            # MSVC DLLs needed for CEF and have to be in same directory as plugin +            with self.prefix(src=os.path.join(os.pardir, 'sharedlibs', 'Release')): +                self.path("msvcp120.dll") +                self.path("msvcr120.dll") + +            # CEF files common to all configurations +            with self.prefix(src=os.path.join(pkgdir, 'resources')): +                self.path("cef.pak") +                self.path("cef_100_percent.pak") +                self.path("cef_200_percent.pak") +                self.path("cef_extensions.pak") +                self.path("devtools_resources.pak") +                self.path("icudtl.dat") + +            with self.prefix(src=os.path.join(pkgdir, 'resources', 'locales'), dst='locales'): +                self.path("am.pak") +                self.path("ar.pak") +                self.path("bg.pak") +                self.path("bn.pak") +                self.path("ca.pak") +                self.path("cs.pak") +                self.path("da.pak") +                self.path("de.pak") +                self.path("el.pak") +                self.path("en-GB.pak") +                self.path("en-US.pak") +                self.path("es-419.pak") +                self.path("es.pak") +                self.path("et.pak") +                self.path("fa.pak") +                self.path("fi.pak") +                self.path("fil.pak") +                self.path("fr.pak") +                self.path("gu.pak") +                self.path("he.pak") +                self.path("hi.pak") +                self.path("hr.pak") +                self.path("hu.pak") +                self.path("id.pak") +                self.path("it.pak") +                self.path("ja.pak") +                self.path("kn.pak") +                self.path("ko.pak") +                self.path("lt.pak") +                self.path("lv.pak") +                self.path("ml.pak") +                self.path("mr.pak") +                self.path("ms.pak") +                self.path("nb.pak") +                self.path("nl.pak") +                self.path("pl.pak") +                self.path("pt-BR.pak") +                self.path("pt-PT.pak") +                self.path("ro.pak") +                self.path("ru.pak") +                self.path("sk.pak") +                self.path("sl.pak") +                self.path("sr.pak") +                self.path("sv.pak") +                self.path("sw.pak") +                self.path("ta.pak") +                self.path("te.pak") +                self.path("th.pak") +                self.path("tr.pak") +                self.path("uk.pak") +                self.path("vi.pak") +                self.path("zh-CN.pak") +                self.path("zh-TW.pak") + +            with self.prefix(src=os.path.join(pkgdir, 'bin', 'release')): +                self.path("libvlc.dll") +                self.path("libvlccore.dll") +                self.path("plugins/")          # pull in the crash logger and updater from other projects          # tag:"crash-logger" here as a cue to the exporter @@ -888,6 +904,9 @@ class DarwinManifest(ViewerManifest):          launcher_app, launcher_icon = "Second Life Launcher.app", "secondlife.icns"          viewer_app,   viewer_icon   = "Second Life Viewer.app",   "secondlife.icns" +        # capture the path to the directory containing toplevel_app +        parentdir = os.path.join(self.get_dst_prefix(), os.pardir) +          # copy over the build result (this is a no-op if run within the xcode script)          self.path(os.path.join(self.args['configuration'], toplevel_app), dst="") @@ -899,10 +918,7 @@ class DarwinManifest(ViewerManifest):          # top-level Second Life application is only a container          with self.prefix(src="", dst="Contents"):  # everything goes in Contents              # top-level Info.plist is as generated by CMake -            Info_plist = "Info.plist" -            ## This self.path() call reports 0 files... skip? -            self.path(Info_plist) -            Info_plist = self.dst_path_of(Info_plist) +            Info_plist = self.dst_path_of("Info.plist")              # the one file in top-level MacOS directory is the trampoline to              # our nested launcher_app @@ -984,25 +1000,7 @@ open "%s" --args "$@"                  # -------------------- nested viewer_app ---------------------                  with self.prefix(dst=os.path.join(viewer_app, "Contents")): -                    # Info.plist is just like top-level one... -                    Info = plistlib.readPlist(Info_plist) -                    # except for these replacements: -                    # (CFBundleExecutable may be moot: SL_Launcher directly -                    # runs the executable, instead of launching the app) -                    Info["CFBundleExecutable"] = "Second Life" -                    Info["CFBundleIconFile"] = viewer_icon -                    self.put_in_file( -                        plistlib.writePlistToString(Info), -                        os.path.basename(Info_plist), -                        "Info.plist") - -                    # CEF framework goes inside viewer_app/Contents/Frameworks. -                    # Remember where we parked this car. -                    with self.prefix(src="", dst="Frameworks"): -                        CEF_framework = "Chromium Embedded Framework.framework" -                        self.path2basename(relpkgdir, CEF_framework) -                        CEF_framework = self.dst_path_of(CEF_framework) - +                    # defer Info.plist until after MacOS                      with self.prefix(dst="MacOS"):                          # CMake constructs the Second Life executable in the                          # MacOS directory belonging to the top-level Second @@ -1015,23 +1013,94 @@ open "%s" --args "$@"                                  # don't move the trampoline script we just made!                                  continue                              fromwhere = os.path.join(toplevel_MacOS, f) -                            towhere   = os.path.join(here, f) +                            towhere   = self.dst_path_of(f)                              print "Moving %s => %s" % \                                    (self.relpath(fromwhere, relbase),                                     self.relpath(towhere, relbase))                              # now do it, only without relativizing paths                              os.rename(fromwhere, towhere) -                        # NOTE: the -S argument to strip causes it to keep -                        # enough info for annotated backtraces (i.e. function -                        # names in the crash log). 'strip' with no arguments -                        # yields a slightly smaller binary but makes crash -                        # logs mostly useless. This may be desirable for the -                        # final release. Or not. +                        # Pick the biggest of the executables as the real viewer. +                        # Make (basename, fullpath) pairs; for each pair, +                        # expand to (size, basename, fullpath) triples; sort +                        # by size; pick the last triple; take the basename and +                        # fullpath from that. +                        _, exename, exepath = \ +                            sorted((os.path.getsize(path), name, path) +                                   for name, path in +                                   ((name, os.path.join(here, name)) +                                    for name in os.listdir(here)))[-1] +                          if ("package" in self.args['actions'] or                               "unpacked" in self.args['actions']): -                            self.run_command( -                                ['strip', '-S', self.dst_path_of('Second Life')]) +                            # only if we're engaging BugSplat +                            if "BUGSPLAT_DB" in os.environ: +                                # Create a symbol archive BEFORE stripping the +                                # binary. +                                self.run_command(['dsymutil', exepath]) +                                # This should produce a Second Life.dSYM bundle directory. +                                try: +                                    # Now pretend we're Xcode making a .xcarchive file. +                                    # Put it as a sibling of the top-level .app. +                                    # From "Dave" at BugSplat support: +                                    # "More from our Mac lead: I think zipping +                                    # a folder containing the binary and +                                    # symbols would be sufficient. Assuming +                                    # symbol files are created with CMake. I'm +                                    # not sure if CMake strips symbols into +                                    # separate files at build time, and if so +                                    # they're in a supported format." +                                    xcarchive = os.path.join(parentdir, +                                                             exename + '.xcarchive.zip') +                                    with zipfile.ZipFile(xcarchive, 'w', +                                                         compression=zipfile.ZIP_DEFLATED) as zf: +                                        print "Creating {}".format(xcarchive) +                                        for base, dirs, files in os.walk(here): +                                            for fn in files: +                                                fullfn = os.path.join(base, fn) +                                                relfn = os.path.relpath(fullfn, here) +                                                print "  {}".format(relfn) +                                                zf.write(fullfn, relfn) +                                finally: +                                    # Whether or not we were able to create the +                                    # .xcarchive file, clean up the .dSYM bundle +                                    shutil.rmtree(self.dst_path_of(exename + '.dSYM')) + +                            # NOTE: the -S argument to strip causes it to keep +                            # enough info for annotated backtraces (i.e. function +                            # names in the crash log). 'strip' with no arguments +                            # yields a slightly smaller binary but makes crash +                            # logs mostly useless. This may be desirable for the +                            # final release. Or not. +                            self.run_command(['strip', '-S', exepath]) + +                    # Info.plist is just like top-level one... +                    Info = plistlib.readPlist(Info_plist) +                    # except for these replacements: +                    # (CFBundleExecutable may be moot: SL_Launcher directly +                    # runs the executable, instead of launching the app) +                    Info["CFBundleExecutable"] = exename +                    Info["CFBundleIconFile"] = viewer_icon +                    try: +                        # https://www.bugsplat.com/docs/platforms/os-x#configuration +                        Info["BugsplatServerURL"] = \ +                            "https://{BUGSPLAT_DB}.bugsplatsoftware.com/".format(**os.environ) +                    except KeyError: +                        # skip the assignment if there's no BUGSPLAT_DB variable +                        pass +                    self.put_in_file( +                        plistlib.writePlistToString(Info), +                        os.path.basename(Info_plist), +                        "Info.plist") + +                    with self.prefix(src="", dst="Frameworks"): +                        # CEF framework goes inside viewer_app/Contents/Frameworks. +                        CEF_framework = "Chromium Embedded Framework.framework" +                        self.path2basename(relpkgdir, CEF_framework) +                        # Remember where we parked this car. +                        CEF_framework = self.dst_path_of(CEF_framework) + +                        self.path2basename(relpkgdir, "BugsplatMac.framework")                      with self.prefix(dst="Resources"):                          # defer cross-platform file copies until we're in the right | 
