diff options
Diffstat (limited to 'indra')
668 files changed, 20265 insertions, 6902 deletions
diff --git a/indra/CMakeLists.txt b/indra/CMakeLists.txt index 422927704a..e7e41fd316 100644 --- a/indra/CMakeLists.txt +++ b/indra/CMakeLists.txt @@ -24,6 +24,10 @@ if( USE_CONAN ) set( USE_AUTOBUILD_3P OFF ) conan_basic_setup(TARGETS NO_OUTPUT_DIRS) add_compile_definitions(LL_USESYSTEMLIBS USE_CONAN NO_AUTOBUILD_3P) +elseif( USESYSTEMLIBS ) + set( USE_CONAN OFF ) + set( USE_AUTOBUILD_3P OFF ) + add_compile_definitions(LL_USESYSTEMLIBS) else() set( USE_CONAN OFF ) set( USE_AUTOBUILD_3P ON ) @@ -54,7 +58,9 @@ add_subdirectory(${LIBS_OPEN_PREFIX}llmessage) add_subdirectory(${LIBS_OPEN_PREFIX}llprimitive) add_subdirectory(${LIBS_OPEN_PREFIX}llrender) add_subdirectory(${LIBS_OPEN_PREFIX}llfilesystem) +if (NOT CMAKE_SYSTEM_NAME MATCHES FreeBSD) add_subdirectory(${LIBS_OPEN_PREFIX}llwebrtc) +endif () add_subdirectory(${LIBS_OPEN_PREFIX}llwindow) add_subdirectory(${LIBS_OPEN_PREFIX}llxml) @@ -112,7 +118,7 @@ else (USE_BUGSPLAT) endif (USE_BUGSPLAT) add_subdirectory(${VIEWER_PREFIX}newview) -add_dependencies(viewer secondlife-bin) +add_dependencies(viewer ${VIEWER_BINARY_NAME}) add_subdirectory(${VIEWER_PREFIX}doxygen EXCLUDE_FROM_ALL) diff --git a/indra/cmake/00-Common.cmake b/indra/cmake/00-Common.cmake index 07deaa56b0..afe20a6dd3 100644 --- a/indra/cmake/00-Common.cmake +++ b/indra/cmake/00-Common.cmake @@ -15,6 +15,7 @@ include_guard() include(Variables) +include(Linker) # We go to some trouble to set LL_BUILD to the set of relevant compiler flags. set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} $ENV{LL_BUILD}") @@ -113,50 +114,96 @@ if (WINDOWS) add_compile_definitions(_CRT_SECURE_NO_WARNINGS) endif (WINDOWS) +if (LINUX OR CMAKE_SYSTEM_NAME MATCHES "FreeBSD") + set( CMAKE_BUILD_WITH_INSTALL_RPATH TRUE ) + set( CMAKE_INSTALL_RPATH $ORIGIN $ORIGIN/../lib ) + set(CMAKE_EXE_LINKER_FLAGS "-Wl,--exclude-libs,ALL") -if (LINUX) - set(CMAKE_SKIP_RPATH TRUE) - - # EXTERNAL_TOS - # force this platform to accept TOS via external browser + find_program(CCACHE_EXE ccache) + if(CCACHE_EXE AND NOT DISABLE_CCACHE) + set(CMAKE_C_COMPILER_LAUNCHER ${CCACHE_EXE} ) + set(CMAKE_CXX_COMPILER_LAUNCHER ${CCACHE_EXE} ) + endif() - # LL_IGNORE_SIGCHLD - # don't catch SIGCHLD in our base application class for the viewer - some of - # our 3rd party libs may need their *own* SIGCHLD handler to work. Sigh! The - # viewer doesn't need to catch SIGCHLD anyway. + # LL_IGNORE_SIGCHLD + # don't catch SIGCHLD in our base application class for the viewer - some of + # our 3rd party libs may need their *own* SIGCHLD handler to work. Sigh! The + # viewer doesn't need to catch SIGCHLD anyway. add_compile_definitions( _REENTRANT - _FORTIFY_SOURCE=2 - EXTERNAL_TOS - APPID=secondlife + APPID=megapahit LL_IGNORE_SIGCHLD ) + + if( ENABLE_ASAN ) + add_compile_options(-U_FORTIFY_SOURCE + -fsanitize=address + --param asan-stack=0 + ) + add_link_options(-fsanitize=address) + else() + add_compile_definitions( _FORTIFY_SOURCE=2 ) + endif() + + if (CMAKE_SYSTEM_NAME MATCHES "FreeBSD") + add_compile_definitions(EXTERNAL_TOS) + endif (CMAKE_SYSTEM_NAME MATCHES "FreeBSD") + add_compile_options( - -fexceptions - -fno-math-errno - -fno-strict-aliasing - -fsigned-char - -msse2 - -mfpmath=sse - -pthread - -Wno-parentheses - -Wno-deprecated - -fvisibility=hidden + -fexceptions + -fno-math-errno + -fno-strict-aliasing + -fsigned-char + -msse2 + -mfpmath=sse + -pthread ) - if (ADDRESS_SIZE EQUAL 32) - add_compile_options(-march=pentium4) - endif (ADDRESS_SIZE EQUAL 32) + if (NOT BUILD_SHARED_LIBS) + add_compile_options(-fvisibility=hidden) + endif (NOT BUILD_SHARED_LIBS) + + set(GCC_CLANG_COMPATIBLE_WARNINGS + -Wno-parentheses + -Wno-deprecated + -Wno-c++20-compat + -Wno-pessimizing-move + ) + + set(CLANG_WARNINGS + ${GCC_CLANG_COMPATIBLE_WARNINGS} + # Put clang specific warning configuration here + ) + + set(GCC_WARNINGS + ${GCC_CLANG_COMPATIBLE_WARNINGS} + -Wno-dangling-pointer + ) + + add_link_options( + -Wl,--no-keep-memory + -Wl,--build-id + -Wl,--no-undefined + ) + if (NOT GCC_DISABLE_FATAL_WARNINGS) + add_compile_options( -Werror ) + endif (NOT GCC_DISABLE_FATAL_WARNINGS) # this stops us requiring a really recent glibc at runtime add_compile_options(-fno-stack-protector) - # linking can be very memory-hungry, especially the final viewer link - set(CMAKE_CXX_LINK_FLAGS "-Wl,--no-keep-memory") - - set(CMAKE_CXX_FLAGS_DEBUG "-fno-inline ${CMAKE_CXX_FLAGS_DEBUG}") -endif (LINUX) + if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang") + # ND: clang is a bit more picky than GCC, the latter seems to auto include -lstdc++ and -lm. The former not so and thus fails to link + add_link_options( + -lstdc++ + -lm + ) + add_compile_options(${CLANG_WARNINGS}) + else() + add_compile_options(${GCC_WARNINGS}) + endif() +endif (LINUX OR CMAKE_SYSTEM_NAME MATCHES "FreeBSD") if (DARWIN) # Warnings should be fatal -- thanks, Nicky Perian, for spotting reversed default @@ -179,15 +226,9 @@ if (DARWIN) # required for clang-15/xcode-15 since our boost package still uses deprecated std::unary_function/binary_function # see https://developer.apple.com/documentation/xcode-release-notes/xcode-15-release-notes#C++-Standard-Library add_compile_definitions(_LIBCPP_ENABLE_CXX17_REMOVED_UNARY_BINARY_FUNCTION) -endif (DARWIN) -if (LINUX OR DARWIN) set(GCC_WARNINGS -Wall -Wno-sign-compare -Wno-trigraphs) - if (NOT GCC_DISABLE_FATAL_WARNINGS) - list(APPEND GCC_WARNINGS -Werror) - endif (NOT GCC_DISABLE_FATAL_WARNINGS) - list(APPEND GCC_WARNINGS -Wno-reorder -Wno-non-virtual-dtor ) if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 13) @@ -196,7 +237,4 @@ if (LINUX OR DARWIN) add_compile_options(${GCC_WARNINGS}) add_compile_options(-m${ADDRESS_SIZE}) -endif (LINUX OR DARWIN) - - - +endif () diff --git a/indra/cmake/APR.cmake b/indra/cmake/APR.cmake index 21139319c3..72486f110d 100644 --- a/indra/cmake/APR.cmake +++ b/indra/cmake/APR.cmake @@ -5,6 +5,15 @@ include_guard() add_library( ll::apr INTERFACE IMPORTED ) +if (NOT (USE_AUTOBUILD_3P OR USE_CONAN)) + include(FindPkgConfig) + pkg_check_modules(Apr REQUIRED apr-1 apr-util-1) + target_include_directories(ll::apr SYSTEM INTERFACE ${Apr_INCLUDE_DIRS}) + target_link_directories(ll::apr INTERFACE ${Apr_LIBRARY_DIRS}) + target_link_libraries(ll::apr INTERFACE ${Apr_LIBRARIES}) + return () +endif () + use_system_binary( apr apr-util ) use_prebuilt_binary(apr_suite) diff --git a/indra/cmake/Audio.cmake b/indra/cmake/Audio.cmake index 38547bb017..4388e1e259 100644 --- a/indra/cmake/Audio.cmake +++ b/indra/cmake/Audio.cmake @@ -4,6 +4,15 @@ include(Prebuilt) include_guard() add_library( ll::vorbis INTERFACE IMPORTED ) +if (NOT (USE_AUTOBUILD_3P OR USE_CONAN)) + include(FindPkgConfig) + pkg_check_modules(Vorbis REQUIRED ogg vorbis vorbisenc vorbisfile) + target_include_directories(ll::vorbis SYSTEM INTERFACE ${Vorbis_INCLUDE_DIRS}) + target_link_directories(ll::vorbis INTERFACE ${Vorbis_LIBRARY_DIRS}) + target_link_libraries(ll::vorbis INTERFACE ${Vorbis_LIBRARIES}) + return () +endif () + use_system_binary(vorbis) use_prebuilt_binary(ogg_vorbis) target_include_directories( ll::vorbis SYSTEM INTERFACE ${LIBS_PREBUILT_DIR}/include ) @@ -11,6 +20,6 @@ target_include_directories( ll::vorbis SYSTEM INTERFACE ${LIBS_PREBUILT_DIR}/inc if (WINDOWS) target_link_libraries(ll::vorbis INTERFACE ogg_static vorbis_static vorbisenc_static vorbisfile_static ) else (WINDOWS) - target_link_libraries(ll::vorbis INTERFACE ogg vorbis vorbisenc vorbisfile ) + target_link_libraries(ll::vorbis INTERFACE vorbisfile vorbis ogg vorbisenc ) endif (WINDOWS) diff --git a/indra/cmake/Boost.cmake b/indra/cmake/Boost.cmake index 601a23a86d..a4f81917ea 100644 --- a/indra/cmake/Boost.cmake +++ b/indra/cmake/Boost.cmake @@ -8,6 +8,32 @@ if( USE_CONAN ) target_link_libraries( ll::boost INTERFACE CONAN_PKG::boost ) target_compile_definitions( ll::boost INTERFACE BOOST_ALLOW_DEPRECATED_HEADERS BOOST_BIND_GLOBAL_PLACEHOLDERS ) return() +elseif( NOT USE_AUTOBUILD_3P ) + if (DARWIN) + target_include_directories( ll::boost SYSTEM INTERFACE /opt/local/libexec/boost/1.81/include) + target_link_libraries( ll::boost INTERFACE + /opt/local/libexec/boost/1.81/lib/libboost_context-mt.a + /opt/local/libexec/boost/1.81/lib/libboost_fiber-mt.a + /opt/local/libexec/boost/1.81/lib/libboost_filesystem-mt.a + /opt/local/libexec/boost/1.81/lib/libboost_program_options-mt.a + /opt/local/libexec/boost/1.81/lib/libboost_regex-mt.a + /opt/local/libexec/boost/1.81/lib/libboost_system-mt.a + /opt/local/libexec/boost/1.81/lib/libboost_thread-mt.a + ) + else (DARWIN) + find_package( Boost REQUIRED ) + target_link_libraries( ll::boost INTERFACE + boost_context + boost_fiber + boost_filesystem + boost_program_options + boost_regex + boost_system + boost_thread + ) + endif (DARWIN) + target_compile_definitions( ll::boost INTERFACE BOOST_BIND_GLOBAL_PLACEHOLDERS ) + return() endif() use_prebuilt_binary(boost) @@ -27,14 +53,14 @@ if (WINDOWS) libboost_thread-mt${addrsfx}) elseif (LINUX) target_link_libraries( ll::boost INTERFACE - boost_context-mt${addrsfx} boost_fiber-mt${addrsfx} + boost_context-mt${addrsfx} boost_filesystem-mt${addrsfx} boost_program_options-mt${addrsfx} boost_regex-mt${addrsfx} - boost_signals-mt${addrsfx} + boost_thread-mt${addrsfx} boost_system-mt${addrsfx} - boost_thread-mt${addrsfx}) + ) elseif (DARWIN) target_link_libraries( ll::boost INTERFACE boost_context-mt${addrsfx} diff --git a/indra/cmake/CEFPlugin.cmake b/indra/cmake/CEFPlugin.cmake index 9b77becf29..119a41f570 100644 --- a/indra/cmake/CEFPlugin.cmake +++ b/indra/cmake/CEFPlugin.cmake @@ -5,7 +5,46 @@ include(Prebuilt) include_guard() add_library( ll::cef INTERFACE IMPORTED ) +if (CMAKE_OSX_ARCHITECTURES MATCHES arm64) + if (${PREBUILD_TRACKING_DIR}/sentinel_installed IS_NEWER_THAN ${PREBUILD_TRACKING_DIR}/dullahan_installed OR NOT ${dullahan_installed} EQUAL 0) + if (NOT EXISTS ${CMAKE_BINARY_DIR}/dullahan-1.14.0.202312131437_118.7.1_g99817d2_chromium-118.0.5993.119-darwin64-242070244.tar.bz2) + file(DOWNLOAD + https://megapahit.net/downloads/dullahan-1.14.0.202312131437_118.7.1_g99817d2_chromium-118.0.5993.119-darwin64-242070244.tar.bz2 + ${CMAKE_BINARY_DIR}/dullahan-1.14.0.202312131437_118.7.1_g99817d2_chromium-118.0.5993.119-darwin64-242070244.tar.bz2 + SHOW_PROGRESS + ) + endif (NOT EXISTS ${CMAKE_BINARY_DIR}/dullahan-1.14.0.202312131437_118.7.1_g99817d2_chromium-118.0.5993.119-darwin64-242070244.tar.bz2) + file(ARCHIVE_EXTRACT + INPUT ${CMAKE_BINARY_DIR}/dullahan-1.14.0.202312131437_118.7.1_g99817d2_chromium-118.0.5993.119-darwin64-242070244.tar.bz2 + DESTINATION ${LIBS_PREBUILT_DIR} + ) + file(WRITE ${PREBUILD_TRACKING_DIR}/dullahan_installed "0") + endif (${PREBUILD_TRACKING_DIR}/sentinel_installed IS_NEWER_THAN ${PREBUILD_TRACKING_DIR}/dullahan_installed OR NOT ${dullahan_installed} EQUAL 0) +elseif (CMAKE_OSX_ARCHITECTURES MATCHES x86_64) + if (${PREBUILD_TRACKING_DIR}/sentinel_installed IS_NEWER_THAN ${PREBUILD_TRACKING_DIR}/dullahan_installed OR NOT ${dullahan_installed} EQUAL 0) + if (NOT EXISTS ${CMAKE_BINARY_DIR}/dullahan-1.14.0.202312131437_118.7.1_g99817d2_chromium-118.0.5993.119-darwin64-242070158.tar.bz2) + file(DOWNLOAD + https://megapahit.net/downloads/dullahan-1.14.0.202312131437_118.7.1_g99817d2_chromium-118.0.5993.119-darwin64-242070158.tar.bz2 + ${CMAKE_BINARY_DIR}/dullahan-1.14.0.202312131437_118.7.1_g99817d2_chromium-118.0.5993.119-darwin64-242070158.tar.bz2 + SHOW_PROGRESS + ) + endif (NOT EXISTS ${CMAKE_BINARY_DIR}/dullahan-1.14.0.202312131437_118.7.1_g99817d2_chromium-118.0.5993.119-darwin64-242070158.tar.bz2) + file(ARCHIVE_EXTRACT + INPUT ${CMAKE_BINARY_DIR}/dullahan-1.14.0.202312131437_118.7.1_g99817d2_chromium-118.0.5993.119-darwin64-242070158.tar.bz2 + DESTINATION ${LIBS_PREBUILT_DIR} + ) + file(WRITE ${PREBUILD_TRACKING_DIR}/dullahan_installed "0") + endif (${PREBUILD_TRACKING_DIR}/sentinel_installed IS_NEWER_THAN ${PREBUILD_TRACKING_DIR}/dullahan_installed OR NOT ${dullahan_installed} EQUAL 0) +else (CMAKE_OSX_ARCHITECTURES MATCHES arm64) use_prebuilt_binary(dullahan) + if (${LINUX_DISTRO} MATCHES fedora) + execute_process( + COMMAND patchelf --remove-rpath bin/release/dullahan_host + WORKING_DIRECTORY ${LIBS_PREBUILT_DIR} + ) + endif (${LINUX_DISTRO} MATCHES fedora) +endif (CMAKE_OSX_ARCHITECTURES MATCHES arm64) + target_include_directories( ll::cef SYSTEM INTERFACE ${LIBS_PREBUILT_DIR}/include/cef) if (WINDOWS) @@ -33,4 +72,9 @@ elseif (DARWIN) ) elseif (LINUX) + target_link_libraries( ll::cef INTERFACE + libdullahan.a + cef + cef_dll_wrapper.a + ) endif (WINDOWS) diff --git a/indra/cmake/CMakeLists.txt b/indra/cmake/CMakeLists.txt index 0f338931c0..fa6cd8556b 100644 --- a/indra/cmake/CMakeLists.txt +++ b/indra/cmake/CMakeLists.txt @@ -15,7 +15,6 @@ set(cmake_SOURCE_FILES CEFPlugin.cmake CEFPlugin.cmake CMakeCopyIfDifferent.cmake - ConfigurePkgConfig.cmake CURL.cmake Copy3rdPartyLibs.cmake DBusGlib.cmake @@ -23,6 +22,7 @@ set(cmake_SOURCE_FILES DragDrop.cmake EXPAT.cmake FindAutobuild.cmake + FMODSTUDIO.cmake FreeType.cmake GLEXT.cmake GLH.cmake diff --git a/indra/cmake/CURL.cmake b/indra/cmake/CURL.cmake index b9f685f37b..60b74d3727 100644 --- a/indra/cmake/CURL.cmake +++ b/indra/cmake/CURL.cmake @@ -4,8 +4,102 @@ include(Prebuilt) include_guard() add_library( ll::libcurl INTERFACE IMPORTED ) +if (NOT USESYSTEMLIBS) use_system_binary(libcurl) +endif (NOT USESYSTEMLIBS) +if (LINUX OR NOT USESYSTEMLIBS) use_prebuilt_binary(curl) +elseif (${PREBUILD_TRACKING_DIR}/sentinel_installed IS_NEWER_THAN ${PREBUILD_TRACKING_DIR}/curl_installed OR NOT ${curl_installed} EQUAL 0) + if (NOT EXISTS ${CMAKE_BINARY_DIR}/3p-curl-7.54.1-r1.tar.gz) + file(DOWNLOAD + https://github.com/secondlife/3p-curl/archive/refs/tags/v7.54.1-r1.tar.gz + ${CMAKE_BINARY_DIR}/3p-curl-7.54.1-r1.tar.gz + ) + endif (NOT EXISTS ${CMAKE_BINARY_DIR}/3p-curl-7.54.1-r1.tar.gz) + file(ARCHIVE_EXTRACT + INPUT ${CMAKE_BINARY_DIR}/3p-curl-7.54.1-r1.tar.gz + DESTINATION ${CMAKE_BINARY_DIR} + ) + file( + COPY + ${CMAKE_BINARY_DIR}/3p-curl-7.54.1-r1/curl/include/curl/curl.h + ${CMAKE_BINARY_DIR}/3p-curl-7.54.1-r1/curl/include/curl/curlbuild.h + ${CMAKE_BINARY_DIR}/3p-curl-7.54.1-r1/curl/include/curl/curlrules.h + ${CMAKE_BINARY_DIR}/3p-curl-7.54.1-r1/curl/include/curl/curlver.h + ${CMAKE_BINARY_DIR}/3p-curl-7.54.1-r1/curl/include/curl/easy.h + ${CMAKE_BINARY_DIR}/3p-curl-7.54.1-r1/curl/include/curl/mprintf.h + ${CMAKE_BINARY_DIR}/3p-curl-7.54.1-r1/curl/include/curl/multi.h + ${CMAKE_BINARY_DIR}/3p-curl-7.54.1-r1/curl/include/curl/stdcheaders.h + ${CMAKE_BINARY_DIR}/3p-curl-7.54.1-r1/curl/include/curl/system.h + ${CMAKE_BINARY_DIR}/3p-curl-7.54.1-r1/curl/include/curl/typecheck-gcc.h + DESTINATION ${LIBS_PREBUILT_DIR}/include/curl + ) + file( + COPY + ${LIBS_PREBUILT_DIR}/lib/release/libcrypto.a + ${LIBS_PREBUILT_DIR}/lib/release/libssl.a + DESTINATION ${LIBS_PREBUILT_DIR}/lib + ) + message("We need to temporarily have OpenSSL3 header directory and libraries renamed just until the libcurl building process with OpenSSL1.1 now is finished.") + if (DARWIN) + set(ENV{CFLAGS} "-arch ${CMAKE_OSX_ARCHITECTURES} -mmacosx-version-min=10.15 -std=c90") + execute_process(COMMAND sudo mv /opt/local/include/openssl /opt/local/include/openssl3) + execute_process(COMMAND sudo mv /opt/local/lib/libcrypto.a /opt/local/lib/libcrypto.a.3) + execute_process(COMMAND sudo mv /opt/local/lib/libcrypto.dylib /opt/local/lib/libcrypto.dylib.3) + execute_process(COMMAND sudo mv /opt/local/lib/libssl.a /opt/local/lib/libssl.a.3) + execute_process(COMMAND sudo mv /opt/local/lib/libssl.dylib /opt/local/lib/libssl.dylib.3) + if (CMAKE_OSX_ARCHITECTURES MATCHES arm64) + execute_process( + COMMAND ./configure --host=aarch64-apple-darwin --disable-alt-svc --disable-dict --disable-doh --disable-file --disable-gopher --disable-headers-api --disable-hsts --disable-imap --disable-ldap --disable-ldaps --disable-libcurl-option --disable-manual --disable-mqtt --disable-ntlm --disable-ntlm-wb --disable-pop3 --disable-rtsp --disable-shared --disable-smb --disable-smtp --disable-sspi --disable-telnet --disable-tftp --disable-tls-srp --disable-unix-sockets --disable-verbose --disable-versioned-symbols --enable-threaded-resolver --with-ssl=${LIBS_PREBUILT_DIR} --without-libidn2 --without-libpsl --without-libssh2 + WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/3p-curl-7.54.1-r1/curl + ) + else (CMAKE_OSX_ARCHITECTURES MATCHES arm64) + execute_process( + COMMAND ./configure --host=${CMAKE_OSX_ARCHITECTURES}-apple-darwin --disable-alt-svc --disable-dict --disable-doh --disable-file --disable-gopher --disable-headers-api --disable-hsts --disable-imap --disable-ldap --disable-ldaps --disable-libcurl-option --disable-manual --disable-mqtt --disable-ntlm --disable-ntlm-wb --disable-pop3 --disable-rtsp --disable-shared --disable-smb --disable-smtp --disable-sspi --disable-telnet --disable-tftp --disable-tls-srp --disable-unix-sockets --disable-verbose --disable-versioned-symbols --enable-threaded-resolver --with-ssl=${LIBS_PREBUILT_DIR} --without-libidn2 --without-libpsl --without-libssh2 + WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/3p-curl-7.54.1-r1/curl + ) + endif (CMAKE_OSX_ARCHITECTURES MATCHES arm64) + else (DARWIN) + execute_process(COMMAND sudo mv /usr/include/openssl /usr/include/openssl3) + execute_process(COMMAND sudo mv /usr/lib/libcrypto.a /usr/lib/libcrypto.a.3) + execute_process(COMMAND sudo mv /usr/lib/libcrypto.so /usr/lib/libcrypto.so.3) + execute_process(COMMAND sudo mv /usr/lib/libssl.a /usr/lib/libssl.a.3) + execute_process(COMMAND sudo mv /usr/lib/libssl.so /usr/lib/libssl.so.3) + execute_process( + COMMAND ./configure --disable-alt-svc --disable-dict --disable-doh --disable-file --disable-gopher --disable-headers-api --disable-hsts --disable-imap --disable-ldap --disable-ldaps --disable-libcurl-option --disable-manual --disable-mqtt --disable-ntlm --disable-ntlm-wb --disable-pop3 --disable-rtsp --disable-shared --disable-smb --disable-smtp --disable-sspi --disable-telnet --disable-tftp --disable-tls-srp --disable-unix-sockets --disable-verbose --disable-versioned-symbols --enable-threaded-resolver --with-ssl=${LIBS_PREBUILT_DIR} --without-libidn2 --without-libpsl --without-libssh2 + WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/3p-curl-7.54.1-r1/curl + ) + endif (DARWIN) + execute_process( + COMMAND make -j${MAKE_JOBS} + WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/3p-curl-7.54.1-r1/curl + RESULT_VARIABLE curl_installed + ) + file( + COPY ${CMAKE_BINARY_DIR}/3p-curl-7.54.1-r1/curl/lib/.libs/libcurl.a + DESTINATION ${LIBS_PREBUILT_DIR}/lib/release + ) + if (DARWIN) + unset(ENV{CFLAGS}) + execute_process(COMMAND sudo mv /opt/local/include/openssl3 /opt/local/include/openssl) + execute_process(COMMAND sudo mv /opt/local/lib/libcrypto.a.3 /opt/local/lib/libcrypto.a) + execute_process(COMMAND sudo mv /opt/local/lib/libcrypto.dylib.3 /opt/local/lib/libcrypto.dylib) + execute_process(COMMAND sudo mv /opt/local/lib/libssl.a.3 /opt/local/lib/libssl.a) + execute_process(COMMAND sudo mv /opt/local/lib/libssl.dylib.3 /opt/local/lib/libssl.dylib) + else (DARWIN) + execute_process(COMMAND sudo mv /usr/include/openssl3 /usr/include/openssl) + execute_process(COMMAND sudo mv /usr/lib/libcrypto.a.3 /usr/lib/libcrypto.a) + execute_process(COMMAND sudo mv /usr/lib/libcrypto.so.3 /usr/lib/libcrypto.so) + execute_process(COMMAND sudo mv /usr/lib/libssl.a.3 /usr/lib/libssl.a) + execute_process(COMMAND sudo mv /usr/lib/libssl.so.3 /usr/lib/libssl.so) + endif (DARWIN) + message("OpenSSL3 header directory and library names have been restored.") + file(REMOVE + ${LIBS_PREBUILT_DIR}/lib/libcrypto.a + ${LIBS_PREBUILT_DIR}/lib/libssl.a + ) + file(WRITE ${PREBUILD_TRACKING_DIR}/curl_installed "${curl_installed}") +endif (LINUX OR NOT USESYSTEMLIBS) if (WINDOWS) target_link_libraries(ll::libcurl INTERFACE libcurl.lib) else (WINDOWS) diff --git a/indra/cmake/ConfigurePkgConfig.cmake b/indra/cmake/ConfigurePkgConfig.cmake deleted file mode 100644 index 9e798d663b..0000000000 --- a/indra/cmake/ConfigurePkgConfig.cmake +++ /dev/null @@ -1,74 +0,0 @@ -# -*- cmake -*- - -SET(DEBUG_PKG_CONFIG "YES") - -# Don't change this if manually set by user. -IF("$ENV{PKG_CONFIG_LIBDIR}" STREQUAL "") - - # Guess at architecture-specific system library paths. - if (ADDRESS_SIZE EQUAL 32) - SET(PKG_CONFIG_NO_MULTI_GUESS /usr/lib32 /usr/lib) - SET(PKG_CONFIG_NO_MULTI_LOCAL_GUESS /usr/local/lib32 /usr/local/lib) - SET(PKG_CONFIG_MULTI_GUESS /usr/lib/i386-linux-gnu) - SET(PKG_CONFIG_MULTI_LOCAL_GUESS /usr/local/lib/i386-linux-gnu) - else (ADDRESS_SIZE EQUAL 32) - SET(PKG_CONFIG_NO_MULTI_GUESS /usr/lib64 /usr/lib) - SET(PKG_CONFIG_NO_MULTI_LOCAL_GUESS /usr/local/lib64 /usr/local/lib) - SET(PKG_CONFIG_MULTI_GUESS /usr/local/lib/x86_64-linux-gnu) - SET(PKG_CONFIG_MULTI_LOCAL_GUESS /usr/local/lib/x86_64-linux-gnu) - endif (ADDRESS_SIZE EQUAL 32) - - # Use DPKG architecture, if available. - IF (${DPKG_ARCH}) - SET(PKG_CONFIG_MULTI_GUESS /usr/lib/${DPKG_ARCH}) - SET(PKG_CONFIG_MULTI_LOCAL_GUESS /usrlocal/lib/${DPKG_ARCH}) - ENDIF (${DPKG_ARCH}) - - # Explicitly include anything listed in PKG_CONFIG_PATH - string(REPLACE ":" ";" PKG_CONFIG_PATH_LIST "$ENV{PKG_CONFIG_PATH}") - FOREACH(PKG_CONFIG_DIR ${PKG_CONFIG_PATH_LIST}) - SET(VALID_PKG_LIBDIRS "${VALID_PKG_LIBDIRS}:${PKG_CONFIG_DIR}/pkgconfig") - ENDFOREACH(PKG_CONFIG_DIR) - - # Look for valid pkgconfig directories. - FIND_PATH(PKG_CONFIG_ENV pkgconfig ENV LD_LIBRARY_PATH) - FIND_PATH(PKG_CONFIG_MULTI pkgconfig HINT ${PKG_CONFIG_MULTI_GUESS}) - FIND_PATH(PKG_CONFIG_MULTI_LOCAL pkgconfig HINT ${PKG_CONFIG_MULTI_LOCAL_GUESS}) - FIND_PATH(PKG_CONFIG_NO_MULTI pkgconfig HINT ${PKG_CONFIG_NO_MULTI_GUESS}) - FIND_PATH(PKG_CONFIG_NO_MULTI_LOCAL pkgconfig HINT ${PKG_CONFIG_NO_MULTI_LOCAL_GUESS}) - - # Add anything we found to our list. - IF(NOT PKG_CONFIG_ENV STREQUAL PKG_CONFIG_ENV-NOTFOUND) - SET(VALID_PKG_LIBDIRS "${VALID_PKG_LIBDIRS}:${PKG_CONFIG_ENV}/pkgconfig") - ENDIF(NOT PKG_CONFIG_ENV STREQUAL PKG_CONFIG_ENV-NOTFOUND) - - IF(NOT PKG_CONFIG_MULTI STREQUAL PKG_CONFIG_MULTI-NOTFOUND) - SET(VALID_PKG_LIBDIRS "${VALID_PKG_LIBDIRS}:${PKG_CONFIG_MULTI}/pkgconfig") - ENDIF(NOT PKG_CONFIG_MULTI STREQUAL PKG_CONFIG_MULTI-NOTFOUND) - - IF(NOT PKG_CONFIG_MULTI_LOCAL STREQUAL PKG_CONFIG_MULTI_LOCAL-NOTFOUND) - SET(VALID_PKG_LIBDIRS "${VALID_PKG_LIBDIRS}:${PKG_CONFIG_MULTI_LOCAL}/pkgconfig") - ENDIF(NOT PKG_CONFIG_MULTI_LOCAL STREQUAL PKG_CONFIG_MULTI_LOCAL-NOTFOUND) - - IF(NOT PKG_CONFIG_NO_MULTI STREQUAL PKG_CONFIG_NO_MULTI-NOTFOUND) - SET(VALID_PKG_LIBDIRS "${VALID_PKG_LIBDIRS}:${PKG_CONFIG_NO_MULTI}/pkgconfig") - ENDIF(NOT PKG_CONFIG_NO_MULTI STREQUAL PKG_CONFIG_NO_MULTI-NOTFOUND) - - IF(NOT PKG_CONFIG_NO_MULTI_LOCAL STREQUAL PKG_CONFIG_NO_MULTI_LOCAL-NOTFOUND) - SET(VALID_PKG_LIBDIRS "${VALID_PKG_LIBDIRS}:${PKG_CONFIG_NO_MULTI_LOCAL}/pkgconfig") - ENDIF(NOT PKG_CONFIG_NO_MULTI_LOCAL STREQUAL PKG_CONFIG_NO_MULTI_LOCAL-NOTFOUND) - - # Also add some non-architecture specific package locations. - SET(VALID_PKG_LIBDIRS "${VALID_PKG_LIBDIRS}:/usr/share/pkgconfig:/usr/local/share/pkgconfig") - - # Remove first unwanted ':' - string(SUBSTRING ${VALID_PKG_LIBDIRS} 1 -1 VALID_PKG_LIBDIRS) - - # Set PKG_CONFIG_LIBDIR environment. - SET(ENV{PKG_CONFIG_LIBDIR} ${VALID_PKG_LIBDIRS}) -ENDIF("$ENV{PKG_CONFIG_LIBDIR}" STREQUAL "") - -IF(DEBUG_PKG_CONFIG) - MESSAGE(STATUS "Using PKG_CONFIG_LIBDIR=$ENV{PKG_CONFIG_LIBDIR}") -ENDIF(DEBUG_PKG_CONFIG) - diff --git a/indra/cmake/Copy3rdPartyLibs.cmake b/indra/cmake/Copy3rdPartyLibs.cmake index 30dee3c6c1..d78f2b90b8 100644 --- a/indra/cmake/Copy3rdPartyLibs.cmake +++ b/indra/cmake/Copy3rdPartyLibs.cmake @@ -227,17 +227,7 @@ elseif(LINUX) list( APPEND release_files libapr-1.so.0 libaprutil-1.so.0 - libatk-1.0.so - libfreetype.so.6.6.2 - libfreetype.so.6 libhunspell-1.3.so.0.0.0 - libopenjp2.so - libuuid.so.16 - libuuid.so.16.0.22 - libfontconfig.so.1.8.0 - libfontconfig.so.1 - libgmodule-2.0.so - libgobject-2.0.so ) endif() diff --git a/indra/cmake/FMODSTUDIO.cmake b/indra/cmake/FMODSTUDIO.cmake new file mode 100644 index 0000000000..313ee2cde7 --- /dev/null +++ b/indra/cmake/FMODSTUDIO.cmake @@ -0,0 +1,109 @@ +# -*- cmake -*- + +include_guard() + +# FMODSTUDIO can be set when launching the make using the argument -DUSE_FMODSTUDIO:BOOL=ON +# When building using proprietary binaries though (i.e. having access to LL private servers), +# we always build with FMODSTUDIO. +if (INSTALL_PROPRIETARY) + set(USE_FMODSTUDIO ON CACHE BOOL "Using FMODSTUDIO sound library.") +endif (INSTALL_PROPRIETARY) + +# ND: To streamline arguments passed, switch from FMODSTUDIO to USE_FMODSTUDIO +# To not break all old build scripts convert old arguments but warn about it +if(FMODSTUDIO) + message( WARNING "Use of the FMODSTUDIO argument is deprecated, please switch to USE_FMODSTUDIO") + set(USE_FMODSTUDIO ${FMODSTUDIO}) +endif() + +if (USE_FMODSTUDIO) + add_library( ll::fmodstudio INTERFACE IMPORTED ) + target_compile_definitions( ll::fmodstudio INTERFACE LL_FMODSTUDIO=1) + + if (FMODSTUDIO_LIBRARY AND FMODSTUDIO_INCLUDE_DIR) + # If the path have been specified in the arguments, use that + + target_link_libraries(ll::fmodstudio INTERFACE ${FMODSTUDIO_LIBRARY}) + target_include_directories( ll::fmodstudio SYSTEM INTERFACE ${FMODSTUDIO_INCLUDE_DIR}) + else (FMODSTUDIO_LIBRARY AND FMODSTUDIO_INCLUDE_DIR) + # If not, we're going to try to get the package listed in autobuild.xml + # Note: if you're not using INSTALL_PROPRIETARY, the package URL should be local (file:/// URL) + # as accessing the private LL location will fail if you don't have the credential + include(Prebuilt) + if (USESYSTEMLIBS AND (${PREBUILD_TRACKING_DIR}/sentinel_installed IS_NEWER_THAN ${PREBUILD_TRACKING_DIR}/fmodstudio_installed OR NOT ${fmodstudio_installed} EQUAL 0)) + file(MAKE_DIRECTORY ${LIBS_PREBUILT_DIR}/lib/release) + if (DARWIN) + execute_process( + COMMAND hdiutil attach -noverify fmodstudioapi20223mac-installer.dmg + WORKING_DIRECTORY $ENV{HOME}/Downloads + ) + file( + COPY + /Volumes/FMOD\ Programmers\ API\ Mac/FMOD\ Programmers\ API/api/core/inc/fmod.h + /Volumes/FMOD\ Programmers\ API\ Mac/FMOD\ Programmers\ API/api/core/inc/fmod.hpp + /Volumes/FMOD\ Programmers\ API\ Mac/FMOD\ Programmers\ API/api/core/inc/fmod_codec.h + /Volumes/FMOD\ Programmers\ API\ Mac/FMOD\ Programmers\ API/api/core/inc/fmod_common.h + /Volumes/FMOD\ Programmers\ API\ Mac/FMOD\ Programmers\ API/api/core/inc/fmod_dsp.h + /Volumes/FMOD\ Programmers\ API\ Mac/FMOD\ Programmers\ API/api/core/inc/fmod_dsp_effects.h + /Volumes/FMOD\ Programmers\ API\ Mac/FMOD\ Programmers\ API/api/core/inc/fmod_errors.h + /Volumes/FMOD\ Programmers\ API\ Mac/FMOD\ Programmers\ API/api/core/inc/fmod_output.h + DESTINATION ${LIBS_PREBUILT_DIR}/include/fmodstudio + ) + execute_process( + COMMAND lipo + lib/libfmod.dylib + -thin ${CMAKE_OSX_ARCHITECTURES} + -output ${LIBS_PREBUILT_DIR}/lib/release/libfmod.dylib + WORKING_DIRECTORY /Volumes/FMOD\ Programmers\ API\ Mac/FMOD\ Programmers\ API/api/core + ) + execute_process( + COMMAND hdiutil detach FMOD\ Programmers\ API\ Mac + WORKING_DIRECTORY /Volumes + RESULT_VARIABLE fmodstudio_installed + ) + file(WRITE ${PREBUILD_TRACKING_DIR}/fmodstudio_installed "${fmodstudio_installed}") + else (DARWIN) + file(ARCHIVE_EXTRACT + INPUT $ENV{HOME}/Downloads/fmodstudioapi20223linux.tar.gz + DESTINATION ${CMAKE_BINARY_DIR} + ) + file( + COPY + ${CMAKE_BINARY_DIR}/fmodstudioapi20223linux/api/core/inc/fmod.h + ${CMAKE_BINARY_DIR}/fmodstudioapi20223linux/api/core/inc/fmod.hpp + ${CMAKE_BINARY_DIR}/fmodstudioapi20223linux/api/core/inc/fmod_codec.h + ${CMAKE_BINARY_DIR}/fmodstudioapi20223linux/api/core/inc/fmod_common.h + ${CMAKE_BINARY_DIR}/fmodstudioapi20223linux/api/core/inc/fmod_dsp.h + ${CMAKE_BINARY_DIR}/fmodstudioapi20223linux/api/core/inc/fmod_dsp_effects.h + ${CMAKE_BINARY_DIR}/fmodstudioapi20223linux/api/core/inc/fmod_errors.h + ${CMAKE_BINARY_DIR}/fmodstudioapi20223linux/api/core/inc/fmod_output.h + DESTINATION ${LIBS_PREBUILT_DIR}/include/fmodstudio + ) + file( + COPY + ${CMAKE_BINARY_DIR}/fmodstudioapi20223linux/api/core/lib/${CMAKE_SYSTEM_PROCESSOR}/libfmod.so + ${CMAKE_BINARY_DIR}/fmodstudioapi20223linux/api/core/lib/${CMAKE_SYSTEM_PROCESSOR}/libfmod.so.13 + ${CMAKE_BINARY_DIR}/fmodstudioapi20223linux/api/core/lib/${CMAKE_SYSTEM_PROCESSOR}/libfmod.so.13.23 + DESTINATION ${LIBS_PREBUILT_DIR}/lib/release + FOLLOW_SYMLINK_CHAIN + ) + file(WRITE ${PREBUILD_TRACKING_DIR}/fmodstudio_installed "0") + endif (DARWIN) + else (USESYSTEMLIBS AND (${PREBUILD_TRACKING_DIR}/sentinel_installed IS_NEWER_THAN ${PREBUILD_TRACKING_DIR}/fmodstudio_installed OR NOT ${fmodstudio_installed} EQUAL 0)) + use_prebuilt_binary(fmodstudio) + endif (USESYSTEMLIBS AND (${PREBUILD_TRACKING_DIR}/sentinel_installed IS_NEWER_THAN ${PREBUILD_TRACKING_DIR}/fmodstudio_installed OR NOT ${fmodstudio_installed} EQUAL 0)) + if (WINDOWS) + target_link_libraries( ll::fmodstudio INTERFACE fmod_vc) + elseif (DARWIN) + #despite files being called libfmod.dylib, we are searching for fmod + target_link_libraries( ll::fmodstudio INTERFACE fmod) + elseif (LINUX) + target_link_libraries( ll::fmodstudio INTERFACE fmod) + endif (WINDOWS) + + target_include_directories( ll::fmodstudio SYSTEM INTERFACE ${LIBS_PREBUILT_DIR}/include/fmodstudio) + endif (FMODSTUDIO_LIBRARY AND FMODSTUDIO_INCLUDE_DIR) +else() + set( USE_FMODSTUDIO "OFF") +endif () + diff --git a/indra/cmake/FindPipeWire.cmake b/indra/cmake/FindPipeWire.cmake new file mode 100644 index 0000000000..868acf5ec1 --- /dev/null +++ b/indra/cmake/FindPipeWire.cmake @@ -0,0 +1,100 @@ +# cmake-format: off +# .rst: FindPipeWire +# ------- +# +# Try to find PipeWire on a Unix system. +# +# This will define the following variables: +# +# ``PIPEWIRE_FOUND`` True if (the requested version of) PipeWire is available +# ``PIPEWIRE_VERSION`` The version of PipeWire ``PIPEWIRE_LIBRARIES`` This can +# be passed to target_link_libraries() instead of the ``PipeWire::PipeWire`` +# target ``PIPEWIRE_INCLUDE_DIRS`` This should be passed to +# target_include_directories() if the target is not used for linking +# ``PIPEWIRE_COMPILE_FLAGS`` This should be passed to target_compile_options() +# if the target is not used for linking +# +# If ``PIPEWIRE_FOUND`` is TRUE, it will also define the following imported +# target: +# +# ``PipeWire::PipeWire`` The PipeWire library +# +# In general we recommend using the imported target, as it is easier to use. +# Bear in mind, however, that if the target is in the link interface of an +# exported library, it must be made available by the package config file. + +# ============================================================================= +# Copyright 2014 Alex Merry <alex.merry@kde.org> Copyright 2014 Martin Gräßlin +# <mgraesslin@kde.org> Copyright 2018-2020 Jan Grulich <jgrulich@redhat.com> +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the copyright notice, this list +# of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the copyright notice, this +# list of conditions and the following disclaimer in the documentation and/or +# other materials provided with the distribution. +# 3. The name of the author may not be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED +# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +# EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +# IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# ============================================================================= +# cmake-format: on + +# Use pkg-config to get the directories and then use these values in the FIND_PATH() and FIND_LIBRARY() calls +find_package(PkgConfig QUIET) + +pkg_search_module(PKG_PIPEWIRE QUIET libpipewire-0.3) +pkg_search_module(PKG_SPA QUIET libspa-0.2) + +set(PIPEWIRE_COMPILE_FLAGS "${PKG_PIPEWIRE_CFLAGS}" "${PKG_SPA_CFLAGS}") +set(PIPEWIRE_VERSION "${PKG_PIPEWIRE_VERSION}") + +find_path( + PIPEWIRE_INCLUDE_DIRS + NAMES pipewire/pipewire.h + HINTS ${PKG_PIPEWIRE_INCLUDE_DIRS} ${PKG_PIPEWIRE_INCLUDE_DIRS}/pipewire-0.3) + +find_path( + SPA_INCLUDE_DIRS + NAMES spa/param/props.h + HINTS ${PKG_SPA_INCLUDE_DIRS} ${PKG_SPA_INCLUDE_DIRS}/spa-0.2) + +find_library( + PIPEWIRE_LIBRARIES + NAMES pipewire-0.3 + HINTS ${PKG_PIPEWIRE_LIBRARY_DIRS}) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args( + PipeWire + FOUND_VAR PIPEWIRE_FOUND + REQUIRED_VARS PIPEWIRE_LIBRARIES PIPEWIRE_INCLUDE_DIRS SPA_INCLUDE_DIRS + VERSION_VAR PIPEWIRE_VERSION) + +if(PIPEWIRE_FOUND AND NOT TARGET PipeWire::PipeWire) + add_library(PipeWire::PipeWire UNKNOWN IMPORTED) + set_target_properties( + PipeWire::PipeWire + PROPERTIES IMPORTED_LOCATION "${PIPEWIRE_LIBRARIES}" + INTERFACE_COMPILE_OPTIONS "${PIPEWIRE_COMPILE_FLAGS}" + INTERFACE_INCLUDE_DIRECTORIES "${PIPEWIRE_INCLUDE_DIRS};${SPA_INCLUDE_DIRS}") +endif() + +mark_as_advanced(PIPEWIRE_LIBRARIES PIPEWIRE_INCLUDE_DIRS) + +include(FeatureSummary) +set_package_properties( + PipeWire PROPERTIES + URL "https://www.pipewire.org" + DESCRIPTION "PipeWire - multimedia processing") diff --git a/indra/cmake/FreeType.cmake b/indra/cmake/FreeType.cmake index 77140af641..82ba8fc06e 100644 --- a/indra/cmake/FreeType.cmake +++ b/indra/cmake/FreeType.cmake @@ -4,8 +4,20 @@ include(Prebuilt) include_guard() add_library( ll::freetype INTERFACE IMPORTED ) -use_system_binary(freetype) -use_prebuilt_binary(freetype) -target_include_directories( ll::freetype SYSTEM INTERFACE ${LIBS_PREBUILT_DIR}/include/freetype2/) -target_link_libraries( ll::freetype INTERFACE freetype ) +if (USESYSTEMLIBS) + include(FindPkgConfig) + pkg_check_modules(Freetype REQUIRED freetype2) + target_include_directories( ll::freetype SYSTEM INTERFACE ${Freetype_INCLUDE_DIRS} ) + target_link_directories( ll::freetype INTERFACE ${Freetype_LIBRARY_DIRS} ) + target_link_libraries( ll::freetype INTERFACE ${Freetype_LIBRARIES} ) + return () +endif () + use_system_binary(freetype) + use_prebuilt_binary(freetype) + target_include_directories( ll::freetype SYSTEM INTERFACE ${LIBS_PREBUILT_DIR}/include/freetype2/) +if( LINUX ) + target_link_libraries( ll::freetype INTERFACE ${LIBS_PREBUILT_DIR}/lib/release/libfreetype.a ${LIBS_PREBUILT_DIR}/lib/release/libpng16.a) +else() + target_link_libraries( ll::freetype INTERFACE freetype ) +endif() diff --git a/indra/cmake/GLEXT.cmake b/indra/cmake/GLEXT.cmake index a780966f0c..ea349237d3 100644 --- a/indra/cmake/GLEXT.cmake +++ b/indra/cmake/GLEXT.cmake @@ -3,7 +3,10 @@ include(Prebuilt) include(GLH) add_library( ll::glext INTERFACE IMPORTED ) -use_system_binary(glext) -use_prebuilt_binary(glext) +if (USESYSTEMLIBS) + return () +endif () +use_system_binary(glext) +use_prebuilt_binary(glext) diff --git a/indra/cmake/GLH.cmake b/indra/cmake/GLH.cmake index 0cefc3543a..648a08454b 100644 --- a/indra/cmake/GLH.cmake +++ b/indra/cmake/GLH.cmake @@ -2,6 +2,9 @@ include(Prebuilt) add_library( ll::glh_linear INTERFACE IMPORTED ) +target_include_directories( ll::glh_linear SYSTEM INTERFACE ${LIBS_PREBUILT_DIR}/include) +if (NOT USESYSTEMLIBS) use_system_binary( glh_linear ) +endif (NOT USESYSTEMLIBS) use_prebuilt_binary(glh_linear) diff --git a/indra/cmake/GLIB.cmake b/indra/cmake/GLIB.cmake new file mode 100644 index 0000000000..f52cbb7f87 --- /dev/null +++ b/indra/cmake/GLIB.cmake @@ -0,0 +1,22 @@ +include_guard() + +include(Prebuilt) + +add_library( ll::glib INTERFACE IMPORTED ) +add_library( ll::glib_headers INTERFACE IMPORTED ) +add_library( ll::gio INTERFACE IMPORTED ) + +if( LINUX ) + find_package(PkgConfig REQUIRED) + pkg_search_module(GLIB REQUIRED glib-2.0) + pkg_search_module(GIO REQUIRED gio-2.0) + + target_include_directories( ll::glib SYSTEM INTERFACE ${GLIB_INCLUDE_DIRS} ) + target_link_libraries( ll::glib INTERFACE ${GLIB_LDFLAGS} ) + target_compile_definitions( ll::glib INTERFACE -DLL_GLIB=1) + + target_include_directories( ll::glib_headers SYSTEM INTERFACE ${GLIB_INCLUDE_DIRS} ) + target_compile_definitions( ll::glib_headers INTERFACE -DLL_GLIB=1) + + target_link_libraries( ll::gio INTERFACE ${GIO_LDFLAGS} ) +endif() diff --git a/indra/cmake/GLM.cmake b/indra/cmake/GLM.cmake index 84b155f6c5..451b7292cb 100644 --- a/indra/cmake/GLM.cmake +++ b/indra/cmake/GLM.cmake @@ -3,5 +3,12 @@ include(Prebuilt) add_library( ll::glm INTERFACE IMPORTED ) +if (NOT USESYSTEMLIBS) use_system_binary( glm ) +elseif (NOT LINUX) + find_package( glm REQUIRED ) +endif (NOT USESYSTEMLIBS) + +if (LINUX OR USESYSTEMLIBS) use_prebuilt_binary(glm) +endif (LINUX OR USESYSTEMLIBS) diff --git a/indra/cmake/GStreamer10Plugin.cmake b/indra/cmake/GStreamer10Plugin.cmake new file mode 100644 index 0000000000..160844ef68 --- /dev/null +++ b/indra/cmake/GStreamer10Plugin.cmake @@ -0,0 +1,27 @@ +# -*- cmake -*- + +include_guard() + +include(Prebuilt) +include(GLIB) + +add_library( ll::gstreamer10 INTERFACE IMPORTED ) + +if (LINUX OR CMAKE_SYSTEM_NAME MATCHES "FreeBSD") + include(FindPkgConfig) + + pkg_check_modules(GSTREAMER10 REQUIRED gstreamer-1.0) + pkg_check_modules(GSTREAMER10_PLUGINS_BASE REQUIRED gstreamer-plugins-base-1.0) + + target_include_directories( ll::gstreamer10 SYSTEM INTERFACE ${GSTREAMER10_INCLUDE_DIRS}) + target_link_libraries( ll::gstreamer10 INTERFACE ll::glib_headers) + +endif () + +if (GSTREAMER10_FOUND AND GSTREAMER10_PLUGINS_BASE_FOUND) + set(GSTREAMER10 ON CACHE BOOL "Build with GStreamer-1.0 streaming media support.") +endif (GSTREAMER10_FOUND AND GSTREAMER10_PLUGINS_BASE_FOUND) + +if (GSTREAMER10) + add_definitions(-DLL_GSTREAMER10_ENABLED=1) +endif (GSTREAMER10) diff --git a/indra/cmake/Hunspell.cmake b/indra/cmake/Hunspell.cmake index bb037c0237..96c75ad262 100644 --- a/indra/cmake/Hunspell.cmake +++ b/indra/cmake/Hunspell.cmake @@ -2,7 +2,9 @@ include(Prebuilt) include_guard() +if (USE_AUTOBUILD_3P OR USE_CONAN) use_prebuilt_binary(dictionaries) +endif () add_library( ll::hunspell INTERFACE IMPORTED ) use_system_binary(hunspell) diff --git a/indra/cmake/LLAddBuildTest.cmake b/indra/cmake/LLAddBuildTest.cmake index 6408f1200c..5d96a4398f 100644 --- a/indra/cmake/LLAddBuildTest.cmake +++ b/indra/cmake/LLAddBuildTest.cmake @@ -1,4 +1,11 @@ # -*- cmake -*- + +include_guard() + +if( NOT LL_TESTS ) + return() +endif() + include(00-Common) include(LLTestCommand) include(bugsplat) diff --git a/indra/cmake/LLCoreHttp.cmake b/indra/cmake/LLCoreHttp.cmake index 22ed5fef9c..5464e4d327 100644 --- a/indra/cmake/LLCoreHttp.cmake +++ b/indra/cmake/LLCoreHttp.cmake @@ -1,5 +1,5 @@ # -*- cmake -*- -include(CURL) include(OpenSSL) +include(CURL) include(NGHTTP2) diff --git a/indra/cmake/LLPhysicsExtensions.cmake b/indra/cmake/LLPhysicsExtensions.cmake index 80d243d9f8..1cb1679d75 100644 --- a/indra/cmake/LLPhysicsExtensions.cmake +++ b/indra/cmake/LLPhysicsExtensions.cmake @@ -26,6 +26,9 @@ if (HAVOK) elseif (HAVOK_TPV) use_prebuilt_binary(llphysicsextensions_tpv) target_link_libraries( llphysicsextensions_impl INTERFACE llphysicsextensions_tpv) +elseif (NOT (USE_AUTOBUILD_3P OR USE_CONAN)) + target_link_libraries( llphysicsextensions_impl INTERFACE llphysicsextensionsstub) + return () else (HAVOK) use_prebuilt_binary(llphysicsextensions_stub) set(LLPHYSICSEXTENSIONS_SRC_DIR ${LIBS_PREBUILT_DIR}/llphysicsextensions/stub) diff --git a/indra/cmake/LLPrimitive.cmake b/indra/cmake/LLPrimitive.cmake index 735f5e8052..539f5c0d55 100644 --- a/indra/cmake/LLPrimitive.cmake +++ b/indra/cmake/LLPrimitive.cmake @@ -11,6 +11,16 @@ add_library( ll::minizip-ng INTERFACE IMPORTED ) add_library( ll::libxml INTERFACE IMPORTED ) add_library( ll::colladadom INTERFACE IMPORTED ) +if ( NOT (USE_AUTOBUILD_3P OR USE_CONAN) ) + include(FindPkgConfig) + pkg_check_modules(Colladadom REQUIRED collada-dom) + target_compile_definitions( ll::colladadom INTERFACE COLLADA_DOM_SUPPORT141 ) + target_include_directories( ll::colladadom SYSTEM INTERFACE ${Colladadom_INCLUDE_DIRS} ${Colladadom_INCLUDE_DIRS}/1.4 ) + target_link_directories( ll::colladadom INTERFACE ${Colladadom_LIBRARY_DIRS} ) + target_link_libraries( ll::colladadom INTERFACE ${Colladadom_LIBRARIES} ) + return () +endif () + # ND, needs fixup in collada conan pkg if( USE_CONAN ) target_include_directories( ll::colladadom SYSTEM INTERFACE diff --git a/indra/cmake/LLWindow.cmake b/indra/cmake/LLWindow.cmake index 2e1b601b79..383051a4a6 100644 --- a/indra/cmake/LLWindow.cmake +++ b/indra/cmake/LLWindow.cmake @@ -7,16 +7,27 @@ include(Prebuilt) include_guard() add_library( ll::SDL INTERFACE IMPORTED ) +if (USESYSTEMLIBS AND NOT DARWIN) + include(FindPkgConfig) + pkg_check_modules(Sdl2 REQUIRED sdl2) + target_compile_definitions( ll::SDL INTERFACE LL_SDL=1) + target_include_directories(ll::SDL SYSTEM INTERFACE ${Sdl2_INCLUDE_DIRS}) + target_link_directories(ll::SDL INTERFACE ${Sdl2_LIBRARY_DIRS}) + if (LINUX OR CMAKE_SYSTEM_NAME MATCHES "FreeBSD") + list(APPEND Sdl2_LIBRARIES X11) + endif () + target_link_libraries(ll::SDL INTERFACE ${Sdl2_LIBRARIES}) + return () +endif () + if (LINUX) #Must come first as use_system_binary can exit this file early - target_compile_definitions( ll::SDL INTERFACE LL_SDL=1) + target_compile_definitions( ll::SDL INTERFACE LL_SDL_VERSION=2 LL_SDL) - use_system_binary(SDL) - use_prebuilt_binary(SDL) + #find_package(SDL2 REQUIRED) + #target_link_libraries( ll::SDL INTERFACE SDL2::SDL2 SDL2::SDL2main X11) - target_include_directories( ll::SDL SYSTEM INTERFACE ${LIBS_PREBUILT_DIR}/include) - target_link_libraries( ll::SDL INTERFACE SDL directfb fusion direct X11) + use_prebuilt_binary(SDL2) + target_link_libraries( ll::SDL INTERFACE SDL2 X11) endif (LINUX) - - diff --git a/indra/cmake/LibVLCPlugin.cmake b/indra/cmake/LibVLCPlugin.cmake index 599ce02844..779576a485 100644 --- a/indra/cmake/LibVLCPlugin.cmake +++ b/indra/cmake/LibVLCPlugin.cmake @@ -5,9 +5,56 @@ include(Prebuilt) include_guard() add_library( ll::libvlc INTERFACE IMPORTED ) +if (USESYSTEMLIBS) + if (DARWIN) + if (CMAKE_OSX_ARCHITECTURES MATCHES arm64) + if (${PREBUILD_TRACKING_DIR}/sentinel_installed IS_NEWER_THAN ${PREBUILD_TRACKING_DIR}/vlc_installed OR NOT ${vlc_installed} EQUAL 0) + if (NOT EXISTS ${CMAKE_BINARY_DIR}/vlc-3.0.21-arm64.dmg) + file(DOWNLOAD + https://get.videolan.org/vlc/3.0.21/macosx/vlc-3.0.21-arm64.dmg + ${CMAKE_BINARY_DIR}/vlc-3.0.21-arm64.dmg + ) + endif (NOT EXISTS ${CMAKE_BINARY_DIR}/vlc-3.0.21-arm64.dmg) + file(WRITE ${PREBUILD_TRACKING_DIR}/vlc_installed "0") + endif (${PREBUILD_TRACKING_DIR}/sentinel_installed IS_NEWER_THAN ${PREBUILD_TRACKING_DIR}/vlc_installed OR NOT ${vlc_installed} EQUAL 0) + execute_process( + COMMAND hdiutil attach -noverify vlc-3.0.21-arm64.dmg + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + ) + else (CMAKE_OSX_ARCHITECTURES MATCHES arm64) + if (${PREBUILD_TRACKING_DIR}/sentinel_installed IS_NEWER_THAN ${PREBUILD_TRACKING_DIR}/vlc_installed OR NOT ${vlc_installed} EQUAL 0) + if (NOT EXISTS ${CMAKE_BINARY_DIR}/vlc-3.0.21-intel64.dmg) + file(DOWNLOAD + https://get.videolan.org/vlc/3.0.21/macosx/vlc-3.0.21-intel64.dmg + ${CMAKE_BINARY_DIR}/vlc-3.0.21-intel64.dmg + ) + endif (NOT EXISTS ${CMAKE_BINARY_DIR}/vlc-3.0.21-intel64.dmg) + file(WRITE ${PREBUILD_TRACKING_DIR}/vlc_installed "0") + endif (${PREBUILD_TRACKING_DIR}/sentinel_installed IS_NEWER_THAN ${PREBUILD_TRACKING_DIR}/vlc_installed OR NOT ${vlc_installed} EQUAL 0) + execute_process( + COMMAND hdiutil attach -noverify vlc-3.0.21-intel64.dmg + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + ) + endif (CMAKE_OSX_ARCHITECTURES MATCHES arm64) + target_include_directories( ll::libvlc SYSTEM INTERFACE /Volumes/VLC\ media\ player/VLC.app/Contents/MacOS/include) + target_link_directories( ll::libvlc INTERFACE /Volumes/VLC\ media\ player/VLC.app/Contents/MacOS/lib) + target_link_libraries( ll::libvlc INTERFACE vlc vlccore ) + else (DARWIN) + include(FindPkgConfig) + pkg_check_modules(Libvlc REQUIRED libvlc vlc-plugin) + target_include_directories( ll::libvlc SYSTEM INTERFACE ${Libvlc_INCLUDE_DIRS} ) + target_link_directories( ll::libvlc INTERFACE ${Libvlc_LIBRARY_DIRS} ) + target_link_libraries( ll::libvlc INTERFACE ${Libvlc_LIBRARIES} ) + endif (DARWIN) + set(LIBVLCPLUGIN ON CACHE BOOL + "LIBVLCPLUGIN support for the llplugin/llmedia test apps.") + return() +else (USESYSTEMLIBS) + use_prebuilt_binary(vlc-bin) set(LIBVLCPLUGIN ON CACHE BOOL "LIBVLCPLUGIN support for the llplugin/llmedia test apps.") +endif (USESYSTEMLIBS) if (WINDOWS) target_link_libraries( ll::libvlc INTERFACE diff --git a/indra/cmake/LibraryInstall.cmake b/indra/cmake/LibraryInstall.cmake new file mode 100644 index 0000000000..b94841897c --- /dev/null +++ b/indra/cmake/LibraryInstall.cmake @@ -0,0 +1,13 @@ +list(REMOVE_ITEM ${PROJECT_NAME}_HEADER_FILES CMakeLists.txt) +#install(FILES ${${PROJECT_NAME}_HEADER_FILES} +# DESTINATION include/${PROJECT_NAME}) +if (BUILD_SHARED_LIBS) + if (EXISTS ${CMAKE_SYSROOT}/usr/lib/${ARCH}-linux-gnu) + set(_LIB lib/${ARCH}-linux-gnu) + elseif (EXISTS /lib64) + set(_LIB lib64) + else () + set(_LIB lib) + endif () + install(TARGETS ${PROJECT_NAME} DESTINATION ${_LIB}) +endif () diff --git a/indra/cmake/Linker.cmake b/indra/cmake/Linker.cmake new file mode 100644 index 0000000000..8016842192 --- /dev/null +++ b/indra/cmake/Linker.cmake @@ -0,0 +1,11 @@ +include_guard(GLOBAL) + +if( LINK_WITH_MOLD ) + find_program(MOLD_BIN mold) + if(MOLD_BIN) + message(STATUS "Mold linker found: ${MOLD_BIN}. Enabling mold as active linker.") + add_link_options("-fuse-ld=${MOLD_BIN}") + else() + message(STATUS "Mold linker not found. Using default linker.") + endif() +endif() diff --git a/indra/cmake/Linking.cmake b/indra/cmake/Linking.cmake index 1d757abeff..8e91dac109 100644 --- a/indra/cmake/Linking.cmake +++ b/indra/cmake/Linking.cmake @@ -66,7 +66,7 @@ elseif (WINDOWS) rpcrt4.lib legacy_stdio_definitions ) -else() +elseif (DARWIN) include(CMakeFindFrameworks) find_library(COREFOUNDATION_LIBRARY CoreFoundation) find_library(CARBON_LIBRARY Carbon) diff --git a/indra/cmake/Meshoptimizer.cmake b/indra/cmake/Meshoptimizer.cmake index fd144d2b97..0dc4069431 100644 --- a/indra/cmake/Meshoptimizer.cmake +++ b/indra/cmake/Meshoptimizer.cmake @@ -6,15 +6,74 @@ include(Prebuilt) include_guard() add_library( ll::meshoptimizer INTERFACE IMPORTED ) +if (NOT USESYSTEMLIBS) use_system_binary(meshoptimizer) +else (NOT USESYSTEMLIBS) + if (NOT (${LINUX_DISTRO} MATCHES fedora OR (${LINUX_DISTRO} MATCHES opensuse-tumbleweed) OR DARWIN)) + find_package(meshoptimizer) + target_link_libraries( ll::meshoptimizer INTERFACE meshoptimizer) + endif (NOT (${LINUX_DISTRO} MATCHES fedora OR (${LINUX_DISTRO} MATCHES opensuse-tumbleweed) OR DARWIN)) +endif (NOT USESYSTEMLIBS) + +if (${LINUX_DISTRO} MATCHES fedora OR (${LINUX_DISTRO} MATCHES opensuse-tumbleweed) OR DARWIN OR NOT USESYSTEMLIBS) + if (USESYSTEMLIBS) + if (${PREBUILD_TRACKING_DIR}/sentinel_installed IS_NEWER_THAN ${PREBUILD_TRACKING_DIR}/meshoptimizer_installed OR NOT ${meshoptimizer_installed} EQUAL 0) + if (NOT EXISTS ${CMAKE_BINARY_DIR}/meshoptimizer-0.21.tar.gz) + file(DOWNLOAD + https://github.com/zeux/meshoptimizer/archive/refs/tags/v0.21.tar.gz + ${CMAKE_BINARY_DIR}/meshoptimizer-0.21.tar.gz + ) + endif (NOT EXISTS ${CMAKE_BINARY_DIR}/meshoptimizer-0.21.tar.gz) + file(ARCHIVE_EXTRACT + INPUT ${CMAKE_BINARY_DIR}/meshoptimizer-0.21.tar.gz + DESTINATION ${CMAKE_BINARY_DIR} + ) + if (DARWIN) + try_compile(MESHOPTIMIZER_RESULT + PROJECT meshoptimizer + SOURCE_DIR ${CMAKE_BINARY_DIR}/meshoptimizer-0.21 + BINARY_DIR ${CMAKE_BINARY_DIR}/meshoptimizer-0.21 + TARGET meshoptimizer + CMAKE_FLAGS + -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE} + -DCMAKE_OSX_ARCHITECTURES:STRING=${CMAKE_OSX_ARCHITECTURES} + -DCMAKE_OSX_DEPLOYMENT_TARGET:STRING=10.15 + OUTPUT_VARIABLE meshoptimizer_installed + ) + else (DARWIN) + try_compile(MESHOPTIMIZER_RESULT + PROJECT meshoptimizer + SOURCE_DIR ${CMAKE_BINARY_DIR}/meshoptimizer-0.21 + BINARY_DIR ${CMAKE_BINARY_DIR}/meshoptimizer-0.21 + TARGET meshoptimizer + CMAKE_FLAGS + -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE} + OUTPUT_VARIABLE meshoptimizer_installed + ) + endif (DARWIN) + if (${MESHOPTIMIZER_RESULT}) + file( + COPY ${CMAKE_BINARY_DIR}/meshoptimizer-0.21/src/meshoptimizer.h + DESTINATION ${LIBS_PREBUILT_DIR}/include/meshoptimizer + ) + file( + COPY ${CMAKE_BINARY_DIR}/meshoptimizer-0.21/libmeshoptimizer.a + DESTINATION ${LIBS_PREBUILT_DIR}/lib/release + ) + file(WRITE ${PREBUILD_TRACKING_DIR}/meshoptimizer_installed "0") + endif (${MESHOPTIMIZER_RESULT}) + endif (${PREBUILD_TRACKING_DIR}/sentinel_installed IS_NEWER_THAN ${PREBUILD_TRACKING_DIR}/meshoptimizer_installed OR NOT ${meshoptimizer_installed} EQUAL 0) + else (USESYSTEMLIBS) use_prebuilt_binary(meshoptimizer) + endif (USESYSTEMLIBS) if (WINDOWS) target_link_libraries( ll::meshoptimizer INTERFACE meshoptimizer.lib) elseif (LINUX) - target_link_libraries( ll::meshoptimizer INTERFACE meshoptimizer.o) + target_link_libraries( ll::meshoptimizer INTERFACE libmeshoptimizer.a) elseif (DARWIN) target_link_libraries( ll::meshoptimizer INTERFACE libmeshoptimizer.a) endif (WINDOWS) target_include_directories( ll::meshoptimizer SYSTEM INTERFACE ${LIBS_PREBUILT_DIR}/include/meshoptimizer) +endif (${LINUX_DISTRO} MATCHES fedora OR (${LINUX_DISTRO} MATCHES opensuse-tumbleweed) OR DARWIN OR NOT USESYSTEMLIBS) diff --git a/indra/cmake/Mikktspace.cmake b/indra/cmake/Mikktspace.cmake index 9fd2becba4..c73321e313 100644 --- a/indra/cmake/Mikktspace.cmake +++ b/indra/cmake/Mikktspace.cmake @@ -1,6 +1,4 @@ # -*- cmake -*- include(Prebuilt) -if (NOT USESYSTEMLIBS) use_prebuilt_binary(mikktspace) -endif (NOT USESYSTEMLIBS) diff --git a/indra/cmake/NDOF.cmake b/indra/cmake/NDOF.cmake index b88fbccf2a..1bf6c5086c 100644 --- a/indra/cmake/NDOF.cmake +++ b/indra/cmake/NDOF.cmake @@ -8,7 +8,43 @@ add_library( ll::ndof INTERFACE IMPORTED ) if (NDOF) if (WINDOWS OR DARWIN) + if (USESYSTEMLIBS) + if (${PREBUILD_TRACKING_DIR}/sentinel_installed IS_NEWER_THAN ${PREBUILD_TRACKING_DIR}/libndofdev_installed OR NOT ${libndofdev_installed} EQUAL 0) + file(DOWNLOAD + https://github.com/secondlife/3p-libndofdev/archive/refs/tags/v0.1.8e9edc7.tar.gz + ${CMAKE_BINARY_DIR}/3p-libndofdev-0.1.8e9edc7.tar.gz + ) + file(ARCHIVE_EXTRACT + INPUT ${CMAKE_BINARY_DIR}/3p-libndofdev-0.1.8e9edc7.tar.gz + DESTINATION ${CMAKE_BINARY_DIR} + ) + try_compile(LIBNDOFDEV_RESULT + PROJECT libndofdev + SOURCE_DIR ${CMAKE_BINARY_DIR}/3p-libndofdev-0.1.8e9edc7/libndofdev + BINARY_DIR ${CMAKE_BINARY_DIR}/3p-libndofdev-0.1.8e9edc7/libndofdev + TARGET ndofdev + CMAKE_FLAGS + -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE} + -DCMAKE_OSX_ARCHITECTURES:STRING=${CMAKE_OSX_ARCHITECTURES} + -DCMAKE_OSX_DEPLOYMENT_TARGET:STRING=10.15 + -DCMAKE_C_FLAGS:STRING=-DTARGET_OS_MAC\ -Wno-int-conversion + OUTPUT_VARIABLE libndofdev_installed + ) + if (${LIBNDOFDEV_RESULT}) + file( + COPY ${CMAKE_BINARY_DIR}/3p-libndofdev-0.1.8e9edc7/libndofdev/src/ndofdev_external.h + DESTINATION ${LIBS_PREBUILT_DIR}/include + ) + file( + COPY ${CMAKE_BINARY_DIR}/3p-libndofdev-0.1.8e9edc7/libndofdev/src/libndofdev.dylib + DESTINATION ${LIBS_PREBUILT_DIR}/lib/release + ) + file(WRITE ${PREBUILD_TRACKING_DIR}/libndofdev_installed "0") + endif (${LIBNDOFDEV_RESULT}) + endif (${PREBUILD_TRACKING_DIR}/sentinel_installed IS_NEWER_THAN ${PREBUILD_TRACKING_DIR}/libndofdev_installed OR NOT ${libndofdev_installed} EQUAL 0) + else (USESYSTEMLIBS) use_prebuilt_binary(libndofdev) + endif (USESYSTEMLIBS) elseif (LINUX) use_prebuilt_binary(open-libndofdev) endif (WINDOWS OR DARWIN) @@ -19,6 +55,6 @@ if (NDOF) target_link_libraries( ll::ndof INTERFACE ndofdev) endif (WINDOWS) target_compile_definitions( ll::ndof INTERFACE LIB_NDOF=1) +else() + add_compile_options(-ULIB_NDOF) endif (NDOF) - - diff --git a/indra/cmake/OPENAL.cmake b/indra/cmake/OPENAL.cmake index 347dd02cd7..6555027dc1 100644 --- a/indra/cmake/OPENAL.cmake +++ b/indra/cmake/OPENAL.cmake @@ -18,6 +18,17 @@ endif() if (USE_OPENAL) add_library( ll::openal INTERFACE IMPORTED ) + + if (NOT (USE_AUTOBUILD_3P OR USE_CONAN)) + target_compile_definitions( ll::openal INTERFACE LL_OPENAL=1) + include(FindPkgConfig) + pkg_check_modules(Openal REQUIRED freealut) + target_include_directories(ll::openal SYSTEM INTERFACE ${Openal_INCLUDE_DIRS}) + target_link_directories(ll::openal INTERFACE ${Openal_LIBRARY_DIRS}) + target_link_libraries(ll::openal INTERFACE ${Openal_LIBRARIES}) + return () + endif () + target_include_directories( ll::openal SYSTEM INTERFACE "${LIBS_PREBUILT_DIR}/include/AL") target_compile_definitions( ll::openal INTERFACE LL_OPENAL=1) use_prebuilt_binary(openal) diff --git a/indra/cmake/OpenJPEG.cmake b/indra/cmake/OpenJPEG.cmake index c4aab2e9e5..9bb222d8e8 100644 --- a/indra/cmake/OpenJPEG.cmake +++ b/indra/cmake/OpenJPEG.cmake @@ -4,8 +4,52 @@ include(Prebuilt) include_guard() add_library( ll::openjpeg INTERFACE IMPORTED ) +if (NOT USESYSTEMLIBS) use_system_binary(openjpeg) +elseif (${LINUX_DISTRO} MATCHES fedora OR (${LINUX_DISTRO} MATCHES opensuse-tumbleweed) OR DARWIN OR CMAKE_SYSTEM_NAME MATCHES FreeBSD) + include(FindPkgConfig) + pkg_check_modules(Openjpeg REQUIRED libopenjp2) + target_include_directories(ll::openjpeg SYSTEM INTERFACE ${Openjpeg_INCLUDE_DIRS}) + target_link_directories(ll::openjpeg INTERFACE ${Openjpeg_LIBRARY_DIRS}) + target_link_libraries(ll::openjpeg INTERFACE ${Openjpeg_LIBRARIES}) +endif (NOT USESYSTEMLIBS) +if (USESYSTEMLIBS AND (${LINUX_DISTRO} MATCHES fedora OR (${LINUX_DISTRO} MATCHES opensuse-tumbleweed) OR DARWIN OR CMAKE_SYSTEM_NAME MATCHES FreeBSD)) + if (${PREBUILD_TRACKING_DIR}/sentinel_installed IS_NEWER_THAN ${PREBUILD_TRACKING_DIR}/openjpeg_installed OR NOT ${openjpeg_installed} EQUAL 0) + if (NOT EXISTS ${CMAKE_BINARY_DIR}/openjpeg-2.5.2.tar.gz) + file(DOWNLOAD + https://github.com/uclouvain/openjpeg/archive/refs/tags/v2.5.2.tar.gz + ${CMAKE_BINARY_DIR}/openjpeg-2.5.2.tar.gz + ) + endif (NOT EXISTS ${CMAKE_BINARY_DIR}/openjpeg-2.5.2.tar.gz) + file(ARCHIVE_EXTRACT + INPUT ${CMAKE_BINARY_DIR}/openjpeg-2.5.2.tar.gz + DESTINATION ${CMAKE_BINARY_DIR} + ) + execute_process( + COMMAND cmake + -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE} + . + WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/openjpeg-2.5.2 + RESULT_VARIABLE openjpeg_installed + ) + file( + COPY + ${CMAKE_BINARY_DIR}/openjpeg-2.5.2/src/lib/openjp2/cio.h + ${CMAKE_BINARY_DIR}/openjpeg-2.5.2/src/lib/openjp2/event.h + ${CMAKE_BINARY_DIR}/openjpeg-2.5.2/src/lib/openjp2/opj_config_private.h + DESTINATION ${LIBS_PREBUILT_DIR}/include/openjpeg-2.5 + ) + file(WRITE ${PREBUILD_TRACKING_DIR}/openjpeg_installed "${openjpeg_installed}") + endif (${PREBUILD_TRACKING_DIR}/sentinel_installed IS_NEWER_THAN ${PREBUILD_TRACKING_DIR}/openjpeg_installed OR NOT ${openjpeg_installed} EQUAL 0) +else (USESYSTEMLIBS AND (${LINUX_DISTRO} MATCHES fedora OR (${LINUX_DISTRO} MATCHES opensuse-tumbleweed) OR DARWIN OR CMAKE_SYSTEM_NAME MATCHES FreeBSD)) use_prebuilt_binary(openjpeg) + if (NOT EXISTS ${LIBS_PREBUILT_DIR}/include/openjpeg-2.5) + file(RENAME + ${LIBS_PREBUILT_DIR}/include/openjpeg + ${LIBS_PREBUILT_DIR}/include/openjpeg-2.5 + ) + endif (NOT EXISTS ${LIBS_PREBUILT_DIR}/include/openjpeg-2.5) target_link_libraries(ll::openjpeg INTERFACE openjp2 ) -target_include_directories( ll::openjpeg SYSTEM INTERFACE ${LIBS_PREBUILT_DIR}/include/openjpeg) +endif (USESYSTEMLIBS AND (${LINUX_DISTRO} MATCHES fedora OR (${LINUX_DISTRO} MATCHES opensuse-tumbleweed) OR DARWIN OR CMAKE_SYSTEM_NAME MATCHES FreeBSD)) +target_include_directories( ll::openjpeg SYSTEM INTERFACE ${LIBS_PREBUILT_DIR}/include) diff --git a/indra/cmake/OpenSSL.cmake b/indra/cmake/OpenSSL.cmake index 3387c74f45..4481b3460f 100644 --- a/indra/cmake/OpenSSL.cmake +++ b/indra/cmake/OpenSSL.cmake @@ -4,8 +4,158 @@ include(Prebuilt) include_guard() add_library( ll::openssl INTERFACE IMPORTED ) +if (NOT USESYSTEMLIBS) use_system_binary(openssl) +endif (NOT USESYSTEMLIBS) +if (CMAKE_OSX_ARCHITECTURES MATCHES x86_64 OR LINUX OR NOT USESYSTEMLIBS) use_prebuilt_binary(openssl) +elseif (${PREBUILD_TRACKING_DIR}/sentinel_installed IS_NEWER_THAN ${PREBUILD_TRACKING_DIR}/openssl_installed OR NOT ${openssl_installed} EQUAL 0) + if (NOT EXISTS ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55.tar.gz) + file(DOWNLOAD + https://github.com/secondlife/3p-openssl/archive/refs/tags/v1.1.1q.de53f55.tar.gz + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55.tar.gz + ) + endif (NOT EXISTS ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55.tar.gz) + file(ARCHIVE_EXTRACT + INPUT ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55.tar.gz + DESTINATION ${CMAKE_BINARY_DIR} + ) + if (CMAKE_OSX_ARCHITECTURES MATCHES arm64) + set(ENV{CFLAGS} "-mmacosx-version-min=11.0") + execute_process( + COMMAND ./Configure no-shared darwin64-arm64-cc + WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl + ) + else (CMAKE_OSX_ARCHITECTURES MATCHES arm64) + execute_process( + COMMAND ./config no-shared + WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl + ) + endif (CMAKE_OSX_ARCHITECTURES MATCHES arm64) + execute_process( + COMMAND make -j${MAKE_JOBS} + WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl + RESULT_VARIABLE openssl_installed + ) + if (CMAKE_OSX_ARCHITECTURES MATCHES arm64) + unset(ENV{CFLAGS}) + endif (CMAKE_OSX_ARCHITECTURES MATCHES arm64) + file( + COPY + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/aes.h + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/bnerr.h + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/conf_api.h + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/dtls1.h + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/evperr.h + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/obj_mac.h + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/pkcs12.h + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/rsa.h + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/stack.h + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/x509.h + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/asn1.h + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/buffer.h + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/conferr.h + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/e_os2.h + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/hmac.h + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/objects.h + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/pkcs12err.h + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/rsaerr.h + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/store.h + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/x509_vfy.h + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/asn1_mac.h + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/buffererr.h + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/crypto.h + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/ebcdic.h + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/idea.h + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/objectserr.h + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/pkcs7.h + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/safestack.h + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/storeerr.h + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/x509err.h + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/asn1err.h + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/camellia.h + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/cryptoerr.h + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/ec.h + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/kdf.h + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/ocsp.h + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/pkcs7err.h + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/seed.h + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/symhacks.h + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/x509v3.h + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/asn1t.h + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/cast.h + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/ct.h + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/ecdh.h + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/kdferr.h + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/ocsperr.h + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/rand.h + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/sha.h + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/tls1.h + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/x509v3err.h + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/async.h + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/cmac.h + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/cterr.h + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/ecdsa.h + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/lhash.h + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/opensslconf.h + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/rand_drbg.h + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/srp.h + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/ts.h + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/asyncerr.h + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/cms.h + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/des.h + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/ecerr.h + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/md2.h + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/opensslv.h + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/randerr.h + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/srtp.h + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/tserr.h + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/bio.h + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/cmserr.h + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/dh.h + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/engine.h + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/md4.h + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/ossl_typ.h + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/rc2.h + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/ssl.h + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/txt_db.h + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/bioerr.h + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/comp.h + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/dherr.h + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/engineerr.h + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/md5.h + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/pem.h + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/rc4.h + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/ssl2.h + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/ui.h + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/blowfish.h + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/comperr.h + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/dsa.h + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/err.h + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/mdc2.h + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/pem2.h + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/rc5.h + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/ssl3.h + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/uierr.h + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/bn.h + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/conf.h + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/dsaerr.h + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/evp.h + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/modes.h + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/pemerr.h + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/ripemd.h + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/sslerr.h + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/include/openssl/whrlpool.h + DESTINATION ${LIBS_PREBUILT_DIR}/include/openssl + ) + file( + COPY + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/libcrypto.a + ${CMAKE_BINARY_DIR}/3p-openssl-1.1.1q.de53f55/openssl/libssl.a + DESTINATION ${LIBS_PREBUILT_DIR}/lib/release + ) + file(WRITE ${PREBUILD_TRACKING_DIR}/openssl_installed "${openssl_installed}") +endif (CMAKE_OSX_ARCHITECTURES MATCHES x86_64 OR LINUX OR NOT USESYSTEMLIBS) if (WINDOWS) target_link_libraries(ll::openssl INTERFACE libssl libcrypto) elseif (LINUX) diff --git a/indra/cmake/Prebuilt.cmake b/indra/cmake/Prebuilt.cmake index 634cc15c21..c7b628d370 100644 --- a/indra/cmake/Prebuilt.cmake +++ b/indra/cmake/Prebuilt.cmake @@ -40,6 +40,38 @@ macro (use_prebuilt_binary _binary) --install-dir=${AUTOBUILD_INSTALL_DIR} ${_binary} ") endif(DEBUG_PREBUILT) + if(USESYSTEMLIBS) + execute_process(COMMAND xmllint + --xpath + "//map/map/map/map/map/map/string[contains(text(),'${_binary}')][contains(text(),'common')]/text()" autobuild.xml + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/.. + OUTPUT_VARIABLE package_url + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + if ("${package_url}" STREQUAL "") + string(TOLOWER ${CMAKE_SYSTEM_NAME} system_name) + if (${system_name} MATCHES freebsd) + set(system_name "linux") + endif (${system_name} MATCHES freebsd) + execute_process(COMMAND xmllint + --xpath + "//map/map/map/map/map/map/string[contains(text(),'${_binary}')][contains(text(),'${system_name}64')]/text()" autobuild.xml + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/.. + OUTPUT_VARIABLE package_url + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + endif ("${package_url}" STREQUAL "") + string(REGEX REPLACE ^https://github.com/secondlife/3p-${_binary}/releases/download/[vm][0-9]+.*/ "" package_name ${package_url}) + file(DOWNLOAD + ${package_url} + ${CMAKE_BINARY_DIR}/${package_name} + ) + file(ARCHIVE_EXTRACT + INPUT ${CMAKE_BINARY_DIR}/${package_name} + DESTINATION ${AUTOBUILD_INSTALL_DIR} + ) + set(${_binary}_installed 0) + else(USESYSTEMLIBS) execute_process(COMMAND "${AUTOBUILD_EXECUTABLE}" install --install-dir=${AUTOBUILD_INSTALL_DIR} @@ -47,6 +79,7 @@ macro (use_prebuilt_binary _binary) WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}" RESULT_VARIABLE ${_binary}_installed ) + endif(USESYSTEMLIBS) file(WRITE ${PREBUILD_TRACKING_DIR}/${_binary}_installed "${${_binary}_installed}") endif(${PREBUILD_TRACKING_DIR}/sentinel_installed IS_NEWER_THAN ${PREBUILD_TRACKING_DIR}/${_binary}_installed OR NOT ${${_binary}_installed} EQUAL 0) @@ -67,6 +100,22 @@ macro ( use_system_binary package ) endif() endforeach() return() + elseif( NOT USE_AUTOBUILD_3P ) + include(FindPkgConfig) + pkg_check_modules(${package} ${package}) + if( ${package}_FOUND ) + target_link_directories( ll::${package} INTERFACE ${${package}_LIBRARY_DIRS} ) + else() + pkg_check_modules(${package} lib${package}) + if( ${package}_FOUND ) + target_link_directories( ll::${package} INTERFACE ${${package}_LIBRARY_DIRS} ) + else() + find_package( ${package} REQUIRED ) + endif() + endif() + target_include_directories( ll::${package} SYSTEM INTERFACE ${${package}_INCLUDE_DIRS} ) + target_link_libraries( ll::${package} INTERFACE ${${package}_LIBRARIES} ) + return() endif() endmacro() diff --git a/indra/cmake/UI.cmake b/indra/cmake/UI.cmake index 8f135676d6..a3423bb895 100644 --- a/indra/cmake/UI.cmake +++ b/indra/cmake/UI.cmake @@ -1,36 +1,36 @@ # -*- cmake -*- include(Prebuilt) include(FreeType) +include(GLIB) add_library( ll::uilibraries INTERFACE IMPORTED ) -if (LINUX) - target_compile_definitions(ll::uilibraries INTERFACE LL_GTK=1 LL_X11=1 ) +if (LINUX OR CMAKE_SYSTEM_NAME MATCHES "FreeBSD") + if (NOT USESYSTEMLIBS) + use_prebuilt_binary(fltk) + endif () + target_compile_definitions(ll::uilibraries INTERFACE LL_FLTK=1 LL_X11=1 ) if( USE_CONAN ) - target_link_libraries( ll::uilibraries INTERFACE CONAN_PKG::gtk ) return() endif() - use_prebuilt_binary(gtk-atk-pango-glib) target_link_libraries( ll::uilibraries INTERFACE - atk-1.0 - gdk-x11-2.0 - gdk_pixbuf-2.0 - Xinerama - glib-2.0 - gmodule-2.0 - gobject-2.0 - gthread-2.0 - gtk-x11-2.0 - pango-1.0 - pangoft2-1.0 - pangox-1.0 - pangoxft-1.0 + fltk + Xrender + Xcursor + Xfixes + Xext + Xft Xinerama + ll::fontconfig ll::freetype - ) -endif (LINUX) + ll::SDL + ll::glib + ll::gio + ) + +endif (LINUX OR CMAKE_SYSTEM_NAME MATCHES "FreeBSD") if( WINDOWS ) target_link_libraries( ll::uilibraries INTERFACE opengl32 @@ -48,7 +48,8 @@ if( WINDOWS ) ) endif() +if (NOT USESYSTEMLIBS) target_include_directories( ll::uilibraries SYSTEM INTERFACE ${LIBS_PREBUILT_DIR}/include ) - +endif () diff --git a/indra/cmake/UnixInstall.cmake b/indra/cmake/UnixInstall.cmake index 139be0a008..021700b374 100644 --- a/indra/cmake/UnixInstall.cmake +++ b/indra/cmake/UnixInstall.cmake @@ -6,11 +6,18 @@ set(INSTALL OFF CACHE BOOL "Generate install target.") if (INSTALL) + if (CMAKE_SYSTEM_NAME MATCHES FreeBSD) + set(INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX} CACHE PATH + "Top-level installation directory.") + else (CMAKE_SYSTEM_NAME MATCHES FreeBSD) set(INSTALL_PREFIX /usr CACHE PATH "Top-level installation directory.") + endif (CMAKE_SYSTEM_NAME MATCHES FreeBSD) if (EXISTS /lib64) set(_LIB lib64) + elseif (EXISTS ${CMAKE_SYSROOT}/usr/lib/${ARCH}-linux-gnu) + set(_LIB lib/${ARCH}-linux-gnu) else (EXISTS /lib64) set(_LIB lib) endif (EXISTS /lib64) @@ -25,7 +32,10 @@ if (INSTALL) CACHE PATH "Installation directory for binaries.") - set(APP_SHARE_DIR ${INSTALL_SHARE_DIR}/secondlife-${viewer_VERSION} + set(APP_SHARE_DIR ${INSTALL_SHARE_DIR}/${VIEWER_BINARY_NAME} CACHE PATH "Installation directory for read-only data files.") + set(APP_LIBEXEC_DIR ${INSTALL_PREFIX}/libexec/${VIEWER_BINARY_NAME} + CACHE PATH + "Installation directory for non-manual executables.") endif (INSTALL) diff --git a/indra/cmake/Variables.cmake b/indra/cmake/Variables.cmake index 5b3aeb8b7f..c287f135fe 100644 --- a/indra/cmake/Variables.cmake +++ b/indra/cmake/Variables.cmake @@ -101,12 +101,15 @@ else (ADDRESS_SIZE EQUAL 32) endif() endif (ADDRESS_SIZE EQUAL 32) +cmake_host_system_information(RESULT MAKE_JOBS QUERY NUMBER_OF_LOGICAL_CORES) + if (${CMAKE_SYSTEM_NAME} MATCHES "Windows") set(WINDOWS ON BOOL FORCE) endif (${CMAKE_SYSTEM_NAME} MATCHES "Windows") if (${CMAKE_SYSTEM_NAME} MATCHES "Linux") set(LINUX ON BOOl FORCE) + cmake_host_system_information(RESULT LINUX_DISTRO QUERY DISTRIB_ID) if (ADDRESS_SIZE EQUAL 32) set(DEB_ARCHITECTURE i386) @@ -117,7 +120,7 @@ if (${CMAKE_SYSTEM_NAME} MATCHES "Linux") set(FIND_LIBRARY_USE_LIB64_PATHS ON) endif (ADDRESS_SIZE EQUAL 32) - execute_process(COMMAND dpkg-architecture -a${DEB_ARCHITECTURE} -qDEB_HOST_MULTIARCH + execute_process(COMMAND dpkg-architecture -a${DEB_ARCHITECTURE} -qDEB_HOST_MULTIARCH RESULT_VARIABLE DPKG_RESULT OUTPUT_VARIABLE DPKG_ARCH OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET) @@ -127,8 +130,6 @@ if (${CMAKE_SYSTEM_NAME} MATCHES "Linux") set(CMAKE_SYSTEM_LIBRARY_PATH /usr/lib/${DPKG_ARCH} /usr/local/lib/${DPKG_ARCH} ${CMAKE_SYSTEM_LIBRARY_PATH}) endif (DPKG_RESULT EQUAL 0) - include(ConfigurePkgConfig) - if (INSTALL_PROPRIETARY) # Only turn on headless if we can find osmesa libraries. include(FindPkgConfig) @@ -204,7 +205,7 @@ if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") set(CMAKE_XCODE_ATTRIBUTE_CODE_SIGN_ENTITLEMENTS "") set(CMAKE_XCODE_ATTRIBUTE_DISABLE_MANUAL_TARGET_ORDER_BUILD_WARNING YES) set(CMAKE_XCODE_ATTRIBUTE_GCC_WARN_64_TO_32_BIT_CONVERSION NO) - set(CMAKE_OSX_ARCHITECTURES "${ARCH}") + #set(CMAKE_OSX_ARCHITECTURES "${ARCH}") string(REPLACE "i686" "i386" CMAKE_OSX_ARCHITECTURES "${CMAKE_OSX_ARCHITECTURES}") string(REPLACE "AMD64" "x86_64" CMAKE_OSX_ARCHITECTURES "${CMAKE_OSX_ARCHITECTURES}") endif (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") diff --git a/indra/cmake/ViewerMiscLibs.cmake b/indra/cmake/ViewerMiscLibs.cmake index cae68fbc11..4df54e2b59 100644 --- a/indra/cmake/ViewerMiscLibs.cmake +++ b/indra/cmake/ViewerMiscLibs.cmake @@ -1,23 +1,48 @@ # -*- cmake -*- include(Prebuilt) -if (LINUX) - #use_prebuilt_binary(libuuid) +if (NOT DARWIN) add_library( ll::fontconfig INTERFACE IMPORTED ) - if( NOT USE_CONAN ) - use_prebuilt_binary(fontconfig) - else() - target_link_libraries( ll::fontconfig INTERFACE CONAN_PKG::fontconfig ) - endif() -endif (LINUX) + find_package(Fontconfig REQUIRED) + target_link_libraries( ll::fontconfig INTERFACE Fontconfig::Fontconfig ) +endif (NOT DARWIN) -if( NOT USE_CONAN ) +if( USE_AUTOBUILD_3P ) use_prebuilt_binary(libhunspell) endif() +if (NOT USESYSTEMLIBS) use_prebuilt_binary(slvoice) use_prebuilt_binary(nanosvg) +elseif (${LINUX_DISTRO} MATCHES debian OR DARWIN) + if (${PREBUILD_TRACKING_DIR}/sentinel_installed IS_NEWER_THAN ${PREBUILD_TRACKING_DIR}/nanosvg_installed OR NOT ${nanosvg_installed} EQUAL 0) + if (DARWIN) + if (NOT EXISTS ${CMAKE_BINARY_DIR}/nanosvg-2022.09.27-darwin64-580364.tar.bz2) + file(DOWNLOAD + https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/115452/994130/nanosvg-2022.09.27-darwin64-580364.tar.bz2 + ${CMAKE_BINARY_DIR}/nanosvg-2022.09.27-darwin64-580364.tar.bz2 + ) + endif (NOT EXISTS ${CMAKE_BINARY_DIR}/nanosvg-2022.09.27-darwin64-580364.tar.bz2) + file(ARCHIVE_EXTRACT + INPUT ${CMAKE_BINARY_DIR}/nanosvg-2022.09.27-darwin64-580364.tar.bz2 + DESTINATION ${LIBS_PREBUILT_DIR} + ) + else (DARWIN) + if (NOT EXISTS ${CMAKE_BINARY_DIR}/nanosvg-2022.09.27-linux-580337.tar.bz2) + file(DOWNLOAD + https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/115397/993664/nanosvg-2022.09.27-linux-580337.tar.bz2 + ${CMAKE_BINARY_DIR}/nanosvg-2022.09.27-linux-580337.tar.bz2 + ) + endif (NOT EXISTS ${CMAKE_BINARY_DIR}/nanosvg-2022.09.27-linux-580337.tar.bz2) + file(ARCHIVE_EXTRACT + INPUT ${CMAKE_BINARY_DIR}/nanosvg-2022.09.27-linux-580337.tar.bz2 + DESTINATION ${LIBS_PREBUILT_DIR} + ) + endif (DARWIN) + file(WRITE ${PREBUILD_TRACKING_DIR}/nanosvg_installed "0") + endif (${PREBUILD_TRACKING_DIR}/sentinel_installed IS_NEWER_THAN ${PREBUILD_TRACKING_DIR}/nanosvg_installed OR NOT ${nanosvg_installed} EQUAL 0) +endif (NOT USESYSTEMLIBS) use_prebuilt_binary(viewer-fonts) use_prebuilt_binary(emoji_shortcodes) diff --git a/indra/cmake/VulkanGltf.cmake b/indra/cmake/VulkanGltf.cmake index 94541d5307..d7083a33c9 100644 --- a/indra/cmake/VulkanGltf.cmake +++ b/indra/cmake/VulkanGltf.cmake @@ -1,5 +1,7 @@ # -*- cmake -*- include(Prebuilt) +if (NOT USESYSTEMLIBS) use_prebuilt_binary(vulkan_gltf) +endif () diff --git a/indra/cmake/WebRTC.cmake b/indra/cmake/WebRTC.cmake index 230522a40a..030d3f4919 100644 --- a/indra/cmake/WebRTC.cmake +++ b/indra/cmake/WebRTC.cmake @@ -6,7 +6,34 @@ include_guard() add_library( ll::webrtc INTERFACE IMPORTED ) target_include_directories( ll::webrtc SYSTEM INTERFACE "${LIBS_PREBUILT_DIR}/include/webrtc" "${LIBS_PREBUILT_DIR}/include/webrtc/third_party/abseil-cpp") +if (CMAKE_OSX_ARCHITECTURES MATCHES arm64) + if (${PREBUILD_TRACKING_DIR}/sentinel_installed IS_NEWER_THAN ${PREBUILD_TRACKING_DIR}/webrtc_installed OR NOT ${webrtc_installed} EQUAL 0) + if (NOT EXISTS ${CMAKE_BINARY_DIR}/libwebrtc-macos-arm64.tar.xz) + file(DOWNLOAD + https://github.com/crow-misia/libwebrtc-bin/releases/download/114.5735.6.1/libwebrtc-macos-arm64.tar.xz + ${CMAKE_BINARY_DIR}/libwebrtc-macos-arm64.tar.xz + SHOW_PROGRESS + ) + endif (NOT EXISTS ${CMAKE_BINARY_DIR}/libwebrtc-macos-arm64.tar.xz) + file(ARCHIVE_EXTRACT + INPUT ${CMAKE_BINARY_DIR}/libwebrtc-macos-arm64.tar.xz + DESTINATION ${LIBS_PREBUILT_DIR} + ) + file(RENAME + ${LIBS_PREBUILT_DIR}/lib/libwebrtc.a + ${LIBS_PREBUILT_DIR}/lib/release/libwebrtc.a + ) + file(REMOVE_RECURSE ${LIBS_PREBUILT_DIR}/lib/release/WebRTC.framework) + file(RENAME + ${LIBS_PREBUILT_DIR}/Frameworks/WebRTC.xcframework/macos-arm64/WebRTC.framework + ${LIBS_PREBUILT_DIR}/lib/release/WebRTC.framework + ) + file(REMOVE_RECURSE ${LIBS_PREBUILT_DIR}/Frameworks) + file(WRITE ${PREBUILD_TRACKING_DIR}/webrtc_installed "0") + endif (${PREBUILD_TRACKING_DIR}/sentinel_installed IS_NEWER_THAN ${PREBUILD_TRACKING_DIR}/webrtc_installed OR NOT ${webrtc_installed} EQUAL 0) +elseif (NOT CMAKE_SYSTEM_NAME MATCHES FreeBSD) use_prebuilt_binary(webrtc) +endif (CMAKE_OSX_ARCHITECTURES MATCHES arm64) if (WINDOWS) target_link_libraries( ll::webrtc INTERFACE webrtc.lib ) diff --git a/indra/cmake/XmlRpcEpi.cmake b/indra/cmake/XmlRpcEpi.cmake index 6409f9d6e2..739648500c 100644 --- a/indra/cmake/XmlRpcEpi.cmake +++ b/indra/cmake/XmlRpcEpi.cmake @@ -4,8 +4,92 @@ include(Prebuilt) include_guard() add_library( ll::xmlrpc-epi INTERFACE IMPORTED ) +if (NOT USESYSTEMLIBS) use_system_binary( xmlrpc-epi ) use_prebuilt_binary(xmlrpc-epi) +elseif ((${LINUX_DISTRO} MATCHES opensuse-tumbleweed OR DARWIN) AND (${PREBUILD_TRACKING_DIR}/sentinel_installed IS_NEWER_THAN ${PREBUILD_TRACKING_DIR}/xmlrpc-epi_installed OR NOT ${xmlrpc-epi_installed} EQUAL 0)) + if (NOT EXISTS ${CMAKE_BINARY_DIR}/xmlrpc-epi-0.54.2.tar.bz2) + file(DOWNLOAD + https://sourceforge.net/projects/xmlrpc-epi/files/xmlrpc-epi-base/0.54.2/xmlrpc-epi-0.54.2.tar.bz2 + ${CMAKE_BINARY_DIR}/xmlrpc-epi-0.54.2.tar.bz2 + ) + endif (NOT EXISTS ${CMAKE_BINARY_DIR}/xmlrpc-epi-0.54.2.tar.bz2) + file(ARCHIVE_EXTRACT + INPUT ${CMAKE_BINARY_DIR}/xmlrpc-epi-0.54.2.tar.bz2 + DESTINATION ${CMAKE_BINARY_DIR} + ) + file( + COPY + ${CMAKE_BINARY_DIR}/xmlrpc-epi-0.54.2/src/base64.h + ${CMAKE_BINARY_DIR}/xmlrpc-epi-0.54.2/src/encodings.h + ${CMAKE_BINARY_DIR}/xmlrpc-epi-0.54.2/src/queue.h + ${CMAKE_BINARY_DIR}/xmlrpc-epi-0.54.2/src/simplestring.h + ${CMAKE_BINARY_DIR}/xmlrpc-epi-0.54.2/src/xml_element.h + ${CMAKE_BINARY_DIR}/xmlrpc-epi-0.54.2/src/xml_to_xmlrpc.h + ${CMAKE_BINARY_DIR}/xmlrpc-epi-0.54.2/src/xmlrpc.h + ${CMAKE_BINARY_DIR}/xmlrpc-epi-0.54.2/src/xmlrpc_introspection.h + DESTINATION ${LIBS_PREBUILT_DIR}/include/xmlrpc-epi + ) + file(REMOVE + ${CMAKE_BINARY_DIR}/xmlrpc-epi-0.54.2/config.sub + ${CMAKE_BINARY_DIR}/xmlrpc-epi-0.54.2/missing + ) + execute_process( + COMMAND autoreconf -is + WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/xmlrpc-epi-0.54.2 + ) + set(ENV{CPPFLAGS} -I${CMAKE_BINARY_DIR}/xmlrpc-epi-0.54.2/src) + if (DARWIN) + set(ENV{CFLAGS} "-arch ${CMAKE_OSX_ARCHITECTURES} -mmacosx-version-min=10.15") + if (CMAKE_OSX_ARCHITECTURES MATCHES arm64) + execute_process( + COMMAND sed -i '' -e "s/XMLRPC_VALUE find_named_value/__attribute__((always_inline)) XMLRPC_VALUE find_named_value/g" + xmlrpc_introspection.c + WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/xmlrpc-epi-0.54.2/src + ) + execute_process( + COMMAND sed -i '' -e "s/void describe_method/__attribute__((always_inline)) void describe_method/g" + xmlrpc_introspection.c + WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/xmlrpc-epi-0.54.2/src + ) + execute_process( + COMMAND ./configure --disable-static --host=aarch64-apple-darwin + WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/xmlrpc-epi-0.54.2 + ) + else (CMAKE_OSX_ARCHITECTURES MATCHES arm64) + execute_process( + COMMAND ./configure --disable-static --host=${CMAKE_OSX_ARCHITECTURES}-apple-darwin + WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/xmlrpc-epi-0.54.2 + ) + endif (CMAKE_OSX_ARCHITECTURES MATCHES arm64) + unset(ENV{CFLAGS}) + else (DARWIN) + execute_process( + COMMAND ./configure --disable-shared + WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/xmlrpc-epi-0.54.2 + ) + endif (DARWIN) + execute_process( + COMMAND make -j${MAKE_JOBS} + WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/xmlrpc-epi-0.54.2 + RESULT_VARIABLE xmlrpc-epi_installed + ) + unset(ENV{CPPFLAGS}) + file( + COPY + ${CMAKE_BINARY_DIR}/xmlrpc-epi-0.54.2/src/.libs/libxmlrpc-epi.dylib + ${CMAKE_BINARY_DIR}/xmlrpc-epi-0.54.2/src/.libs/libxmlrpc-epi.0.dylib + DESTINATION ${LIBS_PREBUILT_DIR}/lib/release + FOLLOW_SYMLINK_CHAIN + ) + file(WRITE ${PREBUILD_TRACKING_DIR}/xmlrpc-epi_installed "${xmlrpc-epi_installed}") +endif (NOT USESYSTEMLIBS) target_link_libraries(ll::xmlrpc-epi INTERFACE xmlrpc-epi ) +if (NOT USESYSTEMLIBS) target_include_directories( ll::xmlrpc-epi SYSTEM INTERFACE ${LIBS_PREBUILT_DIR}/include) +elseif (${LINUX_DISTRO} MATCHES opensuse-tumbleweed OR DARWIN) + target_include_directories( ll::xmlrpc-epi SYSTEM INTERFACE ${LIBS_PREBUILT_DIR}/include/xmlrpc-epi) +elseif (LINUX) + target_include_directories( ll::xmlrpc-epi SYSTEM INTERFACE ${CMAKE_SYSROOT}/usr/include/xmlrpc-epi) +endif () diff --git a/indra/cmake/ZLIBNG.cmake b/indra/cmake/ZLIBNG.cmake index 5d99cd9709..60164116dd 100644 --- a/indra/cmake/ZLIBNG.cmake +++ b/indra/cmake/ZLIBNG.cmake @@ -8,6 +8,12 @@ add_library( ll::zlib-ng INTERFACE IMPORTED ) if(USE_CONAN ) target_link_libraries( ll::zlib-ng INTERFACE CONAN_PKG::zlib ) return() +elseif(NOT USE_AUTOBUILD_3P) + pkg_check_modules(Zlib REQUIRED zlib) + target_include_directories( ll::zlib-ng SYSTEM INTERFACE ${Zlib_INCLUDE_DIRS}) + target_link_directories( ll::zlib-ng INTERFACE ${Zlib_LIBRARY_DIRS} ) + target_link_libraries( ll::zlib-ng INTERFACE ${Zlib_LIBRARIES}) + return() endif() use_prebuilt_binary(zlib-ng) diff --git a/indra/cmake/xxHash.cmake b/indra/cmake/xxHash.cmake index a7c1cba62c..2dcab005ba 100644 --- a/indra/cmake/xxHash.cmake +++ b/indra/cmake/xxHash.cmake @@ -5,4 +5,11 @@ endif (XXHASH_CMAKE_INCLUDED) set (XXHASH_CMAKE_INCLUDED TRUE) include(Prebuilt) + +if (NOT (USE_AUTOBUILD_3P OR USE_CONAN)) + include(FindPkgConfig) + pkg_check_modules(Xxhash REQUIRED libxxhash) + return () +endif () + use_prebuilt_binary(xxhash) diff --git a/indra/linux_crash_logger/llcrashloggerlinux.cpp b/indra/linux_crash_logger/llcrashloggerlinux.cpp index 9b40de741e..7992f59b36 100644 --- a/indra/linux_crash_logger/llcrashloggerlinux.cpp +++ b/indra/linux_crash_logger/llcrashloggerlinux.cpp @@ -38,9 +38,6 @@ #include "lldir.h" #include "llsdserialize.h" -#if LL_GTK -# include "gtk/gtk.h" -#endif // LL_GTK #define MAX_LOADSTRING 100 @@ -54,52 +51,9 @@ static const char dialog_text[] = static const char dialog_title[] = "Second Life Crash Logger"; -#if LL_GTK -static void response_callback (GtkDialog *dialog, - gint arg1, - gpointer user_data) -{ - gint *response = (gint*)user_data; - *response = arg1; - gtk_widget_destroy(GTK_WIDGET(dialog)); - gtk_main_quit(); -} -#endif // LL_GTK - static BOOL do_ask_dialog(void) { -#if LL_GTK - gtk_disable_setlocale(); - if (!gtk_init_check(NULL, NULL)) { - LL_INFOS() << "Could not initialize GTK for 'ask to send crash report' dialog; not sending report." << LL_ENDL; - return FALSE; - } - - GtkWidget *win = NULL; - GtkDialogFlags flags = GTK_DIALOG_MODAL; - GtkMessageType messagetype = GTK_MESSAGE_QUESTION; - GtkButtonsType buttons = GTK_BUTTONS_YES_NO; - gint response = GTK_RESPONSE_NONE; - - win = gtk_message_dialog_new(NULL, - flags, messagetype, buttons, - "%s", dialog_text); - gtk_window_set_type_hint(GTK_WINDOW(win), - GDK_WINDOW_TYPE_HINT_DIALOG); - gtk_window_set_title(GTK_WINDOW(win), dialog_title); - g_signal_connect (win, - "response", - G_CALLBACK (response_callback), - &response); - gtk_widget_show_all (win); - gtk_main(); - - return (GTK_RESPONSE_OK == response || - GTK_RESPONSE_YES == response || - GTK_RESPONSE_APPLY == response); -#else - return FALSE; -#endif // LL_GTK + // Ask to send crash report. Yes/No dialog. } LLCrashLoggerLinux::LLCrashLoggerLinux(void) diff --git a/indra/llappearance/CMakeLists.txt b/indra/llappearance/CMakeLists.txt index c3be8bc78e..f3f822f61c 100644 --- a/indra/llappearance/CMakeLists.txt +++ b/indra/llappearance/CMakeLists.txt @@ -84,3 +84,5 @@ if (BUILD_HEADLESS) llcommon ) endif (BUILD_HEADLESS) + +include(LibraryInstall) diff --git a/indra/llappearance/llpolymesh.cpp b/indra/llappearance/llpolymesh.cpp index 97f9ca68b6..719381b4fc 100644 --- a/indra/llappearance/llpolymesh.cpp +++ b/indra/llappearance/llpolymesh.cpp @@ -981,7 +981,7 @@ void LLPolyMesh::initializeForMorph() LLVector4a::memcpyNonAliased16((F32*) mScaledNormals, (F32*) mSharedData->mBaseNormals, sizeof(LLVector4a) * mSharedData->mNumVertices); LLVector4a::memcpyNonAliased16((F32*) mBinormals, (F32*) mSharedData->mBaseNormals, sizeof(LLVector4a) * mSharedData->mNumVertices); LLVector4a::memcpyNonAliased16((F32*) mScaledBinormals, (F32*) mSharedData->mBaseNormals, sizeof(LLVector4a) * mSharedData->mNumVertices); - LLVector4a::memcpyNonAliased16((F32*) mTexCoords, (F32*) mSharedData->mTexCoords, sizeof(LLVector2) * (mSharedData->mNumVertices + mSharedData->mNumVertices%2)); + memcpy((F32*) mTexCoords, (F32*) mSharedData->mTexCoords, sizeof(LLVector2) * (mSharedData->mNumVertices)); // allocated in LLPolyMeshSharedData::allocateVertexData for (S32 i = 0; i < mSharedData->mNumVertices; ++i) { diff --git a/indra/llappearance/lltexlayer.cpp b/indra/llappearance/lltexlayer.cpp index d376c68c7f..27656c8302 100644 --- a/indra/llappearance/lltexlayer.cpp +++ b/indra/llappearance/lltexlayer.cpp @@ -1443,7 +1443,9 @@ void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, 0); } +#if GL_VERSION_1_1 glGetTexImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_RGBA, GL_UNSIGNED_BYTE, temp); +#endif U8* alpha_cursor = alpha_data; U8* pixel = temp; diff --git a/indra/llaudio/CMakeLists.txt b/indra/llaudio/CMakeLists.txt index 9278d3c488..f36da83c69 100644 --- a/indra/llaudio/CMakeLists.txt +++ b/indra/llaudio/CMakeLists.txt @@ -4,6 +4,7 @@ project(llaudio) include(00-Common) include(LLAudio) +include(FMODSTUDIO) include(OPENAL) include(LLCommon) @@ -24,6 +25,20 @@ set(llaudio_HEADER_FILES llwindgen.h ) +if (TARGET ll::fmodstudio) + list(APPEND llaudio_SOURCE_FILES + llaudioengine_fmodstudio.cpp + lllistener_fmodstudio.cpp + llstreamingaudio_fmodstudio.cpp + ) + + list(APPEND llaudio_HEADER_FILES + llaudioengine_fmodstudio.h + lllistener_fmodstudio.h + llstreamingaudio_fmodstudio.h + ) +endif () + if (TARGET ll::openal) list(APPEND llaudio_SOURCE_FILES llaudioengine_openal.cpp @@ -54,3 +69,5 @@ endif() if( TARGET ll::fmodstudio ) target_link_libraries( llaudio ll::fmodstudio ) endif() + +include(LibraryInstall) diff --git a/indra/llaudio/llaudioengine_fmodstudio.cpp b/indra/llaudio/llaudioengine_fmodstudio.cpp new file mode 100644 index 0000000000..b4e8407083 --- /dev/null +++ b/indra/llaudio/llaudioengine_fmodstudio.cpp @@ -0,0 +1,756 @@ +/** + * @file audioengine_fmodstudio.cpp + * @brief Implementation of LLAudioEngine class abstracting the audio + * support as a FMODSTUDIO implementation + * + * $LicenseInfo:firstyear=2020&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2020, 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 "linden_common.h" + +#include "llstreamingaudio.h" +#include "llstreamingaudio_fmodstudio.h" + +#include "llaudioengine_fmodstudio.h" +#include "lllistener_fmodstudio.h" + +#include "llerror.h" +#include "llmath.h" +#include "llrand.h" + +#include "fmodstudio/fmod.hpp" +#include "fmodstudio/fmod_errors.h" +#include "lldir.h" +#include "llapr.h" + +#include "sound_ids.h" + +FMOD_RESULT F_CALLBACK windCallback(FMOD_DSP_STATE *dsp_state, float *inbuffer, float *outbuffer, unsigned int length, int inchannels, int *outchannels); + +FMOD::ChannelGroup *LLAudioEngine_FMODSTUDIO::mChannelGroups[LLAudioEngine::AUDIO_TYPE_COUNT] = {0}; + +LLAudioEngine_FMODSTUDIO::LLAudioEngine_FMODSTUDIO(bool enable_profiler) +: mInited(false), + mWindGen(NULL), + mWindDSP(NULL), + mSystem(NULL), + mEnableProfiler(enable_profiler), + mWindDSPDesc(NULL) +{ +} + + +LLAudioEngine_FMODSTUDIO::~LLAudioEngine_FMODSTUDIO() +{ + // mWindDSPDesc, mWindGen and mWindDSP get cleaned up on cleanupWind in LLAudioEngine::shutdown() + // mSystem gets cleaned up at shutdown() +} + + +static inline bool Check_FMOD_Error(FMOD_RESULT result, const char *string) +{ + if (result == FMOD_OK) + return false; + LL_DEBUGS("FMOD") << string << " Error: " << FMOD_ErrorString(result) << LL_ENDL; + return true; +} + +bool LLAudioEngine_FMODSTUDIO::init(void* userdata, const std::string &app_title) +{ + U32 version; + FMOD_RESULT result; + + LL_DEBUGS("AppInit") << "LLAudioEngine_FMODSTUDIO::init() initializing FMOD" << LL_ENDL; + + result = FMOD::System_Create(&mSystem); + if (Check_FMOD_Error(result, "FMOD::System_Create")) + return false; + + //will call LLAudioEngine_FMODSTUDIO::allocateListener, which needs a valid mSystem pointer. + LLAudioEngine::init(userdata, app_title); + + result = mSystem->getVersion(&version); + Check_FMOD_Error(result, "FMOD::System::getVersion"); + + if (version < FMOD_VERSION) + { + LL_WARNS("AppInit") << "FMOD Studio version mismatch, actual: " << version + << " expected:" << FMOD_VERSION << LL_ENDL; + } + + // In this case, all sounds, PLUS wind and stream will be software. + result = mSystem->setSoftwareChannels(LL_MAX_AUDIO_CHANNELS + 2); + Check_FMOD_Error(result, "FMOD::System::setSoftwareChannels"); + + FMOD_ADVANCEDSETTINGS settings; + memset(&settings, 0, sizeof(settings)); + settings.cbSize = sizeof(FMOD_ADVANCEDSETTINGS); + settings.resamplerMethod = FMOD_DSP_RESAMPLER_LINEAR; + + result = mSystem->setAdvancedSettings(&settings); + Check_FMOD_Error(result, "FMOD::System::setAdvancedSettings"); + + // FMOD_INIT_THREAD_UNSAFE Disables thread safety for API calls. + // Only use this if FMOD is being called from a single thread, and if Studio API is not being used. + U32 fmod_flags = FMOD_INIT_NORMAL | FMOD_INIT_3D_RIGHTHANDED | FMOD_INIT_THREAD_UNSAFE; + if (mEnableProfiler) + { + fmod_flags |= FMOD_INIT_PROFILE_ENABLE; + } + +#if LL_LINUX + bool audio_ok = false; + + if (!audio_ok) + { + const char* env_string = getenv("LL_BAD_FMOD_PULSEAUDIO"); + if (NULL == env_string) + { + LL_DEBUGS("AppInit") << "Trying PulseAudio audio output..." << LL_ENDL; + if (mSystem->setOutput(FMOD_OUTPUTTYPE_PULSEAUDIO) == FMOD_OK && + (result = mSystem->init(LL_MAX_AUDIO_CHANNELS + 2, fmod_flags, const_cast<char*>(app_title.c_str()))) == FMOD_OK) + { + LL_DEBUGS("AppInit") << "PulseAudio output initialized OKAY" << LL_ENDL; + audio_ok = true; + } + else + { + Check_FMOD_Error(result, "PulseAudio audio output FAILED to initialize"); + } + } + else + { + LL_DEBUGS("AppInit") << "PulseAudio audio output SKIPPED" << LL_ENDL; + } + } + if (!audio_ok) + { + const char* env_string = getenv("LL_BAD_FMOD_ALSA"); + if (NULL == env_string) + { + LL_DEBUGS("AppInit") << "Trying ALSA audio output..." << LL_ENDL; + if (mSystem->setOutput(FMOD_OUTPUTTYPE_ALSA) == FMOD_OK && + (result = mSystem->init(LL_MAX_AUDIO_CHANNELS + 2, fmod_flags, 0)) == FMOD_OK) + { + LL_DEBUGS("AppInit") << "ALSA audio output initialized OKAY" << LL_ENDL; + audio_ok = true; + } + else + { + Check_FMOD_Error(result, "ALSA audio output FAILED to initialize"); + } + } + else + { + LL_DEBUGS("AppInit") << "ALSA audio output SKIPPED" << LL_ENDL; + } + } + if (!audio_ok) + { + LL_WARNS("AppInit") << "Overall audio init failure." << LL_ENDL; + return false; + } + + // We're interested in logging which output method we + // ended up with, for QA purposes. + FMOD_OUTPUTTYPE output_type; + mSystem->getOutput(&output_type); + switch (output_type) + { + case FMOD_OUTPUTTYPE_NOSOUND: + LL_INFOS("AppInit") << "Audio output: NoSound" << LL_ENDL; break; + case FMOD_OUTPUTTYPE_PULSEAUDIO: + LL_INFOS("AppInit") << "Audio output: PulseAudio" << LL_ENDL; break; + case FMOD_OUTPUTTYPE_ALSA: + LL_INFOS("AppInit") << "Audio output: ALSA" << LL_ENDL; break; + default: + LL_INFOS("AppInit") << "Audio output: Unknown!" << LL_ENDL; break; + }; +#else // LL_LINUX + + // initialize the FMOD engine + // number of channel in this case looks to be identiacal to number of max simultaneously + // playing objects and we can set practically any number + result = mSystem->init(LL_MAX_AUDIO_CHANNELS + 2, fmod_flags, 0); + if (Check_FMOD_Error(result, "Error initializing FMOD Studio with default settins, retrying with other format")) + { + result = mSystem->setSoftwareFormat(44100, FMOD_SPEAKERMODE_STEREO, 0/*- ignore*/); + if (Check_FMOD_Error(result, "Error setting sotware format. Can't init.")) + { + return false; + } + result = mSystem->init(LL_MAX_AUDIO_CHANNELS + 2, fmod_flags, 0); + } + if (Check_FMOD_Error(result, "Error initializing FMOD Studio")) + { + // If it fails here and (result == FMOD_ERR_OUTPUT_CREATEBUFFER), + // we can retry with other settings + return false; + } +#endif + + LL_INFOS("AppInit") << "LLAudioEngine_FMODSTUDIO::init() FMOD Studio initialized correctly" << LL_ENDL; + + int r_numbuffers, r_samplerate, r_channels; + unsigned int r_bufferlength; + char r_name[512]; + int latency = 100; + mSystem->getDSPBufferSize(&r_bufferlength, &r_numbuffers); + LL_INFOS("AppInit") << "LLAudioEngine_FMODSTUDIO::init(): r_bufferlength=" << r_bufferlength << " bytes" << LL_ENDL; + LL_INFOS("AppInit") << "LLAudioEngine_FMODSTUDIO::init(): r_numbuffers=" << r_numbuffers << LL_ENDL; + + mSystem->getDriverInfo(0, r_name, 511, NULL, &r_samplerate, NULL, &r_channels); + r_name[511] = '\0'; + LL_INFOS("AppInit") << "LLAudioEngine_FMODSTUDIO::init(): r_name=\"" << r_name << "\"" << LL_ENDL; + + if (r_samplerate != 0) + latency = (int)(1000.0f * r_bufferlength * r_numbuffers / r_samplerate); + LL_INFOS("AppInit") << "LLAudioEngine_FMODSTUDIO::init(): latency=" << latency << "ms" << LL_ENDL; + + mInited = true; + + LL_INFOS("AppInit") << "LLAudioEngine_FMODSTUDIO::init(): initialization complete." << LL_ENDL; + + return true; +} + + +std::string LLAudioEngine_FMODSTUDIO::getDriverName(bool verbose) +{ + llassert_always(mSystem); + if (verbose) + { + U32 version; + if (!Check_FMOD_Error(mSystem->getVersion(&version), "FMOD::System::getVersion")) + { + return llformat("FMOD Studio %1x.%02x.%02x (Firelight Technologies Pty Ltd)", version >> 16, version >> 8 & 0x000000FF, version & 0x000000FF); + } + } + return "FMOD STUDIO"; +} + + +// create our favourite FMOD-native streaming audio implementation +LLStreamingAudioInterface *LLAudioEngine_FMODSTUDIO::createDefaultStreamingAudioImpl() const +{ + return new LLStreamingAudio_FMODSTUDIO(mSystem); +} + + +void LLAudioEngine_FMODSTUDIO::allocateListener(void) +{ + mListenerp = (LLListener *) new LLListener_FMODSTUDIO(mSystem); + if (!mListenerp) + { + LL_WARNS("FMOD") << "Listener creation failed" << LL_ENDL; + } +} + + +void LLAudioEngine_FMODSTUDIO::shutdown() +{ + stopInternetStream(); + + LL_INFOS("FMOD") << "About to LLAudioEngine::shutdown()" << LL_ENDL; + LLAudioEngine::shutdown(); + + LL_INFOS("FMOD") << "LLAudioEngine_FMODSTUDIO::shutdown() closing FMOD Studio" << LL_ENDL; + if (mSystem) + { + mSystem->close(); + mSystem->release(); + } + LL_INFOS("FMOD") << "LLAudioEngine_FMODSTUDIO::shutdown() done closing FMOD Studio" << LL_ENDL; + + delete mListenerp; + mListenerp = NULL; +} + + +LLAudioBuffer * LLAudioEngine_FMODSTUDIO::createBuffer() +{ + return new LLAudioBufferFMODSTUDIO(mSystem); +} + + +LLAudioChannel * LLAudioEngine_FMODSTUDIO::createChannel() +{ + return new LLAudioChannelFMODSTUDIO(mSystem); +} + +bool LLAudioEngine_FMODSTUDIO::initWind() +{ + mNextWindUpdate = 0.0; + + if (!mWindDSPDesc) + { + mWindDSPDesc = new FMOD_DSP_DESCRIPTION(); + } + + if (!mWindDSP) + { + memset(mWindDSPDesc, 0, sizeof(*mWindDSPDesc)); //Set everything to zero + strncpy(mWindDSPDesc->name, "Wind Unit", sizeof(mWindDSPDesc->name)); + mWindDSPDesc->pluginsdkversion = FMOD_PLUGIN_SDK_VERSION; + mWindDSPDesc->read = &windCallback; // Assign callback - may be called from arbitrary threads + if (Check_FMOD_Error(mSystem->createDSP(mWindDSPDesc, &mWindDSP), "FMOD::createDSP")) + return false; + + if (mWindGen) + delete mWindGen; + + int frequency = 44100; + + FMOD_SPEAKERMODE mode; + if (Check_FMOD_Error(mSystem->getSoftwareFormat(&frequency, &mode, nullptr), "FMOD::System::getSoftwareFormat")) + { + cleanupWind(); + return false; + } + + mWindGen = new LLWindGen<MIXBUFFERFORMAT>((U32)frequency); + + if (Check_FMOD_Error(mWindDSP->setUserData((void*)mWindGen), "FMOD::DSP::setUserData")) + { + cleanupWind(); + return false; + } + if (Check_FMOD_Error(mWindDSP->setChannelFormat(FMOD_CHANNELMASK_STEREO, 2, mode), "FMOD::DSP::setChannelFormat")) + { + cleanupWind(); + return false; + } + } + + // *TODO: Should this guard against multiple plays? + if (Check_FMOD_Error(mSystem->playDSP(mWindDSP, nullptr, false, nullptr), "FMOD::System::playDSP")) + { + cleanupWind(); + return false; + } + return true; +} + + +void LLAudioEngine_FMODSTUDIO::cleanupWind() +{ + if (mWindDSP) + { + FMOD::ChannelGroup* master_group = NULL; + if (!Check_FMOD_Error(mSystem->getMasterChannelGroup(&master_group), "FMOD::System::getMasterChannelGroup") + && master_group) + { + master_group->removeDSP(mWindDSP); + } + mWindDSP->release(); + mWindDSP = NULL; + } + + delete mWindDSPDesc; + mWindDSPDesc = NULL; + + delete mWindGen; + mWindGen = NULL; +} + + +//----------------------------------------------------------------------- +void LLAudioEngine_FMODSTUDIO::updateWind(LLVector3 wind_vec, F32 camera_height_above_water) +{ + LLVector3 wind_pos; + F64 pitch; + F64 center_freq; + + if (!mEnableWind) + { + return; + } + + if (mWindUpdateTimer.checkExpirationAndReset(LL_WIND_UPDATE_INTERVAL)) + { + + // wind comes in as Linden coordinate (+X = forward, +Y = left, +Z = up) + // need to convert this to the conventional orientation DS3D and OpenAL use + // where +X = right, +Y = up, +Z = backwards + + wind_vec.setVec(-wind_vec.mV[1], wind_vec.mV[2], -wind_vec.mV[0]); + + // cerr << "Wind update" << endl; + + pitch = 1.0 + mapWindVecToPitch(wind_vec); + center_freq = 80.0 * pow(pitch, 2.5*(mapWindVecToGain(wind_vec) + 1.0)); + + mWindGen->mTargetFreq = (F32)center_freq; + mWindGen->mTargetGain = (F32)mapWindVecToGain(wind_vec) * mMaxWindGain; + mWindGen->mTargetPanGainR = (F32)mapWindVecToPan(wind_vec); + } +} + +//----------------------------------------------------------------------- +void LLAudioEngine_FMODSTUDIO::setInternalGain(F32 gain) +{ + if (!mInited) + { + return; + } + + gain = llclamp(gain, 0.0f, 1.0f); + + FMOD::ChannelGroup* master_group = NULL; + if (!Check_FMOD_Error(mSystem->getMasterChannelGroup(&master_group), "FMOD::System::getMasterChannelGroup") + && master_group) + { + master_group->setVolume(gain); + } + + LLStreamingAudioInterface *saimpl = getStreamingAudioImpl(); + if (saimpl) + { + // fmod likes its streaming audio channel gain re-asserted after + // master volume change. + saimpl->setGain(saimpl->getGain()); + } +} + +// +// LLAudioChannelFMODSTUDIO implementation +// + +LLAudioChannelFMODSTUDIO::LLAudioChannelFMODSTUDIO(FMOD::System *system) : LLAudioChannel(), mSystemp(system), mChannelp(NULL), mLastSamplePos(0) +{ +} + + +LLAudioChannelFMODSTUDIO::~LLAudioChannelFMODSTUDIO() +{ + cleanup(); +} + +bool LLAudioChannelFMODSTUDIO::updateBuffer() +{ + if (!mCurrentSourcep) + { + // This channel isn't associated with any source, nothing + // to be updated + return false; + } + + if (LLAudioChannel::updateBuffer()) + { + // Base class update returned true, which means that we need to actually + // set up the channel for a different buffer. + + LLAudioBufferFMODSTUDIO *bufferp = (LLAudioBufferFMODSTUDIO *)mCurrentSourcep->getCurrentBuffer(); + + // Grab the FMOD sample associated with the buffer + FMOD::Sound *soundp = bufferp->getSound(); + if (!soundp) + { + // This is bad, there should ALWAYS be a sound associated with a legit + // buffer. + LL_ERRS() << "No FMOD sound!" << LL_ENDL; + return false; + } + + + // Actually play the sound. Start it off paused so we can do all the necessary + // setup. + if (!mChannelp) + { + FMOD_RESULT result = getSystem()->playSound(soundp, NULL /*free channel?*/, true, &mChannelp); + Check_FMOD_Error(result, "FMOD::System::playSound"); + } + + // Setting up channel mChannelID + } + + // If we have a source for the channel, we need to update its gain. + if (mCurrentSourcep) + { + // SJB: warnings can spam and hurt framerate, disabling + //FMOD_RESULT result; + + mChannelp->setVolume(getSecondaryGain() * mCurrentSourcep->getGain()); + //Check_FMOD_Error(result, "FMOD::Channel::setVolume"); + + mChannelp->setMode(mCurrentSourcep->isLoop() ? FMOD_LOOP_NORMAL : FMOD_LOOP_OFF); + /*if(Check_FMOD_Error(result, "FMOD::Channel::setMode")) + { + S32 index; + mChannelp->getIndex(&index); + LL_WARNS() << "Channel " << index << "Source ID: " << mCurrentSourcep->getID() + << " at " << mCurrentSourcep->getPositionGlobal() << LL_ENDL; + }*/ + } + + return true; +} + + +void LLAudioChannelFMODSTUDIO::update3DPosition() +{ + if (!mChannelp) + { + // We're not actually a live channel (i.e., we're not playing back anything) + return; + } + + LLAudioBufferFMODSTUDIO *bufferp = (LLAudioBufferFMODSTUDIO *)mCurrentBufferp; + if (!bufferp) + { + // We don't have a buffer associated with us (should really have been picked up + // by the above if. + return; + } + + if (mCurrentSourcep->isForcedPriority()) + { + // Prioritized UI and preview sounds don't need to do any positional updates. + set3DMode(false); + } + else + { + // Localized sound. Update the position and velocity of the sound. + set3DMode(true); + + LLVector3 float_pos; + float_pos.setVec(mCurrentSourcep->getPositionGlobal()); + FMOD_RESULT result = mChannelp->set3DAttributes((FMOD_VECTOR*)float_pos.mV, (FMOD_VECTOR*)mCurrentSourcep->getVelocity().mV); + Check_FMOD_Error(result, "FMOD::Channel::set3DAttributes"); + } +} + + +void LLAudioChannelFMODSTUDIO::updateLoop() +{ + if (!mChannelp) + { + // May want to clear up the loop/sample counters. + return; + } + + // + // Hack: We keep track of whether we looped or not by seeing when the + // sample position looks like it's going backwards. Not reliable; may + // yield false negatives. + // + U32 cur_pos; + mChannelp->getPosition(&cur_pos, FMOD_TIMEUNIT_PCMBYTES); + + if (cur_pos < (U32)mLastSamplePos) + { + mLoopedThisFrame = true; + } + mLastSamplePos = cur_pos; +} + + +void LLAudioChannelFMODSTUDIO::cleanup() +{ + if (!mChannelp) + { + // Aborting cleanup with no channel handle. + return; + } + + //Cleaning up channel mChannelID + Check_FMOD_Error(mChannelp->stop(), "FMOD::Channel::stop"); + + mCurrentBufferp = NULL; + mChannelp = NULL; +} + + +void LLAudioChannelFMODSTUDIO::play() +{ + if (!mChannelp) + { + LL_WARNS() << "Playing without a channel handle, aborting" << LL_ENDL; + return; + } + + Check_FMOD_Error(mChannelp->setPaused(false), "FMOD::Channel::pause"); + + getSource()->setPlayedOnce(true); + + if (LLAudioEngine_FMODSTUDIO::mChannelGroups[getSource()->getType()]) + mChannelp->setChannelGroup(LLAudioEngine_FMODSTUDIO::mChannelGroups[getSource()->getType()]); +} + + +void LLAudioChannelFMODSTUDIO::playSynced(LLAudioChannel *channelp) +{ + LLAudioChannelFMODSTUDIO *fmod_channelp = (LLAudioChannelFMODSTUDIO*)channelp; + if (!(fmod_channelp->mChannelp && mChannelp)) + { + // Don't have channels allocated to both the master and the slave + return; + } + + U32 cur_pos; + if (Check_FMOD_Error(mChannelp->getPosition(&cur_pos, FMOD_TIMEUNIT_PCMBYTES), "Unable to retrieve current position")) + return; + + cur_pos %= mCurrentBufferp->getLength(); + + // Try to match the position of our sync master + Check_FMOD_Error(mChannelp->setPosition(cur_pos, FMOD_TIMEUNIT_PCMBYTES), "Unable to set current position"); + + // Start us playing + play(); +} + + +bool LLAudioChannelFMODSTUDIO::isPlaying() +{ + if (!mChannelp) + { + return false; + } + + bool paused, playing; + mChannelp->getPaused(&paused); + mChannelp->isPlaying(&playing); + return !paused && playing; +} + + +// +// LLAudioChannelFMODSTUDIO implementation +// + + +LLAudioBufferFMODSTUDIO::LLAudioBufferFMODSTUDIO(FMOD::System *system) : mSystemp(system), mSoundp(NULL) +{ +} + + +LLAudioBufferFMODSTUDIO::~LLAudioBufferFMODSTUDIO() +{ + if (mSoundp) + { + mSoundp->release(); + mSoundp = NULL; + } +} + + +bool LLAudioBufferFMODSTUDIO::loadWAV(const std::string& filename) +{ + // Try to open a wav file from disk. This will eventually go away, as we don't + // really want to block doing this. + if (filename.empty()) + { + // invalid filename, abort. + return false; + } + + if (!gDirUtilp->fileExists(filename)) + { + // File not found, abort. + return false; + } + + if (mSoundp) + { + // If there's already something loaded in this buffer, clean it up. + mSoundp->release(); + mSoundp = NULL; + } + + FMOD_MODE base_mode = FMOD_LOOP_NORMAL; + FMOD_CREATESOUNDEXINFO exinfo; + memset(&exinfo, 0, sizeof(exinfo)); + exinfo.cbsize = sizeof(exinfo); + exinfo.suggestedsoundtype = FMOD_SOUND_TYPE_WAV; //Hint to speed up loading. + // Load up the wav file into an fmod sample (since 1.05 fmod studio expects everything in UTF-8) + FMOD_RESULT result = getSystem()->createSound(filename.c_str(), base_mode, &exinfo, &mSoundp); + + if (result != FMOD_OK) + { + // We failed to load the file for some reason. + LL_WARNS() << "Could not load data '" << filename << "': " << FMOD_ErrorString(result) << LL_ENDL; + + // + // If we EVER want to load wav files provided by end users, we need + // to rethink this! + // + // file is probably corrupt - remove it. + LLFile::remove(filename); + return false; + } + + // Everything went well, return true + return true; +} + + +U32 LLAudioBufferFMODSTUDIO::getLength() +{ + if (!mSoundp) + { + return 0; + } + + U32 length; + mSoundp->getLength(&length, FMOD_TIMEUNIT_PCMBYTES); + return length; +} + + +void LLAudioChannelFMODSTUDIO::set3DMode(bool use3d) +{ + FMOD_MODE current_mode; + if (mChannelp->getMode(¤t_mode) != FMOD_OK) + return; + FMOD_MODE new_mode = current_mode; + new_mode &= ~(use3d ? FMOD_2D : FMOD_3D); + new_mode |= use3d ? FMOD_3D : FMOD_2D; + + if (current_mode != new_mode) + { + mChannelp->setMode(new_mode); + } +} + +// *NOTE: This is almost certainly being called on the mixer thread, +// not the main thread. May have implications for callees or audio +// engine shutdown. + +FMOD_RESULT F_CALLBACK windCallback(FMOD_DSP_STATE *dsp_state, float *inbuffer, float *outbuffer, unsigned int length, int inchannels, int *outchannels) +{ + // inbuffer = fmod's original mixbuffer. + // outbuffer = the buffer passed from the previous DSP unit. + // length = length in samples at this mix time. + + LLWindGen<LLAudioEngine_FMODSTUDIO::MIXBUFFERFORMAT> *windgen = NULL; + FMOD::DSP *thisdsp = (FMOD::DSP *)dsp_state->instance; + + thisdsp->getUserData((void **)&windgen); + + if (windgen) + { + windgen->windGenerate((LLAudioEngine_FMODSTUDIO::MIXBUFFERFORMAT *)outbuffer, length); + } + + return FMOD_OK; +} diff --git a/indra/llaudio/llaudioengine_fmodstudio.h b/indra/llaudio/llaudioengine_fmodstudio.h new file mode 100644 index 0000000000..eb346e0466 --- /dev/null +++ b/indra/llaudio/llaudioengine_fmodstudio.h @@ -0,0 +1,131 @@ +/** + * @file audioengine_fmodstudio.h + * @brief Definition of LLAudioEngine class abstracting the audio + * support as a FMODSTUDIO implementation + * + * $LicenseInfo:firstyear=2020&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2020, 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_AUDIOENGINE_FMODSTUDIO_H +#define LL_AUDIOENGINE_FMODSTUDIO_H + +#include "llaudioengine.h" +#include "llwindgen.h" + +//Stubs +class LLAudioStreamManagerFMODSTUDIO; +namespace FMOD +{ + class System; + class Channel; + class ChannelGroup; + class Sound; + class DSP; +} +typedef struct FMOD_DSP_DESCRIPTION FMOD_DSP_DESCRIPTION; + +//Interfaces +class LLAudioEngine_FMODSTUDIO : public LLAudioEngine +{ +public: + LLAudioEngine_FMODSTUDIO(bool enable_profiler); + virtual ~LLAudioEngine_FMODSTUDIO(); + + // initialization/startup/shutdown + virtual bool init(void *user_data, const std::string &app_title); + virtual std::string getDriverName(bool verbose); + virtual LLStreamingAudioInterface* createDefaultStreamingAudioImpl() const; + virtual void allocateListener(); + + virtual void shutdown(); + + /*virtual*/ bool initWind(); + /*virtual*/ void cleanupWind(); + + /*virtual*/void updateWind(LLVector3 direction, F32 camera_height_above_water); + + typedef F32 MIXBUFFERFORMAT; + + FMOD::System *getSystem() const {return mSystem;} +protected: + /*virtual*/ LLAudioBuffer *createBuffer(); // Get a free buffer, or flush an existing one if you have to. + /*virtual*/ LLAudioChannel *createChannel(); // Create a new audio channel. + + /*virtual*/ void setInternalGain(F32 gain); + + bool mInited; + + LLWindGen<MIXBUFFERFORMAT> *mWindGen; + + FMOD_DSP_DESCRIPTION *mWindDSPDesc; + FMOD::DSP *mWindDSP; + FMOD::System *mSystem; + bool mEnableProfiler; + +public: + static FMOD::ChannelGroup *mChannelGroups[LLAudioEngine::AUDIO_TYPE_COUNT]; +}; + + +class LLAudioChannelFMODSTUDIO : public LLAudioChannel +{ +public: + LLAudioChannelFMODSTUDIO(FMOD::System *audioengine); + virtual ~LLAudioChannelFMODSTUDIO(); + +protected: + /*virtual*/ void play(); + /*virtual*/ void playSynced(LLAudioChannel *channelp); + /*virtual*/ void cleanup(); + /*virtual*/ bool isPlaying(); + + /*virtual*/ bool updateBuffer(); + /*virtual*/ void update3DPosition(); + /*virtual*/ void updateLoop(); + + void set3DMode(bool use3d); +protected: + FMOD::System *getSystem() const {return mSystemp;} + FMOD::System *mSystemp; + FMOD::Channel *mChannelp; + S32 mLastSamplePos; +}; + + +class LLAudioBufferFMODSTUDIO : public LLAudioBuffer +{ +public: + LLAudioBufferFMODSTUDIO(FMOD::System *audioengine); + virtual ~LLAudioBufferFMODSTUDIO(); + + /*virtual*/ bool loadWAV(const std::string& filename); + /*virtual*/ U32 getLength(); + friend class LLAudioChannelFMODSTUDIO; +protected: + FMOD::System *getSystem() const {return mSystemp;} + FMOD::System *mSystemp; + FMOD::Sound *getSound() const{ return mSoundp; } + FMOD::Sound *mSoundp; +}; + + +#endif // LL_AUDIOENGINE_FMODSTUDIO_H diff --git a/indra/llaudio/lllistener_fmodstudio.cpp b/indra/llaudio/lllistener_fmodstudio.cpp new file mode 100644 index 0000000000..9dc55eec79 --- /dev/null +++ b/indra/llaudio/lllistener_fmodstudio.cpp @@ -0,0 +1,136 @@ +/** + * @file listener_fmodstudio.cpp + * @brief Implementation of LISTENER class abstracting the audio + * support as a FMODSTUDIO implementation + * + * $LicenseInfo:firstyear=2020&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2020, 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 "linden_common.h" +#include "llaudioengine.h" +#include "lllistener_fmodstudio.h" +#include "fmodstudio/fmod.hpp" + +//----------------------------------------------------------------------- +// constructor +//----------------------------------------------------------------------- +LLListener_FMODSTUDIO::LLListener_FMODSTUDIO(FMOD::System *system) +{ + mSystem = system; + init(); +} + +//----------------------------------------------------------------------- +LLListener_FMODSTUDIO::~LLListener_FMODSTUDIO() +{ +} + +//----------------------------------------------------------------------- +void LLListener_FMODSTUDIO::init(void) +{ + // do inherited + LLListener::init(); + mDopplerFactor = 1.0f; + mRolloffFactor = 1.0f; +} + +//----------------------------------------------------------------------- +void LLListener_FMODSTUDIO::translate(LLVector3 offset) +{ + LLListener::translate(offset); + + mSystem->set3DListenerAttributes(0, (FMOD_VECTOR*)mPosition.mV, NULL, (FMOD_VECTOR*)mListenAt.mV, (FMOD_VECTOR*)mListenUp.mV); +} + +//----------------------------------------------------------------------- +void LLListener_FMODSTUDIO::setPosition(LLVector3 pos) +{ + LLListener::setPosition(pos); + + mSystem->set3DListenerAttributes(0, (FMOD_VECTOR*)mPosition.mV, NULL, (FMOD_VECTOR*)mListenAt.mV, (FMOD_VECTOR*)mListenUp.mV); +} + +//----------------------------------------------------------------------- +void LLListener_FMODSTUDIO::setVelocity(LLVector3 vel) +{ + LLListener::setVelocity(vel); + + mSystem->set3DListenerAttributes(0, NULL, (FMOD_VECTOR*)mVelocity.mV, (FMOD_VECTOR*)mListenAt.mV, (FMOD_VECTOR*)mListenUp.mV); +} + +//----------------------------------------------------------------------- +void LLListener_FMODSTUDIO::orient(LLVector3 up, LLVector3 at) +{ + LLListener::orient(up, at); + + // at = -at; by default Fmod studio is 'left-handed' but we are providing + // flag FMOD_INIT_3D_RIGHTHANDED so no correction are needed + + mSystem->set3DListenerAttributes(0, NULL, NULL, (FMOD_VECTOR*)at.mV, (FMOD_VECTOR*)up.mV); +} + +//----------------------------------------------------------------------- +void LLListener_FMODSTUDIO::commitDeferredChanges() +{ + if (!mSystem) + { + return; + } + + mSystem->update(); +} + + +void LLListener_FMODSTUDIO::setRolloffFactor(F32 factor) +{ + //An internal FMOD optimization skips 3D updates if there have not been changes to the 3D sound environment. + // (this was true for FMODex, looks to be still true for FMOD STUDIO, but needs a recheck) + //Sadly, a change in rolloff is not accounted for, thus we must touch the listener properties as well. + //In short: Changing the position ticks a dirtyflag inside fmod, which makes it not skip 3D processing next update call. + if (mRolloffFactor != factor) + { + LLVector3 pos = mPosition - LLVector3(0.f, 0.f, .1f); + mSystem->set3DListenerAttributes(0, (FMOD_VECTOR*)pos.mV, NULL, NULL, NULL); + mSystem->set3DListenerAttributes(0, (FMOD_VECTOR*)mPosition.mV, NULL, NULL, NULL); + } + mRolloffFactor = factor; + mSystem->set3DSettings(mDopplerFactor, 1.f, mRolloffFactor); +} + + +F32 LLListener_FMODSTUDIO::getRolloffFactor() +{ + return mRolloffFactor; +} + + +void LLListener_FMODSTUDIO::setDopplerFactor(F32 factor) +{ + mDopplerFactor = factor; + mSystem->set3DSettings(mDopplerFactor, 1.f, mRolloffFactor); +} + + +F32 LLListener_FMODSTUDIO::getDopplerFactor() +{ + return mDopplerFactor; +} diff --git a/indra/llaudio/lllistener_fmodstudio.h b/indra/llaudio/lllistener_fmodstudio.h new file mode 100644 index 0000000000..5287cbedc6 --- /dev/null +++ b/indra/llaudio/lllistener_fmodstudio.h @@ -0,0 +1,65 @@ +/** + * @file listener_fmodstudio.h + * @brief Description of LISTENER class abstracting the audio support + * as an FMOD 3D implementation + * + * $LicenseInfo:firstyear=2020&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2020, 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_LISTENER_FMODSTUDIO_H +#define LL_LISTENER_FMODSTUDIO_H + +#include "lllistener.h" + +//Stubs +namespace FMOD +{ + class System; +} + +//Interfaces +class LLListener_FMODSTUDIO : public LLListener +{ +public: + LLListener_FMODSTUDIO(FMOD::System *system); + virtual ~LLListener_FMODSTUDIO(); + virtual void init(); + + virtual void translate(LLVector3 offset); + virtual void setPosition(LLVector3 pos); + virtual void setVelocity(LLVector3 vel); + virtual void orient(LLVector3 up, LLVector3 at); + virtual void commitDeferredChanges(); + + virtual void setDopplerFactor(F32 factor); + virtual F32 getDopplerFactor(); + virtual void setRolloffFactor(F32 factor); + virtual F32 getRolloffFactor(); +protected: + FMOD::System *mSystem; + F32 mDopplerFactor; + F32 mRolloffFactor; +}; + +#endif + + diff --git a/indra/llaudio/llstreamingaudio_fmodstudio.cpp b/indra/llaudio/llstreamingaudio_fmodstudio.cpp new file mode 100644 index 0000000000..22fc86c0cd --- /dev/null +++ b/indra/llaudio/llstreamingaudio_fmodstudio.cpp @@ -0,0 +1,481 @@ +/** + * @file streamingaudio_fmodstudio.cpp + * @brief LLStreamingAudio_FMODSTUDIO implementation + * + * $LicenseInfo:firstyear=2020&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2020, 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 "linden_common.h" + +#include "llmath.h" + +#include "fmodstudio/fmod.hpp" +#include "fmodstudio/fmod_errors.h" + +#include "llstreamingaudio_fmodstudio.h" + + +class LLAudioStreamManagerFMODSTUDIO +{ +public: + LLAudioStreamManagerFMODSTUDIO(FMOD::System *system, const std::string& url); + FMOD::Channel* startStream(); + bool stopStream(); // Returns true if the stream was successfully stopped. + bool ready(); + + const std::string& getURL() { return mInternetStreamURL; } + + FMOD_OPENSTATE getOpenState(unsigned int* percentbuffered = NULL, bool* starving = NULL, bool* diskbusy = NULL); +protected: + FMOD::System* mSystem; + FMOD::Channel* mStreamChannel; + FMOD::Sound* mInternetStream; + bool mReady; + + std::string mInternetStreamURL; +}; + + + +//--------------------------------------------------------------------------- +// Internet Streaming +//--------------------------------------------------------------------------- +LLStreamingAudio_FMODSTUDIO::LLStreamingAudio_FMODSTUDIO(FMOD::System *system) : +mSystem(system), +mCurrentInternetStreamp(NULL), +mFMODInternetStreamChannelp(NULL), +mGain(1.0f), +mRetryCount(0) +{ + // Number of milliseconds of audio to buffer for the audio card. + // Must be larger than the usual Second Life frame stutter time. + const U32 buffer_seconds = 10; //sec + const U32 estimated_bitrate = 128; //kbit/sec + FMOD_RESULT result = mSystem->setStreamBufferSize(estimated_bitrate * buffer_seconds * 128/*bytes/kbit*/, FMOD_TIMEUNIT_RAWBYTES); + if (result != FMOD_OK) + { + LL_WARNS("FMOD") << "setStreamBufferSize error: " << FMOD_ErrorString(result) << LL_ENDL; + } + + // Here's where we set the size of the network buffer and some buffering + // parameters. In this case we want a network buffer of 16k, we want it + // to prebuffer 40% of that when we first connect, and we want it + // to rebuffer 80% of that whenever we encounter a buffer underrun. + + // Leave the net buffer properties at the default. + //FSOUND_Stream_Net_SetBufferProperties(20000, 40, 80); +} + + +LLStreamingAudio_FMODSTUDIO::~LLStreamingAudio_FMODSTUDIO() +{ + if (mCurrentInternetStreamp) + { + // Isn't supposed to hapen, stream should be clear by now, + // and if it does, we are likely going to crash. + LL_WARNS("FMOD") << "mCurrentInternetStreamp not null on shutdown!" << LL_ENDL; + stop(); + } + + // Kill dead internet streams, if possible + killDeadStreams(); + + if (!mDeadStreams.empty()) + { + // LLStreamingAudio_FMODSTUDIO was inited on startup + // and should be destroyed on shutdown, it should + // wait for streams to die to not cause crashes or + // leaks. + // Ideally we need to wait on some kind of callback + // to release() streams correctly, but 200 ms should + // be enough and we can't wait forever. + LL_INFOS("FMOD") << "Waiting for " << (S32)mDeadStreams.size() << " streams to stop" << LL_ENDL; + for (S32 i = 0; i < 20; i++) + { + const U32 ms_delay = 10; + ms_sleep(ms_delay); // rude, but not many options here + killDeadStreams(); + if (mDeadStreams.empty()) + { + LL_INFOS("FMOD") << "All streams stopped after " << (S32)((i + 1) * ms_delay) << "ms" << LL_ENDL; + break; + } + } + } + + if (!mDeadStreams.empty()) + { + LL_WARNS("FMOD") << "Failed to kill some audio streams" << LL_ENDL; + } +} + +void LLStreamingAudio_FMODSTUDIO::killDeadStreams() +{ + std::list<LLAudioStreamManagerFMODSTUDIO *>::iterator iter; + for (iter = mDeadStreams.begin(); iter != mDeadStreams.end();) + { + LLAudioStreamManagerFMODSTUDIO *streamp = *iter; + if (streamp->stopStream()) + { + LL_INFOS("FMOD") << "Closed dead stream" << LL_ENDL; + delete streamp; + iter = mDeadStreams.erase(iter); + } + else + { + iter++; + } + } +} + +void LLStreamingAudio_FMODSTUDIO::start(const std::string& url) +{ + //if (!mInited) + //{ + // LL_WARNS() << "startInternetStream before audio initialized" << LL_ENDL; + // return; + //} + + // "stop" stream but don't clear url, etc. in case url == mInternetStreamURL + stop(); + + if (!url.empty()) + { + LL_INFOS("FMOD") << "Starting internet stream: " << url << LL_ENDL; + mCurrentInternetStreamp = new LLAudioStreamManagerFMODSTUDIO(mSystem, url); + mURL = url; + } + else + { + LL_INFOS("FMOD") << "Set internet stream to null" << LL_ENDL; + mURL.clear(); + } + + mRetryCount = 0; +} + + +void LLStreamingAudio_FMODSTUDIO::update() +{ + // Kill dead internet streams, if possible + killDeadStreams(); + + // Don't do anything if there are no streams playing + if (!mCurrentInternetStreamp) + { + return; + } + + unsigned int progress; + bool starving; + bool diskbusy; + FMOD_OPENSTATE open_state = mCurrentInternetStreamp->getOpenState(&progress, &starving, &diskbusy); + + if (open_state == FMOD_OPENSTATE_READY) + { + // Stream is live + + // start the stream if it's ready + if (!mFMODInternetStreamChannelp && + (mFMODInternetStreamChannelp = mCurrentInternetStreamp->startStream())) + { + // Reset volume to previously set volume + setGain(getGain()); + mFMODInternetStreamChannelp->setPaused(false); + } + mRetryCount = 0; + } + else if (open_state == FMOD_OPENSTATE_ERROR) + { + LL_INFOS("FMOD") << "State: FMOD_OPENSTATE_ERROR" + << " Progress: " << U32(progress) + << " Starving: " << S32(starving) + << " Diskbusy: " << S32(diskbusy) << LL_ENDL; + if (mRetryCount < 2) + { + // Retry + std::string url = mURL; + stop(); // might drop mURL, drops mCurrentInternetStreamp + + mRetryCount++; + + if (!url.empty()) + { + LL_INFOS("FMOD") << "Restarting internet stream: " << url << ", attempt " << (mRetryCount + 1) << LL_ENDL; + mCurrentInternetStreamp = new LLAudioStreamManagerFMODSTUDIO(mSystem, url); + mURL = url; + } + } + else + { + stop(); + } + return; + } + + if (mFMODInternetStreamChannelp) + { + FMOD::Sound *sound = NULL; + + if (mFMODInternetStreamChannelp->getCurrentSound(&sound) == FMOD_OK && sound) + { + FMOD_TAG tag; + S32 tagcount, dirtytagcount; + + if (sound->getNumTags(&tagcount, &dirtytagcount) == FMOD_OK && dirtytagcount) + { + for (S32 i = 0; i < tagcount; ++i) + { + if (sound->getTag(NULL, i, &tag) != FMOD_OK) + continue; + + if (tag.type == FMOD_TAGTYPE_FMOD) + { + if (!strcmp(tag.name, "Sample Rate Change")) + { + LL_INFOS("FMOD") << "Stream forced changing sample rate to " << *((float *)tag.data) << LL_ENDL; + mFMODInternetStreamChannelp->setFrequency(*((float *)tag.data)); + } + continue; + } + } + } + + if (starving) + { + bool paused = false; + mFMODInternetStreamChannelp->getPaused(&paused); + if (!paused) + { + LL_INFOS("FMOD") << "Stream starvation detected! Pausing stream until buffer nearly full." << LL_ENDL; + LL_INFOS("FMOD") << " (diskbusy=" << diskbusy << ")" << LL_ENDL; + LL_INFOS("FMOD") << " (progress=" << progress << ")" << LL_ENDL; + mFMODInternetStreamChannelp->setPaused(true); + } + } + else if (progress > 80) + { + mFMODInternetStreamChannelp->setPaused(false); + } + } + } +} + +void LLStreamingAudio_FMODSTUDIO::stop() +{ + if (mFMODInternetStreamChannelp) + { + mFMODInternetStreamChannelp->setPaused(true); + mFMODInternetStreamChannelp->setPriority(0); + mFMODInternetStreamChannelp = NULL; + } + + if (mCurrentInternetStreamp) + { + LL_INFOS("FMOD") << "Stopping internet stream: " << mCurrentInternetStreamp->getURL() << LL_ENDL; + if (mCurrentInternetStreamp->stopStream()) + { + delete mCurrentInternetStreamp; + } + else + { + LL_WARNS("FMOD") << "Pushing stream to dead list: " << mCurrentInternetStreamp->getURL() << LL_ENDL; + mDeadStreams.push_back(mCurrentInternetStreamp); + } + mCurrentInternetStreamp = NULL; + //mURL.clear(); + } +} + +void LLStreamingAudio_FMODSTUDIO::pause(int pauseopt) +{ + if (pauseopt < 0) + { + pauseopt = mCurrentInternetStreamp ? 1 : 0; + } + + if (pauseopt) + { + if (mCurrentInternetStreamp) + { + LL_INFOS("FMOD") << "Pausing internet stream" << LL_ENDL; + stop(); + } + } + else + { + start(getURL()); + } +} + + +// A stream is "playing" if it has been requested to start. That +// doesn't necessarily mean audio is coming out of the speakers. +int LLStreamingAudio_FMODSTUDIO::isPlaying() +{ + if (mCurrentInternetStreamp) + { + return 1; // Active and playing + } + else if (!mURL.empty()) + { + return 2; // "Paused" + } + else + { + return 0; + } +} + + +F32 LLStreamingAudio_FMODSTUDIO::getGain() +{ + return mGain; +} + + +std::string LLStreamingAudio_FMODSTUDIO::getURL() +{ + return mURL; +} + + +void LLStreamingAudio_FMODSTUDIO::setGain(F32 vol) +{ + mGain = vol; + + if (mFMODInternetStreamChannelp) + { + vol = llclamp(vol * vol, 0.f, 1.f); //should vol be squared here? + + mFMODInternetStreamChannelp->setVolume(vol); + } +} + +/////////////////////////////////////////////////////// +// manager of possibly-multiple internet audio streams + +LLAudioStreamManagerFMODSTUDIO::LLAudioStreamManagerFMODSTUDIO(FMOD::System *system, const std::string& url) : +mSystem(system), +mStreamChannel(NULL), +mInternetStream(NULL), +mReady(false) +{ + mInternetStreamURL = url; + + FMOD_RESULT result = mSystem->createStream(url.c_str(), FMOD_2D | FMOD_NONBLOCKING | FMOD_IGNORETAGS, 0, &mInternetStream); + + if (result != FMOD_OK) + { + LL_WARNS("FMOD") << "Couldn't open fmod stream, error " + << FMOD_ErrorString(result) + << LL_ENDL; + mReady = false; + return; + } + + mReady = true; +} + +FMOD::Channel *LLAudioStreamManagerFMODSTUDIO::startStream() +{ + // We need a live and opened stream before we try and play it. + if (!mInternetStream || getOpenState() != FMOD_OPENSTATE_READY) + { + LL_WARNS("FMOD") << "No internet stream to start playing!" << LL_ENDL; + return NULL; + } + + if (mStreamChannel) + return mStreamChannel; //Already have a channel for this stream. + + FMOD_RESULT result = mSystem->playSound(mInternetStream, NULL, true, &mStreamChannel); + if (result != FMOD_OK) + { + LL_WARNS("FMOD") << FMOD_ErrorString(result) << LL_ENDL; + } + return mStreamChannel; +} + +bool LLAudioStreamManagerFMODSTUDIO::stopStream() +{ + if (mInternetStream) + { + + + bool close = true; + switch (getOpenState()) + { + case FMOD_OPENSTATE_CONNECTING: + close = false; + break; + default: + close = true; + } + + if (close) + { + mInternetStream->release(); + mStreamChannel = NULL; + mInternetStream = NULL; + return true; + } + else + { + return false; + } + } + else + { + return true; + } +} + +FMOD_OPENSTATE LLAudioStreamManagerFMODSTUDIO::getOpenState(unsigned int* percentbuffered, bool* starving, bool* diskbusy) +{ + FMOD_OPENSTATE state; + FMOD_RESULT result = mInternetStream->getOpenState(&state, percentbuffered, starving, diskbusy); + if (result != FMOD_OK) + { + LL_WARNS("FMOD") << FMOD_ErrorString(result) << LL_ENDL; + } + return state; +} + +void LLStreamingAudio_FMODSTUDIO::setBufferSizes(U32 streambuffertime, U32 decodebuffertime) +{ + FMOD_RESULT result = mSystem->setStreamBufferSize(streambuffertime / 1000 * 128 * 128, FMOD_TIMEUNIT_RAWBYTES); + if (result != FMOD_OK) + { + LL_WARNS("FMOD") << "setStreamBufferSize error: " << FMOD_ErrorString(result) << LL_ENDL; + return; + } + FMOD_ADVANCEDSETTINGS settings; + memset(&settings, 0, sizeof(settings)); + settings.cbSize = sizeof(settings); + settings.defaultDecodeBufferSize = decodebuffertime;//ms + result = mSystem->setAdvancedSettings(&settings); + if (result != FMOD_OK) + { + LL_WARNS("FMOD") << "setAdvancedSettings error: " << FMOD_ErrorString(result) << LL_ENDL; + } +} diff --git a/indra/llaudio/llstreamingaudio_fmodstudio.h b/indra/llaudio/llstreamingaudio_fmodstudio.h new file mode 100644 index 0000000000..2127841809 --- /dev/null +++ b/indra/llaudio/llstreamingaudio_fmodstudio.h @@ -0,0 +1,76 @@ +/** + * @file streamingaudio_fmodstudio.h + * @brief Definition of LLStreamingAudio_FMODSTUDIO implementation + * + * $LicenseInfo:firstyear=2020&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2020, 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_STREAMINGAUDIO_FMODSTUDIO_H +#define LL_STREAMINGAUDIO_FMODSTUDIO_H + +#include "stdtypes.h" // from llcommon + +#include "llstreamingaudio.h" +#include "lltimer.h" + +//Stubs +class LLAudioStreamManagerFMODSTUDIO; +namespace FMOD +{ + class System; + class Channel; +} + +//Interfaces +class LLStreamingAudio_FMODSTUDIO : public LLStreamingAudioInterface +{ +public: + LLStreamingAudio_FMODSTUDIO(FMOD::System *system); + /*virtual*/ ~LLStreamingAudio_FMODSTUDIO(); + + /*virtual*/ void start(const std::string& url); + /*virtual*/ void stop(); + /*virtual*/ void pause(S32 pause); + /*virtual*/ void update(); + /*virtual*/ S32 isPlaying(); + /*virtual*/ void setGain(F32 vol); + /*virtual*/ F32 getGain(); + /*virtual*/ std::string getURL(); + + /*virtual*/ bool supportsAdjustableBufferSizes(){return true;} + /*virtual*/ void setBufferSizes(U32 streambuffertime, U32 decodebuffertime); +private: + void killDeadStreams(); + + FMOD::System *mSystem; + + LLAudioStreamManagerFMODSTUDIO *mCurrentInternetStreamp; + FMOD::Channel *mFMODInternetStreamChannelp; + std::list<LLAudioStreamManagerFMODSTUDIO *> mDeadStreams; + + std::string mURL; + F32 mGain; + S32 mRetryCount; +}; + + +#endif // LL_STREAMINGAUDIO_FMODSTUDIO_H diff --git a/indra/llcharacter/CMakeLists.txt b/indra/llcharacter/CMakeLists.txt index bc45eb474a..7c158c4ff9 100644 --- a/indra/llcharacter/CMakeLists.txt +++ b/indra/llcharacter/CMakeLists.txt @@ -70,3 +70,5 @@ target_link_libraries( llfilesystem llxml ) + +include(LibraryInstall) diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index 95e991c246..e611847a24 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -8,7 +8,9 @@ include(bugsplat) include(Linking) include(Boost) include(LLSharedLibs) +if (USE_AUTOBUILD_3P OR USE_CONAN) include(Copy3rdPartyLibs) +endif () include(ZLIBNG) include(URIPARSER) include(Tracy) @@ -163,6 +165,7 @@ set(llcommon_HEADER_FILES lleventdispatcher.h lleventfilter.h llevents.h + lleventtimer.h lleventemitter.h llexception.h llfasttimer.h @@ -187,6 +190,7 @@ set(llcommon_HEADER_FILES llliveappconfig.h lllivefile.h llmainthreadtask.h + llmake.h llmd5.h llmemory.h llmemorystream.h @@ -250,7 +254,9 @@ set(llcommon_HEADER_FILES llwin32headerslean.h llworkerthread.h hbxxh.h + is_approx_equal_fraction.h lockstatic.h + mutex.h stdtypes.h stringize.h threadpool.h @@ -286,7 +292,38 @@ target_link_libraries( target_include_directories(llcommon INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) target_include_directories(llcommon PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) +if (CMAKE_OSX_ARCHITECTURES MATCHES arm64) + if (${PREBUILD_TRACKING_DIR}/sentinel_installed IS_NEWER_THAN ${PREBUILD_TRACKING_DIR}/sse2neon_installed OR NOT ${sse2neon_installed} EQUAL 0) + file(MAKE_DIRECTORY ${LIBS_PREBUILT_DIR}/include/sse2neon) + if (NOT EXISTS ${LIBS_PREBUILT_DIR}/include/sse2neon/sse2neon.h) + file(DOWNLOAD + https://raw.githubusercontent.com/DLTcollab/sse2neon/master/sse2neon.h + ${LIBS_PREBUILT_DIR}/include/sse2neon/sse2neon.h + ) + endif (NOT EXISTS ${LIBS_PREBUILT_DIR}/include/sse2neon/sse2neon.h) + file(WRITE ${PREBUILD_TRACKING_DIR}/sse2neon_installed "0") + endif (${PREBUILD_TRACKING_DIR}/sentinel_installed IS_NEWER_THAN ${PREBUILD_TRACKING_DIR}/sse2neon_installed OR NOT ${sse2neon_installed} EQUAL 0) + target_include_directories(llcommon PUBLIC ${LIBS_PREBUILT_DIR}/include/sse2neon) +endif () + +if (USE_AUTOBUILD_3P OR USE_CONAN) add_dependencies(llcommon stage_third_party_libs) +else () + target_compile_options(${PROJECT_NAME} PUBLIC -Wno-deprecated-declarations) + if (CMAKE_CXX_COMPILER_ID MATCHES "GNU") + set_source_files_properties( + llapp.cpp + llsdutil.cpp + PROPERTIES COMPILE_FLAGS -Wno-stringop-truncation) + set_source_files_properties(llevent.cpp PROPERTIES + COMPILE_FLAGS -Wno-nonnull) + elseif (LINUX AND CMAKE_CXX_COMPILER_ID MATCHES "Clang") + set_source_files_properties(llsys.cpp PROPERTIES + COMPILE_FLAGS -Wno-unused-but-set-variable) + endif() +endif () + +include(LibraryInstall) if (LL_TESTS) include(LLAddBuildTest) diff --git a/indra/llcommon/always_return.h b/indra/llcommon/always_return.h index a206471da5..b99eb49096 100644 --- a/indra/llcommon/always_return.h +++ b/indra/llcommon/always_return.h @@ -79,6 +79,22 @@ namespace LL DESIRED mDefault; }; + // specialize for AlwaysReturn<void> + template <> + struct AlwaysReturn<void> + { + public: + AlwaysReturn() {} + + // callable returns a type not convertible to DESIRED, return default + template <typename CALLABLE, typename... ARGS> + void operator()(CALLABLE&& callable, ARGS&&... args) + { + // discard whatever callable(args) returns + std::forward<CALLABLE>(callable)(std::forward<ARGS>(args)...); + } + }; + /** * always_return<T>(some_function, some_args...) calls * some_function(some_args...). It is guaranteed to return a value of type diff --git a/indra/llcommon/hbxxh.cpp b/indra/llcommon/hbxxh.cpp index 41d797a7e3..8ccf8dfcbe 100644 --- a/indra/llcommon/hbxxh.cpp +++ b/indra/llcommon/hbxxh.cpp @@ -34,7 +34,11 @@ // in your build, in which case the latter would be used instead. For ARM64 // builds, this would also automatically enable NEON vectorization. #define XXH_INLINE_ALL +#if LL_USESYSTEMLIBS +#include <xxhash.h> +#else #include "xxhash/xxhash.h" +#endif #include "hbxxh.h" diff --git a/indra/llcommon/llcoros.cpp b/indra/llcommon/llcoros.cpp index 1539b48bd3..3fe7e09e7e 100644 --- a/indra/llcommon/llcoros.cpp +++ b/indra/llcommon/llcoros.cpp @@ -140,7 +140,7 @@ LLCoros::LLCoros(): // Previously we used // boost::context::guarded_stack_allocator::default_stacksize(); // empirically this is insufficient. - mStackSize(1024*1024), + mStackSize(512*1024), // mCurrent does NOT own the current CoroData instance -- it simply // points to it. So initialize it with a no-op deleter. mCurrent{ [](CoroData*){} } @@ -172,7 +172,7 @@ void LLCoros::cleanupSingleton() // don't use llcoro::suspend() because that module depends // on this one // This will yield current(main) thread and will let active - // corutines run once + // coroutines run once boost::this_fiber::yield(); } printActiveCoroutines("after pumping"); @@ -303,55 +303,6 @@ std::string LLCoros::launch(const std::string& prefix, const callable_t& callabl return name; } -namespace -{ - -#if LL_WINDOWS - -static const U32 STATUS_MSC_EXCEPTION = 0xE06D7363; // compiler specific - -U32 exception_filter(U32 code, struct _EXCEPTION_POINTERS *exception_infop) -{ - if (code == STATUS_MSC_EXCEPTION) - { - // C++ exception, go on - return EXCEPTION_CONTINUE_SEARCH; - } - else - { - // handle it - return EXCEPTION_EXECUTE_HANDLER; - } -} - -void sehandle(const LLCoros::callable_t& callable) -{ - __try - { - callable(); - } - __except (exception_filter(GetExceptionCode(), GetExceptionInformation())) - { - // convert to C++ styled exception - // Note: it might be better to use _se_set_translator - // if you want exception to inherit full callstack - char integer_string[512]; - sprintf(integer_string, "SEH, code: %lu\n", GetExceptionCode()); - throw std::exception(integer_string); - } -} - -#else // ! LL_WINDOWS - -inline void sehandle(const LLCoros::callable_t& callable) -{ - callable(); -} - -#endif // ! LL_WINDOWS - -} // anonymous namespace - // Top-level wrapper around caller's coroutine callable. // Normally we like to pass strings and such by const reference -- but in this // case, we WANT to copy both the name and the callable to our local stack! @@ -365,7 +316,7 @@ void LLCoros::toplevel(std::string name, callable_t callable) // run the code the caller actually wants in the coroutine try { - sehandle(callable); + LL::seh::catcher(callable); } catch (const Stop& exc) { diff --git a/indra/llcommon/llerror.h b/indra/llcommon/llerror.h index 6176ce0d1d..7353a36c5f 100644 --- a/indra/llcommon/llerror.h +++ b/indra/llcommon/llerror.h @@ -95,6 +95,11 @@ const int LL_ERR_NOERR = 0; #define LL_STATIC_ASSERT(func, msg) static_assert(func, msg) #define LL_BAD_TEMPLATE_INSTANTIATION(type, msg) static_assert(false, msg) #else +#if LL_LINUX +// We need access to raise and SIGSEGV +#include <signal.h> +#endif + #define LL_STATIC_ASSERT(func, msg) BOOST_STATIC_ASSERT(func) #define LL_BAD_TEMPLATE_INSTANTIATION(type, msg) BOOST_STATIC_ASSERT(sizeof(type) != 0 && false); #endif @@ -408,10 +413,16 @@ typedef LLError::NoClassInfo _LL_CLASS_TO_LOG; #define LL_NEWLINE '\n' // Use this only in LL_ERRS or in a place that LL_ERRS may not be used + +#ifndef LL_LINUX #define LLERROR_CRASH \ { \ crashdriver([](int* ptr){ *ptr = 0; exit(*ptr); }); \ } +#else +// For Linux we just call raise and be done with it. No fighting the compiler to create a crashing code snippet. +#define LLERROR_CRASH raise(SIGSEGV ); +#endif #define LL_ENDL \ LLError::End(); \ diff --git a/indra/llcommon/llexception.cpp b/indra/llcommon/llexception.cpp index c0154a569f..107fdc2b2d 100644 --- a/indra/llcommon/llexception.cpp +++ b/indra/llcommon/llexception.cpp @@ -15,7 +15,12 @@ #include "llexception.h" // STL headers // std headers +#include <iomanip> +#include <sstream> #include <typeinfo> +#if LL_WINDOWS +#include <excpt.h> +#endif // LL_WINDOWS // external library headers #include <boost/exception/diagnostic_information.hpp> #include <boost/exception/error_info.hpp> @@ -29,7 +34,6 @@ // On Windows, header-only implementation causes macro collisions -- use // prebuilt library #define BOOST_STACKTRACE_LINK -#include <excpt.h> #endif // LL_WINDOWS #include <boost/stacktrace.hpp> @@ -94,25 +98,47 @@ void annotate_exception_(boost::exception& exc) // For windows SEH exception handling we sometimes need a filter that will // separate C++ exceptions from C SEH exceptions -static const U32 STATUS_MSC_EXCEPTION = 0xE06D7363; // compiler specific +static constexpr U32 STATUS_MSC_EXCEPTION = 0xE06D7363; // compiler specific +static constexpr U32 STATUS_STACK_FULL = 0xC00000FD; -U32 msc_exception_filter(U32 code, struct _EXCEPTION_POINTERS *exception_infop) +void LL::seh::fill_stacktrace(std::string& stacktrace, U32 code) { - const auto stack = to_string(boost::stacktrace::stacktrace()); - LL_WARNS() << "SEH Exception handled (that probably shouldn't be): Code " << code - << "\n Stack trace: \n" - << stack << LL_ENDL; + // Sadly, despite its diagnostic importance, trying to capture a + // stacktrace when the stack is already blown only terminates us faster. + if (code == STATUS_STACK_FULL) + { + stacktrace = "(stack overflow, no traceback)"; + } + else + { + stacktrace = to_string(boost::stacktrace::stacktrace()); + } +} +U32 LL::seh::common_filter(U32 code, struct _EXCEPTION_POINTERS*) +{ if (code == STATUS_MSC_EXCEPTION) { - // C++ exception, go on + // C++ exception, don't stop at this handler return EXCEPTION_CONTINUE_SEARCH; } else { - // handle it + // This is a non-C++ exception, e.g. hardware check. + // Pass control into the handler block. return EXCEPTION_EXECUTE_HANDLER; } } +void LL::seh::rethrow(U32 code, const std::string& stacktrace) +{ + std::ostringstream out; + out << "Windows exception 0x" << std::hex << code; + if (! stacktrace.empty()) + { + out << '\n' << stacktrace; + } + LLTHROW(Windows_SEH_exception(out.str())); +} + #endif //LL_WINDOWS diff --git a/indra/llcommon/llexception.h b/indra/llcommon/llexception.h index 68e609444e..f58a553eb3 100644 --- a/indra/llcommon/llexception.h +++ b/indra/llcommon/llexception.h @@ -12,6 +12,7 @@ #if ! defined(LL_LLEXCEPTION_H) #define LL_LLEXCEPTION_H +#include "always_return.h" #include <stdexcept> #include <boost/exception/exception.hpp> #include <boost/throw_exception.hpp> @@ -102,14 +103,115 @@ void crash_on_unhandled_exception_(const char*, int, const char*, const std::str log_unhandled_exception_(__FILE__, __LINE__, BOOST_CURRENT_FUNCTION, CONTEXT) void log_unhandled_exception_(const char*, int, const char*, const std::string&); +/***************************************************************************** +* Structured Exception Handling +*****************************************************************************/ +// this is used in platform-generic code -- define outside #if LL_WINDOWS +struct Windows_SEH_exception: public LLException +{ + Windows_SEH_exception(const std::string& what): LLException(what) {} +}; + +namespace LL +{ +namespace seh +{ + +#if LL_WINDOWS //------------------------------------------------------------- + +void fill_stacktrace(std::string& stacktrace, U32 code); + +// wrapper around caller's U32 filter(U32 code, struct _EXCEPTION_POINTERS*) +// filter function: capture a stacktrace, if possible, before forwarding the +// call to the caller's filter() function +template <typename FILTER> +U32 filter_(std::string& stacktrace, FILTER&& filter, + U32 code, struct _EXCEPTION_POINTERS* exptrs) +{ + // By the time the handler gets control, the stack has been unwound, + // so report the stack trace now at filter() time. + fill_stacktrace(stacktrace, code); + return std::forward<FILTER>(filter)(code, exptrs); +} + +template <typename TRYCODE, typename FILTER, typename HANDLER> +auto catcher_inner(std::string& stacktrace, + TRYCODE&& trycode, FILTER&& filter, HANDLER&& handler) +{ + __try + { + return std::forward<TRYCODE>(trycode)(); + } + __except (filter_(stacktrace, + std::forward<FILTER>(filter), + GetExceptionCode(), GetExceptionInformation())) + { + return always_return<decltype(trycode())>( + std::forward<HANDLER>(handler), GetExceptionCode(), stacktrace); + } +} + +// triadic variant specifies try(), filter(U32, struct _EXCEPTION_POINTERS*), +// handler(U32, const std::string& stacktrace) +// stacktrace may or may not be available +template <typename TRYCODE, typename FILTER, typename HANDLER> +auto catcher(TRYCODE&& trycode, FILTER&& filter, HANDLER&& handler) +{ + // Construct and destroy this stacktrace string in the outer function + // because we can't do either in the function with __try/__except. + std::string stacktrace; + return catcher_inner(stacktrace, + std::forward<TRYCODE>(trycode), + std::forward<FILTER>(filter), + std::forward<HANDLER>(handler)); +} -#if LL_WINDOWS +// common_filter() handles the typical case in which we want our handler +// clause to handle only Structured Exceptions rather than explicitly-thrown +// C++ exceptions +U32 common_filter(U32 code, struct _EXCEPTION_POINTERS*); + +// dyadic variant specifies try(), handler(U32, stacktrace), assumes common_filter() +template <typename TRYCODE, typename HANDLER> +auto catcher(TRYCODE&& trycode, HANDLER&& handler) +{ + return catcher(std::forward<TRYCODE>(trycode), + common_filter, + std::forward<HANDLER>(handler)); +} + +// monadic variant specifies try(), assumes default filter and handler +template <typename TRYCODE> +auto catcher(TRYCODE&& trycode) +{ + return catcher(std::forward<TRYCODE>(trycode), rethrow); +} + +[[noreturn]] void rethrow(U32 code, const std::string& stacktrace); + +#else // not LL_WINDOWS ----------------------------------------------------- + +template <typename TRYCODE, typename FILTER, typename HANDLER> +auto catcher(TRYCODE&& trycode, FILTER&&, HANDLER&&) +{ + return std::forward<TRYCODE>(trycode)(); +} + +template <typename TRYCODE, typename HANDLER> +auto catcher(TRYCODE&& trycode, HANDLER&&) +{ + return std::forward<TRYCODE>(trycode)(); +} + +template <typename TRYCODE> +auto catcher(TRYCODE&& trycode) +{ + return std::forward<TRYCODE>(trycode)(); +} -// SEH exception filtering for use in __try __except -// Separates C++ exceptions from C SEH exceptions -// Todo: might be good idea to do some kind of seh_to_msc_wrapper(function, ARGS&&); -U32 msc_exception_filter(U32 code, struct _EXCEPTION_POINTERS *exception_infop); +#endif // not LL_WINDOWS ----------------------------------------------------- -#endif //LL_WINDOWS +} // namespace LL::seh +} // namespace LL #endif /* ! defined(LL_LLEXCEPTION_H) */ diff --git a/indra/llcommon/llfasttimer.cpp b/indra/llcommon/llfasttimer.cpp index 722743f453..7ceb57336e 100644 --- a/indra/llcommon/llfasttimer.cpp +++ b/indra/llcommon/llfasttimer.cpp @@ -43,7 +43,7 @@ #if LL_WINDOWS #include "lltimer.h" -#elif LL_LINUX +#elif LL_LINUX || __FreeBSD__ #include <sys/time.h> #include <sched.h> #include "lltimer.h" diff --git a/indra/llcommon/llfasttimer.h b/indra/llcommon/llfasttimer.h index 09fcf8a1af..a69a03e419 100644 --- a/indra/llcommon/llfasttimer.h +++ b/indra/llcommon/llfasttimer.h @@ -127,8 +127,22 @@ public: #endif +#if (LL_DARWIN && defined(__arm64__)) -#if (LL_LINUX) && !(defined(__i386__) || defined(__amd64__)) + static U32 getCPUClockCount64() + { + U64 t = clock_gettime_nsec_np(CLOCK_UPTIME_RAW); + return t/1000; + } + + static U64 getCPUClockCount32() + { + return (U32) (getCPUClockCount64() >> 8); + } + +#endif + +#if (LL_LINUX && !(defined(__i386__) || defined(__amd64__))) // // Linux implementation of CPU clock - non-x86. // This is accurate but SLOW! Only use out of desperation. @@ -159,7 +173,7 @@ public: #endif // (LL_LINUX) && !(defined(__i386__) || defined(__amd64__)) -#if (LL_LINUX || LL_DARWIN) && (defined(__i386__) || defined(__amd64__)) +#if (LL_LINUX || LL_DARWIN || __FreeBSD__) && (defined(__i386__) || defined(__amd64__)) // // Mac+Linux FAST x86 implementation of CPU clock static U32 getCPUClockCount32() diff --git a/indra/llcommon/llmemory.h b/indra/llcommon/llmemory.h index 80cfe554c4..671ebc38e2 100644 --- a/indra/llcommon/llmemory.h +++ b/indra/llcommon/llmemory.h @@ -52,7 +52,7 @@ class LLMutex ; #define LL_DEFAULT_HEAP_ALIGN 8 #elif LL_DARWIN #define LL_DEFAULT_HEAP_ALIGN 16 -#elif LL_LINUX +#elif LL_LINUX || __FreeBSD__ #define LL_DEFAULT_HEAP_ALIGN 8 #endif @@ -71,7 +71,11 @@ LL_COMMON_API void ll_assert_aligned_func(uintptr_t ptr,U32 alignment); #define ll_assert_aligned(ptr,alignment) #endif +#if defined(__i386__) || defined(__x86_64__) #include <xmmintrin.h> +#else +#include <sse2neon.h> +#endif template <typename T> T* LL_NEXT_ALIGNED_ADDRESS(T* address) { @@ -85,7 +89,7 @@ template <typename T> T* LL_NEXT_ALIGNED_ADDRESS_64(T* address) (uintptr_t(address) + 0x3F) & ~0x3F); } -#if LL_LINUX || LL_DARWIN +#if LL_LINUX || LL_DARWIN || __FreeBSD__ #define LL_ALIGN_PREFIX(x) #define LL_ALIGN_POSTFIX(x) __attribute__((aligned(x))) diff --git a/indra/llcommon/llpreprocessor.h b/indra/llcommon/llpreprocessor.h index 0248e8f8b9..13beb25558 100644 --- a/indra/llcommon/llpreprocessor.h +++ b/indra/llcommon/llpreprocessor.h @@ -32,9 +32,11 @@ #ifdef LL_LINUX #define __ENABLE_WSTRING #include <endian.h> +#elif defined(__FreeBSD__) +#include <sys/endian.h> #endif // LL_LINUX -#if (defined(LL_WINDOWS) || (defined(LL_LINUX) && (__BYTE_ORDER == __LITTLE_ENDIAN)) || (defined(LL_DARWIN) && defined(__LITTLE_ENDIAN__))) +#if (defined(LL_WINDOWS) || (defined(LL_LINUX) && (__BYTE_ORDER == __LITTLE_ENDIAN)) || (defined(LL_DARWIN) && defined(__LITTLE_ENDIAN__)) || (defined(__FreeBSD__) && (_BYTE_ORDER == _LITTLE_ENDIAN))) #define LL_LITTLE_ENDIAN 1 #else #define LL_BIG_ENDIAN 1 @@ -80,7 +82,7 @@ #endif // Deal with minor differences on Unixy OSes. -#if LL_DARWIN || LL_LINUX +#if LL_DARWIN || LL_LINUX || __FreeBSD__ // Different name, same functionality. #define stricmp strcasecmp #define strnicmp strncasecmp diff --git a/indra/llcommon/llprocess.cpp b/indra/llcommon/llprocess.cpp index 912e596c3f..40ef0ddf9b 100644 --- a/indra/llcommon/llprocess.cpp +++ b/indra/llcommon/llprocess.cpp @@ -691,10 +691,22 @@ LLProcess::LLProcess(const LLSDOrParams& params): // terminate with a null pointer argv.push_back(NULL); + // create an env vector for the child process + std::vector<const char*> envv; + + // Add environment value assignments. See above remarks about c_str(). + for (const std::string& env : params.envs) + { + envv.push_back(env.c_str()); + } + + // terminate with a null pointer + envv.push_back(NULL); + // Launch! The NULL would be the environment block, if we were passing // one. Hand-expand chkapr() macro so we can fill in the actual command // string instead of the variable names. - if (ll_apr_warn_status(apr_proc_create(&mProcess, argv[0], &argv[0], NULL, procattr, + if (ll_apr_warn_status(apr_proc_create(&mProcess, argv[0], &argv[0], &envv[0], procattr, mPool))) { LLTHROW(LLProcessError(STRINGIZE(params << " failed"))); diff --git a/indra/llcommon/llprocess.h b/indra/llcommon/llprocess.h index 166da8f424..4e7451c4a1 100644 --- a/indra/llcommon/llprocess.h +++ b/indra/llcommon/llprocess.h @@ -40,7 +40,7 @@ #if LL_WINDOWS #include "llwin32headerslean.h" // for HANDLE -#elif LL_LINUX +#elif LL_LINUX || __FreeBSD__ #if defined(Status) #undef Status #endif @@ -165,6 +165,7 @@ public: Params(): executable("executable"), args("args"), + envs("envs"), cwd("cwd"), autokill("autokill", true), attached("attached", true), @@ -182,6 +183,10 @@ public: * argument while assembling the command line. */ Multiple<std::string> args; + /** + * zero or more additional command-line environment values. + */ + Multiple<std::string> envs; /// current working directory, if need it changed Optional<std::string> cwd; /// implicitly kill child process on termination of parent, whether diff --git a/indra/llcommon/llprocessor.cpp b/indra/llcommon/llprocessor.cpp index 9d53b9be35..0e180d9915 100644 --- a/indra/llcommon/llprocessor.cpp +++ b/indra/llcommon/llprocessor.cpp @@ -638,6 +638,13 @@ public: { getCPUIDInfo(); uint64_t frequency = getSysctlInt64("hw.cpufrequency"); + if (!frequency) { + auto tbfrequency = getSysctlInt64("hw.tbfrequency"); + struct clockinfo clockrate; + auto clockrate_len = sizeof(clockrate); + if (!sysctlbyname("kern.clockrate", &clockrate, &clockrate_len, NULL, 0)) + frequency = tbfrequency * clockrate.hz; + } setInfo(eFrequency, (F64)frequency / (F64)1000000); } @@ -742,12 +749,14 @@ private: : "0" (level)) #endif +#if __i386__ || __x86_64__ unsigned int eax, ebx, ecx, edx; __cpuid(0x1, eax, ebx, ecx, edx); if(feature_infos[0] != (S32)edx) { LL_WARNS() << "machdep.cpu.feature_bits doesn't match expected cpuid result!" << LL_ENDL; } +#endif // __i386__ || __x86_64__ #endif // LL_RELEASE_FOR_DOWNLOAD @@ -792,20 +801,150 @@ private: } }; +#elif __FreeBSD__ + +#include <sys/sysctl.h> +class LLProcessorInfoFreeBSDImpl : public LLProcessorInfoImpl +{ +public: + LLProcessorInfoFreeBSDImpl() + { + size_t len = 0; + using std::string; + + char cpu_brand_string[0x40]; + len = sizeof cpu_brand_string; + memset(cpu_brand_string, '\0', len); + sysctlbyname("hw.model", (void *)cpu_brand_string, &len, + NULL, 0); + cpu_brand_string[0x3f] = '\0'; + setInfo(eBrandName, cpu_brand_string); + + uint64_t cpu_frequency = 0; + len = sizeof cpu_frequency; + sysctlbyname("hw.clockrate", (void *)&cpu_frequency, &len, + NULL, 0); + setInfo(eFrequency, (F64)cpu_frequency); + + auto dmesgboot = LLFile::fopen("/var/run/dmesg.boot", "rb"); + std::ostringstream s; + if (dmesgboot) { + char line[MAX_STRING]; + memset(line, 0, MAX_STRING); + while (fgets(line, MAX_STRING, dmesgboot)) { + line[strlen(line) - 1] = ' '; + s << line; + s << std::endl; + } + fclose(dmesgboot); + s << std::endl; + } + + auto dmesgboot_str = s.str(); + int decimal; + + auto idx1 = dmesgboot_str.find_first_of("\"") + 1; + auto idx2 = (idx1 != string::npos) + ? dmesgboot_str.find_first_of("\"", idx1) + : string::npos; + auto vendor = dmesgboot_str.substr(idx1, idx2 - idx1); + if (vendor.length() > 0) setInfo(eVendor, vendor.c_str()); + + idx1 = dmesgboot_str.find_first_of("=", idx2); + idx1 = dmesgboot_str.find_first_of("=", idx1 + 1) + 3; + idx2 = dmesgboot_str.find_first_of(" ", idx1); + auto family = dmesgboot_str.substr(idx1, idx2 - idx1); + std::istringstream(family) >> std::hex >> decimal; + setInfo(eFamily, decimal); + setInfo(eFamilyName, compute_CPUFamilyName(vendor.c_str(), + decimal, 0)); + + idx1 = dmesgboot_str.find_first_of("=", idx2) + 3; + idx2 = dmesgboot_str.find_first_of(" ", idx1); + auto model = dmesgboot_str.substr(idx1, idx2 - idx1); + std::istringstream(model) >> std::hex >> decimal; + setInfo(eModel, decimal); + + idx1 = dmesgboot_str.find_first_of("=", idx2) + 1; + idx2 = dmesgboot_str.find_first_of("\n", idx1); + auto stepping = dmesgboot_str.substr(idx1, idx2 - idx1); + setInfo(eStepping, std::stoi(stepping)); + + if (dmesgboot_str.find(",SSE,") != string::npos) + setExtension(cpu_feature_names[eSSE_Ext]); + + if (dmesgboot_str.find(",SSE2,") != string::npos) + setExtension(cpu_feature_names[eSSE2_Ext]); + + if (dmesgboot_str.find("<SSE3,") != string::npos) + setExtension(cpu_feature_names[eSSE3_Features]); + + if (dmesgboot_str.find(",SSSE3,") != string::npos) + setExtension(cpu_feature_names[eSSE3S_Features]); + + if (dmesgboot_str.find(",SSE4.1,") != string::npos) + setExtension(cpu_feature_names[eSSE4_1_Features]); + + if (dmesgboot_str.find(",SSE4.2,") != string::npos) + setExtension(cpu_feature_names[eSSE4_2_Features]); + + if (dmesgboot_str.find(",SSE4A,") != string::npos) + setExtension(cpu_feature_names[eSSE4a_Features]); + } + + virtual ~LLProcessorInfoFreeBSDImpl() {} +}; + #elif LL_LINUX + +// *NOTE:Mani - eww, macros! srry. +#define LLPI_SET_INFO_STRING(llpi_id, cpuinfo_id) \ + if (!cpuinfo[cpuinfo_id].empty()) \ + { setInfo(llpi_id, cpuinfo[cpuinfo_id]);} + +#define LLPI_SET_INFO_INT(llpi_id, cpuinfo_id) \ + {\ + S32 result; \ + if (!cpuinfo[cpuinfo_id].empty() \ + && LLStringUtil::convertToS32(cpuinfo[cpuinfo_id], result)) \ + { setInfo(llpi_id, result);} \ + } + const char CPUINFO_FILE[] = "/proc/cpuinfo"; -class LLProcessorInfoLinuxImpl : public LLProcessorInfoImpl -{ +class LLProcessorInfoLinuxImpl : public LLProcessorInfoImpl { public: - LLProcessorInfoLinuxImpl() - { + LLProcessorInfoLinuxImpl() { get_proc_cpuinfo(); } virtual ~LLProcessorInfoLinuxImpl() {} + private: + F64 getCPUMaxMHZ() + { + // Nicky: We just look into cpu0. In theory we could iterate over all cores + // "/sys/devices/system/cpu/cpu*/cpufreq/cpuinfo_max_freq" + // But those should not fluctuate that much? + std::ifstream fIn { "/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq" }; + + if( !fIn.is_open() ) + return 0.0; + + std::string strLine; + fIn >> strLine; + if( strLine.empty() ) + return 0.0l; + + F64 mhz {}; + if( !LLStringUtil::convertToF64(strLine, mhz ) ) + return 0.0; + + mhz = mhz / 1000.0; + return mhz; + } + void get_proc_cpuinfo() { std::map< std::string, std::string > cpuinfo; @@ -834,30 +973,23 @@ private: std::string llinename(linename); LLStringUtil::toLower(llinename); std::string lineval( spacespot + 1, nlspot ); - cpuinfo[ llinename ] = lineval; + cpuinfo[ llinename ] = lineval; } fclose(cpuinfo_fp); } # if LL_X86 -// *NOTE:Mani - eww, macros! srry. -#define LLPI_SET_INFO_STRING(llpi_id, cpuinfo_id) \ - if (!cpuinfo[cpuinfo_id].empty()) \ - { setInfo(llpi_id, cpuinfo[cpuinfo_id]);} - -#define LLPI_SET_INFO_INT(llpi_id, cpuinfo_id) \ - {\ - S32 result; \ - if (!cpuinfo[cpuinfo_id].empty() \ - && LLStringUtil::convertToS32(cpuinfo[cpuinfo_id], result)) \ - { setInfo(llpi_id, result);} \ + F64 mhzFromSys = getCPUMaxMHZ(); + F64 mhzFromProc {}; + if( !LLStringUtil::convertToF64(cpuinfo["cpu mhz"], mhzFromProc ) ) + mhzFromProc = 0.0; + if (mhzFromSys > 1.0 && mhzFromSys > mhzFromProc ) + { + setInfo( eFrequency, mhzFromSys ); } - - F64 mhz; - if (LLStringUtil::convertToF64(cpuinfo["cpu mhz"], mhz) - && 200.0 < mhz && mhz < 10000.0) + else if ( 200.0 < mhzFromProc && mhzFromProc < 10000.0) { - setInfo(eFrequency,(F64)(mhz)); + setInfo(eFrequency,(F64)(mhzFromProc)); } LLPI_SET_INFO_STRING(eBrandName, "model name"); @@ -867,7 +999,7 @@ private: LLPI_SET_INFO_INT(eModel, "model"); - S32 family; + S32 family{}; if (!cpuinfo["cpu family"].empty() && LLStringUtil::convertToS32(cpuinfo["cpu family"], family)) { @@ -972,6 +1104,9 @@ LLProcessorInfo::LLProcessorInfo() : mImpl(NULL) #elif LL_DARWIN static LLProcessorInfoDarwinImpl the_impl; mImpl = &the_impl; +#elif __FreeBSD__ + static LLProcessorInfoFreeBSDImpl the_impl; + mImpl = &the_impl; #else static LLProcessorInfoLinuxImpl the_impl; mImpl = &the_impl; diff --git a/indra/llcommon/llsdutil.cpp b/indra/llcommon/llsdutil.cpp index dd3a58c26d..2d3d7d8b73 100644 --- a/indra/llcommon/llsdutil.cpp +++ b/indra/llcommon/llsdutil.cpp @@ -36,7 +36,7 @@ # include <winsock2.h> // for htonl #elif LL_LINUX # include <netinet/in.h> -#elif LL_DARWIN +#elif LL_DARWIN || __FreeBSD__ # include <arpa/inet.h> #endif @@ -161,7 +161,7 @@ LLSD ll_binary_from_string(const LLSD& sd) char* ll_print_sd(const LLSD& sd) { const U32 bufferSize = 10 * 1024; - static char buffer[bufferSize]; + static char buffer[bufferSize + 1]; std::ostringstream stream; //stream.rdbuf()->pubsetbuf(buffer, bufferSize); stream << LLSDOStreamer<LLSDXMLFormatter>(sd); @@ -183,7 +183,7 @@ char* ll_pretty_print_sd_ptr(const LLSD* sd) char* ll_pretty_print_sd(const LLSD& sd) { const U32 bufferSize = 100 * 1024; - static char buffer[bufferSize]; + static char buffer[bufferSize + 1]; std::ostringstream stream; //stream.rdbuf()->pubsetbuf(buffer, bufferSize); stream << LLSDOStreamer<LLSDXMLFormatter>(sd, LLSDFormatter::OPTIONS_PRETTY); diff --git a/indra/llcommon/llsys.cpp b/indra/llcommon/llsys.cpp index cfb05873df..546f35bc81 100644 --- a/indra/llcommon/llsys.cpp +++ b/indra/llcommon/llsys.cpp @@ -81,8 +81,13 @@ using namespace llsd; # include <sys/sysinfo.h> # include <stdexcept> const char MEMINFO_FILE[] = "/proc/meminfo"; +#ifdef __GNU__ # include <gnu/libc-version.h> #endif +#elif __FreeBSD__ +# include <sys/sysctl.h> +# include <sys/utsname.h> +#endif LLCPUInfo gSysCPU; @@ -337,6 +342,8 @@ LLOSInfo::LLOSInfo() : mOSString = mOSStringSimple; } +#ifdef __GNU__ + const char OS_VERSION_MATCH_EXPRESSION[] = "([0-9]+)\\.([0-9]+)(\\.([0-9]+))?"; boost::regex os_version_parse(OS_VERSION_MATCH_EXPRESSION); boost::smatch matched; @@ -400,6 +407,8 @@ LLOSInfo::LLOSInfo() : LL_WARNS("AppInit") << "glibc version '" << glibc_version << "' cannot be parsed to three numbers; using all zeros" << LL_ENDL; } +#endif // __GNU__ + #else struct utsname un; @@ -426,6 +435,13 @@ LLOSInfo::LLOSInfo() : if (simple.length() > 0) mOSStringSimple = simple; } + else if (ostype == "FreeBSD") + { + // Only care about major and minor FreeBSD versions, truncate at first '-' + std::string simple = mOSStringSimple.substr(0, mOSStringSimple.find_first_of("-", 0)); + if (simple.length() > 0) + mOSStringSimple = simple; + } } else { @@ -501,57 +517,46 @@ const S32 LLOSInfo::getOSBitness() const return mOSBitness; } -//static -U32 LLOSInfo::getProcessVirtualSizeKB() -{ - U32 virtual_size = 0; -#if LL_LINUX -# define STATUS_SIZE 2048 - LLFILE* status_filep = LLFile::fopen("/proc/self/status", "rb"); - if (status_filep) - { - S32 numRead = 0; - char buff[STATUS_SIZE]; /* Flawfinder: ignore */ +namespace { - size_t nbytes = fread(buff, 1, STATUS_SIZE-1, status_filep); - buff[nbytes] = '\0'; + U32 readFromProcStat( std::string entryName ) + { + U32 val{}; +#if LL_LINUX + constexpr U32 STATUS_SIZE = 2048; - // All these guys return numbers in KB - char *memp = strstr(buff, "VmSize:"); - if (memp) + LLFILE* status_filep = LLFile::fopen("/proc/self/status", "rb"); + if (status_filep) { - numRead += sscanf(memp, "%*s %u", &virtual_size); + char buff[STATUS_SIZE]; /* Flawfinder: ignore */ + + size_t nbytes = fread(buff, 1, STATUS_SIZE-1, status_filep); + buff[nbytes] = '\0'; + + // All these guys return numbers in KB + char *memp = strstr(buff, entryName.c_str()); + if (memp) + { + (void) sscanf(memp, "%*s %u", &val); + } + fclose(status_filep); } - fclose(status_filep); - } #endif - return virtual_size; + return val; + } + } //static -U32 LLOSInfo::getProcessResidentSizeKB() +U32 LLOSInfo::getProcessVirtualSizeKB() { - U32 resident_size = 0; -#if LL_LINUX - LLFILE* status_filep = LLFile::fopen("/proc/self/status", "rb"); - if (status_filep != NULL) - { - S32 numRead = 0; - char buff[STATUS_SIZE]; /* Flawfinder: ignore */ - - size_t nbytes = fread(buff, 1, STATUS_SIZE-1, status_filep); - buff[nbytes] = '\0'; + return readFromProcStat( "VmSize:" ); +} - // All these guys return numbers in KB - char *memp = strstr(buff, "VmRSS:"); - if (memp) - { - numRead += sscanf(memp, "%*s %u", &resident_size); - } - fclose(status_filep); - } -#endif - return resident_size; +//static +U32 LLOSInfo::getProcessResidentSizeKB() +{ + return readFromProcStat( "VmRSS:" ); } //static @@ -762,13 +767,17 @@ static U32Kilobytes LLMemoryAdjustKBResult(U32Kilobytes inKB) } #endif -#if LL_DARWIN +#if LL_DARWIN || __FreeBSD__ // static U32Kilobytes LLMemoryInfo::getHardwareMemSize() { // This might work on Linux as well. Someone check... uint64_t phys = 0; +#if LL_DARWIN int mib[2] = { CTL_HW, HW_MEMSIZE }; +#else + int mib[2] = { CTL_HW, HW_PHYSMEM }; +#endif size_t len = sizeof(phys); sysctl(mib, 2, &phys, &len, NULL, 0); @@ -782,7 +791,7 @@ U32Kilobytes LLMemoryInfo::getPhysicalMemoryKB() const #if LL_WINDOWS return LLMemoryAdjustKBResult(U32Kilobytes(mStatsMap["Total Physical KB"].asInteger())); -#elif LL_DARWIN +#elif LL_DARWIN || __FreeBSD__ return getHardwareMemSize(); #elif LL_LINUX diff --git a/indra/llcommon/llsys.h b/indra/llcommon/llsys.h index f97d49eeb1..3307285934 100644 --- a/indra/llcommon/llsys.h +++ b/indra/llcommon/llsys.h @@ -130,7 +130,7 @@ public: void stream(std::ostream& s) const; ///< output text info to s U32Kilobytes getPhysicalMemoryKB() const; -#if LL_DARWIN +#if LL_DARWIN || __FreeBSD__ static U32Kilobytes getHardwareMemSize(); // Because some Mac linkers won't let us reference extern gSysMemory from a different lib. #endif diff --git a/indra/llcommon/llthreadsafequeue.h b/indra/llcommon/llthreadsafequeue.h index 034e3f7897..85fcbbacac 100644 --- a/indra/llcommon/llthreadsafequeue.h +++ b/indra/llcommon/llthreadsafequeue.h @@ -452,7 +452,11 @@ ElementT LLThreadSafeQueue<ElementT, QueueT>::pop(void) // so we can finish draining the queue. pop_result popped = pop_(lock1, value); if (popped == POPPED) +#if LL_LINUX + return value; +#else return std::move(value); +#endif // Once the queue is DONE, there will never be any more coming. if (popped == DONE) diff --git a/indra/llcommon/lltimer.cpp b/indra/llcommon/lltimer.cpp index a3e871661c..5d0a70a382 100644 --- a/indra/llcommon/lltimer.cpp +++ b/indra/llcommon/lltimer.cpp @@ -35,7 +35,7 @@ #if LL_WINDOWS # include "llwin32headerslean.h" -#elif LL_LINUX || LL_DARWIN +#elif LL_LINUX || LL_DARWIN || __FreeBSD__ # include <errno.h> # include <sys/time.h> #else @@ -115,7 +115,7 @@ void ms_sleep(U32 ms) #endif -#elif LL_LINUX || LL_DARWIN +#elif LL_LINUX || LL_DARWIN || __FreeBSD__ static void _sleep_loop(struct timespec& thiswait) { struct timespec nextwait; @@ -233,7 +233,7 @@ F64 calc_clock_frequency() #endif // LL_WINDOWS -#if LL_LINUX || LL_DARWIN +#if LL_LINUX || LL_DARWIN || __FreeBSD__ // Both Linux and Mac use gettimeofday for accurate time F64 calc_clock_frequency() { diff --git a/indra/llcommon/lluuid.cpp b/indra/llcommon/lluuid.cpp index 3b37365ec7..931a6e340d 100644 --- a/indra/llcommon/lluuid.cpp +++ b/indra/llcommon/lluuid.cpp @@ -522,7 +522,7 @@ S32 LLUUID::getNodeID(unsigned char* node_id) #include <net/if.h> #include <net/if_types.h> #include <net/if_dl.h> -#include <net/route.h> +//#include <net/route.h> #include <ifaddrs.h> // static @@ -606,7 +606,7 @@ S32 LLUUID::getNodeID(unsigned char* node_id) #define HAVE_NETINET_IN_H #ifdef HAVE_NETINET_IN_H #include <netinet/in.h> -#if !LL_DARWIN +#if !LL_DARWIN && !__FreeBSD__ #include <linux/sockios.h> #endif #endif diff --git a/indra/llcommon/stdtypes.h b/indra/llcommon/stdtypes.h index 28e50b3d21..b40a718593 100644 --- a/indra/llcommon/stdtypes.h +++ b/indra/llcommon/stdtypes.h @@ -29,6 +29,7 @@ #include <cassert> #include <cfloat> #include <climits> +#include <cstddef> #include <limits> #include <type_traits> @@ -71,7 +72,7 @@ typedef unsigned __int64 U64; #else typedef long long int S64; typedef long long unsigned int U64; -#if LL_DARWIN || LL_LINUX +#if LL_DARWIN || LL_LINUX || __FreeBSD__ #define S64L(a) (a##LL) #define U64L(a) (a##ULL) #endif @@ -113,6 +114,10 @@ typedef U32 TPACKETID; #define FALSE (0) #endif +#if __FreeBSD__ +#undef NULL +#endif + #ifndef NULL #define NULL (0) #endif diff --git a/indra/llcommon/tests/llleap_test.cpp b/indra/llcommon/tests/llleap_test.cpp index fa48bcdefd..3fb25b4cef 100644 --- a/indra/llcommon/tests/llleap_test.cpp +++ b/indra/llcommon/tests/llleap_test.cpp @@ -35,7 +35,7 @@ // causes Windows abdominal pain such that it later fails code-signing in some // mysterious way. Entirely suppressing these LLLeap tests pushes the failure // rate MUCH lower. Can we re-enable them with a smaller data size on Windows? -const size_t BUFFERED_LENGTH = 100*1024; +const size_t BUFFERED_LENGTH = 1023*1024; #else // not Windows const size_t BUFFERED_LENGTH = 1023*1024; // try wrangling just under a megabyte of data diff --git a/indra/llcommon/tests/llstring_test.cpp b/indra/llcommon/tests/llstring_test.cpp index b18712b8e9..b68c63a15f 100644 --- a/indra/llcommon/tests/llstring_test.cpp +++ b/indra/llcommon/tests/llstring_test.cpp @@ -377,7 +377,7 @@ namespace tut { F32 value; std::string str_val("2147483647"); //0x7FFFFFFF - ensure("1: convertToF32 failed", LLStringUtil::convertToF32(str_val, value) && value == 2147483647); + ensure("1: convertToF32 failed", LLStringUtil::convertToF32(str_val, value) && value == 2147483647.f); str_val = "0"; ensure("2: convertToF32 failed", LLStringUtil::convertToF32(str_val, value) && value == 0); @@ -399,7 +399,7 @@ namespace tut { F64 value; std::string str_val("9223372036854775807"); //0x7FFFFFFFFFFFFFFF - ensure("1: convertToF64 failed", LLStringUtil::convertToF64(str_val, value) && value == 9223372036854775807LL); + ensure("1: convertToF64 failed", LLStringUtil::convertToF64(str_val, value) && value == 9223372036854775807.); str_val = "0"; ensure("2: convertToF64 failed", LLStringUtil::convertToF64(str_val, value) && value == 0.0F); diff --git a/indra/llcorehttp/CMakeLists.txt b/indra/llcorehttp/CMakeLists.txt index 5650c4c8ba..aa56407e35 100644 --- a/indra/llcorehttp/CMakeLists.txt +++ b/indra/llcorehttp/CMakeLists.txt @@ -8,9 +8,10 @@ include(OpenSSL) include(NGHTTP2) include(ZLIBNG) include(LLCoreHttp) +if (LL_TESTS) include(LLAddBuildTest) +endif () include(LLCommon) -include(Tut) include(bugsplat) set(llcorehttp_SOURCE_FILES @@ -92,6 +93,8 @@ target_include_directories( llcorehttp INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) # lead to circular dependencies (or in case of cmake, the first project declaring it's dependencies wins) target_include_directories( llcorehttp PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../llmessage) +include(LibraryInstall) + # tests set(LLCOREHTTP_TESTS ON CACHE BOOL "Build and run llcorehttp integration tests specifically") diff --git a/indra/llcrashlogger/CMakeLists.txt b/indra/llcrashlogger/CMakeLists.txt index 6ac73c0d32..3506a35c1e 100644 --- a/indra/llcrashlogger/CMakeLists.txt +++ b/indra/llcrashlogger/CMakeLists.txt @@ -21,3 +21,5 @@ list(APPEND llcrashlogger_SOURCE_FILES ${llcrashlogger_HEADER_FILES}) add_library(llcrashlogger ${llcrashlogger_SOURCE_FILES}) target_link_libraries( llcrashlogger llcommon llmessage llcorehttp llxml llfilesystem ) + +include(LibraryInstall) diff --git a/indra/llfilesystem/CMakeLists.txt b/indra/llfilesystem/CMakeLists.txt index 9f24f75eab..8d85f739b3 100644 --- a/indra/llfilesystem/CMakeLists.txt +++ b/indra/llfilesystem/CMakeLists.txt @@ -4,6 +4,9 @@ project(llfilesystem) include(00-Common) include(LLCommon) +if (LINUX OR CMAKE_SYSTEM_NAME MATCHES FreeBSD) + include(UnixInstall) +endif (LINUX OR CMAKE_SYSTEM_NAME MATCHES FreeBSD) set(llfilesystem_SOURCE_FILES lldir.cpp @@ -30,17 +33,17 @@ if (DARWIN) LIST(APPEND llfilesystem_HEADER_FILES lldir_mac.h) endif (DARWIN) -if (LINUX) +if (LINUX OR CMAKE_SYSTEM_NAME MATCHES FreeBSD) LIST(APPEND llfilesystem_SOURCE_FILES lldir_linux.cpp) LIST(APPEND llfilesystem_HEADER_FILES lldir_linux.h) if (INSTALL) set_source_files_properties(lldir_linux.cpp PROPERTIES COMPILE_FLAGS - "-DAPP_RO_DATA_DIR=\\\"${APP_SHARE_DIR}\\\"" + "-DAPP_RO_DATA_DIR=\\\"${APP_SHARE_DIR}\\\" -DAPP_LIBEXEC_DIR=\\\"${APP_LIBEXEC_DIR}\\\" -DAPP_PLUGIN_DIR=\\\"${INSTALL_LIBRARY_DIR}\\\"" ) endif (INSTALL) -endif (LINUX) +endif (LINUX OR CMAKE_SYSTEM_NAME MATCHES FreeBSD) if (WINDOWS) LIST(APPEND llfilesystem_SOURCE_FILES lldir_win32.cpp) @@ -55,6 +58,7 @@ target_link_libraries(llfilesystem llcommon ) target_include_directories( llfilesystem INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) +include(LibraryInstall) # Add tests if (LL_TESTS) diff --git a/indra/llfilesystem/lldir.cpp b/indra/llfilesystem/lldir.cpp index 8ee2c309a5..42e91963c1 100644 --- a/indra/llfilesystem/lldir.cpp +++ b/indra/llfilesystem/lldir.cpp @@ -386,7 +386,7 @@ std::string LLDir::buildSLOSCacheDir() const } else { - res = add(getOSCacheDir(), "SecondLife"); + res = add(getOSCacheDir(), "Megapahit"); } return res; } @@ -690,7 +690,7 @@ void LLDir::walkSearchSkinDirs(const std::string& subdir, const std::string& filename, const FUNCTION& function) const { - for (const std::string& skindir : mSearchSkinDirs) + for (std::string skindir : mSearchSkinDirs) { std::string subdir_path(add(skindir, subdir)); for (const std::string& subsubdir : subsubdirs) diff --git a/indra/llfilesystem/lldir_linux.cpp b/indra/llfilesystem/lldir_linux.cpp index b13b42c954..69cfedebc7 100644 --- a/indra/llfilesystem/lldir_linux.cpp +++ b/indra/llfilesystem/lldir_linux.cpp @@ -83,7 +83,11 @@ LLDir_Linux::LLDir_Linux() mExecutableFilename = ""; mExecutablePathAndName = ""; +#ifdef APP_LIBEXEC_DIR + mExecutableDir = APP_LIBEXEC_DIR; +#else mExecutableDir = tmp_str; +#endif mWorkingDir = tmp_str; #ifdef APP_RO_DATA_DIR mAppRODataDir = APP_RO_DATA_DIR; @@ -123,7 +127,7 @@ LLDir_Linux::LLDir_Linux() if ((path_end = strrchr(tmp_str,'/'))) { *path_end = '\0'; - mExecutableDir = tmp_str; + //mExecutableDir = tmp_str; mWorkingDir = tmp_str; mExecutableFilename = path_end+1; } @@ -133,7 +137,11 @@ LLDir_Linux::LLDir_Linux() } } +#ifdef APP_PLUGIN_DIR + mLLPluginDir = APP_PLUGIN_DIR; +#else mLLPluginDir = mExecutableDir + mDirDelimiter + "llplugin"; +#endif // *TODO: don't use /tmp, use $HOME/.secondlife/tmp or something. mTempDir = "/tmp"; @@ -205,7 +213,7 @@ void LLDir_Linux::initAppDirs(const std::string &app_name, LL_WARNS() << "Couldn't create LL_PATH_CACHE dir " << getExpandedFilename(LL_PATH_CACHE,"") << LL_ENDL; } - mCAFile = getExpandedFilename(LL_PATH_EXECUTABLE, "ca-bundle.crt"); + mCAFile = add(mAppRODataDir, "ca-bundle.crt"); } U32 LLDir_Linux::countFilesInDir(const std::string &dirname, const std::string &mask) diff --git a/indra/llfilesystem/lldir_linux.h b/indra/llfilesystem/lldir_linux.h index bd031bd7bb..f9b0427ccd 100644 --- a/indra/llfilesystem/lldir_linux.h +++ b/indra/llfilesystem/lldir_linux.h @@ -24,7 +24,7 @@ * $/LicenseInfo$ */ -#if !LL_LINUX +#if !LL_LINUX && !__FreeBSD__ #error This header must not be included when compiling for any target other than Linux. Consider including lldir.h instead. #endif // !LL_LINUX diff --git a/indra/llfilesystem/lldir_mac.cpp b/indra/llfilesystem/lldir_mac.cpp index b9be75c528..b25c654e31 100644 --- a/indra/llfilesystem/lldir_mac.cpp +++ b/indra/llfilesystem/lldir_mac.cpp @@ -64,7 +64,7 @@ LLDir_Mac::LLDir_Mac() { mDirDelimiter = "/"; - const std::string secondLifeString = "SecondLife"; + const std::string secondLifeString = "Megapahit"; std::string executablepathstr = getSystemExecutableFolder(); diff --git a/indra/llimage/CMakeLists.txt b/indra/llimage/CMakeLists.txt index cc75c463bc..f55d9fdf5e 100644 --- a/indra/llimage/CMakeLists.txt +++ b/indra/llimage/CMakeLists.txt @@ -8,9 +8,13 @@ include(LLImage) include(JPEG) include(LLKDU) include(ZLIBNG) +if (LL_TESTS) include(LLAddBuildTest) +endif () include(bugsplat) +if (LL_TESTS) include(Tut) +endif () set(llimage_SOURCE_FILES llimagebmp.cpp @@ -63,6 +67,18 @@ target_link_libraries(llimage ll::libjpeg ) +if (NOT (USE_AUTOBUILD_3P OR USE_CONAN)) + if (CMAKE_CXX_COMPILER_ID MATCHES "GNU") + set_source_files_properties(llimageworker.cpp PROPERTIES COMPILE_FLAGS -Wno-int-in-bool-context) + set_source_files_properties( + llimage.cpp + llimagefilter.cpp + PROPERTIES COMPILE_FLAGS -Wno-stringop-overflow) + endif() +endif () + +include(LibraryInstall) + # Add tests if (LL_TESTS) SET(llimage_TEST_SOURCE_FILES diff --git a/indra/llimage/llimagejpeg.cpp b/indra/llimage/llimagejpeg.cpp index 0e7ec365d4..dd3efb3459 100644 --- a/indra/llimage/llimagejpeg.cpp +++ b/indra/llimage/llimagejpeg.cpp @@ -79,11 +79,13 @@ bool LLImageJPEG::updateData() //try/catch will crash on Mac and Linux if LLImageJPEG::errorExit throws an error //so as instead, we use setjmp/longjmp to avoid this crash, which is the best we can get. --bao // +#if !(LL_DARWIN && defined(__arm64__)) if(setjmp(sSetjmpBuffer)) { jpeg_destroy_decompress(&cinfo); return false; } +#endif try { // Now we can initialize the JPEG decompression object. @@ -223,11 +225,13 @@ bool LLImageJPEG::decode(LLImageRaw* raw_image, F32 decode_time) //try/catch will crash on Mac and Linux if LLImageJPEG::errorExit throws an error //so as instead, we use setjmp/longjmp to avoid this crash, which is the best we can get. --bao // +#if !(LL_DARWIN && defined(__arm64__)) if(setjmp(sSetjmpBuffer)) { jpeg_destroy_decompress(&cinfo); return true; // done } +#endif try { // Now we can initialize the JPEG decompression object. @@ -433,7 +437,9 @@ void LLImageJPEG::errorExit( j_common_ptr cinfo ) jpeg_destroy(cinfo); // Return control to the setjmp point +#if !(LL_DARWIN && defined(__arm64__)) longjmp(sSetjmpBuffer, 1) ; +#endif } // Decide whether to emit a trace or warning message. @@ -545,6 +551,7 @@ bool LLImageJPEG::encode( const LLImageRaw* raw_image, F32 encode_time ) //try/catch will crash on Mac and Linux if LLImageJPEG::errorExit throws an error //so as instead, we use setjmp/longjmp to avoid this crash, which is the best we can get. --bao // +#if !(LL_DARWIN && defined(__arm64__)) if( setjmp(sSetjmpBuffer) ) { // If we get here, the JPEG code has signaled an error. @@ -555,6 +562,7 @@ bool LLImageJPEG::encode( const LLImageRaw* raw_image, F32 encode_time ) mOutputBufferSize = 0; return false; } +#endif try { diff --git a/indra/llimagej2coj/CMakeLists.txt b/indra/llimagej2coj/CMakeLists.txt index 93e85668dd..5a2aac9e84 100644 --- a/indra/llimagej2coj/CMakeLists.txt +++ b/indra/llimagej2coj/CMakeLists.txt @@ -21,9 +21,11 @@ list(APPEND llimagej2coj_SOURCE_FILES ${llimagej2coj_HEADER_FILES}) add_library (llimagej2coj ${llimagej2coj_SOURCE_FILES}) +include_directories( ${CMAKE_SOURCE_DIR}/llimage ) target_link_libraries( llimagej2coj llcommon - llimage + #llimage ll::openjpeg ) +include(LibraryInstall) diff --git a/indra/llimagej2coj/llimagej2coj.cpp b/indra/llimagej2coj/llimagej2coj.cpp index 9a4e382183..a64ae8e55c 100644 --- a/indra/llimagej2coj/llimagej2coj.cpp +++ b/indra/llimagej2coj/llimagej2coj.cpp @@ -28,9 +28,9 @@ #include "llimagej2coj.h" // this is defined so that we get static linking. -#include "openjpeg.h" -#include "event.h" -#include "cio.h" +#include <openjpeg-2.5/openjpeg.h> +#include <openjpeg-2.5/event.h> +#include <openjpeg-2.5/cio.h> #define MAX_ENCODED_DISCARD_LEVELS 5 @@ -576,7 +576,6 @@ public: for (S32 c = 0; c < numcomps; c++) { cmptparm[c].prec = 8; - cmptparm[c].bpp = 8; cmptparm[c].sgnd = 0; cmptparm[c].dx = parameters.subsampling_dx; cmptparm[c].dy = parameters.subsampling_dy; diff --git a/indra/llinventory/CMakeLists.txt b/indra/llinventory/CMakeLists.txt index 93a586759f..88a2c33ae0 100644 --- a/indra/llinventory/CMakeLists.txt +++ b/indra/llinventory/CMakeLists.txt @@ -59,6 +59,8 @@ add_library (llinventory ${llinventory_SOURCE_FILES}) target_link_libraries( llinventory llcommon llmath llmessage llxml ) target_include_directories( llinventory INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) +include(LibraryInstall) + #add unit tests if (LL_TESTS) INCLUDE(LLAddBuildTest) diff --git a/indra/llinventory/llsettingsbase.cpp b/indra/llinventory/llsettingsbase.cpp index c1893eff41..145a44240a 100644 --- a/indra/llinventory/llsettingsbase.cpp +++ b/indra/llinventory/llsettingsbase.cpp @@ -396,6 +396,7 @@ bool LLSettingsBase::validate() LLSD LLSettingsBase::settingValidation(LLSD &settings, validation_list_t &validations, bool partial) { + using boost::placeholders::_1, boost::placeholders::_2; static Validator validateName(SETTING_NAME, false, LLSD::TypeString, boost::bind(&Validator::verifyStringLength, _1, _2, 63)); static Validator validateId(SETTING_ID, false, LLSD::TypeUUID); static Validator validateHash(SETTING_HASH, false, LLSD::TypeInteger); diff --git a/indra/llinventory/llsettingssky.cpp b/indra/llinventory/llsettingssky.cpp index e14b2f25ed..902a66b0b2 100644 --- a/indra/llinventory/llsettingssky.cpp +++ b/indra/llinventory/llsettingssky.cpp @@ -150,6 +150,7 @@ const F32 LLSettingsSky::DOME_RADIUS(15000.f); namespace { + using boost::placeholders::_1, boost::placeholders::_2; LLSettingsSky::validation_list_t legacyHazeValidationList() { diff --git a/indra/llinventory/llsettingswater.cpp b/indra/llinventory/llsettingswater.cpp index 161b8cda25..a6a25b0953 100644 --- a/indra/llinventory/llsettingswater.cpp +++ b/indra/llinventory/llsettingswater.cpp @@ -223,6 +223,7 @@ LLSettingsWater::validation_list_t LLSettingsWater::validationList() if (validation.empty()) { + using boost::placeholders::_1, boost::placeholders::_2; validation.push_back(Validator(SETTING_BLUR_MULTIPLIER, true, LLSD::TypeReal, boost::bind(&Validator::verifyFloatRange, _1, _2, llsd::array(-0.5f, 0.5f)))); validation.push_back(Validator(SETTING_FOG_COLOR, true, LLSD::TypeArray, diff --git a/indra/llmath/CMakeLists.txt b/indra/llmath/CMakeLists.txt index eb29df245a..c0a62ad225 100644 --- a/indra/llmath/CMakeLists.txt +++ b/indra/llmath/CMakeLists.txt @@ -59,6 +59,7 @@ set(llmath_HEADER_FILES llmath.h llmatrix3a.h llmatrix3a.inl + llmatrix4a.h llmodularmath.h lloctree.h llperlin.h @@ -97,11 +98,20 @@ set(llmath_HEADER_FILES list(APPEND llmath_SOURCE_FILES ${llmath_HEADER_FILES}) +include_directories(${LIBS_PREBUILT_DIR}/include) + add_library (llmath ${llmath_SOURCE_FILES}) target_link_libraries(llmath llcommon llmeshoptimizer) target_include_directories( llmath INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) +if (USESYSTEMLIBS AND CMAKE_CXX_COMPILER_ID MATCHES "GNU") + set_source_files_properties(llcalc.cpp PROPERTIES + COMPILE_FLAGS -Wno-dangling-pointer) +endif () + +include(LibraryInstall) + # Add tests if (LL_TESTS) include(LLAddBuildTest) diff --git a/indra/llmath/llcalcparser.h b/indra/llmath/llcalcparser.h index e8fdcc9ae3..b40001cf7e 100644 --- a/indra/llmath/llcalcparser.h +++ b/indra/llmath/llcalcparser.h @@ -131,14 +131,14 @@ struct LLCalcParser : grammar<LLCalcParser> power = unary_expr[power.value = arg1] >> - *('^' >> assert_syntax(unary_expr[power.value = phoenix::bind(&powf)(power.value, arg1)])) + *('^' >> assert_syntax(unary_expr[power.value = phoenix::bind(&LLCalcParser::_pow)(self, power.value, arg1)])) ; term = power[term.value = arg1] >> *(('*' >> assert_syntax(power[term.value *= arg1])) | ('/' >> assert_syntax(power[term.value /= arg1])) | - ('%' >> assert_syntax(power[term.value = phoenix::bind(&fmodf)(term.value, arg1)])) + ('%' >> assert_syntax(power[term.value = phoenix::bind(&LLCalcParser::_fmod)(self, term.value, arg1)])) ) ; @@ -177,6 +177,8 @@ private: F32 _floor(const F32& a) const { return (F32)llfloor(a); } F32 _ceil(const F32& a) const { return llceil(a); } F32 _atan2(const F32& a,const F32& b) const { return atan2(a,b); } + F32 _pow(const F32& a, const F32& b) const { return powf(a, b); } + F32 _fmod(const F32&a, const F32& b) const { return fmodf(a, b); } LLCalc::calc_map_t* mConstants; LLCalc::calc_map_t* mVariables; diff --git a/indra/llmath/llsimdmath.h b/indra/llmath/llsimdmath.h index 40953dc2e8..590d8de92f 100644 --- a/indra/llmath/llsimdmath.h +++ b/indra/llmath/llsimdmath.h @@ -31,7 +31,7 @@ #error "Please include llmath.h before this file." #endif -#if ( ( LL_DARWIN || LL_LINUX ) && !(__SSE2__) ) || ( LL_WINDOWS && ( _M_IX86_FP < 2 && ADDRESS_SIZE == 32 ) ) +#if ( ( LL_DARWIN || LL_LINUX ) && !(__SSE2__ || __ARM_NEON) ) || ( LL_WINDOWS && ( _M_IX86_FP < 2 && ADDRESS_SIZE == 32 ) ) #error SSE2 not enabled. LLVector4a and related class will not compile. #endif @@ -39,8 +39,12 @@ #include <stdint.h> #endif +#if defined(__i386__) || defined(__x86_64__) #include <xmmintrin.h> #include <emmintrin.h> +#else +#include <sse2neon.h> +#endif #include "llmemory.h" #include "llsimdtypes.h" diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index f3db9424d9..8bcfd591b4 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -55,7 +55,11 @@ #include "mikktspace/mikktspace.hh" +#if LL_USESYSTEMLIBS +#include <meshoptimizer.h> +#else #include "meshoptimizer/meshoptimizer.h" +#endif #define DEBUG_SILHOUETTE_BINORMALS 0 #define DEBUG_SILHOUETTE_NORMALS 0 // TomY: Use this to display normals using the silhouette diff --git a/indra/llmeshoptimizer/CMakeLists.txt b/indra/llmeshoptimizer/CMakeLists.txt index dfac44c296..100e4448cb 100644 --- a/indra/llmeshoptimizer/CMakeLists.txt +++ b/indra/llmeshoptimizer/CMakeLists.txt @@ -25,10 +25,12 @@ list(APPEND llmeshoptimizer_SOURCE_FILES ${llmeshoptimizer_HEADER_FILES}) add_library (llmeshoptimizer ${llmeshoptimizer_SOURCE_FILES}) target_include_directories( llmeshoptimizer INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) +include_directories(${CMAKE_SOURCE_DIR}/llmath) target_link_libraries(llmeshoptimizer llcommon - llmath ll::meshoptimizer) +include(LibraryInstall) + # Add tests diff --git a/indra/llmeshoptimizer/llmeshoptimizer.cpp b/indra/llmeshoptimizer/llmeshoptimizer.cpp index 52ed9b9526..d79be48cf8 100644 --- a/indra/llmeshoptimizer/llmeshoptimizer.cpp +++ b/indra/llmeshoptimizer/llmeshoptimizer.cpp @@ -291,6 +291,9 @@ U64 LLMeshOptimizer::simplifyU32(U32 *destination, vertex_positions_stride, target_index_count, target_error, +#if MESHOPTIMIZER_VERSION >= 180 + 0, +#endif result_error ); } @@ -332,6 +335,9 @@ U64 LLMeshOptimizer::simplify(U16 *destination, vertex_positions_stride, target_index_count, target_error, +#if MESHOPTIMIZER_VERSION >= 180 + 0, +#endif result_error ); } diff --git a/indra/llmessage/CMakeLists.txt b/indra/llmessage/CMakeLists.txt index 5322139304..56c93ca5af 100644 --- a/indra/llmessage/CMakeLists.txt +++ b/indra/llmessage/CMakeLists.txt @@ -3,12 +3,14 @@ project(llmessage) include(00-Common) +if (LL_TESTS) include(LLAddBuildTest) +endif () include(LLCommon) include(LLCoreHttp) +if (LL_TESTS) include(LLAddBuildTest) -include(Python) -include(Tut) +endif () include(Python) set(llmessage_SOURCE_FILES @@ -130,6 +132,7 @@ set(llmessage_HEADER_FILES llmessagebuilder.h llmessageconfig.h llmessagereader.h + llmessagesenderinterface.h llmessagetemplate.h llmessagetemplateparser.h llmessagethrottle.h @@ -197,6 +200,15 @@ target_link_libraries( ) target_include_directories( llmessage INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) +if (NOT (USE_AUTOBUILD_3P OR USE_CONAN)) + if (CMAKE_CXX_COMPILER_ID MATCHES "GNU") + set_source_files_properties(llnamevalue.cpp PROPERTIES + COMPILE_FLAGS -Wno-stringop-truncation) + endif() +endif () + +include(LibraryInstall) + # tests if (LL_TESTS) SET(llmessage_TEST_SOURCE_FILES diff --git a/indra/llmessage/llnamevalue.cpp b/indra/llmessage/llnamevalue.cpp index 853ae7df82..05ea3f26a1 100644 --- a/indra/llmessage/llnamevalue.cpp +++ b/indra/llmessage/llnamevalue.cpp @@ -967,4 +967,3 @@ std::ostream& operator<<(std::ostream& s, const LLNameValue &a) } return s; } - diff --git a/indra/llmessage/llproxy.cpp b/indra/llmessage/llproxy.cpp index 864e68998c..d713cb20d9 100644 --- a/indra/llmessage/llproxy.cpp +++ b/indra/llmessage/llproxy.cpp @@ -465,7 +465,7 @@ void LLProxy::applyProxySettings(CURL* handle) /** * @brief Send one TCP packet and receive one in return. * - * This operation is done synchronously with a 1000ms timeout. Therefore, it should not be used when a blocking + * This operation is done synchronously with a 100ms timeout. Therefore, it should not be used when a blocking * operation would impact the operation of the viewer. * * @param handle_ptr Pointer to a connected LLSocket of type STREAM_TCP. @@ -482,7 +482,7 @@ static apr_status_t tcp_blocking_handshake(LLSocket::ptr_t handle, char * dataou apr_size_t expected_len = outlen; - handle->setBlocking(1000); + handle->setBlocking(100000); // 100ms, 100000us. Should be sufficient for localhost, nearby network rv = apr_socket_send(apr_socket, dataout, &outlen); if (APR_SUCCESS != rv) @@ -498,8 +498,6 @@ static apr_status_t tcp_blocking_handshake(LLSocket::ptr_t handle, char * dataou rv = -1; } - ms_sleep(1); - if (APR_SUCCESS == rv) { expected_len = maxinlen; diff --git a/indra/llmessage/lltemplatemessagereader.cpp b/indra/llmessage/lltemplatemessagereader.cpp index b62288590e..1432fd1efd 100644 --- a/indra/llmessage/lltemplatemessagereader.cpp +++ b/indra/llmessage/lltemplatemessagereader.cpp @@ -118,6 +118,9 @@ void LLTemplateMessageReader::getData(const char *blockname, const char *varname { switch( vardata_size ) { + case 0: + // This is here to prevent a memcpy from a null value which is undefined behavior. + break; case 1: *((U8*)datap) = *((U8*)vardata.getData()); break; @@ -286,7 +289,7 @@ void LLTemplateMessageReader::getU8(const char *block, const char *var, void LLTemplateMessageReader::getBOOL(const char *block, const char *var, bool &b, S32 blocknum ) { - U8 value; + U8 value(0); getData(block, var, &value, sizeof(U8), blocknum); b = (bool)value; } @@ -445,7 +448,7 @@ S32 LLTemplateMessageReader::getMessageSize() const // Returns template for the message contained in buffer bool LLTemplateMessageReader::decodeTemplate( const U8* buffer, S32 buffer_size, // inputs - LLMessageTemplate** msg_template ) // outputs + LLMessageTemplate** msg_template, bool custom ) // outputs { const U8* header = buffer + LL_PACKET_ID_SIZE; @@ -487,6 +490,7 @@ bool LLTemplateMessageReader::decodeTemplate( } else // bogus packet received (too short) { + if (!custom) LL_WARNS() << "Packet with unusable length received (too short): " << buffer_size << LL_ENDL; return(false); @@ -499,9 +503,11 @@ bool LLTemplateMessageReader::decodeTemplate( } else { - // MAINT-7482 - make viewer more tolerant of unknown messages. + if (!custom) + { LL_WARNS_ONCE() << "Message #" << std::hex << num << std::dec << " received but not registered!" << LL_ENDL; + } //gMessageSystem->callExceptionFunc(MX_UNREGISTERED_MESSAGE); return(false); } @@ -531,7 +537,7 @@ void LLTemplateMessageReader::logRanOffEndOfPacket( const LLHost& host, const S3 static LLTrace::BlockTimerStatHandle FTM_PROCESS_MESSAGES("Process Messages"); // decode a given message -bool LLTemplateMessageReader::decodeData(const U8* buffer, const LLHost& sender ) +bool LLTemplateMessageReader::decodeData(const U8* buffer, const LLHost& sender, bool custom ) { LL_RECORD_BLOCK_TIME(FTM_PROCESS_MESSAGES); @@ -591,6 +597,7 @@ bool LLTemplateMessageReader::decodeData(const U8* buffer, const LLHost& sender } else { + if (!custom) LL_ERRS() << "Unknown block type" << LL_ENDL; return false; } @@ -637,6 +644,7 @@ bool LLTemplateMessageReader::decodeData(const U8* buffer, const LLHost& sender if ((decode_pos + data_size) > mReceiveSize) { + if (!custom) logRanOffEndOfPacket(sender, decode_pos, data_size); // default to 0 length variable blocks @@ -673,6 +681,7 @@ bool LLTemplateMessageReader::decodeData(const U8* buffer, const LLHost& sender // so, copy data pointer and set data size to fixed size if ((decode_pos + mvci.getSize()) > mReceiveSize) { + if (!custom) logRanOffEndOfPacket(sender, decode_pos, mvci.getSize()); // default to 0s. @@ -697,10 +706,11 @@ bool LLTemplateMessageReader::decodeData(const U8* buffer, const LLHost& sender if (mCurrentRMessageData->mMemberBlocks.empty() && !mCurrentRMessageTemplate->mMemberBlocks.empty()) { - LL_DEBUGS() << "Empty message '" << mCurrentRMessageTemplate->mName << "' (no blocks)" << LL_ENDL; + LL_WARNS() << "Empty message '" << mCurrentRMessageTemplate->mName << "' (no blocks)" << LL_ENDL; return false; } + if (!custom) { static LLTimer decode_timer; @@ -753,11 +763,12 @@ bool LLTemplateMessageReader::decodeData(const U8* buffer, const LLHost& sender bool LLTemplateMessageReader::validateMessage(const U8* buffer, S32 buffer_size, const LLHost& sender, - bool trusted) + bool trusted, + bool custom) { mReceiveSize = buffer_size; - bool valid = decodeTemplate(buffer, buffer_size, &mCurrentRMessageTemplate ); - if(valid) + BOOL valid = decodeTemplate(buffer, buffer_size, &mCurrentRMessageTemplate, custom ); + if(valid && !custom) { mCurrentRMessageTemplate->mReceiveCount++; //LL_DEBUGS() << "MessageRecvd:" @@ -828,3 +839,9 @@ void LLTemplateMessageReader::copyToBuilder(LLMessageBuilder& builder) const } builder.copyFromMessageData(*mCurrentRMessageData); } + +LLMessageTemplate* LLTemplateMessageReader::getTemplate() +{ + return mCurrentRMessageTemplate; +} + diff --git a/indra/llmessage/lltemplatemessagereader.h b/indra/llmessage/lltemplatemessagereader.h index 6f1977cf83..0f7160d328 100644 --- a/indra/llmessage/lltemplatemessagereader.h +++ b/indra/llmessage/lltemplatemessagereader.h @@ -99,25 +99,26 @@ public: virtual void copyToBuilder(LLMessageBuilder&) const; bool validateMessage(const U8* buffer, S32 buffer_size, - const LLHost& sender, bool trusted = false); + const LLHost& sender, bool trusted = false, bool custom = false); bool readMessage(const U8* buffer, const LLHost& sender); bool isTrusted() const; bool isBanned(bool trusted_source) const; bool isUdpBanned() const; + bool decodeData(const U8* buffer, const LLHost& sender, bool custom = false ); + LLMessageTemplate* getTemplate(); + private: void getData(const char *blockname, const char *varname, void *datap, S32 size = 0, S32 blocknum = 0, S32 max_size = S32_MAX); bool decodeTemplate(const U8* buffer, S32 buffer_size, // inputs - LLMessageTemplate** msg_template ); // outputs + LLMessageTemplate** msg_template, bool custom = false ); // outputs void logRanOffEndOfPacket( const LLHost& host, const S32 where, const S32 wanted ); - bool decodeData(const U8* buffer, const LLHost& sender ); - S32 mReceiveSize; LLMessageTemplate* mCurrentRMessageTemplate; LLMsgData* mCurrentRMessageData; diff --git a/indra/llplugin/CMakeLists.txt b/indra/llplugin/CMakeLists.txt index 14a69afe6e..7fa5c957b6 100644 --- a/indra/llplugin/CMakeLists.txt +++ b/indra/llplugin/CMakeLists.txt @@ -31,14 +31,6 @@ set(llplugin_HEADER_FILES llpluginsharedmemory.h ) -if(NOT ADDRESS_SIZE EQUAL 32) - if(WINDOWS) - ##add_definitions(/FIXED:NO) - else(WINDOWS) # not windows therefore gcc LINUX and DARWIN - add_definitions(-fPIC) - endif(WINDOWS) -endif(NOT ADDRESS_SIZE EQUAL 32) - list(APPEND llplugin_SOURCE_FILES ${llplugin_HEADER_FILES}) add_library (llplugin ${llplugin_SOURCE_FILES}) @@ -46,3 +38,4 @@ target_include_directories( llplugin INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) target_link_libraries( llplugin llcommon llmath llrender llmessage ) add_subdirectory(slplugin) +include(LibraryInstall) diff --git a/indra/llplugin/llpluginclassmedia.cpp b/indra/llplugin/llpluginclassmedia.cpp index 8a356da93a..2024579021 100644 --- a/indra/llplugin/llpluginclassmedia.cpp +++ b/indra/llplugin/llpluginclassmedia.cpp @@ -33,7 +33,9 @@ #include "llpluginmessageclasses.h" #include "llcontrol.h" +#if LL_DARWIN || LL_LINUX || __FreeBSD__ extern LLControlGroup gSavedSettings; +#endif #if LL_DARWIN extern bool gHiDPISupport; #endif @@ -934,8 +936,10 @@ void LLPluginClassMedia::setUserDataPath(const std::string &user_data_path_cache message.setValue("username", username); // cef shares cache between users but creates user-based contexts message.setValue("cef_log_file", user_data_path_cef_log); +#if LL_DARWIN || LL_LINUX || __FreeBSD__ bool cef_verbose_log = gSavedSettings.getBOOL("CefVerboseLog"); message.setValueBoolean("cef_verbose_log", cef_verbose_log); +#endif sendMessage(message); } @@ -981,6 +985,15 @@ void LLPluginClassMedia::enableMediaPluginDebugging( bool enable ) sendMessage( message ); } +#if LL_LINUX +void LLPluginClassMedia::enablePipeWireVolumeCatcher( bool enable ) +{ + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "enable_pipewire_volume_catcher"); + message.setValueBoolean( "enable", enable ); + sendMessage( message ); +} +#endif + void LLPluginClassMedia::setTarget(const std::string &target) { mTarget = target; @@ -1198,6 +1211,10 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message) mMediaName = message.getValue("name"); mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_NAME_CHANGED); } + else if(message_name == "nowplaying_text") + { + mMediaNowPlaying = message.getValue("nowplaying"); + } else if(message_name == "pick_file") { mIsMultipleFilePick = message.getValueBoolean("multiple_files"); diff --git a/indra/llplugin/llpluginclassmedia.h b/indra/llplugin/llpluginclassmedia.h index d74b790d8f..109f3880c5 100644 --- a/indra/llplugin/llpluginclassmedia.h +++ b/indra/llplugin/llpluginclassmedia.h @@ -135,6 +135,10 @@ public: // Text may be unicode (utf8 encoded) bool textInput(const std::string &text, MASK modifiers, LLSD native_key_data); +#if LL_LINUX + void enablePipeWireVolumeCatcher( bool enable ); +#endif + static std::string sOIDcookieUrl; static std::string sOIDcookieName; static std::string sOIDcookieValue; @@ -307,6 +311,7 @@ public: const std::string& getMediaName() const { return mMediaName; }; + const std::string& getMediaNowPlaying() const { return mMediaNowPlaying; }; std::string getMediaDescription() const { return mMediaDescription; }; // Crash the plugin. If you use this outside of a testbed, you will be punished. @@ -424,6 +429,7 @@ protected: bool mCanPaste; std::string mMediaName; + std::string mMediaNowPlaying; std::string mMediaDescription; LLColor4 mBackgroundColor; diff --git a/indra/llplugin/llpluginsharedmemory.cpp b/indra/llplugin/llpluginsharedmemory.cpp index 28a0f0bf4e..955c9f90d7 100644 --- a/indra/llplugin/llpluginsharedmemory.cpp +++ b/indra/llplugin/llpluginsharedmemory.cpp @@ -45,8 +45,12 @@ #define USE_WIN32_SHARED_MEMORY 1 #elif LL_DARWIN #define USE_SHM_OPEN_SHARED_MEMORY 1 +#elif _POSIX_SHARED_MEMORY_OBJECTS == -1 + #define USE_APR_SHARED_MEMORY 1 #elif LL_LINUX #define USE_SHM_OPEN_SHARED_MEMORY 1 +#elif __FreeBSD__ + #define USE_SHM_OPEN_SHARED_MEMORY 1 #endif diff --git a/indra/llplugin/slplugin/CMakeLists.txt b/indra/llplugin/slplugin/CMakeLists.txt index 0ea6495eac..3ad6d10336 100644 --- a/indra/llplugin/slplugin/CMakeLists.txt +++ b/indra/llplugin/slplugin/CMakeLists.txt @@ -56,10 +56,23 @@ if (DARWIN) COMMAND mkdir ARGS -p - ${CMAKE_CURRENT_BINARY_DIR}/$<IF:$<BOOL:${LL_GENERATOR_IS_MULTI_CONFIG}>,$<CONFIG>,>/SLPlugin.app/Contents/Resources + ${CMAKE_CURRENT_BINARY_DIR}/$<IF:$<BOOL:${LL_GENERATOR_IS_MULTI_CONFIG}>,$<CONFIG>,>/SLPlugin.app/Contents/Frameworks ) endif (DARWIN) +if (BUILD_SHARED_LIBS) + set_target_properties(SLPlugin PROPERTIES LINK_FLAGS_RELEASE + "${LINK_FLAGS_RELEASE} -Wl,--allow-shlib-undefined") +endif () + +if (INSTALL) + if (DARWIN) + install(TARGETS ${PROJECT_NAME} DESTINATION .) + else (DARWIN) + install(TARGETS ${PROJECT_NAME} DESTINATION libexec/${VIEWER_BINARY_NAME}) + endif (DARWIN) +endif (INSTALL) + if (LL_TESTS) ll_deploy_sharedlibs_command(SLPlugin) endif (LL_TESTS) diff --git a/indra/llplugin/slplugin/slplugin.cpp b/indra/llplugin/slplugin/slplugin.cpp index 81a27cf2e5..ae26b9d452 100644 --- a/indra/llplugin/slplugin/slplugin.cpp +++ b/indra/llplugin/slplugin/slplugin.cpp @@ -46,7 +46,7 @@ using namespace std; #include "slplugin-objc.h" #endif -#if LL_DARWIN || LL_LINUX +#if LL_DARWIN || LL_LINUX || __FreeBSD__ #include <signal.h> #endif @@ -64,7 +64,7 @@ using namespace std; Now that SLPlugin is a bundled app on the Mac, this is no longer necessary (it can just use a regular Info.plist file), but I'm leaving this comment in for posterity. */ -#if LL_DARWIN || LL_LINUX +#if LL_DARWIN || LL_LINUX || __FreeBSD__ // Signal handlers to make crashes not show an OS dialog... static void crash_handler(int sig) { @@ -163,7 +163,7 @@ int main(int argc, char **argv) // display a crash message if something bad happens. The host app will // see the missing heartbeat and log appropriately. initExceptionHandler(); -#elif LL_DARWIN || LL_LINUX +#elif LL_DARWIN || LL_LINUX || __FreeBSD__ if(argc < 2) { LL_ERRS("slplugin") << "usage: " << argv[0] << " launcher_port" << LL_ENDL; diff --git a/indra/llprimitive/CMakeLists.txt b/indra/llprimitive/CMakeLists.txt index 972f502aa9..dea85f8f4f 100644 --- a/indra/llprimitive/CMakeLists.txt +++ b/indra/llprimitive/CMakeLists.txt @@ -74,6 +74,12 @@ target_link_libraries(llprimitive ll::glh_linear ) +if (USESYSTEMLIBS) + add_subdirectory(llphysicsextensions) +endif () + +include(LibraryInstall) + #add unit tests if (LL_TESTS) INCLUDE(LLAddBuildTest) diff --git a/indra/llprimitive/lldaeloader.cpp b/indra/llprimitive/lldaeloader.cpp index 1480322935..a099a07cbd 100644 --- a/indra/llprimitive/lldaeloader.cpp +++ b/indra/llprimitive/lldaeloader.cpp @@ -941,12 +941,20 @@ bool LLDAELoader::OpenFile(const std::string& filename) domCOLLADA* dom; if (mPreprocessDAE) { +#ifdef LL_USESYSTEMLIBS + dom = static_cast<domCOLLADA *>(dae.openFromMemory(uri_filename, preprocessDAE(filename).c_str())); +#else dom = dae.openFromMemory(uri_filename, preprocessDAE(filename).c_str()); +#endif } else { LL_INFOS() << "Skipping dae preprocessing" << LL_ENDL; +#ifdef LL_USESYSTEMLIBS + dom = static_cast<domCOLLADA *>(dae.open(uri_filename)); +#else dom = dae.open(uri_filename); +#endif } if (!dom) @@ -1120,19 +1128,17 @@ bool LLDAELoader::OpenFile(const std::string& filename) if (skin) { - domGeometry* geom = daeSafeCast<domGeometry>(skin->getSource().getElement()); - - if (geom) + if (domGeometry* geom = daeSafeCast<domGeometry>(skin->getSource().getElement())) { - domMesh* mesh = geom->getMesh(); - if (mesh) + if (domMesh* mesh = geom->getMesh()) { - std::vector< LLPointer< LLModel > >::iterator i = mModelsMap[mesh].begin(); - while (i != mModelsMap[mesh].end()) + dae_model_map::const_iterator it = mModelsMap.find(mesh); + if (it != mModelsMap.end()) { - LLPointer<LLModel> mdl = *i; - LLDAELoader::processDomModel(mdl, &dae, root, mesh, skin); - i++; + for (const LLPointer<LLModel>& model : it->second) + { + LLDAELoader::processDomModel(model, &dae, root, mesh, skin); + } } } } @@ -1302,6 +1308,7 @@ void LLDAELoader::processDomModel(LLModel* model, DAE* dae, daeElement* root, do } } else + { //Has one or more skeletons for (std::vector<domInstance_controller::domSkeleton*>::iterator skel_it = skeletons.begin(); skel_it != skeletons.end(); ++skel_it) @@ -1386,6 +1393,7 @@ void LLDAELoader::processDomModel(LLModel* model, DAE* dae, daeElement* root, do } }//got skeleton? } + } domSkin::domJoints* joints = skin->getJoints(); @@ -1686,7 +1694,7 @@ void LLDAELoader::processDomModel(LLModel* model, DAE* dae, daeElement* root, do materials[model->mMaterialList[i]] = LLImportMaterial(); } mScene[transformation].push_back(LLModelInstance(model, model->mLabel, transformation, materials)); - stretch_extents(model, transformation, mExtents[0], mExtents[1], mFirstTransform); + stretch_extents(model, transformation); } } @@ -2079,21 +2087,14 @@ void LLDAELoader::processElement( daeElement* element, bool& badElement, DAE* da mTransform.condition(); } - domInstance_geometry* instance_geo = daeSafeCast<domInstance_geometry>(element); - if (instance_geo) + if (domInstance_geometry* instance_geo = daeSafeCast<domInstance_geometry>(element)) { - domGeometry* geo = daeSafeCast<domGeometry>(instance_geo->getUrl().getElement()); - if (geo) + if (domGeometry* geo = daeSafeCast<domGeometry>(instance_geo->getUrl().getElement())) { - domMesh* mesh = daeSafeCast<domMesh>(geo->getDescendant(daeElement::matchType(domMesh::ID()))); - if (mesh) + if (domMesh* mesh = daeSafeCast<domMesh>(geo->getDescendant(daeElement::matchType(domMesh::ID())))) { - - std::vector< LLPointer< LLModel > >::iterator i = mModelsMap[mesh].begin(); - while (i != mModelsMap[mesh].end()) + for (LLModel* model : mModelsMap.find(mesh)->second) { - LLModel* model = *i; - LLMatrix4 transformation = mTransform; if (mTransform.determinant() < 0) @@ -2164,8 +2165,7 @@ void LLDAELoader::processElement( daeElement* element, bool& badElement, DAE* da } mScene[transformation].push_back(LLModelInstance(model, label, transformation, materials)); - stretch_extents(model, transformation, mExtents[0], mExtents[1], mFirstTransform); - i++; + stretch_extents(model, transformation); } } } diff --git a/indra/llprimitive/lldaeloader.h b/indra/llprimitive/lldaeloader.h index 4531e03474..c6e5ea42fc 100644 --- a/indra/llprimitive/lldaeloader.h +++ b/indra/llprimitive/lldaeloader.h @@ -29,6 +29,7 @@ #include "llmodelloader.h" +#ifndef LL_USESYSTEMLIBS class DAE; class daeElement; class domProfile_COMMON; @@ -38,6 +39,7 @@ class domTranslate; class domController; class domSkin; class domMesh; +#endif class LLDAELoader : public LLModelLoader { diff --git a/indra/llprimitive/llgltfmaterial.h b/indra/llprimitive/llgltfmaterial.h index 10df4c8ee1..b89853c9fd 100644 --- a/indra/llprimitive/llgltfmaterial.h +++ b/indra/llprimitive/llgltfmaterial.h @@ -36,6 +36,7 @@ #include <array> #include <string> +#include <array> #include <map> namespace tinygltf diff --git a/indra/llprimitive/llmodel.cpp b/indra/llprimitive/llmodel.cpp index e7152a2291..4a185f8ba9 100644 --- a/indra/llprimitive/llmodel.cpp +++ b/indra/llprimitive/llmodel.cpp @@ -91,19 +91,15 @@ std::string LLModel::getStatusString(U32 status) } -void LLModel::offsetMesh( const LLVector3& pivotPoint ) +void LLModel::offsetMesh(const LLVector3& pivotPoint) { - LLVector4a pivot( pivotPoint[VX], pivotPoint[VY], pivotPoint[VZ] ); + LLVector4a pivot(pivotPoint[VX], pivotPoint[VY], pivotPoint[VZ]); - for (std::vector<LLVolumeFace>::iterator faceIt = mVolumeFaces.begin(); faceIt != mVolumeFaces.end(); ) + for (LLVolumeFace& face : mVolumeFaces) { - std::vector<LLVolumeFace>:: iterator currentFaceIt = faceIt++; - LLVolumeFace& face = *currentFaceIt; - LLVector4a *pos = (LLVector4a*) face.mPositions; - - for (S32 i=0; i<face.mNumVertices; ++i ) + for (U32 i = 0; i < face.mNumVertices; ++i) { - pos[i].add( pivot ); + face.mPositions[i].add(pivot); } } } @@ -338,7 +334,7 @@ void LLModel::normalizeVolumeFaces() } } -void LLModel::getNormalizedScaleTranslation(LLVector3& scale_out, LLVector3& translation_out) +void LLModel::getNormalizedScaleTranslation(LLVector3& scale_out, LLVector3& translation_out) const { scale_out = mNormalizedScale; translation_out = mNormalizedTranslation; diff --git a/indra/llprimitive/llmodel.h b/indra/llprimitive/llmodel.h index b0cba2d655..b9c6c9aa24 100644 --- a/indra/llprimitive/llmodel.h +++ b/indra/llprimitive/llmodel.h @@ -35,8 +35,10 @@ #include <boost/align/aligned_allocator.hpp> +#ifndef LL_USESYSTEMLIBS class daeElement; class domMesh; +#endif #define MAX_MODEL_FACES 8 @@ -202,8 +204,8 @@ public: void trimVolumeFacesToSize(U32 new_count = LL_SCULPT_MESH_MAX_FACES, LLVolume::face_list_t* remainder = NULL); void remapVolumeFaces(); void optimizeVolumeFaces(); - void offsetMesh( const LLVector3& pivotPoint ); - void getNormalizedScaleTranslation(LLVector3& scale_out, LLVector3& translation_out); + void offsetMesh(const LLVector3& pivotPoint); + void getNormalizedScaleTranslation(LLVector3& scale_out, LLVector3& translation_out) const; LLVector3 getTransformedCenter(const LLMatrix4& mat); //reorder face list based on mMaterialList in this and reference so diff --git a/indra/llprimitive/llmodelloader.cpp b/indra/llprimitive/llmodelloader.cpp index 9a194567d2..1a64e6227f 100644 --- a/indra/llprimitive/llmodelloader.cpp +++ b/indra/llprimitive/llmodelloader.cpp @@ -37,7 +37,7 @@ std::list<LLModelLoader*> LLModelLoader::sActiveLoaderList; -void stretch_extents(LLModel* model, LLMatrix4a& mat, LLVector4a& min, LLVector4a& max, bool& first_transform) +static void stretch_extents(const LLModel* model, const LLMatrix4a& mat, LLVector4a& min, LLVector4a& max, bool& first_transform) { LLVector4a box[] = { @@ -59,7 +59,7 @@ void stretch_extents(LLModel* model, LLMatrix4a& mat, LLVector4a& min, LLVector4 center.setAdd(face.mExtents[0], face.mExtents[1]); center.mul(0.5f); LLVector4a size; - size.setSub(face.mExtents[1],face.mExtents[0]); + size.setSub(face.mExtents[1], face.mExtents[0]); size.mul(0.5f); for (U32 i = 0; i < 8; i++) @@ -85,19 +85,19 @@ void stretch_extents(LLModel* model, LLMatrix4a& mat, LLVector4a& min, LLVector4 } } -void stretch_extents(LLModel* model, LLMatrix4& mat, LLVector3& min, LLVector3& max, bool& first_transform) +void LLModelLoader::stretch_extents(const LLModel* model, const LLMatrix4& mat) { LLVector4a mina, maxa; LLMatrix4a mata; mata.loadu(mat); - mina.load3(min.mV); - maxa.load3(max.mV); + mina.load3(mExtents[0].mV); + maxa.load3(mExtents[1].mV); - stretch_extents(model, mata, mina, maxa, first_transform); + ::stretch_extents(model, mata, mina, maxa, mFirstTransform); - min.set(mina.getF32ptr()); - max.set(maxa.getF32ptr()); + mExtents[0].set(mina.getF32ptr()); + mExtents[1].set(maxa.getF32ptr()); } //----------------------------------------------------------------------------- @@ -292,14 +292,7 @@ bool LLModelLoader::loadFromSLM(const std::string& filename) { if (idx >= model[lod].size()) { - if (model[lod].size()) - { - instance_list[i].mLOD[lod] = model[lod][0]; - } - else - { - instance_list[i].mLOD[lod] = NULL; - } + instance_list[i].mLOD[lod] = model[lod].front(); continue; } @@ -342,7 +335,7 @@ bool LLModelLoader::loadFromSLM(const std::string& filename) { LLModelInstance& cur_instance = instance_list[i]; mScene[cur_instance.mTransform].push_back(cur_instance); - stretch_extents(cur_instance.mModel, cur_instance.mTransform, mExtents[0], mExtents[1], mFirstTransform); + stretch_extents(cur_instance.mModel, cur_instance.mTransform); } setLoadState( DONE ); diff --git a/indra/llprimitive/llmodelloader.h b/indra/llprimitive/llmodelloader.h index 83bd2f5bbd..637dabe08a 100644 --- a/indra/llprimitive/llmodelloader.h +++ b/indra/llprimitive/llmodelloader.h @@ -34,13 +34,13 @@ class LLJoint; -typedef std::map<std::string, LLMatrix4> JointTransformMap; -typedef std::map<std::string, LLMatrix4>::iterator JointTransformMapIt; -typedef std::map<std::string, std::string> JointMap; -typedef std::deque<std::string> JointNameSet; +typedef std::map<std::string, LLMatrix4> JointTransformMap; +typedef std::map<std::string, LLMatrix4>::iterator JointTransformMapIt; +typedef std::map<std::string, std::string> JointMap; +typedef std::deque<std::string> JointNameSet; const S32 SLM_SUPPORTED_VERSION = 3; -const S32 NUM_LOD = 4; +const S32 NUM_LOD = 4; const U32 LEGACY_RIG_OK = 0; const U32 LEGACY_RIG_FLAG_TOO_MANY_JOINTS = 1; @@ -50,32 +50,32 @@ class LLModelLoader : public LLThread { public: - typedef std::map<std::string, LLImportMaterial> material_map; - typedef std::vector<LLPointer<LLModel > > model_list; - typedef std::vector<LLModelInstance> model_instance_list; - typedef std::map<LLMatrix4, model_instance_list > scene; + typedef std::map<std::string, LLImportMaterial> material_map; + typedef std::vector<LLPointer<LLModel>> model_list; + typedef std::vector<LLModelInstance> model_instance_list; + typedef std::map<LLMatrix4, model_instance_list> scene; // Callback with loaded model data and loaded LoD // - typedef boost::function<void (scene&,model_list&,S32,void*) > load_callback_t; + typedef boost::function<void (scene&, model_list&, S32, void*)> load_callback_t; // Function to provide joint lookup by name // (within preview avi skeleton, for example) // - typedef boost::function<LLJoint* (const std::string&,void*) > joint_lookup_func_t; + typedef boost::function<LLJoint* (const std::string&, void*)> joint_lookup_func_t; // Func to load and associate material with all it's textures, // returned value is the number of textures loaded // intentionally non-const so func can modify material to // store platform-specific data // - typedef boost::function<U32 (LLImportMaterial&,void*) > texture_load_func_t; + typedef boost::function<U32 (LLImportMaterial&, void*)> texture_load_func_t; // Callback to inform client of state changes // during loading process (errors will be reported // as state changes here as well) // - typedef boost::function<void (U32,void*) > state_callback_t; + typedef boost::function<void (U32, void*)> state_callback_t; typedef enum { @@ -136,7 +136,7 @@ public: JointNameSet& jointsFromNodes, JointMap& legalJointNamesMap, U32 maxJointsPerMesh); - virtual ~LLModelLoader() ; + virtual ~LLModelLoader(); virtual void setNoNormalize() { mNoNormalize = true; } virtual void setNoOptimize() { mNoOptimize = true; } @@ -156,13 +156,13 @@ public: bool loadFromSLM(const std::string& filename); void loadModelCallback(); - void loadTextures() ; //called in the main thread. + void loadTextures(); // called in the main thread. void setLoadState(U32 state); + void stretch_extents(const LLModel* model, const LLMatrix4& mat); - - S32 mNumOfFetchingTextures ; //updated in the main thread - bool areTexturesReady() { return !mNumOfFetchingTextures; } //called in the main thread. + S32 mNumOfFetchingTextures; // updated in the main thread + bool areTexturesReady() { return !mNumOfFetchingTextures; } // called in the main thread. bool verifyCount( int expected, int result ); @@ -212,10 +212,7 @@ protected: LLSD mWarningsArray; // preview floater will pull logs from here static std::list<LLModelLoader*> sActiveLoaderList; - static bool isAlive(LLModelLoader* loader) ; + static bool isAlive(LLModelLoader* loader); }; -class LLMatrix4a; -void stretch_extents(LLModel* model, LLMatrix4a& mat, LLVector4a& min, LLVector4a& max, bool& first_transform); -void stretch_extents(LLModel* model, LLMatrix4& mat, LLVector3& min, LLVector3& max, bool& first_transform); #endif // LL_LLMODELLOADER_H diff --git a/indra/llprimitive/llphysicsextensions/CMakeLists.txt b/indra/llprimitive/llphysicsextensions/CMakeLists.txt new file mode 100644 index 0000000000..258cea5dd7 --- /dev/null +++ b/indra/llprimitive/llphysicsextensions/CMakeLists.txt @@ -0,0 +1,101 @@ +# -*- cmake -*- + +project(llphysicsextensions) + +include(00-Common) +include(Variables) +include(LLCommon) +include(LLMath) + +set(LLPHYSICSEXTENSIONS_LIB_NAME llphysicsextensions) + +if (WINDOWS) + set(LLPHYSICSEXTENSIONS_LIBRARIES ${LLPHYSICSEXTENSIONS_LIB_NAME}.lib) +else (WINDOWS) + set(LLPHYSICSEXTENSIONS_LIBRARIES ${LLPHYSICSEXTENSIONS_LIB_NAME}.a) +endif (WINDOWS) + +set(LLPHYSICSEXTENSIONS_INCLUDE_DIR + ${CMAKE_CURRENT_SOURCE_DIR}) + +set(LLPHYSICSEXTENSIONS_DEBUG_LIBRARY_PATH ${LIBS_PREBUILT_DIR}/lib/debug) +set(LLPHYSICSEXTENSIONS_RELEASE_LIBRARY_PATH ${LIBS_PREBUILT_DIR}/lib/release) + +#set(LLPHYSICSEXTENSIONS_LIBRARIES_LIBRARIES +# debug ${LLPHYSICSEXTENSIONS_DEBUG_LIB} +# optimized ${LLPHYSICSEXTENTIONS_RELEASE_LIB} +#) + +if (LINUX) + list(INSERT LLPHYSICSEXTENSIONS_LIBRARIES 0 -Wl,--start-group) + list(APPEND LLPHYSICSEXTENSIONS_LIBRARIES -Wl,--end-group) +endif (LINUX) + +#include_directories( +# ${CMAKE_SOURCE_DIR}/llphysicsextensions +# ${LLPHYSICSEXTENSIONS_INCLUDE_DIR} +# ${LLCOMMON_INCLUDE_DIRS} +# ${LLMATH_INCLUDE_DIRS} +# ) + +set(llphysicsextensions_SOURCE_FILES + llpathinglib.cpp + LLPathingLibStubImpl.cpp + llconvexdecomposition.cpp + LLConvexDecompositionStubImpl.cpp + llphysicsextensions.cpp + LLPhysicsExtensionsStubImpl.cpp + ) + +set(llphysicsextensions_HEADER_FILES + + ${LLPHYSICSEXTENSIONS_INCLUDE_DIR}/llpathinglib.h + ${LLPHYSICSEXTENSIONS_INCLUDE_DIR}/llconvexdecomposition.h + ${LLPHYSICSEXTENSIONS_INCLUDE_DIR}/llphysicsextensions.h + LLPathingLibStubImpl.h + LLConvexDecompositionStubImpl.h + LLPhysicsExtensionsStubImpl.h + ) + +if (WINDOWS) + list(APPEND llphysicsextensions_HEADER_FILES + ${LLPHYSICSEXTENSIONS_INCLUDE_DIR}/windowsincludes.h) +endif (WINDOWS) + +set_source_files_properties(${llphysicsextensions_HEADER_FILES} + PROPERTIES HEADER_FILE_ONLY TRUE) + +# some of the include files contain compile-time switches based on these +set_source_files_properties(${llphysicsextensions_SOURCE_FILES} + PROPERTIES COMPILE_DEFINITIONS "LL_PATHING_LIB_STUB;LL_CONVEX_DECOMP_STUB;LL_PHYSICS_EXTENSIONS_STUB") + +list(APPEND llphysicsextensionsstub_SOURCE_FILES ${llphysicsextensions_HEADER_FILES}) + +add_library(${PROJECT_NAME}stub ${${PROJECT_NAME}_SOURCE_FILES}) +target_include_directories(${PROJECT_NAME}stub INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) +target_link_libraries(${PROJECT_NAME}stub llmath llcommon) +list(REMOVE_ITEM ${PROJECT_NAME}_HEADER_FILES + LLPathingLibStubImpl.h + LLConvexDecompositionStubImpl.h + LLPhysicsExtensionsStubImpl.h) +#install(FILES ${${PROJECT_NAME}_HEADER_FILES} DESTINATION include/${PROJECT_NAME}) +if (BUILD_SHARED_LIBS) + if (EXISTS ${CMAKE_SYSROOT}/usr/lib/${ARCH}-linux-gnu) + set(_LIB lib/${ARCH}-linux-gnu) + elseif (EXISTS /lib64) + set(_LIB lib64) + else () + set(_LIB lib) + endif () + install(TARGETS ${PROJECT_NAME}stub DESTINATION ${_LIB}) +endif () + +if (LINUX) + IF(CMAKE_BUILD_TYPE MATCHES Release) + SET(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/release) + ENDIF(CMAKE_BUILD_TYPE MATCHES Release) + IF(CMAKE_BUILD_TYPE MATCHES Debug) + SET(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/debug) + ENDIF(CMAKE_BUILD_TYPE MATCHES Debug) + +endif (LINUX) diff --git a/indra/llprimitive/llphysicsextensions/LLConvexDecompositionStubImpl.cpp b/indra/llprimitive/llphysicsextensions/LLConvexDecompositionStubImpl.cpp new file mode 100644 index 0000000000..b1214a7f31 --- /dev/null +++ b/indra/llprimitive/llphysicsextensions/LLConvexDecompositionStubImpl.cpp @@ -0,0 +1,143 @@ +/** +* @file LLConvexDecompositionStubImpl.cpp +* @author falcon@lindenlab.com +* @brief A stub implementation of LLConvexDecomposition +* +* $LicenseInfo:firstyear=2011&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 20112010, 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 <string.h> +#include <memory> +#include "LLConvexDecompositionStubImpl.h" + +LLConvexDecomposition* LLConvexDecompositionImpl::getInstance() +{ + return NULL; +} + +LLCDResult LLConvexDecompositionImpl::initSystem() +{ + return LLCD_NOT_IMPLEMENTED; +} + +LLCDResult LLConvexDecompositionImpl::initThread() +{ + return LLCD_NOT_IMPLEMENTED; +} + +LLCDResult LLConvexDecompositionImpl::quitThread() +{ + return LLCD_NOT_IMPLEMENTED; +} + +LLCDResult LLConvexDecompositionImpl::quitSystem() +{ + return LLCD_NOT_IMPLEMENTED; +} + +void LLConvexDecompositionImpl::genDecomposition(int& decomp) +{ + decomp = -1; +} + +void LLConvexDecompositionImpl::deleteDecomposition(int decomp) +{ + +} + +void LLConvexDecompositionImpl::bindDecomposition(int decomp) +{ + +} + +LLCDResult LLConvexDecompositionImpl::setParam(const char* name, float val) +{ + return LLCD_NOT_IMPLEMENTED; +} + +LLCDResult LLConvexDecompositionImpl::setParam(const char* name, bool val) +{ + return LLCD_NOT_IMPLEMENTED; +} + +LLCDResult LLConvexDecompositionImpl::setParam(const char* name, int val) +{ + return LLCD_NOT_IMPLEMENTED; +} + +LLCDResult LLConvexDecompositionImpl::setMeshData( const LLCDMeshData* data, bool vertex_based ) +{ + return LLCD_NOT_IMPLEMENTED; +} + +LLCDResult LLConvexDecompositionImpl::registerCallback(int stage, llcdCallbackFunc callback ) +{ + return LLCD_NOT_IMPLEMENTED; +} + +LLCDResult LLConvexDecompositionImpl::executeStage(int stage) +{ + return LLCD_NOT_IMPLEMENTED; +} + +int LLConvexDecompositionImpl::getNumHullsFromStage(int stage) +{ + return 0; +} + +LLCDResult LLConvexDecompositionImpl::getSingleHull( LLCDHull* hullOut ) +{ + memset( hullOut, 0, sizeof(LLCDHull) ); + return LLCD_NOT_IMPLEMENTED; +} + +LLCDResult LLConvexDecompositionImpl::getHullFromStage( int stage, int hull, LLCDHull* hullOut ) +{ + memset( hullOut, 0, sizeof(LLCDHull) ); + return LLCD_NOT_IMPLEMENTED; +} + +LLCDResult LLConvexDecompositionImpl::getMeshFromStage( int stage, int hull, LLCDMeshData* meshDataOut ) +{ + memset( meshDataOut, 0, sizeof(LLCDMeshData) ); + return LLCD_NOT_IMPLEMENTED; +} + +LLCDResult LLConvexDecompositionImpl::getMeshFromHull( LLCDHull* hullIn, LLCDMeshData* meshOut ) +{ + memset( meshOut, 0, sizeof(LLCDMeshData) ); + return LLCD_NOT_IMPLEMENTED; +} + +LLCDResult LLConvexDecompositionImpl::generateSingleHullMeshFromMesh(LLCDMeshData* meshIn, LLCDMeshData* meshOut) +{ + memset( meshOut, 0, sizeof(LLCDMeshData) ); + return LLCD_NOT_IMPLEMENTED; +} + +void LLConvexDecompositionImpl::loadMeshData(const char* fileIn, LLCDMeshData** meshDataOut) +{ + static LLCDMeshData meshData; + memset( &meshData, 0, sizeof(LLCDMeshData) ); + *meshDataOut = &meshData; +} + diff --git a/indra/llprimitive/llphysicsextensions/LLConvexDecompositionStubImpl.h b/indra/llprimitive/llphysicsextensions/LLConvexDecompositionStubImpl.h new file mode 100644 index 0000000000..9ae879efb4 --- /dev/null +++ b/indra/llprimitive/llphysicsextensions/LLConvexDecompositionStubImpl.h @@ -0,0 +1,92 @@ +/** +* @file LLConvexDecompositionStubImpl.h +* @author falcon@lindenlab.com +* @brief A stub implementation of LLConvexDecomposition +* +* $LicenseInfo:firstyear=2011&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 20112010, 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_CONVEX_DECOMP_UTIL_H +#define LL_CONVEX_DECOMP_UTIL_H + +#include "llconvexdecomposition.h" + +class LLConvexDecompositionImpl : public LLConvexDecomposition +{ + public: + + virtual ~LLConvexDecompositionImpl() {} + + static LLConvexDecomposition* getInstance(); + static LLCDResult initSystem(); + static LLCDResult initThread(); + static LLCDResult quitThread(); + static LLCDResult quitSystem(); + + void genDecomposition(int& decomp); + void deleteDecomposition(int decomp); + void bindDecomposition(int decomp); + + // Sets *paramsOut to the address of the LLCDParam array and returns + // the length of the array + int getParameters(const LLCDParam** paramsOut) + { + *paramsOut = NULL; + return 0; + } + + int getStages(const LLCDStageData** stagesOut) + { + *stagesOut = NULL; + return 0; + } + + // Set a parameter by name. Returns false if out of bounds or unsupported parameter + LLCDResult setParam(const char* name, float val); + LLCDResult setParam(const char* name, int val); + LLCDResult setParam(const char* name, bool val); + LLCDResult setMeshData( const LLCDMeshData* data, bool vertex_based ); + LLCDResult registerCallback(int stage, llcdCallbackFunc callback ); + + LLCDResult executeStage(int stage); + + int getNumHullsFromStage(int stage); + + LLCDResult getHullFromStage( int stage, int hull, LLCDHull* hullOut ); + LLCDResult getSingleHull( LLCDHull* hullOut ) ; + + // TODO: Implement lock of some kind to disallow this call if data not yet ready + LLCDResult getMeshFromStage( int stage, int hull, LLCDMeshData* meshDataOut); + LLCDResult getMeshFromHull( LLCDHull* hullIn, LLCDMeshData* meshOut ); + + // For visualizing convex hull shapes in the viewer physics shape display + LLCDResult generateSingleHullMeshFromMesh( LLCDMeshData* meshIn, LLCDMeshData* meshOut); + + /// Debug + void loadMeshData(const char* fileIn, LLCDMeshData** meshDataOut); + + private: + LLConvexDecompositionImpl() {} +}; + +#endif //LL_CONVEX_DECOMP_UTIL_H + diff --git a/indra/llprimitive/llphysicsextensions/LLPathingLibStubImpl.cpp b/indra/llprimitive/llphysicsextensions/LLPathingLibStubImpl.cpp new file mode 100644 index 0000000000..8ad13532f2 --- /dev/null +++ b/indra/llprimitive/llphysicsextensions/LLPathingLibStubImpl.cpp @@ -0,0 +1,107 @@ +/** +* @file LLPathingLibStubImpl.cpp +* @author prep@lindenlab.com +* @brief A stubbed implementation of LLPathingLib +* +* $LicenseInfo:firstyear=2012&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 20112010, 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 "llpathinglib.h" +#include "LLPathingLibStubImpl.h" + +#include "llsd.h" + +//============================================================================= +LLPathingLibImpl::LLPathingLibImpl() +{ +} + +LLPathingLibImpl::~LLPathingLibImpl() +{ + +} + +LLPathingLib* LLPathingLibImpl::getInstance() +{ + return NULL; +} + + +LLPathingLib::LLPLResult LLPathingLibImpl::initSystem() +{ + return LLPL_NOT_IMPLEMENTED; +} + +LLPathingLib::LLPLResult LLPathingLibImpl::quitSystem() +{ + return LLPL_NOT_IMPLEMENTED; +} + +LLPathingLib::LLPLResult LLPathingLibImpl::extractNavMeshSrcFromLLSD( const LLSD::Binary& dataBlock, int dir ) +{ + return LLPL_NOT_IMPLEMENTED; +} + +void LLPathingLibImpl::processNavMeshData() +{ +} + +LLPathingLibImpl::LLPLResult LLPathingLibImpl::generatePath( const PathingPacket& pathingPacket ) +{ + return LLPL_NOT_IMPLEMENTED; +} + +void LLPathingLibImpl::setNavMeshMaterialType( LLPLCharacterType materialType ) +{ +} + +void LLPathingLibImpl::setNavMeshColors( const NavMeshColors& color ) +{ +} + +void LLPathingLibImpl::renderNavMesh() +{ +} + +void LLPathingLibImpl::renderNavMeshEdges() +{ +} + +void LLPathingLibImpl::renderNavMeshShapesVBO( U32 shapeRenderFlags ) +{ +} + +void LLPathingLibImpl::renderPath() +{ +} + +void LLPathingLibImpl::renderPathBookend( LLRender& gl, LLPathingLib::LLPLPathBookEnd type ) +{ +} + +void LLPathingLibImpl::cleanupVBOManager() +{ +} + +void LLPathingLibImpl::cleanupResidual() +{ +} diff --git a/indra/llprimitive/llphysicsextensions/LLPathingLibStubImpl.h b/indra/llprimitive/llphysicsextensions/LLPathingLibStubImpl.h new file mode 100644 index 0000000000..75fdb3fa0f --- /dev/null +++ b/indra/llprimitive/llphysicsextensions/LLPathingLibStubImpl.h @@ -0,0 +1,78 @@ +/** +* @file LLPathingLibSubImpl.h +* @author prep@lindenlab.com +* @brief A stubbed implementation of LLPathingLib +* +* $LicenseInfo:firstyear=2012&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2012, 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_PATHING_LIB_H +#define LL_PATHING_LIB_H + +#include "llpathinglib.h" + +class LLSD; + +//============================================================================= +class LLPathingLibImpl : public LLPathingLib +{ +public: + LLPathingLibImpl(); + virtual ~LLPathingLibImpl(); + + // Obtain a pointer to the actual implementation + static LLPathingLib* getInstance(); + static LLPathingLib::LLPLResult initSystem(); + static LLPathingLib::LLPLResult quitSystem(); + + //Extract and store navmesh data from the llsd datablock sent down by the server + virtual LLPLResult extractNavMeshSrcFromLLSD( const LLSD::Binary& dataBlock, int dir ); + //Stitch any stored navmeshes together + virtual void processNavMeshData(); + + //Method used to generate and visualize a path on the viewers navmesh + virtual LLPLResult generatePath( const PathingPacket& pathingPacket ); + + //Set the material type for the heatmap type + virtual void setNavMeshMaterialType( LLPLCharacterType materialType ); + //Set the various navmesh colors + virtual void setNavMeshColors( const NavMeshColors& color ); + + //The entry method to rendering the client side navmesh + virtual void renderNavMesh(); + //The entry method to rendering the client side navmesh edges + virtual void renderNavMeshEdges(); + //The entry method to render the client navmesh shapes VBO + virtual void renderNavMeshShapesVBO( U32 shapeRenderFlags ); + //The entry method to render the clients designated path + virtual void renderPath(); + //The entry method to render the capsule bookends for the clients designated path + virtual void renderPathBookend( LLRender& gl, LLPathingLib::LLPLPathBookEnd type ); + + //Method to delete any vbo's that are currently being managed by the pathing library + virtual void cleanupVBOManager(); + //Method to cleanup any allocations within the implementation + virtual void cleanupResidual(); +}; + +#endif //LL_PATHING_LIB_H + diff --git a/indra/llprimitive/llphysicsextensions/LLPhysicsExtensionsStubImpl.cpp b/indra/llprimitive/llphysicsextensions/LLPhysicsExtensionsStubImpl.cpp new file mode 100644 index 0000000000..2c432f94e3 --- /dev/null +++ b/indra/llprimitive/llphysicsextensions/LLPhysicsExtensionsStubImpl.cpp @@ -0,0 +1,49 @@ +/** +* @file LLPhysicsExtensionsStubImpl.cpp +* @author prep@lindenlab.com +* @brief A stubbed implementation of LLPhysicsExtensions +* +* $LicenseInfo:firstyear=2012&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2012, 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 "llphysicsextensions.h" +#include "LLPhysicsExtensionsStubImpl.h" + +//============================================================================= +LLPhysicsExtensionsImpl::LLPhysicsExtensionsImpl() +{ +} + +LLPhysicsExtensionsImpl::~LLPhysicsExtensionsImpl() +{ +} + +bool LLPhysicsExtensionsImpl::initSystem() +{ + return false; +} + +bool LLPhysicsExtensionsImpl::quitSystem() +{ + return false; +} + diff --git a/indra/llprimitive/llphysicsextensions/LLPhysicsExtensionsStubImpl.h b/indra/llprimitive/llphysicsextensions/LLPhysicsExtensionsStubImpl.h new file mode 100644 index 0000000000..ac14da1ac3 --- /dev/null +++ b/indra/llprimitive/llphysicsextensions/LLPhysicsExtensionsStubImpl.h @@ -0,0 +1,46 @@ +/** +* @file LLPhysicsExtensionsSubImpl.h +* @author prep@lindenlab.com +* @brief A stubbed implementation of LLPhysicsExtensions +* +* $LicenseInfo:firstyear=2012&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2012, 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_PHYSICS_EXTENSIONS_STUB_IMPL_H +#define LL_PHYSICS_EXTENSIONS_STUB_IMPL_H + +#include "llphysicsextensions.h" + +//============================================================================= +class LLPhysicsExtensionsImpl : public LLPhysicsExtensions +{ + public: + + LLPhysicsExtensionsImpl(); + virtual ~LLPhysicsExtensionsImpl(); + + static bool initSystem(); + static bool quitSystem(); +}; + +#endif //LL_PHYSICS_EXTENSIONS_STUB_IMPL_H + diff --git a/indra/llprimitive/llphysicsextensions/llconvexdecomposition.cpp b/indra/llprimitive/llphysicsextensions/llconvexdecomposition.cpp new file mode 100644 index 0000000000..f7caf7f676 --- /dev/null +++ b/indra/llprimitive/llphysicsextensions/llconvexdecomposition.cpp @@ -0,0 +1,102 @@ +/** +* @file llconvexdecomposition.cpp +* @author falcon@lindenlab.com +* @brief A Havok implementation of LLConvexDecomposition interface +* +* $LicenseInfo:firstyear=2011&license=lgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2011, 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$ +*/ + +#if defined(_WINDOWS) +# include "windowsincludes.h" +#endif + +#ifndef NULL +#define NULL 0 +#endif + +#if !defined(LL_CONVEX_DECOMP_STUB) +# include "LLConvexDecompositionImpl.h" +#else +# include "LLConvexDecompositionStubImpl.h" +#endif + +#include "llconvexdecomposition.h" + + +/*static */bool LLConvexDecomposition::s_isInitialized = false; + +/*static*/bool LLConvexDecomposition::isFunctional() +{ +#if !defined(LL_CONVEX_DECOMP_STUB) + return true; +#else + return false; +#endif +} + +#if !defined(LL_CONVEX_DECOMP_STUB) && defined(HK_COMPILER_CLANG) + //have to specialize before use so that generalized one not auto gen-d +HK_SINGLETON_SPECIALIZATION_DECL(LLConvexDecompositionImpl); +#endif + +/*static*/LLConvexDecomposition* LLConvexDecomposition::getInstance() +{ + if ( !s_isInitialized ) + { + return NULL; + } + else + { +#if !defined(LL_CONVEX_DECOMP_STUB) + return &hkSingleton<LLConvexDecompositionImpl>::getInstance(); +#else + return LLConvexDecompositionImpl::getInstance(); +#endif + } +} + +/*static */LLCDResult LLConvexDecomposition::initSystem() +{ + LLCDResult result = LLConvexDecompositionImpl::initSystem(); + if ( result == LLCD_OK ) + { + s_isInitialized = true; + } + return result; +} + +/*static */LLCDResult LLConvexDecomposition::initThread() +{ + return LLConvexDecompositionImpl::initThread(); +} + +/*static */LLCDResult LLConvexDecomposition::quitThread() +{ + return LLConvexDecompositionImpl::quitThread(); +} + +/*static */LLCDResult LLConvexDecomposition::quitSystem() +{ + return LLConvexDecompositionImpl::quitSystem(); +} + + diff --git a/indra/llprimitive/llphysicsextensions/llconvexdecomposition.h b/indra/llprimitive/llphysicsextensions/llconvexdecomposition.h new file mode 100644 index 0000000000..10c6d55315 --- /dev/null +++ b/indra/llprimitive/llphysicsextensions/llconvexdecomposition.h @@ -0,0 +1,231 @@ +/** + * @file llconvexdecomposition.cpp + * @brief LLConvexDecomposition interface definition + * + * $LicenseInfo:firstyear=2011&license=lgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2011, 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_CONVEX_DECOMPOSITION +#define LL_CONVEX_DECOMPOSITION + +typedef int bool32; + +#if defined(_WIN32) || defined(_WIN64) +#define LLCD_CALL __cdecl +#else +#define LLCD_CALL +#endif + +struct LLCDParam +{ + enum LLCDParamType + { + LLCD_INVALID = 0, + LLCD_INTEGER, + LLCD_FLOAT, + LLCD_BOOLEAN, + LLCD_ENUM + }; + + struct LLCDEnumItem + { + const char* mName; + int mValue; + }; + + union LLCDValue + { + float mFloat; + int mIntOrEnumValue; + bool32 mBool; + }; + + union LLCDParamDetails + { + struct { + LLCDValue mLow; + LLCDValue mHigh; + LLCDValue mDelta; + } mRange; + + struct { + int mNumEnums; + LLCDEnumItem* mEnumsArray; + } mEnumValues; + }; + + const char* mName; + const char* mDescription; + LLCDParamType mType; + LLCDParamDetails mDetails; + LLCDValue mDefault; + int mStage; + + // WARNING: Only the LLConvexDecomposition implementation + // should change this value + int mReserved; +}; + +struct LLCDStageData +{ + const char* mName; + const char* mDescription; + bool32 mSupportsCallback; +}; + +struct LLCDMeshData +{ + enum IndexType + { + INT_16, + INT_32 + }; + + const float* mVertexBase; + int mVertexStrideBytes; + int mNumVertices; + const void* mIndexBase; + IndexType mIndexType; + int mIndexStrideBytes; + int mNumTriangles; +}; + +struct LLCDHull +{ + const float* mVertexBase; + int mVertexStrideBytes; + int mNumVertices; +}; + +enum LLCDResult +{ + LLCD_OK = 0, + LLCD_UNKOWN_ERROR, + LLCD_NULL_PTR, + LLCD_INVALID_STAGE, + LLCD_UNKNOWN_PARAM, + LLCD_BAD_VALUE, + LLCD_REQUEST_OUT_OF_RANGE, + LLCD_INVALID_MESH_DATA, + LLCD_INVALID_HULL_DATA, + LLCD_STAGE_NOT_READY, + LLCD_INVALID_THREAD, + LLCD_NOT_IMPLEMENTED +}; + +// This callback will receive a string describing the current subtask being performed +// as well as a pair of numbers indicating progress. (The values should not be interpreted +// as a completion percentage as 'current' may be greater than 'final'.) +// If the callback returns zero, the decomposition will be terminated +typedef int (LLCD_CALL *llcdCallbackFunc)(const char* description, int current, int final); + +class LLConvexDecomposition +{ +public: + // Obtain a pointer to the actual implementation + static LLConvexDecomposition* getInstance(); + + /// @returns false if this is the stub + static bool isFunctional(); + + static LLCDResult initSystem(); + static LLCDResult initThread(); + static LLCDResult quitThread(); + static LLCDResult quitSystem(); + + // Generate a decomposition object handle + virtual void genDecomposition(int& decomp) = 0; + // Delete decomposition object handle + virtual void deleteDecomposition(int decomp) = 0; + // Bind given decomposition handle + // Commands operate on currently bound decomposition + virtual void bindDecomposition(int decomp) = 0; + + // Sets *paramsOut to the address of the LLCDParam array and returns + // the number of parameters + virtual int getParameters(const LLCDParam** paramsOut) = 0; + + + // Sets *stagesOut to the address of the LLCDStageData array and returns + // the number of stages + virtual int getStages(const LLCDStageData** stagesOut) = 0; + + + // Set a parameter by name. Pass enum values as integers. + virtual LLCDResult setParam(const char* name, float val) = 0; + virtual LLCDResult setParam(const char* name, int val) = 0; + virtual LLCDResult setParam(const char* name, bool val) = 0; + + + // Set incoming mesh data. Data is copied to local buffers and will + // persist until the next setMeshData call + virtual LLCDResult setMeshData( const LLCDMeshData* data, bool vertex_based ) = 0; + + + // Register a callback to be called periodically during the specified stage + // See the typedef above for more information + virtual LLCDResult registerCallback( int stage, llcdCallbackFunc callback ) = 0; + + + // Execute the specified decomposition stage + virtual LLCDResult executeStage(int stage) = 0; + virtual LLCDResult buildSingleHull() = 0 ; + + + // Gets the number of hulls generated by the specified decompositions stage + virtual int getNumHullsFromStage(int stage) = 0; + + + // Populates hullOut to reference the internal copy of the requested hull + // The data will persist only until the next executeStage call for that stage. + virtual LLCDResult getHullFromStage( int stage, int hull, LLCDHull* hullOut ) = 0; + + virtual LLCDResult getSingleHull( LLCDHull* hullOut ) = 0 ; + + + // TODO: Implement lock of some kind to disallow this call if data not yet ready + // Populates the meshDataOut to reference the utility's copy of the mesh geometry + // for the hull and stage specified. + // You must copy this data if you want to continue using it after the next executeStage + // call + virtual LLCDResult getMeshFromStage( int stage, int hull, LLCDMeshData* meshDataOut) = 0; + + + // Creates a mesh from hullIn and temporarily stores it internally in the utility. + // The mesh data persists only until the next call to getMeshFromHull + virtual LLCDResult getMeshFromHull( LLCDHull* hullIn, LLCDMeshData* meshOut ) = 0; + + // Takes meshIn, generates a single convex hull from it, converts that to a mesh + // stored internally, and populates meshOut to reference the internally stored data. + // The data is persistent only until the next call to generateSingleHullMeshFromMesh + virtual LLCDResult generateSingleHullMeshFromMesh( LLCDMeshData* meshIn, LLCDMeshData* meshOut) = 0; + + // + /// Debug + virtual void loadMeshData(const char* fileIn, LLCDMeshData** meshDataOut) = 0; + +private: + static bool s_isInitialized; +}; + +#endif //LL_CONVEX_DECOMPOSITION + diff --git a/indra/llprimitive/llphysicsextensions/llpathinglib.cpp b/indra/llprimitive/llphysicsextensions/llpathinglib.cpp new file mode 100644 index 0000000000..1a6017c4b8 --- /dev/null +++ b/indra/llprimitive/llphysicsextensions/llpathinglib.cpp @@ -0,0 +1,110 @@ +/** +* @file llpathinglib.cpp +* @author prep@lindenlab.com +* @brief LLPathingLib core creation methods +* +* $LicenseInfo:firstyear=2012&license=lgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2011, 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$ +*/ + +#if defined(_WINDOWS) +# include "windowsincludes.h" +#endif + +#ifndef NULL +#define NULL 0 +#endif + + +#if !defined(LL_PATHING_LIB_STUB) +# include "LLPathingLibImpl.h" +#else +# include "LLPathingLibStubImpl.h" +#endif + +#include "llpathinglib.h" + +//disable the undefined symbol optimization +//#pragma warning (disable : 4221) + +//============================================================================= + +/*static */bool LLPathingLib::s_isInitialized = false; + +//============================================================================= + + +/*static*/bool LLPathingLib::isFunctional() +{ +#if !defined(LL_PATHING_LIB_STUB) + return true; +#else + return false; +#endif +} + +#if !defined(LL_PATHING_LIB_STUB) && defined(HK_COMPILER_CLANG) + //have to specialize before use so that generalized one not auto gen-d +HK_SINGLETON_SPECIALIZATION_DECL(LLPathingLibImpl); +#endif + +/*static*/LLPathingLib* LLPathingLib::getInstance() +{ + if ( !s_isInitialized ) + { + return NULL; + } + else + { +#if !defined(LL_PATHING_LIB_STUB) + return &hkSingleton<LLPathingLibImpl>::getInstance(); +#else + return LLPathingLibImpl::getInstance(); +#endif + } +} + +//============================================================================= + +/*static */LLPathingLib::LLPLResult LLPathingLib::initSystem() +{ + if ( LLPathingLibImpl::initSystem() == LLPL_OK ) + { + s_isInitialized = true; + return LLPL_OK; + } + return LLPL_UNKOWN_ERROR; +} +//============================================================================= +/*static */LLPathingLib::LLPLResult LLPathingLib::quitSystem() +{ + LLPLResult quitResult = LLPL_UNKOWN_ERROR; + + if (s_isInitialized) + { + quitResult = LLPathingLibImpl::quitSystem(); + s_isInitialized = false; + } + + return quitResult; +} +//============================================================================= + diff --git a/indra/llprimitive/llphysicsextensions/llpathinglib.h b/indra/llprimitive/llphysicsextensions/llpathinglib.h new file mode 100644 index 0000000000..c8c7410797 --- /dev/null +++ b/indra/llprimitive/llphysicsextensions/llpathinglib.h @@ -0,0 +1,187 @@ +/** + * @file llpathinglib.cpp + * @author prep@lindenlab.com + * @brief LLPathingLib interface definition + * + * $LicenseInfo:firstyear=2012&license=lgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2011, 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_PATHING_LIBRARY +#define LL_PATHING_LIBRARY + +#include "llpreprocessor.h" +#include "llsd.h" +#include "v3dmath.h" +#include "v4math.h" + +#include "v4color.h" +#include "v4coloru.h" +#include "llphysicsextensions.h" + +typedef int bool32; + +#if defined(_WIN32) || defined(_WIN64) +#define LLCD_CALL __cdecl +#else +#define LLCD_CALL +#endif + +class LLRender; + +//============================================================================= +class LLPathingLib +{ + +public: + enum LLShapeType + { + LLST_WalkableObjects = 0, + LLST_ObstacleObjects, + LLST_MaterialPhantoms, + LLST_ExclusionPhantoms, + LLST_MaxShapeTypes = LLST_ExclusionPhantoms+1, + LLST_None = LLST_MaxShapeTypes+2, + LLST_SimpleBox = LLST_None+1, + LLST_SimpleCapsule = LLST_SimpleBox+1, + }; + + enum LLShapeTypeFlag + { + LLSTB_WalkableObjects = 0x1 << 1, + LLSTB_ObstacleObjects = 0x1 << 2, + LLSTB_MaterialPhantoms = 0x1 << 3, + LLSTB_ExclusionPhantoms = 0x1 << 4, + LLSTB_None = 0x1 << 5 + }; + + enum LLPLPathBookEnd + { + LLPL_START = 0, + LLPL_END, + }; + + enum LLPLResult + { + LLPL_OK = 0, + LLPL_NOTSET, + LLPL_ERROR, + LLPL_NO_NAVMESH, + LLPL_UNKOWN_ERROR, + LLPL_NO_PATH, + LLPL_PATH_GENERATED_OK, + LLPL_NOT_IMPLEMENTED, + }; + + enum LLPLCharacterType + { + LLPL_CHARACTER_TYPE_A = 4, + LLPL_CHARACTER_TYPE_B = 3, + LLPL_CHARACTER_TYPE_C = 2, + LLPL_CHARACTER_TYPE_D = 1, + LLPL_CHARACTER_TYPE_NONE = 0 + }; + + struct PathingPacket + { + PathingPacket() : mHasPointA(false), mHasPointB(false), mCharacterWidth(0.0f), mCharacterType(LLPL_CHARACTER_TYPE_NONE) {} + bool mHasPointA; + LLVector3 mStartPointA; + LLVector3 mEndPointA; + bool mHasPointB; + LLVector3 mStartPointB; + LLVector3 mEndPointB; + F32 mCharacterWidth; + LLPLCharacterType mCharacterType; + }; + + struct NavMeshColors + { + LLColor4U mWalkable; + LLColor4U mObstacle; + LLColor4U mMaterial; + LLColor4U mExclusion; + LLColor4U mConnectedEdge; + LLColor4U mBoundaryEdge; + LLColor4 mHeatColorBase; + LLColor4 mHeatColorMax; + LLColor4U mFaceColor; + LLColor4U mStarValid; + LLColor4U mStarInvalid; + LLColor4U mTestPath; + LLColor4U mWaterColor; + }; + +public: + //Ctor + LLPathingLib() {} + virtual ~LLPathingLib() {} + + /// @returns false if this is the stub + static bool isFunctional(); + + // Obtain a pointer to the actual implementation + static LLPathingLib* getInstance(); + static LLPathingLib::LLPLResult initSystem(); + static LLPathingLib::LLPLResult quitSystem(); + + //Extract and store navmesh data from the llsd datablock sent down by the server + virtual LLPLResult extractNavMeshSrcFromLLSD( const LLSD::Binary& dataBlock, int dir ) = 0; + //Stitch any stored navmeshes together + virtual void processNavMeshData( ) = 0; + + //Method used to generate and visualize a path on the viewers navmesh + virtual LLPLResult generatePath( const PathingPacket& pathingPacket ) = 0; + + //Set the material type for the heatmap type + virtual void setNavMeshMaterialType( LLPLCharacterType materialType ) = 0; + //Set the various navmesh colors + virtual void setNavMeshColors( const NavMeshColors& color ) = 0; + + //The entry method to rendering the client side navmesh + virtual void renderNavMesh() = 0; + //The entry method to rendering the client side navmesh edges + virtual void renderNavMeshEdges() = 0; + //The entry method to render the client navmesh shapes VBO + virtual void renderNavMeshShapesVBO( U32 shapeRenderFlags ) = 0; + //The entry method to render the clients designated path + virtual void renderPath() = 0; + //The entry method to render the capsule bookends for the clients designated path + virtual void renderPathBookend( LLRender& gl, LLPathingLib::LLPLPathBookEnd type ) = 0; + //Renders all of the generated simple shapes (using their default transforms) + virtual void renderSimpleShapes( LLRender& gl, F32 regionsWaterHeight ) = 0; + + //Method called from second life to create a capsule from properties of a character + virtual void createPhysicsCapsuleRep( F32 length, F32 radius, BOOL horizontal, const LLUUID& id ) = 0; + //Removes any cached physics capsule using a list of cached uuids + virtual void cleanupPhysicsCapsuleRepResiduals() = 0; + //Renders a selected uuids physics rep + virtual void renderSimpleShapeCapsuleID( LLRender& gl, const LLUUID& id, const LLVector3& pos, const LLQuaternion& rot ) = 0; + + //Method to delete any vbo's that are currently being managed by the pathing library + virtual void cleanupVBOManager( ) = 0; + //Method to cleanup any allocations within the implementation + virtual void cleanupResidual( ) = 0; +private: + static bool s_isInitialized; +}; + +#endif //LL_PATHING_LIBRARY diff --git a/indra/llprimitive/llphysicsextensions/llphysicsextensions.cpp b/indra/llprimitive/llphysicsextensions/llphysicsextensions.cpp new file mode 100644 index 0000000000..9bb4522a23 --- /dev/null +++ b/indra/llprimitive/llphysicsextensions/llphysicsextensions.cpp @@ -0,0 +1,103 @@ +/** +* @file llphysicsextensions.cpp +* @author nyx@lindenlab.com +* @brief LLPhysicsExtensions core initialization methods +* +* $LicenseInfo:firstyear=2012&license=lgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2011, 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$ +*/ + +#if defined(_WINDOWS) +# include "windowsincludes.h" +#endif + +#ifndef NULL +#define NULL 0 +#endif + + +#include "llphysicsextensions.h" + +#if !defined(LL_PHYSICS_EXTENSIONS_STUB) +# include "LLPhysicsExtensionsImpl.h" +#else +# include "LLPhysicsExtensionsStubImpl.h" +#endif + + +//disable the undefined symbol optimization +//#pragma warning (disable : 4221) + +//============================================================================= + +/*static */bool LLPhysicsExtensions::s_isInitialized = false; + + +/*static*/bool LLPhysicsExtensions::isFunctional() +{ +#if !defined(LL_PHYSICS_EXTENSIONS_STUB) + return true; +#else + return false; +#endif +} + +//============================================================================= + +#if !defined(LL_PHYSICS_EXTENSIONS_STUB) && defined(HK_COMPILER_CLANG) + //have to specialize before use so that generalized one not auto gen-d +HK_SINGLETON_SPECIALIZATION_DECL(LLPhysicsExtensionsImpl); +#endif + +/*static*/LLPhysicsExtensions* LLPhysicsExtensions::getInstance() +{ + if ( !s_isInitialized ) + { + return NULL; + } + else + { +#if !defined(LL_PHYSICS_EXTENSIONS_STUB) + return &hkSingleton<LLPhysicsExtensionsImpl>::getInstance(); +#else + return LLPhysicsExtensionsImpl::getInstance(); +#endif + } +} + +//============================================================================= + +/*static */bool LLPhysicsExtensions::initSystem() +{ + bool result = LLPhysicsExtensionsImpl::initSystem(); + if ( result ) + { + s_isInitialized = true; + } + return result; +} +//============================================================================= +/*static */bool LLPhysicsExtensions::quitSystem() +{ + return LLPhysicsExtensionsImpl::quitSystem(); +} +//============================================================================= + diff --git a/indra/llprimitive/llphysicsextensions/llphysicsextensions.h b/indra/llprimitive/llphysicsextensions/llphysicsextensions.h new file mode 100644 index 0000000000..be479f5d8a --- /dev/null +++ b/indra/llprimitive/llphysicsextensions/llphysicsextensions.h @@ -0,0 +1,59 @@ +/** +* @file llphysicsextensions.h +* @author nyx@lindenlab.com +* @brief LLPhysicsExtensions core shared initialization +* routines +* +* $LicenseInfo:firstyear=2012&license=lgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2011, 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_PHYSICS_EXTENSIONS +#define LL_PHYSICS_EXTENSIONS + +#include "llpreprocessor.h" +#include "llsd.h" +#include "v3dmath.h" + +#define LLPHYSICSEXTENSIONS_VERSION "1.0" + +typedef int bool32; + +class LLPhysicsExtensions +{ + +public: + // Obtain a pointer to the actual implementation + static LLPhysicsExtensions* getInstance(); + + /// @returns false if this is the stub + static bool isFunctional(); + + static bool initSystem(); + static bool quitSystem(); + +private: + static bool s_isInitialized; +}; + +#endif //LL_PATHING_LIBRARY + + diff --git a/indra/llprimitive/llprimitive.cpp b/indra/llprimitive/llprimitive.cpp index 644476460c..f6246e283f 100644 --- a/indra/llprimitive/llprimitive.cpp +++ b/indra/llprimitive/llprimitive.cpp @@ -274,7 +274,7 @@ void LLPrimitive::setAllTETextures(const LLUUID &tex_id) //=============================================================== void LLPrimitive::setTE(const U8 index, const LLTextureEntry& te) { - if(mTextureList.copyTexture(index, te) != TEM_CHANGE_NONE && te.getBumpmap() > 0) + if(mTextureList.copyTexture(index, &te) != TEM_CHANGE_NONE && te.getBumpmap() > 0) { mNumBumpmapTEs++; } @@ -753,7 +753,7 @@ void LLPrimitive::copyTEs(const LLPrimitive *primitivep) } for (i = 0; i < num_tes; i++) { - mTextureList.copyTexture(i, *(primitivep->getTE(i))); + mTextureList.copyTexture(i, primitivep->getTE(i)); } } diff --git a/indra/llprimitive/llprimtexturelist.cpp b/indra/llprimitive/llprimtexturelist.cpp index 68f3f5ffac..7f60d8025a 100644 --- a/indra/llprimitive/llprimtexturelist.cpp +++ b/indra/llprimitive/llprimtexturelist.cpp @@ -125,7 +125,7 @@ void LLPrimTextureList::take(LLPrimTextureList& other_list) // virtual // copies LLTextureEntry 'te' // returns TEM_CHANGE_TEXTURE if successful, otherwise TEM_CHANGE_NONE -S32 LLPrimTextureList::copyTexture(const U8 index, const LLTextureEntry& te) +S32 LLPrimTextureList::copyTexture(const U8 index, const LLTextureEntry* te) { if (size_t(index) >= mEntryList.size()) { @@ -137,14 +137,7 @@ S32 LLPrimTextureList::copyTexture(const U8 index, const LLTextureEntry& te) // we're changing an existing entry llassert(mEntryList[index]); delete (mEntryList[index]); - if (&te) - { - mEntryList[index] = te.newCopy(); - } - else - { - mEntryList[index] = LLPrimTextureList::newTextureEntry(); - } + mEntryList[index] = te->newCopy(); return TEM_CHANGE_TEXTURE; } diff --git a/indra/llprimitive/llprimtexturelist.h b/indra/llprimitive/llprimtexturelist.h index 79744e9f08..b8bdad60b3 100644 --- a/indra/llprimitive/llprimtexturelist.h +++ b/indra/llprimitive/llprimtexturelist.h @@ -71,7 +71,7 @@ public: // copies LLTextureEntry 'te' // returns TEM_CHANGE_TEXTURE if successful, otherwise TEM_CHANGE_NONE - S32 copyTexture(const U8 index, const LLTextureEntry& te); + S32 copyTexture(const U8 index, const LLTextureEntry* te); // takes ownership of LLTextureEntry* 'te' // returns TEM_CHANGE_TEXTURE if successful, otherwise TEM_CHANGE_NONE diff --git a/indra/llrender/CMakeLists.txt b/indra/llrender/CMakeLists.txt index 7f881c8bb3..7424356057 100644 --- a/indra/llrender/CMakeLists.txt +++ b/indra/llrender/CMakeLists.txt @@ -106,3 +106,4 @@ target_link_libraries(llrender OpenGL::GLU ) +include(LibraryInstall) diff --git a/indra/llrender/llcubemap.cpp b/indra/llrender/llcubemap.cpp index 26e4aaad52..53691bafe2 100644 --- a/indra/llrender/llcubemap.cpp +++ b/indra/llrender/llcubemap.cpp @@ -214,7 +214,9 @@ void LLCubeMap::initEnvironmentMap(const std::vector<LLPointer<LLImageRaw> >& ra enableTexture(0); bind(); mImages[0]->setFilteringOption(LLTexUnit::TFO_ANISOTROPIC); +#if GL_VERSION_3_2 glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS); +#endif glGenerateMipmap(GL_TEXTURE_CUBE_MAP); gGL.getTexUnit(0)->disable(); disable(); diff --git a/indra/llrender/llcubemaparray.cpp b/indra/llrender/llcubemaparray.cpp index be69b997da..0242fe60ce 100644 --- a/indra/llrender/llcubemaparray.cpp +++ b/indra/llrender/llcubemaparray.cpp @@ -134,8 +134,10 @@ void LLCubeMapArray::allocate(U32 resolution, U32 components, U32 count, bool us while (resolution >= 1) { +#if GL_VERSION_4_0 glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, mip, format, resolution, resolution, count * 6, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); +#endif if (!use_mips) { diff --git a/indra/llrender/llfontfreetype.cpp b/indra/llrender/llfontfreetype.cpp index 741ed993b0..9766de1dfa 100644 --- a/indra/llrender/llfontfreetype.cpp +++ b/indra/llrender/llfontfreetype.cpp @@ -52,7 +52,9 @@ #include "llfontbitmapcache.h" #include "llgl.h" -#define ENABLE_OT_SVG_SUPPORT +#if !defined(LL_NO_OTSVG) + #define ENABLE_OT_SVG_SUPPORT +#endif FT_Render_Mode gFontRenderMode = FT_RENDER_MODE_NORMAL; @@ -87,7 +89,7 @@ LLFontManager::LLFontManager() FT_Done_FreeType(gFTLibrary); } -#ifdef ENABLE_OT_SVG_SUPPORT +#if defined(ENABLE_OT_SVG_SUPPORT) SVG_RendererHooks hooks = { LLFontFreeTypeSvgRenderer::OnInit, LLFontFreeTypeSvgRenderer::OnFree, @@ -483,8 +485,8 @@ LLFontGlyphInfo* LLFontFreetype::addGlyph(llwchar wch, EFontGlyphType glyph_type continue; } glyph_index = FT_Get_Char_Index(pair.first->mFTFace, wch); - if (glyph_index) - { + if (glyph_index) + { return addGlyphFromFont(pair.first, wch, glyph_index, glyph_type); } diff --git a/indra/llrender/llfontfreetypesvg.cpp b/indra/llrender/llfontfreetypesvg.cpp index 355e8432aa..45cbc5dbd7 100644 --- a/indra/llrender/llfontfreetypesvg.cpp +++ b/indra/llrender/llfontfreetypesvg.cpp @@ -34,9 +34,17 @@ #endif #define NANOSVG_IMPLEMENTATION +#if __FreeBSD__ +#include <nanosvg.h> +#else #include <nanosvg/nanosvg.h> +#endif #define NANOSVGRAST_IMPLEMENTATION +#if __FreeBSD__ +#include <nanosvgrast.h> +#else #include <nanosvg/nanosvgrast.h> +#endif #if LL_WINDOWS #pragma warning (pop) @@ -80,6 +88,7 @@ void LLFontFreeTypeSvgRenderer::OnDataFinalizer(void* objectp) //static FT_Error LLFontFreeTypeSvgRenderer::OnPresetGlypthSlot(FT_GlyphSlot glyph_slot, FT_Bool cache, FT_Pointer*) { +#ifndef LL_NO_OTSVG FT_SVG_Document document = static_cast<FT_SVG_Document>(glyph_slot->other); llassert(!glyph_slot->generic.data || !cache || glyph_slot->glyph_index == ((LLSvgRenderData*)glyph_slot->generic.data)->GlyphIndex); @@ -166,6 +175,9 @@ FT_Error LLFontFreeTypeSvgRenderer::OnPresetGlypthSlot(FT_GlyphSlot glyph_slot, } return FT_Err_Ok; +#else + return FT_Err_Unimplemented_Feature; +#endif } // static diff --git a/indra/llrender/llfontfreetypesvg.h b/indra/llrender/llfontfreetypesvg.h index 4170cab273..94b83d5fff 100644 --- a/indra/llrender/llfontfreetypesvg.h +++ b/indra/llrender/llfontfreetypesvg.h @@ -29,7 +29,11 @@ #include <ft2build.h> #include FT_TYPES_H #include FT_MODULE_H -#include FT_OTSVG_H +#ifdef FT_OTSVG_H + #include FT_OTSVG_H +#else + #define LL_NO_OTSVG +#endif // See https://freetype.org/freetype2/docs/reference/ft2-svg_fonts.html class LLFontFreeTypeSvgRenderer diff --git a/indra/llrender/llfontgl.cpp b/indra/llrender/llfontgl.cpp index 59ee8ef84f..9482987970 100644 --- a/indra/llrender/llfontgl.cpp +++ b/indra/llrender/llfontgl.cpp @@ -270,10 +270,10 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons const LLFontGlyphInfo* next_glyph = NULL; - const S32 GLYPH_BATCH_SIZE = 30; - LLVector3 vertices[GLYPH_BATCH_SIZE * 4]; - LLVector2 uvs[GLYPH_BATCH_SIZE * 4]; - LLColor4U colors[GLYPH_BATCH_SIZE * 4]; + const S32 GLYPH_BATCH_SIZE = 120; + LLVector4a vertices[GLYPH_BATCH_SIZE * 6]; + LLVector2 uvs[GLYPH_BATCH_SIZE * 6]; + LLColor4U colors[GLYPH_BATCH_SIZE * 6]; LLColor4U text_color(color); // Preserve the transparency to render fading emojis in fading text (e.g. @@ -305,9 +305,9 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons // otherwise the queued glyphs will be taken from wrong textures. if (glyph_count > 0) { - gGL.begin(LLRender::QUADS); + gGL.begin(LLRender::TRIANGLES); { - gGL.vertexBatchPreTransformed(vertices, uvs, colors, glyph_count * 4); + gGL.vertexBatchPreTransformed(vertices, uvs, colors, glyph_count * 6); } gGL.end(); glyph_count = 0; @@ -338,12 +338,11 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons if (glyph_count >= GLYPH_BATCH_SIZE) { - gGL.begin(LLRender::QUADS); + gGL.begin(LLRender::TRIANGLES); { - gGL.vertexBatchPreTransformed(vertices, uvs, colors, glyph_count * 4); + gGL.vertexBatchPreTransformed(vertices, uvs, colors, glyph_count * 6); } gGL.end(); - glyph_count = 0; } @@ -376,9 +375,9 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons cur_render_y = cur_y; } - gGL.begin(LLRender::QUADS); + gGL.begin(LLRender::TRIANGLES); { - gGL.vertexBatchPreTransformed(vertices, uvs, colors, glyph_count * 4); + gGL.vertexBatchPreTransformed(vertices, uvs, colors, glyph_count * 6); } gGL.end(); @@ -1226,31 +1225,42 @@ LLFontGL &LLFontGL::operator=(const LLFontGL &source) return *this; } -void LLFontGL::renderQuad(LLVector3* vertex_out, LLVector2* uv_out, LLColor4U* colors_out, const LLRectf& screen_rect, const LLRectf& uv_rect, const LLColor4U& color, F32 slant_amt) const +void LLFontGL::renderTriangle(LLVector4a* vertex_out, LLVector2* uv_out, LLColor4U* colors_out, const LLRectf& screen_rect, const LLRectf& uv_rect, const LLColor4U& color, F32 slant_amt) const { S32 index = 0; - vertex_out[index] = LLVector3(screen_rect.mRight, screen_rect.mTop, 0.f); + vertex_out[index] = LLVector4a(screen_rect.mRight, screen_rect.mTop, 0.f); uv_out[index] = LLVector2(uv_rect.mRight, uv_rect.mTop); colors_out[index] = color; index++; - vertex_out[index] = LLVector3(screen_rect.mLeft, screen_rect.mTop, 0.f); + vertex_out[index] = LLVector4a(screen_rect.mLeft, screen_rect.mTop, 0.f); uv_out[index] = LLVector2(uv_rect.mLeft, uv_rect.mTop); colors_out[index] = color; index++; - vertex_out[index] = LLVector3(screen_rect.mLeft, screen_rect.mBottom, 0.f); + vertex_out[index] = LLVector4a(screen_rect.mLeft, screen_rect.mBottom, 0.f); + uv_out[index] = LLVector2(uv_rect.mLeft, uv_rect.mBottom); + colors_out[index] = color; + index++; + + + vertex_out[index] = LLVector4a(screen_rect.mRight, screen_rect.mTop, 0.f); + uv_out[index] = LLVector2(uv_rect.mRight, uv_rect.mTop); + colors_out[index] = color; + index++; + + vertex_out[index] = LLVector4a(screen_rect.mLeft, screen_rect.mBottom, 0.f); uv_out[index] = LLVector2(uv_rect.mLeft, uv_rect.mBottom); colors_out[index] = color; index++; - vertex_out[index] = LLVector3(screen_rect.mRight, screen_rect.mBottom, 0.f); + vertex_out[index] = LLVector4a(screen_rect.mRight, screen_rect.mBottom, 0.f); uv_out[index] = LLVector2(uv_rect.mRight, uv_rect.mBottom); colors_out[index] = color; } -void LLFontGL::drawGlyph(S32& glyph_count, LLVector3* vertex_out, LLVector2* uv_out, LLColor4U* colors_out, const LLRectf& screen_rect, const LLRectf& uv_rect, const LLColor4U& color, U8 style, ShadowType shadow, F32 drop_shadow_strength) const +void LLFontGL::drawGlyph(S32& glyph_count, LLVector4a* vertex_out, LLVector2* uv_out, LLColor4U* colors_out, const LLRectf& screen_rect, const LLRectf& uv_rect, const LLColor4U& color, U8 style, ShadowType shadow, F32 drop_shadow_strength) const { F32 slant_offset; slant_offset = ((style & ITALIC) ? ( -mFontFreetype->getAscenderHeight() * 0.2f) : 0.f); @@ -1264,7 +1274,7 @@ void LLFontGL::drawGlyph(S32& glyph_count, LLVector3* vertex_out, LLVector2* uv_ LLRectf screen_rect_offset = screen_rect; screen_rect_offset.translate((F32)(pass * BOLD_OFFSET), 0.f); - renderQuad(&vertex_out[glyph_count * 4], &uv_out[glyph_count * 4], &colors_out[glyph_count * 4], screen_rect_offset, uv_rect, color, slant_offset); + renderTriangle(&vertex_out[glyph_count * 6], &uv_out[glyph_count * 6], &colors_out[glyph_count * 6], screen_rect_offset, uv_rect, color, slant_offset); glyph_count++; } } @@ -1295,10 +1305,10 @@ void LLFontGL::drawGlyph(S32& glyph_count, LLVector3* vertex_out, LLVector2* uv_ break; } - renderQuad(&vertex_out[glyph_count * 4], &uv_out[glyph_count * 4], &colors_out[glyph_count * 4], screen_rect_offset, uv_rect, shadow_color, slant_offset); + renderTriangle(&vertex_out[glyph_count * 6], &uv_out[glyph_count * 6], &colors_out[glyph_count * 6], screen_rect_offset, uv_rect, shadow_color, slant_offset); glyph_count++; } - renderQuad(&vertex_out[glyph_count * 4], &uv_out[glyph_count * 4], &colors_out[glyph_count * 4], screen_rect, uv_rect, color, slant_offset); + renderTriangle(&vertex_out[glyph_count * 6], &uv_out[glyph_count * 6], &colors_out[glyph_count * 6], screen_rect, uv_rect, color, slant_offset); glyph_count++; } else if (shadow == DROP_SHADOW) @@ -1307,14 +1317,14 @@ void LLFontGL::drawGlyph(S32& glyph_count, LLVector3* vertex_out, LLVector2* uv_ shadow_color.mV[VALPHA] = U8(color.mV[VALPHA] * drop_shadow_strength); LLRectf screen_rect_shadow = screen_rect; screen_rect_shadow.translate(1.f, -1.f); - renderQuad(&vertex_out[glyph_count * 4], &uv_out[glyph_count * 4], &colors_out[glyph_count * 4], screen_rect_shadow, uv_rect, shadow_color, slant_offset); + renderTriangle(&vertex_out[glyph_count * 6], &uv_out[glyph_count * 6], &colors_out[glyph_count * 6], screen_rect_shadow, uv_rect, shadow_color, slant_offset); glyph_count++; - renderQuad(&vertex_out[glyph_count * 4], &uv_out[glyph_count * 4], &colors_out[glyph_count * 4], screen_rect, uv_rect, color, slant_offset); + renderTriangle(&vertex_out[glyph_count * 6], &uv_out[glyph_count * 6], &colors_out[glyph_count * 6], screen_rect, uv_rect, color, slant_offset); glyph_count++; } else // normal rendering { - renderQuad(&vertex_out[glyph_count * 4], &uv_out[glyph_count * 4], &colors_out[glyph_count * 4], screen_rect, uv_rect, color, slant_offset); + renderTriangle(&vertex_out[glyph_count * 6], &uv_out[glyph_count * 6], &colors_out[glyph_count * 6], screen_rect, uv_rect, color, slant_offset); glyph_count++; } } diff --git a/indra/llrender/llfontgl.h b/indra/llrender/llfontgl.h index de7529a583..4bb6c55c65 100644 --- a/indra/llrender/llfontgl.h +++ b/indra/llrender/llfontgl.h @@ -238,8 +238,8 @@ private: LLFontDescriptor mFontDescriptor; LLPointer<LLFontFreetype> mFontFreetype; - void renderQuad(LLVector3* vertex_out, LLVector2* uv_out, LLColor4U* colors_out, const LLRectf& screen_rect, const LLRectf& uv_rect, const LLColor4U& color, F32 slant_amt) const; - void drawGlyph(S32& glyph_count, LLVector3* vertex_out, LLVector2* uv_out, LLColor4U* colors_out, const LLRectf& screen_rect, const LLRectf& uv_rect, const LLColor4U& color, U8 style, ShadowType shadow, F32 drop_shadow_fade) const; + void renderTriangle(LLVector4a* vertex_out, LLVector2* uv_out, LLColor4U* colors_out, const LLRectf& screen_rect, const LLRectf& uv_rect, const LLColor4U& color, F32 slant_amt) const; + void drawGlyph(S32& glyph_count, LLVector4a* vertex_out, LLVector2* uv_out, LLColor4U* colors_out, const LLRectf& screen_rect, const LLRectf& uv_rect, const LLColor4U& color, U8 style, ShadowType shadow, F32 drop_shadow_fade) const; // Registry holds all instantiated fonts. static LLFontRegistry* sFontRegistry; diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp index 7959b3bb57..2a7cc3d141 100644 --- a/indra/llrender/llgl.cpp +++ b/indra/llrender/llgl.cpp @@ -50,6 +50,11 @@ #include "llglheaders.h" #include "llglslshader.h" +#include "llvertexbuffer.h" +#include "llcontrol.h" +extern LLControlGroup gSavedSettings; + + #if LL_WINDOWS #include "lldxhardware.h" #endif @@ -72,7 +77,7 @@ static const std::string HEADLESS_VERSION_STRING("1.0"); llofstream gFailLog; -#if GL_ARB_debug_output +#if GL_ARB_debug_output || GL_KHR_debug #ifndef APIENTRY #define APIENTRY @@ -95,9 +100,9 @@ void APIENTRY gl_debug_callback(GLenum source, }*/ if (gGLManager.mIsDisabled && - severity == GL_DEBUG_SEVERITY_HIGH_ARB && - source == GL_DEBUG_SOURCE_API_ARB && - type == GL_DEBUG_TYPE_ERROR_ARB && + severity == GL_DEBUG_SEVERITY_HIGH && + source == GL_DEBUG_SOURCE_API && + type == GL_DEBUG_TYPE_ERROR && id == GL_INVALID_VALUE) { // Suppress messages about deleting already deleted objects called from LLViewerWindow::stopGL() @@ -157,7 +162,11 @@ void APIENTRY gl_debug_callback(GLenum source, if (ubo != 0) { glGetBufferParameteriv(GL_UNIFORM_BUFFER, GL_BUFFER_SIZE, &ubo_size); +#if GL_EXT_buffer_storage + glGetBufferParameteriv(GL_UNIFORM_BUFFER, GL_BUFFER_IMMUTABLE_STORAGE_EXT, &ubo_immutable); +#else glGetBufferParameteriv(GL_UNIFORM_BUFFER, GL_BUFFER_IMMUTABLE_STORAGE, &ubo_immutable); +#endif } // No needs to halt when is called from LLViewerWindow::stopGL() @@ -211,8 +220,6 @@ LLMatrix4 gGLObliqueProjectionInverse; std::list<LLGLUpdate*> LLGLUpdate::sGLQ; -#if (LL_WINDOWS || LL_LINUX) && !LL_MESA_HEADLESS - #if LL_WINDOWS // WGL_ARB_create_context PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB = nullptr; @@ -232,7 +239,7 @@ PFNWGLBLITCONTEXTFRAMEBUFFERAMDPROC wglBlitContextFramebufferAMD = n PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT = nullptr; PFNWGLGETSWAPINTERVALEXTPROC wglGetSwapIntervalEXT = nullptr; -#endif +/* // GL_VERSION_1_2 //PFNGLDRAWRANGEELEMENTSPROC glDrawRangeElements = nullptr; @@ -978,6 +985,7 @@ PFNGLMULTIDRAWARRAYSINDIRECTCOUNTPROC glMultiDrawArraysIndirectCount = nullpt PFNGLMULTIDRAWELEMENTSINDIRECTCOUNTPROC glMultiDrawElementsIndirectCount = nullptr; PFNGLPOLYGONOFFSETCLAMPPROC glPolygonOffsetClamp = nullptr; +*/ #endif LLGLManager gGLManager; @@ -994,6 +1002,7 @@ LLGLManager::LLGLManager() : mIsAMD(false), mIsNVIDIA(false), mIsIntel(false), + mIsApple(false), #if LL_DARWIN mIsMobileGF(false), #endif @@ -1131,6 +1140,7 @@ bool LLGLManager::initGL() #endif } +#if GL_VERSION_1_3 if (mGLVersion >= 2.1f && LLImageGL::sCompressTextures) { //use texture compression glHint(GL_TEXTURE_COMPRESSION_HINT, GL_NICEST); @@ -1139,6 +1149,7 @@ bool LLGLManager::initGL() { //GL version is < 3.0, always disable texture compression LLImageGL::sCompressTextures = false; } +#endif // Trailing space necessary to keep "nVidia Corpor_ati_on" cards // from being recognized as ATI. @@ -1155,7 +1166,7 @@ bool LLGLManager::initGL() mIsNVIDIA = true; } else if (mGLVendor.find("INTEL") != std::string::npos -#if LL_LINUX +#if LL_LINUX || __FreeBSD__ // The Mesa-based drivers put this in the Renderer string, // not the Vendor string. || mGLRenderer.find("INTEL") != std::string::npos @@ -1165,6 +1176,11 @@ bool LLGLManager::initGL() mGLVendorShort = "INTEL"; mIsIntel = true; } + else if(mGLVendor.find("APPLE") != std::string::npos) + { + mGLVendorShort = "APPLE"; + mIsApple = TRUE; + } else { mGLVendorShort = "MISC"; @@ -1233,10 +1249,12 @@ bool LLGLManager::initGL() } glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &mNumTextureImageUnits); +#if GL_VERSION_3_2 glGetIntegerv(GL_MAX_COLOR_TEXTURE_SAMPLES, &mMaxColorTextureSamples); glGetIntegerv(GL_MAX_DEPTH_TEXTURE_SAMPLES, &mMaxDepthTextureSamples); glGetIntegerv(GL_MAX_INTEGER_SAMPLES, &mMaxIntegerSamples); glGetIntegerv(GL_MAX_SAMPLE_MASK_WORDS, &mMaxSampleMaskWords); +#endif glGetIntegerv(GL_MAX_SAMPLES, &mMaxSamples); glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &mMaxUniformBlockSize); @@ -1246,11 +1264,23 @@ bool LLGLManager::initGL() if (mGLVersion >= 4.59f) { - glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY, &mMaxAnisotropy); + glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &mMaxAnisotropy); } initGLStates(); + U32 MPVBufferOptiMode = gSavedSettings.getU32("MPVBufferOptiMode"); + if (MPVBufferOptiMode == 0) + { + if(mIsApple) MPVBufferOptiMode = 2; + else MPVBufferOptiMode = 1; + gSavedSettings.setU32("MPVBufferOptiMode",MPVBufferOptiMode); + } + LLVertexBuffer::sMappingMode = MPVBufferOptiMode; + //LLRender::sMappingMode = MPVBufferOptiMode; + + LL_INFOS() << "milo init sMappingMode " << MPVBufferOptiMode << LL_ENDL; + return true; } @@ -1367,6 +1397,7 @@ void LLGLManager::asLLSD(LLSD& info) info["is_ati"] = mIsAMD; // note, do not rename is_ati to is_amd without coordinating with DW info["is_nvidia"] = mIsNVIDIA; info["is_intel"] = mIsIntel; + info["is_apple"] = mIsApple; info["gl_renderer"] = mGLRenderer; } @@ -1386,6 +1417,9 @@ void LLGLManager::shutdownGL() void LLGLManager::initExtensions() { +#if LL_LINUX + glh_init_extensions(""); +#endif #if LL_DARWIN GLint num_extensions = 0; std::string all_extensions{""}; @@ -1416,10 +1450,10 @@ void LLGLManager::initExtensions() mInited = true; -#if (LL_WINDOWS || LL_LINUX) && !LL_MESA_HEADLESS +/* +#if LL_WINDOWS LL_DEBUGS("RenderInit") << "GL Probe: Getting symbols" << LL_ENDL; -#if LL_WINDOWS // WGL_AMD_gpu_association wglGetGPUIDsAMD = (PFNWGLGETGPUIDSAMDPROC)GLH_EXT_GET_PROC_ADDRESS("wglGetGPUIDsAMD"); wglGetGPUInfoAMD = (PFNWGLGETGPUINFOAMDPROC)GLH_EXT_GET_PROC_ADDRESS("wglGetGPUInfoAMD"); @@ -1437,8 +1471,6 @@ void LLGLManager::initExtensions() // WGL_ARB_create_context wglCreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC)GLH_EXT_GET_PROC_ADDRESS("wglCreateContextAttribsARB"); -#endif - // Load entire OpenGL API through GetProcAddress, leaving sections beyond mGLVersion unloaded @@ -2256,6 +2288,7 @@ void LLGLManager::initExtensions() glPolygonOffsetClamp = (PFNGLPOLYGONOFFSETCLAMPPROC)GLH_EXT_GET_PROC_ADDRESS("glPolygonOffsetClamp"); #endif +*/ } void rotate_quat(LLQuaternion& rotation) @@ -2282,12 +2315,14 @@ void log_glerror() error = glGetError(); while (LL_UNLIKELY(error)) { +#if GLU_VERSION_1_1 GLubyte const * gl_error_msg = gluErrorString(error); if (NULL != gl_error_msg) { LL_WARNS() << "GL Error: " << error << " GL Error String: " << gl_error_msg << LL_ENDL ; } else +#endif // GLU_VERSION_1_1 { // gluErrorString returns NULL for some extensions' error codes. // you'll probably have to grep for the number in glext.h. @@ -2306,6 +2341,7 @@ void do_assert_glerror() if (LL_UNLIKELY(error)) { quit = true; +#if GLU_VERSION_1_1 GLubyte const * gl_error_msg = gluErrorString(error); if (NULL != gl_error_msg) { @@ -2318,6 +2354,7 @@ void do_assert_glerror() } } else +#endif // GLU_VERSION_1_1 { // gluErrorString returns NULL for some extensions' error codes. // you'll probably have to grep for the number in glext.h. @@ -2392,8 +2429,10 @@ void LLGLState::initClass() // sStateMap[GL_TEXTURE_2D] = GL_TRUE; //make sure multisample defaults to disabled +#if GL_EXT_multisample || GL_EXT_multisampled_compatibility sStateMap[GL_MULTISAMPLE] = GL_FALSE; glDisable(GL_MULTISAMPLE); +#endif } //static @@ -2408,6 +2447,7 @@ void LLGLState::restoreGL() void LLGLState::resetTextureStates() { gGL.flush(); +#if GL_VERSION_1_3 GLint maxTextureUnits; glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &maxTextureUnits); @@ -2417,6 +2457,7 @@ void LLGLState::resetTextureStates() glClientActiveTexture(GL_TEXTURE0+j); j == 0 ? gGL.getTexUnit(j)->enable(LLTexUnit::TT_TEXTURE) : gGL.getTexUnit(j)->disable(); } +#endif } void LLGLState::dumpStates() @@ -2566,6 +2607,7 @@ void parse_gl_version( S32* major, S32* minor, S32* release, std::string* vendor { return; } + LL_INFOS() << "GL: " << version << LL_ENDL; version_string->assign(version); @@ -2945,5 +2987,3 @@ extern "C" __declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1; } #endif - - diff --git a/indra/llrender/llgl.h b/indra/llrender/llgl.h index 909dad2e85..a3d87e001c 100644 --- a/indra/llrender/llgl.h +++ b/indra/llrender/llgl.h @@ -101,6 +101,7 @@ public: bool mIsAMD; bool mIsNVIDIA; bool mIsIntel; + bool mIsApple; #if LL_DARWIN // Needed to distinguish problem cards on older Macs that break with Materials diff --git a/indra/llrender/llglheaders.h b/indra/llrender/llglheaders.h index c5e1ff3e23..7d56f12766 100644 --- a/indra/llrender/llglheaders.h +++ b/indra/llrender/llglheaders.h @@ -27,7 +27,7 @@ #ifndef LL_LLGLHEADERS_H #define LL_LLGLHEADERS_H -#if LL_MESA +#if LL_MESA || LL_LINUX || __FreeBSD__ //---------------------------------------------------------------------------- // MESA headers // quotes so we get libraries/.../GL/ version @@ -41,6 +41,22 @@ # include "GL/glh_extensions.h" # undef __APPLE__ +#elif LL_LINUX +#define GL_GLEXT_PROTOTYPES +#define GLX_GLEXT_PROTOTYPES + +#include "GL/gl.h" +#include "GL/glext.h" +#include "GL/glu.h" + +// The __APPLE__ kludge is to make glh_extensions.h not symbol-clash horribly +# define __APPLE__ +# include "GL/glh_extensions.h" +# undef __APPLE__ + +# include "GL/glx.h" +# include "GL/glxext.h" + #elif LL_WINDOWS //---------------------------------------------------------------------------- // LL_WINDOWS @@ -823,10 +839,14 @@ extern PFNGLPOLYGONOFFSETCLAMPPROC glPolygonOffsetClamp; #define GL_EXT_separate_specular_color 1 #define GL_GLEXT_PROTOTYPES -#include "GL/glext.h" +#include <OpenGL/glext.h> + +#define GL_DO_NOT_WARN_IF_MULTI_GL_VERSION_HEADERS_INCLUDED +#include <OpenGL/gl3.h> #include "GL/glh_extensions.h" +#if 0 // These symbols don't exist on 10.3.9, so they have to be declared weak. Redeclaring them here fixes the problem. // Note that they also must not be called on 10.3.9. This should be taken care of by a runtime check for the existence of the GL extension. #include <AvailabilityMacros.h> @@ -1028,6 +1048,26 @@ extern void glGetBufferPointervARB (GLenum, GLenum, GLvoid* *); #endif #include <OpenGL/gl.h> +#endif // 0 + +#elif LL_LINUX + +#define GL_GLEXT_PROTOTYPES +#define GLX_GLEXT_PROTOTYPES + +#include "GL/gl.h" +#include "GL/glu.h" +#include "GL/glext.h" +#include "GL/glx.h" + +// The __APPLE__ kludge is to make glh_extensions.h not symbol-clash horribly +# define __APPLE__ +# include "GL/glh_extensions.h" +# undef __APPLE__ + +// #include <X11/Xlib.h> +// #include <X11/Xutil.h> +#include "GL/glh_extensions.h" #endif // LL_MESA / LL_WINDOWS / LL_DARWIN diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp index 25e4a88f28..880b491253 100644 --- a/indra/llrender/llglslshader.cpp +++ b/indra/llrender/llglslshader.cpp @@ -235,12 +235,18 @@ void LLGLSLShader::placeProfileQuery(bool for_runtime) glGenQueries(1, &mPrimitivesQuery); } - glBeginQuery(GL_TIME_ELAPSED, mTimerQuery); +#if GL_EXT_timer_query || GL_EXT_disjoint_timer_query + glBeginQuery(GL_TIME_ELAPSED_EXT, mTimerQuery); +#endif if (!for_runtime) { +#if GL_VERSION_1_5 glBeginQuery(GL_SAMPLES_PASSED, mSamplesQuery); +#endif +#if GL_VERSION_3_0 glBeginQuery(GL_PRIMITIVES_GENERATED, mPrimitivesQuery); +#endif } } } @@ -251,19 +257,30 @@ bool LLGLSLShader::readProfileQuery(bool for_runtime, bool force_read) { if (!mProfilePending) { - glEndQuery(GL_TIME_ELAPSED); +#if GL_EXT_timer_query || GL_EXT_disjoint_timer_query + glEndQuery(GL_TIME_ELAPSED_EXT); +#endif if (!for_runtime) { +#if GL_VERSION_1_5 glEndQuery(GL_SAMPLES_PASSED); +#endif +#if GL_VERSION_3_0 glEndQuery(GL_PRIMITIVES_GENERATED); +#endif } mProfilePending = for_runtime; } if (mProfilePending && for_runtime && !force_read) { +#if GL_ARB_timer_query GLuint64 result = 0; glGetQueryObjectui64v(mTimerQuery, GL_QUERY_RESULT_AVAILABLE, &result); +#else + GLuint result = 0; + glGetQueryObjectuiv(mTimerQuery, GL_QUERY_RESULT_AVAILABLE, &result); +#endif if (result != GL_TRUE) { @@ -271,18 +288,31 @@ bool LLGLSLShader::readProfileQuery(bool for_runtime, bool force_read) } } +#if GL_ARB_timer_query GLuint64 time_elapsed = 0; glGetQueryObjectui64v(mTimerQuery, GL_QUERY_RESULT, &time_elapsed); +#else + GLuint time_elapsed = 0; + glGetQueryObjectuiv(mTimerQuery, GL_QUERY_RESULT, &time_elapsed); +#endif mTimeElapsed += time_elapsed; mProfilePending = false; if (!for_runtime) { +#if GL_ARB_timer_query GLuint64 samples_passed = 0; glGetQueryObjectui64v(mSamplesQuery, GL_QUERY_RESULT, &samples_passed); GLuint64 primitives_generated = 0; glGetQueryObjectui64v(mPrimitivesQuery, GL_QUERY_RESULT, &primitives_generated); +#else + GLuint samples_passed = 0; + glGetQueryObjectuiv(mSamplesQuery, GL_QUERY_RESULT, &samples_passed); + + GLuint primitives_generated = 0; + glGetQueryObjectuiv(mPrimitivesQuery, GL_QUERY_RESULT, &primitives_generated); +#endif sTotalTimeElapsed += time_elapsed; sTotalSamplesDrawn += samples_passed; @@ -701,10 +731,14 @@ void LLGLSLShader::mapUniform(GLint index) case GL_FLOAT_VEC2: size *= 2; break; case GL_FLOAT_VEC3: size *= 3; break; case GL_FLOAT_VEC4: size *= 4; break; +#if GL_VERSION_1_1 case GL_DOUBLE: size *= 2; break; +#if GL_VERSION_4_0 case GL_DOUBLE_VEC2: size *= 2; break; case GL_DOUBLE_VEC3: size *= 6; break; case GL_DOUBLE_VEC4: size *= 8; break; +#endif // GL_VERSION_4_0 +#endif // GL_VERSION_1_1 case GL_INT_VEC2: size *= 2; break; case GL_INT_VEC3: size *= 3; break; case GL_INT_VEC4: size *= 4; break; @@ -723,6 +757,7 @@ void LLGLSLShader::mapUniform(GLint index) case GL_FLOAT_MAT3x4: size *= 12; break; case GL_FLOAT_MAT4x2: size *= 8; break; case GL_FLOAT_MAT4x3: size *= 12; break; +#if GL_VERSION_4_0 case GL_DOUBLE_MAT2: size *= 8; break; case GL_DOUBLE_MAT3: size *= 18; break; case GL_DOUBLE_MAT4: size *= 32; break; @@ -732,6 +767,7 @@ void LLGLSLShader::mapUniform(GLint index) case GL_DOUBLE_MAT3x4: size *= 24; break; case GL_DOUBLE_MAT4x2: size *= 16; break; case GL_DOUBLE_MAT4x3: size *= 24; break; +#endif // GL_VERSION_4_0 } mTotalUniformSize += size; } @@ -795,7 +831,10 @@ GLint LLGLSLShader::mapUniformTextureChannel(GLint location, GLenum type, GLint { LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER; - if ((type >= GL_SAMPLER_1D && type <= GL_SAMPLER_2D_RECT_SHADOW) || + if ( +#if GL_VERSION_2_0 + (type >= GL_SAMPLER_1D && type <= GL_SAMPLER_2D_RECT_SHADOW) || +#endif type == GL_SAMPLER_2D_MULTISAMPLE || type == GL_SAMPLER_CUBE_MAP_ARRAY) { //this here is a texture diff --git a/indra/llrender/llglstates.h b/indra/llrender/llglstates.h index 9bb980d7ad..68d4df8e90 100644 --- a/indra/llrender/llglstates.h +++ b/indra/llrender/llglstates.h @@ -166,6 +166,7 @@ public: //---------------------------------------------------------------------------- +#if GL_VERSION_1_1 class LLGLSSpecular { public: @@ -190,6 +191,7 @@ public: } } }; +#endif //---------------------------------------------------------------------------- diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index 7e5cd628c1..fb02c72338 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -273,23 +273,31 @@ S32 LLImageGL::dataFormatBits(S32 dataformat) { switch (dataformat) { +#if GL_EXT_texture_compression_s3tc || GL_EXT_texture_compression_dxt1 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: return 4; - case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: return 4; case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: return 8; - case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT: return 8; case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: return 8; +#endif +#if GL_EXT_texture_sRGB || GL_EXT_texture_compression_s3tc_srgb + case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: return 4; + case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT: return 8; case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: return 8; +#endif case GL_LUMINANCE: return 8; case GL_ALPHA: return 8; case GL_RED: return 8; +#if GL_VERSION_1_1 case GL_COLOR_INDEX: return 8; +#endif case GL_LUMINANCE_ALPHA: return 16; case GL_RGB: return 24; case GL_SRGB: return 24; case GL_RGB8: return 24; case GL_RGBA: return 32; +#if GL_VERSION_2_1 case GL_SRGB_ALPHA: return 32; case GL_BGRA: return 32; // Used for QuickTime media textures on the Mac +#endif case GL_DEPTH_COMPONENT: return 24; case GL_RGB16F: return 48; case GL_RGBA16F: return 64; @@ -304,6 +312,8 @@ S64 LLImageGL::dataFormatBytes(S32 dataformat, S32 width, S32 height) { switch (dataformat) { +#if GL_EXT_texture_compression_s3tc || GL_EXT_texture_compression_dxt1 \ + || GL_EXT_texture_sRGB || GL_EXT_texture_compression_s3tc_srgb case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: @@ -313,6 +323,7 @@ S64 LLImageGL::dataFormatBytes(S32 dataformat, S32 width, S32 height) if (width < 4) width = 4; if (height < 4) height = 4; break; +#endif default: break; } @@ -326,22 +337,30 @@ S32 LLImageGL::dataFormatComponents(S32 dataformat) { switch (dataformat) { +#if GL_EXT_texture_compression_s3tc || GL_EXT_texture_compression_dxt1 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: return 3; - case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: return 3; case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: return 4; - case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT: return 4; case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: return 4; +#endif +#if GL_EXT_texture_sRGB || GL_EXT_texture_compression_s3tc_srgb + case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: return 3; + case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT: return 4; case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: return 4; +#endif case GL_LUMINANCE: return 1; case GL_ALPHA: return 1; case GL_RED: return 1; +#if GL_VERSION_1_1 case GL_COLOR_INDEX: return 1; +#endif case GL_LUMINANCE_ALPHA: return 2; case GL_RGB: return 3; case GL_SRGB: return 3; case GL_RGBA: return 4; +#if GL_VERSION_2_1 case GL_SRGB_ALPHA: return 4; case GL_BGRA: return 4; // Used for QuickTime media textures on the Mac +#endif default: LL_ERRS() << "LLImageGL::Unknown format: " << dataformat << LL_ENDL; return 0; @@ -795,11 +814,13 @@ bool LLImageGL::setImage(const U8* data_in, bool data_hasmips /* = false */, S32 } else { +#if GL_VERSION_1_1 if(mFormatSwapBytes) { glPixelStorei(GL_UNPACK_SWAP_BYTES, 1); stop_glerror(); } +#endif LLImageGL::setManualImage(mTarget, gl_level, mFormatInternal, w, h, mFormatPrimary, GL_UNSIGNED_BYTE, (GLvoid*)data_in, mAllowCompression); if (gl_level == 0) @@ -808,11 +829,13 @@ bool LLImageGL::setImage(const U8* data_in, bool data_hasmips /* = false */, S32 } updatePickMask(w, h, data_in); +#if GL_VERSION_1_1 if(mFormatSwapBytes) { glPixelStorei(GL_UNPACK_SWAP_BYTES, 0); stop_glerror(); } +#endif stop_glerror(); } @@ -825,11 +848,13 @@ bool LLImageGL::setImage(const U8* data_in, bool data_hasmips /* = false */, S32 { stop_glerror(); { +#if GL_VERSION_1_1 if(mFormatSwapBytes) { glPixelStorei(GL_UNPACK_SWAP_BYTES, 1); stop_glerror(); } +#endif S32 w = getWidth(mCurrentDiscardLevel); S32 h = getHeight(mCurrentDiscardLevel); @@ -839,10 +864,12 @@ bool LLImageGL::setImage(const U8* data_in, bool data_hasmips /* = false */, S32 //use legacy mipmap generation mode (note: making this condional can cause rendering issues) // -- but making it not conditional triggers deprecation warnings when core profile is enabled // (some rendering issues while core profile is enabled are acceptable at this point in time) +#if GL_VERSION_1_4 if (!LLRender::sGLCoreProfile) { glTexParameteri(mTarget, GL_GENERATE_MIPMAP, GL_TRUE); } +#endif LLImageGL::setManualImage(mTarget, 0, mFormatInternal, w, h, @@ -853,11 +880,13 @@ bool LLImageGL::setImage(const U8* data_in, bool data_hasmips /* = false */, S32 updatePickMask(w, h, data_in); +#if GL_VERSION_1_1 if(mFormatSwapBytes) { glPixelStorei(GL_UNPACK_SWAP_BYTES, 0); stop_glerror(); } +#endif if (LLRender::sGLCoreProfile) { @@ -942,11 +971,13 @@ bool LLImageGL::setImage(const U8* data_in, bool data_hasmips /* = false */, S32 llassert(w > 0 && h > 0 && cur_mip_data); (void)cur_mip_data; { +#if GL_VERSION_1_1 if(mFormatSwapBytes) { glPixelStorei(GL_UNPACK_SWAP_BYTES, 1); stop_glerror(); } +#endif LLImageGL::setManualImage(mTarget, m, mFormatInternal, w, h, mFormatPrimary, mFormatType, cur_mip_data, mAllowCompression); if (m == 0) @@ -959,11 +990,13 @@ bool LLImageGL::setImage(const U8* data_in, bool data_hasmips /* = false */, S32 updatePickMask(w, h, cur_mip_data); } +#if GL_VERSION_1_1 if(mFormatSwapBytes) { glPixelStorei(GL_UNPACK_SWAP_BYTES, 0); stop_glerror(); } +#endif } if (prev_mip_data && prev_mip_data != data_in) { @@ -998,11 +1031,13 @@ bool LLImageGL::setImage(const U8* data_in, bool data_hasmips /* = false */, S32 } else { +#if GL_VERSION_1_1 if(mFormatSwapBytes) { glPixelStorei(GL_UNPACK_SWAP_BYTES, 1); stop_glerror(); } +#endif LLImageGL::setManualImage(mTarget, 0, mFormatInternal, w, h, mFormatPrimary, mFormatType, (GLvoid *)data_in, mAllowCompression); @@ -1012,11 +1047,13 @@ bool LLImageGL::setImage(const U8* data_in, bool data_hasmips /* = false */, S32 stop_glerror(); +#if GL_VERSION_1_1 if(mFormatSwapBytes) { glPixelStorei(GL_UNPACK_SWAP_BYTES, 0); stop_glerror(); } +#endif } } @@ -1061,13 +1098,17 @@ bool LLImageGL::preAddToAtlas(S32 discard_level, const LLImageRaw* raw_image) { case 1: // Use luminance alpha (for fonts) +#if GL_VERSION_1_1 mFormatInternal = GL_LUMINANCE8; +#endif mFormatPrimary = GL_LUMINANCE; mFormatType = GL_UNSIGNED_BYTE; break; case 2: // Use luminance alpha (for fonts) +#if GL_VERSION_1_1 mFormatInternal = GL_LUMINANCE8_ALPHA8; +#endif mFormatPrimary = GL_LUMINANCE_ALPHA; mFormatType = GL_UNSIGNED_BYTE; break; @@ -1095,22 +1136,26 @@ bool LLImageGL::preAddToAtlas(S32 discard_level, const LLImageRaw* raw_image) glPixelStorei(GL_UNPACK_ROW_LENGTH, raw_image->getWidth()); stop_glerror(); +#if GL_VERSION_1_1 if(mFormatSwapBytes) { glPixelStorei(GL_UNPACK_SWAP_BYTES, 1); stop_glerror(); } +#endif return true ; } void LLImageGL::postAddToAtlas() { +#if GL_VERSION_1_1 if(mFormatSwapBytes) { glPixelStorei(GL_UNPACK_SWAP_BYTES, 0); stop_glerror(); } +#endif glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); gGL.getTexUnit(0)->setTextureFilteringOption(mFilterOption); @@ -1124,7 +1169,9 @@ U32 type_width_from_pixtype(U32 pixtype) { case GL_UNSIGNED_BYTE: case GL_BYTE: +#if GL_VERSION_1_2 case GL_UNSIGNED_INT_8_8_8_8_REV: +#endif type_width = 1; break; case GL_UNSIGNED_SHORT: @@ -1239,11 +1286,13 @@ bool LLImageGL::setSubImage(const U8* datap, S32 data_width, S32 data_height, S3 glPixelStorei(GL_UNPACK_ROW_LENGTH, data_width); stop_glerror(); +#if GL_VERSION_1_1 if(mFormatSwapBytes) { glPixelStorei(GL_UNPACK_SWAP_BYTES, 1); stop_glerror(); } +#endif const U8* sub_datap = datap + (y_pos * data_width + x_pos) * getComponents(); // Update the GL texture @@ -1267,11 +1316,13 @@ bool LLImageGL::setSubImage(const U8* datap, S32 data_width, S32 data_height, S3 gGL.getTexUnit(0)->disable(); stop_glerror(); +#if GL_VERSION_1_1 if(mFormatSwapBytes) { glPixelStorei(GL_UNPACK_SWAP_BYTES, 0); stop_glerror(); } +#endif glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); stop_glerror(); @@ -1439,35 +1490,57 @@ void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 widt { case GL_RGB: case GL_RGB8: +#if GL_VERSION_1_3 intformat = GL_COMPRESSED_RGB; +#endif break; case GL_SRGB: case GL_SRGB8: +#if GL_VERSION_2_1 intformat = GL_COMPRESSED_SRGB; +#endif break; case GL_RGBA: case GL_RGBA8: +#if GL_VERSION_1_3 intformat = GL_COMPRESSED_RGBA; +#endif break; - case GL_SRGB_ALPHA: case GL_SRGB8_ALPHA8: +#if GL_VERSION_2_1 + case GL_SRGB_ALPHA: intformat = GL_COMPRESSED_SRGB_ALPHA; +#endif break; case GL_LUMINANCE: +#if GL_VERSION_1_1 case GL_LUMINANCE8: +#endif +#if GL_VERSION_1_3 intformat = GL_COMPRESSED_LUMINANCE; +#endif break; case GL_LUMINANCE_ALPHA: +#if GL_VERSION_1_1 case GL_LUMINANCE8_ALPHA8: +#endif +#if GL_VERSION_1_3 intformat = GL_COMPRESSED_LUMINANCE_ALPHA; +#endif break; case GL_ALPHA: +#if GL_VERSION_1_1 case GL_ALPHA8: +#endif +#if GL_VERSION_1_3 intformat = GL_COMPRESSED_ALPHA; +#endif break; case GL_RED: case GL_R8: +#if GL_VERSION_3_0 intformat = GL_COMPRESSED_RED; +#endif break; default: LL_WARNS() << "Could not compress format: " << std::hex << intformat << LL_ENDL; @@ -1606,13 +1679,21 @@ bool LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S { case 1: // Use luminance alpha (for fonts) +#if GL_VERSION_1_1 mFormatInternal = GL_LUMINANCE8; +#else + mFormatInternal = GL_LUMINANCE; +#endif mFormatPrimary = GL_LUMINANCE; mFormatType = GL_UNSIGNED_BYTE; break; case 2: // Use luminance alpha (for fonts) +#if GL_VERSION_1_1 mFormatInternal = GL_LUMINANCE8_ALPHA8; +#else + mFormatInternal = GL_LUMINANCE_ALPHA; +#endif mFormatPrimary = GL_LUMINANCE_ALPHA; mFormatType = GL_UNSIGNED_BYTE; break; @@ -1896,6 +1977,7 @@ bool LLImageGL::readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compre LLImageDataLock lock(imageraw); +#if GL_VERSION_1_3 if (is_compressed) { LLGLint glbytes; @@ -1922,6 +2004,7 @@ bool LLImageGL::readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compre glGetTexImage(GL_TEXTURE_2D, gl_discard, mFormatPrimary, mFormatType, (GLvoid*)(imageraw->getData())); //stop_glerror(); } +#endif // GL_VERSION_1_3 //----------------------------------------------------------------------------------------------- if((error = glGetError()) != GL_NO_ERROR) @@ -2010,11 +2093,13 @@ bool LLImageGL::getIsResident(bool test_now) { if (test_now) { +#if GL_VERSION_1_1 if (mTexName != 0) { glAreTexturesResident(1, (GLuint*)&mTexName, &mIsResident); } else +#endif { mIsResident = false; } @@ -2144,12 +2229,16 @@ void LLImageGL::calcAlphaChannelOffsetAndStride() mIsMask = false; return; //no alpha channel. case GL_RGBA: +#if GL_VERSION_2_1 case GL_SRGB_ALPHA: +#endif mAlphaStride = 4; break; +#if GL_EXT_bgra case GL_BGRA_EXT: mAlphaStride = 4; break; +#endif default: break; } @@ -2159,6 +2248,7 @@ void LLImageGL::calcAlphaChannelOffsetAndStride() { mAlphaOffset = mAlphaStride - 1 ; } +#if GL_VERSION_1_2 else if(is_little_endian()) { if (mFormatType == GL_UNSIGNED_INT_8_8_8_8) @@ -2181,10 +2271,15 @@ void LLImageGL::calcAlphaChannelOffsetAndStride() mAlphaOffset = 0 ; } } +#endif // GL_VERSION_1_2 if( mAlphaStride < 1 || //unsupported format - mAlphaOffset < 0 || //unsupported type - (mFormatPrimary == GL_BGRA_EXT && mFormatType != GL_UNSIGNED_BYTE)) //unknown situation + mAlphaOffset < 0 //unsupported type +#if GL_EXT_bgra + || + (mFormatPrimary == GL_BGRA_EXT && mFormatType != GL_UNSIGNED_BYTE) //unknown situation +#endif + ) { LL_WARNS() << "Cannot analyze alpha for image with format type " << std::hex << mFormatType << std::dec << LL_ENDL; @@ -2330,6 +2425,8 @@ bool LLImageGL::isCompressed() bool is_compressed = false; switch (mFormatPrimary) { +#if GL_EXT_texture_compression_s3tc || GL_EXT_texture_compression_dxt1 \ + || GL_EXT_texture_sRGB || GL_EXT_texture_compression_s3tc_srgb case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: @@ -2338,6 +2435,7 @@ bool LLImageGL::isCompressed() case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: is_compressed = true; break; +#endif default: break; } @@ -2356,7 +2454,10 @@ void LLImageGL::updatePickMask(S32 width, S32 height, const U8* data_in) if (mFormatType != GL_UNSIGNED_BYTE || ((mFormatPrimary != GL_RGBA) - && (mFormatPrimary != GL_SRGB_ALPHA))) +#if GL_VERSION_2_1 + && (mFormatPrimary != GL_SRGB_ALPHA) +#endif + )) { //cannot generate a pick mask for this texture return; diff --git a/indra/llrender/llpostprocess.cpp b/indra/llrender/llpostprocess.cpp index 8ebd09f20d..29ec1408d5 100644 --- a/indra/llrender/llpostprocess.cpp +++ b/indra/llrender/llpostprocess.cpp @@ -296,8 +296,10 @@ void LLPostProcess::getShaderUniforms(glslUniforms & uniforms, GLuint & prog) void LLPostProcess::doEffects(void) { /// Save GL State +#if GL_VERSION_1_1 glPushAttrib(GL_ALL_ATTRIB_BITS); glPushClientAttrib(GL_ALL_ATTRIB_BITS); +#endif /// Copy the screen buffer to the render texture { @@ -322,15 +324,19 @@ void LLPostProcess::doEffects(void) viewPerspective(); /// Reset GL State +#if GL_VERSION_1_1 glPopClientAttrib(); glPopAttrib(); +#endif checkError(); } void LLPostProcess::copyFrameBuffer(U32 & texture, unsigned int width, unsigned int height) { gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, texture); +#if GL_VERSION_3_1 glCopyTexImage2D(GL_TEXTURE_RECTANGLE, 0, GL_RGBA, 0, 0, width, height, 0); +#endif } void LLPostProcess::drawOrthoQuad(unsigned int width, unsigned int height, QuadType type) @@ -371,8 +377,10 @@ void LLPostProcess::createTexture(LLPointer<LLImageGL>& texture, unsigned int wi if(texture->createGLTexture()) { gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, texture->getTexName()); +#if GL_VERSION_3_1 glTexImage2D(GL_TEXTURE_RECTANGLE, 0, 4, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, &data[0]); +#endif gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR); gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); } @@ -406,18 +414,22 @@ bool LLPostProcess::checkError(void) while (glErr != GL_NO_ERROR) { // shaderErrorLog << (const char *) gluErrorString(glErr) << std::endl; +#if GLU_VERSION_1_1 char const * err_str_raw = (const char *) gluErrorString(glErr); if(err_str_raw == NULL) { +#endif std::ostringstream err_builder; err_builder << "unknown error number " << glErr; mShaderErrorString = err_builder.str(); +#if GLU_VERSION_1_1 } else { mShaderErrorString = err_str_raw; } +#endif retCode = true; glErr = glGetError(); diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index a0209fab43..633a453ab0 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -50,6 +50,8 @@ extern void APIENTRY gl_debug_callback(GLenum source, thread_local LLRender gGL; +const U32 BATCH_SIZE = 16334; + // Handy copies of last good GL matrices F32 gGLModelView[16]; F32 gGLLastModelView[16]; @@ -66,7 +68,7 @@ S32 gGLViewport[4]; U32 LLRender::sUICalls = 0; U32 LLRender::sUIVerts = 0; U32 LLTexUnit::sWhiteTexture = 0; -bool LLRender::sGLCoreProfile = false; +bool LLRender::sGLCoreProfile = true; bool LLRender::sNsightDebugSupport = false; LLVector2 LLRender::sUIGLScaleFactor = LLVector2(1.f, 1.f); @@ -81,10 +83,16 @@ static std::unordered_map<U64, LLVBCache> sVBCache; static const GLenum sGLTextureType[] = { GL_TEXTURE_2D, +#if GL_VERSION_3_1 GL_TEXTURE_RECTANGLE, +#endif GL_TEXTURE_CUBE_MAP, +#if GL_VERSION_4_0 GL_TEXTURE_CUBE_MAP_ARRAY, +#endif +#if GL_VERSION_3_2 GL_TEXTURE_2D_MULTISAMPLE, +#endif GL_TEXTURE_3D }; @@ -522,17 +530,18 @@ void LLTexUnit::setTextureFilteringOption(LLTexUnit::eTextureFilterOptions optio { if (LLImageGL::sGlobalUseAnisotropic && option == TFO_ANISOTROPIC) { - glTexParameterf(sGLTextureType[mCurrTexType], GL_TEXTURE_MAX_ANISOTROPY, gGLManager.mMaxAnisotropy); + glTexParameterf(sGLTextureType[mCurrTexType], GL_TEXTURE_MAX_ANISOTROPY_EXT, gGLManager.mMaxAnisotropy); } else { - glTexParameterf(sGLTextureType[mCurrTexType], GL_TEXTURE_MAX_ANISOTROPY, 1.f); + glTexParameterf(sGLTextureType[mCurrTexType], GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.f); } } } GLint LLTexUnit::getTextureSource(eTextureBlendSrc src) { +#if GL_VERSION_1_3 switch(src) { // All four cases should return the same value. @@ -547,8 +556,10 @@ GLint LLTexUnit::getTextureSource(eTextureBlendSrc src) case TBS_TEX_ALPHA: case TBS_ONE_MINUS_TEX_COLOR: case TBS_ONE_MINUS_TEX_ALPHA: +#endif return GL_TEXTURE; +#if GL_VERSION_1_3 // All four cases should return the same value. case TBS_VERT_COLOR: case TBS_VERT_ALPHA: @@ -567,6 +578,7 @@ GLint LLTexUnit::getTextureSource(eTextureBlendSrc src) LL_WARNS() << "Unknown eTextureBlendSrc: " << src << ". Using Vertex Color instead." << LL_ENDL; return GL_PRIMARY_COLOR; } +#endif } GLint LLTexUnit::getTextureSourceType(eTextureBlendSrc src, bool isAlpha) @@ -613,7 +625,9 @@ void LLTexUnit::setColorScale(S32 scale) { mCurrColorScale = scale; gGL.flush(); +#if GL_VERSION_1_1 glTexEnvi( GL_TEXTURE_ENV, GL_RGB_SCALE, scale ); +#endif } } @@ -623,7 +637,9 @@ void LLTexUnit::setAlphaScale(S32 scale) { mCurrAlphaScale = scale; gGL.flush(); +#if GL_VERSION_1_1 glTexEnvi( GL_TEXTURE_ENV, GL_ALPHA_SCALE, scale ); +#endif } } @@ -877,7 +893,9 @@ bool LLRender::init(bool needs_vertex_buffer) glCullFace(GL_BACK); // necessary for reflection maps +#if GL_VERSION_3_2 glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS); +#endif #if LL_WINDOWS if (glGenVertexArrays == nullptr) @@ -904,7 +922,7 @@ void LLRender::initVertexBuffer() llassert_always(mBuffer.isNull()); stop_glerror(); mBuffer = new LLVertexBuffer(immediate_mask); - mBuffer->allocateBuffer(4096, 0); + mBuffer->allocateBuffer(BATCH_SIZE, 0); mBuffer->getVertexStrider(mVerticesp); mBuffer->getTexCoord0Strider(mTexcoordsp); mBuffer->getColorStrider(mColorsp); @@ -1319,9 +1337,8 @@ void LLRender::translateUI(F32 x, F32 y, F32 z) LL_ERRS() << "Need to push a UI translation frame before offsetting" << LL_ENDL; } - mUIOffset.back().mV[0] += x; - mUIOffset.back().mV[1] += y; - mUIOffset.back().mV[2] += z; + LLVector4a add(x,y,z); + mUIOffset.back().add(add); } void LLRender::scaleUI(F32 x, F32 y, F32 z) @@ -1331,14 +1348,15 @@ void LLRender::scaleUI(F32 x, F32 y, F32 z) LL_ERRS() << "Need to push a UI transformation frame before scaling." << LL_ENDL; } - mUIScale.back().scaleVec(LLVector3(x,y,z)); + LLVector4a scale(x,y,z); + mUIScale.back().mul(scale); } void LLRender::pushUIMatrix() { if (mUIOffset.empty()) { - mUIOffset.push_back(LLVector3(0,0,0)); + mUIOffset.emplace_back(LLVector4a::getZero()); } else { @@ -1347,7 +1365,7 @@ void LLRender::pushUIMatrix() if (mUIScale.empty()) { - mUIScale.push_back(LLVector3(1,1,1)); + mUIScale.emplace_back(LLVector4a(1.f)); } else { @@ -1371,7 +1389,7 @@ LLVector3 LLRender::getUITranslation() { return LLVector3(0,0,0); } - return mUIOffset.back(); + return LLVector3(mUIOffset.back().getF32ptr()); } LLVector3 LLRender::getUIScale() @@ -1380,18 +1398,17 @@ LLVector3 LLRender::getUIScale() { return LLVector3(1,1,1); } - return mUIScale.back(); + return LLVector3(mUIScale.back().getF32ptr()); } - void LLRender::loadUIIdentity() { if (mUIOffset.empty()) { LL_ERRS() << "Need to push UI translation frame before clearing offset." << LL_ENDL; } - mUIOffset.back().setVec(0,0,0); - mUIScale.back().setVec(1,1,1); + mUIOffset.back().splat(0.f); + mUIScale.back().splat(1.f); } void LLRender::setColorMask(bool writeColor, bool writeAlpha) @@ -1580,7 +1597,7 @@ void LLRender::end() mMode != LLRender::LINES && mMode != LLRender::TRIANGLES && mMode != LLRender::POINTS) || - mCount > 2048) + mCount > (BATCH_SIZE / 2)) { flush(); } @@ -1601,28 +1618,28 @@ void LLRender::flush() //store mCount in a local variable to avoid re-entrance (drawArrays may call flush) U32 count = mCount; - if (mMode == LLRender::QUADS && !sGLCoreProfile) + if (mMode == LLRender::QUADS && !sGLCoreProfile) + { + if (mCount%4 != 0) { - if (mCount%4 != 0) - { count -= (mCount % 4); LL_WARNS() << "Incomplete quad requested." << LL_ENDL; - } } + } - if (mMode == LLRender::TRIANGLES) + if (mMode == LLRender::TRIANGLES) + { + if (mCount%3 != 0) { - if (mCount%3 != 0) - { count -= (mCount % 3); LL_WARNS() << "Incomplete triangle requested." << LL_ENDL; - } } + } - if (mMode == LLRender::LINES) + if (mMode == LLRender::LINES) + { + if (mCount%2 != 0) { - if (mCount%2 != 0) - { count -= (mCount % 2); LL_WARNS() << "Incomplete line requested." << LL_ENDL; } @@ -1684,7 +1701,7 @@ void LLRender::flush() vb->setBuffer(); - vb->setPositionData((LLVector4a*) mVerticesp.get()); + vb->setPositionData(mVerticesp.get()); if (attribute_mask & LLVertexBuffer::MAP_TEXCOORD0) { @@ -1696,9 +1713,12 @@ void LLRender::flush() vb->setColorData(mColorsp.get()); } -#if LL_DARWIN - vb->unmapBuffer(); -#endif + //LL_INFOS() << "LLVertexBuffer::sMappingMode " << LLVertexBuffer::sMappingMode << LL_ENDL; + if(LLVertexBuffer::sMappingMode == 3) + { + vb->unmapBuffer(); + } + vb->unbind(); sVBCache[vhash] = { vb , std::chrono::steady_clock::now() }; @@ -1754,10 +1774,10 @@ void LLRender::flush() } } -void LLRender::vertex3f(const GLfloat& x, const GLfloat& y, const GLfloat& z) +void LLRender::vertex4a(const LLVector4a& vertex) { //the range of mVerticesp, mColorsp and mTexcoordsp is [0, 4095] - if (mCount > 2048) + if (mCount > BATCH_SIZE / 2) { //break when buffer gets reasonably full to keep GL command buffers happy and avoid overflow below switch (mMode) { @@ -1768,20 +1788,20 @@ void LLRender::vertex3f(const GLfloat& x, const GLfloat& y, const GLfloat& z) } } - if (mCount > 4094) + if (mCount > BATCH_SIZE - 2) { - // LL_WARNS() << "GL immediate mode overflow. Some geometry not drawn." << LL_ENDL; + LL_WARNS() << "GL immediate mode overflow. Some geometry not drawn." << LL_ENDL; return; } if (mUIOffset.empty()) { - mVerticesp[mCount] = LLVector3(x,y,z); + mVerticesp[mCount] = vertex; } else { - LLVector3 vert = (LLVector3(x,y,z)+mUIOffset.back()).scaledVec(mUIScale.back()); - mVerticesp[mCount] = vert; + mVerticesp[mCount].setAdd(vertex, mUIOffset.back()); + mVerticesp[mCount].mul(mUIScale.back()); } if (mMode == LLRender::QUADS && LLRender::sGLCoreProfile) @@ -1809,9 +1829,9 @@ void LLRender::vertex3f(const GLfloat& x, const GLfloat& y, const GLfloat& z) mTexcoordsp[mCount] = mTexcoordsp[mCount-1]; } -void LLRender::vertexBatchPreTransformed(LLVector3* verts, S32 vert_count) +void LLRender::vertexBatchPreTransformed(LLVector4a* verts, S32 vert_count) { - if (mCount + vert_count > 4094) + if (mCount + vert_count > BATCH_SIZE - 2) { // LL_WARNS() << "GL immediate mode overflow. Some geometry not drawn." << LL_ENDL; return; @@ -1867,9 +1887,9 @@ void LLRender::vertexBatchPreTransformed(LLVector3* verts, S32 vert_count) mVerticesp[mCount] = mVerticesp[mCount-1]; } -void LLRender::vertexBatchPreTransformed(LLVector3* verts, LLVector2* uvs, S32 vert_count) +void LLRender::vertexBatchPreTransformed(LLVector4a* verts, LLVector2* uvs, S32 vert_count) { - if (mCount + vert_count > 4094) + if (mCount + vert_count > BATCH_SIZE - 2) { // LL_WARNS() << "GL immediate mode overflow. Some geometry not drawn." << LL_ENDL; return; @@ -1928,9 +1948,9 @@ void LLRender::vertexBatchPreTransformed(LLVector3* verts, LLVector2* uvs, S32 v } } -void LLRender::vertexBatchPreTransformed(LLVector3* verts, LLVector2* uvs, LLColor4U* colors, S32 vert_count) +void LLRender::vertexBatchPreTransformed(LLVector4a* verts, LLVector2* uvs, LLColor4U* colors, S32 vert_count) { - if (mCount + vert_count > 4094) + if (mCount + vert_count > BATCH_SIZE - 2) { // LL_WARNS() << "GL immediate mode overflow. Some geometry not drawn." << LL_ENDL; return; @@ -1991,25 +2011,6 @@ void LLRender::vertexBatchPreTransformed(LLVector3* verts, LLVector2* uvs, LLCol } } -void LLRender::vertex2i(const GLint& x, const GLint& y) -{ - vertex3f((GLfloat) x, (GLfloat) y, 0); -} - -void LLRender::vertex2f(const GLfloat& x, const GLfloat& y) -{ - vertex3f(x,y,0); -} - -void LLRender::vertex2fv(const GLfloat* v) -{ - vertex3f(v[0], v[1], 0); -} - -void LLRender::vertex3fv(const GLfloat* v) -{ - vertex3f(v[0], v[1], v[2]); -} void LLRender::texCoord2f(const GLfloat& x, const GLfloat& y) { diff --git a/indra/llrender/llrender.h b/indra/llrender/llrender.h index be9f3895e7..5852201c94 100644 --- a/indra/llrender/llrender.h +++ b/indra/llrender/llrender.h @@ -34,6 +34,7 @@ //#include "linden_common.h" +#include <array> #include "v2math.h" #include "v3math.h" #include "v4coloru.h" @@ -415,11 +416,15 @@ public: void begin(const GLuint& mode); void end(); - void vertex2i(const GLint& x, const GLint& y); - void vertex2f(const GLfloat& x, const GLfloat& y); - void vertex3f(const GLfloat& x, const GLfloat& y, const GLfloat& z); - void vertex2fv(const GLfloat* v); - void vertex3fv(const GLfloat* v); + + LL_FORCE_INLINE void vertex2i(const GLint& x, const GLint& y) { vertex4a(LLVector4a((GLfloat)x,(GLfloat)y,0.f)); } + LL_FORCE_INLINE void vertex2f(const GLfloat& x, const GLfloat& y) { vertex4a(LLVector4a(x,y,0.f)); } + LL_FORCE_INLINE void vertex3f(const GLfloat& x, const GLfloat& y, const GLfloat& z) { vertex4a(LLVector4a(x,y,z)); } + LL_FORCE_INLINE void vertex2fv(const GLfloat* v) { vertex4a(LLVector4a(v[0],v[1],0.f)); } + LL_FORCE_INLINE void vertex3fv(const GLfloat* v) { vertex4a(LLVector4a(v[0],v[1],v[2])); } + + void vertex4a(const LLVector4a& v); + void texCoord2i(const GLint& x, const GLint& y); void texCoord2f(const GLfloat& x, const GLfloat& y); @@ -439,9 +444,9 @@ public: void diffuseColor4ubv(const U8* c); void diffuseColor4ub(U8 r, U8 g, U8 b, U8 a); - void vertexBatchPreTransformed(LLVector3* verts, S32 vert_count); - void vertexBatchPreTransformed(LLVector3* verts, LLVector2* uvs, S32 vert_count); - void vertexBatchPreTransformed(LLVector3* verts, LLVector2* uvs, LLColor4U*, S32 vert_count); + void vertexBatchPreTransformed(LLVector4a* verts, S32 vert_count); + void vertexBatchPreTransformed(LLVector4a* verts, LLVector2* uvs, S32 vert_count); + void vertexBatchPreTransformed(LLVector4a* verts, LLVector2* uvs, LLColor4U*, S32 vert_count); void setColorMask(bool writeColor, bool writeAlpha); void setColorMask(bool writeColorR, bool writeColorG, bool writeColorB, bool writeAlpha); @@ -480,6 +485,8 @@ public: static bool sNsightDebugSupport; static LLVector2 sUIGLScaleFactor; + //static U32 sMappingMode; + private: friend class LLLightState; @@ -499,7 +506,7 @@ private: bool mCurrColorMask[4]; LLPointer<LLVertexBuffer> mBuffer; - LLStrider<LLVector3> mVerticesp; + LLStrider<LLVector4a> mVerticesp; LLStrider<LLVector2> mTexcoordsp; LLStrider<LLColor4U> mColorsp; std::array<LLTexUnit, LL_NUM_TEXTURE_LAYERS> mTexUnits; @@ -511,8 +518,8 @@ private: eBlendFactor mCurrBlendAlphaSFactor; eBlendFactor mCurrBlendAlphaDFactor; - std::vector<LLVector3> mUIOffset; - std::vector<LLVector3> mUIScale; + std::vector<LLVector4a> mUIOffset; + std::vector<LLVector4a> mUIScale; }; diff --git a/indra/llrender/llrender2dutils.cpp b/indra/llrender/llrender2dutils.cpp index ef02fbd071..97e9875afb 100644 --- a/indra/llrender/llrender2dutils.cpp +++ b/indra/llrender/llrender2dutils.cpp @@ -119,14 +119,18 @@ void gl_rect_2d(S32 left, S32 top, S32 right, S32 bottom, bool filled ) { gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - // Counterclockwise quad will face the viewer if( filled ) { - gGL.begin( LLRender::QUADS ); + gGL.begin( LLRender::TRIANGLES ); + { gGL.vertex2i(left, top); gGL.vertex2i(left, bottom); gGL.vertex2i(right, bottom); + + gGL.vertex2i(left, top); + gGL.vertex2i(right, bottom); gGL.vertex2i(right, top); + } gGL.end(); } else @@ -171,51 +175,73 @@ void gl_drop_shadow(S32 left, S32 top, S32 right, S32 bottom, const LLColor4 &st LLColor4 end_color = start_color; end_color.mV[VALPHA] = 0.f; + gGL.begin(LLRender::TRIANGLES); - gGL.begin(LLRender::QUADS); - - // Right edge, CCW faces screen + // Right edge + gGL.color4fv(start_color.mV); + gGL.vertex2i(right, top-lines); + gGL.vertex2i(right, bottom); + gGL.color4fv(end_color.mV); + gGL.vertex2i(right+lines, bottom); gGL.color4fv(start_color.mV); - gGL.vertex2i(right, top-lines); - gGL.vertex2i(right, bottom); + gGL.vertex2i(right, top-lines); gGL.color4fv(end_color.mV); gGL.vertex2i(right+lines, bottom); gGL.vertex2i(right+lines, top-lines); - // Bottom edge, CCW faces screen + // Bottom edge gGL.color4fv(start_color.mV); - gGL.vertex2i(right, bottom); - gGL.vertex2i(left+lines, bottom); + gGL.vertex2i(right, bottom); + gGL.vertex2i(left+lines, bottom); + gGL.color4fv(end_color.mV); + gGL.vertex2i(left+lines, bottom-lines); + gGL.color4fv(start_color.mV); + gGL.vertex2i(right, bottom); gGL.color4fv(end_color.mV); - gGL.vertex2i(left+lines, bottom-lines); - gGL.vertex2i(right, bottom-lines); + gGL.vertex2i(left+lines, bottom-lines); + gGL.vertex2i(right, bottom-lines); // bottom left Corner gGL.color4fv(start_color.mV); - gGL.vertex2i(left+lines, bottom); + gGL.vertex2i(left+lines, bottom); + gGL.color4fv(end_color.mV); + gGL.vertex2i(left, bottom); + + // bottom left corner + gGL.vertex2i(left+1, bottom-lines+1); + gGL.color4fv(start_color.mV); + gGL.vertex2i(left+lines, bottom); gGL.color4fv(end_color.mV); - gGL.vertex2i(left, bottom); - // make the bottom left corner not sharp - gGL.vertex2i(left+1, bottom-lines+1); - gGL.vertex2i(left+lines, bottom-lines); + gGL.vertex2i(left+1, bottom-lines+1); + gGL.vertex2i(left+lines, bottom-lines); // bottom right corner gGL.color4fv(start_color.mV); - gGL.vertex2i(right, bottom); + gGL.vertex2i(right, bottom); gGL.color4fv(end_color.mV); - gGL.vertex2i(right, bottom-lines); + gGL.vertex2i(right, bottom-lines); + // make the rightmost corner not sharp gGL.vertex2i(right+lines-1, bottom-lines+1); - gGL.vertex2i(right+lines, bottom); + gGL.color4fv(start_color.mV); + gGL.vertex2i(right, bottom); + gGL.color4fv(end_color.mV); + gGL.vertex2i(right+lines-1, bottom-lines+1); + gGL.vertex2i(right+lines, bottom); // top right corner gGL.color4fv(start_color.mV); - gGL.vertex2i( right, top-lines ); + gGL.vertex2i( right, top-lines ); gGL.color4fv(end_color.mV); - gGL.vertex2i( right+lines, top-lines ); + gGL.vertex2i( right+lines, top-lines ); + // make the corner not sharp - gGL.vertex2i( right+lines-1, top-1 ); - gGL.vertex2i( right, top ); + gGL.vertex2i( right+lines-1, top-1 ); + gGL.color4fv(start_color.mV); + gGL.vertex2i( right, top-lines ); + gGL.color4fv(end_color.mV); + gGL.vertex2i( right+lines-1, top-1 ); + gGL.vertex2i( right, top ); gGL.end(); stop_glerror(); @@ -429,165 +455,237 @@ void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 width, S32 height, LLTex gGL.color4fv(color.mV); - const S32 NUM_VERTICES = 9 * 4; // 9 quads + const S32 NUM_VERTICES = 9 * 6; LLVector2 uv[NUM_VERTICES]; - LLVector3 pos[NUM_VERTICES]; + LLVector4a pos[NUM_VERTICES]; S32 index = 0; - gGL.begin(LLRender::QUADS); + gGL.begin(LLRender::TRIANGLES); { // draw bottom left uv[index] = LLVector2(uv_outer_rect.mLeft, uv_outer_rect.mBottom); - pos[index] = LLVector3(draw_outer_rect.mLeft, draw_outer_rect.mBottom, 0.f); + pos[index] = LLVector4a(draw_outer_rect.mLeft, draw_outer_rect.mBottom, 0.f); index++; uv[index] = LLVector2(uv_center_rect.mLeft, uv_outer_rect.mBottom); - pos[index] = LLVector3(draw_center_rect.mLeft, draw_outer_rect.mBottom, 0.f); + pos[index] = LLVector4a(draw_center_rect.mLeft, draw_outer_rect.mBottom, 0.f); + index++; + + uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mBottom); + pos[index] = LLVector4a(draw_center_rect.mLeft, draw_center_rect.mBottom, 0.f); + index++; + + uv[index] = LLVector2(uv_outer_rect.mLeft, uv_outer_rect.mBottom); + pos[index] = LLVector4a(draw_outer_rect.mLeft, draw_outer_rect.mBottom, 0.f); index++; uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mBottom); - pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mBottom, 0.f); + pos[index] = LLVector4a(draw_center_rect.mLeft, draw_center_rect.mBottom, 0.f); index++; uv[index] = LLVector2(uv_outer_rect.mLeft, uv_center_rect.mBottom); - pos[index] = LLVector3(draw_outer_rect.mLeft, draw_center_rect.mBottom, 0.f); + pos[index] = LLVector4a(draw_outer_rect.mLeft, draw_center_rect.mBottom, 0.f); index++; // draw bottom middle uv[index] = LLVector2(uv_center_rect.mLeft, uv_outer_rect.mBottom); - pos[index] = LLVector3(draw_center_rect.mLeft, draw_outer_rect.mBottom, 0.f); + pos[index] = LLVector4a(draw_center_rect.mLeft, draw_outer_rect.mBottom, 0.f); index++; uv[index] = LLVector2(uv_center_rect.mRight, uv_outer_rect.mBottom); - pos[index] = LLVector3(draw_center_rect.mRight, draw_outer_rect.mBottom, 0.f); + pos[index] = LLVector4a(draw_center_rect.mRight, draw_outer_rect.mBottom, 0.f); index++; uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mBottom); - pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mBottom, 0.f); + pos[index] = LLVector4a(draw_center_rect.mRight, draw_center_rect.mBottom, 0.f); + index++; + + uv[index] = LLVector2(uv_center_rect.mLeft, uv_outer_rect.mBottom); + pos[index] = LLVector4a(draw_center_rect.mLeft, draw_outer_rect.mBottom, 0.f); + index++; + + uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mBottom); + pos[index] = LLVector4a(draw_center_rect.mRight, draw_center_rect.mBottom, 0.f); index++; uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mBottom); - pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mBottom, 0.f); + pos[index] = LLVector4a(draw_center_rect.mLeft, draw_center_rect.mBottom, 0.f); index++; // draw bottom right uv[index] = LLVector2(uv_center_rect.mRight, uv_outer_rect.mBottom); - pos[index] = LLVector3(draw_center_rect.mRight, draw_outer_rect.mBottom, 0.f); + pos[index] = LLVector4a(draw_center_rect.mRight, draw_outer_rect.mBottom, 0.f); index++; uv[index] = LLVector2(uv_outer_rect.mRight, uv_outer_rect.mBottom); - pos[index] = LLVector3(draw_outer_rect.mRight, draw_outer_rect.mBottom, 0.f); + pos[index] = LLVector4a(draw_outer_rect.mRight, draw_outer_rect.mBottom, 0.f); index++; uv[index] = LLVector2(uv_outer_rect.mRight, uv_center_rect.mBottom); - pos[index] = LLVector3(draw_outer_rect.mRight, draw_center_rect.mBottom, 0.f); + pos[index] = LLVector4a(draw_outer_rect.mRight, draw_center_rect.mBottom, 0.f); + index++; + + uv[index] = LLVector2(uv_center_rect.mRight, uv_outer_rect.mBottom); + pos[index] = LLVector4a(draw_center_rect.mRight, draw_outer_rect.mBottom, 0.f); + index++; + + uv[index] = LLVector2(uv_outer_rect.mRight, uv_center_rect.mBottom); + pos[index] = LLVector4a(draw_outer_rect.mRight, draw_center_rect.mBottom, 0.f); index++; uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mBottom); - pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mBottom, 0.f); + pos[index] = LLVector4a(draw_center_rect.mRight, draw_center_rect.mBottom, 0.f); index++; // draw left uv[index] = LLVector2(uv_outer_rect.mLeft, uv_center_rect.mBottom); - pos[index] = LLVector3(draw_outer_rect.mLeft, draw_center_rect.mBottom, 0.f); + pos[index] = LLVector4a(draw_outer_rect.mLeft, draw_center_rect.mBottom, 0.f); index++; uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mBottom); - pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mBottom, 0.f); + pos[index] = LLVector4a(draw_center_rect.mLeft, draw_center_rect.mBottom, 0.f); + index++; + + uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mTop); + pos[index] = LLVector4a(draw_center_rect.mLeft, draw_center_rect.mTop, 0.f); + index++; + + uv[index] = LLVector2(uv_outer_rect.mLeft, uv_center_rect.mBottom); + pos[index] = LLVector4a(draw_outer_rect.mLeft, draw_center_rect.mBottom, 0.f); index++; uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mTop); - pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mTop, 0.f); + pos[index] = LLVector4a(draw_center_rect.mLeft, draw_center_rect.mTop, 0.f); index++; uv[index] = LLVector2(uv_outer_rect.mLeft, uv_center_rect.mTop); - pos[index] = LLVector3(draw_outer_rect.mLeft, draw_center_rect.mTop, 0.f); + pos[index] = LLVector4a(draw_outer_rect.mLeft, draw_center_rect.mTop, 0.f); index++; // draw middle uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mBottom); - pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mBottom, 0.f); + pos[index] = LLVector4a(draw_center_rect.mLeft, draw_center_rect.mBottom, 0.f); index++; uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mBottom); - pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mBottom, 0.f); + pos[index] = LLVector4a(draw_center_rect.mRight, draw_center_rect.mBottom, 0.f); index++; uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mTop); - pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mTop, 0.f); + pos[index] = LLVector4a(draw_center_rect.mRight, draw_center_rect.mTop, 0.f); + index++; + + uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mBottom); + pos[index] = LLVector4a(draw_center_rect.mLeft, draw_center_rect.mBottom, 0.f); + index++; + + uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mTop); + pos[index] = LLVector4a(draw_center_rect.mRight, draw_center_rect.mTop, 0.f); index++; uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mTop); - pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mTop, 0.f); + pos[index] = LLVector4a(draw_center_rect.mLeft, draw_center_rect.mTop, 0.f); index++; // draw right uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mBottom); - pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mBottom, 0.f); + pos[index] = LLVector4a(draw_center_rect.mRight, draw_center_rect.mBottom, 0.f); index++; uv[index] = LLVector2(uv_outer_rect.mRight, uv_center_rect.mBottom); - pos[index] = LLVector3(draw_outer_rect.mRight, draw_center_rect.mBottom, 0.f); + pos[index] = LLVector4a(draw_outer_rect.mRight, draw_center_rect.mBottom, 0.f); index++; uv[index] = LLVector2(uv_outer_rect.mRight, uv_center_rect.mTop); - pos[index] = LLVector3(draw_outer_rect.mRight, draw_center_rect.mTop, 0.f); + pos[index] = LLVector4a(draw_outer_rect.mRight, draw_center_rect.mTop, 0.f); + index++; + + uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mBottom); + pos[index] = LLVector4a(draw_center_rect.mRight, draw_center_rect.mBottom, 0.f); + index++; + + uv[index] = LLVector2(uv_outer_rect.mRight, uv_center_rect.mTop); + pos[index] = LLVector4a(draw_outer_rect.mRight, draw_center_rect.mTop, 0.f); index++; uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mTop); - pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mTop, 0.f); + pos[index] = LLVector4a(draw_center_rect.mRight, draw_center_rect.mTop, 0.f); index++; // draw top left uv[index] = LLVector2(uv_outer_rect.mLeft, uv_center_rect.mTop); - pos[index] = LLVector3(draw_outer_rect.mLeft, draw_center_rect.mTop, 0.f); + pos[index] = LLVector4a(draw_outer_rect.mLeft, draw_center_rect.mTop, 0.f); index++; uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mTop); - pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mTop, 0.f); + pos[index] = LLVector4a(draw_center_rect.mLeft, draw_center_rect.mTop, 0.f); index++; uv[index] = LLVector2(uv_center_rect.mLeft, uv_outer_rect.mTop); - pos[index] = LLVector3(draw_center_rect.mLeft, draw_outer_rect.mTop, 0.f); + pos[index] = LLVector4a(draw_center_rect.mLeft, draw_outer_rect.mTop, 0.f); + index++; + + uv[index] = LLVector2(uv_outer_rect.mLeft, uv_center_rect.mTop); + pos[index] = LLVector4a(draw_outer_rect.mLeft, draw_center_rect.mTop, 0.f); + index++; + + uv[index] = LLVector2(uv_center_rect.mLeft, uv_outer_rect.mTop); + pos[index] = LLVector4a(draw_center_rect.mLeft, draw_outer_rect.mTop, 0.f); index++; uv[index] = LLVector2(uv_outer_rect.mLeft, uv_outer_rect.mTop); - pos[index] = LLVector3(draw_outer_rect.mLeft, draw_outer_rect.mTop, 0.f); + pos[index] = LLVector4a(draw_outer_rect.mLeft, draw_outer_rect.mTop, 0.f); index++; // draw top middle uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mTop); - pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mTop, 0.f); + pos[index] = LLVector4a(draw_center_rect.mLeft, draw_center_rect.mTop, 0.f); index++; uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mTop); - pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mTop, 0.f); + pos[index] = LLVector4a(draw_center_rect.mRight, draw_center_rect.mTop, 0.f); index++; uv[index] = LLVector2(uv_center_rect.mRight, uv_outer_rect.mTop); - pos[index] = LLVector3(draw_center_rect.mRight, draw_outer_rect.mTop, 0.f); + pos[index] = LLVector4a(draw_center_rect.mRight, draw_outer_rect.mTop, 0.f); + index++; + + uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mTop); + pos[index] = LLVector4a(draw_center_rect.mLeft, draw_center_rect.mTop, 0.f); + index++; + + uv[index] = LLVector2(uv_center_rect.mRight, uv_outer_rect.mTop); + pos[index] = LLVector4a(draw_center_rect.mRight, draw_outer_rect.mTop, 0.f); index++; uv[index] = LLVector2(uv_center_rect.mLeft, uv_outer_rect.mTop); - pos[index] = LLVector3(draw_center_rect.mLeft, draw_outer_rect.mTop, 0.f); + pos[index] = LLVector4a(draw_center_rect.mLeft, draw_outer_rect.mTop, 0.f); index++; // draw top right uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mTop); - pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mTop, 0.f); + pos[index] = LLVector4a(draw_center_rect.mRight, draw_center_rect.mTop, 0.f); index++; uv[index] = LLVector2(uv_outer_rect.mRight, uv_center_rect.mTop); - pos[index] = LLVector3(draw_outer_rect.mRight, draw_center_rect.mTop, 0.f); + pos[index] = LLVector4a(draw_outer_rect.mRight, draw_center_rect.mTop, 0.f); index++; uv[index] = LLVector2(uv_outer_rect.mRight, uv_outer_rect.mTop); - pos[index] = LLVector3(draw_outer_rect.mRight, draw_outer_rect.mTop, 0.f); + pos[index] = LLVector4a(draw_outer_rect.mRight, draw_outer_rect.mTop, 0.f); + index++; + + uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mTop); + pos[index] = LLVector4a(draw_center_rect.mRight, draw_center_rect.mTop, 0.f); + index++; + + uv[index] = LLVector2(uv_outer_rect.mRight, uv_outer_rect.mTop); + pos[index] = LLVector4a(draw_outer_rect.mRight, draw_outer_rect.mTop, 0.f); index++; uv[index] = LLVector2(uv_center_rect.mRight, uv_outer_rect.mTop); - pos[index] = LLVector3(draw_center_rect.mRight, draw_outer_rect.mTop, 0.f); + pos[index] = LLVector4a(draw_center_rect.mRight, draw_outer_rect.mTop, 0.f); index++; gGL.vertexBatchPreTransformed(pos, uv, NUM_VERTICES); @@ -629,11 +727,11 @@ void gl_draw_scaled_rotated_image(S32 x, S32 y, S32 width, S32 height, F32 degre if (degrees == 0.f) { - const S32 NUM_VERTICES = 4; // 9 quads + const S32 NUM_VERTICES = 6; LLVector2 uv[NUM_VERTICES]; - LLVector3 pos[NUM_VERTICES]; + LLVector4a pos[NUM_VERTICES]; - gGL.begin(LLRender::QUADS); + gGL.begin(LLRender::TRIANGLES); { LLVector3 ui_scale = gGL.getUIScale(); LLVector3 ui_translation = gGL.getUITranslation(); @@ -645,19 +743,27 @@ void gl_draw_scaled_rotated_image(S32 x, S32 y, S32 width, S32 height, F32 degre S32 scaled_height = ll_round(height * ui_scale.mV[VY]); uv[index] = LLVector2(uv_rect.mRight, uv_rect.mTop); - pos[index] = LLVector3(ui_translation.mV[VX] + scaled_width, ui_translation.mV[VY] + scaled_height, 0.f); + pos[index] = LLVector4a(ui_translation.mV[VX] + scaled_width, ui_translation.mV[VY] + scaled_height, 0.f); index++; uv[index] = LLVector2(uv_rect.mLeft, uv_rect.mTop); - pos[index] = LLVector3(ui_translation.mV[VX], ui_translation.mV[VY] + scaled_height, 0.f); + pos[index] = LLVector4a(ui_translation.mV[VX], ui_translation.mV[VY] + scaled_height, 0.f); + index++; + + uv[index] = LLVector2(uv_rect.mLeft, uv_rect.mBottom); + pos[index] = LLVector4a(ui_translation.mV[VX], ui_translation.mV[VY], 0.f); + index++; + + uv[index] = LLVector2(uv_rect.mRight, uv_rect.mTop); + pos[index] = LLVector4a(ui_translation.mV[VX] + scaled_width, ui_translation.mV[VY] + scaled_height, 0.f); index++; uv[index] = LLVector2(uv_rect.mLeft, uv_rect.mBottom); - pos[index] = LLVector3(ui_translation.mV[VX], ui_translation.mV[VY], 0.f); + pos[index] = LLVector4a(ui_translation.mV[VX], ui_translation.mV[VY], 0.f); index++; uv[index] = LLVector2(uv_rect.mRight, uv_rect.mBottom); - pos[index] = LLVector3(ui_translation.mV[VX] + scaled_width, ui_translation.mV[VY], 0.f); + pos[index] = LLVector4a(ui_translation.mV[VX] + scaled_width, ui_translation.mV[VY], 0.f); index++; gGL.vertexBatchPreTransformed(pos, uv, NUM_VERTICES); @@ -687,26 +793,32 @@ void gl_draw_scaled_rotated_image(S32 x, S32 y, S32 width, S32 height, F32 degre gGL.color4fv(color.mV); - gGL.begin(LLRender::QUADS); + gGL.begin(LLRender::TRIANGLES); { - LLVector3 v; + LLVector3 v1 = LLVector3(offset_x, offset_y, 0.f) * quat; + LLVector3 v2 = LLVector3(-offset_x, offset_y, 0.f) * quat; + LLVector3 v3 = LLVector3(-offset_x, -offset_y, 0.f) * quat; + LLVector3 v4 = LLVector3(offset_x, -offset_y, 0.f) * quat; - v = LLVector3(offset_x, offset_y, 0.f) * quat; gGL.texCoord2f(uv_rect.mRight, uv_rect.mTop); - gGL.vertex2f(v.mV[0], v.mV[1] ); + gGL.vertex2f(v1.mV[0], v1.mV[1] ); - v = LLVector3(-offset_x, offset_y, 0.f) * quat; gGL.texCoord2f(uv_rect.mLeft, uv_rect.mTop); - gGL.vertex2f(v.mV[0], v.mV[1] ); + gGL.vertex2f(v2.mV[0], v2.mV[1] ); + + gGL.texCoord2f(uv_rect.mLeft, uv_rect.mBottom); + gGL.vertex2f(v3.mV[0], v3.mV[1] ); + + gGL.texCoord2f(uv_rect.mRight, uv_rect.mTop); + gGL.vertex2f(v1.mV[0], v1.mV[1] ); - v = LLVector3(-offset_x, -offset_y, 0.f) * quat; gGL.texCoord2f(uv_rect.mLeft, uv_rect.mBottom); - gGL.vertex2f(v.mV[0], v.mV[1] ); + gGL.vertex2f(v3.mV[0], v3.mV[1] ); - v = LLVector3(offset_x, -offset_y, 0.f) * quat; gGL.texCoord2f(uv_rect.mRight, uv_rect.mBottom); - gGL.vertex2f(v.mV[0], v.mV[1] ); + gGL.vertex2f(v4.mV[0], v4.mV[1] ); } + gGL.end(); gGL.popUIMatrix(); } @@ -948,8 +1060,8 @@ void gl_washer_segment_2d(F32 outer_radius, F32 inner_radius, F32 start_radians, void gl_rect_2d_simple_tex( S32 width, S32 height ) { - gGL.begin( LLRender::QUADS ); - + gGL.begin( LLRender::TRIANGLES ); + { gGL.texCoord2f(1.f, 1.f); gGL.vertex2i(width, height); @@ -959,19 +1071,30 @@ void gl_rect_2d_simple_tex( S32 width, S32 height ) gGL.texCoord2f(0.f, 0.f); gGL.vertex2i(0, 0); + gGL.texCoord2f(1.f, 1.f); + gGL.vertex2i(width, height); + + gGL.texCoord2f(0.f, 0.f); + gGL.vertex2i(0, 0); + gGL.texCoord2f(1.f, 0.f); gGL.vertex2i(width, 0); - + } gGL.end(); } void gl_rect_2d_simple( S32 width, S32 height ) { - gGL.begin( LLRender::QUADS ); + gGL.begin( LLRender::TRIANGLES ); + { gGL.vertex2i(width, height); gGL.vertex2i(0, height); gGL.vertex2i(0, 0); + + gGL.vertex2i(width, height); + gGL.vertex2i(0, 0); gGL.vertex2i(width, 0); + } gGL.end(); } @@ -1011,7 +1134,7 @@ void gl_segmented_rect_2d_tex(const S32 left, LLVector2 width_vec((F32)width, 0.f); LLVector2 height_vec(0.f, (F32)height); - gGL.begin(LLRender::QUADS); + gGL.begin(LLRender::TRIANGLES); { // draw bottom left gGL.texCoord2f(0.f, 0.f); @@ -1023,6 +1146,12 @@ void gl_segmented_rect_2d_tex(const S32 left, gGL.texCoord2f(border_uv_scale.mV[VX], border_uv_scale.mV[VY]); gGL.vertex2fv((border_width_left + border_height_bottom).mV); + gGL.texCoord2f(0.f, 0.f); + gGL.vertex2f(0.f, 0.f); + + gGL.texCoord2f(border_uv_scale.mV[VX], border_uv_scale.mV[VY]); + gGL.vertex2fv((border_width_left + border_height_bottom).mV); + gGL.texCoord2f(0.f, border_uv_scale.mV[VY]); gGL.vertex2fv(border_height_bottom.mV); @@ -1036,6 +1165,12 @@ void gl_segmented_rect_2d_tex(const S32 left, gGL.texCoord2f(1.f - border_uv_scale.mV[VX], border_uv_scale.mV[VY]); gGL.vertex2fv((width_vec - border_width_right + border_height_bottom).mV); + gGL.texCoord2f(border_uv_scale.mV[VX], 0.f); + gGL.vertex2fv(border_width_left.mV); + + gGL.texCoord2f(1.f - border_uv_scale.mV[VX], border_uv_scale.mV[VY]); + gGL.vertex2fv((width_vec - border_width_right + border_height_bottom).mV); + gGL.texCoord2f(border_uv_scale.mV[VX], border_uv_scale.mV[VY]); gGL.vertex2fv((border_width_left + border_height_bottom).mV); @@ -1049,6 +1184,12 @@ void gl_segmented_rect_2d_tex(const S32 left, gGL.texCoord2f(1.f, border_uv_scale.mV[VY]); gGL.vertex2fv((width_vec + border_height_bottom).mV); + gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 0.f); + gGL.vertex2fv((width_vec - border_width_right).mV); + + gGL.texCoord2f(1.f, border_uv_scale.mV[VY]); + gGL.vertex2fv((width_vec + border_height_bottom).mV); + gGL.texCoord2f(1.f - border_uv_scale.mV[VX], border_uv_scale.mV[VY]); gGL.vertex2fv((width_vec - border_width_right + border_height_bottom).mV); @@ -1062,6 +1203,12 @@ void gl_segmented_rect_2d_tex(const S32 left, gGL.texCoord2f(border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]); gGL.vertex2fv((border_width_left + height_vec - border_height_top).mV); + gGL.texCoord2f(0.f, border_uv_scale.mV[VY]); + gGL.vertex2fv(border_height_bottom.mV); + + gGL.texCoord2f(border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]); + gGL.vertex2fv((border_width_left + height_vec - border_height_top).mV); + gGL.texCoord2f(0.f, 1.f - border_uv_scale.mV[VY]); gGL.vertex2fv((height_vec - border_height_top).mV); @@ -1075,6 +1222,12 @@ void gl_segmented_rect_2d_tex(const S32 left, gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]); gGL.vertex2fv((width_vec - border_width_right + height_vec - border_height_top).mV); + gGL.texCoord2f(border_uv_scale.mV[VX], border_uv_scale.mV[VY]); + gGL.vertex2fv((border_width_left + border_height_bottom).mV); + + gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]); + gGL.vertex2fv((width_vec - border_width_right + height_vec - border_height_top).mV); + gGL.texCoord2f(border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]); gGL.vertex2fv((border_width_left + height_vec - border_height_top).mV); @@ -1088,6 +1241,12 @@ void gl_segmented_rect_2d_tex(const S32 left, gGL.texCoord2f(1.f, 1.f - border_uv_scale.mV[VY]); gGL.vertex2fv((width_vec + height_vec - border_height_top).mV); + gGL.texCoord2f(1.f - border_uv_scale.mV[VX], border_uv_scale.mV[VY]); + gGL.vertex2fv((width_vec - border_width_right + border_height_bottom).mV); + + gGL.texCoord2f(1.f, 1.f - border_uv_scale.mV[VY]); + gGL.vertex2fv((width_vec + height_vec - border_height_top).mV); + gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]); gGL.vertex2fv((width_vec - border_width_right + height_vec - border_height_top).mV); @@ -1101,6 +1260,12 @@ void gl_segmented_rect_2d_tex(const S32 left, gGL.texCoord2f(border_uv_scale.mV[VX], 1.f); gGL.vertex2fv((border_width_left + height_vec).mV); + gGL.texCoord2f(0.f, 1.f - border_uv_scale.mV[VY]); + gGL.vertex2fv((height_vec - border_height_top).mV); + + gGL.texCoord2f(border_uv_scale.mV[VX], 1.f); + gGL.vertex2fv((border_width_left + height_vec).mV); + gGL.texCoord2f(0.f, 1.f); gGL.vertex2fv((height_vec).mV); @@ -1114,6 +1279,12 @@ void gl_segmented_rect_2d_tex(const S32 left, gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f); gGL.vertex2fv((width_vec - border_width_right + height_vec).mV); + gGL.texCoord2f(border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]); + gGL.vertex2fv((border_width_left + height_vec - border_height_top).mV); + + gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f); + gGL.vertex2fv((width_vec - border_width_right + height_vec).mV); + gGL.texCoord2f(border_uv_scale.mV[VX], 1.f); gGL.vertex2fv((border_width_left + height_vec).mV); @@ -1127,6 +1298,12 @@ void gl_segmented_rect_2d_tex(const S32 left, gGL.texCoord2f(1.f, 1.f); gGL.vertex2fv((width_vec + height_vec).mV); + gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]); + gGL.vertex2fv((width_vec - border_width_right + height_vec - border_height_top).mV); + + gGL.texCoord2f(1.f, 1.f); + gGL.vertex2fv((width_vec + height_vec).mV); + gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f); gGL.vertex2fv((width_vec - border_width_right + height_vec).mV); } @@ -1181,7 +1358,7 @@ void gl_segmented_rect_2d_fragment_tex(const LLRect& rect, LLVector2 x_min; LLVector2 x_max; - gGL.begin(LLRender::QUADS); + gGL.begin(LLRender::TRIANGLES); { if (start_fragment < middle_start) { @@ -1200,6 +1377,12 @@ void gl_segmented_rect_2d_fragment_tex(const LLRect& rect, gGL.texCoord2f(u_max, border_uv_scale.mV[VY]); gGL.vertex2fv((x_max + border_height_bottom).mV); + gGL.texCoord2f(u_min, 0.f); + gGL.vertex2fv(x_min.mV); + + gGL.texCoord2f(u_max, border_uv_scale.mV[VY]); + gGL.vertex2fv((x_max + border_height_bottom).mV); + gGL.texCoord2f(u_min, border_uv_scale.mV[VY]); gGL.vertex2fv((x_min + border_height_bottom).mV); @@ -1213,6 +1396,12 @@ void gl_segmented_rect_2d_fragment_tex(const LLRect& rect, gGL.texCoord2f(u_max, 1.f - border_uv_scale.mV[VY]); gGL.vertex2fv((x_max + height_vec - border_height_top).mV); + gGL.texCoord2f(u_min, border_uv_scale.mV[VY]); + gGL.vertex2fv((x_min + border_height_bottom).mV); + + gGL.texCoord2f(u_max, 1.f - border_uv_scale.mV[VY]); + gGL.vertex2fv((x_max + height_vec - border_height_top).mV); + gGL.texCoord2f(u_min, 1.f - border_uv_scale.mV[VY]); gGL.vertex2fv((x_min + height_vec - border_height_top).mV); @@ -1226,6 +1415,12 @@ void gl_segmented_rect_2d_fragment_tex(const LLRect& rect, gGL.texCoord2f(u_max, 1.f); gGL.vertex2fv((x_max + height_vec).mV); + gGL.texCoord2f(u_min, 1.f - border_uv_scale.mV[VY]); + gGL.vertex2fv((x_min + height_vec - border_height_top).mV); + + gGL.texCoord2f(u_max, 1.f); + gGL.vertex2fv((x_max + height_vec).mV); + gGL.texCoord2f(u_min, 1.f); gGL.vertex2fv((x_min + height_vec).mV); } @@ -1245,6 +1440,12 @@ void gl_segmented_rect_2d_fragment_tex(const LLRect& rect, gGL.texCoord2f(1.f - border_uv_scale.mV[VX], border_uv_scale.mV[VY]); gGL.vertex2fv((x_max + border_height_bottom).mV); + gGL.texCoord2f(border_uv_scale.mV[VX], 0.f); + gGL.vertex2fv(x_min.mV); + + gGL.texCoord2f(1.f - border_uv_scale.mV[VX], border_uv_scale.mV[VY]); + gGL.vertex2fv((x_max + border_height_bottom).mV); + gGL.texCoord2f(border_uv_scale.mV[VX], border_uv_scale.mV[VY]); gGL.vertex2fv((x_min + border_height_bottom).mV); @@ -1258,6 +1459,12 @@ void gl_segmented_rect_2d_fragment_tex(const LLRect& rect, gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]); gGL.vertex2fv((x_max + height_vec - border_height_top).mV); + gGL.texCoord2f(border_uv_scale.mV[VX], border_uv_scale.mV[VY]); + gGL.vertex2fv((x_min + border_height_bottom).mV); + + gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]); + gGL.vertex2fv((x_max + height_vec - border_height_top).mV); + gGL.texCoord2f(border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]); gGL.vertex2fv((x_min + height_vec - border_height_top).mV); @@ -1271,6 +1478,12 @@ void gl_segmented_rect_2d_fragment_tex(const LLRect& rect, gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f); gGL.vertex2fv((x_max + height_vec).mV); + gGL.texCoord2f(border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]); + gGL.vertex2fv((x_min + height_vec - border_height_top).mV); + + gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f); + gGL.vertex2fv((x_max + height_vec).mV); + gGL.texCoord2f(border_uv_scale.mV[VX], 1.f); gGL.vertex2fv((x_min + height_vec).mV); } @@ -1292,6 +1505,12 @@ void gl_segmented_rect_2d_fragment_tex(const LLRect& rect, gGL.texCoord2f(u_max, border_uv_scale.mV[VY]); gGL.vertex2fv((x_max + border_height_bottom).mV); + gGL.texCoord2f(u_min, 0.f); + gGL.vertex2fv((x_min).mV); + + gGL.texCoord2f(u_max, border_uv_scale.mV[VY]); + gGL.vertex2fv((x_max + border_height_bottom).mV); + gGL.texCoord2f(u_min, border_uv_scale.mV[VY]); gGL.vertex2fv((x_min + border_height_bottom).mV); @@ -1305,6 +1524,12 @@ void gl_segmented_rect_2d_fragment_tex(const LLRect& rect, gGL.texCoord2f(u_max, 1.f - border_uv_scale.mV[VY]); gGL.vertex2fv((x_max + height_vec - border_height_top).mV); + gGL.texCoord2f(u_min, border_uv_scale.mV[VY]); + gGL.vertex2fv((x_min + border_height_bottom).mV); + + gGL.texCoord2f(u_max, 1.f - border_uv_scale.mV[VY]); + gGL.vertex2fv((x_max + height_vec - border_height_top).mV); + gGL.texCoord2f(u_min, 1.f - border_uv_scale.mV[VY]); gGL.vertex2fv((x_min + height_vec - border_height_top).mV); @@ -1318,6 +1543,12 @@ void gl_segmented_rect_2d_fragment_tex(const LLRect& rect, gGL.texCoord2f(u_max, 1.f); gGL.vertex2fv((x_max + height_vec).mV); + gGL.texCoord2f(u_min, 1.f - border_uv_scale.mV[VY]); + gGL.vertex2fv((x_min + height_vec - border_height_top).mV); + + gGL.texCoord2f(u_max, 1.f); + gGL.vertex2fv((x_max + height_vec).mV); + gGL.texCoord2f(u_min, 1.f); gGL.vertex2fv((x_min + height_vec).mV); } @@ -1332,7 +1563,7 @@ void gl_segmented_rect_3d_tex(const LLRectf& clip_rect, const LLRectf& center_uv { LL_PROFILE_ZONE_SCOPED_CATEGORY_UI; - gGL.begin(LLRender::QUADS); + gGL.begin(LLRender::TRIANGLES); { // draw bottom left gGL.texCoord2f(clip_rect.mLeft, clip_rect.mBottom); @@ -1344,6 +1575,12 @@ void gl_segmented_rect_3d_tex(const LLRectf& clip_rect, const LLRectf& center_uv gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mBottom); gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mBottom * height_vec).mV); + gGL.texCoord2f(clip_rect.mLeft, clip_rect.mBottom); + gGL.vertex3f(0.f, 0.f, 0.f); + + gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mBottom); + gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mBottom * height_vec).mV); + gGL.texCoord2f(clip_rect.mLeft, center_uv_rect.mBottom); gGL.vertex3fv((center_draw_rect.mBottom * height_vec).mV); @@ -1357,6 +1594,12 @@ void gl_segmented_rect_3d_tex(const LLRectf& clip_rect, const LLRectf& center_uv gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mBottom); gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mBottom * height_vec).mV); + gGL.texCoord2f(center_uv_rect.mLeft, clip_rect.mBottom); + gGL.vertex3fv((center_draw_rect.mLeft * width_vec).mV); + + gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mBottom); + gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mBottom * height_vec).mV); + gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mBottom); gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mBottom * height_vec).mV); @@ -1370,6 +1613,12 @@ void gl_segmented_rect_3d_tex(const LLRectf& clip_rect, const LLRectf& center_uv gGL.texCoord2f(clip_rect.mRight, center_uv_rect.mBottom); gGL.vertex3fv((width_vec + center_draw_rect.mBottom * height_vec).mV); + gGL.texCoord2f(center_uv_rect.mRight, clip_rect.mBottom); + gGL.vertex3fv((center_draw_rect.mRight * width_vec).mV); + + gGL.texCoord2f(clip_rect.mRight, center_uv_rect.mBottom); + gGL.vertex3fv((width_vec + center_draw_rect.mBottom * height_vec).mV); + gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mBottom); gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mBottom * height_vec).mV); @@ -1383,6 +1632,12 @@ void gl_segmented_rect_3d_tex(const LLRectf& clip_rect, const LLRectf& center_uv gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mTop); gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mTop * height_vec).mV); + gGL.texCoord2f(clip_rect.mLeft, center_uv_rect.mBottom); + gGL.vertex3fv((center_draw_rect.mBottom * height_vec).mV); + + gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mTop); + gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mTop * height_vec).mV); + gGL.texCoord2f(clip_rect.mLeft, center_uv_rect.mTop); gGL.vertex3fv((center_draw_rect.mTop * height_vec).mV); @@ -1396,6 +1651,12 @@ void gl_segmented_rect_3d_tex(const LLRectf& clip_rect, const LLRectf& center_uv gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mTop); gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mTop * height_vec).mV); + gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mBottom); + gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mBottom * height_vec).mV); + + gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mTop); + gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mTop * height_vec).mV); + gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mTop); gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mTop * height_vec).mV); @@ -1409,6 +1670,12 @@ void gl_segmented_rect_3d_tex(const LLRectf& clip_rect, const LLRectf& center_uv gGL.texCoord2f(clip_rect.mRight, center_uv_rect.mTop); gGL.vertex3fv((width_vec + center_draw_rect.mTop * height_vec).mV); + gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mBottom); + gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mBottom * height_vec).mV); + + gGL.texCoord2f(clip_rect.mRight, center_uv_rect.mTop); + gGL.vertex3fv((width_vec + center_draw_rect.mTop * height_vec).mV); + gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mTop); gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mTop * height_vec).mV); @@ -1422,6 +1689,12 @@ void gl_segmented_rect_3d_tex(const LLRectf& clip_rect, const LLRectf& center_uv gGL.texCoord2f(center_uv_rect.mLeft, clip_rect.mTop); gGL.vertex3fv((center_draw_rect.mLeft * width_vec + height_vec).mV); + gGL.texCoord2f(clip_rect.mLeft, center_uv_rect.mTop); + gGL.vertex3fv((center_draw_rect.mTop * height_vec).mV); + + gGL.texCoord2f(center_uv_rect.mLeft, clip_rect.mTop); + gGL.vertex3fv((center_draw_rect.mLeft * width_vec + height_vec).mV); + gGL.texCoord2f(clip_rect.mLeft, clip_rect.mTop); gGL.vertex3fv((height_vec).mV); @@ -1435,6 +1708,12 @@ void gl_segmented_rect_3d_tex(const LLRectf& clip_rect, const LLRectf& center_uv gGL.texCoord2f(center_uv_rect.mRight, clip_rect.mTop); gGL.vertex3fv((center_draw_rect.mRight * width_vec + height_vec).mV); + gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mTop); + gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mTop * height_vec).mV); + + gGL.texCoord2f(center_uv_rect.mRight, clip_rect.mTop); + gGL.vertex3fv((center_draw_rect.mRight * width_vec + height_vec).mV); + gGL.texCoord2f(center_uv_rect.mLeft, clip_rect.mTop); gGL.vertex3fv((center_draw_rect.mLeft * width_vec + height_vec).mV); @@ -1448,6 +1727,12 @@ void gl_segmented_rect_3d_tex(const LLRectf& clip_rect, const LLRectf& center_uv gGL.texCoord2f(clip_rect.mRight, clip_rect.mTop); gGL.vertex3fv((width_vec + height_vec).mV); + gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mTop); + gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mTop * height_vec).mV); + + gGL.texCoord2f(clip_rect.mRight, clip_rect.mTop); + gGL.vertex3fv((width_vec + height_vec).mV); + gGL.texCoord2f(center_uv_rect.mRight, clip_rect.mTop); gGL.vertex3fv((center_draw_rect.mRight * width_vec + height_vec).mV); } @@ -1514,10 +1799,12 @@ void LLRender2D::setLineWidth(F32 width) // If outside the allowed range, glLineWidth fails with "invalid value". // On Darwin, the range is [1, 1]. static GLfloat range[2]{0.0}; +#if GL_VERSION_1_2 if (range[1] == 0) { glGetFloatv(GL_SMOOTH_LINE_WIDTH_RANGE, range); } +#endif width *= lerp(LLRender::sUIGLScaleFactor.mV[VX], LLRender::sUIGLScaleFactor.mV[VY], 0.5f); glLineWidth(llclamp(width, range[0], range[1])); } diff --git a/indra/llrender/llrendertarget.cpp b/indra/llrender/llrendertarget.cpp index efdde77a32..dcc81a8874 100644 --- a/indra/llrender/llrendertarget.cpp +++ b/indra/llrender/llrendertarget.cpp @@ -430,7 +430,8 @@ void LLRenderTarget::bindTarget() if (mTex.empty()) { //no color buffer to draw to - glDrawBuffer(GL_NONE); + GLenum drawbuffers[] = {GL_NONE}; + glDrawBuffers(0, drawbuffers); glReadBuffer(GL_NONE); } @@ -498,7 +499,9 @@ void LLRenderTarget::bindTexture(U32 index, S32 channel, LLTexUnit::eTextureFilt { case GL_SRGB: case GL_SRGB8: +#if GL_VERSION_2_1 case GL_SRGB_ALPHA: +#endif case GL_SRGB8_ALPHA8: isSRGB = true; break; diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index 2eb7c21f77..6cded7f67a 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -37,6 +37,10 @@ #include "llglslshader.h" #include "llmemory.h" +#include "llcontrol.h" + +extern LLControlGroup gSavedSettings; + //Next Highest Power Of Two //helper function, returns first number > v that is a power of 2, or v if v is already a power of 2 U32 nhpo2(U32 v) @@ -290,7 +294,7 @@ static GLuint gen_buffer() #define ANALYZE_VBO_POOL 0 -#if LL_DARWIN +#if 0 // LL_DARWIN // experimental -- disable VBO pooling on OS X and use glMapBuffer class LLVBOPool @@ -351,6 +355,8 @@ class LLVBOPool public: typedef std::chrono::steady_clock::time_point Time; + U32 mMappingMode; + struct Entry { U8* mData; @@ -358,8 +364,16 @@ public: Time mAge; }; + /* + LLVBOPool() + { + + } + */ + ~LLVBOPool() { + if(mMappingMode == 3) return; clear(); } @@ -378,7 +392,8 @@ public: U64 getVramBytesUsed() { - return mAllocated + mReserved; + if(mMappingMode == 3) return mAllocated; + else return mAllocated + mReserved; } // increase the size to some common value (e.g. a power of two) to increase hit rate @@ -400,6 +415,20 @@ public: llassert(data == nullptr); // non null data indicates a buffer that wasn't freed llassert(size >= 2); // any buffer size smaller than a single index is nonsensical + if(mMappingMode == 3) + { + mAllocated += size; + + { //allocate a new buffer + LL_PROFILE_GPU_ZONE("vbo alloc"); + // ON OS X, we don't allocate a VBO until the last possible moment + // in unmapBuffer + data = (U8*) ll_aligned_malloc_16(size); + //STOP_GLERROR; + } + return; + } + mDistributed += size; adjustSize(size); mAllocated += size; @@ -453,6 +482,25 @@ public: LL_PROFILE_ZONE_SCOPED_CATEGORY_VERTEX; llassert(type == GL_ARRAY_BUFFER || type == GL_ELEMENT_ARRAY_BUFFER); llassert(size >= 2); + + if(mMappingMode == 3) + { + if (data) + { + ll_aligned_free_16(data); + } + + mAllocated -= size; + //STOP_GLERROR; + if (name) + { + glDeleteBuffers(1, &name); + } + //STOP_GLERROR; + + return; + } + llassert(name != 0); llassert(data != nullptr); @@ -584,6 +632,7 @@ U32 LLVertexBuffer::sGLRenderIndices = 0; U32 LLVertexBuffer::sLastMask = 0; U32 LLVertexBuffer::sVertexCount = 0; +U32 LLVertexBuffer::sMappingMode = 0; //NOTE: each component must be AT LEAST 4 bytes in size to avoid a performance penalty on AMD hardware const U32 LLVertexBuffer::sTypeSize[LLVertexBuffer::TYPE_MAX] = @@ -836,6 +885,9 @@ void LLVertexBuffer::initClass(LLWindow* window) { llassert(sVBOPool == nullptr); sVBOPool = new LLVBOPool(); + sVBOPool->mMappingMode = sMappingMode; + + //LL_INFOS() << "sVBOPool intialized with mapping mode: " << sMappingMode << LL_ENDL; #if ENABLE_GL_WORK_QUEUE sQueue = new GLWorkQueue(); @@ -1144,28 +1196,30 @@ U8* LLVertexBuffer::mapVertexBuffer(LLVertexBuffer::AttributeType type, U32 inde count = mNumVerts - index; } -#if !LL_DARWIN - U32 start = mOffsets[type] + sTypeSize[type] * index; - U32 end = start + sTypeSize[type] * count-1; - - bool flagged = false; - // flag region as mapped - for (U32 i = 0; i < mMappedVertexRegions.size(); ++i) + if(sMappingMode != 3) { - MappedRegion& region = mMappedVertexRegions[i]; - if (expand_region(region, start, end)) + U32 start = mOffsets[type] + sTypeSize[type] * index; + U32 end = start + sTypeSize[type] * count-1; + + bool flagged = false; + // flag region as mapped + for (U32 i = 0; i < mMappedVertexRegions.size(); ++i) { - flagged = true; - break; + MappedRegion& region = mMappedVertexRegions[i]; + if (expand_region(region, start, end)) + { + flagged = true; + break; + } } - } - if (!flagged) - { - //didn't expand an existing region, make a new one - mMappedVertexRegions.push_back({ start, end }); + if (!flagged) + { + //didn't expand an existing region, make a new one + mMappedVertexRegions.push_back({ start, end }); + } } -#endif + return mMappedData+mOffsets[type]+sTypeSize[type]*index; } @@ -1179,28 +1233,29 @@ U8* LLVertexBuffer::mapIndexBuffer(U32 index, S32 count) count = mNumIndices-index; } -#if !LL_DARWIN - U32 start = sizeof(U16) * index; - U32 end = start + sizeof(U16) * count-1; - - bool flagged = false; - // flag region as mapped - for (U32 i = 0; i < mMappedIndexRegions.size(); ++i) + if(sMappingMode != 3) { - MappedRegion& region = mMappedIndexRegions[i]; - if (expand_region(region, start, end)) + U32 start = sizeof(U16) * index; + U32 end = start + sizeof(U16) * count-1; + + bool flagged = false; + // flag region as mapped + for (U32 i = 0; i < mMappedIndexRegions.size(); ++i) { - flagged = true; - break; + MappedRegion& region = mMappedIndexRegions[i]; + if (expand_region(region, start, end)) + { + flagged = true; + break; + } } - } - if (!flagged) - { - //didn't expand an existing region, make a new one - mMappedIndexRegions.push_back({ start, end }); + if (!flagged) + { + //didn't expand an existing region, make a new one + mMappedIndexRegions.push_back({ start, end }); + } } -#endif return mMappedIndexData + sizeof(U16)*index; } @@ -1213,12 +1268,31 @@ U8* LLVertexBuffer::mapIndexBuffer(U32 index, S32 count) // dst -- mMappedData or mMappedIndexData void LLVertexBuffer::flush_vbo(GLenum target, U32 start, U32 end, void* data, U8* dst) { -#if LL_DARWIN - LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("vb memcpy"); - STOP_GLERROR; - // copy into mapped buffer - memcpy(dst+start, data, end-start+1); -#else + if(sMappingMode == 2) + { + //LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("vb glMapBufferRange"); + if (end == 0) return; + U32 buffer_size = end-start+1; + U8 * mptr = (U8*) glMapBufferRange( target, start, end-start+1, GL_MAP_WRITE_BIT); + + if (mptr) + { + std::memcpy(mptr, (U8*) data, buffer_size); + if(!glUnmapBuffer(target)) LL_WARNS() << "glUnmapBuffer() failed" << LL_ENDL; + } + else LL_WARNS() << "glMapBufferRange() returned NULL" << LL_ENDL; + return; + } + + if(sMappingMode == 3) + { + LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("vb memcpy"); + //STOP_GLERROR; + // copy into mapped buffer + memcpy(dst+start, data, end-start+1); + return; + } + llassert(target == GL_ARRAY_BUFFER ? sGLRenderBuffer == mGLBuffer : sGLRenderIndices == mGLIndices); // skip mapped data and stream to GPU via glBufferSubData @@ -1240,7 +1314,6 @@ void LLVertexBuffer::flush_vbo(GLenum target, U32 start, U32 end, void* data, U8 glBufferSubData(target, i, size, (U8*) data + (i-start)); } } -#endif } void LLVertexBuffer::unmapBuffer() @@ -1254,46 +1327,48 @@ void LLVertexBuffer::unmapBuffer() } }; -#if LL_DARWIN - STOP_GLERROR; - if (mMappedData) + if(sMappingMode == 3) { - if (mGLBuffer) + //STOP_GLERROR; + if (mMappedData) { - glDeleteBuffers(1, &mGLBuffer); + if (mGLBuffer) + { + glDeleteBuffers(1, &mGLBuffer); + } + mGLBuffer = gen_buffer(); + glBindBuffer(GL_ARRAY_BUFFER, mGLBuffer); + sGLRenderBuffer = mGLBuffer; + glBufferData(GL_ARRAY_BUFFER, mSize, mMappedData, GL_DYNAMIC_DRAW); } - mGLBuffer = gen_buffer(); - glBindBuffer(GL_ARRAY_BUFFER, mGLBuffer); - sGLRenderBuffer = mGLBuffer; - glBufferData(GL_ARRAY_BUFFER, mSize, mMappedData, GL_STATIC_DRAW); - } - else if (mGLBuffer != sGLRenderBuffer) - { - glBindBuffer(GL_ARRAY_BUFFER, mGLBuffer); - sGLRenderBuffer = mGLBuffer; - } - STOP_GLERROR; - - if (mMappedIndexData) - { - if (mGLIndices) + else if (mGLBuffer != sGLRenderBuffer) { - glDeleteBuffers(1, &mGLIndices); + glBindBuffer(GL_ARRAY_BUFFER, mGLBuffer); + sGLRenderBuffer = mGLBuffer; } + //STOP_GLERROR; - mGLIndices = gen_buffer(); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mGLIndices); - sGLRenderIndices = mGLIndices; + if (mMappedIndexData) + { + if (mGLIndices) + { + glDeleteBuffers(1, &mGLIndices); + } - glBufferData(GL_ELEMENT_ARRAY_BUFFER, mIndicesSize, mMappedIndexData, GL_STATIC_DRAW); - } - else if (mGLIndices != sGLRenderIndices) - { - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mGLIndices); - sGLRenderIndices = mGLIndices; + mGLIndices = gen_buffer(); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mGLIndices); + sGLRenderIndices = mGLIndices; + + glBufferData(GL_ELEMENT_ARRAY_BUFFER, mIndicesSize, mMappedIndexData, GL_DYNAMIC_DRAW); + } + else if (mGLIndices != sGLRenderIndices) + { + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mGLIndices); + sGLRenderIndices = mGLIndices; + } + //STOP_GLERROR; + return; } - STOP_GLERROR; -#else if (!mMappedVertexRegions.empty()) { @@ -1361,7 +1436,6 @@ void LLVertexBuffer::unmapBuffer() flush_vbo(GL_ELEMENT_ARRAY_BUFFER, start, end, (U8*)mMappedIndexData + start, mMappedIndexData); mMappedIndexRegions.clear(); } -#endif } //---------------------------------------------------------------------------- @@ -1482,13 +1556,14 @@ bool LLVertexBuffer::getClothWeightStrider(LLStrider<LLVector4>& strider, U32 in // Set for rendering void LLVertexBuffer::setBuffer() { - STOP_GLERROR; -#if LL_DARWIN - if (!mGLBuffer) - { // OS X doesn't allocate a buffer until we call unmapBuffer - return; + if(sMappingMode == 3) + { + if (!mGLBuffer) + { + return; + } } -#endif + // no data may be pending llassert(mMappedVertexRegions.empty()); llassert(mMappedIndexRegions.empty()); diff --git a/indra/llrender/llvertexbuffer.h b/indra/llrender/llvertexbuffer.h index 49500e28ce..4dd375a4af 100644 --- a/indra/llrender/llvertexbuffer.h +++ b/indra/llrender/llvertexbuffer.h @@ -163,7 +163,7 @@ public: // set for rendering // assumes (and will assert on) the following: - // - this buffer has no pending unampBuffer call + // - this buffer has no pending unmapBuffer call // - a shader is currently bound // - This buffer has sufficient attributes within it to satisfy the needs of the currently bound shader void setBuffer(); @@ -289,6 +289,8 @@ public: static U32 sGLRenderIndices; static U32 sLastMask; static U32 sVertexCount; + + static U32 sMappingMode; }; #ifdef LL_PROFILER_ENABLE_RENDER_DOC diff --git a/indra/llui/CMakeLists.txt b/indra/llui/CMakeLists.txt index a0314cb5f2..5991a5b35e 100644 --- a/indra/llui/CMakeLists.txt +++ b/indra/llui/CMakeLists.txt @@ -270,6 +270,8 @@ target_link_libraries(llui llcommon ) +include(LibraryInstall) + # Add tests if(LL_TESTS) include(LLAddBuildTest) diff --git a/indra/llui/llbadge.cpp b/indra/llui/llbadge.cpp index 3397c97ee1..55fbd72165 100644 --- a/indra/llui/llbadge.cpp +++ b/indra/llui/llbadge.cpp @@ -202,15 +202,17 @@ void renderBadgeBackground(F32 centerX, F32 centerY, F32 width, F32 height, cons ll_round(x) + width, ll_round(y) + height); - LLVector3 vertices[4]; - vertices[0] = LLVector3(screen_rect.mRight, screen_rect.mTop, 1.0f); - vertices[1] = LLVector3(screen_rect.mLeft, screen_rect.mTop, 1.0f); - vertices[2] = LLVector3(screen_rect.mLeft, screen_rect.mBottom, 1.0f); - vertices[3] = LLVector3(screen_rect.mRight, screen_rect.mBottom, 1.0f); - - gGL.begin(LLRender::QUADS); + LLVector4a vertices[6]; + vertices[0].set(screen_rect.mLeft, screen_rect.mTop, 1.0f); + vertices[1].set(screen_rect.mLeft, screen_rect.mBottom, 1.0f); + vertices[2].set(screen_rect.mRight, screen_rect.mTop, 1.0f); + vertices[3].set(screen_rect.mRight, screen_rect.mTop, 1.0f); + vertices[4].set(screen_rect.mLeft, screen_rect.mBottom, 1.0f); + vertices[5].set(screen_rect.mRight, screen_rect.mBottom, 1.0f); + + gGL.begin(LLRender::TRIANGLES); { - gGL.vertexBatchPreTransformed(vertices, 4); + gGL.vertexBatchPreTransformed(vertices, 6); } gGL.end(); diff --git a/indra/llui/llfocusmgr.cpp b/indra/llui/llfocusmgr.cpp index 937dde4def..e0e789f730 100644 --- a/indra/llui/llfocusmgr.cpp +++ b/indra/llui/llfocusmgr.cpp @@ -59,6 +59,12 @@ bool LLFocusableElement::handleUnicodeChar(llwchar uni_char, bool called_from_pa } // virtual +bool LLFocusableElement::handleUnicodeString(char *uni_str, bool editing, bool called_from_parent) +{ + return FALSE; +} + +// virtual bool LLFocusableElement::wantsKeyUpKeyDown() const { return false; diff --git a/indra/llui/llfocusmgr.h b/indra/llui/llfocusmgr.h index 1fa0ac137e..1ca6f50354 100644 --- a/indra/llui/llfocusmgr.h +++ b/indra/llui/llfocusmgr.h @@ -59,6 +59,7 @@ public: virtual bool handleKey(KEY key, MASK mask, bool called_from_parent); virtual bool handleKeyUp(KEY key, MASK mask, bool called_from_parent); virtual bool handleUnicodeChar(llwchar uni_char, bool called_from_parent); + virtual bool handleUnicodeString(char *uni_str, bool editing, bool called_from_parent); /** * If true this LLFocusableElement wants to receive KEYUP and KEYDOWN messages diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp index 50bf3f5877..fa71c7704d 100644 --- a/indra/llui/lllineeditor.cpp +++ b/indra/llui/lllineeditor.cpp @@ -1031,6 +1031,25 @@ void LLLineEditor::addChar(const llwchar uni_char) getWindow()->hideCursorUntilMouseMove(); } +void LLLineEditor::addString(char *s, bool editing) +{ + if (hasSelection()) + deleteSelection(); + else if (LL_KIM_OVERWRITE == gKeyboard->getInsertMode()) { + if (!prevalidateInput(mText.getWString() + .substr(getCursor(), 1))) + return; + mText.erase(getCursor(), 1); + } else if (editing) { + mText.clear(); + setCursor(0); + } + mText.insert(getCursor(), utf8str_to_wstring(s)); + if (editing) setCursor(strlen(s)); + else setCursor(getCursor() + 1); + getWindow()->hideCursorUntilMouseMove(); +} + // Extends the selection box to the new cursor position void LLLineEditor::extendSelection( S32 new_cursor_pos ) { @@ -1685,6 +1704,36 @@ bool LLLineEditor::handleUnicodeCharHere(llwchar uni_char) return handled; } +bool LLLineEditor::handleUnicodeStringHere(char *uni_str, bool editing) +{ + auto handled = FALSE; + + if ((gFocusMgr.getKeyboardFocus() == this) + && getVisible() && !mReadOnly) { + handled = TRUE; + LLLineEditorRollback rollback(this); + + addString(uni_str, editing); + + mKeystrokeTimer.reset(); + deselect(); + auto need_to_rollback = mPrevalidator + && !mPrevalidator.validate(mText.getWString()); + + if (need_to_rollback) { + rollback.doRollback(this); + LLUI::getInstance()->reportBadKeystroke(); + mPrevalidator.showLastErrorUsingTimeout(); + } + + if (!need_to_rollback && handled) { + onKeystroke(); + mSpellCheckTimer.setTimerExpirySec(SPELLCHECK_DELAY); + } + } + + return handled; +} bool LLLineEditor::canDoDelete() const { diff --git a/indra/llui/lllineeditor.h b/indra/llui/lllineeditor.h index e955cbb17d..2d9c3ac58a 100644 --- a/indra/llui/lllineeditor.h +++ b/indra/llui/lllineeditor.h @@ -133,6 +133,7 @@ public: /*virtual*/ bool handleRightMouseDown(S32 x, S32 y, MASK mask) override; /*virtual*/ bool handleKeyHere(KEY key, MASK mask) override; /*virtual*/ bool handleUnicodeCharHere(llwchar uni_char) override; + /*virtual*/ bool handleUnicodeStringHere(char *uni_str, bool editing) override; /*virtual*/ void onMouseCaptureLost() override; // LLEditMenuHandler overrides @@ -300,6 +301,7 @@ public: void removeChar(); void addChar(const llwchar c); + void addString(char *s, bool editing); void setCursorAtLocalPos(S32 local_mouse_x); S32 findPixelNearestPos(S32 cursor_offset = 0) const; S32 calcCursorPos(S32 mouse_x); diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp index dc3026e14d..5d30c1299a 100644 --- a/indra/llui/lltexteditor.cpp +++ b/indra/llui/lltexteditor.cpp @@ -167,6 +167,50 @@ private: }; /////////////////////////////////////////////////////////////////// +class LLTextEditor::TextCmdAddString : public LLTextBase::TextCmd +{ +public: + TextCmdAddString(S32 pos, bool group_with_next, char *str, + LLTextSegmentPtr segment) : + TextCmd(pos, group_with_next, segment), + mWString(utf8str_to_wstring(str)), + mBlockExtensions(FALSE) + { + } + virtual void blockExtensions() + { + mBlockExtensions = TRUE; + } + virtual bool canExtend(S32 pos) const + { + if (!mSegments.empty()) return FALSE; + + return !mBlockExtensions + && (pos == getPosition() + (S32)mWString.length()); + } + virtual bool execute(LLTextBase* editor, S32* delta) + { + *delta = insert(editor, getPosition(), mWString); + LLWStringUtil::truncate(mWString, *delta); + return (*delta != 0); + } + virtual S32 undo(LLTextBase* editor) + { + remove(editor, getPosition(), mWString.length()); + return getPosition(); + } + virtual S32 redo(LLTextBase* editor) + { + insert(editor, getPosition(), mWString); + return getPosition() + mWString.length(); + } + +private: + LLWString mWString; + bool mBlockExtensions; +}; + +/////////////////////////////////////////////////////////////////// class LLTextEditor::TextCmdOverwriteChar : public LLTextBase::TextCmd { @@ -1164,6 +1208,18 @@ S32 LLTextEditor::addChar(S32 pos, llwchar wc) return execute(new TextCmdAddChar(pos, false, wc, LLTextSegmentPtr())); } +S32 LLTextEditor::addString(S32 pos, char *str) +{ + if ((wstring_utf8_length(getWText()) + strlen(str)) + > mMaxTextByteLength) { + make_ui_sound("UISndBadKeystroke"); + return 0; + } + + return execute(new TextCmdAddString(pos, FALSE, str, + LLTextSegmentPtr())); +} + void LLTextEditor::addChar(llwchar wc) { if (!getEnabled()) @@ -1201,6 +1257,38 @@ void LLTextEditor::addChar(llwchar wc) } } +void LLTextEditor::addString(char *str, bool editing) +{ + if (!getEnabled()) + return; + if (hasSelection()) + deleteSelection(TRUE); + else if (LL_KIM_OVERWRITE == gKeyboard->getInsertMode()) + removeChar(mCursorPos); + else if (editing) { + clear(); + setCursorPos(0); + } + + setCursorPos(mCursorPos + addString(mCursorPos, str)); + + if (!mReadOnly && mAutoreplaceCallback != NULL) { + S32 replacement_start; + S32 replacement_length; + LLWString replacement_string; + S32 new_cursor_pos = mCursorPos; + mAutoreplaceCallback(replacement_start, replacement_length, + replacement_string, new_cursor_pos, getWText()); + + if (replacement_length > 0 || !replacement_string.empty()) { + remove(replacement_start, replacement_length, true); + insert(replacement_start, replacement_string, false, + LLTextSegmentPtr()); + setCursorPos(new_cursor_pos); + } + } +} + void LLTextEditor::showEmojiHelper() { if (mReadOnly || !mShowEmojiHelper) @@ -1972,6 +2060,24 @@ bool LLTextEditor::handleUnicodeCharHere(llwchar uni_char) return handled; } +bool LLTextEditor::handleUnicodeStringHere(char *uni_str, bool editing) +{ + auto handled = FALSE; + + if (!mReadOnly) { + addString(uni_str, editing); + getWindow()->hideCursorUntilMouseMove(); + handled = TRUE; + } + + if (handled) { + resetCursorBlink(); + deselect(); + onKeyStroke(); + } + + return handled; +} // virtual bool LLTextEditor::canDoDelete() const diff --git a/indra/llui/lltexteditor.h b/indra/llui/lltexteditor.h index be7f7cb256..6ce08f48b5 100644 --- a/indra/llui/lltexteditor.h +++ b/indra/llui/lltexteditor.h @@ -105,6 +105,7 @@ public: virtual bool handleKeyHere(KEY key, MASK mask ); virtual bool handleUnicodeCharHere(llwchar uni_char); + virtual bool handleUnicodeStringHere(char *uni_str, bool editing); virtual void onMouseCaptureLost(); @@ -249,6 +250,8 @@ protected: // Undoable operations void addChar(llwchar c); // at mCursorPos S32 addChar(S32 pos, llwchar wc); + void addString(char *s, bool editing); + S32 addString(S32 pos, char *str); void addLineBreakChar(bool group_together = false); S32 overwriteChar(S32 pos, llwchar wc); void removeChar(); @@ -310,6 +313,7 @@ private: // Concrete TextCmd sub-classes used by the LLTextEditor base class class TextCmdInsert; class TextCmdAddChar; + class TextCmdAddString; class TextCmdOverwriteChar; class TextCmdRemove; diff --git a/indra/llui/llui.cpp b/indra/llui/llui.cpp index 66ec3ad9bd..ba8fe84377 100644 --- a/indra/llui/llui.cpp +++ b/indra/llui/llui.cpp @@ -223,6 +223,11 @@ void LLUI::getMousePositionScreen(S32 *x, S32 *y) LLCoordGL cursor_pos_gl(cursor_pos_window.convert()); *x = ll_round((F32)cursor_pos_gl.mX / getScaleFactor().mV[VX]); *y = ll_round((F32)cursor_pos_gl.mY / getScaleFactor().mV[VY]); +#if defined(LL_SDL) + *x = *x * LLView::getWindow()->getSystemUISize(); + *y = *y * LLView::getWindow()->getSystemUISize(); +#endif + } void LLUI::setMousePositionLocal(const LLView* viewp, S32 x, S32 y) diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp index 441b7d6a6c..1e72228fee 100644 --- a/indra/llui/llview.cpp +++ b/indra/llui/llview.cpp @@ -1080,12 +1080,31 @@ bool LLView::handleUnicodeChar(llwchar uni_char, bool called_from_parent) return handled; } +bool LLView::handleUnicodeString(char *uni_str, bool editing, bool called_from_parent) +{ + auto handled = FALSE; + + if (getVisible() && getEnabled() && !handled) { + handled = handleUnicodeStringHere(uni_str, editing); + if (handled && LLView::sDebugKeys) + LL_INFOS() << "Unicode key handled by " << getName() << LL_ENDL; + } + + if (!handled && !called_from_parent && mParentView) + handled = mParentView->handleUnicodeString(uni_str, editing, FALSE); + + return handled; +} bool LLView::handleUnicodeCharHere(llwchar uni_char ) { return false; } +bool LLView::handleUnicodeStringHere(char *uni_str, bool editing) +{ + return FALSE; +} bool LLView::handleDragAndDrop(S32 x, S32 y, MASK mask, bool drop, EDragAndDropType cargo_type, void* cargo_data, diff --git a/indra/llui/llview.h b/indra/llui/llview.h index 3ce7243370..ad3b71505d 100644 --- a/indra/llui/llview.h +++ b/indra/llui/llview.h @@ -385,6 +385,7 @@ public: /* virtual */ bool handleKey(KEY key, MASK mask, bool called_from_parent); /* virtual */ bool handleKeyUp(KEY key, MASK mask, bool called_from_parent); /* virtual */ bool handleUnicodeChar(llwchar uni_char, bool called_from_parent); + /* virtual */ bool handleUnicodeString(char *uni_str, bool editing, bool called_from_parent); virtual bool handleDragAndDrop(S32 x, S32 y, MASK mask, bool drop, EDragAndDropType cargo_type, @@ -518,6 +519,7 @@ public: virtual bool handleKeyHere(KEY key, MASK mask); virtual bool handleKeyUpHere(KEY key, MASK mask); virtual bool handleUnicodeCharHere(llwchar uni_char); + virtual bool handleUnicodeStringHere(char *uni_str, bool editing); virtual void handleReshape(const LLRect& rect, bool by_user); virtual void dirtyRect(); diff --git a/indra/llwebrtc/CMakeLists.txt b/indra/llwebrtc/CMakeLists.txt index a18b716003..425376d248 100644 --- a/indra/llwebrtc/CMakeLists.txt +++ b/indra/llwebrtc/CMakeLists.txt @@ -28,7 +28,9 @@ list(APPEND llwebrtc_SOURCE_FILES ${llwebrtc_HEADER_FILES}) add_library (llwebrtc SHARED ${llwebrtc_SOURCE_FILES}) +if (NOT INSTALL) set_target_properties(llwebrtc PROPERTIES PUBLIC_HEADER llwebrtc.h) +endif () if (WINDOWS) cmake_policy(SET CMP0091 NEW) @@ -74,3 +76,16 @@ ADD_CUSTOM_COMMAND(TARGET llwebrtc POST_BUILD # Add tests if (LL_TESTS) endif (LL_TESTS) + +if (INSTALL) + if (DARWIN) + set(_LIB ../Frameworks) + elseif (EXISTS ${CMAKE_SYSROOT}/usr/lib/${ARCH}-linux-gnu) + set(_LIB lib/${ARCH}-linux-gnu) + elseif (EXISTS /lib64) + set(_LIB lib64) + else (DARWIN) + set(_LIB lib) + endif (DARWIN) + install(TARGETS ${PROJECT_NAME} DESTINATION ${_LIB}) +endif (INSTALL) diff --git a/indra/llwebrtc/llwebrtc.cpp b/indra/llwebrtc/llwebrtc.cpp index 0daa767766..83350dd457 100644 --- a/indra/llwebrtc/llwebrtc.cpp +++ b/indra/llwebrtc/llwebrtc.cpp @@ -203,7 +203,9 @@ void LLWebRTCImpl::init() mTuningDeviceModule->SetPlayoutDevice(mPlayoutDevice); mTuningDeviceModule->SetRecordingDevice(mRecordingDevice); mTuningDeviceModule->EnableBuiltInAEC(false); +#if __x86_64__ && !__FreeBSD__ mTuningDeviceModule->SetAudioDeviceSink(this); +#endif mTuningDeviceModule->InitMicrophone(); mTuningDeviceModule->InitSpeaker(); mTuningDeviceModule->SetStereoRecording(false); diff --git a/indra/llwebrtc/llwebrtc_impl.h b/indra/llwebrtc/llwebrtc_impl.h index f8a7873af8..6543b2718c 100644 --- a/indra/llwebrtc/llwebrtc_impl.h +++ b/indra/llwebrtc/llwebrtc_impl.h @@ -184,7 +184,10 @@ class LLCustomProcessor : public webrtc::CustomProcessing // Primary singleton implementation for interfacing // with the native webrtc library. -class LLWebRTCImpl : public LLWebRTCDeviceInterface, public webrtc::AudioDeviceSink +class LLWebRTCImpl : public LLWebRTCDeviceInterface +#if __x86_64__ && !__FreeBSD__ + , public webrtc::AudioDeviceSink +#endif { public: LLWebRTCImpl(LLWebRTCLogCallback* logCallback); @@ -219,7 +222,11 @@ class LLWebRTCImpl : public LLWebRTCDeviceInterface, public webrtc::AudioDeviceS // // AudioDeviceSink // - void OnDevicesUpdated() override; + void OnDevicesUpdated() +#if __x86_64__ && !__FreeBSD__ + override +#endif + ; // // Helpers diff --git a/indra/llwindow/CMakeLists.txt b/indra/llwindow/CMakeLists.txt index 7b1430c67c..6b70d66d7a 100644 --- a/indra/llwindow/CMakeLists.txt +++ b/indra/llwindow/CMakeLists.txt @@ -51,7 +51,6 @@ set(llwindow_LINK_LIBRARIES llcommon llimage llmath - llrender llfilesystem llxml ll::glh_linear @@ -59,11 +58,14 @@ set(llwindow_LINK_LIBRARIES ll::uilibraries ll::SDL ) + +include_directories(${CMAKE_SOURCE_DIR}/llrender) + # Libraries on which this library depends, needed for Linux builds # Sort by high-level to low-level -if (LINUX) - list(APPEND viewer_SOURCE_FILES - llkeyboardsdl.cpp +if (USESYSTEMLIBS AND NOT DARWIN) + list(APPEND viewer_SOURCE_FILES + llkeyboardsdl.cpp llwindowsdl.cpp ) list(APPEND viewer_HEADER_FILES @@ -83,8 +85,7 @@ if (LINUX) fontconfig # For FCInit and other FC* functions. ) endif (BUILD_HEADLESS) - -endif (LINUX) +endif (USESYSTEMLIBS AND NOT DARWIN) if (DARWIN) list(APPEND llwindow_SOURCE_FILES @@ -179,9 +180,11 @@ endif (SDL_FOUND) target_link_libraries (llwindow ${llwindow_LINK_LIBRARIES}) target_include_directories(llwindow INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) - + if (DARWIN) include(CMakeFindFrameworks) find_library(CARBON_LIBRARY Carbon) target_link_libraries(llwindow ${CARBON_LIBRARY}) endif (DARWIN) + +include(LibraryInstall) diff --git a/indra/llwindow/llkeyboard.cpp b/indra/llwindow/llkeyboard.cpp index 4f29fb0b0a..d76a90e98a 100644 --- a/indra/llwindow/llkeyboard.cpp +++ b/indra/llwindow/llkeyboard.cpp @@ -41,7 +41,6 @@ std::map<KEY,std::string> LLKeyboard::sKeysToNames; std::map<std::string,KEY> LLKeyboard::sNamesToKeys; LLKeyStringTranslatorFunc* LLKeyboard::mStringTranslator = NULL; // Used for l10n + PC/Mac/Linux accelerator labeling - // // Class Implementation // @@ -195,12 +194,11 @@ void LLKeyboard::resetKeys() } -bool LLKeyboard::translateKey(const U16 os_key, KEY *out_key) +bool LLKeyboard::translateKey(const NATIVE_KEY_TYPE os_key, KEY *out_key) { - std::map<U16, KEY>::iterator iter; // Only translate keys in the map, ignore all other keys for now - iter = mTranslateKeyMap.find(os_key); + auto iter = mTranslateKeyMap.find(os_key); if (iter == mTranslateKeyMap.end()) { //LL_WARNS() << "Unknown virtual key " << os_key << LL_ENDL; @@ -214,11 +212,9 @@ bool LLKeyboard::translateKey(const U16 os_key, KEY *out_key) } } - -U16 LLKeyboard::inverseTranslateKey(const KEY translated_key) +LLKeyboard::NATIVE_KEY_TYPE LLKeyboard::inverseTranslateKey(const KEY translated_key) { - std::map<KEY, U16>::iterator iter; - iter = mInvTranslateKeyMap.find(translated_key); + auto iter = mInvTranslateKeyMap.find(translated_key); if (iter == mInvTranslateKeyMap.end()) { return 0; diff --git a/indra/llwindow/llkeyboard.h b/indra/llwindow/llkeyboard.h index 7f8d0af155..83ce6e5b04 100644 --- a/indra/llwindow/llkeyboard.h +++ b/indra/llwindow/llkeyboard.h @@ -55,6 +55,11 @@ class LLWindowCallbacks; class LLKeyboard { public: +#ifndef LL_SDL + typedef U16 NATIVE_KEY_TYPE; +#else + typedef U32 NATIVE_KEY_TYPE; +#endif LLKeyboard(); virtual ~LLKeyboard(); @@ -67,16 +72,15 @@ public: bool getKeyDown(const KEY key) { return mKeyLevel[key]; } bool getKeyRepeated(const KEY key) { return mKeyRepeated[key]; } - bool translateKey(const U16 os_key, KEY *translated_key); - U16 inverseTranslateKey(const KEY translated_key); + bool translateKey(const NATIVE_KEY_TYPE os_key, KEY *translated_key); + NATIVE_KEY_TYPE inverseTranslateKey(const KEY translated_key); bool handleTranslatedKeyUp(KEY translated_key, U32 translated_mask); // Translated into "Linden" keycodes bool handleTranslatedKeyDown(KEY translated_key, U32 translated_mask); // Translated into "Linden" keycodes + virtual bool handleKeyUp(const NATIVE_KEY_TYPE key, MASK mask) = 0; + virtual bool handleKeyDown(const NATIVE_KEY_TYPE key, MASK mask) = 0; - virtual bool handleKeyUp(const U16 key, MASK mask) = 0; - virtual bool handleKeyDown(const U16 key, MASK mask) = 0; - -#ifdef LL_DARWIN +#if defined(LL_DARWIN) && !defined(LL_SDL) // We only actually use this for macOS. virtual void handleModifier(MASK mask) = 0; #endif // LL_DARWIN @@ -111,8 +115,8 @@ protected: void addKeyName(KEY key, const std::string& name); protected: - std::map<U16, KEY> mTranslateKeyMap; // Map of translations from OS keys to Linden KEYs - std::map<KEY, U16> mInvTranslateKeyMap; // Map of translations from Linden KEYs to OS keys + std::map<NATIVE_KEY_TYPE, KEY> mTranslateKeyMap; // Map of translations from OS keys to Linden KEYs + std::map<KEY, NATIVE_KEY_TYPE> mInvTranslateKeyMap; // Map of translations from Linden KEYs to OS keys LLWindowCallbacks *mCallbacks; LLTimer mKeyLevelTimer[KEY_COUNT]; // Time since level was set diff --git a/indra/llwindow/llkeyboardheadless.cpp b/indra/llwindow/llkeyboardheadless.cpp index 8669a5b41a..6f8c829dd5 100644 --- a/indra/llwindow/llkeyboardheadless.cpp +++ b/indra/llwindow/llkeyboardheadless.cpp @@ -35,12 +35,8 @@ void LLKeyboardHeadless::resetMaskKeys() { } -bool LLKeyboardHeadless::handleKeyDown(const U16 key, const U32 mask) -{ return false; } -bool LLKeyboardHeadless::handleKeyUp(const U16 key, const U32 mask) -{ return false; } MASK LLKeyboardHeadless::currentMask(bool for_mouse_event) { return MASK_NONE; } diff --git a/indra/llwindow/llkeyboardheadless.h b/indra/llwindow/llkeyboardheadless.h index 2528f0e3f1..439abaf25b 100644 --- a/indra/llwindow/llkeyboardheadless.h +++ b/indra/llwindow/llkeyboardheadless.h @@ -35,8 +35,13 @@ public: LLKeyboardHeadless(); /*virtual*/ ~LLKeyboardHeadless() {}; - /*virtual*/ bool handleKeyUp(const U16 key, MASK mask); - /*virtual*/ bool handleKeyDown(const U16 key, MASK mask); +#ifndef LL_SDL + /*virtual*/ bool handleKeyUp(const U16 key, MASK mask) { return false; } + /*virtual*/ bool handleKeyDown(const U16 key, MASK mask) { return false; } +#else + /*virtual*/ bool handleKeyUp(const U32 key, MASK mask) { return false; } + /*virtual*/ bool handleKeyDown(const U32 key, MASK mask) { return false; } +#endif /*virtual*/ void resetMaskKeys(); /*virtual*/ MASK currentMask(bool for_mouse_event); /*virtual*/ void scanKeyboard(); diff --git a/indra/llwindow/llkeyboardsdl.cpp b/indra/llwindow/llkeyboardsdl.cpp index 97198f0cc0..72b4577276 100644 --- a/indra/llwindow/llkeyboardsdl.cpp +++ b/indra/llwindow/llkeyboardsdl.cpp @@ -1,6 +1,5 @@ /** - * @file llkeyboardsdl.cpp - * @brief Handler for assignable key bindings + * @author This module has many fathers, and it shows. * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code @@ -24,12 +23,11 @@ * $/LicenseInfo$ */ -#if LL_SDL - #include "linden_common.h" #include "llkeyboardsdl.h" #include "llwindowcallbacks.h" -#include "SDL/SDL.h" +#include "SDL2/SDL.h" +#include "SDL2/SDL_keycode.h" LLKeyboardSDL::LLKeyboardSDL() { @@ -40,6 +38,10 @@ LLKeyboardSDL::LLKeyboardSDL() // Virtual key mappings from SDL_keysym.h ... // SDL maps the letter keys to the ASCII you'd expect, but it's lowercase... + + // <FS:ND> Looks like we need to map those despite of SDL_TEXTINPUT handling most of this, but without + // the translation lower->upper here accelerators will not work. + U16 cur_char; for (cur_char = 'A'; cur_char <= 'Z'; cur_char++) { @@ -68,13 +70,12 @@ LLKeyboardSDL::LLKeyboardSDL() //mTranslateKeyMap[SDLK_KP3] = KEY_PAGE_DOWN; //mTranslateKeyMap[SDLK_KP0] = KEY_INSERT; - mTranslateKeyMap[SDLK_SPACE] = ' '; + mTranslateKeyMap[SDLK_SPACE] = ' '; // <FS:ND/> Those are handled by SDL2 via text input, do not map them mTranslateKeyMap[SDLK_RETURN] = KEY_RETURN; mTranslateKeyMap[SDLK_LEFT] = KEY_LEFT; mTranslateKeyMap[SDLK_RIGHT] = KEY_RIGHT; mTranslateKeyMap[SDLK_UP] = KEY_UP; mTranslateKeyMap[SDLK_DOWN] = KEY_DOWN; - mTranslateKeyMap[SDLK_ESCAPE] = KEY_ESCAPE; mTranslateKeyMap[SDLK_KP_ENTER] = KEY_RETURN; mTranslateKeyMap[SDLK_ESCAPE] = KEY_ESCAPE; mTranslateKeyMap[SDLK_BACKSPACE] = KEY_BACKSPACE; @@ -111,40 +112,39 @@ LLKeyboardSDL::LLKeyboardSDL() mTranslateKeyMap[SDLK_F10] = KEY_F10; mTranslateKeyMap[SDLK_F11] = KEY_F11; mTranslateKeyMap[SDLK_F12] = KEY_F12; - mTranslateKeyMap[SDLK_PLUS] = '='; - mTranslateKeyMap[SDLK_COMMA] = ','; - mTranslateKeyMap[SDLK_MINUS] = '-'; - mTranslateKeyMap[SDLK_PERIOD] = '.'; - mTranslateKeyMap[SDLK_BACKQUOTE] = '`'; - mTranslateKeyMap[SDLK_SLASH] = KEY_DIVIDE; - mTranslateKeyMap[SDLK_SEMICOLON] = ';'; - mTranslateKeyMap[SDLK_LEFTBRACKET] = '['; - mTranslateKeyMap[SDLK_BACKSLASH] = '\\'; - mTranslateKeyMap[SDLK_RIGHTBRACKET] = ']'; - mTranslateKeyMap[SDLK_QUOTE] = '\''; + mTranslateKeyMap[SDLK_PLUS] = '='; // <FS:ND/> Those are handled by SDL2 via text input, do not map them + mTranslateKeyMap[SDLK_COMMA] = ','; // <FS:ND/> Those are handled by SDL2 via text input, do not map them + mTranslateKeyMap[SDLK_MINUS] = '-'; // <FS:ND/> Those are handled by SDL2 via text input, do not map them + mTranslateKeyMap[SDLK_PERIOD] = '.'; // <FS:ND/> Those are handled by SDL2 via text input, do not map them + mTranslateKeyMap[SDLK_BACKQUOTE] = '`'; // <FS:ND/> Those are handled by SDL2 via text input, do not map them + mTranslateKeyMap[SDLK_SLASH] = KEY_DIVIDE; // <FS:ND/> Those are handled by SDL2 via text input, do not map them + mTranslateKeyMap[SDLK_SEMICOLON] = ';'; // <FS:ND/> Those are handled by SDL2 via text input, do not map them + mTranslateKeyMap[SDLK_LEFTBRACKET] = '['; // <FS:ND/> Those are handled by SDL2 via text input, do not map them + mTranslateKeyMap[SDLK_BACKSLASH] = '\\'; // <FS:ND/> Those are handled by SDL2 via text input, do not map them + mTranslateKeyMap[SDLK_RIGHTBRACKET] = ']'; // <FS:ND/> Those are handled by SDL2 via text input, do not map them + mTranslateKeyMap[SDLK_QUOTE] = '\''; // <FS:ND/> Those are handled by SDL2 via text input, do not map them // Build inverse map - std::map<U16, KEY>::iterator iter; - for (iter = mTranslateKeyMap.begin(); iter != mTranslateKeyMap.end(); iter++) + for (auto iter = mTranslateKeyMap.begin(); iter != mTranslateKeyMap.end(); iter++) { mInvTranslateKeyMap[iter->second] = iter->first; } // numpad map - mTranslateNumpadMap[SDLK_KP0] = KEY_PAD_INS; - mTranslateNumpadMap[SDLK_KP1] = KEY_PAD_END; - mTranslateNumpadMap[SDLK_KP2] = KEY_PAD_DOWN; - mTranslateNumpadMap[SDLK_KP3] = KEY_PAD_PGDN; - mTranslateNumpadMap[SDLK_KP4] = KEY_PAD_LEFT; - mTranslateNumpadMap[SDLK_KP5] = KEY_PAD_CENTER; - mTranslateNumpadMap[SDLK_KP6] = KEY_PAD_RIGHT; - mTranslateNumpadMap[SDLK_KP7] = KEY_PAD_HOME; - mTranslateNumpadMap[SDLK_KP8] = KEY_PAD_UP; - mTranslateNumpadMap[SDLK_KP9] = KEY_PAD_PGUP; + mTranslateNumpadMap[SDLK_KP_0] = KEY_PAD_INS; + mTranslateNumpadMap[SDLK_KP_1] = KEY_PAD_END; + mTranslateNumpadMap[SDLK_KP_2] = KEY_PAD_DOWN; + mTranslateNumpadMap[SDLK_KP_3] = KEY_PAD_PGDN; + mTranslateNumpadMap[SDLK_KP_4] = KEY_PAD_LEFT; + mTranslateNumpadMap[SDLK_KP_5] = KEY_PAD_CENTER; + mTranslateNumpadMap[SDLK_KP_6] = KEY_PAD_RIGHT; + mTranslateNumpadMap[SDLK_KP_7] = KEY_PAD_HOME; + mTranslateNumpadMap[SDLK_KP_8] = KEY_PAD_UP; + mTranslateNumpadMap[SDLK_KP_9] = KEY_PAD_PGUP; mTranslateNumpadMap[SDLK_KP_PERIOD] = KEY_PAD_DEL; // build inverse numpad map - for (iter = mTranslateNumpadMap.begin(); + for (auto iter = mTranslateNumpadMap.begin(); iter != mTranslateNumpadMap.end(); iter++) { @@ -154,7 +154,7 @@ LLKeyboardSDL::LLKeyboardSDL() void LLKeyboardSDL::resetMaskKeys() { - SDLMod mask = SDL_GetModState(); + SDL_Keymod mask = SDL_GetModState(); // MBW -- XXX -- This mirrors the operation of the Windows version of resetMaskKeys(). // It looks a bit suspicious, as it won't correct for keys that have been released. @@ -165,7 +165,11 @@ void LLKeyboardSDL::resetMaskKeys() mKeyLevel[KEY_SHIFT] = true; } - if(mask & KMOD_CTRL) + if(mask & (KMOD_CTRL +#ifdef LL_DARWIN + | KMOD_GUI +#endif + )) { mKeyLevel[KEY_CONTROL] = true; } @@ -187,7 +191,11 @@ MASK LLKeyboardSDL::updateModifiers(const U32 mask) out_mask |= MASK_SHIFT; } - if(mask & KMOD_CTRL) + if(mask & (KMOD_CTRL +#ifdef LL_DARWIN + | KMOD_GUI +#endif + )) { out_mask |= MASK_CONTROL; } @@ -201,34 +209,34 @@ MASK LLKeyboardSDL::updateModifiers(const U32 mask) } -static U16 adjustNativekeyFromUnhandledMask(const U16 key, const U32 mask) +static U32 adjustNativekeyFromUnhandledMask(const U32 key, const U32 mask) { // SDL doesn't automatically adjust the keysym according to // whether NUMLOCK is engaged, so we massage the keysym manually. - U16 rtn = key; + U32 rtn = key; if (!(mask & KMOD_NUM)) { switch (key) { - case SDLK_KP_PERIOD: rtn = SDLK_DELETE; break; - case SDLK_KP0: rtn = SDLK_INSERT; break; - case SDLK_KP1: rtn = SDLK_END; break; - case SDLK_KP2: rtn = SDLK_DOWN; break; - case SDLK_KP3: rtn = SDLK_PAGEDOWN; break; - case SDLK_KP4: rtn = SDLK_LEFT; break; - case SDLK_KP6: rtn = SDLK_RIGHT; break; - case SDLK_KP7: rtn = SDLK_HOME; break; - case SDLK_KP8: rtn = SDLK_UP; break; - case SDLK_KP9: rtn = SDLK_PAGEUP; break; + case SDLK_KP_PERIOD: rtn = SDLK_DELETE; break; + case SDLK_KP_0: rtn = SDLK_INSERT; break; + case SDLK_KP_1: rtn = SDLK_END; break; + case SDLK_KP_2: rtn = SDLK_DOWN; break; + case SDLK_KP_3: rtn = SDLK_PAGEDOWN; break; + case SDLK_KP_4: rtn = SDLK_LEFT; break; + case SDLK_KP_6: rtn = SDLK_RIGHT; break; + case SDLK_KP_7: rtn = SDLK_HOME; break; + case SDLK_KP_8: rtn = SDLK_UP; break; + case SDLK_KP_9: rtn = SDLK_PAGEUP; break; } } return rtn; } -bool LLKeyboardSDL::handleKeyDown(const U16 key, const U32 mask) +bool LLKeyboardSDL::handleKeyDown(const U32 key, const U32 mask) { - U16 adjusted_nativekey; + U32 adjusted_nativekey; KEY translated_key = 0; U32 translated_mask = MASK_NONE; bool handled = false; @@ -246,9 +254,9 @@ bool LLKeyboardSDL::handleKeyDown(const U16 key, const U32 mask) } -bool LLKeyboardSDL::handleKeyUp(const U16 key, const U32 mask) +bool LLKeyboardSDL::handleKeyUp(const U32 key, const U32 mask) { - U16 adjusted_nativekey; + U32 adjusted_nativekey; KEY translated_key = 0; U32 translated_mask = MASK_NONE; bool handled = false; @@ -268,16 +276,20 @@ bool LLKeyboardSDL::handleKeyUp(const U16 key, const U32 mask) MASK LLKeyboardSDL::currentMask(bool for_mouse_event) { MASK result = MASK_NONE; - SDLMod mask = SDL_GetModState(); + SDL_Keymod mask = SDL_GetModState(); - if (mask & KMOD_SHIFT) result |= MASK_SHIFT; - if (mask & KMOD_CTRL) result |= MASK_CONTROL; - if (mask & KMOD_ALT) result |= MASK_ALT; + if (mask & KMOD_SHIFT) + result |= MASK_SHIFT; + if (mask & KMOD_CTRL) + result |= MASK_CONTROL; + if (mask & KMOD_ALT) + result |= MASK_ALT; // For keyboard events, consider Meta keys equivalent to Control if (!for_mouse_event) { - if (mask & KMOD_META) result |= MASK_CONTROL; + if (mask & KMOD_GUI) + result |= MASK_CONTROL; } return result; @@ -310,7 +322,7 @@ void LLKeyboardSDL::scanKeyboard() } -bool LLKeyboardSDL::translateNumpadKey( const U16 os_key, KEY *translated_key) +bool LLKeyboardSDL::translateNumpadKey( const U32 os_key, KEY *translated_key) { return translateKey(os_key, translated_key); } @@ -320,5 +332,338 @@ U16 LLKeyboardSDL::inverseTranslateNumpadKey(const KEY translated_key) return inverseTranslateKey(translated_key); } -#endif +enum class WindowsVK : U32 +{ + VK_UNKNOWN = 0, + VK_CANCEL = 0x03, + VK_BACK = 0x08, + VK_TAB = 0x09, + VK_CLEAR = 0x0C, + VK_RETURN = 0x0D, + VK_SHIFT = 0x10, + VK_CONTROL = 0x11, + VK_MENU = 0x12, + VK_PAUSE = 0x13, + VK_CAPITAL = 0x14, + VK_KANA = 0x15, + VK_HANGUL = 0x15, + VK_JUNJA = 0x17, + VK_FINAL = 0x18, + VK_HANJA = 0x19, + VK_KANJI = 0x19, + VK_ESCAPE = 0x1B, + VK_CONVERT = 0x1C, + VK_NONCONVERT = 0x1D, + VK_ACCEPT = 0x1E, + VK_MODECHANGE = 0x1F, + VK_SPACE = 0x20, + VK_PRIOR = 0x21, + VK_NEXT = 0x22, + VK_END = 0x23, + VK_HOME = 0x24, + VK_LEFT = 0x25, + VK_UP = 0x26, + VK_RIGHT = 0x27, + VK_DOWN = 0x28, + VK_SELECT = 0x29, + VK_PRINT = 0x2A, + VK_EXECUTE = 0x2B, + VK_SNAPSHOT = 0x2C, + VK_INSERT = 0x2D, + VK_DELETE = 0x2E, + VK_HELP = 0x2F, + VK_0 = 0x30, + VK_1 = 0x31, + VK_2 = 0x32, + VK_3 = 0x33, + VK_4 = 0x34, + VK_5 = 0x35, + VK_6 = 0x36, + VK_7 = 0x37, + VK_8 = 0x38, + VK_9 = 0x39, + VK_A = 0x41, + VK_B = 0x42, + VK_C = 0x43, + VK_D = 0x44, + VK_E = 0x45, + VK_F = 0x46, + VK_G = 0x47, + VK_H = 0x48, + VK_I = 0x49, + VK_J = 0x4A, + VK_K = 0x4B, + VK_L = 0x4C, + VK_M = 0x4D, + VK_N = 0x4E, + VK_O = 0x4F, + VK_P = 0x50, + VK_Q = 0x51, + VK_R = 0x52, + VK_S = 0x53, + VK_T = 0x54, + VK_U = 0x55, + VK_V = 0x56, + VK_W = 0x57, + VK_X = 0x58, + VK_Y = 0x59, + VK_Z = 0x5A, + VK_LWIN = 0x5B, + VK_RWIN = 0x5C, + VK_APPS = 0x5D, + VK_SLEEP = 0x5F, + VK_NUMPAD0 = 0x60, + VK_NUMPAD1 = 0x61, + VK_NUMPAD2 = 0x62, + VK_NUMPAD3 = 0x63, + VK_NUMPAD4 = 0x64, + VK_NUMPAD5 = 0x65, + VK_NUMPAD6 = 0x66, + VK_NUMPAD7 = 0x67, + VK_NUMPAD8 = 0x68, + VK_NUMPAD9 = 0x69, + VK_MULTIPLY = 0x6A, + VK_ADD = 0x6B, + VK_SEPARATOR = 0x6C, + VK_SUBTRACT = 0x6D, + VK_DECIMAL = 0x6E, + VK_DIVIDE = 0x6F, + VK_F1 = 0x70, + VK_F2 = 0x71, + VK_F3 = 0x72, + VK_F4 = 0x73, + VK_F5 = 0x74, + VK_F6 = 0x75, + VK_F7 = 0x76, + VK_F8 = 0x77, + VK_F9 = 0x78, + VK_F10 = 0x79, + VK_F11 = 0x7A, + VK_F12 = 0x7B, + VK_F13 = 0x7C, + VK_F14 = 0x7D, + VK_F15 = 0x7E, + VK_F16 = 0x7F, + VK_F17 = 0x80, + VK_F18 = 0x81, + VK_F19 = 0x82, + VK_F20 = 0x83, + VK_F21 = 0x84, + VK_F22 = 0x85, + VK_F23 = 0x86, + VK_F24 = 0x87, + VK_NUMLOCK = 0x90, + VK_SCROLL = 0x91, + VK_LSHIFT = 0xA0, + VK_RSHIFT = 0xA1, + VK_LCONTROL = 0xA2, + VK_RCONTROL = 0xA3, + VK_LMENU = 0xA4, + VK_RMENU = 0xA5, + VK_BROWSER_BACK = 0xA6, + VK_BROWSER_FORWARD = 0xA7, + VK_BROWSER_REFRESH = 0xA8, + VK_BROWSER_STOP = 0xA9, + VK_BROWSER_SEARCH = 0xAA, + VK_BROWSER_FAVORITES = 0xAB, + VK_BROWSER_HOME = 0xAC, + VK_VOLUME_MUTE = 0xAD, + VK_VOLUME_DOWN = 0xAE, + VK_VOLUME_UP = 0xAF, + VK_MEDIA_NEXT_TRACK = 0xB0, + VK_MEDIA_PREV_TRACK = 0xB1, + VK_MEDIA_STOP = 0xB2, + VK_MEDIA_PLAY_PAUSE = 0xB3, + VK_MEDIA_LAUNCH_MAIL = 0xB4, + VK_MEDIA_LAUNCH_MEDIA_SELECT = 0xB5, + VK_MEDIA_LAUNCH_APP1 = 0xB6, + VK_MEDIA_LAUNCH_APP2 = 0xB7, + VK_OEM_1 = 0xBA, + VK_OEM_PLUS = 0xBB, + VK_OEM_COMMA = 0xBC, + VK_OEM_MINUS = 0xBD, + VK_OEM_PERIOD = 0xBE, + VK_OEM_2 = 0xBF, + VK_OEM_3 = 0xC0, + VK_OEM_4 = 0xDB, + VK_OEM_5 = 0xDC, + VK_OEM_6 = 0xDD, + VK_OEM_7 = 0xDE, + VK_OEM_8 = 0xDF, + VK_OEM_102 = 0xE2, + VK_PROCESSKEY = 0xE5, + VK_PACKET = 0xE7, + VK_ATTN = 0xF6, + VK_CRSEL = 0xF7, + VK_EXSEL = 0xF8, + VK_EREOF = 0xF9, + VK_PLAY = 0xFA, + VK_ZOOM = 0xFB, + VK_NONAME = 0xFC, + VK_PA1 = 0xFD, + VK_OEM_CLEAR = 0xFE, +}; + +std::map< U32, U32 > mSDL2_to_Win; +std::set< U32 > mIgnoreSDL2Keys; + +U32 LLKeyboardSDL::mapSDL2toWin( U32 aSymbol ) +{ + // <FS:ND> Map SDLK_ virtual keys to Windows VK_ virtual keys. + // Text is handled via unicode input (SDL_TEXTINPUT event) and does not need to be translated into VK_ values as those match already. + if( mSDL2_to_Win.empty() ) + { + mSDL2_to_Win[ SDLK_BACKSPACE ] = (U32)WindowsVK::VK_BACK; + mSDL2_to_Win[ SDLK_TAB ] = (U32)WindowsVK::VK_TAB; + mSDL2_to_Win[ 12 ] = (U32)WindowsVK::VK_CLEAR; + mSDL2_to_Win[ SDLK_RETURN ] = (U32)WindowsVK::VK_RETURN; + mSDL2_to_Win[ 19 ] = (U32)WindowsVK::VK_PAUSE; + mSDL2_to_Win[ SDLK_ESCAPE ] = (U32)WindowsVK::VK_ESCAPE; + mSDL2_to_Win[ SDLK_SPACE ] = (U32)WindowsVK::VK_SPACE; + mSDL2_to_Win[ SDLK_QUOTE ] = (U32)WindowsVK::VK_OEM_7; + mSDL2_to_Win[ SDLK_COMMA ] = (U32)WindowsVK::VK_OEM_COMMA; + mSDL2_to_Win[ SDLK_MINUS ] = (U32)WindowsVK::VK_OEM_MINUS; + mSDL2_to_Win[ SDLK_PERIOD ] = (U32)WindowsVK::VK_OEM_PERIOD; + mSDL2_to_Win[ SDLK_SLASH ] = (U32)WindowsVK::VK_OEM_2; + + mSDL2_to_Win[ SDLK_0 ] = (U32)WindowsVK::VK_0; + mSDL2_to_Win[ SDLK_1 ] = (U32)WindowsVK::VK_1; + mSDL2_to_Win[ SDLK_2 ] = (U32)WindowsVK::VK_2; + mSDL2_to_Win[ SDLK_3 ] = (U32)WindowsVK::VK_3; + mSDL2_to_Win[ SDLK_4 ] = (U32)WindowsVK::VK_4; + mSDL2_to_Win[ SDLK_5 ] = (U32)WindowsVK::VK_5; + mSDL2_to_Win[ SDLK_6 ] = (U32)WindowsVK::VK_6; + mSDL2_to_Win[ SDLK_7 ] = (U32)WindowsVK::VK_7; + mSDL2_to_Win[ SDLK_8 ] = (U32)WindowsVK::VK_8; + mSDL2_to_Win[ SDLK_9 ] = (U32)WindowsVK::VK_9; + + mSDL2_to_Win[ SDLK_SEMICOLON ] = (U32)WindowsVK::VK_OEM_1; + mSDL2_to_Win[ SDLK_LESS ] = (U32)WindowsVK::VK_OEM_102; + mSDL2_to_Win[ SDLK_EQUALS ] = (U32)WindowsVK::VK_OEM_PLUS; + mSDL2_to_Win[ SDLK_KP_EQUALS ] = (U32)WindowsVK::VK_OEM_PLUS; + + mSDL2_to_Win[ SDLK_LEFTBRACKET ] = (U32)WindowsVK::VK_OEM_4; + mSDL2_to_Win[ SDLK_BACKSLASH ] = (U32)WindowsVK::VK_OEM_5; + mSDL2_to_Win[ SDLK_RIGHTBRACKET ] = (U32)WindowsVK::VK_OEM_6; + mSDL2_to_Win[ SDLK_BACKQUOTE ] = (U32)WindowsVK::VK_OEM_8; + + mSDL2_to_Win[ SDLK_a ] = (U32)WindowsVK::VK_A; + mSDL2_to_Win[ SDLK_b ] = (U32)WindowsVK::VK_B; + mSDL2_to_Win[ SDLK_c ] = (U32)WindowsVK::VK_C; + mSDL2_to_Win[ SDLK_d ] = (U32)WindowsVK::VK_D; + mSDL2_to_Win[ SDLK_e ] = (U32)WindowsVK::VK_E; + mSDL2_to_Win[ SDLK_f ] = (U32)WindowsVK::VK_F; + mSDL2_to_Win[ SDLK_g ] = (U32)WindowsVK::VK_G; + mSDL2_to_Win[ SDLK_h ] = (U32)WindowsVK::VK_H; + mSDL2_to_Win[ SDLK_i ] = (U32)WindowsVK::VK_I; + mSDL2_to_Win[ SDLK_j ] = (U32)WindowsVK::VK_J; + mSDL2_to_Win[ SDLK_k ] = (U32)WindowsVK::VK_K; + mSDL2_to_Win[ SDLK_l ] = (U32)WindowsVK::VK_L; + mSDL2_to_Win[ SDLK_m ] = (U32)WindowsVK::VK_M; + mSDL2_to_Win[ SDLK_n ] = (U32)WindowsVK::VK_N; + mSDL2_to_Win[ SDLK_o ] = (U32)WindowsVK::VK_O; + mSDL2_to_Win[ SDLK_p ] = (U32)WindowsVK::VK_P; + mSDL2_to_Win[ SDLK_q ] = (U32)WindowsVK::VK_Q; + mSDL2_to_Win[ SDLK_r ] = (U32)WindowsVK::VK_R; + mSDL2_to_Win[ SDLK_s ] = (U32)WindowsVK::VK_S; + mSDL2_to_Win[ SDLK_t ] = (U32)WindowsVK::VK_T; + mSDL2_to_Win[ SDLK_u ] = (U32)WindowsVK::VK_U; + mSDL2_to_Win[ SDLK_v ] = (U32)WindowsVK::VK_V; + mSDL2_to_Win[ SDLK_w ] = (U32)WindowsVK::VK_W; + mSDL2_to_Win[ SDLK_x ] = (U32)WindowsVK::VK_X; + mSDL2_to_Win[ SDLK_y ] = (U32)WindowsVK::VK_Y; + mSDL2_to_Win[ SDLK_z ] = (U32)WindowsVK::VK_Z; + + mSDL2_to_Win[ SDLK_DELETE ] = (U32)WindowsVK::VK_DELETE; + + + mSDL2_to_Win[ SDLK_NUMLOCKCLEAR ] = (U32)WindowsVK::VK_NUMLOCK; + mSDL2_to_Win[ SDLK_SCROLLLOCK ] = (U32)WindowsVK::VK_SCROLL; + + mSDL2_to_Win[ SDLK_HELP ] = (U32)WindowsVK::VK_HELP; + mSDL2_to_Win[ SDLK_PRINTSCREEN ] = (U32)WindowsVK::VK_SNAPSHOT; + mSDL2_to_Win[ SDLK_CANCEL ] = (U32)WindowsVK::VK_CANCEL; + mSDL2_to_Win[ SDLK_APPLICATION ] = (U32)WindowsVK::VK_APPS; + + mSDL2_to_Win[ SDLK_UNKNOWN ] = (U32)WindowsVK::VK_UNKNOWN; + mSDL2_to_Win[ SDLK_BACKSPACE ] = (U32)WindowsVK::VK_BACK; + mSDL2_to_Win[ SDLK_TAB ] = (U32)WindowsVK::VK_TAB; + mSDL2_to_Win[ SDLK_CLEAR ] = (U32)WindowsVK::VK_CLEAR; + mSDL2_to_Win[ SDLK_RETURN ] = (U32)WindowsVK::VK_RETURN; + mSDL2_to_Win[ SDLK_PAUSE ] = (U32)WindowsVK::VK_PAUSE; + mSDL2_to_Win[ SDLK_ESCAPE ] = (U32)WindowsVK::VK_ESCAPE; + mSDL2_to_Win[ SDLK_DELETE ] = (U32)WindowsVK::VK_DELETE; + + mSDL2_to_Win[ SDLK_KP_PERIOD ] = (U32)WindowsVK::VK_OEM_PERIOD; // VK_DECIMAL? + mSDL2_to_Win[ SDLK_KP_DIVIDE ] = (U32)WindowsVK::VK_DIVIDE; + mSDL2_to_Win[ SDLK_KP_MULTIPLY] = (U32)WindowsVK::VK_MULTIPLY; + mSDL2_to_Win[ SDLK_KP_MINUS ] = (U32)WindowsVK::VK_OEM_MINUS; // VK_SUBSTRACT? + mSDL2_to_Win[ SDLK_KP_PLUS ] = (U32)WindowsVK::VK_OEM_PLUS; // VK_ADD? + mSDL2_to_Win[ SDLK_KP_ENTER ] = (U32)WindowsVK::VK_RETURN; + mSDL2_to_Win[ SDLK_KP_0 ] = (U32)WindowsVK::VK_NUMPAD0; + mSDL2_to_Win[ SDLK_KP_1 ] = (U32)WindowsVK::VK_NUMPAD1; + mSDL2_to_Win[ SDLK_KP_2 ] = (U32)WindowsVK::VK_NUMPAD2; + mSDL2_to_Win[ SDLK_KP_3 ] = (U32)WindowsVK::VK_NUMPAD3; + mSDL2_to_Win[ SDLK_KP_4 ] = (U32)WindowsVK::VK_NUMPAD4; + mSDL2_to_Win[ SDLK_KP_5 ] = (U32)WindowsVK::VK_NUMPAD5; + mSDL2_to_Win[ SDLK_KP_6 ] = (U32)WindowsVK::VK_NUMPAD6; + mSDL2_to_Win[ SDLK_KP_7 ] = (U32)WindowsVK::VK_NUMPAD7; + mSDL2_to_Win[ SDLK_KP_8 ] = (U32)WindowsVK::VK_NUMPAD8; + mSDL2_to_Win[ SDLK_KP_9 ] = (U32)WindowsVK::VK_NUMPAD9; + + // ? + + mSDL2_to_Win[ SDLK_UP ] = (U32)WindowsVK::VK_UP; + mSDL2_to_Win[ SDLK_DOWN ] = (U32)WindowsVK::VK_DOWN; + mSDL2_to_Win[ SDLK_RIGHT ] = (U32)WindowsVK::VK_RIGHT; + mSDL2_to_Win[ SDLK_LEFT ] = (U32)WindowsVK::VK_LEFT; + mSDL2_to_Win[ SDLK_INSERT ] = (U32)WindowsVK::VK_INSERT; + mSDL2_to_Win[ SDLK_HOME ] = (U32)WindowsVK::VK_HOME; + mSDL2_to_Win[ SDLK_END ] = (U32)WindowsVK::VK_END; + mSDL2_to_Win[ SDLK_PAGEUP ] = (U32)WindowsVK::VK_PRIOR; + mSDL2_to_Win[ SDLK_PAGEDOWN ] = (U32)WindowsVK::VK_NEXT; + mSDL2_to_Win[ SDLK_F1 ] = (U32)WindowsVK::VK_F1; + mSDL2_to_Win[ SDLK_F2 ] = (U32)WindowsVK::VK_F2; + mSDL2_to_Win[ SDLK_F3 ] = (U32)WindowsVK::VK_F3; + mSDL2_to_Win[ SDLK_F4 ] = (U32)WindowsVK::VK_F4; + mSDL2_to_Win[ SDLK_F5 ] = (U32)WindowsVK::VK_F5; + mSDL2_to_Win[ SDLK_F6 ] = (U32)WindowsVK::VK_F6; + mSDL2_to_Win[ SDLK_F7 ] = (U32)WindowsVK::VK_F7; + mSDL2_to_Win[ SDLK_F8 ] = (U32)WindowsVK::VK_F8; + mSDL2_to_Win[ SDLK_F9 ] = (U32)WindowsVK::VK_F9; + mSDL2_to_Win[ SDLK_F10 ] = (U32)WindowsVK::VK_F10; + mSDL2_to_Win[ SDLK_F11 ] = (U32)WindowsVK::VK_F11; + mSDL2_to_Win[ SDLK_F12 ] = (U32)WindowsVK::VK_F12; + mSDL2_to_Win[ SDLK_F13 ] = (U32)WindowsVK::VK_F13; + mSDL2_to_Win[ SDLK_F14 ] = (U32)WindowsVK::VK_F14; + mSDL2_to_Win[ SDLK_F15 ] = (U32)WindowsVK::VK_F15; + mSDL2_to_Win[ SDLK_CAPSLOCK ] = (U32)WindowsVK::VK_CAPITAL; + mSDL2_to_Win[ SDLK_RSHIFT ] = (U32)WindowsVK::VK_SHIFT; + mSDL2_to_Win[ SDLK_LSHIFT ] = (U32)WindowsVK::VK_SHIFT; + mSDL2_to_Win[ SDLK_RCTRL ] = (U32)WindowsVK::VK_CONTROL; + mSDL2_to_Win[ SDLK_LCTRL ] = (U32)WindowsVK::VK_CONTROL; + mSDL2_to_Win[ SDLK_RALT ] = (U32)WindowsVK::VK_MENU; + mSDL2_to_Win[ SDLK_LALT ] = (U32)WindowsVK::VK_MENU; + + mSDL2_to_Win[ SDLK_MENU ] = (U32)WindowsVK::VK_MENU; + + // VK_MODECHANGE ? + // mSDL2_to_Win[ SDLK_MODE ] = (U32)WindowsVK::VK_MODE; + + // ? + // mSDL2_to_Win[ SDLK_SYSREQ ] = (U32)WindowsVK::VK_SYSREQ; + // mSDL2_to_Win[ SDLK_POWER ] = (U32)WindowsVK::VK_POWER; + // mSDL2_to_Win[ SDLK_UNDO ] = (U32)WindowsVK::VK_UNDO; + // mSDL2_to_Win[ SDLK_KP_EQUALS ] = (U32)WindowsVK::VK_EQUALS; + // mSDL2_to_Win[ 311 ] = (U32)WindowsVK::VK_LWIN; + // mSDL2_to_Win[ 312 ] = (U32)WindowsVK::VK_RWIN; + // mSDL2_to_Win[ SDLK_COLON ] = ? + } + + auto itr = mSDL2_to_Win.find( aSymbol ); + if( itr != mSDL2_to_Win.end() ) + return itr->second; + + return aSymbol; +} diff --git a/indra/llwindow/llkeyboardsdl.h b/indra/llwindow/llkeyboardsdl.h index fd348b28f2..3af098c4d1 100644 --- a/indra/llwindow/llkeyboardsdl.h +++ b/indra/llwindow/llkeyboardsdl.h @@ -1,8 +1,7 @@ /** - * @file llkeyboardsdl.h - * @brief Handler for assignable key bindings + * @author This module has many fathers, and it shows. * - * $LicenseInfo:firstyear=2004&license=viewerlgpl$ + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. * @@ -24,11 +23,14 @@ * $/LicenseInfo$ */ -#ifndef LL_LLKEYBOARDSDL_H -#define LL_LLKEYBOARDSDL_H +#ifndef LL_LLKEYBOARDSDL2_H +#define LL_LLKEYBOARDSDL2_H #include "llkeyboard.h" -#include "SDL/SDL.h" +#if !defined(__i386__) && !defined(__x86_64__) +#define SDL_DISABLE_IMMINTRIN_H +#endif +#include "SDL2/SDL.h" class LLKeyboardSDL : public LLKeyboard { @@ -36,8 +38,8 @@ public: LLKeyboardSDL(); /*virtual*/ ~LLKeyboardSDL() {}; - /*virtual*/ bool handleKeyUp(const U16 key, MASK mask); - /*virtual*/ bool handleKeyDown(const U16 key, MASK mask); + /*virtual*/ bool handleKeyUp(const U32 key, MASK mask); + /*virtual*/ bool handleKeyDown(const U32 key, MASK mask); /*virtual*/ void resetMaskKeys(); /*virtual*/ MASK currentMask(bool for_mouse_event); /*virtual*/ void scanKeyboard(); @@ -45,11 +47,14 @@ public: protected: MASK updateModifiers(const U32 mask); void setModifierKeyLevel( KEY key, bool new_state ); - bool translateNumpadKey( const U16 os_key, KEY *translated_key ); + bool translateNumpadKey( const U32 os_key, KEY *translated_key ); U16 inverseTranslateNumpadKey(const KEY translated_key); private: - std::map<U16, KEY> mTranslateNumpadMap; // special map for translating OS keys to numpad keys - std::map<KEY, U16> mInvTranslateNumpadMap; // inverse of the above + std::map<U32, KEY> mTranslateNumpadMap; // special map for translating OS keys to numpad keys + std::map<KEY, U32> mInvTranslateNumpadMap; // inverse of the above + +public: + static U32 mapSDL2toWin( U32 ); }; #endif diff --git a/indra/llwindow/llwindow.cpp b/indra/llwindow/llwindow.cpp index 56c393be0f..325f1280b9 100644 --- a/indra/llwindow/llwindow.cpp +++ b/indra/llwindow/llwindow.cpp @@ -76,7 +76,7 @@ S32 OSMessageBox(const std::string& text, const std::string& caption, U32 type) return OSBTN_OK; #elif LL_WINDOWS result = OSMessageBoxWin32(text, caption, type); -#elif LL_DARWIN +#elif LL_DARWIN && !LL_SDL result = OSMessageBoxMacOSX(text, caption, type); #elif LL_SDL result = OSMessageBoxSDL(text, caption, type); @@ -261,7 +261,7 @@ std::vector<std::string> LLWindow::getDynamicFallbackFontList() { #if LL_WINDOWS return LLWindowWin32::getDynamicFallbackFontList(); -#elif LL_DARWIN +#elif LL_DARWIN && !LL_SDL return LLWindowMacOSX::getDynamicFallbackFontList(); #elif LL_SDL return LLWindowSDL::getDynamicFallbackFontList(); @@ -275,7 +275,7 @@ std::vector<std::string> LLWindow::getDisplaysResolutionList() { #if LL_WINDOWS return LLWindowWin32::getDisplaysResolutionList(); -#elif LL_DARWIN +#elif LL_DARWIN && !LL_SDL return LLWindowMacOSX::getDisplaysResolutionList(); #else return std::vector<std::string>(); @@ -346,7 +346,7 @@ LLSplashScreen *LLSplashScreen::create() return 0; #elif LL_WINDOWS return new LLSplashScreenWin32; -#elif LL_DARWIN +#elif LL_DARWIN && !LL_SDL return new LLSplashScreenMacOSX; #else #error("LLSplashScreen not implemented on this platform!") @@ -361,7 +361,7 @@ void LLSplashScreen::show() { #if LL_WINDOWS && !LL_MESA_HEADLESS gSplashScreenp = new LLSplashScreenWin32; -#elif LL_DARWIN +#elif LL_DARWIN && !LL_SDL gSplashScreenp = new LLSplashScreenMacOSX; #endif if (gSplashScreenp) @@ -411,7 +411,7 @@ LLWindow* LLWindowManager::createWindow( U32 max_cores, F32 max_gl_version) { - LLWindow* new_window; + LLWindow* new_window = nullptr; if (use_gl) { diff --git a/indra/llwindow/llwindowcallbacks.cpp b/indra/llwindow/llwindowcallbacks.cpp index c160382c17..624ecd5030 100644 --- a/indra/llwindow/llwindowcallbacks.cpp +++ b/indra/llwindow/llwindowcallbacks.cpp @@ -52,6 +52,10 @@ bool LLWindowCallbacks::handleUnicodeChar(llwchar uni_char, MASK mask) return false; } +bool LLWindowCallbacks::handleUnicodeString(char *uni_str, bool editing) +{ + return FALSE; +} bool LLWindowCallbacks::handleMouseDown(LLWindow *window, const LLCoordGL pos, MASK mask) { diff --git a/indra/llwindow/llwindowcallbacks.h b/indra/llwindow/llwindowcallbacks.h index 63b585231f..74660e1705 100644 --- a/indra/llwindow/llwindowcallbacks.h +++ b/indra/llwindow/llwindowcallbacks.h @@ -37,6 +37,7 @@ public: virtual bool handleTranslatedKeyUp(KEY key, MASK mask); virtual void handleScanKey(KEY key, bool key_down, bool key_up, bool key_level); virtual bool handleUnicodeChar(llwchar uni_char, MASK mask); + virtual bool handleUnicodeString(char *uni_str, bool editing); virtual bool handleMouseDown(LLWindow *window, LLCoordGL pos, MASK mask); virtual bool handleMouseUp(LLWindow *window, LLCoordGL pos, MASK mask); diff --git a/indra/llwindow/llwindowmacosx.cpp b/indra/llwindow/llwindowmacosx.cpp index 80001b14ee..3cfc9d7c84 100644 --- a/indra/llwindow/llwindowmacosx.cpp +++ b/indra/llwindow/llwindowmacosx.cpp @@ -38,6 +38,7 @@ #include "lldir.h" #include "indra_constants.h" + #include <OpenGL/OpenGL.h> #include <Carbon/Carbon.h> #include <CoreServices/CoreServices.h> diff --git a/indra/llwindow/llwindowsdl.cpp b/indra/llwindow/llwindowsdl.cpp index 7433ad6bd2..8c90f917b8 100644 --- a/indra/llwindow/llwindowsdl.cpp +++ b/indra/llwindow/llwindowsdl.cpp @@ -25,8 +25,6 @@ * $/LicenseInfo$ */ -#if LL_SDL - #include "linden_common.h" #include "llwindowsdl.h" @@ -40,23 +38,23 @@ #include "lldir.h" #include "llfindlocale.h" -#if LL_GTK -extern "C" { -# include "gtk/gtk.h" -} -#include <locale.h> -#endif // LL_GTK +#ifdef LL_GLIB +#include <glib.h> +#endif extern "C" { # include "fontconfig/fontconfig.h" } -#if LL_LINUX +#if LL_LINUX || __FreeBSD__ // not necessarily available on random SDL platforms, so #if LL_LINUX // for execv(), waitpid(), fork() # include <unistd.h> # include <sys/types.h> # include <sys/wait.h> +# define GLX_GLXEXT_PROTOTYPES 1 +# include <GL/glx.h> +# include <stdio.h> #endif // LL_LINUX extern bool gDebugWindowProc; @@ -66,6 +64,43 @@ const S32 MAX_NUM_RESOLUTIONS = 200; // static variable for ATI mouse cursor crash work-around: static bool ATIbug = false; +#if LL_DARWIN + +#include <OpenGL/OpenGL.h> +#include <CoreGraphics/CGDirectDisplay.h> +#include <CoreServices/CoreServices.h> + +bool gHiDPISupport = true; + +namespace +{ + struct NativeKeyEventData { + enum EventType { + KEYUNKNOWN, + KEYUP, + KEYDOWN, + KEYCHAR + }; + + EventType mKeyEvent = KEYUNKNOWN; + uint32_t mEventType = 0; + uint32_t mEventModifiers = 0; + uint32_t mEventKeyCode = 0; + uint32_t mEventChars = 0; + uint32_t mEventUnmodChars = 0; + bool mEventRepeat = false; + } *mRawKeyEvent = NULL; +} +// +// LLWindowMacOSX +// + +bool LLWindowSDL::sUseMultGL = false; + +#endif + +bool hasHIDPI = 0; + // // LLWindowSDL // @@ -97,108 +132,291 @@ void maybe_unlock_display(void) } -#if LL_GTK -// Lazily initialize and check the runtime GTK version for goodness. +#if LL_X11 // static -bool LLWindowSDL::ll_try_gtk_init(void) +Window LLWindowSDL::get_SDL_XWindowID(void) +{ + if (gWindowImplementation) { + return gWindowImplementation->mSDL_XWindowID; + } + return None; +} + +//static +Display* LLWindowSDL::get_SDL_Display(void) +{ + if (gWindowImplementation) { + return gWindowImplementation->mSDL_Display; + } + return NULL; +} +#endif // LL_X11 + +#if LL_X11 + +// Clipboard handing via native X11, base on the implementation in Cool VL by Henri Beauchamp + +namespace { - static bool done_gtk_diag = false; - static bool gtk_is_good = false; - static bool done_setlocale = false; - static bool tried_gtk_init = false; + std::array<Atom, 3> gSupportedAtoms; - if (!done_setlocale) + Atom XA_CLIPBOARD; + Atom XA_TARGETS; + Atom PVT_PASTE_BUFFER; + long const MAX_PASTE_BUFFER_SIZE = 16383; + + void filterSelectionRequest( XEvent aEvent ) { - LL_INFOS() << "Starting GTK Initialization." << LL_ENDL; - maybe_lock_display(); - gtk_disable_setlocale(); - maybe_unlock_display(); - done_setlocale = true; + auto *display = LLWindowSDL::getSDLDisplay(); + auto &request = aEvent.xselectionrequest; + + XSelectionEvent reply { SelectionNotify, aEvent.xany.serial, aEvent.xany.send_event, display, + request.requestor, request.selection, request.target, + request.property,request.time }; + + if (request.target == XA_TARGETS) + { + XChangeProperty(display, request.requestor, request.property, + XA_ATOM, 32, PropModeReplace, + (unsigned char *) &gSupportedAtoms.front(), gSupportedAtoms.size()); + } + else if (std::find(gSupportedAtoms.begin(), gSupportedAtoms.end(), request.target) != + gSupportedAtoms.end()) + { + std::string utf8; + if (request.selection == XA_PRIMARY) + utf8 = wstring_to_utf8str(gWindowImplementation->getPrimaryText()); + else + utf8 = wstring_to_utf8str(gWindowImplementation->getSecondaryText()); + + XChangeProperty(display, request.requestor, request.property, + request.target, 8, PropModeReplace, + (unsigned char *) utf8.c_str(), utf8.length()); + } + else if (request.selection == XA_CLIPBOARD) + { + // Did not have what they wanted, so no property set + reply.property = None; + } + else + return; + + XSendEvent(request.display, request.requestor, False, NoEventMask, (XEvent *) &reply); + XSync(display, False); } - if (!tried_gtk_init) + void filterSelectionClearRequest( XEvent aEvent ) { - tried_gtk_init = true; - if (!g_thread_supported ()) g_thread_init (NULL); - maybe_lock_display(); - gtk_is_good = gtk_init_check(NULL, NULL); - maybe_unlock_display(); - if (!gtk_is_good) - LL_WARNS() << "GTK Initialization failed." << LL_ENDL; + auto &request = aEvent.xselectionrequest; + if (request.selection == XA_PRIMARY) + gWindowImplementation->clearPrimaryText(); + else if (request.selection == XA_CLIPBOARD) + gWindowImplementation->clearSecondaryText(); } - if (gtk_is_good && !done_gtk_diag) + int x11_clipboard_filter(void*, SDL_Event *evt) { - LL_INFOS() << "GTK Initialized." << LL_ENDL; - LL_INFOS() << "- Compiled against GTK version " - << GTK_MAJOR_VERSION << "." - << GTK_MINOR_VERSION << "." - << GTK_MICRO_VERSION << LL_ENDL; - LL_INFOS() << "- Running against GTK version " - << gtk_major_version << "." - << gtk_minor_version << "." - << gtk_micro_version << LL_ENDL; + Display *display = LLWindowSDL::getSDLDisplay(); + if (!display) + return 1; + + if (evt->type != SDL_SYSWMEVENT) + return 1; + + auto xevent = evt->syswm.msg->msg.x11.event; + + if (xevent.type == SelectionRequest) + filterSelectionRequest( xevent ); + else if (xevent.type == SelectionClear) + filterSelectionClearRequest( xevent ); + return 1; + } + + bool grab_property(Display* display, Window window, Atom selection, Atom target) + { + if( !display ) + return false; + maybe_lock_display(); - const gchar* gtk_warning = gtk_check_version( - GTK_MAJOR_VERSION, - GTK_MINOR_VERSION, - GTK_MICRO_VERSION); + + XDeleteProperty(display, window, PVT_PASTE_BUFFER); + XFlush(display); + + XConvertSelection(display, selection, target, PVT_PASTE_BUFFER, window, CurrentTime); + + // Unlock the connection so that the SDL event loop may function maybe_unlock_display(); - if (gtk_warning) + + const auto start{ SDL_GetTicks() }; + const auto end{ start + 1000 }; + + XEvent xevent {}; + bool response = false; + + do { - LL_WARNS() << "- GTK COMPATIBILITY WARNING: " << - gtk_warning << LL_ENDL; - gtk_is_good = false; - } else { - LL_INFOS() << "- GTK version is good." << LL_ENDL; - } + SDL_Event event {}; + + // Wait for an event + SDL_WaitEvent(&event); + + // If the event is a window manager event + if (event.type == SDL_SYSWMEVENT) + { + xevent = event.syswm.msg->msg.x11.event; + + if (xevent.type == SelectionNotify && xevent.xselection.requestor == window) + response = true; + } + } while (!response && SDL_GetTicks() < end ); + + return response && xevent.xselection.property != None; + } +} + +void LLWindowSDL::initialiseX11Clipboard() +{ + if (!mSDL_Display) + return; + + SDL_EventState(SDL_SYSWMEVENT, SDL_ENABLE); + SDL_SetEventFilter(x11_clipboard_filter, nullptr); + + maybe_lock_display(); + + XA_CLIPBOARD = XInternAtom(mSDL_Display, "CLIPBOARD", False); + + gSupportedAtoms[0] = XInternAtom(mSDL_Display, "UTF8_STRING", False); + gSupportedAtoms[1] = XInternAtom(mSDL_Display, "COMPOUND_TEXT", False); + gSupportedAtoms[2] = XA_STRING; + + // TARGETS atom + XA_TARGETS = XInternAtom(mSDL_Display, "TARGETS", False); + + // SL_PASTE_BUFFER atom + PVT_PASTE_BUFFER = XInternAtom(mSDL_Display, "FS_PASTE_BUFFER", False); + + maybe_unlock_display(); +} + +bool LLWindowSDL::getSelectionText( Atom aSelection, Atom aType, LLWString &text ) +{ + if( !mSDL_Display ) + return false; + + if( !grab_property(mSDL_Display, mSDL_XWindowID, aSelection,aType ) ) + return false; - done_gtk_diag = true; + maybe_lock_display(); + + Atom type; + int format{}; + unsigned long len{},remaining {}; + unsigned char* data = nullptr; + int res = XGetWindowProperty(mSDL_Display, mSDL_XWindowID, + PVT_PASTE_BUFFER, 0, MAX_PASTE_BUFFER_SIZE, False, + AnyPropertyType, &type, &format, &len, + &remaining, &data); + if (data && len) + { + text = LLWString( + utf8str_to_wstring(reinterpret_cast< char const *>( data ) ) + ); + XFree(data); } - return gtk_is_good; + maybe_unlock_display(); + return res == Success; } -#endif // LL_GTK +bool LLWindowSDL::getSelectionText(Atom selection, LLWString& text) +{ + if (!mSDL_Display) + return false; -#if LL_X11 -// static -Window LLWindowSDL::get_SDL_XWindowID(void) + maybe_lock_display(); + + Window owner = XGetSelectionOwner(mSDL_Display, selection); + if (owner == None) + { + if (selection == XA_PRIMARY) + { + owner = DefaultRootWindow(mSDL_Display); + selection = XA_CUT_BUFFER0; + } + else + { + maybe_unlock_display(); + return false; + } + } + + maybe_unlock_display(); + + for( Atom atom : gSupportedAtoms ) + { + if(getSelectionText(selection, atom, text ) ) + return true; + } + + return false; +} + +bool LLWindowSDL::setSelectionText(Atom selection, const LLWString& text) { - if (gWindowImplementation) { - return gWindowImplementation->mSDL_XWindowID; + maybe_lock_display(); + + if (selection == XA_PRIMARY) + { + std::string utf8 = wstring_to_utf8str(text); + XStoreBytes(mSDL_Display, utf8.c_str(), utf8.length() + 1); + mPrimaryClipboard = text; } - return None; + else + mSecondaryClipboard = text; + + XSetSelectionOwner(mSDL_Display, selection, mSDL_XWindowID, CurrentTime); + + auto owner = XGetSelectionOwner(mSDL_Display, selection); + + maybe_unlock_display(); + + return owner == mSDL_XWindowID; } -//static -Display* LLWindowSDL::get_SDL_Display(void) +Display* LLWindowSDL::getSDLDisplay() { - if (gWindowImplementation) { + if (gWindowImplementation) return gWindowImplementation->mSDL_Display; - } - return NULL; + return nullptr; } -#endif // LL_X11 + +#endif LLWindowSDL::LLWindowSDL(LLWindowCallbacks* callbacks, - const std::string& title, S32 x, S32 y, S32 width, - S32 height, U32 flags, - bool fullscreen, bool clearBg, - bool disable_vsync, bool use_gl, - bool ignore_pixel_depth, U32 fsaa_samples) - : LLWindow(callbacks, fullscreen, flags), - Lock_Display(NULL), - Unlock_Display(NULL), mGamma(1.0f) + const std::string& title, S32 x, S32 y, S32 width, + S32 height, U32 flags, + bool fullscreen, bool clearBg, + bool disable_vsync, bool use_gl, + bool ignore_pixel_depth, U32 fsaa_samples) + : LLWindow(callbacks, fullscreen, flags), + Lock_Display(NULL), + //Unlock_Display(NULL), mGamma(1.0f) + Unlock_Display(NULL), mGamma(1.0f) { // Initialize the keyboard gKeyboard = new LLKeyboardSDL(); gKeyboard->setCallbacks(callbacks); // Note that we can't set up key-repeat until after SDL has init'd video +#if LL_DARWIN + hasHIDPI = gHiDPISupport; +#endif + // Ignore use_gl for now, only used for drones on PC mWindow = NULL; + mContext = {}; mNeedsResize = false; mOverrideAspectRatio = 0.f; mGrabbyKeyFlags = 0; @@ -212,13 +430,6 @@ LLWindowSDL::LLWindowSDL(LLWindowCallbacks* callbacks, mSDL_Display = NULL; #endif // LL_X11 -#if LL_GTK - // We MUST be the first to initialize GTK so that GTK doesn't get badly - // initialized with a non-C locale and cause lots of serious random - // weirdness. - ll_try_gtk_init(); -#endif // LL_GTK - // Assume 4:3 aspect ratio until we know better mOriginalAspectRatio = 1024.0 / 768.0; @@ -244,9 +455,9 @@ LLWindowSDL::LLWindowSDL(LLWindowCallbacks* callbacks, #if LL_X11 mFlashing = false; + initialiseX11Clipboard(); #endif // LL_X11 - mKeyScanCode = 0; mKeyVirtualKey = 0; mKeyModifiers = KMOD_NONE; } @@ -258,10 +469,10 @@ static SDL_Surface *Load_BMP_Resource(const char *basename) // Figure out where our BMP is living on the disk snprintf(path_buffer, PATH_BUFFER_SIZE-1, "%s%sres-sdl%s%s", - gDirUtilp->getAppRODataDir().c_str(), - gDirUtilp->getDirDelimiter().c_str(), - gDirUtilp->getDirDelimiter().c_str(), - basename); + gDirUtilp->getAppRODataDir().c_str(), + gDirUtilp->getDirDelimiter().c_str(), + gDirUtilp->getDirDelimiter().c_str(), + basename); path_buffer[PATH_BUFFER_SIZE-1] = '\0'; return SDL_LoadBMP(path_buffer); @@ -348,7 +559,7 @@ static int x11_detect_VRAM_kb() if (fp) { LL_INFOS() << "Looking in " << fname - << " for VRAM info..." << LL_ENDL; + << " for VRAM info..." << LL_ENDL; rtn = x11_detect_VRAM_kb_fp(fp, ": VideoRAM: "); fclose(fp); if (0 == rtn) @@ -373,7 +584,7 @@ static int x11_detect_VRAM_kb() else { LL_INFOS() << "Could not open " << fname - << " - skipped." << LL_ENDL; + << " - skipped." << LL_ENDL; // Try old XFree86 log otherwise fname = x_log_location; fname += "XFree86."; @@ -383,7 +594,7 @@ static int x11_detect_VRAM_kb() if (fp) { LL_INFOS() << "Looking in " << fname - << " for VRAM info..." << LL_ENDL; + << " for VRAM info..." << LL_ENDL; rtn = x11_detect_VRAM_kb_fp(fp, ": VideoRAM: "); fclose(fp); if (0 == rtn) @@ -399,95 +610,170 @@ static int x11_detect_VRAM_kb() else { LL_INFOS() << "Could not open " << fname - << " - skipped." << LL_ENDL; + << " - skipped." << LL_ENDL; } } return rtn; } #endif // LL_X11 +void LLWindowSDL::setTitle(const std::string title) +{ + SDL_SetWindowTitle( mWindow, title.c_str() ); +} + +void LLWindowSDL::tryFindFullscreenSize( int &width, int &height ) +{ + LL_INFOS() << "createContext: setting up fullscreen " << width << "x" << height << LL_ENDL; + + // If the requested width or height is 0, find the best default for the monitor. + if((width == 0) || (height == 0)) + { + // Scan through the list of modes, looking for one which has: + // height between 700 and 800 + // aspect ratio closest to the user's original mode + S32 resolutionCount = 0; + LLWindowResolution *resolutionList = getSupportedResolutions(resolutionCount); + + if(resolutionList != NULL) + { + F32 closestAspect = 0; + U32 closestHeight = 0; + U32 closestWidth = 0; + int i; + + LL_INFOS() << "createContext: searching for a display mode, original aspect is " << mOriginalAspectRatio << LL_ENDL; + + for(i=0; i < resolutionCount; i++) + { + F32 aspect = (F32)resolutionList[i].mWidth / (F32)resolutionList[i].mHeight; + + LL_INFOS() << "createContext: width " << resolutionList[i].mWidth << " height " << resolutionList[i].mHeight << " aspect " << aspect << LL_ENDL; + + if( (resolutionList[i].mHeight >= 700) && (resolutionList[i].mHeight <= 800) && + (fabs(aspect - mOriginalAspectRatio) < fabs(closestAspect - mOriginalAspectRatio))) + { + LL_INFOS() << " (new closest mode) " << LL_ENDL; + + // This is the closest mode we've seen yet. + closestWidth = resolutionList[i].mWidth; + closestHeight = resolutionList[i].mHeight; + closestAspect = aspect; + } + } + + width = closestWidth; + height = closestHeight; + } + } + + if((width == 0) || (height == 0)) + { + // Mode search failed for some reason. Use the old-school default. + width = 1024; + height = 768; + } +} + bool LLWindowSDL::createContext(int x, int y, int width, int height, int bits, bool fullscreen, bool disable_vsync) { //bool glneedsinit = false; LL_INFOS() << "createContext, fullscreen=" << fullscreen << - " size=" << width << "x" << height << LL_ENDL; + " size=" << width << "x" << height << LL_ENDL; // captures don't survive contexts mGrabbyKeyFlags = 0; mReallyCapturedCount = 0; - if (SDL_Init(SDL_INIT_VIDEO) < 0) + std::initializer_list<std::tuple< char const*, char const * > > hintList = + { + {SDL_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR,"0"}, + {SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH,"1"}, + {SDL_HINT_IME_INTERNAL_EDITING,"1"} + }; + + for( auto hint: hintList ) { - LL_INFOS() << "sdl_init() failed! " << SDL_GetError() << LL_ENDL; - setupFailure("sdl_init() failure, window creation error", "error", OSMB_OK); - return false; + SDL_SetHint( std::get<0>(hint), std::get<1>(hint)); + } + + std::initializer_list<std::tuple<uint32_t, char const*, bool>> initList= + { {SDL_INIT_VIDEO,"SDL_INIT_VIDEO", true}, + {SDL_INIT_AUDIO,"SDL_INIT_AUDIO", false}, + {SDL_INIT_GAMECONTROLLER,"SDL_INIT_GAMECONTROLLER", false}, + {SDL_INIT_SENSOR,"SDL_INIT_SENSOR", false} + }; + + for( auto subSystem : initList) + { + if( SDL_InitSubSystem( std::get<0>(subSystem) ) < 0 ) + { + LL_WARNS() << "SDL_InitSubSystem for " << std::get<1>(subSystem) << " failed " << SDL_GetError() << LL_ENDL; + + if( std::get<2>(subSystem)) + setupFailure("SDL_Init() failure", "error", OSMB_OK); + + } } SDL_version c_sdl_version; SDL_VERSION(&c_sdl_version); LL_INFOS() << "Compiled against SDL " - << int(c_sdl_version.major) << "." - << int(c_sdl_version.minor) << "." - << int(c_sdl_version.patch) << LL_ENDL; - const SDL_version *r_sdl_version; - r_sdl_version = SDL_Linked_Version(); + << int(c_sdl_version.major) << "." + << int(c_sdl_version.minor) << "." + << int(c_sdl_version.patch) << LL_ENDL; + SDL_version r_sdl_version; + SDL_GetVersion(&r_sdl_version); LL_INFOS() << " Running against SDL " - << int(r_sdl_version->major) << "." - << int(r_sdl_version->minor) << "." - << int(r_sdl_version->patch) << LL_ENDL; + << int(r_sdl_version.major) << "." + << int(r_sdl_version.minor) << "." + << int(r_sdl_version.patch) << LL_ENDL; - const SDL_VideoInfo *video_info = SDL_GetVideoInfo( ); - if (!video_info) - { - LL_INFOS() << "SDL_GetVideoInfo() failed! " << SDL_GetError() << LL_ENDL; - setupFailure("SDL_GetVideoInfo() failed, Window creation error", "Error", OSMB_OK); - return false; - } + if (width == 0) + width = 1024; + if (height == 0) + width = 768; - if (video_info->current_h > 0) - { - mOriginalAspectRatio = (float)video_info->current_w / (float)video_info->current_h; - LL_INFOS() << "Original aspect ratio was " << video_info->current_w << ":" << video_info->current_h << "=" << mOriginalAspectRatio << LL_ENDL; - } + mFullscreen = fullscreen; - SDL_EnableUNICODE(1); - SDL_WM_SetCaption(mWindowTitle.c_str(), mWindowTitle.c_str()); + int sdlflags = SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE; - // Set the application icon. - SDL_Surface *bmpsurface; - bmpsurface = Load_BMP_Resource("ll_icon.BMP"); - if (bmpsurface) + if( mFullscreen ) { - // This attempts to give a black-keyed mask to the icon. - SDL_SetColorKey(bmpsurface, - SDL_SRCCOLORKEY, - SDL_MapRGB(bmpsurface->format, 0,0,0) ); - SDL_WM_SetIcon(bmpsurface, NULL); - // The SDL examples cheerfully avoid freeing the icon - // surface, but I'm betting that's leaky. - SDL_FreeSurface(bmpsurface); - bmpsurface = NULL; + sdlflags |= SDL_WINDOW_FULLSCREEN; + tryFindFullscreenSize( width, height ); } - // note: these SetAttributes make Tom's 9600-on-AMD64 fail to - // get a visual, but it's broken anyway when it does, and without - // these SetAttributes we might easily get an avoidable substandard - // visual to work with on most other machines. - SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); - SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE,8); - SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); - SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, (bits <= 16) ? 16 : 24); - // We need stencil support for a few (minor) things. - if (!getenv("LL_GL_NO_STENCIL")) - SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8); - SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, (bits <= 16) ? 1 : 8); + if(hasHIDPI) sdlflags = sdlflags | SDL_WINDOW_ALLOW_HIGHDPI; - // *FIX: try to toggle vsync here? + mSDLFlags = sdlflags; - mFullscreen = fullscreen; + GLint redBits{8}, greenBits{8}, blueBits{8}, alphaBits{8}; + + GLint depthBits{(bits <= 16) ? 16 : 24}, stencilBits{8}; + + if (getenv("LL_GL_NO_STENCIL")) + stencilBits = 0; - int sdlflags = SDL_OPENGL | SDL_RESIZABLE | SDL_ANYFORMAT; + SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, alphaBits); + SDL_GL_SetAttribute(SDL_GL_RED_SIZE, redBits); + SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, greenBits); + SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, blueBits); + SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, depthBits ); + + // We need stencil support for a few (minor) things. + if (stencilBits) + SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, stencilBits); + // *FIX: try to toggle vsync here? + + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4); +#if LL_DARWIN + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1); +#else + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 6); +#endif + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); @@ -497,80 +783,41 @@ bool LLWindowSDL::createContext(int x, int y, int width, int height, int bits, b SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, mFSAASamples); } - mSDLFlags = sdlflags; + SDL_GL_SetAttribute(SDL_GL_SHARE_WITH_CURRENT_CONTEXT, 1); + mWindow = SDL_CreateWindow( mWindowTitle.c_str(), SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width, height, mSDLFlags ); - if (mFullscreen) + if( mWindow ) { - LL_INFOS() << "createContext: setting up fullscreen " << width << "x" << height << LL_ENDL; + mContext = SDL_GL_CreateContext( mWindow ); - // If the requested width or height is 0, find the best default for the monitor. - if((width == 0) || (height == 0)) + if( mContext == 0 ) { - // Scan through the list of modes, looking for one which has: - // height between 700 and 800 - // aspect ratio closest to the user's original mode - S32 resolutionCount = 0; - LLWindowResolution *resolutionList = getSupportedResolutions(resolutionCount); - - if(resolutionList != NULL) - { - F32 closestAspect = 0; - U32 closestHeight = 0; - U32 closestWidth = 0; - int i; - - LL_INFOS() << "createContext: searching for a display mode, original aspect is " << mOriginalAspectRatio << LL_ENDL; - - for(i=0; i < resolutionCount; i++) - { - F32 aspect = (F32)resolutionList[i].mWidth / (F32)resolutionList[i].mHeight; - - LL_INFOS() << "createContext: width " << resolutionList[i].mWidth << " height " << resolutionList[i].mHeight << " aspect " << aspect << LL_ENDL; - - if( (resolutionList[i].mHeight >= 700) && (resolutionList[i].mHeight <= 800) && - (fabs(aspect - mOriginalAspectRatio) < fabs(closestAspect - mOriginalAspectRatio))) - { - LL_INFOS() << " (new closest mode) " << LL_ENDL; - - // This is the closest mode we've seen yet. - closestWidth = resolutionList[i].mWidth; - closestHeight = resolutionList[i].mHeight; - closestAspect = aspect; - } - } - - width = closestWidth; - height = closestHeight; - } + LL_WARNS() << "Cannot create GL context " << SDL_GetError() << LL_ENDL; + setupFailure("GL Context creation error creation error", "Error", OSMB_OK); + return false; } + // SDL_GL_SetSwapInterval(1); + } - if((width == 0) || (height == 0)) - { - // Mode search failed for some reason. Use the old-school default. - width = 1024; - height = 768; - } - - mWindow = SDL_SetVideoMode(width, height, bits, sdlflags | SDL_FULLSCREEN); - if (!mWindow && bits > 16) - { - SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16); - mWindow = SDL_SetVideoMode(width, height, bits, sdlflags | SDL_FULLSCREEN); - } + if( mFullscreen ) + { if (mWindow) { mFullscreen = true; - mFullscreenWidth = mWindow->w; - mFullscreenHeight = mWindow->h; - mFullscreenBits = mWindow->format->BitsPerPixel; + /* + mFullscreenWidth = mSurface->w; + mFullscreenHeight = mSurface->h; + mFullscreenBits = mSurface->format->BitsPerPixel; + */ + SDL_GetWindowSize(mWindow, &mFullscreenWidth, &mFullscreenHeight); mFullscreenRefresh = -1; LL_INFOS() << "Running at " << mFullscreenWidth - << "x" << mFullscreenHeight - << "x" << mFullscreenBits - << " @ " << mFullscreenRefresh - << LL_ENDL; + << "x" << mFullscreenHeight + << "x" << mFullscreenBits + << " @ " << mFullscreenRefresh + << LL_ENDL; } else { @@ -584,33 +831,27 @@ bool LLWindowSDL::createContext(int x, int y, int width, int height, int bits, b std::string error = llformat("Unable to run fullscreen at %d x %d.\nRunning in window.", width, height); OSMessageBox(error, "Error", OSMB_OK); + return false; } } - - if(!mFullscreen && (mWindow == NULL)) + else { - if (width == 0) - width = 1024; - if (height == 0) - width = 768; - - LL_INFOS() << "createContext: creating window " << width << "x" << height << "x" << bits << LL_ENDL; - mWindow = SDL_SetVideoMode(width, height, bits, sdlflags); - if (!mWindow && bits > 16) - { - SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16); - mWindow = SDL_SetVideoMode(width, height, bits, sdlflags); - } - if (!mWindow) { LL_WARNS() << "createContext: window creation failure. SDL: " << SDL_GetError() << LL_ENDL; setupFailure("Window creation error", "Error", OSMB_OK); return false; } - } else if (!mFullscreen && (mWindow != NULL)) + } + + // Set the application icon. + SDL_Surface *bmpsurface; + bmpsurface = Load_BMP_Resource("ll_icon.BMP"); + if (bmpsurface) { - LL_INFOS() << "createContext: SKIPPING - !fullscreen, but +mWindow " << width << "x" << height << "x" << bits << LL_ENDL; + SDL_SetWindowIcon(mWindow, bmpsurface); + SDL_FreeSurface(bmpsurface); + bmpsurface = NULL; } // Detect video memory size. @@ -620,39 +861,67 @@ bool LLWindowSDL::createContext(int x, int y, int width, int height, int bits, b { LL_INFOS() << "X11 log-parser detected " << gGLManager.mVRAM << "MB VRAM." << LL_ENDL; } else + { + PFNGLXQUERYCURRENTRENDERERINTEGERMESAPROC queryInteger; + queryInteger = (PFNGLXQUERYCURRENTRENDERERINTEGERMESAPROC) + glXGetProcAddressARB((const GLubyte *)"glXQueryCurrentRendererIntegerMESA"); + unsigned int vram_megabytes = 0; + queryInteger(GLX_RENDERER_VIDEO_MEMORY_MESA, &vram_megabytes); + if (!vram_megabytes) { + glGetIntegerv(GL_GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX, (int *)&vram_megabytes); + vram_megabytes /= 1024; + } + if (!vram_megabytes) { + glGetIntegerv(GL_VBO_FREE_MEMORY_ATI, (int *)&vram_megabytes); + vram_megabytes /= 1024; + } + gGLManager.mVRAM = vram_megabytes; + } +#elif LL_DARWIN + CGLRendererInfoObj info = 0; + GLint vram_megabytes = 0; + int num_renderers = 0; + auto err = CGLQueryRendererInfo(CGDisplayIDToOpenGLDisplayMask(kCGDirectMainDisplay), + &info, &num_renderers); + if (!err) { + CGLDescribeRenderer(info, 0, kCGLRPVideoMemoryMegabytes, &vram_megabytes); + CGLDestroyRendererInfo(info); + } else + vram_megabytes = 256; + gGLManager.mVRAM = vram_megabytes; # endif // LL_X11 +/* { // fallback to letting SDL detect VRAM. // note: I've not seen SDL's detection ever actually find // VRAM != 0, but if SDL *does* detect it then that's a bonus. - gGLManager.mVRAM = video_info->video_mem / 1024; + gGLManager.mVRAM = 0; if (gGLManager.mVRAM != 0) { LL_INFOS() << "SDL detected " << gGLManager.mVRAM << "MB VRAM." << LL_ENDL; } } +*/ // If VRAM is not detected, that is handled later // *TODO: Now would be an appropriate time to check for some // explicitly unsupported cards. //const char* RENDERER = (const char*) glGetString(GL_RENDERER); - GLint depthBits, stencilBits, redBits, greenBits, blueBits, alphaBits; - - glGetIntegerv(GL_RED_BITS, &redBits); - glGetIntegerv(GL_GREEN_BITS, &greenBits); - glGetIntegerv(GL_BLUE_BITS, &blueBits); - glGetIntegerv(GL_ALPHA_BITS, &alphaBits); - glGetIntegerv(GL_DEPTH_BITS, &depthBits); - glGetIntegerv(GL_STENCIL_BITS, &stencilBits); + SDL_GL_GetAttribute(SDL_GL_RED_SIZE, &redBits); + SDL_GL_GetAttribute(SDL_GL_GREEN_SIZE, &greenBits); + SDL_GL_GetAttribute(SDL_GL_BLUE_SIZE, &blueBits); + SDL_GL_GetAttribute(SDL_GL_ALPHA_SIZE, &alphaBits); + SDL_GL_GetAttribute(SDL_GL_DEPTH_SIZE, &depthBits); + SDL_GL_GetAttribute(SDL_GL_STENCIL_SIZE, &stencilBits); LL_INFOS() << "GL buffer:" << LL_ENDL; - LL_INFOS() << " Red Bits " << S32(redBits) << LL_ENDL; - LL_INFOS() << " Green Bits " << S32(greenBits) << LL_ENDL; - LL_INFOS() << " Blue Bits " << S32(blueBits) << LL_ENDL; - LL_INFOS() << " Alpha Bits " << S32(alphaBits) << LL_ENDL; - LL_INFOS() << " Depth Bits " << S32(depthBits) << LL_ENDL; - LL_INFOS() << " Stencil Bits " << S32(stencilBits) << LL_ENDL; + LL_INFOS() << " Red Bits " << S32(redBits) << LL_ENDL; + LL_INFOS() << " Green Bits " << S32(greenBits) << LL_ENDL; + LL_INFOS() << " Blue Bits " << S32(blueBits) << LL_ENDL; + LL_INFOS() << " Alpha Bits " << S32(alphaBits) << LL_ENDL; + LL_INFOS() << " Depth Bits " << S32(depthBits) << LL_ENDL; + LL_INFOS() << " Stencil Bits " << S32(stencilBits) << LL_ENDL; GLint colorBits = redBits + greenBits + blueBits + alphaBits; // fixme: actually, it's REALLY important for picking that we get at @@ -660,70 +929,51 @@ bool LLWindowSDL::createContext(int x, int y, int width, int height, int bits, b // relaxed about if we have to. if (colorBits < 32) { +#if 0 close(); setupFailure( - "Second Life requires True Color (32-bit) to run in a window.\n" - "Please go to Control Panels -> Display -> Settings and\n" - "set the screen to 32-bit color.\n" - "Alternately, if you choose to run fullscreen, Second Life\n" - "will automatically adjust the screen each time it runs.", - "Error", - OSMB_OK); - return false; - } - -#if 0 // *FIX: we're going to brave it for now... - if (alphaBits < 8) - { - close(); - setupFailure( - "Second Life is unable to run because it can't get an 8 bit alpha\n" - "channel. Usually this is due to video card driver issues.\n" - "Please make sure you have the latest video card drivers installed.\n" - "Also be sure your monitor is set to True Color (32-bit) in\n" - "Control Panels -> Display -> Settings.\n" - "If you continue to receive this message, contact customer service.", - "Error", - OSMB_OK); + "Second Life requires True Color (32-bit) to run in a window.\n" + "Please go to Control Panels -> Display -> Settings and\n" + "set the screen to 32-bit color.\n" + "Alternately, if you choose to run fullscreen, Second Life\n" + "will automatically adjust the screen each time it runs.", + "Error", + OSMB_OK); return false; - } #endif + } #if LL_X11 /* Grab the window manager specific information */ SDL_SysWMinfo info; SDL_VERSION(&info.version); - if ( SDL_GetWMInfo(&info) ) + if ( SDL_GetWindowWMInfo(mWindow, &info) ) { /* Save the information for later use */ if ( info.subsystem == SDL_SYSWM_X11 ) { mSDL_Display = info.info.x11.display; - mSDL_XWindowID = info.info.x11.wmwindow; - Lock_Display = info.info.x11.lock_func; - Unlock_Display = info.info.x11.unlock_func; + mSDL_XWindowID = info.info.x11.window; } else { LL_WARNS() << "We're not running under X11? Wild." - << LL_ENDL; + << LL_ENDL; } } else { LL_WARNS() << "We're not running under any known WM. Wild." - << LL_ENDL; + << LL_ENDL; } #endif // LL_X11 + SDL_StartTextInput(); //make sure multisampling is disabled by default +#if GL_VERSION_1_3 glDisable(GL_MULTISAMPLE_ARB); - - // We need to do this here, once video is init'd - if (-1 == SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, - SDL_DEFAULT_REPEAT_INTERVAL)) - LL_WARNS() << "Couldn't enable key-repeat: " << SDL_GetError() <<LL_ENDL; +#endif // Don't need to get the current gamma, since there's a call that restores it to the system defaults. return true; @@ -761,6 +1011,7 @@ void LLWindowSDL::destroyContext() { LL_INFOS() << "destroyContext begins" << LL_ENDL; + SDL_StopTextInput(); #if LL_X11 mSDL_Display = NULL; mSDL_XWindowID = None; @@ -794,23 +1045,39 @@ LLWindowSDL::~LLWindowSDL() void LLWindowSDL::show() { // *FIX: What to do with SDL? + if (mWindow) + { + SDL_ShowWindow(mWindow); + } } void LLWindowSDL::hide() { // *FIX: What to do with SDL? + if (mWindow) + { + SDL_HideWindow(mWindow); + } } //virtual void LLWindowSDL::minimize() { // *FIX: What to do with SDL? + if (mWindow) + { + SDL_MinimizeWindow(mWindow); + } } //virtual void LLWindowSDL::restore() { // *FIX: What to do with SDL? + if (mWindow) + { + SDL_RestoreWindow(mWindow); + } } @@ -844,7 +1111,7 @@ bool LLWindowSDL::getVisible() // Then what is? if (mWindow) { - result = true; + if( SDL_GetWindowFlags(mWindow) & SDL_WINDOW_SHOWN ) result = true; } return(result); @@ -854,10 +1121,12 @@ bool LLWindowSDL::getMinimized() { bool result = false; - if (mWindow && (1 == mIsMinimized)) + if (mWindow/*&& (1 == mIsMinimized)*/) { - result = true; + if( SDL_GetWindowFlags(mWindow) & SDL_WINDOW_MINIMIZED ) result = true; } + + mIsMinimized = result; return(result); } @@ -868,6 +1137,8 @@ bool LLWindowSDL::getMaximized() if (mWindow) { // TODO + if( SDL_GetWindowFlags(mWindow) & SDL_WINDOW_MAXIMIZED ) result = true; + else result = false; } return(result); @@ -876,7 +1147,15 @@ bool LLWindowSDL::getMaximized() bool LLWindowSDL::maximize() { // TODO - return false; + bool result = false; + + if (mWindow) + { + SDL_MaximizeWindow(mWindow); + result = true; + } + + return result; } bool LLWindowSDL::getFullscreen() @@ -896,9 +1175,13 @@ bool LLWindowSDL::getSize(LLCoordScreen *size) { if (mWindow) { - size->mX = mWindow->w; - size->mY = mWindow->h; - return (true); + /* + if(hasHIDPI) + SDL_GL_GetDrawableSize(mWindow, &size->mX, &size->mY); + else + */ + SDL_GetWindowSize(mWindow, &size->mX, &size->mY); + return (true); } return (false); @@ -908,9 +1191,11 @@ bool LLWindowSDL::getSize(LLCoordWindow *size) { if (mWindow) { - size->mX = mWindow->w; - size->mY = mWindow->h; - return (true); + if(hasHIDPI) + SDL_GL_GetDrawableSize(mWindow, &size->mX, &size->mY); + else + SDL_GetWindowSize(mWindow, &size->mX, &size->mY); + return (true); } return (false); @@ -918,49 +1203,50 @@ bool LLWindowSDL::getSize(LLCoordWindow *size) bool LLWindowSDL::setPosition(const LLCoordScreen position) { + bool result = false; + if(mWindow) { // *FIX: (?) //MacMoveWindow(mWindow, position.mX, position.mY, false); + SDL_SetWindowPosition(mWindow, position.mX, position.mY); + result = true; } - return true; + return result; } -bool LLWindowSDL::setSizeImpl(const LLCoordScreen size) +template< typename T > bool setSizeImpl( const T& newSize, SDL_Window *pWin ) { - if(mWindow) - { - // Push a resize event onto SDL's queue - we'll handle it - // when it comes out again. - SDL_Event event; - event.type = SDL_VIDEORESIZE; - event.resize.w = size.mX; - event.resize.h = size.mY; - SDL_PushEvent(&event); // copied into queue + if( !pWin ) + return false; - return true; - } + auto nFlags = SDL_GetWindowFlags( pWin ); - return false; + if( nFlags & SDL_WINDOW_MAXIMIZED ) + SDL_RestoreWindow( pWin ); + + + SDL_SetWindowSize( pWin, newSize.mX, newSize.mY ); + SDL_Event event; + event.type = SDL_WINDOWEVENT; + event.window.event = SDL_WINDOWEVENT_RESIZED; + event.window.windowID = SDL_GetWindowID( pWin ); + event.window.data1 = newSize.mX; + event.window.data2 = newSize.mY; + SDL_PushEvent( &event ); + + return true; } -bool LLWindowSDL::setSizeImpl(const LLCoordWindow size) +bool LLWindowSDL::setSizeImpl(const LLCoordScreen size) { - if(mWindow) - { - // Push a resize event onto SDL's queue - we'll handle it - // when it comes out again. - SDL_Event event; - event.type = SDL_VIDEORESIZE; - event.resize.w = size.mX; - event.resize.h = size.mY; - SDL_PushEvent(&event); // copied into queue - - return true; - } + return ::setSizeImpl( size, mWindow ); +} - return false; +bool LLWindowSDL::setSizeImpl(const LLCoordWindow size) +{ + return ::setSizeImpl( size, mWindow ); } @@ -968,7 +1254,7 @@ void LLWindowSDL::swapBuffers() { if (mWindow) { - SDL_GL_SwapBuffers(); + SDL_GL_SwapWindow( mWindow ); } } @@ -990,7 +1276,10 @@ F32 LLWindowSDL::getGamma() bool LLWindowSDL::restoreGamma() { //CGDisplayRestoreColorSyncSettings(); - SDL_SetGamma(1.0f, 1.0f, 1.0f); + // SDL_SetGamma(1.0f, 1.0f, 1.0f); + Uint16 ramp; + SDL_CalculateGammaRamp(1.0f, &ramp); + SDL_SetWindowGammaRamp(mWindow, &ramp, &ramp, &ramp); return true; } @@ -999,7 +1288,10 @@ bool LLWindowSDL::setGamma(const F32 gamma) mGamma = gamma; if (mGamma == 0) mGamma = 0.1f; mGamma = 1/mGamma; - SDL_SetGamma(mGamma, mGamma, mGamma); + // SDL_SetGamma(mGamma, mGamma, mGamma); + Uint16 ramp; + SDL_CalculateGammaRamp(mGamma, &ramp); + SDL_SetWindowGammaRamp(mWindow, &ramp, &ramp, &ramp); return true; } @@ -1048,7 +1340,14 @@ bool LLWindowSDL::setCursorPosition(const LLCoordWindow position) //LL_INFOS() << "setCursorPosition(" << screen_pos.mX << ", " << screen_pos.mY << ")" << LL_ENDL; // do the actual forced cursor move. - SDL_WarpMouse(screen_pos.mX, screen_pos.mY); + + if (mFullscreen) + { + SDL_WarpMouseGlobal(screen_pos.mX, screen_pos.mY); + return result; + } + + SDL_WarpMouseInWindow(mWindow, screen_pos.mX, screen_pos.mY); //LL_INFOS() << llformat("llcw %d,%d -> scr %d,%d", position.mX, position.mY, screen_pos.mX, screen_pos.mY) << LL_ENDL; @@ -1070,21 +1369,14 @@ bool LLWindowSDL::getCursorPosition(LLCoordWindow *position) return convertCoords(screen_pos, position); } +F32 LLWindowSDL::getSystemUISize() +{ + if(hasHIDPI) return 2.0f; + else return 1.f; +} F32 LLWindowSDL::getNativeAspectRatio() { -#if 0 - // RN: this hack presumes that the largest supported resolution is monitor-limited - // and that pixels in that mode are square, therefore defining the native aspect ratio - // of the monitor...this seems to work to a close approximation for most CRTs/LCDs - S32 num_resolutions; - LLWindowResolution* resolutions = getSupportedResolutions(num_resolutions); - - - return ((F32)resolutions[num_resolutions - 1].mWidth / (F32)resolutions[num_resolutions - 1].mHeight); - //rn: AC -#endif - // MBW -- there are a couple of bad assumptions here. One is that the display list won't include // ridiculous resolutions nobody would ever use. The other is that the list is in order. @@ -1146,7 +1438,7 @@ void LLWindowSDL::beforeDialog() // it only works in X11 if (running_x11 && mWindow) { - SDL_WM_ToggleFullScreen(mWindow); + SDL_SetWindowFullscreen( mWindow, 0 ); } } } @@ -1162,12 +1454,6 @@ void LLWindowSDL::beforeDialog() } #endif // LL_X11 -#if LL_GTK - // this is a good time to grab some GTK version information for - // diagnostics, if not already done. - ll_try_gtk_init(); -#endif // LL_GTK - maybe_lock_display(); } @@ -1188,7 +1474,7 @@ void LLWindowSDL::afterDialog() // in X11 if (running_x11 && mWindow) { - SDL_WM_ToggleFullScreen(mWindow); + SDL_SetWindowFullscreen( mWindow, 0 ); } } } @@ -1224,143 +1510,87 @@ void LLWindowSDL::x11_set_urgent(bool urgent) void LLWindowSDL::flashIcon(F32 seconds) { + if (getMinimized()) + { #if !LL_X11 - LL_INFOS() << "Stub LLWindowSDL::flashIcon(" << seconds << ")" << LL_ENDL; + LL_INFOS() << "Stub LLWindowSDL::flashIcon(" << seconds << ")" << LL_ENDL; #else - LL_INFOS() << "X11 LLWindowSDL::flashIcon(" << seconds << ")" << LL_ENDL; + LL_INFOS() << "X11 LLWindowSDL::flashIcon(" << seconds << ")" << LL_ENDL; - F32 remaining_time = mFlashTimer.getRemainingTimeF32(); - if (remaining_time < seconds) - remaining_time = seconds; - mFlashTimer.reset(); - mFlashTimer.setTimerExpirySec(remaining_time); + F32 remaining_time = mFlashTimer.getRemainingTimeF32(); + if (remaining_time < seconds) + remaining_time = seconds; + mFlashTimer.reset(); + mFlashTimer.setTimerExpirySec(remaining_time); - x11_set_urgent(true); - mFlashing = true; + x11_set_urgent(true); + mFlashing = true; #endif // LL_X11 -} - - -#if LL_GTK -bool LLWindowSDL::isClipboardTextAvailable() -{ - if (ll_try_gtk_init()) - { - GtkClipboard * const clipboard = - gtk_clipboard_get(GDK_NONE); - return gtk_clipboard_wait_is_text_available(clipboard) ? - true : false; - } - return false; // failure -} - -bool LLWindowSDL::pasteTextFromClipboard(LLWString &text) -{ - if (ll_try_gtk_init()) - { - GtkClipboard * const clipboard = - gtk_clipboard_get(GDK_NONE); - gchar * const data = gtk_clipboard_wait_for_text(clipboard); - if (data) - { - text = LLWString(utf8str_to_wstring(data)); - g_free(data); - return true; - } - } - return false; // failure -} - -bool LLWindowSDL::copyTextToClipboard(const LLWString &text) -{ - if (ll_try_gtk_init()) - { - const std::string utf8 = wstring_to_utf8str(text); - GtkClipboard * const clipboard = - gtk_clipboard_get(GDK_NONE); - gtk_clipboard_set_text(clipboard, utf8.c_str(), utf8.length()); - return true; } - return false; // failure } - -bool LLWindowSDL::isPrimaryTextAvailable() -{ - if (ll_try_gtk_init()) - { - GtkClipboard * const clipboard = - gtk_clipboard_get(GDK_SELECTION_PRIMARY); - return gtk_clipboard_wait_is_text_available(clipboard) ? - true : false; - } - return false; // failure -} - -bool LLWindowSDL::pasteTextFromPrimary(LLWString &text) +bool LLWindowSDL::isClipboardTextAvailable() { - if (ll_try_gtk_init()) - { - GtkClipboard * const clipboard = - gtk_clipboard_get(GDK_SELECTION_PRIMARY); - gchar * const data = gtk_clipboard_wait_for_text(clipboard); - if (data) - { - text = LLWString(utf8str_to_wstring(data)); - g_free(data); - return true; - } - } - return false; // failure +#if LL_X11 + return mSDL_Display && XGetSelectionOwner(mSDL_Display, XA_CLIPBOARD) != None; +#else + return SDL_HasClipboardText(); +#endif } -bool LLWindowSDL::copyTextToPrimary(const LLWString &text) +bool LLWindowSDL::pasteTextFromClipboard(LLWString &dst) { - if (ll_try_gtk_init()) +#if LL_X11 + return getSelectionText(XA_CLIPBOARD, dst); +#else + auto data = SDL_GetClipboardText(); + if (data) { - const std::string utf8 = wstring_to_utf8str(text); - GtkClipboard * const clipboard = - gtk_clipboard_get(GDK_SELECTION_PRIMARY); - gtk_clipboard_set_text(clipboard, utf8.c_str(), utf8.length()); + dst = LLWString(utf8str_to_wstring(data)); + SDL_free(data); return true; } - return false; // failure -} - -#else - -bool LLWindowSDL::isClipboardTextAvailable() -{ - return false; // unsupported -} - -bool LLWindowSDL::pasteTextFromClipboard(LLWString &dst) -{ - return false; // unsupported + return false; +#endif } bool LLWindowSDL::copyTextToClipboard(const LLWString &s) { - return false; // unsupported +#if LL_X11 + return setSelectionText(XA_CLIPBOARD, s); +#else + return !SDL_SetClipboardText(wstring_to_utf8str(s).c_str()); +#endif } bool LLWindowSDL::isPrimaryTextAvailable() { +#if LL_X11 + LLWString text; + return getSelectionText(XA_PRIMARY, text) && !text.empty(); +#else return false; // unsupported +#endif } bool LLWindowSDL::pasteTextFromPrimary(LLWString &dst) { +#if LL_X11 + return getSelectionText(XA_PRIMARY, dst); +#else return false; // unsupported +#endif } bool LLWindowSDL::copyTextToPrimary(const LLWString &s) { - return false; // unsupported +#if LL_X11 + return setSelectionText(XA_PRIMARY, s); +#else + return false; // unsupported +#endif } -#endif // LL_GTK - LLWindow::LLWindowResolution* LLWindowSDL::getSupportedResolutions(S32 &num_resolutions) { if (!mSupportedResolutions) @@ -1368,33 +1598,30 @@ LLWindow::LLWindowResolution* LLWindowSDL::getSupportedResolutions(S32 &num_reso mSupportedResolutions = new LLWindowResolution[MAX_NUM_RESOLUTIONS]; mNumSupportedResolutions = 0; - SDL_Rect **modes = SDL_ListModes(NULL, SDL_OPENGL | SDL_FULLSCREEN); - if ( (modes != NULL) && (modes != ((SDL_Rect **) -1)) ) + // <FS:ND> Use display no from mWindow/mSurface here? + int max = SDL_GetNumDisplayModes(0); + max = llclamp( max, 0, MAX_NUM_RESOLUTIONS ); + + for( int i =0; i < max; ++i ) { - int count = 0; - while (*modes && count<MAX_NUM_RESOLUTIONS) // they're sorted biggest to smallest, so find end... + SDL_DisplayMode mode = { SDL_PIXELFORMAT_UNKNOWN, 0, 0, 0, 0 }; + if (SDL_GetDisplayMode( 0 , i, &mode) != 0) { - modes++; - count++; + continue; } - while (count--) + int w = mode.w; + int h = mode.h; + if ((w >= 800) && (h >= 600)) { - modes--; - SDL_Rect *r = *modes; - int w = r->w; - int h = r->h; - if ((w >= 800) && (h >= 600)) + // make sure we don't add the same resolution multiple times! + if ( (mNumSupportedResolutions == 0) || + ((mSupportedResolutions[mNumSupportedResolutions-1].mWidth != w) && + (mSupportedResolutions[mNumSupportedResolutions-1].mHeight != h)) ) { - // make sure we don't add the same resolution multiple times! - if ( (mNumSupportedResolutions == 0) || - ((mSupportedResolutions[mNumSupportedResolutions-1].mWidth != w) && - (mSupportedResolutions[mNumSupportedResolutions-1].mHeight != h)) ) - { - mSupportedResolutions[mNumSupportedResolutions].mWidth = w; - mSupportedResolutions[mNumSupportedResolutions].mHeight = h; - mNumSupportedResolutions++; - } + mSupportedResolutions[mNumSupportedResolutions].mWidth = w; + mSupportedResolutions[mNumSupportedResolutions].mHeight = h; + mNumSupportedResolutions++; } } } @@ -1410,7 +1637,9 @@ bool LLWindowSDL::convertCoords(LLCoordGL from, LLCoordWindow *to) return false; to->mX = from.mX; - to->mY = mWindow->h - from.mY - 1; + int h; + SDL_GetWindowSize(mWindow, nullptr, &h); + to->mY = h - from.mY - 1; return true; } @@ -1421,7 +1650,9 @@ bool LLWindowSDL::convertCoords(LLCoordWindow from, LLCoordGL* to) return false; to->mX = from.mX; - to->mY = mWindow->h - from.mY - 1; + int h; + SDL_GetWindowSize(mWindow, nullptr, &h); + to->mY = h - from.mY - 1; return true; } @@ -1482,13 +1713,13 @@ bool LLWindowSDL::SDLReallyCaptureInput(bool capture) else mReallyCapturedCount = 0; - SDL_GrabMode wantmode, newmode; + bool wantGrab; if (mReallyCapturedCount <= 0) // uncapture { - wantmode = SDL_GRAB_OFF; + wantGrab = false; } else // capture { - wantmode = SDL_GRAB_ON; + wantGrab = true; } if (mReallyCapturedCount < 0) // yuck, imbalance. @@ -1497,9 +1728,11 @@ bool LLWindowSDL::SDLReallyCaptureInput(bool capture) LL_WARNS() << "ReallyCapture count was < 0" << LL_ENDL; } + bool newGrab = wantGrab; + +#if LL_X11 if (!mFullscreen) /* only bother if we're windowed anyway */ { -#if LL_X11 if (mSDL_Display) { /* we dirtily mix raw X11 with SDL so that our pointer @@ -1512,49 +1745,37 @@ bool LLWindowSDL::SDLReallyCaptureInput(bool capture) *keyboard* input from the window manager, which was frustrating users. */ int result; - if (wantmode == SDL_GRAB_ON) + if (wantGrab == true) { - //LL_INFOS() << "X11 POINTER GRABBY" << LL_ENDL; - //newmode = SDL_WM_GrabInput(wantmode); maybe_lock_display(); result = XGrabPointer(mSDL_Display, mSDL_XWindowID, - True, 0, GrabModeAsync, - GrabModeAsync, - None, None, CurrentTime); + True, 0, GrabModeAsync, + GrabModeAsync, + None, None, CurrentTime); maybe_unlock_display(); if (GrabSuccess == result) - newmode = SDL_GRAB_ON; + newGrab = true; else - newmode = SDL_GRAB_OFF; - } else if (wantmode == SDL_GRAB_OFF) + newGrab = false; + } + else { - //LL_INFOS() << "X11 POINTER UNGRABBY" << LL_ENDL; - newmode = SDL_GRAB_OFF; - //newmode = SDL_WM_GrabInput(SDL_GRAB_OFF); + newGrab = false; maybe_lock_display(); XUngrabPointer(mSDL_Display, CurrentTime); // Make sure the ungrab happens RIGHT NOW. XSync(mSDL_Display, False); maybe_unlock_display(); - } else - { - newmode = SDL_GRAB_QUERY; // neutral } - } else // not actually running on X11, for some reason - newmode = wantmode; -#endif // LL_X11 - } else { - // pretend we got what we wanted, when really we don't care. - newmode = wantmode; + } } - +#endif // LL_X11 // return boolean success for whether we ended up in the desired state - return (capture && SDL_GRAB_ON==newmode) || - (!capture && SDL_GRAB_OFF==newmode); + return capture == newGrab; } -U32 LLWindowSDL::SDLCheckGrabbyKeys(SDLKey keysym, bool gain) +U32 LLWindowSDL::SDLCheckGrabbyKeys(U32 keysym, bool gain) { /* part of the fix for SL-13243: Some popular window managers like to totally eat alt-drag for the purposes of moving windows. We @@ -1572,16 +1793,16 @@ U32 LLWindowSDL::SDLCheckGrabbyKeys(SDLKey keysym, bool gain) U32 mask = 0; switch (keysym) { - case SDLK_LALT: - mask = 1U << 0; break; - case SDLK_RALT: - mask = 1U << 1; break; - case SDLK_LCTRL: - mask = 1U << 2; break; - case SDLK_RCTRL: - mask = 1U << 3; break; - default: - break; + case SDLK_LALT: + mask = 1U << 0; break; + case SDLK_RALT: + mask = 1U << 1; break; + case SDLK_LCTRL: + mask = 1U << 2; break; + case SDLK_RCTRL: + mask = 1U << 3; break; + default: + break; } if (gain) @@ -1679,7 +1900,7 @@ void check_vm_bloat() last_rss_size = this_rss_size; last_vm_size = this_vm_size; -finally: + finally: if (NULL != ptr) { free(ptr); @@ -1694,33 +1915,17 @@ finally: // virtual void LLWindowSDL::processMiscNativeEvents() { -#if LL_GTK - // Pump GTK events to avoid starvation for: - // * DBUS servicing - // * Anything else which quietly hooks into the default glib/GTK loop - if (ll_try_gtk_init()) - { - // Yuck, Mozilla's GTK callbacks play with the locale - push/pop - // the locale to protect it, as exotic/non-C locales - // causes our code lots of general critical weirdness - // and crashness. (SL-35450) - static std::string saved_locale; - saved_locale = ll_safe_string(setlocale(LC_ALL, NULL)); - - // Pump until we've nothing left to do or passed 1/15th of a - // second pumping for this frame. - static LLTimer pump_timer; - pump_timer.reset(); - pump_timer.setTimerExpirySec(1.0f / 15.0f); - do { - // Always do at least one non-blocking pump - gtk_main_iteration_do(false); - } while (gtk_events_pending() && - !pump_timer.hasExpired()); - - setlocale(LC_ALL, saved_locale.c_str() ); - } -#endif // LL_GTK +#if LL_GLIB + // Pump until we've nothing left to do or passed 1/15th of a + // second pumping for this frame. + static LLTimer pump_timer; + pump_timer.reset(); + pump_timer.setTimerExpirySec(1.0f / 15.0f); + do + { + g_main_context_iteration(g_main_context_default(), false); + } while( g_main_context_pending(g_main_context_default()) && !pump_timer.hasExpired()); +#endif // hack - doesn't belong here - but this is just for debugging if (getenv("LL_DEBUG_BLOAT")) @@ -1743,43 +1948,89 @@ void LLWindowSDL::gatherInput() { switch (event.type) { + case SDL_MOUSEWHEEL: + if( event.wheel.y != 0 ) + mCallbacks->handleScrollWheel(this, -event.wheel.y); + break; + case SDL_MOUSEMOTION: { LLCoordWindow winCoord(event.button.x, event.button.y); LLCoordGL openGlCoord; convertCoords(winCoord, &openGlCoord); + + openGlCoord.mX = openGlCoord.mX * getSystemUISize(); + openGlCoord.mY = openGlCoord.mY * getSystemUISize(); + + //LL_INFOS() << "SDL_MOUSEMOTION " << event.button.x << " " << event.button.y << " gl " << openGlCoord.mX << " " << openGlCoord.mY << LL_ENDL; + MASK mask = gKeyboard->currentMask(true); mCallbacks->handleMouseMove(this, openGlCoord, mask); break; } + case SDL_TEXTINPUT: + { + auto string = utf8str_to_utf16str( event.text.text ); + mKeyModifiers = gKeyboard->currentMask( false ); + mInputType = "textinput"; + for( auto key: string ) + { + mKeyVirtualKey = key; + + if( (MASK_CONTROL|MASK_ALT)&mKeyModifiers ) + gKeyboard->handleKeyDown(mKeyVirtualKey, mKeyModifiers ); + else + handleUnicodeUTF16( key, mKeyModifiers ); + } + break; + } + case SDL_KEYDOWN: - mKeyScanCode = event.key.keysym.scancode; - mKeyVirtualKey = event.key.keysym.unicode; - mKeyModifiers = event.key.keysym.mod; + mKeyVirtualKey = event.key.keysym.sym; + mKeyModifiers = event.key.keysym.mod; + mInputType = "keydown"; - gKeyboard->handleKeyDown(event.key.keysym.sym, event.key.keysym.mod); - // part of the fix for SL-13243 - if (SDLCheckGrabbyKeys(event.key.keysym.sym, true) != 0) - SDLReallyCaptureInput(true); + // treat all possible Enter/Return keys the same + if (mKeyVirtualKey == SDLK_RETURN2 || mKeyVirtualKey == SDLK_KP_ENTER) + { + mKeyVirtualKey = SDLK_RETURN; + } + + gKeyboard->handleKeyDown(mKeyVirtualKey, mKeyModifiers ); + + // <FS:ND> Slightly hacky :| To make the viewer honor enter (eg to accept form input) we've to not only send handleKeyDown but also send a + // invoke handleUnicodeUTF16 in case the user hits return. + // Note that we cannot blindly use handleUnicodeUTF16 for each SDL_KEYDOWN. Doing so will create bogus keyboard input (like % for cursor left). + if( mKeyVirtualKey == SDLK_RETURN ) + { + // fix return key not working when capslock, scrolllock or numlock are enabled + mKeyModifiers &= (~(KMOD_NUM | KMOD_CAPS | KMOD_MODE | KMOD_SCROLL)); + handleUnicodeUTF16( mKeyVirtualKey, mKeyModifiers ); + } + + // part of the fix for SL-13243 + if (SDLCheckGrabbyKeys(event.key.keysym.sym, true) != 0) + SDLReallyCaptureInput(true); - if (event.key.keysym.unicode) - { - handleUnicodeUTF16(event.key.keysym.unicode, - gKeyboard->currentMask(false)); - } break; case SDL_KEYUP: - mKeyScanCode = event.key.keysym.scancode; - mKeyVirtualKey = event.key.keysym.unicode; - mKeyModifiers = event.key.keysym.mod; + mKeyVirtualKey = event.key.keysym.sym; + mKeyModifiers = event.key.keysym.mod; + mInputType = "keyup"; - if (SDLCheckGrabbyKeys(event.key.keysym.sym, false) == 0) - SDLReallyCaptureInput(false); // part of the fix for SL-13243 + // treat all possible Enter/Return keys the same + if (mKeyVirtualKey == SDLK_RETURN2 || mKeyVirtualKey == SDLK_KP_ENTER) + { + mKeyVirtualKey = SDLK_RETURN; + } - gKeyboard->handleKeyUp(event.key.keysym.sym, event.key.keysym.mod); - break; + if (SDLCheckGrabbyKeys(mKeyVirtualKey, false) == 0) + SDLReallyCaptureInput(false); // part of the fix for SL-13243 + + gKeyboard->handleKeyUp(mKeyVirtualKey,mKeyModifiers); + break; case SDL_MOUSEBUTTONDOWN: { @@ -1787,7 +2038,11 @@ void LLWindowSDL::gatherInput() LLCoordWindow winCoord(event.button.x, event.button.y); LLCoordGL openGlCoord; convertCoords(winCoord, &openGlCoord); - MASK mask = gKeyboard->currentMask(true); + + openGlCoord.mX *= getSystemUISize(); + openGlCoord.mY *= getSystemUISize(); + + MASK mask = gKeyboard->currentMask(true); if (event.button.button == SDL_BUTTON_LEFT) // SDL doesn't manage double clicking... { @@ -1799,7 +2054,7 @@ void LLWindowSDL::gatherInput() if (++leftClick >= 2) { leftClick = 0; - isDoubleClick = true; + isDoubleClick = true; } } lastLeftDown = now; @@ -1830,7 +2085,7 @@ void LLWindowSDL::gatherInput() else if (event.button.button == SDL_BUTTON_RIGHT) // right { - mCallbacks->handleRightMouseDown(this, openGlCoord, mask); + mCallbacks->handleRightMouseDown(this, openGlCoord, mask); } else if (event.button.button == SDL_BUTTON_MIDDLE) // middle @@ -1850,86 +2105,108 @@ void LLWindowSDL::gatherInput() LLCoordWindow winCoord(event.button.x, event.button.y); LLCoordGL openGlCoord; convertCoords(winCoord, &openGlCoord); - MASK mask = gKeyboard->currentMask(true); + + openGlCoord.mX *= getSystemUISize(); + openGlCoord.mY *= getSystemUISize(); + + MASK mask = gKeyboard->currentMask(true); if (event.button.button == SDL_BUTTON_LEFT) // left - mCallbacks->handleMouseUp(this, openGlCoord, mask); + mCallbacks->handleMouseUp(this, openGlCoord, mask); else if (event.button.button == SDL_BUTTON_RIGHT) // right - mCallbacks->handleRightMouseUp(this, openGlCoord, mask); + mCallbacks->handleRightMouseUp(this, openGlCoord, mask); else if (event.button.button == SDL_BUTTON_MIDDLE) // middle - mCallbacks->handleMiddleMouseUp(this, openGlCoord, mask); + mCallbacks->handleMiddleMouseUp(this, openGlCoord, mask); // don't handle mousewheel here... break; } - case SDL_VIDEOEXPOSE: // VIDEOEXPOSE doesn't specify the damage, but hey, it's OpenGL...repaint the whole thing! - mCallbacks->handlePaint(this, 0, 0, mWindow->w, mWindow->h); - break; - - case SDL_VIDEORESIZE: // *FIX: handle this? + case SDL_WINDOWEVENT: // *FIX: handle this? { - LL_INFOS() << "Handling a resize event: " << event.resize.w << - "x" << event.resize.h << LL_ENDL; + if( event.window.event == SDL_WINDOWEVENT_RESIZED + /* || event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED*/ ) // <FS:ND> SDL_WINDOWEVENT_SIZE_CHANGED is followed by SDL_WINDOWEVENT_RESIZED, so handling one shall be enough + { + LL_INFOS() << "Handling a resize event: " << event.window.data1 << "x" << event.window.data2 << LL_ENDL; - S32 width = llmax(event.resize.w, (S32)mMinWindowWidth); - S32 height = llmax(event.resize.h, (S32)mMinWindowHeight); + S32 width = llmax(event.window.data1, (S32)mMinWindowWidth); + S32 height = llmax(event.window.data2, (S32)mMinWindowHeight); - // *FIX: I'm not sure this is necessary! - mWindow = SDL_SetVideoMode(width, height, 32, mSDLFlags); - if (!mWindow) - { - // *FIX: More informative dialog? - LL_INFOS() << "Could not recreate context after resize! Quitting..." << LL_ENDL; - if(mCallbacks->handleCloseRequest(this)) + // *FIX: I'm not sure this is necessary! + // <FS:ND> I think is is not + // SDL_SetWindowSize(mWindow, width, height); + // + + mCallbacks->handleResize(this, width * getSystemUISize(), height * getSystemUISize()); + } + else if(event.window.event == SDL_WINDOWEVENT_ENTER) { - // Get the app to initiate cleanup. - mCallbacks->handleQuit(this); - // The app is responsible for calling destroyWindow when done with GL + LL_INFOS() << "SDL_WINDOWEVENT_ENTER" << LL_ENDL; + if(!mHaveInputFocus) mCallbacks->handleFocus(this); + mHaveInputFocus = true; } - break; - } - - mCallbacks->handleResize(this, width, height); - break; - } - case SDL_ACTIVEEVENT: - if (event.active.state & SDL_APPINPUTFOCUS) + else if(event.window.event == SDL_WINDOWEVENT_LEAVE) { - // Note that for SDL (particularly on X11), keyboard - // and mouse focus are independent things. Here we are - // tracking keyboard focus state changes. - - // We have to do our own state massaging because SDL - // can send us two unfocus events in a row for example, - // which confuses the focus code [SL-24071]. - if (event.active.gain != mHaveInputFocus) - { - mHaveInputFocus = !!event.active.gain; + LL_INFOS() << "SDL_WINDOWEVENT_LEAVE" << LL_ENDL; + if(mHaveInputFocus) mCallbacks->handleFocusLost(this); + mHaveInputFocus = false; + } + else if( event.window.event == SDL_WINDOWEVENT_FOCUS_GAINED ) // <FS:ND> What about SDL_WINDOWEVENT_ENTER (mouse focus) + { + // We have to do our own state massaging because SDL + // can send us two unfocus events in a row for example, + // which confuses the focus code [SL-24071]. + mHaveInputFocus = true; - if (mHaveInputFocus) mCallbacks->handleFocus(this); - else + } + else if( event.window.event == SDL_WINDOWEVENT_FOCUS_LOST ) // <FS:ND> What about SDL_WINDOWEVENT_LEAVE (mouse focus) + { + // We have to do our own state massaging because SDL + // can send us two unfocus events in a row for example, + // which confuses the focus code [SL-24071]. + mHaveInputFocus = false; + mCallbacks->handleFocusLost(this); - } } - if (event.active.state & SDL_APPACTIVE) + /* + + Bug : the app remains inactive when maximized .. + + else if(event.window.event == SDL_WINDOWEVENT_MINIMIZED) { - // Change in iconification/minimization state. - if ((!event.active.gain) != mIsMinimized) - { - mIsMinimized = (!event.active.gain); + LL_INFOS() << "SDL_WINDOWEVENT_MINIMIZED" << LL_ENDL; + if(!mIsMinimized) mCallbacks->handleActivate(this,false); + mIsMinimized = true; + } + else if(event.window.event == SDL_WINDOWEVENT_MAXIMIZED) + { + LL_INFOS() << "SDL_WINDOWEVENT_MAXIMIZED" << LL_ENDL; + if(mIsMinimized) mCallbacks->handleActivate(this,true); + mIsMinimized = false; + } + */ + else if (event.window.event == SDL_WINDOWEVENT_EXPOSED) + { + int w, h; + SDL_GL_GetDrawableSize(mWindow, &w, &h); - mCallbacks->handleActivate(this, !mIsMinimized); - LL_INFOS() << "SDL deiconification state switched to " << bool(event.active.gain) << LL_ENDL; - } - else - { - LL_INFOS() << "Ignored bogus redundant SDL deiconification state switch to " << bool(event.active.gain) << LL_ENDL; - } + mCallbacks->handlePaint(this, 0, 0, w, h); } - break; + else if( event.window.event == SDL_WINDOWEVENT_MINIMIZED || + event.window.event == SDL_WINDOWEVENT_MAXIMIZED || + event.window.event == SDL_WINDOWEVENT_RESTORED || + event.window.event == SDL_WINDOWEVENT_EXPOSED || + event.window.event == SDL_WINDOWEVENT_SHOWN ) + { + mIsMinimized = (event.window.event == SDL_WINDOWEVENT_MINIMIZED); + mCallbacks->handleActivate(this, !mIsMinimized); + LL_INFOS() << "SDL deiconification state switched to " << mIsMinimized << LL_ENDL; + } + + break; + } case SDL_QUIT: if(mCallbacks->handleCloseRequest(this)) { @@ -1938,9 +2215,9 @@ void LLWindowSDL::gatherInput() // The app is responsible for calling destroyWindow when done with GL } break; - default: - //LL_INFOS() << "Unhandled SDL event type " << event.type << LL_ENDL; - break; + default: + //LL_INFOS() << "Unhandled SDL event type " << event.type << LL_ENDL; + break; } } @@ -1968,21 +2245,21 @@ static SDL_Cursor *makeSDLCursorFromBMP(const char *filename, int hotx, int hoty { SDL_Surface *cursurface; LL_DEBUGS() << "Loaded cursor file " << filename << " " - << bmpsurface->w << "x" << bmpsurface->h << LL_ENDL; + << bmpsurface->w << "x" << bmpsurface->h << LL_ENDL; cursurface = SDL_CreateRGBSurface (SDL_SWSURFACE, - bmpsurface->w, - bmpsurface->h, - 32, - SDL_SwapLE32(0xFFU), - SDL_SwapLE32(0xFF00U), - SDL_SwapLE32(0xFF0000U), - SDL_SwapLE32(0xFF000000U)); + bmpsurface->w, + bmpsurface->h, + 32, + SDL_SwapLE32(0xFFU), + SDL_SwapLE32(0xFF00U), + SDL_SwapLE32(0xFF0000U), + SDL_SwapLE32(0xFF000000U)); SDL_FillRect(cursurface, NULL, SDL_SwapLE32(0x00000000U)); // Blit the cursor pixel data onto a 32-bit RGBA surface so we // only have to cope with processing one type of pixel format. if (0 == SDL_BlitSurface(bmpsurface, NULL, - cursurface, NULL)) + cursurface, NULL)) { // n.b. we already checked that width is a multiple of 8. const int bitmap_bytes = (cursurface->w * cursurface->h) / 8; @@ -1997,26 +2274,26 @@ static SDL_Cursor *makeSDLCursorFromBMP(const char *filename, int hotx, int hoty for (i=0; i<cursurface->h; ++i) { for (j=0; j<cursurface->w; ++j) { U8 *pixelp = - ((U8*)cursurface->pixels) - + cursurface->pitch * i - + j*cursurface->format->BytesPerPixel; + ((U8*)cursurface->pixels) + + cursurface->pitch * i + + j*cursurface->format->BytesPerPixel; U8 srcred = pixelp[0]; U8 srcgreen = pixelp[1]; U8 srcblue = pixelp[2]; bool mask_bit = (srcred != 200) - || (srcgreen != 200) - || (srcblue != 200); + || (srcgreen != 200) + || (srcblue != 200); bool data_bit = mask_bit && (srcgreen <= 80);//not 0x80 unsigned char bit_offset = (cursurface->w/8) * i - + j/8; + + j/8; cursor_data[bit_offset] |= (data_bit) << (7 - (j&7)); cursor_mask[bit_offset] |= (mask_bit) << (7 - (j&7)); } } sdlcursor = SDL_CreateCursor((Uint8*)cursor_data, - (Uint8*)cursor_mask, - cursurface->w, cursurface->h, - hotx, hoty); + (Uint8*)cursor_mask, + cursurface->w, cursurface->h, + hotx, hoty); delete[] cursor_data; delete[] cursor_mask; } else { @@ -2207,8 +2484,6 @@ void LLWindowSDL::hideCursorUntilMouseMove() } } - - // // LLSplashScreenSDL - I don't think we'll bother to implement this; it's // fairly obsolete at this point. @@ -2233,133 +2508,71 @@ void LLSplashScreenSDL::hideImpl() { } - - -#if LL_GTK -static void response_callback (GtkDialog *dialog, - gint arg1, - gpointer user_data) -{ - gint *response = (gint*)user_data; - *response = arg1; - gtk_widget_destroy(GTK_WIDGET(dialog)); - gtk_main_quit(); -} - S32 OSMessageBoxSDL(const std::string& text, const std::string& caption, U32 type) { - S32 rtn = OSBTN_CANCEL; - - if(gWindowImplementation != NULL) - gWindowImplementation->beforeDialog(); + SDL_MessageBoxData oData = { SDL_MESSAGEBOX_INFORMATION, nullptr, caption.c_str(), text.c_str(), 0, nullptr, nullptr }; + SDL_MessageBoxButtonData btnOk[] = {{SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT, OSBTN_OK, "OK" }}; + SDL_MessageBoxButtonData btnOkCancel [] = {{SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT, OSBTN_OK, "OK" }, {SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT, OSBTN_CANCEL, "Cancel"} }; + SDL_MessageBoxButtonData btnYesNo[] = { {SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT, OSBTN_YES, "Yes" }, {SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT, OSBTN_NO, "No"} }; - if (LLWindowSDL::ll_try_gtk_init()) + switch (type) { - GtkWidget *win = NULL; - - LL_INFOS() << "Creating a dialog because we're in windowed mode and GTK is happy." << LL_ENDL; - - GtkDialogFlags flags = GTK_DIALOG_MODAL; - GtkMessageType messagetype; - GtkButtonsType buttons; - switch (type) - { default: case OSMB_OK: - messagetype = GTK_MESSAGE_WARNING; - buttons = GTK_BUTTONS_OK; + oData.flags = SDL_MESSAGEBOX_WARNING; + oData.buttons = btnOk; + oData.numbuttons = 1; break; case OSMB_OKCANCEL: - messagetype = GTK_MESSAGE_QUESTION; - buttons = GTK_BUTTONS_OK_CANCEL; + oData.flags = SDL_MESSAGEBOX_INFORMATION; + oData.buttons = btnOkCancel; + oData.numbuttons = 2; break; case OSMB_YESNO: - messagetype = GTK_MESSAGE_QUESTION; - buttons = GTK_BUTTONS_YES_NO; + oData.flags = SDL_MESSAGEBOX_INFORMATION; + oData.buttons = btnYesNo; + oData.numbuttons = 2; break; - } - win = gtk_message_dialog_new(NULL, flags, messagetype, buttons, "%s", - text.c_str()); - -# if LL_X11 - // Make GTK tell the window manager to associate this - // dialog with our non-GTK SDL window, which should try - // to keep it on top etc. - if (gWindowImplementation && - gWindowImplementation->mSDL_XWindowID != None) - { - gtk_widget_realize(GTK_WIDGET(win)); // so we can get its gdkwin - GdkWindow *gdkwin = gdk_window_foreign_new(gWindowImplementation->mSDL_XWindowID); - gdk_window_set_transient_for(GTK_WIDGET(win)->window, - gdkwin); - } -# endif //LL_X11 - - gtk_window_set_position(GTK_WINDOW(win), - GTK_WIN_POS_CENTER_ON_PARENT); - - gtk_window_set_type_hint(GTK_WINDOW(win), - GDK_WINDOW_TYPE_HINT_DIALOG); - - if (!caption.empty()) - gtk_window_set_title(GTK_WINDOW(win), caption.c_str()); - - gint response = GTK_RESPONSE_NONE; - g_signal_connect (win, - "response", - G_CALLBACK (response_callback), - &response); - - // we should be able to use a gtk_dialog_run(), but it's - // apparently not written to exist in a world without a higher - // gtk_main(), so we manage its signal/destruction outselves. - gtk_widget_show_all (win); - gtk_main(); - - //LL_INFOS() << "response: " << response << LL_ENDL; - switch (response) - { - case GTK_RESPONSE_OK: rtn = OSBTN_OK; break; - case GTK_RESPONSE_YES: rtn = OSBTN_YES; break; - case GTK_RESPONSE_NO: rtn = OSBTN_NO; break; - case GTK_RESPONSE_APPLY: rtn = OSBTN_OK; break; - case GTK_RESPONSE_NONE: - case GTK_RESPONSE_CANCEL: - case GTK_RESPONSE_CLOSE: - case GTK_RESPONSE_DELETE_EVENT: - default: rtn = OSBTN_CANCEL; - } - } - else - { - LL_INFOS() << "MSGBOX: " << caption << ": " << text << LL_ENDL; - LL_INFOS() << "Skipping dialog because we're in fullscreen mode or GTK is not happy." << LL_ENDL; - rtn = OSBTN_OK; } - if(gWindowImplementation != NULL) - gWindowImplementation->afterDialog(); + int btn{0}; + if( 0 == SDL_ShowMessageBox( &oData, &btn ) ) + return btn; + return OSBTN_CANCEL; +} - return rtn; +bool LLWindowSDL::dialogColorPicker( F32 *r, F32 *g, F32 *b) +{ + return (false); } -static void color_changed_callback(GtkWidget *widget, - gpointer user_data) +#if LL_DARWIN +LLSD LLWindowSDL::getNativeKeyData() { - GtkColorSelection *colorsel = GTK_COLOR_SELECTION(widget); - GdkColor *colorp = (GdkColor*)user_data; + LLSD result = LLSD::emptyMap(); - gtk_color_selection_get_current_color(colorsel, colorp); -} + if(mRawKeyEvent) + { + result["event_type"] = LLSD::Integer(mRawKeyEvent->mEventType); + result["event_modifiers"] = LLSD::Integer(mRawKeyEvent->mEventModifiers); + result["event_keycode"] = LLSD::Integer(mRawKeyEvent->mEventKeyCode); + result["event_chars"] = (mRawKeyEvent->mEventChars) ? LLSD(LLSD::Integer(mRawKeyEvent->mEventChars)) : LLSD(); + result["event_umodchars"] = (mRawKeyEvent->mEventUnmodChars) ? LLSD(LLSD::Integer(mRawKeyEvent->mEventUnmodChars)) : LLSD(); + result["event_isrepeat"] = LLSD::Boolean(mRawKeyEvent->mEventRepeat); + } + LL_DEBUGS() << "native key data is: " << result << LL_ENDL; + return result; +} +#else /* Make the raw keyboard data available - used to poke through to LLQtWebKit so that Qt/Webkit has access to the virtual keycodes etc. that it needs */ LLSD LLWindowSDL::getNativeKeyData() { - LLSD result = LLSD::emptyMap(); + LLSD result = LLSD::emptyMap(); U32 modifiers = 0; // pretend-native modifiers... oh what a tangled web we weave! @@ -2377,99 +2590,15 @@ LLSD LLWindowSDL::getNativeKeyData() // *todo: test ALTs - I don't have a case for testing these. Do you? // *todo: NUM? - I don't care enough right now (and it's not a GDK modifier). - result["scan_code"] = (S32)mKeyScanCode; - result["virtual_key"] = (S32)mKeyVirtualKey; + result["virtual_key"] = (S32)mKeyVirtualKey; + result["virtual_key_win"] = (S32)LLKeyboardSDL::mapSDL2toWin( mKeyVirtualKey ); result["modifiers"] = (S32)modifiers; - - return result; -} - - -bool LLWindowSDL::dialogColorPicker( F32 *r, F32 *g, F32 *b) -{ - bool rtn = false; - - beforeDialog(); - - if (ll_try_gtk_init()) - { - GtkWidget *win = NULL; - - win = gtk_color_selection_dialog_new(NULL); - -# if LL_X11 - // Get GTK to tell the window manager to associate this - // dialog with our non-GTK SDL window, which should try - // to keep it on top etc. - if (mSDL_XWindowID != None) - { - gtk_widget_realize(GTK_WIDGET(win)); // so we can get its gdkwin - GdkWindow *gdkwin = gdk_window_foreign_new(mSDL_XWindowID); - gdk_window_set_transient_for(GTK_WIDGET(win)->window, - gdkwin); - } -# endif //LL_X11 - - GtkColorSelection *colorsel = GTK_COLOR_SELECTION (GTK_COLOR_SELECTION_DIALOG(win)->colorsel); - - GdkColor color, orig_color; - orig_color.pixel = 0; - orig_color.red = guint16(65535 * *r); - orig_color.green= guint16(65535 * *g); - orig_color.blue = guint16(65535 * *b); - color = orig_color; - - gtk_color_selection_set_previous_color (colorsel, &color); - gtk_color_selection_set_current_color (colorsel, &color); - gtk_color_selection_set_has_palette (colorsel, true); - gtk_color_selection_set_has_opacity_control(colorsel, false); - - gint response = GTK_RESPONSE_NONE; - g_signal_connect (win, - "response", - G_CALLBACK (response_callback), - &response); - - g_signal_connect (G_OBJECT (colorsel), "color_changed", - G_CALLBACK (color_changed_callback), - &color); - - gtk_window_set_modal(GTK_WINDOW(win), true); - gtk_widget_show_all(win); - // hide the help button - we don't service it. - gtk_widget_hide(GTK_COLOR_SELECTION_DIALOG(win)->help_button); - gtk_main(); - - if (response == GTK_RESPONSE_OK && - (orig_color.red != color.red - || orig_color.green != color.green - || orig_color.blue != color.blue) ) - { - *r = color.red / 65535.0f; - *g = color.green / 65535.0f; - *b = color.blue / 65535.0f; - rtn = true; - } - } - - afterDialog(); - - return rtn; -} -#else -S32 OSMessageBoxSDL(const std::string& text, const std::string& caption, U32 type) -{ - LL_INFOS() << "MSGBOX: " << caption << ": " << text << LL_ENDL; - return 0; -} - -bool LLWindowSDL::dialogColorPicker( F32 *r, F32 *g, F32 *b) -{ - return (false); + result["input_type"] = mInputType; + return result; } -#endif // LL_GTK +#endif // LL_DARWIN -#if LL_LINUX +#if LL_LINUX || LL_SOLARIS || __FreeBSD__ // extracted from spawnWebBrowser for clarity and to eliminate // compiler confusion regarding close(int fd) vs. LLWindow::close() void exec_cmd(const std::string& cmd, const std::string& arg) @@ -2481,9 +2610,32 @@ void exec_cmd(const std::string& cmd, const std::string& arg) { // child // disconnect from stdin/stdout/stderr, or child will // keep our output pipe undesirably alive if it outlives us. - close(0); - close(1); - close(2); + // close(0); + // close(1); + // close(2); + // <FS:TS> Reopen stdin, stdout, and stderr to /dev/null. + // It's good practice to always have those file + // descriptors open to something, lest the exec'd + // program actually try to use them. + FILE *result; + result = freopen("/dev/null","r",stdin); + if (result == NULL) + { + LL_WARNS() << "Error reopening stdin for web browser: " + << strerror(errno) << LL_ENDL; + } + result = freopen("/dev/null","w",stdout); + if (result == NULL) + { + LL_WARNS() << "Error reopening stdout for web browser: " + << strerror(errno) << LL_ENDL; + } + result = freopen("/dev/null","w",stderr); + if (result == NULL) + { + LL_WARNS() << "Error reopening stderr for web browser: " + << strerror(errno) << LL_ENDL; + } // end ourself by running the command execv(cmd.c_str(), argv); /* Flawfinder: ignore */ // if execv returns at all, there was a problem. @@ -2525,7 +2677,7 @@ void LLWindowSDL::spawnWebBrowser(const std::string& escaped_url, bool async) LL_INFOS() << "spawn_web_browser: " << escaped_url << LL_ENDL; -#if LL_LINUX +#if LL_LINUX || __FreeBSD__ # if LL_X11 if (mSDL_Display) { @@ -2537,43 +2689,65 @@ void LLWindowSDL::spawnWebBrowser(const std::string& escaped_url, bool async) # endif // LL_X11 std::string cmd, arg; +#ifdef LL_USESYSTEMLIBS + cmd = gDirUtilp->getExecutableDir(); +#else cmd = gDirUtilp->getAppRODataDir(); cmd += gDirUtilp->getDirDelimiter(); cmd += "etc"; +#endif cmd += gDirUtilp->getDirDelimiter(); cmd += "launch_url.sh"; arg = escaped_url; exec_cmd(cmd, arg); -#endif // LL_LINUX - LL_INFOS() << "spawn_web_browser returning." << LL_ENDL; -} +#elif LL_DARWIN + S32 result = 0; + CFURLRef urlRef = NULL; -void *LLWindowSDL::getPlatformWindow() -{ -#if LL_GTK && LL_LLMOZLIB_ENABLED - if (LLWindowSDL::ll_try_gtk_init()) + LL_INFOS() << "Opening URL " << escaped_url << LL_ENDL; + + CFStringRef stringRef = CFStringCreateWithCString(NULL, escaped_url.c_str(), kCFStringEncodingUTF8); + if (stringRef) { - maybe_lock_display(); + // This will succeed if the string is a full URL, including the http:// + // Note that URLs specified this way need to be properly percent-escaped. + urlRef = CFURLCreateWithString(NULL, stringRef, NULL); - GtkWidget *owin = gtk_window_new(GTK_WINDOW_POPUP); - // Why a layout widget? A MozContainer would be ideal, but - // it involves exposing Mozilla headers to mozlib-using apps. - // A layout widget with a GtkWindow parent has the desired - // properties of being plain GTK, having a window, and being - // derived from a GtkContainer. - GtkWidget *rtnw = gtk_layout_new(NULL, NULL); - gtk_container_add(GTK_CONTAINER(owin), rtnw); - gtk_widget_realize(rtnw); - GTK_WIDGET_UNSET_FLAGS(GTK_WIDGET(rtnw), GTK_NO_WINDOW); + // Don't use CRURLCreateWithFileSystemPath -- only want valid URLs - maybe_unlock_display(); + CFRelease(stringRef); + } - return rtnw; + if (urlRef) + { + result = LSOpenCFURLRef(urlRef, NULL); + + if (result != noErr) + { + LL_INFOS() << "Error " << result << " on open." << LL_ENDL; + } + + CFRelease(urlRef); } -#endif // LL_GTK && LL_LLMOZLIB_ENABLED - // Unixoid mozilla really needs GTK. + else + { + LL_INFOS() << "Error: couldn't create URL." << LL_ENDL; + } + +#endif // LL_LINUX + + LL_INFOS() << "spawn_web_browser returning." << LL_ENDL; +} + +void LLWindowSDL::openFile(const std::string& file_name) +{ + spawnWebBrowser("file://"+file_name,true); +} + +void *LLWindowSDL::getPlatformWindow() +{ return NULL; } @@ -2634,10 +2808,10 @@ std::vector<std::string> LLWindowSDL::getDynamicFallbackFontList() LL_INFOS("AppInit") << "Variant " << locale->variant << LL_ENDL; LL_INFOS() << "Preferring fonts of language: " - << locale->lang - << LL_ENDL; + << locale->lang + << LL_ENDL; sort_order = "lang=" + std::string(locale->lang) + ":" - + sort_order; + + sort_order; } } FL_FreeLocale(&locale); @@ -2655,7 +2829,7 @@ std::vector<std::string> LLWindowSDL::getDynamicFallbackFontList() // Sort the list of system fonts from most-to-least-desirable. FcResult result; fs = FcFontSort(NULL, sortpat, elide_unicode_coverage, - NULL, &result); + NULL, &result); FcPatternDestroy(sortpat); } @@ -2669,8 +2843,8 @@ std::vector<std::string> LLWindowSDL::getDynamicFallbackFontList() { FcChar8 *filename; if (FcResultMatch == FcPatternGetString(fs->fonts[i], - FC_FILE, 0, - &filename) + FC_FILE, 0, + &filename) && filename) { rtns.push_back(std::string((const char*)filename)); @@ -2694,4 +2868,64 @@ std::vector<std::string> LLWindowSDL::getDynamicFallbackFontList() return rtns; } -#endif // LL_SDL + +void* LLWindowSDL::createSharedContext() +{ + auto *pContext = SDL_GL_CreateContext(mWindow); + if ( pContext) + { + SDL_GL_SetSwapInterval(0); + SDL_GL_MakeCurrent(mWindow, mContext); + + LLCoordScreen size; + if (getSize(&size)) + setSize(size); + + LL_DEBUGS() << "Creating shared OpenGL context successful!" << LL_ENDL; + + return (void*)pContext; + } + + LL_WARNS() << "Creating shared OpenGL context failed!" << LL_ENDL; + + return nullptr; +} + +void LLWindowSDL::makeContextCurrent(void* contextPtr) +{ + LL_PROFILER_GPU_CONTEXT; + SDL_GL_MakeCurrent( mWindow, contextPtr ); +} + +void LLWindowSDL::destroySharedContext(void* contextPtr) +{ + SDL_GL_DeleteContext( contextPtr ); +} + +void LLWindowSDL::toggleVSync(bool enable_vsync) +{ + if( !enable_vsync) + { + SDL_GL_SetSwapInterval(0); + SDL_SetHintWithPriority(SDL_HINT_RENDER_VSYNC,"0",SDL_HINT_OVERRIDE); + } + else + { + SDL_GL_SetSwapInterval(1); + SDL_SetHintWithPriority(SDL_HINT_RENDER_VSYNC,"1",SDL_HINT_OVERRIDE); + } +} + +void LLWindowSDL::setLanguageTextInput(const LLCoordGL& position) +{ + LLCoordWindow win_pos; + convertCoords( position, &win_pos ); + + SDL_Rect r; + r.x = win_pos.mX; + r.y = win_pos.mY; + r.w = 500; + r.h = 16; + + SDL_SetTextInputRect(&r); +} diff --git a/indra/llwindow/llwindowsdl.h b/indra/llwindow/llwindowsdl.h index 196ad2986d..3ed2811572 100644 --- a/indra/llwindow/llwindowsdl.h +++ b/indra/llwindow/llwindowsdl.h @@ -24,20 +24,24 @@ * $/LicenseInfo$ */ -#ifndef LL_LLWINDOWSDL_H -#define LL_LLWINDOWSDL_H +#ifndef LL_LLWINDOWSDL2_H +#define LL_LLWINDOWSDL2_H // Simple Directmedia Layer (http://libsdl.org/) implementation of LLWindow class #include "llwindow.h" #include "lltimer.h" -#include "SDL/SDL.h" -#include "SDL/SDL_endian.h" +#if !defined(__i386__) && !defined(__x86_64__) +#define SDL_DISABLE_IMMINTRIN_H +#endif +#include "SDL2/SDL.h" +#include "SDL2/SDL_video.h" +#include "SDL2/SDL_endian.h" #if LL_X11 // get X11-specific headers for use in low-level stuff like copy-and-paste support -#include "SDL/SDL_syswm.h" +#include "SDL2/SDL_syswm.h" #endif // AssertMacros.h does bad things. @@ -46,83 +50,141 @@ #undef require -class LLWindowSDL : public LLWindow -{ +class LLWindowSDL : public LLWindow { public: - /*virtual*/ void show(); - /*virtual*/ void hide(); - /*virtual*/ void close(); - /*virtual*/ bool getVisible(); - /*virtual*/ bool getMinimized(); - /*virtual*/ bool getMaximized(); - /*virtual*/ bool maximize(); - /*virtual*/ void minimize(); - /*virtual*/ void restore(); - /*virtual*/ bool getFullscreen(); - /*virtual*/ bool getPosition(LLCoordScreen *position); - /*virtual*/ bool getSize(LLCoordScreen *size); - /*virtual*/ bool getSize(LLCoordWindow *size); - /*virtual*/ bool setPosition(LLCoordScreen position); - /*virtual*/ bool setSizeImpl(LLCoordScreen size); - /*virtual*/ bool setSizeImpl(LLCoordWindow size); - /*virtual*/ bool switchContext(bool fullscreen, const LLCoordScreen &size, bool disable_vsync, const LLCoordScreen * const posp = NULL); - /*virtual*/ bool setCursorPosition(LLCoordWindow position); - /*virtual*/ bool getCursorPosition(LLCoordWindow *position); - /*virtual*/ void showCursor(); - /*virtual*/ void hideCursor(); - /*virtual*/ void showCursorFromMouseMove(); - /*virtual*/ void hideCursorUntilMouseMove(); - /*virtual*/ bool isCursorHidden(); - /*virtual*/ void updateCursor(); - /*virtual*/ void captureMouse(); - /*virtual*/ void releaseMouse(); - /*virtual*/ void setMouseClipping( bool b ); - /*virtual*/ void setMinSize(U32 min_width, U32 min_height, bool enforce_immediately = true); - - /*virtual*/ bool isClipboardTextAvailable(); - /*virtual*/ bool pasteTextFromClipboard(LLWString &dst); - /*virtual*/ bool copyTextToClipboard(const LLWString & src); - - /*virtual*/ bool isPrimaryTextAvailable(); - /*virtual*/ bool pasteTextFromPrimary(LLWString &dst); - /*virtual*/ bool copyTextToPrimary(const LLWString & src); - - /*virtual*/ void flashIcon(F32 seconds); - /*virtual*/ F32 getGamma(); - /*virtual*/ bool setGamma(const F32 gamma); // Set the gamma - /*virtual*/ U32 getFSAASamples(); - /*virtual*/ void setFSAASamples(const U32 samples); - /*virtual*/ bool restoreGamma(); // Restore original gamma table (before updating gamma) - /*virtual*/ ESwapMethod getSwapMethod() { return mSwapMethod; } - /*virtual*/ void processMiscNativeEvents(); - /*virtual*/ void gatherInput(); - /*virtual*/ void swapBuffers(); - /*virtual*/ void restoreGLContext() {}; - - /*virtual*/ void delayInputProcessing() { }; + void show() override; + + void hide() override; + + void close() override; + + bool getVisible() override; + + bool getMinimized() override; + + bool getMaximized() override; + + bool maximize() override; + + void minimize() override; + + void restore() override; + + bool getFullscreen(); + + bool getPosition(LLCoordScreen *position) override; + + bool getSize(LLCoordScreen *size) override; + + bool getSize(LLCoordWindow *size) override; + + bool setPosition(LLCoordScreen position) override; + + bool setSizeImpl(LLCoordScreen size) override; + + bool setSizeImpl(LLCoordWindow size) override; + + bool switchContext(bool fullscreen, const LLCoordScreen &size, bool disable_vsync, + const LLCoordScreen *const posp = NULL) override; + + bool setCursorPosition(LLCoordWindow position) override; + + bool getCursorPosition(LLCoordWindow *position) override; + + void showCursor() override; + + void hideCursor() override; + + void showCursorFromMouseMove() override; + + void hideCursorUntilMouseMove() override; + + bool isCursorHidden() override; + + void updateCursor() override; + + void captureMouse() override; + + void releaseMouse() override; + + void setMouseClipping(bool b) override; + + void setMinSize(U32 min_width, U32 min_height, bool enforce_immediately = true) override; + + bool isClipboardTextAvailable() override; + + bool pasteTextFromClipboard(LLWString &dst) override; + + bool copyTextToClipboard(const LLWString &src) override; + + bool isPrimaryTextAvailable() override; + + bool pasteTextFromPrimary(LLWString &dst) override; + + bool copyTextToPrimary(const LLWString &src) override; + + void flashIcon(F32 seconds) override; + + F32 getGamma() override; + + bool setGamma(const F32 gamma) override; // Set the gamma + U32 getFSAASamples() override; + + void setFSAASamples(const U32 samples) override; + + bool restoreGamma() override; // Restore original gamma table (before updating gamma) + ESwapMethod getSwapMethod() override { return mSwapMethod; } + + void processMiscNativeEvents() override; + + void gatherInput() override; + + void swapBuffers() override; + + void restoreGLContext() {}; + + void delayInputProcessing() override {}; // handy coordinate space conversion routines - /*virtual*/ bool convertCoords(LLCoordScreen from, LLCoordWindow *to); - /*virtual*/ bool convertCoords(LLCoordWindow from, LLCoordScreen *to); - /*virtual*/ bool convertCoords(LLCoordWindow from, LLCoordGL *to); - /*virtual*/ bool convertCoords(LLCoordGL from, LLCoordWindow *to); - /*virtual*/ bool convertCoords(LLCoordScreen from, LLCoordGL *to); - /*virtual*/ bool convertCoords(LLCoordGL from, LLCoordScreen *to); + bool convertCoords(LLCoordScreen from, LLCoordWindow *to) override; + + bool convertCoords(LLCoordWindow from, LLCoordScreen *to) override; + + bool convertCoords(LLCoordWindow from, LLCoordGL *to) override; + + bool convertCoords(LLCoordGL from, LLCoordWindow *to) override; + + bool convertCoords(LLCoordScreen from, LLCoordGL *to) override; + + bool convertCoords(LLCoordGL from, LLCoordScreen *to) override; - /*virtual*/ LLWindowResolution* getSupportedResolutions(S32 &num_resolutions); - /*virtual*/ F32 getNativeAspectRatio(); - /*virtual*/ F32 getPixelAspectRatio(); - /*virtual*/ void setNativeAspectRatio(F32 ratio) { mOverrideAspectRatio = ratio; } + LLWindowResolution *getSupportedResolutions(S32 &num_resolutions) override; - /*virtual*/ void beforeDialog(); - /*virtual*/ void afterDialog(); + F32 getNativeAspectRatio() override; - /*virtual*/ bool dialogColorPicker(F32 *r, F32 *g, F32 *b); + F32 getPixelAspectRatio() override; - /*virtual*/ void *getPlatformWindow(); - /*virtual*/ void bringToFront(); + void setNativeAspectRatio(F32 ratio) override { mOverrideAspectRatio = ratio; } - /*virtual*/ void spawnWebBrowser(const std::string& escaped_url, bool async); + F32 getSystemUISize() override; + + void beforeDialog() override; + + void afterDialog() override; + + bool dialogColorPicker(F32 *r, F32 *g, F32 *b) override; + + void *getPlatformWindow() override; + + void bringToFront() override; + + void setLanguageTextInput(const LLCoordGL& pos) override; + + void spawnWebBrowser(const std::string &escaped_url, bool async) override; + + void openFile(const std::string &file_name); + + void setTitle(const std::string title) override; static std::vector<std::string> getDynamicFallbackFontList(); @@ -132,40 +194,56 @@ public: Window mSDL_XWindowID; Display *mSDL_Display; #endif + void (*Lock_Display)(void); - void (*Unlock_Display)(void); -#if LL_GTK - // Lazily initialize and check the runtime GTK version for goodness. - static bool ll_try_gtk_init(void); -#endif // LL_GTK + void (*Unlock_Display)(void); #if LL_X11 + static Window get_SDL_XWindowID(void); - static Display* get_SDL_Display(void); + + static Display *get_SDL_Display(void); + #endif // LL_X11 +#if LL_DARWIN + static bool sUseMultGL; +#endif + + void *createSharedContext() override; + + void makeContextCurrent(void *context) override; + + void destroySharedContext(void *context) override; + + void toggleVSync(bool enable_vsync) override; + protected: - LLWindowSDL(LLWindowCallbacks* callbacks, - const std::string& title, int x, int y, int width, int height, U32 flags, - bool fullscreen, bool clearBg, bool disable_vsync, bool use_gl, - bool ignore_pixel_depth, U32 fsaa_samples); + LLWindowSDL(LLWindowCallbacks *callbacks, + const std::string &title, int x, int y, int width, int height, U32 flags, + bool fullscreen, bool clearBg, bool disable_vsync, bool use_gl, + bool ignore_pixel_depth, U32 fsaa_samples); + ~LLWindowSDL(); - /*virtual*/ bool isValid(); - /*virtual*/ LLSD getNativeKeyData(); + bool isValid() override; + + LLSD getNativeKeyData() override; - void initCursors(); - void quitCursors(); - void moveWindow(const LLCoordScreen& position,const LLCoordScreen& size); + void initCursors(); + + void quitCursors(); + + void moveWindow(const LLCoordScreen &position, const LLCoordScreen &size); // Changes display resolution. Returns true if successful - bool setDisplayResolution(S32 width, S32 height, S32 bits, S32 refresh); + bool setDisplayResolution(S32 width, S32 height, S32 bits, S32 refresh); // Go back to last fullscreen display resolution. - bool setFullscreenResolution(); + bool setFullscreenResolution(); - bool shouldPostQuit() { return mPostQuit; } + bool shouldPostQuit() { return mPostQuit; } protected: // @@ -174,46 +252,84 @@ protected: // create or re-create the GL context/window. Called from the constructor and switchContext(). bool createContext(int x, int y, int width, int height, int bits, bool fullscreen, bool disable_vsync); + void destroyContext(); - void setupFailure(const std::string& text, const std::string& caption, U32 type); + + void setupFailure(const std::string &text, const std::string &caption, U32 type); + void fixWindowSize(void); - U32 SDLCheckGrabbyKeys(SDLKey keysym, bool gain); + + U32 SDLCheckGrabbyKeys(U32 keysym, bool gain); + bool SDLReallyCaptureInput(bool capture); // // Platform specific variables // - U32 mGrabbyKeyFlags; - int mReallyCapturedCount; - SDL_Surface * mWindow; + U32 mGrabbyKeyFlags; + int mReallyCapturedCount; + + SDL_Window *mWindow; + SDL_GLContext mContext; + SDL_Cursor *mSDLCursors[UI_CURSOR_COUNT]; + std::string mWindowTitle; - double mOriginalAspectRatio; - bool mNeedsResize; // Constructor figured out the window is too big, it needs a resize. - LLCoordScreen mNeedsResizeSize; - F32 mOverrideAspectRatio; - F32 mGamma; - U32 mFSAASamples; + double mOriginalAspectRatio; + bool mNeedsResize; // Constructor figured out the window is too big, it needs a resize. + LLCoordScreen mNeedsResizeSize; + F32 mOverrideAspectRatio; + F32 mGamma; + U32 mFSAASamples; - int mSDLFlags; + int mSDLFlags; - SDL_Cursor* mSDLCursors[UI_CURSOR_COUNT]; - int mHaveInputFocus; /* 0=no, 1=yes, else unknown */ - int mIsMinimized; /* 0=no, 1=yes, else unknown */ + int mHaveInputFocus; /* 0=no, 1=yes, else unknown */ + int mIsMinimized; /* 0=no, 1=yes, else unknown */ + int mIsActive; /* 0=no, 1=yes, else unknown */ friend class LLWindowManager; private: #if LL_X11 + void x11_set_urgent(bool urgent); + bool mFlashing; LLTimer mFlashTimer; #endif //LL_X11 - U32 mKeyScanCode; - U32 mKeyVirtualKey; - SDLMod mKeyModifiers; -}; + U32 mKeyVirtualKey; + U32 mKeyModifiers; + std::string mInputType; + +public: +#if LL_X11 + + static Display *getSDLDisplay(); + LLWString const &getPrimaryText() const { return mPrimaryClipboard; } + + LLWString const &getSecondaryText() const { return mSecondaryClipboard; } + + void clearPrimaryText() { mPrimaryClipboard.clear(); } + + void clearSecondaryText() { mSecondaryClipboard.clear(); } + +private: + void initialiseX11Clipboard(); + + bool getSelectionText(Atom selection, LLWString &text); + + bool getSelectionText(Atom selection, Atom type, LLWString &text); + + bool setSelectionText(Atom selection, const LLWString &text); +#endif + + void tryFindFullscreenSize(int &aWidth, int &aHeight); + + LLWString mPrimaryClipboard; + LLWString mSecondaryClipboard; +}; class LLSplashScreenSDL : public LLSplashScreen { @@ -221,9 +337,9 @@ public: LLSplashScreenSDL(); virtual ~LLSplashScreenSDL(); - /*virtual*/ void showImpl(); - /*virtual*/ void updateImpl(const std::string& mesg); - /*virtual*/ void hideImpl(); + void showImpl(); + void updateImpl(const std::string& mesg); + void hideImpl(); }; S32 OSMessageBoxSDL(const std::string& text, const std::string& caption, U32 type); diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index f0f7e03691..fee0de7739 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -163,18 +163,7 @@ HGLRC SafeCreateContext(HDC &hdc) GLuint SafeChoosePixelFormat(HDC &hdc, const PIXELFORMATDESCRIPTOR *ppfd) { - __try - { - return ChoosePixelFormat(hdc, ppfd); - } - __except (EXCEPTION_EXECUTE_HANDLER) - { - // convert to C++ styled exception - // C exception don't allow classes, so it's a regular char array - char integer_string[32]; - sprintf(integer_string, "SEH, code: %lu\n", GetExceptionCode()); - throw std::exception(integer_string); - } + return LL::seh::catcher([hdc, ppfd]{ return ChoosePixelFormat(hdc, ppfd); }); } //static diff --git a/indra/llxml/CMakeLists.txt b/indra/llxml/CMakeLists.txt index 508c2b919b..03ac4bc9f2 100644 --- a/indra/llxml/CMakeLists.txt +++ b/indra/llxml/CMakeLists.txt @@ -4,6 +4,7 @@ project(llxml) include(00-Common) include(LLCommon) +include(LLWindow) set(llxml_SOURCE_FILES llcontrol.cpp @@ -31,9 +32,11 @@ target_link_libraries( llxml llmath llcommon ll::expat + ll::SDL ) target_include_directories( llxml INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) +include(LibraryInstall) # tests diff --git a/indra/llxml/llxmlnode.cpp b/indra/llxml/llxmlnode.cpp index 0fd4516844..acfd3fb213 100644 --- a/indra/llxml/llxmlnode.cpp +++ b/indra/llxml/llxmlnode.cpp @@ -29,6 +29,9 @@ #include <iostream> #include <map> +#if LL_SDL +#include <SDL_rwops.h> +#endif #include "llxmlnode.h" diff --git a/indra/llxml/llxmltree.cpp b/indra/llxml/llxmltree.cpp index 0ace1baf2a..d66544d0f8 100644 --- a/indra/llxml/llxmltree.cpp +++ b/indra/llxml/llxmltree.cpp @@ -108,14 +108,17 @@ LLXmlTreeNode::LLXmlTreeNode( const std::string& name, LLXmlTreeNode* parent, LL LLXmlTreeNode::~LLXmlTreeNode() { - attribute_map_t::iterator iter; - for (iter=mAttributes.begin(); iter != mAttributes.end(); iter++) - delete iter->second; - for(LLXmlTreeNode* node : mChildren) - { - delete node; - } - mChildren.clear(); + for (auto& attr : mAttributes) + { + delete attr.second; + } + mAttributes.clear(); + + for (auto& child : mChildren) + { + delete child; + } + mChildren.clear(); } void LLXmlTreeNode::dump( const std::string& prefix ) diff --git a/indra/media_plugins/CMakeLists.txt b/indra/media_plugins/CMakeLists.txt index 972bb7dd2d..78bdba8f18 100644 --- a/indra/media_plugins/CMakeLists.txt +++ b/indra/media_plugins/CMakeLists.txt @@ -2,9 +2,15 @@ add_subdirectory(base) +if (CMAKE_SYSTEM_NAME MATCHES "FreeBSD") + add_subdirectory(example) + add_subdirectory(libvlc) +endif (CMAKE_SYSTEM_NAME MATCHES "FreeBSD") + if (LINUX) - #add_subdirectory(gstreamer010) + add_subdirectory(cef) add_subdirectory(example) + add_subdirectory(libvlc) endif (LINUX) if (DARWIN) diff --git a/indra/media_plugins/base/CMakeLists.txt b/indra/media_plugins/base/CMakeLists.txt index 64b6a4228d..57e3782ada 100644 --- a/indra/media_plugins/base/CMakeLists.txt +++ b/indra/media_plugins/base/CMakeLists.txt @@ -12,13 +12,6 @@ include(PluginAPI) ### media_plugin_base -if(NOT ADDRESS_SIZE EQUAL 32) - if(WINDOWS) - ##add_definitions(/FIXED:NO) - else(WINDOWS) # not windows therefore gcc LINUX and DARWIN - add_definitions(-fPIC) - endif(WINDOWS) -endif(NOT ADDRESS_SIZE EQUAL 32) set(media_plugin_base_SOURCE_FILES media_plugin_base.cpp @@ -31,6 +24,7 @@ set(media_plugin_base_HEADER_FILES ) add_library(media_plugin_base + STATIC ${media_plugin_base_SOURCE_FILES} ) diff --git a/indra/media_plugins/base/media_plugin_base.cpp b/indra/media_plugins/base/media_plugin_base.cpp index 545eee25a9..d54e67c532 100644 --- a/indra/media_plugins/base/media_plugin_base.cpp +++ b/indra/media_plugins/base/media_plugin_base.cpp @@ -167,10 +167,60 @@ void MediaPluginBase::sendStatus() sendMessage(message); } +#if LL_LINUX || __FreeBSD__ + +size_t SymbolGrabber::registerSymbol( SymbolToGrab aSymbol ) +{ + gSymbolsToGrab.emplace_back(aSymbol); + return gSymbolsToGrab.size(); +} + +bool SymbolGrabber::grabSymbols(std::vector< std::string > const &aDSONames) +{ + std::cerr << "SYMBOLS: " << gSymbolsToGrab.size() << std::endl; + + if (sSymsGrabbed) + return true; + + //attempt to load the shared libraries + apr_pool_create(&sSymDSOMemoryPool, nullptr); + + for( std::vector< std::string >::const_iterator itr = aDSONames.begin(); itr != aDSONames.end(); ++itr ) + { + apr_dso_handle_t *pDSO(NULL); + std::string strDSO{ *itr }; + if( APR_SUCCESS == apr_dso_load( &pDSO, strDSO.c_str(), sSymDSOMemoryPool )) + sLoadedLibraries.push_back( pDSO ); + + for( auto i = 0; i < gSymbolsToGrab.size(); ++i ) + { + if( !*gSymbolsToGrab[i].mPPFunc ) + apr_dso_sym( gSymbolsToGrab[i].mPPFunc, pDSO, gSymbolsToGrab[i].mName ); + } + } + + bool sym_error = false; + + for( auto i = 0; i < gSymbolsToGrab.size(); ++i ) + { + if( gSymbolsToGrab[ i ].mRequired && ! *gSymbolsToGrab[ i ].mPPFunc ) + sym_error = true; + } + + sSymsGrabbed = !sym_error; + return sSymsGrabbed; +} + +void SymbolGrabber::ungrabSymbols() +{ + +} +#endif + #if LL_WINDOWS # define LLSYMEXPORT __declspec(dllexport) -#elif LL_LINUX +#elif LL_LINUX || __FreeBSD__ # define LLSYMEXPORT __attribute__ ((visibility("default"))) #else # define LLSYMEXPORT /**/ @@ -204,3 +254,50 @@ int WINAPI DllEntryPoint( HINSTANCE hInstance, unsigned long reason, void* param return 1; } #endif + +#if LL_LINUX +pid_t getParentPid( pid_t aPid ) +{ + std::stringstream strm; + strm << "/proc/" << aPid << "/status"; + std::ifstream in{ strm.str() }; + + if( !in.is_open() ) + return 0; + + pid_t res {0}; + while( !in.eof() && res == 0 ) + { + std::string line; + line.resize( 1024, 0 ); + in.getline( &line[0], line.length() ); + + auto i = line.find( "PPid:" ); + + if( i == std::string::npos ) + continue; + + char const *pIn = line.c_str() + 5; // Skip over pid; + while( *pIn != 0 && isspace( *pIn ) ) + ++pIn; + + if( *pIn ) + res = atoll( pIn ); + } + return res; +} + +bool isPluginPid( pid_t aPid ) +{ + auto myPid = getpid(); + + do + { + if( aPid == myPid ) + return true; + aPid = getParentPid( aPid ); + } while( aPid > 1 ); + + return false; +} +#endif diff --git a/indra/media_plugins/base/media_plugin_base.h b/indra/media_plugins/base/media_plugin_base.h index f65c712a66..a6f3bc7d71 100644 --- a/indra/media_plugins/base/media_plugin_base.h +++ b/indra/media_plugins/base/media_plugin_base.h @@ -32,6 +32,41 @@ #include "llpluginmessage.h" #include "llpluginmessageclasses.h" +#if LL_LINUX || __FreeBSD__ + +struct SymbolToGrab +{ + bool mRequired; + char const *mName; + apr_dso_handle_sym_t *mPPFunc; +}; + +class SymbolGrabber +{ +public: + size_t registerSymbol( SymbolToGrab aSymbol ); + bool grabSymbols(std::vector< std::string > const &aDSONames); + void ungrabSymbols(); + +private: + std::vector< SymbolToGrab > gSymbolsToGrab; + + bool sSymsGrabbed = false; + apr_pool_t *sSymDSOMemoryPool = nullptr; + std::vector<apr_dso_handle_t *> sLoadedLibraries; +}; + +extern SymbolGrabber gSymbolGrabber; + +// extern SymbolGrabber gSymbolGrabber; + +#define LL_GRAB_SYM(SYMBOL_GRABBER, REQUIRED, SYMBOL_NAME, RETURN, ...) \ + RETURN (*ll##SYMBOL_NAME)(__VA_ARGS__) = nullptr; \ + size_t gRegistered##SYMBOL_NAME = SYMBOL_GRABBER.registerSymbol( \ + { REQUIRED, #SYMBOL_NAME , (apr_dso_handle_sym_t*)&ll##SYMBOL_NAME} \ + ); + +#endif class MediaPluginBase { @@ -46,7 +81,6 @@ public: static void staticReceiveMessage(const char *message_string, void **user_data); protected: - /** Plugin status. */ typedef enum { @@ -126,4 +160,7 @@ int init_media_plugin( LLPluginInstance::sendMessageFunction *plugin_send_func, void **plugin_user_data); - +#if LL_LINUX +pid_t getParentPid(pid_t aPid); +bool isPluginPid(pid_t aPid); +#endif diff --git a/indra/media_plugins/cef/CMakeLists.txt b/indra/media_plugins/cef/CMakeLists.txt index 410778114d..7f44270fe7 100644 --- a/indra/media_plugins/cef/CMakeLists.txt +++ b/indra/media_plugins/cef/CMakeLists.txt @@ -10,18 +10,10 @@ include(Linking) include(PluginAPI) include(CEFPlugin) - +include(GLIB) ### media_plugin_cef -if(NOT ADDRESS_SIZE EQUAL 32) - if(WINDOWS) - ##add_definitions(/FIXED:NO) - else(WINDOWS) # not windows therefore gcc LINUX and DARWIN - add_definitions(-fPIC) - endif(WINDOWS) -endif(NOT ADDRESS_SIZE EQUAL 32) - set(media_plugin_cef_SOURCE_FILES media_plugin_cef.cpp ) @@ -32,10 +24,36 @@ set(media_plugin_cef_HEADER_FILES # Select which VolumeCatcher implementation to use if (LINUX) - message(FATAL_ERROR "CEF plugin has been enabled for a Linux compile.\n" - " Please create a volume_catcher implementation for this platform.") + foreach( PULSE_FILE pulse/introspect.h pulse/context.h pulse/subscribe.h pulse/glib-mainloop.h ) + find_path( PULSE_FILE_${PULSE_FILE}_FOUND ${PULSE_FILE} NO_CACHE) + if( NOT PULSE_FILE_${PULSE_FILE}_FOUND ) + message( "Looking for ${PULSE_FILE} ... not found") + message( FATAL_ERROR "Pulse header not found" ) + else() + message( "Looking for ${PULSE_FILE} ... found") + endif() + endforeach() + + include(FindPipeWire) + include_directories(SYSTEM ${PIPEWIRE_INCLUDE_DIRS} ${SPA_INCLUDE_DIRS}) + + message( "Building with Linux volume catcher for PipeWire and PulseAudio" ) + + list(APPEND media_plugin_cef_HEADER_FILES + linux/volume_catcher_linux.h + ) + + set(LINUX_VOLUME_CATCHER + linux/volume_catcher_linux.cpp + linux/volume_catcher_pulseaudio.cpp + linux/volume_catcher_pipewire.cpp + ) + + list(APPEND media_plugin_cef_SOURCE_FILES ${LINUX_VOLUME_CATCHER}) + set(CMAKE_SHARED_LINKER_FLAGS "-Wl,--build-id -Wl,-rpath,'$ORIGIN:$ORIGIN/../../lib'") + list(APPEND media_plugin_cef_LINK_LIBRARIES llwindow ) elseif (DARWIN) - list(APPEND media_plugin_cef_SOURCE_FILES mac_volume_catcher_null.cpp) + list(APPEND media_plugin_cef_SOURCE_FILES volume_catcher_null.cpp) find_library(CORESERVICES_LIBRARY CoreServices) find_library(AUDIOUNIT_LIBRARY AudioUnit) set( media_plugin_cef_LINK_LIBRARIES @@ -60,6 +78,7 @@ add_library(media_plugin_cef target_link_libraries(media_plugin_cef media_plugin_base ll::cef + ll::glib_headers ) if (WINDOWS) @@ -84,9 +103,42 @@ if (DARWIN) add_custom_command(TARGET media_plugin_cef POST_BUILD COMMAND ${CMAKE_INSTALL_NAME_TOOL} -change "@executable_path/Chromium Embedded Framework" "@executable_path/../../../../Frameworks/Chromium Embedded Framework.framework/Chromium Embedded Framework" + -change "/opt/local/lib/libopenjp2.7.dylib" "@loader_path/../../Frameworks/libopenjp2.7.dylib" + -change "/opt/local/lib/libpng16.16.dylib" "@loader_path/../../Frameworks/libpng16.16.dylib" + -change "/opt/local/lib/libjpeg.8.dylib" "@loader_path/../../Frameworks/libjpeg.8.dylib" + -change "/opt/local/lib/libfreetype.6.dylib" "@loader_path/../../Frameworks/libfreetype.6.dylib" + -change "/opt/local/lib/libaprutil-1.0.dylib" "@loader_path/../../Frameworks/libaprutil-1.0.dylib" + -change "/opt/local/lib/libiconv.2.dylib" "@loader_path/../../Frameworks/libiconv.2.dylib" + -change "/opt/local/lib/libapr-1.0.dylib" "@loader_path/../../Frameworks/libapr-1.0.dylib" + -change "/opt/local/lib/libexpat.1.dylib" "@loader_path/../../Frameworks/libexpat.1.dylib" + -change "/opt/local/lib/libjsoncpp.25.dylib" "@loader_path/../../Frameworks/libjsoncpp.25.dylib" + -change "/opt/local/lib/libz.1.dylib" "@loader_path/../../Frameworks/libz.1.dylib" + -change "/opt/local/libexec/boost/1.76/lib/libboost_context-mt.dylib" "@loader_path/../../Frameworks/libboost_context-mt.dylib" + -change "/opt/local/libexec/boost/1.76/lib/libboost_fiber-mt.dylib" "@loader_path/../../Frameworks/libboost_fiber-mt.dylib" + -change "/opt/local/libexec/boost/1.76/lib/libboost_filesystem-mt.dylib" "@loader_path/../../Frameworks/libboost_filesystem-mt.dylib" + -change "/opt/local/libexec/boost/1.76/lib/libboost_program_options-mt.dylib" "@loader_path/../../Frameworks/libboost_program_options-mt.dylib" + -change "/opt/local/libexec/boost/1.76/lib/libboost_regex-mt.dylib" "@loader_path/../../Frameworks/libboost_regex-mt.dylib" + -change "/opt/local/libexec/boost/1.76/lib/libboost_system-mt.dylib" "@loader_path/../../Frameworks/libboost_system-mt.dylib" + -change "/opt/local/libexec/boost/1.76/lib/libboost_thread-mt.dylib" "@loader_path/../../Frameworks/libboost_thread-mt.dylib" + -change "/opt/local/lib/liburiparser.1.dylib" "@loader_path/../../Frameworks/liburiparser.1.dylib" + -change "/opt/local/lib/libnghttp2.14.dylib" "@loader_path/../../Frameworks/libnghttp2.14.dylib" + -change "/usr/local/lib/libxmlrpc-epi.0.dylib" "@loader_path/../../Frameworks/libxmlrpc-epi.0.dylib" "$<TARGET_FILE:media_plugin_cef>" VERBATIM COMMENT "Fixing path to CEF Framework" ) endif (DARWIN) + +if (INSTALL) + if (DARWIN) + set(_LIB llplugin) + elseif (EXISTS ${CMAKE_SYSROOT}/usr/lib/${ARCH}-linux-gnu) + set(_LIB lib/${ARCH}-linux-gnu) + elseif (EXISTS /lib64) + set(_LIB lib64) + else (DARWIN) + set(_LIB lib) + endif (DARWIN) + install(TARGETS ${PROJECT_NAME} DESTINATION ${_LIB}) +endif (INSTALL) diff --git a/indra/media_plugins/cef/linux/volume_catcher_linux.cpp b/indra/media_plugins/cef/linux/volume_catcher_linux.cpp new file mode 100644 index 0000000000..7d33242063 --- /dev/null +++ b/indra/media_plugins/cef/linux/volume_catcher_linux.cpp @@ -0,0 +1,78 @@ +/** + * @file volume_catcher.cpp + * @brief Linux volume catcher which will pick an implementation to use + * + * @cond + * $LicenseInfo:firstyear=2010&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + * @endcond + */ + +#include "volume_catcher_linux.h" + +VolumeCatcher::VolumeCatcher() +{ +} + +void VolumeCatcher::onEnablePipeWireVolumeCatcher(bool enable) +{ + if (pimpl != nullptr) + return; + + if (enable) + { + LL_DEBUGS() << "volume catcher using pipewire" << LL_ENDL; + pimpl = new VolumeCatcherPipeWire(); + } + else + { + LL_DEBUGS() << "volume catcher using pulseaudio" << LL_ENDL; + pimpl = new VolumeCatcherPulseAudio(); + } +} + +VolumeCatcher::~VolumeCatcher() +{ + if (pimpl != nullptr) + { + delete pimpl; + pimpl = nullptr; + } +} + +void VolumeCatcher::setVolume(F32 volume) +{ + if (pimpl != nullptr) { + pimpl->setVolume(volume); + } +} + +void VolumeCatcher::setPan(F32 pan) +{ + if (pimpl != nullptr) + pimpl->setPan(pan); +} + +void VolumeCatcher::pump() +{ + if (pimpl != nullptr) + pimpl->pump(); +} diff --git a/indra/media_plugins/cef/linux/volume_catcher_linux.h b/indra/media_plugins/cef/linux/volume_catcher_linux.h new file mode 100644 index 0000000000..505f9ffb31 --- /dev/null +++ b/indra/media_plugins/cef/linux/volume_catcher_linux.h @@ -0,0 +1,149 @@ +/** + * @file volume_catcher_impl.h + * @brief + * + * @cond + * $LicenseInfo:firstyear=2010&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + * @endcond + */ + +#ifndef VOLUME_CATCHER_LINUX_H +#define VOLUME_CATCHER_LINUX_H + +#include "linden_common.h" + +#include "../volume_catcher.h" + +#include <unordered_set> +#include <mutex> + +extern "C" { +// There's no special reason why we want the *glib* PA mainloop, but the generic polling implementation seems broken. +#include <pulse/glib-mainloop.h> +#include <pulse/context.h> + +#include <pipewire/pipewire.h> + +#include "apr_pools.h" +#include "apr_dso.h" +} + +#include "media_plugin_base.h" + +class VolumeCatcherImpl +{ +public: + virtual ~VolumeCatcherImpl() = default; + + virtual void setVolume(F32 volume) = 0; // 0.0 - 1.0 + + // Set the left-right pan of audio sources + // where -1.0 = left, 0 = center, and 1.0 = right + virtual void setPan(F32 pan) = 0; + + virtual void pump() = 0; // call this at least a few times a second if you can - it affects how quickly we can 'catch' a new audio source and adjust its volume +}; + +class VolumeCatcherPulseAudio : public VolumeCatcherImpl +{ +public: + VolumeCatcherPulseAudio(); + ~VolumeCatcherPulseAudio(); + + void setVolume(F32 volume); + void setPan(F32 pan); + void pump(); + + // for internal use - can't be private because used from our C callbacks + + bool loadsyms(std::string pa_dso_name); + void init(); + void cleanup(); + + void update_all_volumes(F32 volume); + void update_index_volume(U32 index, F32 volume); + void connected_okay(); + + std::set<U32> mSinkInputIndices; + std::map<U32,U32> mSinkInputNumChannels; + F32 mDesiredVolume; + pa_glib_mainloop *mMainloop; + pa_context *mPAContext; + bool mConnected; + bool mGotSyms; +}; + +class VolumeCatcherPipeWire : public VolumeCatcherImpl +{ +public: + VolumeCatcherPipeWire(); + ~VolumeCatcherPipeWire(); + + bool loadsyms(std::string pw_dso_name); + void init(); + void cleanup(); + + // some of these should be private + + void lock(); + void unlock(); + + void setVolume(F32 volume); + void setPan(F32 pan); + void pump(); + + void handleRegistryEventGlobal( + uint32_t id, uint32_t permissions, const char* type, + uint32_t version, const struct spa_dict* props + ); + + class ChildNode + { + public: + bool mActive = false; + + pw_proxy* mProxy = nullptr; + spa_hook mNodeListener {}; + spa_hook mProxyListener {}; + VolumeCatcherPipeWire* mImpl = nullptr; + + void updateVolume(); + void destroy(); + }; + + bool mGotSyms = false; + + F32 mVolume = 1.0f; // max by default + // F32 mPan = 0.0f; // center + + pw_thread_loop* mThreadLoop = nullptr; + pw_context* mContext = nullptr; + pw_core* mCore = nullptr; + pw_registry* mRegistry = nullptr; + spa_hook mRegistryListener; + + std::unordered_set<ChildNode*> mChildNodes; + std::mutex mChildNodesMutex; + std::mutex mCleanupMutex; +}; + +#endif // VOLUME_CATCHER_LINUX_H diff --git a/indra/media_plugins/cef/linux/volume_catcher_pipewire.cpp b/indra/media_plugins/cef/linux/volume_catcher_pipewire.cpp new file mode 100755 index 0000000000..27fea547c9 --- /dev/null +++ b/indra/media_plugins/cef/linux/volume_catcher_pipewire.cpp @@ -0,0 +1,333 @@ +/** + * @file volume_catcher_pipewire.cpp + * @brief A Linux-specific, PipeWire-specific hack to detect and volume-adjust new audio sources + * + * @cond + * $LicenseInfo:firstyear=2010&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + * @endcond + */ + +/* + The high-level design is as follows: + 1) Connect to the PipeWire daemon + 2) Find all existing and new audio nodes + 3) Examine PID and parent PID's to see if it belongs to our process + 4) If so, tell PipeWire to adjust the volume of that node + 5) Keep a list of all audio nodes and adjust when we setVolume() + */ + +#include "linden_common.h" + +#include "volume_catcher_linux.h" + +extern "C" { +#include <spa/pod/builder.h> +#include <spa/param/props.h> +} + +SymbolGrabber pwSymbolGrabber; + +#include "volume_catcher_pipewire_syms.inc" + +//////////////////////////////////////////////////// + +VolumeCatcherPipeWire::VolumeCatcherPipeWire() +{ + init(); +} + +VolumeCatcherPipeWire::~VolumeCatcherPipeWire() +{ + cleanup(); +} + +static void registryEventGlobal( + void *data, uint32_t id, uint32_t permissions, const char *type, + uint32_t version, const struct spa_dict *props) +{ + static_cast<VolumeCatcherPipeWire*>(data)->handleRegistryEventGlobal( + id, permissions, type, version, props + ); +} + +static const struct pw_registry_events REGISTRY_EVENTS = { + .version = PW_VERSION_REGISTRY_EVENTS, + .global = registryEventGlobal, +}; + +bool VolumeCatcherPipeWire::loadsyms(std::string pw_dso_name) +{ + return pwSymbolGrabber.grabSymbols({ pw_dso_name }); +} + +void VolumeCatcherPipeWire::init() +{ + LL_DEBUGS() << "init" << LL_ENDL; + + mGotSyms = loadsyms("libpipewire-0.3.so.0"); + + if (!mGotSyms) + return; + + LL_DEBUGS() << "successfully got symbols" << LL_ENDL; + + llpw_init(nullptr, nullptr); + + mThreadLoop = llpw_thread_loop_new("SL Plugin Volume Adjuster", nullptr); + + if (!mThreadLoop) + return; + + // i dont think we need to lock this early + // std::lock_guard pwLock(*this); + + mContext = llpw_context_new( + llpw_thread_loop_get_loop(mThreadLoop), nullptr, 0 + ); + + if (!mContext) + return; + + mCore = llpw_context_connect(mContext, nullptr, 0); + + if (!mCore) + return; + + mRegistry = pw_core_get_registry(mCore, PW_VERSION_REGISTRY, 0); + + LL_DEBUGS() << "pw_core_get_registry: " << (mRegistry?"success":"nullptr") << LL_ENDL; + + spa_zero(mRegistryListener); + + pw_registry_add_listener( + mRegistry, &mRegistryListener, ®ISTRY_EVENTS, this + ); + + llpw_thread_loop_start(mThreadLoop); + + LL_DEBUGS() << "thread loop started" << LL_ENDL; +} + +void VolumeCatcherPipeWire::cleanup() +{ + { + std::unique_lock childNodesLock(mChildNodesMutex); + for (auto *childNode: mChildNodes) + childNode->destroy(); + + mChildNodes.clear(); + } + + { + std::unique_lock pwLock(mCleanupMutex); + if (mRegistry) + llpw_proxy_destroy((struct pw_proxy *) mRegistry); + + spa_zero(mRegistryListener); + + if (mCore) + llpw_core_disconnect(mCore); + if (mContext) + llpw_context_destroy(mContext); + } + + if (!mThreadLoop) + return; + + llpw_thread_loop_stop(mThreadLoop); + llpw_thread_loop_destroy(mThreadLoop); + + LL_DEBUGS() << "cleanup done" << LL_ENDL; +} + +void VolumeCatcherPipeWire::lock() +{ + if (!mThreadLoop) + return; + + llpw_thread_loop_lock(mThreadLoop); +} + +void VolumeCatcherPipeWire::unlock() +{ + if (!mThreadLoop) + return; + + llpw_thread_loop_unlock(mThreadLoop); +} + +const uint32_t channels = 1; +const float resetVolumes[channels] = { 1.0f }; + +void VolumeCatcherPipeWire::ChildNode::updateVolume() +{ + if (!mActive) + return; + + F32 volume = std::clamp(mImpl->mVolume, 0.0f, 1.0f); + + const float volumes[channels] = { volume }; + + uint8_t buffer[512]; + + spa_pod_builder builder; + spa_pod_builder_init(&builder, buffer, sizeof(buffer)); + + spa_pod_frame frame; + spa_pod_builder_push_object(&builder, &frame, SPA_TYPE_OBJECT_Props, SPA_PARAM_Props); + + // resets system-wide memorized volume for chromium (not google chrome) to 100% + spa_pod_builder_prop(&builder, SPA_PROP_channelVolumes, 0); + spa_pod_builder_array(&builder, sizeof(float), SPA_TYPE_Float, channels, resetVolumes); + + // sets temporary volume + spa_pod_builder_prop(&builder, SPA_PROP_softVolumes, 0); + spa_pod_builder_array(&builder, sizeof(float), SPA_TYPE_Float, channels, volumes); + + spa_pod* pod = static_cast<spa_pod*>(spa_pod_builder_pop(&builder, &frame)); + + { + std::lock_guard pwLock(*mImpl); + pw_node_set_param(mProxy, SPA_PARAM_Props, 0, pod); + } +} + +void VolumeCatcherPipeWire::ChildNode::destroy() +{ + if (!mActive) + return; + + mActive = false; + + { + std::unique_lock childNodesLock(mImpl->mChildNodesMutex); + mImpl->mChildNodes.erase(this); + } + + spa_hook_remove(&mNodeListener); + spa_hook_remove(&mProxyListener); + + { + std::lock_guard pwLock(*mImpl); + llpw_proxy_destroy(mProxy); + } +} + +static void nodeEventInfo(void* data, const struct pw_node_info* info) +{ + const char* processId = spa_dict_lookup(info->props, PW_KEY_APP_PROCESS_ID); + + if (processId == nullptr) + return; + + pid_t pid = atoll(processId); + + if (!isPluginPid(pid)) + return; + + const char* appName = spa_dict_lookup(info->props, PW_KEY_APP_NAME); + LL_DEBUGS() << "got app: " << appName << LL_ENDL; + + auto* const childNode = static_cast<VolumeCatcherPipeWire::ChildNode*>(data); + LL_DEBUGS() << "init volume: " << childNode->mImpl->mVolume << LL_ENDL; + + childNode->updateVolume(); + + { + std::lock_guard childNodesLock(childNode->mImpl->mChildNodesMutex); + childNode->mImpl->mChildNodes.insert(childNode); + } +} + +static const struct pw_node_events NODE_EVENTS = { + .version = PW_VERSION_CLIENT_EVENTS, + .info = nodeEventInfo, +}; + +static void proxyEventDestroy(void* data) +{ + auto* const childNode = static_cast<VolumeCatcherPipeWire::ChildNode*>(data); + childNode->destroy(); +} + +static void proxyEventRemoved(void* data) +{ + auto* const childNode = static_cast<VolumeCatcherPipeWire::ChildNode*>(data); + childNode->destroy(); +} + +static const struct pw_proxy_events PROXY_EVENTS = { + .version = PW_VERSION_PROXY_EVENTS, + .destroy = proxyEventDestroy, + .removed = proxyEventRemoved, +}; + +void VolumeCatcherPipeWire::handleRegistryEventGlobal( + uint32_t id, uint32_t permissions, const char *type, uint32_t version, + const struct spa_dict *props) +{ + if (props == nullptr || type == nullptr || strcmp(type, PW_TYPE_INTERFACE_Node) != 0) + return; + + const char* mediaClass = spa_dict_lookup(props, PW_KEY_MEDIA_CLASS); + + if (mediaClass == nullptr || strcmp(mediaClass, "Stream/Output/Audio") != 0) + return; + + pw_proxy* proxy = static_cast<pw_proxy*>( + pw_registry_bind(mRegistry, id, type, PW_VERSION_CLIENT, sizeof(ChildNode)) + ); + + auto* const childNode = static_cast<ChildNode*>(llpw_proxy_get_user_data(proxy)); + + childNode->mActive = true; + childNode->mProxy = proxy; + childNode->mImpl = this; + + pw_node_add_listener(proxy, &childNode->mNodeListener, &NODE_EVENTS, childNode); + llpw_proxy_add_listener(proxy, &childNode->mProxyListener, &PROXY_EVENTS, childNode); +} + +void VolumeCatcherPipeWire::setVolume(F32 volume) +{ + LL_DEBUGS() << "setting volume to: " << volume << LL_ENDL; + + mVolume = volume; + + { + std::unique_lock childNodeslock(mChildNodesMutex); + std::unordered_set<ChildNode *> copyOfChildNodes(mChildNodes); + + LL_DEBUGS() << "found " << copyOfChildNodes.size() << " child nodes" << LL_ENDL; + + for (auto* childNode : copyOfChildNodes) + childNode->updateVolume(); + } +} + +void VolumeCatcherPipeWire::setPan(F32 pan) +{ +} + +void VolumeCatcherPipeWire::pump() +{ +} diff --git a/indra/media_plugins/cef/linux/volume_catcher_pipewire_syms.inc b/indra/media_plugins/cef/linux/volume_catcher_pipewire_syms.inc new file mode 100644 index 0000000000..dbc0f5f169 --- /dev/null +++ b/indra/media_plugins/cef/linux/volume_catcher_pipewire_syms.inc @@ -0,0 +1,26 @@ +#define G pwSymbolGrabber + +// required symbols to grab +LL_GRAB_SYM(G, true, pw_init, void, int *argc, char **argv[]); +// LL_GRAB_SYM(G, true, pw_main_loop_new, struct pw_main_loop *, const struct spa_dict *props); +// LL_GRAB_SYM(G, true, pw_main_loop_get_loop, struct pw_loop *, struct pw_main_loop *loop); +// LL_GRAB_SYM(G, true, pw_main_loop_destroy, void, struct pw_main_loop *loop); +// LL_GRAB_SYM(G, true, pw_main_loop_run, void, struct pw_main_loop *loop); +LL_GRAB_SYM(G, true, pw_context_new, struct pw_context *, struct pw_loop *main_loop, struct pw_properties *props, size_t user_data_size); +LL_GRAB_SYM(G, true, pw_context_destroy, void, struct pw_context *context); +LL_GRAB_SYM(G, true, pw_context_connect, struct pw_core *, struct pw_context *context, struct pw_properties *properties, size_t user_data_size); +LL_GRAB_SYM(G, true, pw_thread_loop_new, struct pw_thread_loop *, const char *name, const struct spa_dict *props); +LL_GRAB_SYM(G, true, pw_thread_loop_destroy, void, struct pw_thread_loop *loop); +LL_GRAB_SYM(G, true, pw_thread_loop_get_loop, struct pw_loop *, struct pw_thread_loop *loop); +LL_GRAB_SYM(G, true, pw_thread_loop_start, int, struct pw_thread_loop *loop); +LL_GRAB_SYM(G, true, pw_thread_loop_stop, void, struct pw_thread_loop *loop); +LL_GRAB_SYM(G, true, pw_thread_loop_lock, void, struct pw_thread_loop *loop); +LL_GRAB_SYM(G, true, pw_thread_loop_unlock, void, struct pw_thread_loop *loop); +LL_GRAB_SYM(G, true, pw_proxy_add_listener, void, struct pw_proxy *proxy, struct spa_hook *listener, const struct pw_proxy_events *events, void *data); +LL_GRAB_SYM(G, true, pw_proxy_destroy, void, struct pw_proxy *proxy); +LL_GRAB_SYM(G, true, pw_proxy_get_user_data, void *, struct pw_proxy *proxy); +LL_GRAB_SYM(G, true, pw_core_disconnect, int, struct pw_core *core); + +// optional symbols to grab + +#undef G diff --git a/indra/media_plugins/cef/linux/volume_catcher_pulseaudio.cpp b/indra/media_plugins/cef/linux/volume_catcher_pulseaudio.cpp new file mode 100755 index 0000000000..9417c49d38 --- /dev/null +++ b/indra/media_plugins/cef/linux/volume_catcher_pulseaudio.cpp @@ -0,0 +1,322 @@ +/** + * @file volume_catcher_pulseaudio.cpp + * @brief A Linux-specific, PulseAudio-specific hack to detect and volume-adjust new audio sources + * + * @cond + * $LicenseInfo:firstyear=2010&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + * @endcond + */ + +/* + The high-level design is as follows: + 1) Connect to the PulseAudio daemon + 2) Watch for the creation of new audio players connecting to the daemon (this includes ALSA clients running on the PulseAudio emulation layer, such as Flash plugins) + 3) Examine any new audio player's PID to see if it belongs to our own process + 4) If so, tell PA to adjust the volume of that audio player ('sink input' in PA parlance) + 5) Keep a list of all living audio players that we care about, adjust the volumes of all of them when we get a new setVolume() call + */ + +#include "linden_common.h" + +#include "volume_catcher_linux.h" + +extern "C" { +#include <glib.h> +#include <glib-object.h> + +#include <pulse/introspect.h> + +#include <pulse/subscribe.h> +} + +SymbolGrabber paSymbolGrabber; + +#include "volume_catcher_pulseaudio_syms.inc" +#include "volume_catcher_pulseaudio_glib_syms.inc" + +//////////////////////////////////////////////////// + +// PulseAudio requires a chain of callbacks with C linkage +extern "C" { + void callback_discovered_sinkinput(pa_context *context, const pa_sink_input_info *i, int eol, void *userdata); + void callback_subscription_alert(pa_context *context, pa_subscription_event_type_t t, uint32_t index, void *userdata); + void callback_context_state(pa_context *context, void *userdata); +} + +VolumeCatcherPulseAudio::VolumeCatcherPulseAudio() + : mDesiredVolume(0.0f), + mMainloop(nullptr), + mPAContext(nullptr), + mConnected(false), + mGotSyms(false) +{ + init(); +} + +VolumeCatcherPulseAudio::~VolumeCatcherPulseAudio() +{ + cleanup(); +} + +bool VolumeCatcherPulseAudio::loadsyms(std::string pulse_dso_name) +{ + return paSymbolGrabber.grabSymbols({ pulse_dso_name }); +} + +void VolumeCatcherPulseAudio::init() +{ + // try to be as defensive as possible because PA's interface is a + // bit fragile and (for our purposes) we'd rather simply not function + // than crash + + // we cheat and rely upon libpulse-mainloop-glib.so.0 to pull-in + // libpulse.so.0 - this isn't a great assumption, and the two DSOs should + // probably be loaded separately. Our Linux DSO framework needs refactoring, + // we do this sort of thing a lot with practically identical logic... + mGotSyms = loadsyms("libpulse-mainloop-glib.so.0"); + + if (!mGotSyms) + mGotSyms = loadsyms("libpulse.so.0"); + + if (!mGotSyms) + return; + + mMainloop = llpa_glib_mainloop_new(g_main_context_default()); + + if (mMainloop) + { + pa_mainloop_api *api = llpa_glib_mainloop_get_api(mMainloop); + + if (api) + { + pa_proplist *proplist = llpa_proplist_new(); + + if (proplist) + { + llpa_proplist_sets(proplist, PA_PROP_APPLICATION_ICON_NAME, "multimedia-player"); + llpa_proplist_sets(proplist, PA_PROP_APPLICATION_ID, "com.secondlife.viewer.mediaplugvoladjust"); + llpa_proplist_sets(proplist, PA_PROP_APPLICATION_NAME, "SL Plugin Volume Adjuster"); + llpa_proplist_sets(proplist, PA_PROP_APPLICATION_VERSION, "1"); + + // plain old pa_context_new() is broken! + mPAContext = llpa_context_new_with_proplist(api, nullptr, proplist); + + llpa_proplist_free(proplist); + } + } + } + + // Now we've set up a PA context and mainloop, try connecting the + // PA context to a PA daemon. + if (mPAContext) + { + llpa_context_set_state_callback(mPAContext, callback_context_state, this); + pa_context_flags_t cflags = (pa_context_flags)0; // maybe add PA_CONTEXT_NOAUTOSPAWN? + if (llpa_context_connect(mPAContext, nullptr, cflags, nullptr) >= 0) + { + // Okay! We haven't definitely connected, but we + // haven't definitely failed yet. + } + else + { + // Failed to connect to PA manager... we'll leave + // things like that. Perhaps we should try again later. + } + } +} + +void VolumeCatcherPulseAudio::cleanup() +{ + mConnected = false; + + if (mGotSyms && mPAContext) + { + llpa_context_disconnect(mPAContext); + llpa_context_unref(mPAContext); + } + + mPAContext = nullptr; + + if (mGotSyms && mMainloop) + llpa_glib_mainloop_free(mMainloop); + + mMainloop = nullptr; +} + +void VolumeCatcherPulseAudio::setVolume(F32 volume) +{ + mDesiredVolume = volume; + + if (!mGotSyms) + return; + + if (mConnected && mPAContext) + { + update_all_volumes(mDesiredVolume); + } + + pump(); +} + +void VolumeCatcherPulseAudio::setPan(F32 pan) +{ +} + +void VolumeCatcherPulseAudio::pump() +{ + gboolean may_block = FALSE; + g_main_context_iteration(g_main_context_default(), may_block); +} + +void VolumeCatcherPulseAudio::connected_okay() +{ + pa_operation *op; + + // fetch global list of existing sinkinputs + if ((op = llpa_context_get_sink_input_info_list(mPAContext, + callback_discovered_sinkinput, + this))) + { + llpa_operation_unref(op); + } + + // subscribe to future global sinkinput changes + llpa_context_set_subscribe_callback(mPAContext, + callback_subscription_alert, + this); + if ((op = llpa_context_subscribe(mPAContext, (pa_subscription_mask_t) + (PA_SUBSCRIPTION_MASK_SINK_INPUT), + nullptr, nullptr))) + { + llpa_operation_unref(op); + } +} + +void VolumeCatcherPulseAudio::update_all_volumes(F32 volume) +{ + for (std::set<U32>::iterator it = mSinkInputIndices.begin(); + it != mSinkInputIndices.end(); ++it) + { + update_index_volume(*it, volume); + } +} + +void VolumeCatcherPulseAudio::update_index_volume(U32 index, F32 volume) +{ + static pa_cvolume cvol; + llpa_cvolume_set(&cvol, mSinkInputNumChannels[index], + llpa_sw_volume_from_linear(volume)); + + pa_context *c = mPAContext; + uint32_t idx = index; + const pa_cvolume *cvolumep = &cvol; + pa_context_success_cb_t cb = nullptr; // okay as null + void *userdata = nullptr; // okay as null + + pa_operation *op; + if ((op = llpa_context_set_sink_input_volume(c, idx, cvolumep, cb, userdata))) + llpa_operation_unref(op); +} + +void callback_discovered_sinkinput(pa_context *context, const pa_sink_input_info *sii, int eol, void *userdata) +{ + VolumeCatcherPulseAudio *impl = dynamic_cast<VolumeCatcherPulseAudio*>((VolumeCatcherPulseAudio*)userdata); + llassert(impl); + + if (0 == eol) + { + pa_proplist *proplist = sii->proplist; + pid_t sinkpid = atoll(llpa_proplist_gets(proplist, PA_PROP_APPLICATION_PROCESS_ID)); + + if (isPluginPid( sinkpid )) // does the discovered sinkinput belong to this process? + { + bool is_new = (impl->mSinkInputIndices.find(sii->index) == impl->mSinkInputIndices.end()); + + impl->mSinkInputIndices.insert(sii->index); + impl->mSinkInputNumChannels[sii->index] = sii->channel_map.channels; + + if (is_new) + { + // new! + impl->update_index_volume(sii->index, impl->mDesiredVolume); + } + else + { + // seen it already, do nothing. + } + } + } +} + +void callback_subscription_alert(pa_context *context, pa_subscription_event_type_t t, uint32_t index, void *userdata) +{ + VolumeCatcherPulseAudio *impl = dynamic_cast<VolumeCatcherPulseAudio*>((VolumeCatcherPulseAudio*)userdata); + llassert(impl); + + switch (t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) + { + case PA_SUBSCRIPTION_EVENT_SINK_INPUT: + if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) + { + // forget this sinkinput, if we were caring about it + impl->mSinkInputIndices.erase(index); + impl->mSinkInputNumChannels.erase(index); + } + else if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_NEW) + { + // ask for more info about this new sinkinput + pa_operation *op; + if ((op = llpa_context_get_sink_input_info(impl->mPAContext, index, callback_discovered_sinkinput, impl))) + { + llpa_operation_unref(op); + } + } + else + { + // property change on this sinkinput - we don't care. + } + break; + + default:; + } +} + +void callback_context_state(pa_context *context, void *userdata) +{ + VolumeCatcherPulseAudio *impl = dynamic_cast<VolumeCatcherPulseAudio*>((VolumeCatcherPulseAudio*)userdata); + llassert(impl); + + switch (llpa_context_get_state(context)) + { + case PA_CONTEXT_READY: + impl->mConnected = true; + impl->connected_okay(); + break; + case PA_CONTEXT_TERMINATED: + impl->mConnected = false; + break; + case PA_CONTEXT_FAILED: + impl->mConnected = false; + break; + default:; + } +} diff --git a/indra/media_plugins/cef/linux/volume_catcher_pulseaudio_glib_syms.inc b/indra/media_plugins/cef/linux/volume_catcher_pulseaudio_glib_syms.inc new file mode 100755 index 0000000000..e9b7196e51 --- /dev/null +++ b/indra/media_plugins/cef/linux/volume_catcher_pulseaudio_glib_syms.inc @@ -0,0 +1,10 @@ +#define G paSymbolGrabber + +// required symbols to grab +LL_GRAB_SYM(G, true, pa_glib_mainloop_free, void, pa_glib_mainloop* g) +LL_GRAB_SYM(G, true, pa_glib_mainloop_get_api, pa_mainloop_api*, pa_glib_mainloop* g) +LL_GRAB_SYM(G, true, pa_glib_mainloop_new, pa_glib_mainloop *, GMainContext *c) + +// optional symbols to grab + +#undef G diff --git a/indra/media_plugins/cef/linux/volume_catcher_pulseaudio_syms.inc b/indra/media_plugins/cef/linux/volume_catcher_pulseaudio_syms.inc new file mode 100755 index 0000000000..4859a34405 --- /dev/null +++ b/indra/media_plugins/cef/linux/volume_catcher_pulseaudio_syms.inc @@ -0,0 +1,29 @@ +#define G paSymbolGrabber + +// required symbols to grab +LL_GRAB_SYM(G, true, pa_context_connect, int, pa_context *c, const char *server, pa_context_flags_t flags, const pa_spawn_api *api) +LL_GRAB_SYM(G, true, pa_context_disconnect, void, pa_context *c) +LL_GRAB_SYM(G, true, pa_context_get_sink_input_info, pa_operation*, pa_context *c, uint32_t idx, pa_sink_input_info_cb_t cb, void *userdata) +LL_GRAB_SYM(G, true, pa_context_get_sink_input_info_list, pa_operation*, pa_context *c, pa_sink_input_info_cb_t cb, void *userdata) +LL_GRAB_SYM(G, true, pa_context_get_state, pa_context_state_t, pa_context *c) +LL_GRAB_SYM(G, true, pa_context_new_with_proplist, pa_context*, pa_mainloop_api *mainloop, const char *name, pa_proplist *proplist) +LL_GRAB_SYM(G, true, pa_context_set_sink_input_volume, pa_operation*, pa_context *c, uint32_t idx, const pa_cvolume *volume, pa_context_success_cb_t cb, void *userdata) +LL_GRAB_SYM(G, true, pa_context_set_state_callback, void, pa_context *c, pa_context_notify_cb_t cb, void *userdata) +LL_GRAB_SYM(G, true, pa_context_set_subscribe_callback, void, pa_context *c, pa_context_subscribe_cb_t cb, void *userdata) +LL_GRAB_SYM(G, true, pa_context_subscribe, pa_operation*, pa_context *c, pa_subscription_mask_t m, pa_context_success_cb_t cb, void *userdata) +LL_GRAB_SYM(G, true, pa_context_unref, void, pa_context *c) +LL_GRAB_SYM(G, true, pa_cvolume_set, pa_cvolume*, pa_cvolume *a, unsigned channels, pa_volume_t v) +LL_GRAB_SYM(G, true, pa_operation_unref, void, pa_operation *o) +LL_GRAB_SYM(G, true, pa_proplist_free, void, pa_proplist* p) +LL_GRAB_SYM(G, true, pa_proplist_gets, const char*, pa_proplist *p, const char *key) +LL_GRAB_SYM(G, true, pa_proplist_new, pa_proplist*, void) +LL_GRAB_SYM(G, true, pa_proplist_sets, int, pa_proplist *p, const char *key, const char *value) +LL_GRAB_SYM(G, true, pa_sw_volume_from_linear, pa_volume_t, double v) +// LL_GRAB_SYM(G, true, pa_mainloop_free, void, pa_mainloop *m) +// LL_GRAB_SYM(G, true, pa_mainloop_get_api, pa_mainloop_api *, pa_mainloop *m) +// LL_GRAB_SYM(G, true, pa_mainloop_iterate, int, pa_mainloop *m, int block, int *retval) +// LL_GRAB_SYM(G, true, pa_mainloop_new, pa_mainloop *, void) + +// optional symbols to grab + +#undef G diff --git a/indra/media_plugins/cef/media_plugin_cef.cpp b/indra/media_plugins/cef/media_plugin_cef.cpp index 64fc7e452b..9c205b558c 100644 --- a/indra/media_plugins/cef/media_plugin_cef.cpp +++ b/indra/media_plugins/cef/media_plugin_cef.cpp @@ -886,7 +886,7 @@ void MediaPluginCEF::receiveMessage(const char* message_string) keyEvent(key_event, native_key_data); -#elif LL_WINDOWS +#else std::string event = message_in.getValue("event"); LLSD native_key_data = message_in.getValueLLSD("native_key_data"); @@ -908,6 +908,13 @@ void MediaPluginCEF::receiveMessage(const char* message_string) { mEnableMediaPluginDebugging = message_in.getValueBoolean("enable"); } +#if LL_LINUX + else if (message_name == "enable_pipewire_volume_catcher") + { + bool enable = message_in.getValueBoolean("enable"); + mVolumeCatcher.onEnablePipeWireVolumeCatcher(enable); + } +#endif if (message_name == "pick_file_response") { LLSD file_list_llsd = message_in.getValueLLSD("file_list"); @@ -1050,6 +1057,28 @@ void MediaPluginCEF::keyEvent(dullahan::EKeyEvent key_event, LLSD native_key_dat mCEFLib->nativeKeyboardEventWin(msg, wparam, lparam); #endif + +#if LL_LINUX + + uint32_t native_virtual_key = (uint32_t)(native_key_data["virtual_key"].asInteger()); // this is actually the SDL event.key.keysym.sym; + uint32_t native_virtual_key_win = (uint32_t)(native_key_data["virtual_key_win"].asInteger()); + uint32_t native_modifiers = (uint32_t)(native_key_data["modifiers"].asInteger()); + + // only for non-printable keysyms, the actual text input is done in unicodeInput() below + if (native_virtual_key <= 0x1b || native_virtual_key >= 0x7f) + { + // set keypad flag, not sure if this even does anything + bool keypad = false; + if (native_virtual_key_win >= 0x60 && native_virtual_key_win <= 0x6f) + { + keypad = true; + } + + // yes, we send native_virtual_key_win twice because native_virtual_key breaks it + mCEFLib->nativeKeyboardEventSDL2(key_event, native_virtual_key, native_modifiers, keypad); + } + +#endif // LL_LINUX }; void MediaPluginCEF::unicodeInput(std::string event, LLSD native_key_data = LLSD::emptyMap()) @@ -1080,6 +1109,16 @@ void MediaPluginCEF::unicodeInput(std::string event, LLSD native_key_data = LLSD U64 lparam = ll_U32_from_sd(native_key_data["l_param"]); mCEFLib->nativeKeyboardEventWin(msg, wparam, lparam); #endif + +#if LL_LINUX + + uint32_t native_scan_code = (uint32_t)(native_key_data["sdl_sym"].asInteger()); + uint32_t native_virtual_key = (uint32_t)(native_key_data["virtual_key"].asInteger()); + uint32_t native_modifiers = (uint32_t)(native_key_data["modifiers"].asInteger()); + + mCEFLib->nativeKeyboardEvent(dullahan::KE_KEY_DOWN, native_scan_code, native_virtual_key, native_modifiers); + +#endif // LL_LINUX }; //////////////////////////////////////////////////////////////////////////////// diff --git a/indra/media_plugins/cef/volume_catcher.h b/indra/media_plugins/cef/volume_catcher.h index ea97a24947..6933854e8e 100644 --- a/indra/media_plugins/cef/volume_catcher.h +++ b/indra/media_plugins/cef/volume_catcher.h @@ -35,19 +35,20 @@ class VolumeCatcherImpl; class VolumeCatcher { - public: +public: VolumeCatcher(); ~VolumeCatcher(); - void setVolume(F32 volume); // 0.0 - 1.0 - - // Set the left-right pan of audio sources - // where -1.0 = left, 0 = center, and 1.0 = right + void setVolume(F32 volume); void setPan(F32 pan); - void pump(); // call this at least a few times a second if you can - it affects how quickly we can 'catch' a new audio source and adjust its volume + void pump(); + +#if LL_LINUX + void onEnablePipeWireVolumeCatcher(bool enable); +#endif - private: +private: VolumeCatcherImpl *pimpl; }; diff --git a/indra/media_plugins/cef/mac_volume_catcher_null.cpp b/indra/media_plugins/cef/volume_catcher_null.cpp index c479e24a95..c6028da45b 100644 --- a/indra/media_plugins/cef/mac_volume_catcher_null.cpp +++ b/indra/media_plugins/cef/volume_catcher_null.cpp @@ -1,5 +1,5 @@ -/** - * @file windows_volume_catcher.cpp +/** + * @file volume_catcher_null.cpp * @brief A null implementation of volume level control of all audio channels opened by a process. * We are using this for the macOS version for now until we can understand how to make the * exitising mac_volume_catcher.cpp work without the (now, non-existant) QuickTime dependency @@ -29,67 +29,25 @@ */ #include "volume_catcher.h" -#include "llsingleton.h" -class VolumeCatcherImpl : public LLSingleton<VolumeCatcherImpl> -{ - LLSINGLETON(VolumeCatcherImpl); - // This is a singleton class -- both callers and the component implementation should use getInstance() to find the instance. - ~VolumeCatcherImpl(); - -public: - - void setVolume(F32 volume); - void setPan(F32 pan); - -private: - F32 mVolume; - F32 mPan; - bool mSystemIsVistaOrHigher; -}; - -VolumeCatcherImpl::VolumeCatcherImpl() -: mVolume(1.0f), // default volume is max - mPan(0.f) // default pan is centered -{ -} - -VolumeCatcherImpl::~VolumeCatcherImpl() -{ -} - -void VolumeCatcherImpl::setVolume(F32 volume) -{ - mVolume = volume; -} - -void VolumeCatcherImpl::setPan(F32 pan) -{ // remember pan for calculating individual channel levels later - mPan = pan; -} ///////////////////////////////////////////////////// VolumeCatcher::VolumeCatcher() { - pimpl = VolumeCatcherImpl::getInstance(); } VolumeCatcher::~VolumeCatcher() { - // Let the instance persist until exit. } void VolumeCatcher::setVolume(F32 volume) { - pimpl->setVolume(volume); } void VolumeCatcher::setPan(F32 pan) { - pimpl->setPan(pan); } void VolumeCatcher::pump() { - // No periodic tasks are necessary for this implementation. } diff --git a/indra/media_plugins/cef/windows_volume_catcher.cpp b/indra/media_plugins/cef/windows_volume_catcher.cpp index e7daeb5f74..1e52fee9de 100644 --- a/indra/media_plugins/cef/windows_volume_catcher.cpp +++ b/indra/media_plugins/cef/windows_volume_catcher.cpp @@ -44,7 +44,6 @@ public: private: F32 mVolume; F32 mPan; - bool mSystemIsVistaOrHigher; }; VolumeCatcherImpl::VolumeCatcherImpl() diff --git a/indra/media_plugins/example/CMakeLists.txt b/indra/media_plugins/example/CMakeLists.txt index 7d3e7f663b..86e982fbb4 100644 --- a/indra/media_plugins/example/CMakeLists.txt +++ b/indra/media_plugins/example/CMakeLists.txt @@ -13,14 +13,6 @@ include(ExamplePlugin) ### media_plugin_example -if(NOT ADDRESS_SIZE EQUAL 32) - if(WINDOWS) - ##add_definitions(/FIXED:NO) - else(WINDOWS) # not windows therefore gcc LINUX and DARWIN - add_definitions(-fPIC) - endif(WINDOWS) -endif(NOT ADDRESS_SIZE EQUAL 32) - set(media_plugin_example_SOURCE_FILES media_plugin_example.cpp ) diff --git a/indra/media_plugins/gstreamer010/CMakeLists.txt b/indra/media_plugins/gstreamer010/CMakeLists.txt deleted file mode 100644 index 38fc8201bf..0000000000 --- a/indra/media_plugins/gstreamer010/CMakeLists.txt +++ /dev/null @@ -1,46 +0,0 @@ -# -*- cmake -*- - -project(media_plugin_gstreamer010) - -include(00-Common) -include(LLCommon) -include(LLImage) -include(LLMath) -include(LLWindow) -include(Linking) -include(PluginAPI) -include(OpenGL) - -include(GStreamer010Plugin) - -### media_plugin_gstreamer010 - -if(NOT ADDRESS_SIZE EQUAL 32) - if(WINDOWS) - ##add_definitions(/FIXED:NO) - else(WINDOWS) # not windows therefore gcc LINUX and DARWIN - add_definitions(-fPIC) - endif(WINDOWS) -endif(NOT ADDRESS_SIZE EQUAL 32) - -set(media_plugin_gstreamer010_SOURCE_FILES - media_plugin_gstreamer010.cpp - llmediaimplgstreamer_syms.cpp - llmediaimplgstreamervidplug.cpp - ) - -set(media_plugin_gstreamer010_HEADER_FILES - llmediaimplgstreamervidplug.h - llmediaimplgstreamer_syms.h - llmediaimplgstreamertriviallogging.h - ) - -add_library(media_plugin_gstreamer010 - SHARED - ${media_plugin_gstreamer010_SOURCE_FILES} - ) - -target_link_libraries(media_plugin_gstreamer010 - media_plugin_base - ll::gstreamer - ) diff --git a/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms.cpp b/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms.cpp deleted file mode 100644 index dcc04b37e4..0000000000 --- a/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms.cpp +++ /dev/null @@ -1,167 +0,0 @@ -/** - * @file llmediaimplgstreamer_syms.cpp - * @brief dynamic GStreamer symbol-grabbing code - * - * @cond - * $LicenseInfo:firstyear=2007&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - * @endcond - */ - -#if LL_GSTREAMER010_ENABLED - -#include <string> - -extern "C" { -#include <gst/gst.h> - -#include "apr_pools.h" -#include "apr_dso.h" -} - -#include "llmediaimplgstreamertriviallogging.h" - -#define LL_GST_SYM(REQ, GSTSYM, RTN, ...) RTN (*ll##GSTSYM)(__VA_ARGS__) = NULL -#include "llmediaimplgstreamer_syms_raw.inc" -#include "llmediaimplgstreamer_syms_rawv.inc" -#undef LL_GST_SYM - -// a couple of stubs for disgusting reasons -GstDebugCategory* -ll_gst_debug_category_new(gchar *name, guint color, gchar *description) -{ - static GstDebugCategory dummy; - return &dummy; -} -void ll_gst_debug_register_funcptr(GstDebugFuncPtr func, gchar* ptrname) -{ -} - -static bool sSymsGrabbed = false; -static apr_pool_t *sSymGSTDSOMemoryPool = NULL; -static apr_dso_handle_t *sSymGSTDSOHandleG = NULL; -static apr_dso_handle_t *sSymGSTDSOHandleV = NULL; - - -bool grab_gst_syms(std::string gst_dso_name, - std::string gst_dso_name_vid) -{ - if (sSymsGrabbed) - { - // already have grabbed good syms - return TRUE; - } - - bool sym_error = false; - bool rtn = false; - apr_status_t rv; - apr_dso_handle_t *sSymGSTDSOHandle = NULL; - -#define LL_GST_SYM(REQ, GSTSYM, RTN, ...) do{rv = apr_dso_sym((apr_dso_handle_sym_t*)&ll##GSTSYM, sSymGSTDSOHandle, #GSTSYM); if (rv != APR_SUCCESS) {INFOMSG("Failed to grab symbol: %s", #GSTSYM); if (REQ) sym_error = true;} else DEBUGMSG("grabbed symbol: %s from %p", #GSTSYM, (void*)ll##GSTSYM);}while(0) - - //attempt to load the shared libraries - apr_pool_create(&sSymGSTDSOMemoryPool, NULL); - - if ( APR_SUCCESS == (rv = apr_dso_load(&sSymGSTDSOHandle, - gst_dso_name.c_str(), - sSymGSTDSOMemoryPool) )) - { - INFOMSG("Found DSO: %s", gst_dso_name.c_str()); -#include "llmediaimplgstreamer_syms_raw.inc" - - if ( sSymGSTDSOHandle ) - { - sSymGSTDSOHandleG = sSymGSTDSOHandle; - sSymGSTDSOHandle = NULL; - } - - if ( APR_SUCCESS == - (rv = apr_dso_load(&sSymGSTDSOHandle, - gst_dso_name_vid.c_str(), - sSymGSTDSOMemoryPool) )) - { - INFOMSG("Found DSO: %s", gst_dso_name_vid.c_str()); -#include "llmediaimplgstreamer_syms_rawv.inc" - rtn = !sym_error; - } - else - { - INFOMSG("Couldn't load DSO: %s", gst_dso_name_vid.c_str()); - rtn = false; // failure - } - } - else - { - INFOMSG("Couldn't load DSO: %s", gst_dso_name.c_str()); - rtn = false; // failure - } - - if (sym_error) - { - WARNMSG("Failed to find necessary symbols in GStreamer libraries."); - } - - if ( sSymGSTDSOHandle ) - { - sSymGSTDSOHandleV = sSymGSTDSOHandle; - sSymGSTDSOHandle = NULL; - } -#undef LL_GST_SYM - - sSymsGrabbed = !!rtn; - return rtn; -} - - -void ungrab_gst_syms() -{ - // should be safe to call regardless of whether we've - // actually grabbed syms. - - if ( sSymGSTDSOHandleG ) - { - apr_dso_unload(sSymGSTDSOHandleG); - sSymGSTDSOHandleG = NULL; - } - - if ( sSymGSTDSOHandleV ) - { - apr_dso_unload(sSymGSTDSOHandleV); - sSymGSTDSOHandleV = NULL; - } - - if ( sSymGSTDSOMemoryPool ) - { - apr_pool_destroy(sSymGSTDSOMemoryPool); - sSymGSTDSOMemoryPool = NULL; - } - - // NULL-out all of the symbols we'd grabbed -#define LL_GST_SYM(REQ, GSTSYM, RTN, ...) do{ll##GSTSYM = NULL;}while(0) -#include "llmediaimplgstreamer_syms_raw.inc" -#include "llmediaimplgstreamer_syms_rawv.inc" -#undef LL_GST_SYM - - sSymsGrabbed = false; -} - - -#endif // LL_GSTREAMER010_ENABLED diff --git a/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms.h b/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms.h deleted file mode 100644 index 57d446c7df..0000000000 --- a/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms.h +++ /dev/null @@ -1,74 +0,0 @@ -/** - * @file llmediaimplgstreamer_syms.h - * @brief dynamic GStreamer symbol-grabbing code - * - * @cond - * $LicenseInfo:firstyear=2007&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - * @endcond - */ - -#include "linden_common.h" - -#if LL_GSTREAMER010_ENABLED - -extern "C" { -#include <gst/gst.h> -} - -bool grab_gst_syms(std::string gst_dso_name, - std::string gst_dso_name_vid); -void ungrab_gst_syms(); - -#define LL_GST_SYM(REQ, GSTSYM, RTN, ...) extern RTN (*ll##GSTSYM)(__VA_ARGS__) -#include "llmediaimplgstreamer_syms_raw.inc" -#include "llmediaimplgstreamer_syms_rawv.inc" -#undef LL_GST_SYM - -// regrettable hacks to give us better runtime compatibility with older systems -#define llg_return_if_fail(COND) do{if (!(COND)) return;}while(0) -#define llg_return_val_if_fail(COND,V) do{if (!(COND)) return V;}while(0) - -// regrettable hacks because GStreamer was not designed for runtime loading -#undef GST_TYPE_MESSAGE -#define GST_TYPE_MESSAGE (llgst_message_get_type()) -#undef GST_TYPE_OBJECT -#define GST_TYPE_OBJECT (llgst_object_get_type()) -#undef GST_TYPE_PIPELINE -#define GST_TYPE_PIPELINE (llgst_pipeline_get_type()) -#undef GST_TYPE_ELEMENT -#define GST_TYPE_ELEMENT (llgst_element_get_type()) -#undef GST_TYPE_VIDEO_SINK -#define GST_TYPE_VIDEO_SINK (llgst_video_sink_get_type()) -// more regrettable hacks to stub-out these .h-exposed GStreamer internals -void ll_gst_debug_register_funcptr(GstDebugFuncPtr func, gchar* ptrname); -#undef _gst_debug_register_funcptr -#define _gst_debug_register_funcptr ll_gst_debug_register_funcptr -GstDebugCategory* ll_gst_debug_category_new(gchar *name, guint color, gchar *description); -#undef _gst_debug_category_new -#define _gst_debug_category_new ll_gst_debug_category_new -#undef __gst_debug_enabled -#define __gst_debug_enabled (0) - -// more hacks -#define LLGST_MESSAGE_TYPE_NAME(M) (llgst_message_type_get_name(GST_MESSAGE_TYPE(M))) - -#endif // LL_GSTREAMER010_ENABLED diff --git a/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms_raw.inc b/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms_raw.inc deleted file mode 100644 index b33e59363d..0000000000 --- a/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms_raw.inc +++ /dev/null @@ -1,51 +0,0 @@ - -// required symbols to grab -LL_GST_SYM(true, gst_pad_peer_accept_caps, gboolean, GstPad *pad, GstCaps *caps); -LL_GST_SYM(true, gst_buffer_new, GstBuffer*, void); -LL_GST_SYM(true, gst_buffer_set_caps, void, GstBuffer*, GstCaps *); -LL_GST_SYM(true, gst_structure_set_value, void, GstStructure *, const gchar *, const GValue*); -LL_GST_SYM(true, gst_init_check, gboolean, int *argc, char **argv[], GError ** err); -LL_GST_SYM(true, gst_message_get_type, GType, void); -LL_GST_SYM(true, gst_message_type_get_name, const gchar*, GstMessageType type); -LL_GST_SYM(true, gst_message_parse_error, void, GstMessage *message, GError **gerror, gchar **debug); -LL_GST_SYM(true, gst_message_parse_warning, void, GstMessage *message, GError **gerror, gchar **debug); -LL_GST_SYM(true, gst_message_parse_state_changed, void, GstMessage *message, GstState *oldstate, GstState *newstate, GstState *pending); -LL_GST_SYM(true, gst_element_set_state, GstStateChangeReturn, GstElement *element, GstState state); -LL_GST_SYM(true, gst_object_unref, void, gpointer object); -LL_GST_SYM(true, gst_object_get_type, GType, void); -LL_GST_SYM(true, gst_pipeline_get_type, GType, void); -LL_GST_SYM(true, gst_pipeline_get_bus, GstBus*, GstPipeline *pipeline); -LL_GST_SYM(true, gst_bus_add_watch, guint, GstBus * bus, GstBusFunc func, gpointer user_data); -LL_GST_SYM(true, gst_element_factory_make, GstElement*, const gchar *factoryname, const gchar *name); -LL_GST_SYM(true, gst_element_get_type, GType, void); -LL_GST_SYM(true, gst_static_pad_template_get, GstPadTemplate*, GstStaticPadTemplate *pad_template); -LL_GST_SYM(true, gst_element_class_add_pad_template, void, GstElementClass *klass, GstPadTemplate *temp); -LL_GST_SYM(true, gst_element_class_set_details, void, GstElementClass *klass, const GstElementDetails *details); -LL_GST_SYM(true, gst_caps_unref, void, GstCaps* caps); -LL_GST_SYM(true, gst_caps_ref, GstCaps *, GstCaps* caps); -//LL_GST_SYM(true, gst_caps_is_empty, gboolean, const GstCaps *caps); -LL_GST_SYM(true, gst_caps_from_string, GstCaps *, const gchar *string); -LL_GST_SYM(true, gst_caps_replace, void, GstCaps **caps, GstCaps *newcaps); -LL_GST_SYM(true, gst_caps_get_structure, GstStructure *, const GstCaps *caps, guint index); -LL_GST_SYM(true, gst_caps_copy, GstCaps *, const GstCaps * caps); -//LL_GST_SYM(true, gst_caps_intersect, GstCaps *, const GstCaps *caps1, const GstCaps *caps2); -LL_GST_SYM(true, gst_element_register, gboolean, GstPlugin *plugin, const gchar *name, guint rank, GType type); -LL_GST_SYM(true, _gst_plugin_register_static, void, GstPluginDesc *desc); -LL_GST_SYM(true, gst_structure_get_int, gboolean, const GstStructure *structure, const gchar *fieldname, gint *value); -LL_GST_SYM(true, gst_structure_get_value, G_CONST_RETURN GValue *, const GstStructure *structure, const gchar *fieldname); -LL_GST_SYM(true, gst_value_get_fraction_numerator, gint, const GValue *value); -LL_GST_SYM(true, gst_value_get_fraction_denominator, gint, const GValue *value); -LL_GST_SYM(true, gst_structure_get_name, G_CONST_RETURN gchar *, const GstStructure *structure); -LL_GST_SYM(true, gst_element_seek, bool, GstElement *, gdouble, GstFormat, GstSeekFlags, GstSeekType, gint64, GstSeekType, gint64); - -// optional symbols to grab -LL_GST_SYM(false, gst_registry_fork_set_enabled, void, gboolean enabled); -LL_GST_SYM(false, gst_segtrap_set_enabled, void, gboolean enabled); -LL_GST_SYM(false, gst_message_parse_buffering, void, GstMessage *message, gint *percent); -LL_GST_SYM(false, gst_message_parse_info, void, GstMessage *message, GError **gerror, gchar **debug); -LL_GST_SYM(false, gst_element_query_position, gboolean, GstElement *element, GstFormat *format, gint64 *cur); -LL_GST_SYM(false, gst_version, void, guint *major, guint *minor, guint *micro, guint *nano); - -// GStreamer 'internal' symbols which may not be visible in some runtimes but are still used in expanded GStreamer header macros - yuck! We'll substitute our own stubs for these. -//LL_GST_SYM(true, _gst_debug_register_funcptr, void, GstDebugFuncPtr func, gchar* ptrname); -//LL_GST_SYM(true, _gst_debug_category_new, GstDebugCategory *, gchar *name, guint color, gchar *description); diff --git a/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms_rawv.inc b/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms_rawv.inc deleted file mode 100644 index 14fbcb48b9..0000000000 --- a/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms_rawv.inc +++ /dev/null @@ -1,5 +0,0 @@ - -// required symbols to grab -LL_GST_SYM(true, gst_video_sink_get_type, GType, void); - -// optional symbols to grab diff --git a/indra/media_plugins/gstreamer010/llmediaimplgstreamertriviallogging.h b/indra/media_plugins/gstreamer010/llmediaimplgstreamertriviallogging.h deleted file mode 100644 index 43ebad6744..0000000000 --- a/indra/media_plugins/gstreamer010/llmediaimplgstreamertriviallogging.h +++ /dev/null @@ -1,55 +0,0 @@ -/** - * @file llmediaimplgstreamertriviallogging.h - * @brief minimal logging utilities. - * - * @cond - * $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$ - * @endcond - */ - -#ifndef __LLMEDIAIMPLGSTREAMERTRIVIALLOGGING_H__ -#define __LLMEDIAIMPLGSTREAMERTRIVIALLOGGING_H__ - -#include <cstdio> - -extern "C" { -#include <sys/types.h> -#include <unistd.h> -} - -///////////////////////////////////////////////////////////////////////// -// Debug/Info/Warning macros. -#define MSGMODULEFOO "(media plugin)" -#define STDERRMSG(...) do{\ - fprintf(stderr, " pid:%d: ", (int)getpid());\ - fprintf(stderr, MSGMODULEFOO " %s:%d: ", __FUNCTION__, __LINE__);\ - fprintf(stderr, __VA_ARGS__);\ - fputc('\n',stderr);\ - }while(0) -#define NULLMSG(...) do{}while(0) - -#define DEBUGMSG NULLMSG -#define INFOMSG STDERRMSG -#define WARNMSG STDERRMSG -///////////////////////////////////////////////////////////////////////// - -#endif /* __LLMEDIAIMPLGSTREAMERTRIVIALLOGGING_H__ */ diff --git a/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.cpp b/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.cpp deleted file mode 100644 index acec0f2399..0000000000 --- a/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.cpp +++ /dev/null @@ -1,526 +0,0 @@ -/** - * @file llmediaimplgstreamervidplug.h - * @brief Video-consuming static GStreamer plugin for gst-to-LLMediaImpl - * - * @cond - * $LicenseInfo:firstyear=2007&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - * @endcond - */ - -#if LL_GSTREAMER010_ENABLED - -#include "linden_common.h" - -#include <gst/gst.h> -#include <gst/video/video.h> -#include <gst/video/gstvideosink.h> - -#include "llmediaimplgstreamer_syms.h" -#include "llmediaimplgstreamertriviallogging.h" - -#include "llmediaimplgstreamervidplug.h" - - -GST_DEBUG_CATEGORY_STATIC (gst_slvideo_debug); -#define GST_CAT_DEFAULT gst_slvideo_debug - - -#define SLV_SIZECAPS ", width=(int)[1,2048], height=(int)[1,2048] " -#define SLV_ALLCAPS GST_VIDEO_CAPS_RGBx SLV_SIZECAPS - -static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ( - (gchar*)"sink", - GST_PAD_SINK, - GST_PAD_ALWAYS, - GST_STATIC_CAPS (SLV_ALLCAPS) - ); - -GST_BOILERPLATE (GstSLVideo, gst_slvideo, GstVideoSink, - GST_TYPE_VIDEO_SINK); - -static void gst_slvideo_set_property (GObject * object, guint prop_id, - const GValue * value, - GParamSpec * pspec); -static void gst_slvideo_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec); - -static void -gst_slvideo_base_init (gpointer gclass) -{ - static GstElementDetails element_details = { - (gchar*)"PluginTemplate", - (gchar*)"Generic/PluginTemplate", - (gchar*)"Generic Template Element", - (gchar*)"Linden Lab" - }; - GstElementClass *element_class = GST_ELEMENT_CLASS (gclass); - - llgst_element_class_add_pad_template (element_class, - llgst_static_pad_template_get (&sink_factory)); - llgst_element_class_set_details (element_class, &element_details); -} - - -static void -gst_slvideo_finalize (GObject * object) -{ - GstSLVideo *slvideo; - slvideo = GST_SLVIDEO (object); - if (slvideo->caps) - { - llgst_caps_unref(slvideo->caps); - } - - G_OBJECT_CLASS(parent_class)->finalize (object); -} - - -static GstFlowReturn -gst_slvideo_show_frame (GstBaseSink * bsink, GstBuffer * buf) -{ - GstSLVideo *slvideo; - llg_return_val_if_fail (buf != NULL, GST_FLOW_ERROR); - - slvideo = GST_SLVIDEO(bsink); - - DEBUGMSG("transferring a frame of %dx%d <- %p (%d)", - slvideo->width, slvideo->height, GST_BUFFER_DATA(buf), - slvideo->format); - - if (GST_BUFFER_DATA(buf)) - { - // copy frame and frame info into neutral territory - GST_OBJECT_LOCK(slvideo); - slvideo->retained_frame_ready = TRUE; - slvideo->retained_frame_width = slvideo->width; - slvideo->retained_frame_height = slvideo->height; - slvideo->retained_frame_format = slvideo->format; - int rowbytes = - SLVPixelFormatBytes[slvideo->retained_frame_format] * - slvideo->retained_frame_width; - int needbytes = rowbytes * slvideo->retained_frame_width; - // resize retained frame hunk only if necessary - if (needbytes != slvideo->retained_frame_allocbytes) - { - delete[] slvideo->retained_frame_data; - slvideo->retained_frame_data = new unsigned char[needbytes]; - slvideo->retained_frame_allocbytes = needbytes; - - } - // copy the actual frame data to neutral territory - - // flipped, for GL reasons - for (int ypos=0; ypos<slvideo->height; ++ypos) - { - memcpy(&slvideo->retained_frame_data[(slvideo->height-1-ypos)*rowbytes], - &(((unsigned char*)GST_BUFFER_DATA(buf))[ypos*rowbytes]), - rowbytes); - } - // done with the shared data - GST_OBJECT_UNLOCK(slvideo); - } - - return GST_FLOW_OK; -} - - -static GstStateChangeReturn -gst_slvideo_change_state(GstElement * element, GstStateChange transition) -{ - GstSLVideo *slvideo; - GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS; - - slvideo = GST_SLVIDEO (element); - - switch (transition) { - case GST_STATE_CHANGE_NULL_TO_READY: - break; - case GST_STATE_CHANGE_READY_TO_PAUSED: - break; - case GST_STATE_CHANGE_PAUSED_TO_PLAYING: - break; - default: - break; - } - - ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); - if (ret == GST_STATE_CHANGE_FAILURE) - return ret; - - switch (transition) { - case GST_STATE_CHANGE_PLAYING_TO_PAUSED: - break; - case GST_STATE_CHANGE_PAUSED_TO_READY: - slvideo->fps_n = 0; - slvideo->fps_d = 1; - GST_VIDEO_SINK_WIDTH(slvideo) = 0; - GST_VIDEO_SINK_HEIGHT(slvideo) = 0; - break; - case GST_STATE_CHANGE_READY_TO_NULL: - break; - default: - break; - } - - return ret; -} - - -static GstCaps * -gst_slvideo_get_caps (GstBaseSink * bsink) -{ - GstSLVideo *slvideo; - slvideo = GST_SLVIDEO(bsink); - - return llgst_caps_ref (slvideo->caps); -} - - -/* this function handles the link with other elements */ -static gboolean -gst_slvideo_set_caps (GstBaseSink * bsink, GstCaps * caps) -{ - GstSLVideo *filter; - GstStructure *structure; - - GST_DEBUG ("set caps with %" GST_PTR_FORMAT, caps); - - filter = GST_SLVIDEO(bsink); - - int width, height; - gboolean ret; - const GValue *fps; - const GValue *par; - structure = llgst_caps_get_structure (caps, 0); - ret = llgst_structure_get_int (structure, "width", &width); - ret = ret && llgst_structure_get_int (structure, "height", &height); - fps = llgst_structure_get_value (structure, "framerate"); - ret = ret && (fps != NULL); - par = llgst_structure_get_value (structure, "pixel-aspect-ratio"); - if (!ret) - return FALSE; - - INFOMSG("** filter caps set with width=%d, height=%d", width, height); - - GST_OBJECT_LOCK(filter); - - filter->width = width; - filter->height = height; - - filter->fps_n = llgst_value_get_fraction_numerator(fps); - filter->fps_d = llgst_value_get_fraction_denominator(fps); - if (par) - { - filter->par_n = llgst_value_get_fraction_numerator(par); - filter->par_d = llgst_value_get_fraction_denominator(par); - } - else - { - filter->par_n = 1; - filter->par_d = 1; - } - GST_VIDEO_SINK_WIDTH(filter) = width; - GST_VIDEO_SINK_HEIGHT(filter) = height; - - // crufty lump - we *always* accept *only* RGBX now. - /* - filter->format = SLV_PF_UNKNOWN; - if (0 == strcmp(llgst_structure_get_name(structure), - "video/x-raw-rgb")) - { - int red_mask; - int green_mask; - int blue_mask; - llgst_structure_get_int(structure, "red_mask", &red_mask); - llgst_structure_get_int(structure, "green_mask", &green_mask); - llgst_structure_get_int(structure, "blue_mask", &blue_mask); - if ((unsigned int)red_mask == 0xFF000000 && - (unsigned int)green_mask == 0x00FF0000 && - (unsigned int)blue_mask == 0x0000FF00) - { - filter->format = SLV_PF_RGBX; - //fprintf(stderr, "\n\nPIXEL FORMAT RGB\n\n"); - } else if ((unsigned int)red_mask == 0x0000FF00 && - (unsigned int)green_mask == 0x00FF0000 && - (unsigned int)blue_mask == 0xFF000000) - { - filter->format = SLV_PF_BGRX; - //fprintf(stderr, "\n\nPIXEL FORMAT BGR\n\n"); - } - }*/ - - filter->format = SLV_PF_RGBX; - - GST_OBJECT_UNLOCK(filter); - - return TRUE; -} - - -static gboolean -gst_slvideo_start (GstBaseSink * bsink) -{ - gboolean ret = TRUE; - - GST_SLVIDEO(bsink); - - return ret; -} - -static gboolean -gst_slvideo_stop (GstBaseSink * bsink) -{ - GstSLVideo *slvideo; - slvideo = GST_SLVIDEO(bsink); - - // free-up retained frame buffer - GST_OBJECT_LOCK(slvideo); - slvideo->retained_frame_ready = FALSE; - delete[] slvideo->retained_frame_data; - slvideo->retained_frame_data = NULL; - slvideo->retained_frame_allocbytes = 0; - GST_OBJECT_UNLOCK(slvideo); - - return TRUE; -} - - -static GstFlowReturn -gst_slvideo_buffer_alloc (GstBaseSink * bsink, guint64 offset, guint size, - GstCaps * caps, GstBuffer ** buf) -{ - gint width, height; - GstStructure *structure = NULL; - GstSLVideo *slvideo; - slvideo = GST_SLVIDEO(bsink); - - // caps == requested caps - // we can ignore these and reverse-negotiate our preferred dimensions with - // the peer if we like - we need to do this to obey dynamic resize requests - // flowing in from the app. - structure = llgst_caps_get_structure (caps, 0); - if (!llgst_structure_get_int(structure, "width", &width) || - !llgst_structure_get_int(structure, "height", &height)) - { - GST_WARNING_OBJECT (slvideo, "no width/height in caps %" GST_PTR_FORMAT, caps); - return GST_FLOW_NOT_NEGOTIATED; - } - - GstBuffer *newbuf = llgst_buffer_new(); - bool made_bufferdata_ptr = false; -#define MAXDEPTHHACK 4 - - GST_OBJECT_LOCK(slvideo); - if (slvideo->resize_forced_always) // app is giving us a fixed size to work with - { - gint slwantwidth, slwantheight; - slwantwidth = slvideo->resize_try_width; - slwantheight = slvideo->resize_try_height; - - if (slwantwidth != width || - slwantheight != height) - { - // don't like requested caps, we will issue our own suggestion - copy - // the requested caps but substitute our own width and height and see - // if our peer is happy with that. - - GstCaps *desired_caps; - GstStructure *desired_struct; - desired_caps = llgst_caps_copy (caps); - desired_struct = llgst_caps_get_structure (desired_caps, 0); - - GValue value = {0}; - g_value_init(&value, G_TYPE_INT); - g_value_set_int(&value, slwantwidth); - llgst_structure_set_value (desired_struct, "width", &value); - g_value_unset(&value); - g_value_init(&value, G_TYPE_INT); - g_value_set_int(&value, slwantheight); - llgst_structure_set_value (desired_struct, "height", &value); - - if (llgst_pad_peer_accept_caps (GST_VIDEO_SINK_PAD (slvideo), - desired_caps)) - { - // todo: re-use buffers from a pool? - // todo: set MALLOCDATA to null, set DATA to point straight to shm? - - // peer likes our cap suggestion - DEBUGMSG("peer loves us :)"); - GST_BUFFER_SIZE(newbuf) = slwantwidth * slwantheight * MAXDEPTHHACK; - GST_BUFFER_MALLOCDATA(newbuf) = (guint8*)g_malloc(GST_BUFFER_SIZE(newbuf)); - GST_BUFFER_DATA(newbuf) = GST_BUFFER_MALLOCDATA(newbuf); - llgst_buffer_set_caps (GST_BUFFER_CAST(newbuf), desired_caps); - - made_bufferdata_ptr = true; - } else { - // peer hates our cap suggestion - INFOMSG("peer hates us :("); - llgst_caps_unref(desired_caps); - } - } - } - - GST_OBJECT_UNLOCK(slvideo); - - if (!made_bufferdata_ptr) // need to fallback to malloc at original size - { - GST_BUFFER_SIZE(newbuf) = width * height * MAXDEPTHHACK; - GST_BUFFER_MALLOCDATA(newbuf) = (guint8*)g_malloc(GST_BUFFER_SIZE(newbuf)); - GST_BUFFER_DATA(newbuf) = GST_BUFFER_MALLOCDATA(newbuf); - llgst_buffer_set_caps (GST_BUFFER_CAST(newbuf), caps); - } - - *buf = GST_BUFFER_CAST(newbuf); - - return GST_FLOW_OK; -} - - -/* initialize the plugin's class */ -static void -gst_slvideo_class_init (GstSLVideoClass * klass) -{ - GObjectClass *gobject_class; - GstElementClass *gstelement_class; - GstBaseSinkClass *gstbasesink_class; - - gobject_class = (GObjectClass *) klass; - gstelement_class = (GstElementClass *) klass; - gstbasesink_class = (GstBaseSinkClass *) klass; - - gobject_class->finalize = gst_slvideo_finalize; - gobject_class->set_property = gst_slvideo_set_property; - gobject_class->get_property = gst_slvideo_get_property; - - gstelement_class->change_state = gst_slvideo_change_state; - -#define LLGST_DEBUG_FUNCPTR(p) (p) - gstbasesink_class->get_caps = LLGST_DEBUG_FUNCPTR (gst_slvideo_get_caps); - gstbasesink_class->set_caps = LLGST_DEBUG_FUNCPTR( gst_slvideo_set_caps); - gstbasesink_class->buffer_alloc=LLGST_DEBUG_FUNCPTR(gst_slvideo_buffer_alloc); - //gstbasesink_class->get_times = LLGST_DEBUG_FUNCPTR (gst_slvideo_get_times); - gstbasesink_class->preroll = LLGST_DEBUG_FUNCPTR (gst_slvideo_show_frame); - gstbasesink_class->render = LLGST_DEBUG_FUNCPTR (gst_slvideo_show_frame); - - gstbasesink_class->start = LLGST_DEBUG_FUNCPTR (gst_slvideo_start); - gstbasesink_class->stop = LLGST_DEBUG_FUNCPTR (gst_slvideo_stop); - - // gstbasesink_class->unlock = LLGST_DEBUG_FUNCPTR (gst_slvideo_unlock); -#undef LLGST_DEBUG_FUNCPTR -} - - -/* initialize the new element - * instantiate pads and add them to element - * set functions - * initialize structure - */ -static void -gst_slvideo_init (GstSLVideo * filter, - GstSLVideoClass * gclass) -{ - filter->caps = NULL; - filter->width = -1; - filter->height = -1; - - // this is the info we share with the client app - GST_OBJECT_LOCK(filter); - filter->retained_frame_ready = FALSE; - filter->retained_frame_data = NULL; - filter->retained_frame_allocbytes = 0; - filter->retained_frame_width = filter->width; - filter->retained_frame_height = filter->height; - filter->retained_frame_format = SLV_PF_UNKNOWN; - GstCaps *caps = llgst_caps_from_string (SLV_ALLCAPS); - llgst_caps_replace (&filter->caps, caps); - filter->resize_forced_always = false; - filter->resize_try_width = -1; - filter->resize_try_height = -1; - GST_OBJECT_UNLOCK(filter); -} - -static void -gst_slvideo_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec) -{ - llg_return_if_fail (GST_IS_SLVIDEO (object)); - - switch (prop_id) { - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -gst_slvideo_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec) -{ - llg_return_if_fail (GST_IS_SLVIDEO (object)); - - switch (prop_id) { - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - - -/* entry point to initialize the plug-in - * initialize the plug-in itself - * register the element factories and pad templates - * register the features - */ -static gboolean -plugin_init (GstPlugin * plugin) -{ - DEBUGMSG("PLUGIN INIT"); - - GST_DEBUG_CATEGORY_INIT (gst_slvideo_debug, (gchar*)"private-slvideo-plugin", - 0, (gchar*)"Second Life Video Sink"); - - return llgst_element_register (plugin, "private-slvideo", - GST_RANK_NONE, GST_TYPE_SLVIDEO); -} - -/* this is the structure that gstreamer looks for to register plugins - */ -/* NOTE: Can't rely upon GST_PLUGIN_DEFINE_STATIC to self-register, since - some g++ versions buggily avoid __attribute__((constructor)) functions - - so we provide an explicit plugin init function. - */ -#define PACKAGE (gchar*)"packagehack" -// this macro quietly refers to PACKAGE internally -GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, - GST_VERSION_MINOR, - (gchar*)"private-slvideoplugin", - (gchar*)"SL Video sink plugin", - plugin_init, (gchar*)"1.0", (gchar*)"LGPL", - (gchar*)"Second Life", - (gchar*)"http://www.secondlife.com/"); -#undef PACKAGE -void gst_slvideo_init_class (void) -{ - ll_gst_plugin_register_static (&gst_plugin_desc); - DEBUGMSG("CLASS INIT"); -} - -#endif // LL_GSTREAMER010_ENABLED diff --git a/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.h b/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.h deleted file mode 100644 index d4e07daf4f..0000000000 --- a/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.h +++ /dev/null @@ -1,105 +0,0 @@ -/** - * @file llmediaimplgstreamervidplug.h - * @brief Video-consuming static GStreamer plugin for gst-to-LLMediaImpl - * - * @cond - * $LicenseInfo:firstyear=2007&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - * @endcond - */ - -#ifndef __GST_SLVIDEO_H__ -#define __GST_SLVIDEO_H__ - -#if LL_GSTREAMER010_ENABLED - -extern "C" { -#include <gst/gst.h> -#include <gst/video/video.h> -#include <gst/video/gstvideosink.h> -} - -G_BEGIN_DECLS - -/* #defines don't like whitespacey bits */ -#define GST_TYPE_SLVIDEO \ - (gst_slvideo_get_type()) -#define GST_SLVIDEO(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_SLVIDEO,GstSLVideo)) -#define GST_SLVIDEO_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_SLVIDEO,GstSLVideoClass)) -#define GST_IS_SLVIDEO(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_SLVIDEO)) -#define GST_IS_SLVIDEO_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_SLVIDEO)) - -typedef struct _GstSLVideo GstSLVideo; -typedef struct _GstSLVideoClass GstSLVideoClass; - -typedef enum { - SLV_PF_UNKNOWN = 0, - SLV_PF_RGBX = 1, - SLV_PF_BGRX = 2, - SLV__END = 3 -} SLVPixelFormat; -const int SLVPixelFormatBytes[SLV__END] = {1, 4, 4}; - -struct _GstSLVideo -{ - GstVideoSink video_sink; - - GstCaps *caps; - - int fps_n, fps_d; - int par_n, par_d; - int height, width; - SLVPixelFormat format; - - // SHARED WITH APPLICATION: - // Access to the following should be protected by GST_OBJECT_LOCK() on - // the GstSLVideo object, and should be totally consistent upon UNLOCK - // (i.e. all written at once to reflect the current retained frame info - // when the retained frame is updated.) - bool retained_frame_ready; // new frame ready since flag last reset. (*TODO: could get the writer to wait on a semaphore instead of having the reader poll, potentially making dropped frames somewhat cheaper.) - unsigned char* retained_frame_data; - int retained_frame_allocbytes; - int retained_frame_width, retained_frame_height; - SLVPixelFormat retained_frame_format; - // sticky resize info - bool resize_forced_always; - int resize_try_width; - int resize_try_height; -}; - -struct _GstSLVideoClass -{ - GstVideoSinkClass parent_class; -}; - -GType gst_slvideo_get_type (void); - -void gst_slvideo_init_class (void); - -G_END_DECLS - -#endif // LL_GSTREAMER010_ENABLED - -#endif /* __GST_SLVIDEO_H__ */ diff --git a/indra/media_plugins/gstreamer010/media_plugin_gstreamer010.cpp b/indra/media_plugins/gstreamer010/media_plugin_gstreamer010.cpp deleted file mode 100644 index 97d1d7d7b5..0000000000 --- a/indra/media_plugins/gstreamer010/media_plugin_gstreamer010.cpp +++ /dev/null @@ -1,1266 +0,0 @@ -/** - * @file media_plugin_gstreamer010.cpp - * @brief GStreamer-0.10 plugin for LLMedia API plugin system - * - * @cond - * $LicenseInfo:firstyear=2007&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - * @endcond - */ - -#include "linden_common.h" - -#include "llgl.h" - -#include "llplugininstance.h" -#include "llpluginmessage.h" -#include "llpluginmessageclasses.h" -#include "media_plugin_base.h" - -#if LL_GSTREAMER010_ENABLED - -extern "C" { -#include <gst/gst.h> -} - -#include "llmediaimplgstreamer.h" -#include "llmediaimplgstreamertriviallogging.h" - -#include "llmediaimplgstreamervidplug.h" - -#include "llmediaimplgstreamer_syms.h" - -////////////////////////////////////////////////////////////////////////////// -// -class MediaPluginGStreamer010 : public MediaPluginBase -{ -public: - MediaPluginGStreamer010(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data); - ~MediaPluginGStreamer010(); - - /* virtual */ void receiveMessage(const char *message_string); - - static bool startup(); - static bool closedown(); - - gboolean processGSTEvents(GstBus *bus, - GstMessage *message); - -private: - std::string getVersion(); - bool navigateTo( const std::string urlIn ); - bool seek( double time_sec ); - bool setVolume( float volume ); - - // misc - bool pause(); - bool stop(); - bool play(double rate); - bool getTimePos(double &sec_out); - - static const double MIN_LOOP_SEC = 1.0F; - - bool mIsLooping; - - enum ECommand { - COMMAND_NONE, - COMMAND_STOP, - COMMAND_PLAY, - COMMAND_FAST_FORWARD, - COMMAND_FAST_REWIND, - COMMAND_PAUSE, - COMMAND_SEEK, - }; - ECommand mCommand; - -private: - bool unload(); - bool load(); - - bool update(int milliseconds); - void mouseDown( int x, int y ); - void mouseUp( int x, int y ); - void mouseMove( int x, int y ); - - void sizeChanged(); - - static bool mDoneInit; - - guint mBusWatchID; - - float mVolume; - - int mDepth; - - // media NATURAL size - int mNaturalWidth; - int mNaturalHeight; - // media current size - int mCurrentWidth; - int mCurrentHeight; - int mCurrentRowbytes; - // previous media size so we can detect changes - int mPreviousWidth; - int mPreviousHeight; - // desired render size from host - int mWidth; - int mHeight; - // padded texture size we need to write into - int mTextureWidth; - int mTextureHeight; - - int mTextureFormatPrimary; - int mTextureFormatType; - - bool mSeekWanted; - double mSeekDestination; - - // Very GStreamer-specific - GMainLoop *mPump; // event pump for this media - GstElement *mPlaybin; - GstElement *mVisualizer; - GstSLVideo *mVideoSink; -}; - -//static -bool MediaPluginGStreamer010::mDoneInit = false; - -MediaPluginGStreamer010::MediaPluginGStreamer010( - LLPluginInstance::sendMessageFunction host_send_func, - void *host_user_data ) : - MediaPluginBase(host_send_func, host_user_data), - mBusWatchID ( 0 ), - mCurrentRowbytes ( 4 ), - mTextureFormatPrimary ( GL_RGBA ), - mTextureFormatType ( GL_UNSIGNED_INT_8_8_8_8_REV ), - mSeekWanted(false), - mSeekDestination(0.0), - mPump ( NULL ), - mPlaybin ( NULL ), - mVisualizer ( NULL ), - mVideoSink ( NULL ), - mCommand ( COMMAND_NONE ) -{ - std::ostringstream str; - INFOMSG("MediaPluginGStreamer010 constructor - my PID=%u", U32(getpid())); -} - -/////////////////////////////////////////////////////////////////////////////// -// -//#define LL_GST_REPORT_STATE_CHANGES -#ifdef LL_GST_REPORT_STATE_CHANGES -static char* get_gst_state_name(GstState state) -{ - switch (state) { - case GST_STATE_VOID_PENDING: return "VOID_PENDING"; - case GST_STATE_NULL: return "NULL"; - case GST_STATE_READY: return "READY"; - case GST_STATE_PAUSED: return "PAUSED"; - case GST_STATE_PLAYING: return "PLAYING"; - } - return "(unknown)"; -} -#endif // LL_GST_REPORT_STATE_CHANGES - -gboolean -MediaPluginGStreamer010::processGSTEvents(GstBus *bus, - GstMessage *message) -{ - if (!message) - return TRUE; // shield against GStreamer bug - - if (GST_MESSAGE_TYPE(message) != GST_MESSAGE_STATE_CHANGED && - GST_MESSAGE_TYPE(message) != GST_MESSAGE_BUFFERING) - { - DEBUGMSG("Got GST message type: %s", - LLGST_MESSAGE_TYPE_NAME (message)); - } - else - { - // TODO: grok 'duration' message type - DEBUGMSG("Got GST message type: %s", - LLGST_MESSAGE_TYPE_NAME (message)); - } - - switch (GST_MESSAGE_TYPE (message)) { - case GST_MESSAGE_BUFFERING: { - // NEEDS GST 0.10.11+ - if (llgst_message_parse_buffering) - { - gint percent = 0; - llgst_message_parse_buffering(message, &percent); - DEBUGMSG("GST buffering: %d%%", percent); - } - break; - } - case GST_MESSAGE_STATE_CHANGED: { - GstState old_state; - GstState new_state; - GstState pending_state; - llgst_message_parse_state_changed(message, - &old_state, - &new_state, - &pending_state); -#ifdef LL_GST_REPORT_STATE_CHANGES - // not generally very useful, and rather spammy. - DEBUGMSG("state change (old,<new>,pending): %s,<%s>,%s", - get_gst_state_name(old_state), - get_gst_state_name(new_state), - get_gst_state_name(pending_state)); -#endif // LL_GST_REPORT_STATE_CHANGES - - switch (new_state) { - case GST_STATE_VOID_PENDING: - break; - case GST_STATE_NULL: - break; - case GST_STATE_READY: - setStatus(STATUS_LOADED); - break; - case GST_STATE_PAUSED: - setStatus(STATUS_PAUSED); - break; - case GST_STATE_PLAYING: - setStatus(STATUS_PLAYING); - break; - } - break; - } - case GST_MESSAGE_ERROR: { - GError *err = NULL; - gchar *debug = NULL; - - llgst_message_parse_error (message, &err, &debug); - WARNMSG("GST error: %s", err?err->message:"(unknown)"); - if (err) - g_error_free (err); - g_free (debug); - - mCommand = COMMAND_STOP; - - setStatus(STATUS_ERROR); - - break; - } - case GST_MESSAGE_INFO: { - if (llgst_message_parse_info) - { - GError *err = NULL; - gchar *debug = NULL; - - llgst_message_parse_info (message, &err, &debug); - INFOMSG("GST info: %s", err?err->message:"(unknown)"); - if (err) - g_error_free (err); - g_free (debug); - } - break; - } - case GST_MESSAGE_WARNING: { - GError *err = NULL; - gchar *debug = NULL; - - llgst_message_parse_warning (message, &err, &debug); - WARNMSG("GST warning: %s", err?err->message:"(unknown)"); - if (err) - g_error_free (err); - g_free (debug); - - break; - } - case GST_MESSAGE_EOS: - /* end-of-stream */ - DEBUGMSG("GST end-of-stream."); - if (mIsLooping) - { - DEBUGMSG("looping media..."); - double eos_pos_sec = 0.0F; - bool got_eos_position = getTimePos(eos_pos_sec); - - if (got_eos_position && eos_pos_sec < MIN_LOOP_SEC) - { - // if we know that the movie is really short, don't - // loop it else it can easily become a time-hog - // because of GStreamer spin-up overhead - DEBUGMSG("really short movie (%0.3fsec) - not gonna loop this, pausing instead.", eos_pos_sec); - // inject a COMMAND_PAUSE - mCommand = COMMAND_PAUSE; - } - else - { -#undef LLGST_LOOP_BY_SEEKING -// loop with a stop-start instead of a seek, because it actually seems rather -// faster than seeking on remote streams. -#ifdef LLGST_LOOP_BY_SEEKING - // first, try looping by an explicit rewind - bool seeksuccess = seek(0.0); - if (seeksuccess) - { - play(1.0); - } - else -#endif // LLGST_LOOP_BY_SEEKING - { // use clumsy stop-start to loop - DEBUGMSG("didn't loop by rewinding - stopping and starting instead..."); - stop(); - play(1.0); - } - } - } - else // not a looping media - { - // inject a COMMAND_STOP - mCommand = COMMAND_STOP; - } - break; - default: - /* unhandled message */ - break; - } - - /* we want to be notified again the next time there is a message - * on the bus, so return true (false means we want to stop watching - * for messages on the bus and our callback should not be called again) - */ - return TRUE; -} - -extern "C" { -gboolean -llmediaimplgstreamer_bus_callback (GstBus *bus, - GstMessage *message, - gpointer data) -{ - MediaPluginGStreamer010 *impl = (MediaPluginGStreamer010*)data; - return impl->processGSTEvents(bus, message); -} -} // extern "C" - - - -bool -MediaPluginGStreamer010::navigateTo ( const std::string urlIn ) -{ - if (!mDoneInit) - return false; // error - - setStatus(STATUS_LOADING); - - DEBUGMSG("Setting media URI: %s", urlIn.c_str()); - - mSeekWanted = false; - - if (NULL == mPump || - NULL == mPlaybin) - { - setStatus(STATUS_ERROR); - return false; // error - } - - // set URI - g_object_set (G_OBJECT (mPlaybin), "uri", urlIn.c_str(), NULL); - //g_object_set (G_OBJECT (mPlaybin), "uri", "file:///tmp/movie", NULL); - - // navigateTo implicitly plays, too. - play(1.0); - - return true; -} - - -bool -MediaPluginGStreamer010::update(int milliseconds) -{ - if (!mDoneInit) - return false; // error - - DEBUGMSG("updating media..."); - - // sanity check - if (NULL == mPump || - NULL == mPlaybin) - { - DEBUGMSG("dead media..."); - return false; - } - - // see if there's an outstanding seek wanted - if (mSeekWanted && - // bleh, GST has to be happy that the movie is really truly playing - // or it may quietly ignore the seek (with rtsp:// at least). - (GST_STATE(mPlaybin) == GST_STATE_PLAYING)) - { - seek(mSeekDestination); - mSeekWanted = false; - } - - // *TODO: time-limit - but there isn't a lot we can do here, most - // time is spent in gstreamer's own opaque worker-threads. maybe - // we can do something sneaky like only unlock the video object - // for 'milliseconds' and otherwise hold the lock. - while (g_main_context_pending(g_main_loop_get_context(mPump))) - { - g_main_context_iteration(g_main_loop_get_context(mPump), FALSE); - } - - // check for availability of a new frame - - if (mVideoSink) - { - GST_OBJECT_LOCK(mVideoSink); - if (mVideoSink->retained_frame_ready) - { - DEBUGMSG("NEW FRAME READY"); - - if (mVideoSink->retained_frame_width != mCurrentWidth || - mVideoSink->retained_frame_height != mCurrentHeight) - // *TODO: also check for change in format - { - // just resize container, don't consume frame - int neww = mVideoSink->retained_frame_width; - int newh = mVideoSink->retained_frame_height; - - int newd = 4; - mTextureFormatPrimary = GL_RGBA; - mTextureFormatType = GL_UNSIGNED_INT_8_8_8_8_REV; - - /* - int newd = SLVPixelFormatBytes[mVideoSink->retained_frame_format]; - if (SLV_PF_BGRX == mVideoSink->retained_frame_format) - { - mTextureFormatPrimary = GL_BGRA; - mTextureFormatType = GL_UNSIGNED_INT_8_8_8_8_REV; - } - else - { - mTextureFormatPrimary = GL_RGBA; - mTextureFormatType = GL_UNSIGNED_INT_8_8_8_8_REV; - } - */ - - GST_OBJECT_UNLOCK(mVideoSink); - - mCurrentRowbytes = neww * newd; - DEBUGMSG("video container resized to %dx%d", - neww, newh); - - mDepth = newd; - mCurrentWidth = neww; - mCurrentHeight = newh; - sizeChanged(); - return true; - } - - if (mPixels && - mCurrentHeight <= mHeight && - mCurrentWidth <= mWidth && - !mTextureSegmentName.empty()) - { - // we're gonna totally consume this frame - reset 'ready' flag - mVideoSink->retained_frame_ready = FALSE; - int destination_rowbytes = mWidth * mDepth; - for (int row=0; row<mCurrentHeight; ++row) - { - memcpy(&mPixels - [destination_rowbytes * row], - &mVideoSink->retained_frame_data - [mCurrentRowbytes * row], - mCurrentRowbytes); - } - - GST_OBJECT_UNLOCK(mVideoSink); - DEBUGMSG("NEW FRAME REALLY TRULY CONSUMED, TELLING HOST"); - - setDirty(0,0,mCurrentWidth,mCurrentHeight); - } - else - { - // new frame ready, but we're not ready to - // consume it. - - GST_OBJECT_UNLOCK(mVideoSink); - - DEBUGMSG("NEW FRAME not consumed, still waiting for a shm segment and/or shm resize"); - } - - return true; - } - else - { - // nothing to do yet. - GST_OBJECT_UNLOCK(mVideoSink); - return true; - } - } - - return true; -} - - -void -MediaPluginGStreamer010::mouseDown( int x, int y ) -{ - // do nothing -} - -void -MediaPluginGStreamer010::mouseUp( int x, int y ) -{ - // do nothing -} - -void -MediaPluginGStreamer010::mouseMove( int x, int y ) -{ - // do nothing -} - - -bool -MediaPluginGStreamer010::pause() -{ - DEBUGMSG("pausing media..."); - // todo: error-check this? - if (mDoneInit && mPlaybin) - { - llgst_element_set_state(mPlaybin, GST_STATE_PAUSED); - return true; - } - return false; -} - -bool -MediaPluginGStreamer010::stop() -{ - DEBUGMSG("stopping media..."); - // todo: error-check this? - if (mDoneInit && mPlaybin) - { - llgst_element_set_state(mPlaybin, GST_STATE_READY); - return true; - } - return false; -} - -bool -MediaPluginGStreamer010::play(double rate) -{ - // NOTE: we don't actually support non-natural rate. - - DEBUGMSG("playing media... rate=%f", rate); - // todo: error-check this? - if (mDoneInit && mPlaybin) - { - llgst_element_set_state(mPlaybin, GST_STATE_PLAYING); - return true; - } - return false; -} - -bool -MediaPluginGStreamer010::setVolume( float volume ) -{ - // we try to only update volume as conservatively as - // possible, as many gst-plugins-base versions up to at least - // November 2008 have critical race-conditions in setting volume - sigh - if (mVolume == volume) - return true; // nothing to do, everything's fine - - mVolume = volume; - if (mDoneInit && mPlaybin) - { - g_object_set(mPlaybin, "volume", mVolume, NULL); - return true; - } - - return false; -} - -bool -MediaPluginGStreamer010::seek(double time_sec) -{ - bool success = false; - if (mDoneInit && mPlaybin) - { - success = llgst_element_seek(mPlaybin, 1.0F, GST_FORMAT_TIME, - GstSeekFlags(GST_SEEK_FLAG_FLUSH | - GST_SEEK_FLAG_KEY_UNIT), - GST_SEEK_TYPE_SET, gint64(time_sec*GST_SECOND), - GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE); - } - DEBUGMSG("MEDIA SEEK REQUEST to %fsec result was %d", - float(time_sec), int(success)); - return success; -} - -bool -MediaPluginGStreamer010::getTimePos(double &sec_out) -{ - bool got_position = false; - if (mDoneInit && mPlaybin) - { - gint64 pos; - GstFormat timefmt = GST_FORMAT_TIME; - got_position = - llgst_element_query_position && - llgst_element_query_position(mPlaybin, - &timefmt, - &pos); - got_position = got_position - && (timefmt == GST_FORMAT_TIME); - // GStreamer may have other ideas, but we consider the current position - // undefined if not PLAYING or PAUSED - got_position = got_position && - (GST_STATE(mPlaybin) == GST_STATE_PLAYING || - GST_STATE(mPlaybin) == GST_STATE_PAUSED); - if (got_position && !GST_CLOCK_TIME_IS_VALID(pos)) - { - if (GST_STATE(mPlaybin) == GST_STATE_PLAYING) - { - // if we're playing then we treat an invalid clock time - // as 0, for complicated reasons (insert reason here) - pos = 0; - } - else - { - got_position = false; - } - - } - // If all the preconditions succeeded... we can trust the result. - if (got_position) - { - sec_out = double(pos) / double(GST_SECOND); // gst to sec - } - } - return got_position; -} - -bool -MediaPluginGStreamer010::load() -{ - if (!mDoneInit) - return false; // error - - setStatus(STATUS_LOADING); - - DEBUGMSG("setting up media..."); - - mIsLooping = false; - mVolume = 0.1234567; // minor hack to force an initial volume update - - // Create a pumpable main-loop for this media - mPump = g_main_loop_new (NULL, FALSE); - if (!mPump) - { - setStatus(STATUS_ERROR); - return false; // error - } - - // instantiate a playbin element to do the hard work - mPlaybin = llgst_element_factory_make ("playbin", "play"); - if (!mPlaybin) - { - setStatus(STATUS_ERROR); - return false; // error - } - - // get playbin's bus - GstBus *bus = llgst_pipeline_get_bus (GST_PIPELINE (mPlaybin)); - if (!bus) - { - setStatus(STATUS_ERROR); - return false; // error - } - mBusWatchID = llgst_bus_add_watch (bus, - llmediaimplgstreamer_bus_callback, - this); - llgst_object_unref (bus); - -#if 0 // not quite stable/correct yet - // get a visualizer element (bonus feature!) - char* vis_name = getenv("LL_GST_VIS_NAME"); - if (!vis_name || - (vis_name && std::string(vis_name)!="none")) - { - if (vis_name) - { - mVisualizer = llgst_element_factory_make (vis_name, "vis"); - } - if (!mVisualizer) - { - mVisualizer = llgst_element_factory_make ("libvisual_jess", "vis"); - if (!mVisualizer) - { - mVisualizer = llgst_element_factory_make ("goom", "vis"); - if (!mVisualizer) - { - mVisualizer = llgst_element_factory_make ("libvisual_lv_scope", "vis"); - if (!mVisualizer) - { - // That's okay, we don't NEED this. - } - } - } - } - } -#endif - - if (NULL == getenv("LL_GSTREAMER_EXTERNAL")) { - // instantiate a custom video sink - mVideoSink = - GST_SLVIDEO(llgst_element_factory_make ("private-slvideo", "slvideo")); - if (!mVideoSink) - { - WARNMSG("Could not instantiate private-slvideo element."); - // todo: cleanup. - setStatus(STATUS_ERROR); - return false; // error - } - - // connect the pieces - g_object_set(mPlaybin, "video-sink", mVideoSink, NULL); - } - - if (mVisualizer) - { - g_object_set(mPlaybin, "vis-plugin", mVisualizer, NULL); - } - - return true; -} - -bool -MediaPluginGStreamer010::unload () -{ - if (!mDoneInit) - return false; // error - - DEBUGMSG("unloading media..."); - - // stop getting callbacks for this bus - g_source_remove(mBusWatchID); - mBusWatchID = 0; - - if (mPlaybin) - { - llgst_element_set_state (mPlaybin, GST_STATE_NULL); - llgst_object_unref (GST_OBJECT (mPlaybin)); - mPlaybin = NULL; - } - - if (mVisualizer) - { - llgst_object_unref (GST_OBJECT (mVisualizer)); - mVisualizer = NULL; - } - - if (mPump) - { - g_main_loop_quit(mPump); - mPump = NULL; - } - - mVideoSink = NULL; - - setStatus(STATUS_NONE); - - return true; -} - - -//static -bool -MediaPluginGStreamer010::startup() -{ - // first - check if GStreamer is explicitly disabled - if (NULL != getenv("LL_DISABLE_GSTREAMER")) - return false; - - // only do global GStreamer initialization once. - if (!mDoneInit) - { - g_thread_init(NULL); - - // Init the glib type system - we need it. - g_type_init(); - - // Get symbols! -#if LL_DARWIN - if (! grab_gst_syms("libgstreamer-0.10.dylib", - "libgstvideo-0.10.dylib") ) -#elseif LL_WINDOWS - if (! grab_gst_syms("libgstreamer-0.10.dll", - "libgstvideo-0.10.dll") ) -#else // linux or other ELFy unixoid - if (! grab_gst_syms("libgstreamer-0.10.so.0", - "libgstvideo-0.10.so.0") ) -#endif - { - WARNMSG("Couldn't find suitable GStreamer 0.10 support on this system - video playback disabled."); - return false; - } - - if (llgst_segtrap_set_enabled) - { - llgst_segtrap_set_enabled(FALSE); - } - else - { - WARNMSG("gst_segtrap_set_enabled() is not available; plugin crashes won't be caught."); - } - -#if LL_LINUX - // Gstreamer tries a fork during init, waitpid-ing on it, - // which conflicts with any installed SIGCHLD handler... - struct sigaction tmpact, oldact; - if (llgst_registry_fork_set_enabled) { - // if we can disable SIGCHLD-using forking behaviour, - // do it. - llgst_registry_fork_set_enabled(false); - } - else { - // else temporarily install default SIGCHLD handler - // while GStreamer initialises - tmpact.sa_handler = SIG_DFL; - sigemptyset( &tmpact.sa_mask ); - tmpact.sa_flags = SA_SIGINFO; - sigaction(SIGCHLD, &tmpact, &oldact); - } -#endif // LL_LINUX - - // Protect against GStreamer resetting the locale, yuck. - static std::string saved_locale; - saved_locale = setlocale(LC_ALL, NULL); - - // finally, try to initialize GStreamer! - GError *err = NULL; - gboolean init_gst_success = llgst_init_check(NULL, NULL, &err); - - // restore old locale - setlocale(LC_ALL, saved_locale.c_str() ); - -#if LL_LINUX - // restore old SIGCHLD handler - if (!llgst_registry_fork_set_enabled) - sigaction(SIGCHLD, &oldact, NULL); -#endif // LL_LINUX - - if (!init_gst_success) // fail - { - if (err) - { - WARNMSG("GST init failed: %s", err->message); - g_error_free(err); - } - else - { - WARNMSG("GST init failed for unspecified reason."); - } - return false; - } - - // Init our custom plugins - only really need do this once. - gst_slvideo_init_class(); - - mDoneInit = true; - } - - return true; -} - - -void -MediaPluginGStreamer010::sizeChanged() -{ - // the shared writing space has possibly changed size/location/whatever - - // Check to see whether the movie's NATURAL size has been set yet - if (1 == mNaturalWidth && - 1 == mNaturalHeight) - { - mNaturalWidth = mCurrentWidth; - mNaturalHeight = mCurrentHeight; - DEBUGMSG("Media NATURAL size better detected as %dx%d", - mNaturalWidth, mNaturalHeight); - } - - // if the size has changed then the shm has changed and the app needs telling - if (mCurrentWidth != mPreviousWidth || - mCurrentHeight != mPreviousHeight) - { - mPreviousWidth = mCurrentWidth; - mPreviousHeight = mCurrentHeight; - - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change_request"); - message.setValue("name", mTextureSegmentName); - message.setValueS32("width", mNaturalWidth); - message.setValueS32("height", mNaturalHeight); - DEBUGMSG("<--- Sending size change request to application with name: '%s' - natural size is %d x %d", mTextureSegmentName.c_str(), mNaturalWidth, mNaturalHeight); - sendMessage(message); - } -} - - - -//static -bool -MediaPluginGStreamer010::closedown() -{ - if (!mDoneInit) - return false; // error - - ungrab_gst_syms(); - - mDoneInit = false; - - return true; -} - -MediaPluginGStreamer010::~MediaPluginGStreamer010() -{ - DEBUGMSG("MediaPluginGStreamer010 destructor"); - - closedown(); - - DEBUGMSG("GStreamer010 closing down"); -} - - -std::string -MediaPluginGStreamer010::getVersion() -{ - std::string plugin_version = "GStreamer010 media plugin, GStreamer version "; - if (mDoneInit && - llgst_version) - { - guint major, minor, micro, nano; - llgst_version(&major, &minor, µ, &nano); - plugin_version += llformat("%u.%u.%u.%u (runtime), %u.%u.%u.%u (headers)", (unsigned int)major, (unsigned int)minor, (unsigned int)micro, (unsigned int)nano, (unsigned int)GST_VERSION_MAJOR, (unsigned int)GST_VERSION_MINOR, (unsigned int)GST_VERSION_MICRO, (unsigned int)GST_VERSION_NANO); - } - else - { - plugin_version += "(unknown)"; - } - return plugin_version; -} - -void MediaPluginGStreamer010::receiveMessage(const char *message_string) -{ - //std::cerr << "MediaPluginGStreamer010::receiveMessage: received message: \"" << message_string << "\"" << std::endl; - - LLPluginMessage message_in; - - if(message_in.parse(message_string) >= 0) - { - std::string message_class = message_in.getClass(); - std::string message_name = message_in.getName(); - if(message_class == LLPLUGIN_MESSAGE_CLASS_BASE) - { - if(message_name == "init") - { - LLPluginMessage message("base", "init_response"); - LLSD versions = LLSD::emptyMap(); - versions[LLPLUGIN_MESSAGE_CLASS_BASE] = LLPLUGIN_MESSAGE_CLASS_BASE_VERSION; - versions[LLPLUGIN_MESSAGE_CLASS_MEDIA] = LLPLUGIN_MESSAGE_CLASS_MEDIA_VERSION; - versions[LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME] = LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME_VERSION; - message.setValueLLSD("versions", versions); - - if ( load() ) - { - DEBUGMSG("GStreamer010 media instance set up"); - } - else - { - WARNMSG("GStreamer010 media instance failed to set up"); - } - - message.setValue("plugin_version", getVersion()); - sendMessage(message); - } - else if(message_name == "idle") - { - // no response is necessary here. - double time = message_in.getValueReal("time"); - - // Convert time to milliseconds for update() - update((int)(time * 1000.0f)); - } - else if(message_name == "cleanup") - { - unload(); - closedown(); - } - else if(message_name == "shm_added") - { - SharedSegmentInfo info; - info.mAddress = message_in.getValuePointer("address"); - info.mSize = (size_t)message_in.getValueS32("size"); - std::string name = message_in.getValue("name"); - - std::ostringstream str; - INFOMSG("MediaPluginGStreamer010::receiveMessage: shared memory added, name: %s, size: %d, address: %p", name.c_str(), int(info.mSize), info.mAddress); - - mSharedSegments.insert(SharedSegmentMap::value_type(name, info)); - } - else if(message_name == "shm_remove") - { - std::string name = message_in.getValue("name"); - - DEBUGMSG("MediaPluginGStreamer010::receiveMessage: shared memory remove, name = %s", name.c_str()); - - SharedSegmentMap::iterator iter = mSharedSegments.find(name); - if(iter != mSharedSegments.end()) - { - if(mPixels == iter->second.mAddress) - { - // This is the currently active pixel buffer. Make sure we stop drawing to it. - mPixels = NULL; - mTextureSegmentName.clear(); - - // Make sure the movie decoder is no longer pointed at the shared segment. - sizeChanged(); - } - mSharedSegments.erase(iter); - } - else - { - WARNMSG("MediaPluginGStreamer010::receiveMessage: unknown shared memory region!"); - } - - // Send the response so it can be cleaned up. - LLPluginMessage message("base", "shm_remove_response"); - message.setValue("name", name); - sendMessage(message); - } - else - { - std::ostringstream str; - INFOMSG("MediaPluginGStreamer010::receiveMessage: unknown base message: %s", message_name.c_str()); - } - } - else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA) - { - if(message_name == "init") - { - // Plugin gets to decide the texture parameters to use. - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "texture_params"); - // lame to have to decide this now, it depends on the movie. Oh well. - mDepth = 4; - - mCurrentWidth = 1; - mCurrentHeight = 1; - mPreviousWidth = 1; - mPreviousHeight = 1; - mNaturalWidth = 1; - mNaturalHeight = 1; - mWidth = 1; - mHeight = 1; - mTextureWidth = 1; - mTextureHeight = 1; - - message.setValueU32("format", GL_RGBA); - message.setValueU32("type", GL_UNSIGNED_INT_8_8_8_8_REV); - - message.setValueS32("depth", mDepth); - message.setValueS32("default_width", mWidth); - message.setValueS32("default_height", mHeight); - message.setValueU32("internalformat", GL_RGBA8); - message.setValueBoolean("coords_opengl", true); // true == use OpenGL-style coordinates, false == (0,0) is upper left. - message.setValueBoolean("allow_downsample", true); // we respond with grace and performance if asked to downscale - sendMessage(message); - } - else if(message_name == "size_change") - { - std::string name = message_in.getValue("name"); - S32 width = message_in.getValueS32("width"); - S32 height = message_in.getValueS32("height"); - S32 texture_width = message_in.getValueS32("texture_width"); - S32 texture_height = message_in.getValueS32("texture_height"); - - std::ostringstream str; - INFOMSG("---->Got size change instruction from application with shm name: %s - size is %d x %d", name.c_str(), width, height); - - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change_response"); - message.setValue("name", name); - message.setValueS32("width", width); - message.setValueS32("height", height); - message.setValueS32("texture_width", texture_width); - message.setValueS32("texture_height", texture_height); - sendMessage(message); - - if(!name.empty()) - { - // Find the shared memory region with this name - SharedSegmentMap::iterator iter = mSharedSegments.find(name); - if(iter != mSharedSegments.end()) - { - INFOMSG("*** Got size change with matching shm, new size is %d x %d", width, height); - INFOMSG("*** Got size change with matching shm, texture size size is %d x %d", texture_width, texture_height); - - mPixels = (unsigned char*)iter->second.mAddress; - mTextureSegmentName = name; - mWidth = width; - mHeight = height; - - if (texture_width > 1 || - texture_height > 1) // not a dummy size from the app, a real explicit forced size - { - INFOMSG("**** = REAL RESIZE REQUEST FROM APP"); - - GST_OBJECT_LOCK(mVideoSink); - mVideoSink->resize_forced_always = true; - mVideoSink->resize_try_width = texture_width; - mVideoSink->resize_try_height = texture_height; - GST_OBJECT_UNLOCK(mVideoSink); - } - - mTextureWidth = texture_width; - mTextureHeight = texture_height; - } - } - } - else if(message_name == "load_uri") - { - std::string uri = message_in.getValue("uri"); - navigateTo( uri ); - sendStatus(); - } - else if(message_name == "mouse_event") - { - std::string event = message_in.getValue("event"); - S32 x = message_in.getValueS32("x"); - S32 y = message_in.getValueS32("y"); - - if(event == "down") - { - mouseDown(x, y); - } - else if(event == "up") - { - mouseUp(x, y); - } - else if(event == "move") - { - mouseMove(x, y); - }; - }; - } - else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME) - { - if(message_name == "stop") - { - stop(); - } - else if(message_name == "start") - { - double rate = 0.0; - if(message_in.hasValue("rate")) - { - rate = message_in.getValueReal("rate"); - } - // NOTE: we don't actually support rate. - play(rate); - } - else if(message_name == "pause") - { - pause(); - } - else if(message_name == "seek") - { - double time = message_in.getValueReal("time"); - // defer the actual seek in case we haven't - // really truly started yet in which case there - // is nothing to seek upon - mSeekWanted = true; - mSeekDestination = time; - } - else if(message_name == "set_loop") - { - bool loop = message_in.getValueBoolean("loop"); - mIsLooping = loop; - } - else if(message_name == "set_volume") - { - double volume = message_in.getValueReal("volume"); - setVolume(volume); - } - } - else - { - INFOMSG("MediaPluginGStreamer010::receiveMessage: unknown message class: %s", message_class.c_str()); - } - } -} - -int init_media_plugin(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data, LLPluginInstance::sendMessageFunction *plugin_send_func, void **plugin_user_data) -{ - if (MediaPluginGStreamer010::startup()) - { - MediaPluginGStreamer010 *self = new MediaPluginGStreamer010(host_send_func, host_user_data); - *plugin_send_func = MediaPluginGStreamer010::staticReceiveMessage; - *plugin_user_data = (void*)self; - - return 0; // okay - } - else - { - return -1; // failed to init - } -} - -#else // LL_GSTREAMER010_ENABLED - -// Stubbed-out class with constructor/destructor (necessary or windows linker -// will just think its dead code and optimize it all out) -class MediaPluginGStreamer010 : public MediaPluginBase -{ -public: - MediaPluginGStreamer010(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data); - ~MediaPluginGStreamer010(); - /* virtual */ void receiveMessage(const char *message_string); -}; - -MediaPluginGStreamer010::MediaPluginGStreamer010( - LLPluginInstance::sendMessageFunction host_send_func, - void *host_user_data ) : - MediaPluginBase(host_send_func, host_user_data) -{ - // no-op -} - -MediaPluginGStreamer010::~MediaPluginGStreamer010() -{ - // no-op -} - -void MediaPluginGStreamer010::receiveMessage(const char *message_string) -{ - // no-op -} - -// We're building without GStreamer enabled. Just refuse to initialize. -int init_media_plugin(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data, LLPluginInstance::sendMessageFunction *plugin_send_func, void **plugin_user_data) -{ - return -1; -} - -#endif // LL_GSTREAMER010_ENABLED diff --git a/indra/media_plugins/gstreamer10/CMakeLists.txt b/indra/media_plugins/gstreamer10/CMakeLists.txt new file mode 100644 index 0000000000..f9898368cc --- /dev/null +++ b/indra/media_plugins/gstreamer10/CMakeLists.txt @@ -0,0 +1,52 @@ +# -*- cmake -*- + +project(media_plugin_gstreamer) + +include(00-Common) +include(LLCommon) +include(LLImage) +include(LLMath) +include(LLWindow) +include(Linking) +include(PluginAPI) +include(OpenGL) +include(GLIB) + +include(GStreamer10Plugin) + +### media_plugin_gstreamer10 + +set(${PROJECT_NAME}_SOURCE_FILES + media_plugin_gstreamer10.cpp + ) + +set(media_plugin_gstreamer10_HEADER_FILES + llmediaimplgstreamer_syms.h + llmediaimplgstreamertriviallogging.h + ) + +add_library(${PROJECT_NAME} + SHARED + ${${PROJECT_NAME}_SOURCE_FILES} +) + +target_link_libraries(${PROJECT_NAME} media_plugin_base ll::gstreamer10 ) + +if (WINDOWS) + set_target_properties( + media_plugin_gstreamer10 + PROPERTIES + LINK_FLAGS "/MANIFEST:NO /SAFESEH:NO /NODEFAULTLIB:LIBCMT" + ) +endif (WINDOWS) + +if (INSTALL) + if (EXISTS ${CMAKE_SYSROOT}/usr/lib/${ARCH}-linux-gnu) + set(_LIB lib/${ARCH}-linux-gnu) + elseif (EXISTS /lib64) + set(_LIB lib64) + else () + set(_LIB lib) + endif () + install(TARGETS ${PROJECT_NAME} DESTINATION ${_LIB}) +endif () diff --git a/indra/media_plugins/gstreamer010/llmediaimplgstreamer.h b/indra/media_plugins/gstreamer10/llmediaimplgstreamer.h index cae11a5cb3..cae11a5cb3 100644 --- a/indra/media_plugins/gstreamer010/llmediaimplgstreamer.h +++ b/indra/media_plugins/gstreamer10/llmediaimplgstreamer.h diff --git a/indra/media_plugins/gstreamer10/llmediaimplgstreamer_syms_raw.inc b/indra/media_plugins/gstreamer10/llmediaimplgstreamer_syms_raw.inc new file mode 100644 index 0000000000..6f5bb04bdf --- /dev/null +++ b/indra/media_plugins/gstreamer10/llmediaimplgstreamer_syms_raw.inc @@ -0,0 +1,71 @@ +#define G gstSymbolGrabber + +LL_GRAB_SYM(G, true, gst_buffer_new, GstBuffer*, void) +LL_GRAB_SYM(G, true, gst_structure_set_value, void, GstStructure *, const gchar *, const GValue*) +LL_GRAB_SYM(G, true, gst_init_check, gboolean, int *argc, char **argv[], GError ** err) +LL_GRAB_SYM(G, true, gst_message_get_type, GType, void) +LL_GRAB_SYM(G, true, gst_message_type_get_name, const gchar*, GstMessageType type) +LL_GRAB_SYM(G, true, gst_message_parse_error, void, GstMessage *message, GError **gerror, gchar **debug) +LL_GRAB_SYM(G, true, gst_message_parse_warning, void, GstMessage *message, GError **gerror, gchar **debug) +LL_GRAB_SYM(G, true, gst_message_parse_state_changed, void, GstMessage *message, GstState *oldstate, GstState *newstate, GstState *pending) +LL_GRAB_SYM(G, true, gst_element_set_state, GstStateChangeReturn, GstElement *element, GstState state) +LL_GRAB_SYM(G, true, gst_object_unref, void, gpointer object) +LL_GRAB_SYM(G, true, gst_object_get_type, GType, void) +LL_GRAB_SYM(G, true, gst_pipeline_get_type, GType, void) +LL_GRAB_SYM(G, true, gst_pipeline_get_bus, GstBus*, GstPipeline *pipeline) +LL_GRAB_SYM(G, true, gst_bus_add_watch, guint, GstBus * bus, GstBusFunc func, gpointer user_data) +LL_GRAB_SYM(G, true, gst_element_factory_make, GstElement*, const gchar *factoryname, const gchar *name) +LL_GRAB_SYM(G, true, gst_element_get_type, GType, void) +LL_GRAB_SYM(G, true, gst_static_pad_template_get, GstPadTemplate*, GstStaticPadTemplate *pad_template) +LL_GRAB_SYM(G, true, gst_element_class_add_pad_template, void, GstElementClass *klass, GstPadTemplate *temp) +LL_GRAB_SYM(G, true, gst_caps_from_string, GstCaps *, const gchar *string) +LL_GRAB_SYM(G, true, gst_caps_get_structure, GstStructure *, const GstCaps *caps, guint index) +LL_GRAB_SYM(G, true, gst_element_register, gboolean, GstPlugin *plugin, const gchar *name, guint rank, GType type) +LL_GRAB_SYM(G, true, gst_structure_get_int, gboolean, const GstStructure *structure, const gchar *fieldname, gint *value) +LL_GRAB_SYM(G, true, gst_structure_get_value, const GValue *, const GstStructure *structure, const gchar *fieldname) +LL_GRAB_SYM(G, true, gst_value_get_fraction_numerator, gint, const GValue *value) +LL_GRAB_SYM(G, true, gst_value_get_fraction_denominator, gint, const GValue *value) +LL_GRAB_SYM(G, true, gst_structure_get_name, const gchar *, const GstStructure *structure) +LL_GRAB_SYM(G, true, gst_element_seek, bool, GstElement *, gdouble, GstFormat, GstSeekFlags, GstSeekType, gint64, GstSeekType, gint64) + +LL_GRAB_SYM(G, false, gst_registry_fork_set_enabled, void, gboolean enabled) +LL_GRAB_SYM(G, false, gst_segtrap_set_enabled, void, gboolean enabled) +LL_GRAB_SYM(G, false, gst_message_parse_buffering, void, GstMessage *message, gint *percent) +LL_GRAB_SYM(G, false, gst_message_parse_info, void, GstMessage *message, GError **gerror, gchar **debug) +LL_GRAB_SYM(G, false, gst_element_query_position, gboolean, GstElement *element, GstFormat *format, gint64 *cur) +LL_GRAB_SYM(G, false, gst_version, void, guint *major, guint *minor, guint *micro, guint *nano) + +LL_GRAB_SYM(G, true, gst_message_parse_tag, void, GstMessage *, GstTagList **) +LL_GRAB_SYM(G, true, gst_tag_list_foreach, void, const GstTagList *, GstTagForeachFunc, gpointer) +LL_GRAB_SYM(G, true, gst_tag_list_get_tag_size, guint, const GstTagList *, const gchar *) +LL_GRAB_SYM(G, true, gst_tag_list_get_value_index, const GValue *, const GstTagList *, const gchar *, guint) + +LL_GRAB_SYM(G, true, gst_caps_new_simple, GstCaps*, const char *, const char*, ... ) + +LL_GRAB_SYM(G, true, gst_sample_get_caps, GstCaps*, GstSample* ) +LL_GRAB_SYM(G, true, gst_sample_get_buffer, GstBuffer*, GstSample* ) +LL_GRAB_SYM(G, true, gst_buffer_map, gboolean, GstBuffer*, GstMapInfo*, GstMapFlags ) +LL_GRAB_SYM(G, true, gst_buffer_unmap, void, GstBuffer*, GstMapInfo* ) + +LL_GRAB_SYM(G, true, gst_app_sink_set_caps, void, GstAppSink*, GstCaps const* ) +LL_GRAB_SYM(G, true, gst_app_sink_pull_sample, GstSample*, GstAppSink* ) + +LL_GRAB_SYM(G, true, g_free, void, gpointer ) +LL_GRAB_SYM(G, true, g_error_free, void, GError* ) + +LL_GRAB_SYM(G, true, g_main_context_pending, gboolean, GMainContext* ) +LL_GRAB_SYM(G, true, g_main_loop_get_context, GMainContext*, GMainLoop* ) +LL_GRAB_SYM(G, true, g_main_context_iteration, gboolean, GMainContext*, gboolean ) +LL_GRAB_SYM(G, true, g_main_loop_new, GMainLoop*, GMainContext*, gboolean ) +LL_GRAB_SYM(G, true, g_main_loop_quit, void, GMainLoop* ) +LL_GRAB_SYM(G, true, gst_mini_object_unref, void, GstMiniObject* ) +LL_GRAB_SYM(G, true, g_object_set, void, gpointer, gchar const*, ... ) +LL_GRAB_SYM(G, true, g_source_remove, gboolean, guint ) +LL_GRAB_SYM(G, true, g_value_get_string, gchar const*, GValue const* ) + +LL_GRAB_SYM(G, true, gst_debug_set_active, void, gboolean ) +LL_GRAB_SYM(G, true, gst_debug_add_log_function, void, GstLogFunction, gpointer, GDestroyNotify ) +LL_GRAB_SYM(G, true, gst_debug_set_default_threshold, void, GstDebugLevel ) +LL_GRAB_SYM(G, true, gst_debug_message_get , gchar const*, GstDebugMessage * ) + +#undef G diff --git a/indra/media_plugins/gstreamer10/media_plugin_gstreamer10.cpp b/indra/media_plugins/gstreamer10/media_plugin_gstreamer10.cpp new file mode 100644 index 0000000000..3f636915ea --- /dev/null +++ b/indra/media_plugins/gstreamer10/media_plugin_gstreamer10.cpp @@ -0,0 +1,958 @@ +/** + * @file media_plugin_gstreamer10.cpp + * @brief GStreamer-1.0 plugin for LLMedia API plugin system + * + * @cond + * $LicenseInfo:firstyear=2016&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2016, Linden Research, Inc. / Nicky Dasmijn + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + * @endcond + */ + +#define FLIP_Y + +#include "linden_common.h" + +#include "llgl.h" + +#include "llplugininstance.h" +#include "llpluginmessage.h" +#include "llpluginmessageclasses.h" +#include "media_plugin_base.h" + +#define G_DISABLE_CAST_CHECKS +extern "C" { +#include <gst/gst.h> +#include <gst/app/gstappsink.h> +} + +SymbolGrabber gstSymbolGrabber; + +#include "llmediaimplgstreamer_syms_raw.inc" + +static inline void llgst_caps_unref( GstCaps * caps ) +{ + llgst_mini_object_unref( GST_MINI_OBJECT_CAST( caps ) ); +} + +static inline void llgst_sample_unref( GstSample *aSample ) +{ + llgst_mini_object_unref( GST_MINI_OBJECT_CAST( aSample ) ); +} + +////////////////////////////////////////////////////////////////////////////// +// +class MediaPluginGStreamer10 : public MediaPluginBase +{ +public: + MediaPluginGStreamer10(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data); + ~MediaPluginGStreamer10(); + + /* virtual */ void receiveMessage(const char *message_string); + + static bool startup(); + static bool closedown(); + + gboolean processGSTEvents(GstBus *bus, GstMessage *message); + +private: + std::string getVersion(); + bool navigateTo( const std::string urlIn ); + bool seek( double time_sec ); + bool setVolume( float volume ); + + // misc + bool pause(); + bool stop(); + bool play(double rate); + bool getTimePos(double &sec_out); + + double MIN_LOOP_SEC = 1.0F; + U32 INTERNAL_TEXTURE_SIZE = 1024; + + bool mIsLooping; + + enum ECommand { + COMMAND_NONE, + COMMAND_STOP, + COMMAND_PLAY, + COMMAND_FAST_FORWARD, + COMMAND_FAST_REWIND, + COMMAND_PAUSE, + COMMAND_SEEK, + }; + ECommand mCommand; + +private: + bool unload(); + bool load(); + + bool update(int milliseconds); + void mouseDown( int x, int y ); + void mouseUp( int x, int y ); + void mouseMove( int x, int y ); + + static bool mDoneInit; + + guint mBusWatchID; + + float mVolume; + + int mDepth; + + // padded texture size we need to write into + int mTextureWidth; + int mTextureHeight; + + bool mSeekWanted; + double mSeekDestination; + + // Very GStreamer-specific + GMainLoop *mPump; // event pump for this media + GstElement *mPlaybin; + GstAppSink *mAppSink; +}; + +//static +bool MediaPluginGStreamer10::mDoneInit = false; + +MediaPluginGStreamer10::MediaPluginGStreamer10( LLPluginInstance::sendMessageFunction host_send_func, + void *host_user_data ) + : MediaPluginBase(host_send_func, host_user_data) + , mBusWatchID ( 0 ) + , mSeekWanted(false) + , mSeekDestination(0.0) + , mPump ( nullptr ) + , mPlaybin ( nullptr ) + , mAppSink ( nullptr ) + , mCommand ( COMMAND_NONE ) +{ +} + +gboolean MediaPluginGStreamer10::processGSTEvents(GstBus *bus, GstMessage *message) +{ + if (!message) + return TRUE; // shield against GStreamer bug + + switch (GST_MESSAGE_TYPE (message)) + { + case GST_MESSAGE_BUFFERING: + { + // NEEDS GST 0.10.11+ + if (llgst_message_parse_buffering) + { + gint percent = 0; + llgst_message_parse_buffering(message, &percent); + } + break; + } + case GST_MESSAGE_STATE_CHANGED: + { + GstState old_state; + GstState new_state; + GstState pending_state; + llgst_message_parse_state_changed(message, + &old_state, + &new_state, + &pending_state); + + switch (new_state) + { + case GST_STATE_VOID_PENDING: + break; + case GST_STATE_NULL: + break; + case GST_STATE_READY: + setStatus(STATUS_LOADED); + break; + case GST_STATE_PAUSED: + setStatus(STATUS_PAUSED); + break; + case GST_STATE_PLAYING: + setStatus(STATUS_PLAYING); + break; + } + break; + } + case GST_MESSAGE_ERROR: + { + GError *err = nullptr; + gchar *debug = nullptr; + + llgst_message_parse_error (message, &err, &debug); + if (err) + llg_error_free (err); + llg_free (debug); + + mCommand = COMMAND_STOP; + + setStatus(STATUS_ERROR); + + break; + } + case GST_MESSAGE_INFO: + { + if (llgst_message_parse_info) + { + GError *err = nullptr; + gchar *debug = nullptr; + + llgst_message_parse_info (message, &err, &debug); + if (err) + llg_error_free (err); + llg_free (debug); + } + break; + } + case GST_MESSAGE_WARNING: + { + GError *err = nullptr; + gchar *debug = nullptr; + + llgst_message_parse_warning (message, &err, &debug); + if (err) + llg_error_free (err); + llg_free (debug); + + break; + } + case GST_MESSAGE_EOS: + /* end-of-stream */ + if (mIsLooping) + { + double eos_pos_sec = 0.0F; + bool got_eos_position = getTimePos(eos_pos_sec); + + if (got_eos_position && eos_pos_sec < MIN_LOOP_SEC) + { + // if we know that the movie is really short, don't + // loop it else it can easily become a time-hog + // because of GStreamer spin-up overhead + // inject a COMMAND_PAUSE + mCommand = COMMAND_PAUSE; + } + else + { + stop(); + play(1.0); + } + } + else // not a looping media + { + // inject a COMMAND_STOP + mCommand = COMMAND_STOP; + } + break; + default: + /* unhandled message */ + break; + } + + /* we want to be notified again the next time there is a message + * on the bus, so return true (false means we want to stop watching + * for messages on the bus and our callback should not be called again) + */ + return TRUE; +} + +extern "C" { + gboolean llmediaimplgstreamer_bus_callback (GstBus *bus, + GstMessage *message, + gpointer data) + { + MediaPluginGStreamer10 *impl = (MediaPluginGStreamer10*)data; + return impl->processGSTEvents(bus, message); + } +} // extern "C" + + + +bool MediaPluginGStreamer10::navigateTo ( const std::string urlIn ) +{ + if (!mDoneInit) + return false; // error + + setStatus(STATUS_LOADING); + + mSeekWanted = false; + + if (nullptr == mPump || nullptr == mPlaybin) + { + setStatus(STATUS_ERROR); + return false; // error + } + + llg_object_set (G_OBJECT (mPlaybin), "uri", urlIn.c_str(), nullptr); + + // navigateTo implicitly plays, too. + play(1.0); + + return true; +} + + +class GstSampleUnref +{ + GstSample *mT; +public: + GstSampleUnref( GstSample *aT ) + : mT( aT ) + { llassert_always( mT ); } + + ~GstSampleUnref( ) + { llgst_sample_unref( mT ); } +}; + +bool MediaPluginGStreamer10::update(int milliseconds) +{ + if (!mDoneInit) + return false; // error + + // DEBUGMSG("updating media..."); + + // sanity check + if (nullptr == mPump || nullptr == mPlaybin) + { + return false; + } + + // see if there's an outstanding seek wanted + if (mSeekWanted && + // bleh, GST has to be happy that the movie is really truly playing + // or it may quietly ignore the seek (with rtsp:// at least). + (GST_STATE(mPlaybin) == GST_STATE_PLAYING)) + { + seek(mSeekDestination); + mSeekWanted = false; + } + + // *TODO: time-limit - but there isn't a lot we can do here, most + // time is spent in gstreamer's own opaque worker-threads. maybe + // we can do something sneaky like only unlock the video object + // for 'milliseconds' and otherwise hold the lock. + while (llg_main_context_pending(llg_main_loop_get_context(mPump))) + { + llg_main_context_iteration(llg_main_loop_get_context(mPump), FALSE); + } + + // check for availability of a new frame + + if( !mAppSink ) + return true; + + if( GST_STATE(mPlaybin) != GST_STATE_PLAYING) // Do not try to pull a sample if not in playing state + return true; + + GstSample *pSample = llgst_app_sink_pull_sample( mAppSink ); + if(!pSample) + return false; // Done playing + + GstSampleUnref oSampleUnref( pSample ); + GstCaps *pCaps = llgst_sample_get_caps ( pSample ); + if (!pCaps) + return false; + + gint width = 0, height = 0; + GstStructure *pStruct = llgst_caps_get_structure ( pCaps, 0); + + if(!llgst_structure_get_int ( pStruct, "width", &width) ) + width = 0; + if(!llgst_structure_get_int ( pStruct, "height", &height) ) + height = 0; + + if( !mPixels || width == 0 || height == 0) + return true; + + GstBuffer *pBuffer = llgst_sample_get_buffer ( pSample ); + GstMapInfo map; + llgst_buffer_map ( pBuffer, &map, GST_MAP_READ); + + // Our render buffer is always 1kx1k + + U32 rowSkip = INTERNAL_TEXTURE_SIZE / mTextureHeight; + U32 colSkip = INTERNAL_TEXTURE_SIZE / mTextureWidth; + + for (int row = 0; row < mTextureHeight; ++row) + { + U8 const *pTexelIn = map.data + (row*rowSkip * width *3); +#ifndef FLIP_Y + U8 *pTexelOut = mPixels + (row * mTextureWidth * mDepth ); +#else + U8 *pTexelOut = mPixels + ((mTextureHeight-row-1) * mTextureWidth * mDepth ); +#endif + for( int col = 0; col < mTextureWidth; ++col ) + { + pTexelOut[ 0 ] = pTexelIn[0]; + pTexelOut[ 1 ] = pTexelIn[1]; + pTexelOut[ 2 ] = pTexelIn[2]; + pTexelOut += mDepth; + pTexelIn += colSkip*3; + } + } + + llgst_buffer_unmap( pBuffer, &map ); + setDirty(0,0,mTextureWidth,mTextureHeight); + + return true; +} + +void MediaPluginGStreamer10::mouseDown( int x, int y ) +{ + // do nothing +} + +void MediaPluginGStreamer10::mouseUp( int x, int y ) +{ + // do nothing +} + +void MediaPluginGStreamer10::mouseMove( int x, int y ) +{ + // do nothing +} + + +bool MediaPluginGStreamer10::pause() +{ + // todo: error-check this? + if (mDoneInit && mPlaybin) + { + llgst_element_set_state(mPlaybin, GST_STATE_PAUSED); + return true; + } + return false; +} + +bool MediaPluginGStreamer10::stop() +{ + // todo: error-check this? + if (mDoneInit && mPlaybin) + { + llgst_element_set_state(mPlaybin, GST_STATE_READY); + return true; + } + return false; +} + +bool MediaPluginGStreamer10::play(double rate) +{ + // NOTE: we don't actually support non-natural rate. + + // todo: error-check this? + if (mDoneInit && mPlaybin) + { + llgst_element_set_state(mPlaybin, GST_STATE_PLAYING); + return true; + } + return false; +} + +bool MediaPluginGStreamer10::setVolume( float volume ) +{ + // we try to only update volume as conservatively as + // possible, as many gst-plugins-base versions up to at least + // November 2008 have critical race-conditions in setting volume - sigh + if (mVolume == volume) + return true; // nothing to do, everything's fine + + mVolume = volume; + if (mDoneInit && mPlaybin) + { + llg_object_set(mPlaybin, "volume", mVolume, nullptr); + return true; + } + + return false; +} + +bool MediaPluginGStreamer10::seek(double time_sec) +{ + bool success = false; + if (mDoneInit && mPlaybin) + { + success = llgst_element_seek(mPlaybin, 1.0F, GST_FORMAT_TIME, + GstSeekFlags(GST_SEEK_FLAG_FLUSH | + GST_SEEK_FLAG_KEY_UNIT), + GST_SEEK_TYPE_SET, gint64(time_sec*GST_SECOND), + GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE); + } + return success; +} + +bool MediaPluginGStreamer10::getTimePos(double &sec_out) +{ + bool got_position = false; + if (mDoneInit && mPlaybin) + { + gint64 pos(0); + GstFormat timefmt = GST_FORMAT_TIME; + got_position = + llgst_element_query_position && + llgst_element_query_position(mPlaybin, + &timefmt, + &pos); + got_position = got_position + && (timefmt == GST_FORMAT_TIME); + // GStreamer may have other ideas, but we consider the current position + // undefined if not PLAYING or PAUSED + got_position = got_position && + (GST_STATE(mPlaybin) == GST_STATE_PLAYING || + GST_STATE(mPlaybin) == GST_STATE_PAUSED); + if (got_position && !GST_CLOCK_TIME_IS_VALID(pos)) + { + if (GST_STATE(mPlaybin) == GST_STATE_PLAYING) + { + // if we're playing then we treat an invalid clock time + // as 0, for complicated reasons (insert reason here) + pos = 0; + } + else + { + got_position = false; + } + + } + // If all the preconditions succeeded... we can trust the result. + if (got_position) + { + sec_out = double(pos) / double(GST_SECOND); // gst to sec + } + } + return got_position; +} + +bool MediaPluginGStreamer10::load() +{ + if (!mDoneInit) + return false; // error + + setStatus(STATUS_LOADING); + + mIsLooping = false; + mVolume = 0.1234567f; // minor hack to force an initial volume update + + // Create a pumpable main-loop for this media + mPump = llg_main_loop_new (nullptr, FALSE); + if (!mPump) + { + setStatus(STATUS_ERROR); + return false; // error + } + + // instantiate a playbin element to do the hard work + mPlaybin = llgst_element_factory_make ("playbin", ""); + if (!mPlaybin) + { + setStatus(STATUS_ERROR); + return false; // error + } + + // get playbin's bus + GstBus *bus = llgst_pipeline_get_bus (GST_PIPELINE (mPlaybin)); + if (!bus) + { + setStatus(STATUS_ERROR); + return false; // error + } + mBusWatchID = llgst_bus_add_watch (bus, + llmediaimplgstreamer_bus_callback, + this); + llgst_object_unref (bus); + + mAppSink = (GstAppSink*)(llgst_element_factory_make ("appsink", "")); + + GstCaps* pCaps = llgst_caps_new_simple( "video/x-raw", + "format", G_TYPE_STRING, "RGB", + "width", G_TYPE_INT, INTERNAL_TEXTURE_SIZE, + "height", G_TYPE_INT, INTERNAL_TEXTURE_SIZE, + nullptr ); + + llgst_app_sink_set_caps( mAppSink, pCaps ); + llgst_caps_unref( pCaps ); + + if (!mAppSink) + { + setStatus(STATUS_ERROR); + return false; + } + + llg_object_set(mPlaybin, "video-sink", mAppSink, nullptr); + + return true; +} + +bool MediaPluginGStreamer10::unload () +{ + if (!mDoneInit) + return false; // error + + // stop getting callbacks for this bus + llg_source_remove(mBusWatchID); + mBusWatchID = 0; + + if (mPlaybin) + { + llgst_element_set_state (mPlaybin, GST_STATE_NULL); + llgst_object_unref (GST_OBJECT (mPlaybin)); + mPlaybin = nullptr; + } + + if (mPump) + { + llg_main_loop_quit(mPump); + mPump = nullptr; + } + + mAppSink = nullptr; + + setStatus(STATUS_NONE); + + return true; +} + +void LogFunction(GstDebugCategory *category, GstDebugLevel level, const gchar *file, const gchar *function, gint line, GObject *object, GstDebugMessage *message, gpointer user_data ) +{ + std::cerr << file << ":" << line << "(" << function << "): " << llgst_debug_message_get( message ) << std::endl; +} + +//static +bool MediaPluginGStreamer10::startup() +{ + // first - check if GStreamer is explicitly disabled + if (nullptr != getenv("LL_DISABLE_GSTREAMER")) + return false; + + // only do global GStreamer initialization once. + if (!mDoneInit) + { + ll_init_apr(); + + // Get symbols! + std::vector< std::string > vctDSONames; + vctDSONames.push_back( "libgstreamer-1.0.so.0" ); + vctDSONames.push_back( "libgstapp-1.0.so.0" ); + vctDSONames.push_back( "libglib-2.0.so.0" ); + vctDSONames.push_back( "libgobject-2.0.so" ); + if( !gstSymbolGrabber.grabSymbols( vctDSONames ) ) + return false; + + if (llgst_segtrap_set_enabled) + { + llgst_segtrap_set_enabled(FALSE); + } + + // Gstreamer tries a fork during init, waitpid-ing on it, + // which conflicts with any installed SIGCHLD handler... + struct sigaction tmpact, oldact; + if (llgst_registry_fork_set_enabled ) { + // if we can disable SIGCHLD-using forking behaviour, + // do it. + llgst_registry_fork_set_enabled(false); + } + else { + // else temporarily install default SIGCHLD handler + // while GStreamer initialises + tmpact.sa_handler = SIG_DFL; + sigemptyset( &tmpact.sa_mask ); + tmpact.sa_flags = SA_SIGINFO; + sigaction(SIGCHLD, &tmpact, &oldact); + } + // Protect against GStreamer resetting the locale, yuck. + static std::string saved_locale; + saved_locale = setlocale(LC_ALL, nullptr); + + llgst_debug_set_default_threshold( GST_LEVEL_WARNING ); + llgst_debug_add_log_function( LogFunction, nullptr, nullptr ); + llgst_debug_set_active( false ); + + // finally, try to initialize GStreamer! + GError *err = nullptr; + gboolean init_gst_success = llgst_init_check(nullptr, nullptr, &err); + + // restore old locale + setlocale(LC_ALL, saved_locale.c_str() ); + + // restore old SIGCHLD handler + if (!llgst_registry_fork_set_enabled) + sigaction(SIGCHLD, &oldact, nullptr); + + if (!init_gst_success) // fail + { + if (err) + llg_error_free(err); + return false; + } + + mDoneInit = true; + } + + return true; +} + +//static +bool MediaPluginGStreamer10::closedown() +{ + if (!mDoneInit) + return false; // error + + gstSymbolGrabber.ungrabSymbols(); + mDoneInit = false; + + return true; +} + +MediaPluginGStreamer10::~MediaPluginGStreamer10() +{ + closedown(); +} + +std::string MediaPluginGStreamer10::getVersion() +{ + std::string plugin_version = "GStreamer10 media plugin, GStreamer version "; + if (mDoneInit && + llgst_version) + { + guint major, minor, micro, nano; + llgst_version(&major, &minor, µ, &nano); + plugin_version += llformat("%u.%u.%u.%u (runtime), %u.%u.%u.%u (headers)", (unsigned int)major, (unsigned int)minor, + (unsigned int)micro, (unsigned int)nano, (unsigned int)GST_VERSION_MAJOR, (unsigned int)GST_VERSION_MINOR, + (unsigned int)GST_VERSION_MICRO, (unsigned int)GST_VERSION_NANO); + } + else + { + plugin_version += "(unknown)"; + } + return plugin_version; +} + +void MediaPluginGStreamer10::receiveMessage(const char *message_string) +{ + LLPluginMessage message_in; + + if(message_in.parse(message_string) >= 0) + { + std::string message_class = message_in.getClass(); + std::string message_name = message_in.getName(); + + if(message_class == LLPLUGIN_MESSAGE_CLASS_BASE) + { + if(message_name == "init") + { + LLPluginMessage message("base", "init_response"); + LLSD versions = LLSD::emptyMap(); + versions[LLPLUGIN_MESSAGE_CLASS_BASE] = LLPLUGIN_MESSAGE_CLASS_BASE_VERSION; + versions[LLPLUGIN_MESSAGE_CLASS_MEDIA] = LLPLUGIN_MESSAGE_CLASS_MEDIA_VERSION; + versions[LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME] = LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME_VERSION; + message.setValueLLSD("versions", versions); + + load(); + + message.setValue("plugin_version", getVersion()); + sendMessage(message); + } + else if(message_name == "idle") + { + // no response is necessary here. + double time = message_in.getValueReal("time"); + + // Convert time to milliseconds for update() + update((int)(time * 1000.0f)); + } + else if(message_name == "cleanup") + { + unload(); + closedown(); + } + else if(message_name == "shm_added") + { + SharedSegmentInfo info; + info.mAddress = message_in.getValuePointer("address"); + info.mSize = (size_t)message_in.getValueS32("size"); + std::string name = message_in.getValue("name"); + + mSharedSegments.insert(SharedSegmentMap::value_type(name, info)); + } + else if(message_name == "shm_remove") + { + std::string name = message_in.getValue("name"); + + SharedSegmentMap::iterator iter = mSharedSegments.find(name); + if(iter != mSharedSegments.end()) + { + if(mPixels == iter->second.mAddress) + { + // This is the currently active pixel buffer. Make sure we stop drawing to it. + mPixels = nullptr; + mTextureSegmentName.clear(); + } + mSharedSegments.erase(iter); + } + + // Send the response so it can be cleaned up. + LLPluginMessage message("base", "shm_remove_response"); + message.setValue("name", name); + sendMessage(message); + } + } + else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA) + { + if(message_name == "init") + { + // Plugin gets to decide the texture parameters to use. + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "texture_params"); + // lame to have to decide this now, it depends on the movie. Oh well. + mDepth = 4; + + mTextureWidth = 1; + mTextureHeight = 1; + + message.setValueU32("format", GL_RGBA); + message.setValueU32("type", GL_UNSIGNED_INT_8_8_8_8_REV); + + message.setValueS32("depth", mDepth); + message.setValueS32("default_width", INTERNAL_TEXTURE_SIZE ); + message.setValueS32("default_height", INTERNAL_TEXTURE_SIZE ); + message.setValueU32("internalformat", GL_RGBA8); + message.setValueBoolean("coords_opengl", true); // true == use OpenGL-style coordinates, false == (0,0) is upper left. + message.setValueBoolean("allow_downsample", true); // we respond with grace and performance if asked to downscale + sendMessage(message); + } + else if(message_name == "size_change") + { + std::string name = message_in.getValue("name"); + S32 width = message_in.getValueS32("width"); + S32 height = message_in.getValueS32("height"); + S32 texture_width = message_in.getValueS32("texture_width"); + S32 texture_height = message_in.getValueS32("texture_height"); + + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change_response"); + message.setValue("name", name); + message.setValueS32("width", width); + message.setValueS32("height", height); + message.setValueS32("texture_width", texture_width); + message.setValueS32("texture_height", texture_height); + sendMessage(message); + + if(!name.empty()) + { + // Find the shared memory region with this name + SharedSegmentMap::iterator iter = mSharedSegments.find(name); + if(iter != mSharedSegments.end()) + { + mPixels = (unsigned char*)iter->second.mAddress; + mTextureSegmentName = name; + + mTextureWidth = texture_width; + mTextureHeight = texture_height; + memset( mPixels, 0, mTextureWidth*mTextureHeight*mDepth ); + } + + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change_request"); + message.setValue("name", mTextureSegmentName); + message.setValueS32("width", INTERNAL_TEXTURE_SIZE ); + message.setValueS32("height", INTERNAL_TEXTURE_SIZE ); + sendMessage(message); + + } + } + else if(message_name == "load_uri") + { + std::string uri = message_in.getValue("uri"); + navigateTo( uri ); + sendStatus(); + } + else if(message_name == "mouse_event") + { + std::string event = message_in.getValue("event"); + S32 x = message_in.getValueS32("x"); + S32 y = message_in.getValueS32("y"); + + if(event == "down") + { + mouseDown(x, y); + } + else if(event == "up") + { + mouseUp(x, y); + } + else if(event == "move") + { + mouseMove(x, y); + }; + }; + } + else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME) + { + if(message_name == "stop") + { + stop(); + } + else if(message_name == "start") + { + double rate = 0.0; + if(message_in.hasValue("rate")) + { + rate = message_in.getValueReal("rate"); + } + // NOTE: we don't actually support rate. + play(rate); + } + else if(message_name == "pause") + { + pause(); + } + else if(message_name == "seek") + { + double time = message_in.getValueReal("time"); + // defer the actual seek in case we haven't + // really truly started yet in which case there + // is nothing to seek upon + mSeekWanted = true; + mSeekDestination = time; + } + else if(message_name == "set_loop") + { + bool loop = message_in.getValueBoolean("loop"); + mIsLooping = loop; + } + else if(message_name == "set_volume") + { + double volume = message_in.getValueReal("volume"); + setVolume(volume); + } + } + } +} + +int init_media_plugin(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data, LLPluginInstance::sendMessageFunction *plugin_send_func, void **plugin_user_data) +{ + if( MediaPluginGStreamer10::startup() ) + { + MediaPluginGStreamer10 *self = new MediaPluginGStreamer10(host_send_func, host_user_data); + *plugin_send_func = MediaPluginGStreamer10::staticReceiveMessage; + *plugin_user_data = (void*)self; + + return 0; // okay + } + else + { + return -1; // failed to init + } +} diff --git a/indra/media_plugins/libvlc/CMakeLists.txt b/indra/media_plugins/libvlc/CMakeLists.txt index a3c1c4ef99..1710d18f4d 100644 --- a/indra/media_plugins/libvlc/CMakeLists.txt +++ b/indra/media_plugins/libvlc/CMakeLists.txt @@ -13,13 +13,6 @@ include(LibVLCPlugin) ### media_plugin_libvlc -if(NOT ADDRESS_SIZE EQUAL 32) - if(WINDOWS) - ##add_definitions(/FIXED:NO) - else(WINDOWS) # not windows therefore gcc LINUX and DARWIN - add_definitions(-fPIC) - endif(WINDOWS) -endif(NOT ADDRESS_SIZE EQUAL 32) set(media_plugin_libvlc_SOURCE_FILES media_plugin_libvlc.cpp @@ -54,4 +47,46 @@ if (DARWIN) LINK_FLAGS "-exported_symbols_list ${CMAKE_CURRENT_SOURCE_DIR}/../base/media_plugin_base.exp" ) + add_custom_command(TARGET ${PROJECT_NAME} + POST_BUILD COMMAND ${CMAKE_INSTALL_NAME_TOOL} + -change "/opt/local/lib/libopenjp2.7.dylib" "@loader_path/../../Frameworks/libopenjp2.7.dylib" + -change "/opt/local/lib/libpng16.16.dylib" "@loader_path/../../Frameworks/libpng16.16.dylib" + -change "/opt/local/lib/libjpeg.8.dylib" "@loader_path/../../Frameworks/libjpeg.8.dylib" + -change "/opt/local/lib/libfreetype.6.dylib" "@loader_path/../../Frameworks/libfreetype.6.dylib" + -change "/opt/local/lib/libaprutil-1.0.dylib" "@loader_path/../../Frameworks/libaprutil-1.0.dylib" + -change "/opt/local/lib/libiconv.2.dylib" "@loader_path/../../Frameworks/libiconv.2.dylib" + -change "/opt/local/lib/libapr-1.0.dylib" "@loader_path/../../Frameworks/libapr-1.0.dylib" + -change "/opt/local/lib/libexpat.1.dylib" "@loader_path/../../Frameworks/libexpat.1.dylib" + -change "/opt/local/lib/libjsoncpp.25.dylib" "@loader_path/../../Frameworks/libjsoncpp.25.dylib" + -change "/opt/local/lib/libz.1.dylib" "@loader_path/../../Frameworks/libz.1.dylib" + -change "/opt/local/libexec/boost/1.76/lib/libboost_context-mt.dylib" "@loader_path/../../Frameworks/libboost_context-mt.dylib" + -change "/opt/local/libexec/boost/1.76/lib/libboost_fiber-mt.dylib" "@loader_path/../../Frameworks/libboost_fiber-mt.dylib" + -change "/opt/local/libexec/boost/1.76/lib/libboost_filesystem-mt.dylib" "@loader_path/../../Frameworks/libboost_filesystem-mt.dylib" + -change "/opt/local/libexec/boost/1.76/lib/libboost_program_options-mt.dylib" "@loader_path/../../Frameworks/libboost_program_options-mt.dylib" + -change "/opt/local/libexec/boost/1.76/lib/libboost_regex-mt.dylib" "@loader_path/../../Frameworks/libboost_regex-mt.dylib" + -change "/opt/local/libexec/boost/1.76/lib/libboost_system-mt.dylib" "@loader_path/../../Frameworks/libboost_system-mt.dylib" + -change "/opt/local/libexec/boost/1.76/lib/libboost_thread-mt.dylib" "@loader_path/../../Frameworks/libboost_thread-mt.dylib" + -change "/opt/local/lib/liburiparser.1.dylib" "@loader_path/../../Frameworks/liburiparser.1.dylib" + -change "/opt/local/lib/libnghttp2.14.dylib" "@loader_path/../../Frameworks/libnghttp2.14.dylib" + -change "/usr/local/lib/libxmlrpc-epi.0.dylib" "@loader_path/../../Frameworks/libxmlrpc-epi.0.dylib" + -change "@rpath/libvlc.dylib" "@loader_path/plugins/libvlc.dylib" + -change "@rpath/libvlccore.dylib" "@loader_path/plugins/libvlccore.dylib" + "$<TARGET_FILE:media_plugin_libvlc>" + VERBATIM + COMMENT "Fixing paths to LibVLC media plugin dependencies" + ) + endif (DARWIN) + +if (INSTALL) + if (DARWIN) + set(_LIB llplugin) + elseif (EXISTS ${CMAKE_SYSROOT}/usr/lib/${ARCH}-linux-gnu) + set(_LIB lib/${ARCH}-linux-gnu) + elseif (EXISTS /lib64) + set(_LIB lib64) + else (DARWIN) + set(_LIB lib) + endif (DARWIN) + install(TARGETS ${PROJECT_NAME} DESTINATION ${_LIB}) +endif (INSTALL) diff --git a/indra/media_plugins/libvlc/media_plugin_libvlc.cpp b/indra/media_plugins/libvlc/media_plugin_libvlc.cpp index a5d8f885fd..8ae9931dd4 100644 --- a/indra/media_plugins/libvlc/media_plugin_libvlc.cpp +++ b/indra/media_plugins/libvlc/media_plugin_libvlc.cpp @@ -294,6 +294,15 @@ void MediaPluginLibVLC::eventCallbacks(const libvlc_event_t* event, void* ptr) } } break; + case libvlc_MediaMetaChanged: + auto now_playing = libvlc_media_get_meta(parent->mLibVLCMedia, libvlc_meta_NowPlaying); + if (now_playing) + { + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "nowplaying_text"); + message.setValue("nowplaying", now_playing); + parent->sendMessage(message); + } + break; } } @@ -348,6 +357,11 @@ void MediaPluginLibVLC::playMedia() libvlc_event_attach(em, libvlc_MediaPlayerLengthChanged, eventCallbacks, this); libvlc_event_attach(em, libvlc_MediaPlayerTitleChanged, eventCallbacks, this); } + auto event_manager = libvlc_media_event_manager(mLibVLCMedia); + if (event_manager) + { + libvlc_event_attach(event_manager, libvlc_MediaMetaChanged, eventCallbacks, this); + } libvlc_video_set_callbacks(mLibVLCMediaPlayer, lock, unlock, display, &mLibVLCCallbackContext); libvlc_video_set_format(mLibVLCMediaPlayer, "RV32", mWidth, mHeight, mWidth * mDepth); diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 97d9c02ce1..546e38b4d7 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -9,15 +9,21 @@ include(Linking) include(Boost) include(bugsplat) +if (NOT USESYSTEMLIBS) include(BuildPackagesInfo) +endif () include(BuildVersion) include(CMakeCopyIfDifferent) +if (NOT USESYSTEMLIBS) include(CubemapToEquirectangularJS) include(DBusGlib) +endif () include(DragDrop) include(EXPAT) include(Hunspell) +if (NOT USESYSTEMLIBS) include(JPEGEncoderBasic) +endif () include(LLAppearance) include(LLAudio) include(LLCA) @@ -36,18 +42,29 @@ include(OpenSSL) include(PNG) include(TemplateCheck) include(TinyEXR) +if (NOT USESYSTEMLIBS) include(ThreeJS) +endif () include(Tracy) include(UI) include(ViewerMiscLibs) +if (NOT USESYSTEMLIBS) include(ViewerManager) +endif () include(VisualLeakDetector) include(VulkanGltf) include(ZLIBNG) include(URIPARSER) include(LLPrimitive) -if (NOT HAVOK_TPV) +if (ENABLE_MEDIA_PLUGINS) + include(LibVLCPlugin) + if (DARWIN OR LINUX) + include(CEFPlugin) + endif (DARWIN OR LINUX) +endif (ENABLE_MEDIA_PLUGINS) + +if (NOT (USESYSTEMLIBS OR HAVOK_TPV)) # When using HAVOK_TPV, the library is precompiled, so no need for this # Stub and probably havok lib itself is a hack, autobuild loads a 3p that really is a source tarball @@ -68,7 +85,7 @@ if (NOT HAVOK_TPV) target_compile_options( llphysicsextensions PRIVATE -Wno-unused-local-typedef) endif (DARWIN) endif() -endif (NOT HAVOK_TPV) +endif (NOT (USESYSTEMLIBS OR HAVOK_TPV)) set(viewer_SOURCE_FILES gltfscenemanager.cpp @@ -228,6 +245,8 @@ set(viewer_SOURCE_FILES llfloaterhandler.cpp llfloaterhelpbrowser.cpp llfloaterhoverheight.cpp + mpfloatertuning.cpp + fsfloatersearch.cpp llfloaterhowto.cpp llfloaterhud.cpp llfloaterimagepreview.cpp @@ -722,6 +741,10 @@ set(viewer_SOURCE_FILES pipeline.cpp ) +if (CMAKE_SYSTEM_NAME MATCHES FreeBSD) + list(REMOVE_ITEM viewer_SOURCE_FILES llvoicewebrtc.cpp) +endif () + set(VIEWER_BINARY_NAME "secondlife-bin" CACHE STRING "The name of the viewer executable to create.") @@ -888,6 +911,8 @@ set(viewer_HEADER_FILES llfloaterhandler.h llfloaterhelpbrowser.h llfloaterhoverheight.h + mpfloatertuning.h + fsfloatersearch.h llfloaterhowto.h llfloaterhud.h llfloaterimagepreview.h @@ -1433,17 +1458,18 @@ if (DARWIN) list(APPEND viewer_SOURCE_FILES ${viewer_RESOURCE_FILES}) endif (DARWIN) -if (LINUX) +if (USESYSTEMLIBS AND NOT DARWIN) LIST(APPEND viewer_SOURCE_FILES llappviewerlinux.cpp) set_source_files_properties( llappviewerlinux.cpp PROPERTIES COMPILE_DEFINITIONS "${VIEWER_CHANNEL_VERSION_DEFINES}" ) - LIST(APPEND viewer_SOURCE_FILES llappviewerlinux_api_dbus.cpp) + if (NOT CMAKE_CXX_COMPILER_ID MATCHES "AppleClang") SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--as-needed") + endif () -endif (LINUX) +endif (USESYSTEMLIBS AND NOT DARWIN) if (WINDOWS) @@ -1630,6 +1656,10 @@ set(viewer_APPSETTINGS_FILES featuretable_mac.txt ) +if (USESYSTEMLIBS) + list(REMOVE_ITEM viewer_APPSETTINGS_FILES packages-info.txt) +endif () + source_group("App Settings" FILES ${viewer_APPSETTINGS_FILES}) set_source_files_properties(${viewer_APPSETTINGS_FILES} @@ -1911,7 +1941,6 @@ target_link_libraries(${VIEWER_BINARY_NAME} llcorehttp llcommon llmeshoptimizer - llwebrtc ll::ndof lllogin llprimitive @@ -1921,6 +1950,17 @@ target_link_libraries(${VIEWER_BINARY_NAME} ll::tracy ) +if (NOT CMAKE_SYSTEM_NAME MATCHES FreeBSD) + target_link_libraries(${VIEWER_BINARY_NAME} llwebrtc ) +endif () + +if (ENABLE_MEDIA_PLUGINS) + target_link_libraries(${VIEWER_BINARY_NAME} ll::libvlc ) + if (DARWIN OR LINUX) + target_link_libraries(${VIEWER_BINARY_NAME} ll::cef ) + endif (DARWIN OR LINUX) +endif (ENABLE_MEDIA_PLUGINS) + if( TARGET ll::intel_memops ) target_link_libraries(${VIEWER_BINARY_NAME} ll::intel_memops ) endif() @@ -1932,6 +1972,46 @@ endif() set(ARTWORK_DIR ${CMAKE_CURRENT_SOURCE_DIR} CACHE PATH "Path to artwork files.") +set_source_files_properties(llinventorygallery.cpp PROPERTIES COMPILE_FLAGS + -Wno-unused-but-set-variable) +if (CMAKE_CXX_COMPILER_ID MATCHES "Clang") + set_source_files_properties(llappviewerlinux.cpp PROPERTIES + COMPILE_FLAGS -Wno-dangling-gsl + ) + set_source_files_properties(llviewerstats.cpp PROPERTIES + COMPILE_FLAGS -Wno-unused-value) +elseif (CMAKE_CXX_COMPILER_ID MATCHES "GNU") + set_source_files_properties( + llface.cpp + llhttpretrypolicy.cpp + llmodelpreview.cpp + llpanelface.cpp + lltexturefetch.cpp + PROPERTIES COMPILE_FLAGS -Wno-maybe-uninitialized) + set_source_files_properties(llfasttimerview.cpp PROPERTIES + COMPILE_FLAGS -Wno-nonnull) + set_source_files_properties(llinventorygallerymenu.cpp PROPERTIES + COMPILE_FLAGS -Wno-uninitialized) + set_source_files_properties(llviewerstats.cpp PROPERTIES + COMPILE_FLAGS -Wno-unused-value) + set_source_files_properties(llurl.cpp PROPERTIES COMPILE_FLAGS + -Wno-stringop-truncation) + set_source_files_properties( + llfloaterimsessiontab.cpp + llfloatersimplesnapshot.cpp + llfloatersidepanelcontainer.cpp + llinventorypanel.cpp + llpanelmaininventory.cpp + llpathfindingnavmesh.cpp + llsidepanelinventory.cpp + PROPERTIES COMPILE_FLAGS -Wno-dangling-reference + ) + set_source_files_properties( + gltf/animation.cpp + gltf/primitive.cpp + PROPERTIES COMPILE_FLAGS -Wno-unused-function) +endif () + message("Copying fonts") file(GLOB FONT_FILE_GLOB_LIST "${AUTOBUILD_INSTALL_DIR}/fonts/*" @@ -1954,7 +2034,92 @@ foreach(elem ${country_codes}) configure_file(${emoji_mapping_src_file} ${emoji_mapping_dst_file} COPYONLY) endforeach() +if (PACKAGE AND USESYSTEMLIBS) + set(CPACK_PACKAGE_NAME ${VIEWER_BINARY_NAME} + CACHE STRING "Viewer binary name.") + set(CPACK_PACKAGE_VERSION ${VIEWER_VERSION_MAJOR}.${VIEWER_VERSION_MINOR}.${VIEWER_VERSION_PATCH}.${VIEWER_VERSION_REVISION} + CACHE STRING "Viewer major.minor.patch.revision versions.") + set(VIEWER_PACKAGE_COMMENT + "A fork of the Second Life viewer" + ) + set(VIEWER_PACKAGE_DESCRIPTION + "An entrance to virtual empires in only megabytes. A shelter for the metaverse refugees, especially those from less supported operating systems." + ) + set(VIEWER_PACKAGE_DOMAIN_NAME + ${VIEWER_BINARY_NAME}.net + ) +endif (PACKAGE AND USESYSTEMLIBS) + if (LINUX) + if (USESYSTEMLIBS) + add_custom_command( + TARGET ${VIEWER_BINARY_NAME} POST_BUILD + COMMAND ${CMAKE_SYSROOT}/usr/bin/sed + ARGS -e '/Linden Lab.*/d' ${CMAKE_HOME_DIRECTORY}/../doc/contributions.txt > ${CMAKE_CURRENT_BINARY_DIR}/contributions.txt + COMMAND ${CMAKE_SYSROOT}/usr/bin/sed + ARGS -i ${CMAKE_CURRENT_BINARY_DIR}/contributions.txt -e '/following residents.*/d' ${CMAKE_CURRENT_BINARY_DIR}/contributions.txt + COMMAND ${CMAKE_SYSROOT}/usr/bin/sed + ARGS -i ${CMAKE_CURRENT_BINARY_DIR}/contributions.txt -e '/along with.*/d' ${CMAKE_CURRENT_BINARY_DIR}/contributions.txt + COMMAND ${CMAKE_SYSROOT}/usr/bin/sed + ARGS -i ${CMAKE_CURRENT_BINARY_DIR}/contributions.txt -e '/^$$/d' ${CMAKE_CURRENT_BINARY_DIR}/contributions.txt + COMMAND ${CMAKE_SYSROOT}/usr/bin/sed + ARGS -i ${CMAKE_CURRENT_BINARY_DIR}/contributions.txt -e '/\t.*/d' ${CMAKE_CURRENT_BINARY_DIR}/contributions.txt + COMMAND ${CMAKE_SYSROOT}/usr/bin/sed + ARGS -i ${CMAKE_CURRENT_BINARY_DIR}/contributions.txt -e '/^ .*/d' ${CMAKE_CURRENT_BINARY_DIR}/contributions.txt + COMMAND sort + ARGS -R contributions.txt -o ${CMAKE_CURRENT_BINARY_DIR}/contributions.txt + COMMAND paste + ARGS -s -d, ${CMAKE_CURRENT_BINARY_DIR}/contributions.txt > ${CMAKE_CURRENT_BINARY_DIR}/contributors.txt + COMMAND ${CMAKE_SYSROOT}/usr/bin/sed + ARGS -i ${CMAKE_CURRENT_BINARY_DIR}/contributions.txt -e 's/,/, /g' ${CMAKE_CURRENT_BINARY_DIR}/contributors.txt + ) + if (PACKAGE) + if (${LINUX_DISTRO} MATCHES debian OR ${LINUX_DISTRO} MATCHES ubuntu) + set(CPACK_BINARY_DEB ON CACHE BOOL "Able to package Debian DEB.") + set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE + amd64 + CACHE STRING "Debian package architecture.") + set(CPACK_DEBIAN_PACKAGE_DESCRIPTION ${VIEWER_PACKAGE_COMMENT} + CACHE STRING "Debian package description.") + set(CPACK_DEBIAN_PACKAGE_MAINTAINER + $ENV{USER}@${VIEWER_PACKAGE_DOMAIN_NAME} + CACHE STRING "Debian package maintainer.") + set(CPACK_DEBIAN_PACKAGE_SECTION net + CACHE STRING "Debian package section.") + if (${LINUX_DISTRO} MATCHES debian) + set(CPACK_DEBIAN_PACKAGE_DEPENDS + "libalut0, libaprutil1, libboost-fiber1.81.0, libboost-filesystem1.81.0, libboost-program-options1.81.0, libboost-regex1.81.0, libboost-thread1.81.0, libcollada-dom2.5-dp0, libexpat1, libfltk1.3, libglu1-mesa, libhunspell-1.7-0, libmeshoptimizer2d (>= 0.18), libnghttp2-14, libsdl2-2.0-0, liburiparser1, libvlc5, libvorbisenc2, libvorbisfile3, libxmlrpc-epi0, vlc-plugin-base" + CACHE STRING "Debian package dependencies.") + elseif (${LINUX_DISTRO} MATCHES ubuntu) + set(CPACK_DEBIAN_PACKAGE_DEPENDS + "libalut0, libaprutil1t64, libboost-fiber1.83.0, libboost-filesystem1.83.0, libboost-program-options1.83.0, libboost-regex1.83.0, libboost-thread1.83.0, libcollada-dom2.5-dp0, libexpat1, libfltk2.0-0t64, libglu1-mesa, libhunspell-1.7-0, libmeshoptimizer2d, libnghttp2-14, libsdl2-2.0-0, liburiparser1, libvlc5, libvorbisenc2, libvorbisfile3, libxmlrpc-epi0t64, vlc-plugin-base" + CACHE STRING "Debian package dependencies.") + endif (${LINUX_DISTRO} MATCHES debian) + elseif (${LINUX_DISTRO} MATCHES fedora OR (${LINUX_DISTRO} MATCHES opensuse-tumbleweed)) + set(CPACK_BINARY_RPM ON CACHE BOOL "Able to package Fedora RPM.") + set(CPACK_RPM_PACKAGE_SUMMARY ${VIEWER_PACKAGE_COMMENT} + CACHE STRING "RPM package summary.") + set(CPACK_RPM_PACKAGE_ARCHITECTURE + ${CMAKE_SYSTEM_PROCESSOR} + CACHE STRING "RPM package architecture.") + set(CPACK_RPM_PACKAGE_LICENSE LGPL-2.1-only + CACHE STRING "RPM package license.") + set(CPACK_RPM_PACKAGE_VENDOR ${VIEWER_CHANNEL} + CACHE STRING "RPM package vendor.") + set(CPACK_RPM_PACKAGE_URL + https://${VIEWER_PACKAGE_DOMAIN_NAME} + CACHE STRING "RPM package URL.") + set(CPACK_RPM_PACKAGE_DESCRIPTION ${VIEWER_PACKAGE_DESCRIPTION} + CACHE STRING "RPM package description.") + if (${LINUX_DISTRO} MATCHES fedora) + set(CPACK_RPM_PACKAGE_REQUIRES + "apr-util, boost-fiber, boost-program-options, boost-regex, boost-thread, collada-dom, expat, fltk, mesa-libGLU, hunspell, libnghttp2, openjpeg2, SDL2, uriparser, vlc-libs, vlc-plugins-base, libvorbis, xmlrpc-epi" + CACHE STRING "RPM package requirements.") + elseif (${LINUX_DISTRO} MATCHES opensuse-tumbleweed) + endif (${LINUX_DISTRO} MATCHES fedora) + endif (${LINUX_DISTRO} MATCHES debian OR ${LINUX_DISTRO} MATCHES ubuntu) + endif (PACKAGE) + else (USESYSTEMLIBS) set(product SecondLife-${ARCH}-${VIEWER_SHORT_VERSION}.${VIEWER_VERSION_REVISION}) # These are the generated targets that are copied to package/ @@ -2027,6 +2192,49 @@ if (LINUX) add_dependencies(llpackage copy_l_viewer_manifest) check_message_template(llpackage) endif (PACKAGE) + endif (USESYSTEMLIBS) +elseif (USESYSTEMLIBS) + add_custom_command( + TARGET ${VIEWER_BINARY_NAME} POST_BUILD + COMMAND sed + ARGS -e '/Linden Lab.*/d' ${CMAKE_HOME_DIRECTORY}/../doc/contributions.txt > ${CMAKE_CURRENT_BINARY_DIR}/contributions.txt + COMMAND sed + ARGS -i '' -e '/following residents.*/d' ${CMAKE_CURRENT_BINARY_DIR}/contributions.txt + COMMAND sed + ARGS -i '' -e '/along with.*/d' ${CMAKE_CURRENT_BINARY_DIR}/contributions.txt + COMMAND sed + ARGS -i '' -e '/^$$/d' ${CMAKE_CURRENT_BINARY_DIR}/contributions.txt + COMMAND sed + ARGS -i '' -e '/\t.*/d' ${CMAKE_CURRENT_BINARY_DIR}/contributions.txt + COMMAND sed + ARGS -i '' -e '/^ .*/d' ${CMAKE_CURRENT_BINARY_DIR}/contributions.txt + COMMAND sort + ARGS -R contributions.txt -o ${CMAKE_CURRENT_BINARY_DIR}/contributions.txt + COMMAND paste + ARGS -s -d, ${CMAKE_CURRENT_BINARY_DIR}/contributions.txt > ${CMAKE_CURRENT_BINARY_DIR}/contributors.txt + COMMAND sed + ARGS -i '' -e 's/,/, /g' ${CMAKE_CURRENT_BINARY_DIR}/contributors.txt + ) + if (CMAKE_SYSTEM_NAME MATCHES FreeBSD AND PACKAGE) + set(CPACK_BINARY_FREEBSD ON CACHE BOOL "Able to package FreeBSD PKG.") + set(CPACK_FREEBSD_PACKAGE_COMMENT ${VIEWER_PACKAGE_COMMENT} + CACHE STRING "FreeBSD package comment.") + set(CPACK_FREEBSD_PACKAGE_DESCRIPTION ${VIEWER_PACKAGE_DESCRIPTION} + CACHE STRING "FreeBSD package description.") + set(CPACK_FREEBSD_PACKAGE_WWW + https://${VIEWER_PACKAGE_DOMAIN_NAME} + CACHE STRING "FreeBSD package WWW.") + set(CPACK_FREEBSD_PACKAGE_LICENSE LGPL21 + CACHE STRING "FreeBSD package license.") + set(CPACK_FREEBSD_PACKAGE_MAINTAINER + $ENV{USER}@${VIEWER_PACKAGE_DOMAIN_NAME} + CACHE STRING "FreeBSD package maintainer.") + set(CPACK_FREEBSD_PACKAGE_ORIGIN net/${VIEWER_BINARY_NAME} + CACHE STRING "FreeBSD package origin.") + set(CPACK_FREEBSD_PACKAGE_DEPS + "audio/freealut;devel/collada-dom;graphics/libGLU;textproc/hunspell;misc/meshoptimizer;www/libnghttp2;graphics/openjpeg;net/uriparser;multimedia/vlc;audio/libvorbis;net/xmlrpc-epi" + CACHE STRING "FreeBSD package dependencies.") + endif (CMAKE_SYSTEM_NAME MATCHES FreeBSD AND PACKAGE) endif (LINUX) if (DARWIN) @@ -2036,13 +2244,13 @@ if (DARWIN) set(product "${VIEWER_CHANNEL}") set(MACOSX_EXECUTABLE_NAME "${VIEWER_CHANNEL}") set(MACOSX_BUNDLE_INFO_STRING "${VIEWER_CHANNEL}") - set(MACOSX_BUNDLE_ICON_FILE "secondlife.icns") - set(MACOSX_BUNDLE_GUI_IDENTIFIER "com.secondlife.indra.viewer") + set(MACOSX_BUNDLE_ICON_FILE "${VIEWER_CHANNEL}.icns") + set(MACOSX_BUNDLE_GUI_IDENTIFIER "net.megapahit.viewer") set(MACOSX_BUNDLE_LONG_VERSION_STRING "${VIEWER_CHANNEL} ${VIEWER_SHORT_VERSION}.${VIEWER_VERSION_REVISION}") - set(MACOSX_BUNDLE_BUNDLE_NAME "SecondLife") + set(MACOSX_BUNDLE_BUNDLE_NAME "Megapahit") set(MACOSX_BUNDLE_SHORT_VERSION_STRING "${VIEWER_SHORT_VERSION}.${VIEWER_VERSION_REVISION}") set(MACOSX_BUNDLE_BUNDLE_VERSION "${VIEWER_SHORT_VERSION}${VIEWER_MACOSX_PHASE}${VIEWER_REVISION}") - set(MACOSX_BUNDLE_COPYRIGHT "Copyright © Linden Research, Inc. 2020") + set(MACOSX_BUNDLE_COPYRIGHT "Copyright © Megapahit 2024") set(MACOSX_BUNDLE_NSMAIN_NIB_FILE "SecondLife.nib") set(MACOSX_BUNDLE_NSPRINCIPAL_CLASS "LLApplication") @@ -2060,6 +2268,7 @@ if (DARWIN) LINK_FLAGS "-rpath @loader_path/../Frameworks" MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/Info-SecondLife.plist" XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER "${MACOSX_BUNDLE_GUI_IDENTIFIER}" + MACOSX_BUNDLE TRUE ) set(VIEWER_APP_BUNDLE "${CMAKE_CURRENT_BINARY_DIR}/$<IF:$<BOOL:${LL_GENERATOR_IS_MULTI_CONFIG}>,$<CONFIG>,>/${product}.app") @@ -2070,6 +2279,19 @@ if (DARWIN) "${VIEWER_APP_BUNDLE}/Contents/Info.plist" ) + if (USESYSTEMLIBS) + configure_file( + ${CMAKE_CURRENT_SOURCE_DIR}/English.lproj/InfoPlist.strings + ${CMAKE_CURRENT_BINARY_DIR}/InfoPlist.strings + ) + add_custom_command( + TARGET ${VIEWER_BINARY_NAME} POST_BUILD + COMMAND ${CMAKE_INSTALL_NAME_TOOL} + -change "/usr/local/lib/libxmlrpc-epi.0.dylib" "${AUTOBUILD_INSTALL_DIR}/lib/release/libxmlrpc-epi.0.dylib" + ${VIEWER_APP_EXE} + VERBATIM + ) + else (USESYSTEMLIBS) add_custom_command( TARGET ${VIEWER_BINARY_NAME} POST_BUILD COMMAND ${PYTHON_EXECUTABLE} @@ -2093,8 +2315,11 @@ if (DARWIN) ${VIEWER_BINARY_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py ) + endif (USESYSTEMLIBS) + if (ENABLE_MEDIA_PLUGINS) add_dependencies(${VIEWER_BINARY_NAME} SLPlugin media_plugin_libvlc media_plugin_cef) + endif () if (ENABLE_SIGNING) set(SIGNING_SETTING "--signature=${SIGNING_IDENTITY}") @@ -2103,6 +2328,26 @@ if (DARWIN) endif (ENABLE_SIGNING) if (PACKAGE) + if (USESYSTEMLIBS) + set(CPACK_DMG_VOLUME_NAME "${product} Installer" + CACHE STRING "Disk image volume name.") + set(CPACK_DMG_FORMAT UDRW CACHE STRING "Disk image format.") + set(CPACK_DMG_DS_STORE + ${CMAKE_CURRENT_SOURCE_DIR}/installers/darwin/release-dmg/_DS_Store + CACHE STRING "Disk image .DS_Store file.") + set(CPACK_DMG_DS_STORE_SETUP_SCRIPT + ${CMAKE_CURRENT_SOURCE_DIR}/installers/darwin/dmg-cleanup.applescript + CACHE STRING "Disk image AppleScript file.") + set(CPACK_DMG_BACKGROUND_IMAGE + ${CMAKE_CURRENT_SOURCE_DIR}/installers/darwin/release-dmg/background.jpg + CACHE STRING "Disk image background image.") + set(CPACK_BUNDLE_NAME ${product} CACHE STRING "Bundle name.") + set(CPACK_BUNDLE_PLIST ${VIEWER_APP_BUNDLE}/Contents/Info.plist + CACHE STRING "Bundle Property List file.") + set(CPACK_BUNDLE_ICON ${CMAKE_CURRENT_SOURCE_DIR}/secondlife.icns + CACHE STRING "Bundle icon file.") + + else (USESYSTEMLIBS) add_custom_target(llpackage ALL DEPENDS ${VIEWER_BINARY_NAME}) add_custom_command( @@ -2127,12 +2372,16 @@ if (DARWIN) DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py ) + endif (USESYSTEMLIBS) endif (PACKAGE) endif (DARWIN) if (INSTALL) include(${CMAKE_CURRENT_SOURCE_DIR}/ViewerInstall.cmake) endif (INSTALL) +if (PACKAGE AND USESYSTEMLIBS) + include(CPack) +endif (PACKAGE AND USESYSTEMLIBS) if (PACKAGE AND (RELEASE_CRASH_REPORTING OR NON_RELEASE_CRASH_REPORTING) AND VIEWER_SYMBOL_FILE) if (USE_BUGSPLAT) @@ -2343,4 +2592,3 @@ if (LL_TESTS) endif (LL_TESTS) check_message_template(${VIEWER_BINARY_NAME}) - diff --git a/indra/newview/English.lproj/InfoPlist.strings b/indra/newview/English.lproj/InfoPlist.strings index 041b8cea0b..48e7262dd5 100644 --- a/indra/newview/English.lproj/InfoPlist.strings +++ b/indra/newview/English.lproj/InfoPlist.strings @@ -1,7 +1,7 @@ /* Localized versions of Info.plist keys */ -CFBundleName = "Second Life"; +CFBundleName = "Megapahit"; -CFBundleShortVersionString = "Second Life version %%VERSION%%"; -CFBundleGetInfoString = "Second Life version %%VERSION%%, Copyright 2004 Linden Research, Inc."; +CFBundleShortVersionString = "Megapahit version ${MACOSX_BUNDLE_SHORT_VERSION_STRING}"; +CFBundleGetInfoString = "Megapahit version ${MACOSX_BUNDLE_SHORT_VERSION_STRING}, Copyright 2024 Megapahit."; diff --git a/indra/newview/FixBundle.cmake.in b/indra/newview/FixBundle.cmake.in new file mode 100644 index 0000000000..b0d23c712c --- /dev/null +++ b/indra/newview/FixBundle.cmake.in @@ -0,0 +1,156 @@ +include(BundleUtilities) + +set(dirs + /opt/local/lib + ) + +fixup_bundle(${viewer_BINARY_DIR}/${VIEWER_CHANNEL}.app/Contents/MacOS/${VIEWER_CHANNEL} "" "${dirs}") + +file(CREATE_LINK + "../../../../Frameworks/libnghttp2.14.dylib" + "${viewer_BINARY_DIR}/${VIEWER_CHANNEL}.app/Contents/Resources/SLPlugin.app/Contents/Frameworks/libnghttp2.14.dylib" + SYMBOLIC + ) +file(CREATE_LINK + "../../../../Frameworks/libxmlrpc-epi.0.dylib" + "${viewer_BINARY_DIR}/${VIEWER_CHANNEL}.app/Contents/Resources/SLPlugin.app/Contents/Frameworks/libxmlrpc-epi.0.dylib" + SYMBOLIC + ) +file(CREATE_LINK + "../../../../Frameworks/libopenjp2.7.dylib" + "${viewer_BINARY_DIR}/${VIEWER_CHANNEL}.app/Contents/Resources/SLPlugin.app/Contents/Frameworks/libopenjp2.7.dylib" + SYMBOLIC + ) +file(CREATE_LINK + "../../../../Frameworks/libpng16.16.dylib" + "${viewer_BINARY_DIR}/${VIEWER_CHANNEL}.app/Contents/Resources/SLPlugin.app/Contents/Frameworks/libpng16.16.dylib" + SYMBOLIC + ) +file(CREATE_LINK + "../../../../Frameworks/libjpeg.8.dylib" + "${viewer_BINARY_DIR}/${VIEWER_CHANNEL}.app/Contents/Resources/SLPlugin.app/Contents/Frameworks/libjpeg.8.dylib" + SYMBOLIC + ) +file(CREATE_LINK + "../../../../Frameworks/libaprutil-1.0.dylib" + "${viewer_BINARY_DIR}/${VIEWER_CHANNEL}.app/Contents/Resources/SLPlugin.app/Contents/Frameworks/libaprutil-1.0.dylib" + SYMBOLIC + ) +file(CREATE_LINK + "../../../../Frameworks/libiconv.2.dylib" + "${viewer_BINARY_DIR}/${VIEWER_CHANNEL}.app/Contents/Resources/SLPlugin.app/Contents/Frameworks/libiconv.2.dylib" + SYMBOLIC + ) +file(CREATE_LINK + "../../../../Frameworks/libapr-1.0.dylib" + "${viewer_BINARY_DIR}/${VIEWER_CHANNEL}.app/Contents/Resources/SLPlugin.app/Contents/Frameworks/libapr-1.0.dylib" + SYMBOLIC + ) +file(CREATE_LINK + "../../../../Frameworks/libjsoncpp.25.dylib" + "${viewer_BINARY_DIR}/${VIEWER_CHANNEL}.app/Contents/Resources/SLPlugin.app/Contents/Frameworks/libjsoncpp.25.dylib" + SYMBOLIC + ) +file(CREATE_LINK + "../../../../Frameworks/libz.1.dylib" + "${viewer_BINARY_DIR}/${VIEWER_CHANNEL}.app/Contents/Resources/SLPlugin.app/Contents/Frameworks/libz.1.dylib" + SYMBOLIC + ) +file(CREATE_LINK + "../../../../Frameworks/libboost_context-mt.dylib" + "${viewer_BINARY_DIR}/${VIEWER_CHANNEL}.app/Contents/Resources/SLPlugin.app/Contents/Frameworks/libboost_context-mt.dylib" + SYMBOLIC + ) +file(CREATE_LINK + "../../../../Frameworks/libboost_fiber-mt.dylib" + "${viewer_BINARY_DIR}/${VIEWER_CHANNEL}.app/Contents/Resources/SLPlugin.app/Contents/Frameworks/libboost_fiber-mt.dylib" + SYMBOLIC + ) +file(CREATE_LINK + "../../../../Frameworks/libboost_filesystem-mt.dylib" + "${viewer_BINARY_DIR}/${VIEWER_CHANNEL}.app/Contents/Resources/SLPlugin.app/Contents/Frameworks/libboost_filesystem-mt.dylib" + SYMBOLIC + ) +file(CREATE_LINK + "../../../../Frameworks/libboost_program_options-mt.dylib" + "${viewer_BINARY_DIR}/${VIEWER_CHANNEL}.app/Contents/Resources/SLPlugin.app/Contents/Frameworks/libboost_program_options-mt.dylib" + SYMBOLIC + ) +file(CREATE_LINK + "../../../../Frameworks/libboost_regex-mt.dylib" + "${viewer_BINARY_DIR}/${VIEWER_CHANNEL}.app/Contents/Resources/SLPlugin.app/Contents/Frameworks/libboost_regex-mt.dylib" + SYMBOLIC + ) +file(CREATE_LINK + "../../../../Frameworks/libboost_system-mt.dylib" + "${viewer_BINARY_DIR}/${VIEWER_CHANNEL}.app/Contents/Resources/SLPlugin.app/Contents/Frameworks/libboost_system-mt.dylib" + SYMBOLIC + ) +file(CREATE_LINK + "../../../../Frameworks/libboost_thread-mt.dylib" + "${viewer_BINARY_DIR}/${VIEWER_CHANNEL}.app/Contents/Resources/SLPlugin.app/Contents/Frameworks/libboost_thread-mt.dylib" + SYMBOLIC + ) +file(CREATE_LINK + "../../../../Frameworks/liburiparser.1.dylib" + "${viewer_BINARY_DIR}/${VIEWER_CHANNEL}.app/Contents/Resources/SLPlugin.app/Contents/Frameworks/liburiparser.1.dylib" + SYMBOLIC + ) +file(CREATE_LINK + "../../../../Frameworks/libexpat.1.dylib" + "${viewer_BINARY_DIR}/${VIEWER_CHANNEL}.app/Contents/Resources/SLPlugin.app/Contents/Frameworks/libexpat.1.dylib" + SYMBOLIC + ) +file(CREATE_LINK + "../../../../Frameworks/libfreetype.6.dylib" + "${viewer_BINARY_DIR}/${VIEWER_CHANNEL}.app/Contents/Resources/SLPlugin.app/Contents/Frameworks/libfreetype.6.dylib" + SYMBOLIC + ) +file(CREATE_LINK + "../../../../Frameworks/libicudata.74.dylib" + "${viewer_BINARY_DIR}/${VIEWER_CHANNEL}.app/Contents/Resources/SLPlugin.app/Contents/Frameworks/libicudata.74.dylib" + SYMBOLIC + ) +file(CREATE_LINK + "../../../../Frameworks/libicui18n.74.dylib" + "${viewer_BINARY_DIR}/${VIEWER_CHANNEL}.app/Contents/Resources/SLPlugin.app/Contents/Frameworks/libicui18n.74.dylib" + SYMBOLIC + ) +file(CREATE_LINK + "../../../../Frameworks/libicuuc.74.dylib" + "${viewer_BINARY_DIR}/${VIEWER_CHANNEL}.app/Contents/Resources/SLPlugin.app/Contents/Frameworks/libicuuc.74.dylib" + SYMBOLIC + ) +file(CREATE_LINK + "../../../../Frameworks/libbz2.1.0.dylib" + "${viewer_BINARY_DIR}/${VIEWER_CHANNEL}.app/Contents/Resources/SLPlugin.app/Contents/Frameworks/libbz2.1.0.dylib" + SYMBOLIC + ) +file(CREATE_LINK + "../../../../Frameworks/libbrotlidec.1.1.0.dylib" + "${viewer_BINARY_DIR}/${VIEWER_CHANNEL}.app/Contents/Resources/SLPlugin.app/Contents/Frameworks/libbrotlidec.1.1.0.dylib" + SYMBOLIC + ) +file(CREATE_LINK + "../../../../Frameworks/libbrotlidec.1.dylib" + "${viewer_BINARY_DIR}/${VIEWER_CHANNEL}.app/Contents/Resources/SLPlugin.app/Contents/Frameworks/libbrotlidec.1.dylib" + SYMBOLIC + ) +file(CREATE_LINK + "../../../../Frameworks/libbrotlicommon.1.dylib" + "${viewer_BINARY_DIR}/${VIEWER_CHANNEL}.app/Contents/Resources/SLPlugin.app/Contents/Frameworks/libbrotlicommon.1.dylib" + SYMBOLIC + ) +file(CREATE_LINK + "../../../../Frameworks/Chromium Embedded Framework.framework" + "${viewer_BINARY_DIR}/${VIEWER_CHANNEL}.app/Contents/Resources/SLPlugin.app/Contents/Frameworks/Chromium Embedded Framework.framework" + SYMBOLIC + ) + +file(CHMOD + "${viewer_BINARY_DIR}/${VIEWER_CHANNEL}.app/Contents/Resources/SLPlugin.app/Contents/Frameworks/DullahanHelper.app/Contents/MacOS/DullahanHelper" + "${viewer_BINARY_DIR}/${VIEWER_CHANNEL}.app/Contents/Resources/SLPlugin.app/Contents/Frameworks/DullahanHelper (GPU).app/Contents/MacOS/DullahanHelper (GPU)" + "${viewer_BINARY_DIR}/${VIEWER_CHANNEL}.app/Contents/Resources/SLPlugin.app/Contents/Frameworks/DullahanHelper (Plugin).app/Contents/MacOS/DullahanHelper (Plugin)" + "${viewer_BINARY_DIR}/${VIEWER_CHANNEL}.app/Contents/Resources/SLPlugin.app/Contents/Frameworks/DullahanHelper (Renderer).app/Contents/MacOS/DullahanHelper (Renderer)" + PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE + ) diff --git a/indra/newview/FixPackage.cmake.in b/indra/newview/FixPackage.cmake.in new file mode 100644 index 0000000000..fc8cae1d19 --- /dev/null +++ b/indra/newview/FixPackage.cmake.in @@ -0,0 +1,156 @@ +include(BundleUtilities) + +set(dirs + /opt/local/lib + ) + +fixup_bundle(${CMAKE_CACHEFILE_DIR}/_CPack_Packages/${CMAKE_SYSTEM_NAME}/Bundle/${CPACK_BUNDLE_NAME}-${CPACK_PACKAGE_VERSION}-${CMAKE_SYSTEM_NAME}/${CPACK_BUNDLE_NAME}.app/Contents/MacOS/${CPACK_BUNDLE_NAME} "" "${dirs}") + +file(CREATE_LINK + "../../../../Frameworks/libnghttp2.14.dylib" + "${CMAKE_CACHEFILE_DIR}/_CPack_Packages/${CMAKE_SYSTEM_NAME}/Bundle/${CPACK_BUNDLE_NAME}-${CPACK_PACKAGE_VERSION}-${CMAKE_SYSTEM_NAME}/${CPACK_BUNDLE_NAME}.app/Contents/Resources/SLPlugin.app/Contents/Frameworks/libnghttp2.14.dylib" + SYMBOLIC + ) +file(CREATE_LINK + "../../../../Frameworks/libxmlrpc-epi.0.dylib" + "${CMAKE_CACHEFILE_DIR}/_CPack_Packages/${CMAKE_SYSTEM_NAME}/Bundle/${CPACK_BUNDLE_NAME}-${CPACK_PACKAGE_VERSION}-${CMAKE_SYSTEM_NAME}/${CPACK_BUNDLE_NAME}.app/Contents/Resources/SLPlugin.app/Contents/Frameworks/libxmlrpc-epi.0.dylib" + SYMBOLIC + ) +file(CREATE_LINK + "../../../../Frameworks/libopenjp2.7.dylib" + "${CMAKE_CACHEFILE_DIR}/_CPack_Packages/${CMAKE_SYSTEM_NAME}/Bundle/${CPACK_BUNDLE_NAME}-${CPACK_PACKAGE_VERSION}-${CMAKE_SYSTEM_NAME}/${CPACK_BUNDLE_NAME}.app/Contents/Resources/SLPlugin.app/Contents/Frameworks/libopenjp2.7.dylib" + SYMBOLIC + ) +file(CREATE_LINK + "../../../../Frameworks/libpng16.16.dylib" + "${CMAKE_CACHEFILE_DIR}/_CPack_Packages/${CMAKE_SYSTEM_NAME}/Bundle/${CPACK_BUNDLE_NAME}-${CPACK_PACKAGE_VERSION}-${CMAKE_SYSTEM_NAME}/${CPACK_BUNDLE_NAME}.app/Contents/Resources/SLPlugin.app/Contents/Frameworks/libpng16.16.dylib" + SYMBOLIC + ) +file(CREATE_LINK + "../../../../Frameworks/libjpeg.8.dylib" + "${CMAKE_CACHEFILE_DIR}/_CPack_Packages/${CMAKE_SYSTEM_NAME}/Bundle/${CPACK_BUNDLE_NAME}-${CPACK_PACKAGE_VERSION}-${CMAKE_SYSTEM_NAME}/${CPACK_BUNDLE_NAME}.app/Contents/Resources/SLPlugin.app/Contents/Frameworks/libjpeg.8.dylib" + SYMBOLIC + ) +file(CREATE_LINK + "../../../../Frameworks/libaprutil-1.0.dylib" + "${CMAKE_CACHEFILE_DIR}/_CPack_Packages/${CMAKE_SYSTEM_NAME}/Bundle/${CPACK_BUNDLE_NAME}-${CPACK_PACKAGE_VERSION}-${CMAKE_SYSTEM_NAME}/${CPACK_BUNDLE_NAME}.app/Contents/Resources/SLPlugin.app/Contents/Frameworks/libaprutil-1.0.dylib" + SYMBOLIC + ) +file(CREATE_LINK + "../../../../Frameworks/libiconv.2.dylib" + "${CMAKE_CACHEFILE_DIR}/_CPack_Packages/${CMAKE_SYSTEM_NAME}/Bundle/${CPACK_BUNDLE_NAME}-${CPACK_PACKAGE_VERSION}-${CMAKE_SYSTEM_NAME}/${CPACK_BUNDLE_NAME}.app/Contents/Resources/SLPlugin.app/Contents/Frameworks/libiconv.2.dylib" + SYMBOLIC + ) +file(CREATE_LINK + "../../../../Frameworks/libapr-1.0.dylib" + "${CMAKE_CACHEFILE_DIR}/_CPack_Packages/${CMAKE_SYSTEM_NAME}/Bundle/${CPACK_BUNDLE_NAME}-${CPACK_PACKAGE_VERSION}-${CMAKE_SYSTEM_NAME}/${CPACK_BUNDLE_NAME}.app/Contents/Resources/SLPlugin.app/Contents/Frameworks/libapr-1.0.dylib" + SYMBOLIC + ) +file(CREATE_LINK + "../../../../Frameworks/libjsoncpp.25.dylib" + "${CMAKE_CACHEFILE_DIR}/_CPack_Packages/${CMAKE_SYSTEM_NAME}/Bundle/${CPACK_BUNDLE_NAME}-${CPACK_PACKAGE_VERSION}-${CMAKE_SYSTEM_NAME}/${CPACK_BUNDLE_NAME}.app/Contents/Resources/SLPlugin.app/Contents/Frameworks/libjsoncpp.25.dylib" + SYMBOLIC + ) +file(CREATE_LINK + "../../../../Frameworks/libz.1.dylib" + "${CMAKE_CACHEFILE_DIR}/_CPack_Packages/${CMAKE_SYSTEM_NAME}/Bundle/${CPACK_BUNDLE_NAME}-${CPACK_PACKAGE_VERSION}-${CMAKE_SYSTEM_NAME}/${CPACK_BUNDLE_NAME}.app/Contents/Resources/SLPlugin.app/Contents/Frameworks/libz.1.dylib" + SYMBOLIC + ) +file(CREATE_LINK + "../../../../Frameworks/libboost_context-mt.dylib" + "${CMAKE_CACHEFILE_DIR}/_CPack_Packages/${CMAKE_SYSTEM_NAME}/Bundle/${CPACK_BUNDLE_NAME}-${CPACK_PACKAGE_VERSION}-${CMAKE_SYSTEM_NAME}/${CPACK_BUNDLE_NAME}.app/Contents/Resources/SLPlugin.app/Contents/Frameworks/libboost_context-mt.dylib" + SYMBOLIC + ) +file(CREATE_LINK + "../../../../Frameworks/libboost_fiber-mt.dylib" + "${CMAKE_CACHEFILE_DIR}/_CPack_Packages/${CMAKE_SYSTEM_NAME}/Bundle/${CPACK_BUNDLE_NAME}-${CPACK_PACKAGE_VERSION}-${CMAKE_SYSTEM_NAME}/${CPACK_BUNDLE_NAME}.app/Contents/Resources/SLPlugin.app/Contents/Frameworks/libboost_fiber-mt.dylib" + SYMBOLIC + ) +file(CREATE_LINK + "../../../../Frameworks/libboost_filesystem-mt.dylib" + "${CMAKE_CACHEFILE_DIR}/_CPack_Packages/${CMAKE_SYSTEM_NAME}/Bundle/${CPACK_BUNDLE_NAME}-${CPACK_PACKAGE_VERSION}-${CMAKE_SYSTEM_NAME}/${CPACK_BUNDLE_NAME}.app/Contents/Resources/SLPlugin.app/Contents/Frameworks/libboost_filesystem-mt.dylib" + SYMBOLIC + ) +file(CREATE_LINK + "../../../../Frameworks/libboost_program_options-mt.dylib" + "${CMAKE_CACHEFILE_DIR}/_CPack_Packages/${CMAKE_SYSTEM_NAME}/Bundle/${CPACK_BUNDLE_NAME}-${CPACK_PACKAGE_VERSION}-${CMAKE_SYSTEM_NAME}/${CPACK_BUNDLE_NAME}.app/Contents/Resources/SLPlugin.app/Contents/Frameworks/libboost_program_options-mt.dylib" + SYMBOLIC + ) +file(CREATE_LINK + "../../../../Frameworks/libboost_regex-mt.dylib" + "${CMAKE_CACHEFILE_DIR}/_CPack_Packages/${CMAKE_SYSTEM_NAME}/Bundle/${CPACK_BUNDLE_NAME}-${CPACK_PACKAGE_VERSION}-${CMAKE_SYSTEM_NAME}/${CPACK_BUNDLE_NAME}.app/Contents/Resources/SLPlugin.app/Contents/Frameworks/libboost_regex-mt.dylib" + SYMBOLIC + ) +file(CREATE_LINK + "../../../../Frameworks/libboost_system-mt.dylib" + "${CMAKE_CACHEFILE_DIR}/_CPack_Packages/${CMAKE_SYSTEM_NAME}/Bundle/${CPACK_BUNDLE_NAME}-${CPACK_PACKAGE_VERSION}-${CMAKE_SYSTEM_NAME}/${CPACK_BUNDLE_NAME}.app/Contents/Resources/SLPlugin.app/Contents/Frameworks/libboost_system-mt.dylib" + SYMBOLIC + ) +file(CREATE_LINK + "../../../../Frameworks/libboost_thread-mt.dylib" + "${CMAKE_CACHEFILE_DIR}/_CPack_Packages/${CMAKE_SYSTEM_NAME}/Bundle/${CPACK_BUNDLE_NAME}-${CPACK_PACKAGE_VERSION}-${CMAKE_SYSTEM_NAME}/${CPACK_BUNDLE_NAME}.app/Contents/Resources/SLPlugin.app/Contents/Frameworks/libboost_thread-mt.dylib" + SYMBOLIC + ) +file(CREATE_LINK + "../../../../Frameworks/liburiparser.1.dylib" + "${CMAKE_CACHEFILE_DIR}/_CPack_Packages/${CMAKE_SYSTEM_NAME}/Bundle/${CPACK_BUNDLE_NAME}-${CPACK_PACKAGE_VERSION}-${CMAKE_SYSTEM_NAME}/${CPACK_BUNDLE_NAME}.app/Contents/Resources/SLPlugin.app/Contents/Frameworks/liburiparser.1.dylib" + SYMBOLIC + ) +file(CREATE_LINK + "../../../../Frameworks/libexpat.1.dylib" + "${CMAKE_CACHEFILE_DIR}/_CPack_Packages/${CMAKE_SYSTEM_NAME}/Bundle/${CPACK_BUNDLE_NAME}-${CPACK_PACKAGE_VERSION}-${CMAKE_SYSTEM_NAME}/${CPACK_BUNDLE_NAME}.app/Contents/Resources/SLPlugin.app/Contents/Frameworks/libexpat.1.dylib" + SYMBOLIC + ) +file(CREATE_LINK + "../../../../Frameworks/libfreetype.6.dylib" + "${CMAKE_CACHEFILE_DIR}/_CPack_Packages/${CMAKE_SYSTEM_NAME}/Bundle/${CPACK_BUNDLE_NAME}-${CPACK_PACKAGE_VERSION}-${CMAKE_SYSTEM_NAME}/${CPACK_BUNDLE_NAME}.app/Contents/Resources/SLPlugin.app/Contents/Frameworks/libfreetype.6.dylib" + SYMBOLIC + ) +file(CREATE_LINK + "../../../../Frameworks/libicudata.74.dylib" + "${CMAKE_CACHEFILE_DIR}/_CPack_Packages/${CMAKE_SYSTEM_NAME}/Bundle/${CPACK_BUNDLE_NAME}-${CPACK_PACKAGE_VERSION}-${CMAKE_SYSTEM_NAME}/${CPACK_BUNDLE_NAME}.app/Contents/Resources/SLPlugin.app/Contents/Frameworks/libicudata.74.dylib" + SYMBOLIC + ) +file(CREATE_LINK + "../../../../Frameworks/libicui18n.74.dylib" + "${CMAKE_CACHEFILE_DIR}/_CPack_Packages/${CMAKE_SYSTEM_NAME}/Bundle/${CPACK_BUNDLE_NAME}-${CPACK_PACKAGE_VERSION}-${CMAKE_SYSTEM_NAME}/${CPACK_BUNDLE_NAME}.app/Contents/Resources/SLPlugin.app/Contents/Frameworks/libicui18n.74.dylib" + SYMBOLIC + ) +file(CREATE_LINK + "../../../../Frameworks/libicuuc.74.dylib" + "${CMAKE_CACHEFILE_DIR}/_CPack_Packages/${CMAKE_SYSTEM_NAME}/Bundle/${CPACK_BUNDLE_NAME}-${CPACK_PACKAGE_VERSION}-${CMAKE_SYSTEM_NAME}/${CPACK_BUNDLE_NAME}.app/Contents/Resources/SLPlugin.app/Contents/Frameworks/libicuuc.74.dylib" + SYMBOLIC + ) +file(CREATE_LINK + "../../../../Frameworks/libbz2.1.0.dylib" + "${CMAKE_CACHEFILE_DIR}/_CPack_Packages/${CMAKE_SYSTEM_NAME}/Bundle/${CPACK_BUNDLE_NAME}-${CPACK_PACKAGE_VERSION}-${CMAKE_SYSTEM_NAME}/${CPACK_BUNDLE_NAME}.app/Contents/Resources/SLPlugin.app/Contents/Frameworks/libbz2.1.0.dylib" + SYMBOLIC + ) +file(CREATE_LINK + "../../../../Frameworks/libbrotlidec.1.1.0.dylib" + "${CMAKE_CACHEFILE_DIR}/_CPack_Packages/${CMAKE_SYSTEM_NAME}/Bundle/${CPACK_BUNDLE_NAME}-${CPACK_PACKAGE_VERSION}-${CMAKE_SYSTEM_NAME}/${CPACK_BUNDLE_NAME}.app/Contents/Resources/SLPlugin.app/Contents/Frameworks/libbrotlidec.1.1.0.dylib" + SYMBOLIC + ) +file(CREATE_LINK + "../../../../Frameworks/libbrotlidec.1.dylib" + "${CMAKE_CACHEFILE_DIR}/_CPack_Packages/${CMAKE_SYSTEM_NAME}/Bundle/${CPACK_BUNDLE_NAME}-${CPACK_PACKAGE_VERSION}-${CMAKE_SYSTEM_NAME}/${CPACK_BUNDLE_NAME}.app/Contents/Resources/SLPlugin.app/Contents/Frameworks/libbrotlidec.1.dylib" + SYMBOLIC + ) +file(CREATE_LINK + "../../../../Frameworks/libbrotlicommon.1.dylib" + "${CMAKE_CACHEFILE_DIR}/_CPack_Packages/${CMAKE_SYSTEM_NAME}/Bundle/${CPACK_BUNDLE_NAME}-${CPACK_PACKAGE_VERSION}-${CMAKE_SYSTEM_NAME}/${CPACK_BUNDLE_NAME}.app/Contents/Resources/SLPlugin.app/Contents/Frameworks/libbrotlicommon.1.dylib" + SYMBOLIC + ) +file(CREATE_LINK + "../../../../Frameworks/Chromium Embedded Framework.framework" + "${CMAKE_CACHEFILE_DIR}/_CPack_Packages/${CMAKE_SYSTEM_NAME}/Bundle/${CPACK_BUNDLE_NAME}-${CPACK_PACKAGE_VERSION}-${CMAKE_SYSTEM_NAME}/${CPACK_BUNDLE_NAME}.app/Contents/Resources/SLPlugin.app/Contents/Frameworks/Chromium Embedded Framework.framework" + SYMBOLIC + ) + +file(CHMOD + "${CMAKE_CACHEFILE_DIR}/_CPack_Packages/${CMAKE_SYSTEM_NAME}/Bundle/${CPACK_BUNDLE_NAME}-${CPACK_PACKAGE_VERSION}-${CMAKE_SYSTEM_NAME}/${CPACK_BUNDLE_NAME}.app/Contents/Resources/SLPlugin.app/Contents/Frameworks/DullahanHelper.app/Contents/MacOS/DullahanHelper" + "${CMAKE_CACHEFILE_DIR}/_CPack_Packages/${CMAKE_SYSTEM_NAME}/Bundle/${CPACK_BUNDLE_NAME}-${CPACK_PACKAGE_VERSION}-${CMAKE_SYSTEM_NAME}/${CPACK_BUNDLE_NAME}.app/Contents/Resources/SLPlugin.app/Contents/Frameworks/DullahanHelper (GPU).app/Contents/MacOS/DullahanHelper (GPU)" + "${CMAKE_CACHEFILE_DIR}/_CPack_Packages/${CMAKE_SYSTEM_NAME}/Bundle/${CPACK_BUNDLE_NAME}-${CPACK_PACKAGE_VERSION}-${CMAKE_SYSTEM_NAME}/${CPACK_BUNDLE_NAME}.app/Contents/Resources/SLPlugin.app/Contents/Frameworks/DullahanHelper (Plugin).app/Contents/MacOS/DullahanHelper (Plugin)" + "${CMAKE_CACHEFILE_DIR}/_CPack_Packages/${CMAKE_SYSTEM_NAME}/Bundle/${CPACK_BUNDLE_NAME}-${CPACK_PACKAGE_VERSION}-${CMAKE_SYSTEM_NAME}/${CPACK_BUNDLE_NAME}.app/Contents/Resources/SLPlugin.app/Contents/Frameworks/DullahanHelper (Renderer).app/Contents/MacOS/DullahanHelper (Renderer)" + PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE + ) diff --git a/indra/newview/Info-SecondLife.plist b/indra/newview/Info-SecondLife.plist index 09b0e1ec1b..82f63519db 100644 --- a/indra/newview/Info-SecondLife.plist +++ b/indra/newview/Info-SecondLife.plist @@ -11,7 +11,7 @@ <key>CFBundleIconFile</key> <string>${MACOSX_BUNDLE_ICON_FILE}</string> <key>CFBundleIdentifier</key> - <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> + <string>${MACOSX_BUNDLE_GUI_IDENTIFIER}</string> <key>CFBundleInfoDictionaryVersion</key> <string>6.0</string> <key>CFBundleLongVersionString</key> @@ -34,6 +34,10 @@ <string>${MACOSX_BUNDLE_COPYRIGHT}</string> <key>NSMicrophoneUsageDescription</key> <string>For voice chat, you must grant permission for Second Life to use the microphone.</string> + <key>LSApplicationCategoryType</key> + <string>public.app-category.games</string> + <key>NSHighResolutionCapable</key> + <true/> <key>CFBundleDocumentTypes</key> <array> <dict> diff --git a/indra/newview/SecondLife.nib b/indra/newview/SecondLife.nib Binary files differindex c4ddca50dc..ef0fa80b12 100644 --- a/indra/newview/SecondLife.nib +++ b/indra/newview/SecondLife.nib diff --git a/indra/newview/SecondLife.xib b/indra/newview/SecondLife.xib index fbff8fe307..8302392f5d 100644 --- a/indra/newview/SecondLife.xib +++ b/indra/newview/SecondLife.xib @@ -42,7 +42,7 @@ <array class="NSMutableArray" key="NSMenuItems"> <object class="NSMenuItem" id="694149608"> <reference key="NSMenu" ref="649796088"/> - <string key="NSTitle">Second Life</string> + <string key="NSTitle">Megapahit</string> <string key="NSKeyEquiv"/> <int key="NSMnemonicLoc">2147483647</int> <object class="NSCustomResource" key="NSOnImage" id="353210768"> @@ -55,11 +55,11 @@ </object> <string key="NSAction">submenuAction:</string> <object class="NSMenu" key="NSSubmenu" id="110575045"> - <string key="NSTitle">Second Life</string> + <string key="NSTitle">Megapahit</string> <array class="NSMutableArray" key="NSMenuItems"> <object class="NSMenuItem" id="238522557"> <reference key="NSMenu" ref="110575045"/> - <string key="NSTitle">About Second Life</string> + <string key="NSTitle">About Megapahit</string> <string key="NSKeyEquiv"/> <int key="NSMnemonicLoc">2147483647</int> <reference key="NSOnImage" ref="353210768"/> @@ -120,7 +120,7 @@ </object> <object class="NSMenuItem" id="755159360"> <reference key="NSMenu" ref="110575045"/> - <string key="NSTitle">Hide Second Life</string> + <string key="NSTitle">Hide Megapahit</string> <string key="NSKeyEquiv">h</string> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> @@ -156,7 +156,7 @@ </object> <object class="NSMenuItem" id="632727374"> <reference key="NSMenu" ref="110575045"/> - <string key="NSTitle">Quit Second Life</string> + <string key="NSTitle">Quit Megapahit</string> <string key="NSKeyEquiv">q</string> <int key="NSKeyEquivModMask">1048576</int> <int key="NSMnemonicLoc">2147483647</int> @@ -323,7 +323,7 @@ <int key="NSWindowBacking">2</int> <string key="NSWindowRect">{{196, 240}, {1024, 600}}</string> <int key="NSWTFlags">74974208</int> - <string key="NSWindowTitle">Second Life</string> + <string key="NSWindowTitle">Megapahit</string> <string key="NSWindowClass">LLNSWindow</string> <nil key="NSViewClass"/> <nil key="NSUserInterfaceItemIdentifier"/> @@ -338,7 +338,7 @@ </object> <string key="NSScreenRect">{{0, 0}, {2560, 1418}}</string> <string key="NSMaxSize">{10000000000000, 10000000000000}</string> - <string key="NSFrameAutosaveName">Second Life</string> + <string key="NSFrameAutosaveName">Megapahit</string> <int key="NSWindowCollectionBehavior">128</int> <bool key="NSWindowIsRestorable">NO</bool> </object> diff --git a/indra/newview/ViewerInstall.cmake b/indra/newview/ViewerInstall.cmake index ac2247c815..5c4c08dc9d 100644 --- a/indra/newview/ViewerInstall.cmake +++ b/indra/newview/ViewerInstall.cmake @@ -1,28 +1,204 @@ +if (DARWIN) + + install(FILES + ${CMAKE_CURRENT_BINARY_DIR}/InfoPlist.strings + ${CMAKE_CURRENT_SOURCE_DIR}/English.lproj/language.txt + DESTINATION English.lproj + ) + + install(DIRECTORY + German.lproj + Japanese.lproj + Korean.lproj + app_settings + character + cursors_mac + da.lproj + es.lproj + fonts + fr.lproj + uk.lproj + hu.lproj + it.lproj + nl.lproj + pl.lproj + pt.lproj + ru.lproj + skins + tr.lproj + zh-Hans.lproj + DESTINATION . + ) + + install(FILES + SecondLife.nib + ${AUTOBUILD_INSTALL_DIR}/ca-bundle.crt + cube.dae + featuretable_mac.txt + DESTINATION . + ) + + if (NOT PACKAGE) + install(FILES + secondlife.icns + RENAME ${VIEWER_CHANNEL}.icns + DESTINATION . + ) + endif (NOT PACKAGE) + + install(FILES + licenses-mac.txt + RENAME licenses.txt + DESTINATION . + ) + + install(FILES + ${SCRIPTS_DIR}/messages/message_template.msg + ${SCRIPTS_DIR}/../etc/message.xml + ${CMAKE_CURRENT_BINARY_DIR}/contributors.txt + DESTINATION app_settings + ) + + install(DIRECTORY + /Volumes/VLC\ media\ player/VLC.app/Contents/MacOS/plugins + DESTINATION llplugin + ) + + install(FILES + /Volumes/VLC\ media\ player/VLC.app/Contents/MacOS/lib/libvlc.5.dylib + /Volumes/VLC\ media\ player/VLC.app/Contents/MacOS/lib/libvlc.dylib + /Volumes/VLC\ media\ player/VLC.app/Contents/MacOS/lib/libvlccore.9.dylib + /Volumes/VLC\ media\ player/VLC.app/Contents/MacOS/lib/libvlccore.dylib + DESTINATION llplugin/plugins + ) + + install(DIRECTORY + "${AUTOBUILD_INSTALL_DIR}/lib/release/Chromium Embedded Framework.framework" + DESTINATION ../Frameworks + ) + + install(DIRECTORY + "${AUTOBUILD_INSTALL_DIR}/lib/release/DullahanHelper.app" + "${AUTOBUILD_INSTALL_DIR}/lib/release/DullahanHelper (GPU).app" + "${AUTOBUILD_INSTALL_DIR}/lib/release/DullahanHelper (Plugin).app" + "${AUTOBUILD_INSTALL_DIR}/lib/release/DullahanHelper (Renderer).app" + DESTINATION SLPlugin.app/Contents/Frameworks + ) + + if (NDOF) + install(FILES + "${AUTOBUILD_INSTALL_DIR}/lib/release/libndofdev.dylib" + DESTINATION . + ) + endif () + + if (PACKAGE) + configure_file( + ${CMAKE_CURRENT_SOURCE_DIR}/FixPackage.cmake.in + ${CMAKE_CURRENT_BINARY_DIR}/FixBundle.cmake + ) + else (PACKAGE) + configure_file( + ${CMAKE_CURRENT_SOURCE_DIR}/FixBundle.cmake.in + ${CMAKE_CURRENT_BINARY_DIR}/FixBundle.cmake + ) + endif (PACKAGE) + install(SCRIPT ${CMAKE_CURRENT_BINARY_DIR}/FixBundle.cmake) + +else (DARWIN) + install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/${VIEWER_BINARY_NAME} - DESTINATION ${APP_BINARY_DIR} + DESTINATION bin + ) + +install(PROGRAMS linux_tools/launch_url.sh + DESTINATION libexec/${VIEWER_BINARY_NAME} ) -install(DIRECTORY skins app_settings linux_tools - DESTINATION ${APP_SHARE_DIR} +if (LINUX) + if (EXISTS ${CMAKE_SYSROOT}/usr/lib/${ARCH}-linux-gnu) + set(_LIB lib/${ARCH}-linux-gnu) + elseif (EXISTS /lib64) + set(_LIB lib64) + else () + set(_LIB lib) + endif () + install(FILES + ${AUTOBUILD_INSTALL_DIR}/lib/release/libcef.so + DESTINATION ${_LIB}) + if (USE_FMODSTUDIO) + install(FILES + ${AUTOBUILD_INSTALL_DIR}/lib/release/libfmod.so + ${AUTOBUILD_INSTALL_DIR}/lib/release/libfmod.so.13 + ${AUTOBUILD_INSTALL_DIR}/lib/release/libfmod.so.13.23 + DESTINATION ${_LIB}) + endif (USE_FMODSTUDIO) + install(PROGRAMS + ${AUTOBUILD_INSTALL_DIR}/bin/release/chrome-sandbox + DESTINATION libexec/${VIEWER_BINARY_NAME} + #PERMISSIONS SETUID OWNER_READ OWNER_WRITE OWNER_EXECUTE + #GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE + ) + install(PROGRAMS + ${AUTOBUILD_INSTALL_DIR}/bin/release/dullahan_host + DESTINATION libexec/${VIEWER_BINARY_NAME}) + install(FILES + ${AUTOBUILD_INSTALL_DIR}/bin/release/snapshot_blob.bin + ${AUTOBUILD_INSTALL_DIR}/bin/release/v8_context_snapshot.bin + DESTINATION ${_LIB}) + install(FILES + ${AUTOBUILD_INSTALL_DIR}/resources/chrome_100_percent.pak + ${AUTOBUILD_INSTALL_DIR}/resources/chrome_200_percent.pak + ${AUTOBUILD_INSTALL_DIR}/resources/icudtl.dat + ${AUTOBUILD_INSTALL_DIR}/resources/resources.pak + DESTINATION ${_LIB}) + install(DIRECTORY + ${AUTOBUILD_INSTALL_DIR}/resources/locales + DESTINATION ${_LIB}) +endif (LINUX) + +install(DIRECTORY skins app_settings fonts + DESTINATION share/${VIEWER_BINARY_NAME} PATTERN ".svn" EXCLUDE ) +install(DIRECTORY icons/hicolor + DESTINATION share/icons + ) + find_file(IS_ARTWORK_PRESENT NAMES have_artwork_bundle.marker PATHS ${VIEWER_DIR}/newview/res) if (IS_ARTWORK_PRESENT) install(DIRECTORY res res-sdl character - DESTINATION ${APP_SHARE_DIR} + DESTINATION share/${VIEWER_BINARY_NAME} PATTERN ".svn" EXCLUDE ) else (IS_ARTWORK_PRESENT) message(STATUS "WARNING: Artwork is not present, and will not be installed") endif (IS_ARTWORK_PRESENT) -install(FILES featuretable_linux.txt featuretable_solaris.txt - DESTINATION ${APP_SHARE_DIR} + install(FILES + ${AUTOBUILD_INSTALL_DIR}/ca-bundle.crt + featuretable_linux.txt + #featuretable_solaris.txt + DESTINATION share/${VIEWER_BINARY_NAME} + ) + + install(FILES + licenses-linux.txt + RENAME licenses.txt + DESTINATION share/${VIEWER_BINARY_NAME} ) install(FILES ${SCRIPTS_DIR}/messages/message_template.msg - DESTINATION ${APP_SHARE_DIR}/app_settings + ${SCRIPTS_DIR}/../etc/message.xml + ${CMAKE_CURRENT_BINARY_DIR}/contributors.txt + DESTINATION share/${VIEWER_BINARY_NAME}/app_settings + ) + + install(FILES linux_tools/${VIEWER_BINARY_NAME}.desktop + DESTINATION share/applications ) + +endif (DARWIN) diff --git a/indra/newview/app_settings/camera/Rear.xml b/indra/newview/app_settings/camera/Rear.xml index 7eda566e48..db02001b9c 100644 --- a/indra/newview/app_settings/camera/Rear.xml +++ b/indra/newview/app_settings/camera/Rear.xml @@ -53,8 +53,8 @@ <key>Value</key> <array> <real>-3</real> - <real>0</real> - <real>0.75</real> + <real>0.5</real> + <real>0.2</real> </array> </map> <key>CameraOffsetScale</key> @@ -89,9 +89,9 @@ <string>Vector3D</string> <key>Value</key> <array> - <real>1.0</real> - <real>0.0</real> - <real>1.0</real> + <real>0.9</real> + <real>0.5</real> + <real>0.2</real> </array> </map> <key>PresetCameraActive</key> diff --git a/indra/newview/app_settings/commands.xml b/indra/newview/app_settings/commands.xml index 4a3dfffde1..b47ceff446 100644 --- a/indra/newview/app_settings/commands.xml +++ b/indra/newview/app_settings/commands.xml @@ -46,7 +46,7 @@ available_in_toybox="true" is_flashing_allowed="true" icon="Command_Chat_Icon" - label_ref="Command_Chat_Label" + label_ref="Command_Conversations_Label" tooltip_ref="Command_Conversations_Tooltip" execute_function="Floater.ToggleOrBringToFront" execute_parameters="im_container" diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 50632a7b07..745addd451 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -68,6 +68,17 @@ <key>Value</key> <integer>1</integer> </map> + <key>IMShowArrivalsDepartures</key> + <map> + <key>Comment</key> + <string>Enable(disable) showing of arrivals and departures in the chat.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> <key>CrashHostUrl</key> <map> <key>Comment</key> @@ -1241,8 +1252,8 @@ <key>Value</key> <array> <real>-3.0</real> - <real>0.0</real> - <real>0.75</real> + <real>0.5</real> + <real>0.2</real> </array> </map> <key>CameraOffsetScale</key> @@ -2468,7 +2479,7 @@ <key>Value</key> <integer>0</integer> </map> - <key>DoubleClickTeleport</key> + <key>DoubleClickTeleport</key> <map> <key>Comment</key> <string>Enable double-click to teleport where allowed (afects minimap and people panel)</string> @@ -3056,9 +3067,9 @@ <string>Vector3D</string> <key>Value</key> <array> - <real>1.0</real> - <real>0.0</real> - <real>1.0</real> + <real>0.9</real> + <real>0.5</real> + <real>0.2</real> </array> </map> <key>AvatarSitRotation</key> @@ -4920,6 +4931,17 @@ <key>Value</key> <integer>0</integer> </map> + <key>MediaPluginPipeWireVolumeCatcher</key> + <map> + <key>Comment</key> + <string>Use PipeWire instead of PulseAudio for controlling web media volume.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> <key>MediaControlFadeTime</key> <map> <key>Comment</key> @@ -8698,7 +8720,7 @@ <key>Type</key> <string>Boolean</string> <key>Value</key> - <integer>0</integer> + <integer>1</integer> </map> <key>NameTagShowUsernames</key> <map> @@ -8887,7 +8909,7 @@ <key>Value</key> <integer>1</integer> </map> - + <key>RenderReflectionDetail</key> <map> <key>Comment</key> @@ -8954,7 +8976,7 @@ <key>Value</key> <real>1</real> </map> - + <key>RenderReflectionProbeDrawDistance</key> <map> <key>Comment</key> @@ -9142,7 +9164,7 @@ <key>Value</key> <real>0.7</real> </map> - + <key>RenderReflectionProbeMaxLocalLightAmbiance</key> <map> <key>Comment</key> @@ -9752,7 +9774,7 @@ <key>Type</key> <string>String</string> <key>Value</key> - <string>https://feedback.secondlife.com/</string> + <string>https://megapahit.com/enter_bug.cgi?product=Viewer</string> </map> <key>RevokePermsOnStopAnimation</key> <map> @@ -10302,7 +10324,7 @@ <key>Type</key> <string>Boolean</string> <key>Value</key> - <integer>0</integer> + <integer>1</integer> </map> <key>NavBarShowParcelProperties</key> <map> @@ -10589,7 +10611,7 @@ <string>Boolean</string> <key>Value</key> <integer>0</integer> - </map> + </map> <key>NearbyListShowMap</key> <map> <key>Comment</key> @@ -13532,13 +13554,24 @@ <key>MaxFPS</key> <map> <key>Comment</key> - <string>OBSOLETE UNUSED setting.</string> + <string>FPS Limiter.</string> <key>Persist</key> <integer>1</integer> <key>Type</key> - <string>F32</string> + <string>U32</string> <key>Value</key> - <real>-1.0</real> + <real>0</real> + </map> + <key>MaxFPS</key> + <map> + <key>Comment</key> + <string>FPS Limiter.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>U32</string> + <key>Value</key> + <real>0</real> </map> <key>ZoomDirect</key> <map> @@ -13799,6 +13832,334 @@ <real>12</real> </map> + + <!-- megapahit settings --> + <key>MPVBufferOptiMode</key> + <map> + <key>Comment</key> + <string> + OpenGL buffer mapping mode: + 0:auto + 1:normal + 2:MP optimised + 3:LL optimized.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>U32</string> + <key>Value</key> + <integer>0</integer> + </map> + <key>MPVCameraCollapsed</key> + <map> + <key>Comment</key> + <string> + Camera floater collapsed</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> + <key>MPVNearMeRange</key> + <map> + <key>Comment</key> + <string>Search radius in the people panel</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <integer>4096</integer> + </map> + <key>RenderVSyncEnabled</key> + <map> + <key>Comment</key> + <string>VSync</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> + <key>MemProfiling</key> + <map> + <key>Comment</key> + <string>VSync</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> + <key>FSLastSearchTab</key> + <map> + <key>Comment</key> + <string>Last selected tab in search window</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>S32</string> + <key>Value</key> + <integer>0</integer> + </map> + <key>FSLegacySearchActionOnTeleport</key> + <map> + <key>Comment</key> + <string>Controls what action Legacy Search should take when teleporting: 0 = No effect, + 1 = Close floater, 2 Minimise floater</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>U32</string> + <key>Value</key> + <integer>1</integer> + </map> + <key>ShowPGGroups</key> + <map> + <key>Comment</key> + <string>Controls what action Legacy Search should take when teleporting: 0 = No effect, + 1 = Close floater, 2 Minimise floater</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>U32</string> + <key>Value</key> + <integer>1</integer> + </map> + <key>ShowPGGroups</key> + <map> + <key>Comment</key> + <string>Display results of find groups that are flagged as general</string> + <key>Persist</key> + <integer>1</integer> + <key>HideFromEditor</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> + <key>ShowMatureGroups</key> + <map> + <key>Comment</key> + <string>Display results of find groups that are flagged as moderate</string> + <key>Persist</key> + <integer>1</integer> + <key>HideFromEditor</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> + <key>ShowAdultGroups</key> + <map> + <key>Comment</key> + <string>Display results of find groups that are flagged as adult</string> + <key>Persist</key> + <integer>1</integer> + <key>HideFromEditor</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> + <key>ShowPGClassifieds</key> + <map> + <key>Comment</key> + <string>Display results of find classifieds that are flagged as general</string> + <key>Persist</key> + <integer>1</integer> + <key>HideFromEditor</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> + <key>ShowMatureClassifieds</key> + <map> + <key>Comment</key> + <string>Display results of find classifieds that are flagged as moderate</string> + <key>Persist</key> + <integer>1</integer> + <key>HideFromEditor</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> + <key>ShowAdultClassifieds</key> + <map> + <key>Comment</key> + <string>Display results of find classifieds that are flagged as adult</string> + <key>Persist</key> + <integer>1</integer> + <key>HideFromEditor</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> + <key>ShowPGEvents</key> + <map> + <key>Comment</key> + <string>Display results of find events that are flagged as general</string> + <key>Persist</key> + <integer>1</integer> + <key>HideFromEditor</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> + <key>ShowMatureEvents</key> + <map> + <key>Comment</key> + <string>Display results of find events that are flagged as moderate</string> + <key>Persist</key> + <integer>1</integer> + <key>HideFromEditor</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> + <key>ShowAdultEvents</key> + <map> + <key>Comment</key> + <string>Display results of find events that are flagged as adult</string> + <key>Persist</key> + <integer>1</integer> + <key>HideFromEditor</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> + <key>ShowPGLand</key> + <map> + <key>Comment</key> + <string>Display results of find land sales that are flagged as general</string> + <key>Persist</key> + <integer>1</integer> + <key>HideFromEditor</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> + <key>ShowMatureLand</key> + <map> + <key>Comment</key> + <string>Display results of find land sales that are flagged as moderate</string> + <key>Persist</key> + <integer>1</integer> + <key>HideFromEditor</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> + <key>ShowAdultLand</key> + <map> + <key>Comment</key> + <string>Display results of find land sales that are flagged as adult</string> + <key>Persist</key> + <integer>1</integer> + <key>HideFromEditor</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> + <key>ShowPGSims</key> + <map> + <key>Comment</key> + <string>Display results of find places or find popular that are in general sims</string> + <key>Persist</key> + <integer>1</integer> + <key>HideFromEditor</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> + <key>ShowMatureSims</key> + <map> + <key>Comment</key> + <string>Display results of find places or find popular that are in moderate sims</string> + <key>Persist</key> + <integer>1</integer> + <key>HideFromEditor</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> + <key>ShowAdultSims</key> + <map> + <key>Comment</key> + <string>Display results of find places or find popular that are in adult sims</string> + <key>Persist</key> + <integer>1</integer> + <key>HideFromEditor</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> + <key>FindLandArea</key> + <map> + <key>Comment</key> + <string>Enables filtering of land search results by area</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> + <key>FindLandPrice</key> + <map> + <key>Comment</key> + <string>Enables filtering of land search results by price</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> + <key>FindLandType</key> + <map> + <key>Comment</key> + <string>Controls which type of land you are searching for in Find Land interface ("All", + "Auction", "For Sale")</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>String</string> + <key>Value</key> + <string>All</string> + </map> + <!-- Settings below are for back compatibility only. They are not used in current viewer anymore. But they can't be removed to avoid influence on previous versions of the viewer in case of settings are not used or default value @@ -15659,7 +16020,7 @@ <key>Type</key> <string>Boolean</string> <key>Value</key> - <integer>1</integer> + <integer>1</integer> </map> <key>UpdateAppWindowTitleBar</key> <map> diff --git a/indra/newview/app_settings/shaders/class1/deferred/aoUtil.glsl b/indra/newview/app_settings/shaders/class1/deferred/aoUtil.glsl index ce018623a8..1a065daf89 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/aoUtil.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/aoUtil.glsl @@ -78,10 +78,10 @@ float calcAmbientOcclusion(vec4 pos, vec3 norm, vec2 pos_screen) { float ret = 1.0; vec3 pos_world = pos.xyz; - vec2 noise_reflect = texture(noiseMap, pos_screen.xy * (screen_res / 128)).xy; + vec2 noise_reflect = texture(noiseMap, pos_screen.xy * (screen_res / 128.0)).xy; float angle_hidden = 0.0; - float points = 0; + float points = 0.0; float scale = min(ssao_radius / -pos_world.z, ssao_max_radius); diff --git a/indra/newview/app_settings/shaders/class1/deferred/deferredUtil.glsl b/indra/newview/app_settings/shaders/class1/deferred/deferredUtil.glsl index ab0e4fd4d8..5193a46ac2 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/deferredUtil.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/deferredUtil.glsl @@ -240,7 +240,7 @@ vec4 texture2DLodSpecular(vec2 tc, float lod) vec2 dist = vec2(0.5) - abs(tc-vec2(0.5)); float det = min(lod/(proj_lod*0.5), 1.0); float d = min(dist.x, dist.y); - d *= min(1, d * (proj_lod - lod)); // BUG? extra factor compared to diffuse causes N repeats + d *= min(1.0, d * (proj_lod - lod)); // BUG? extra factor compared to diffuse causes N repeats float edge = 0.25*det; ret *= clamp(d/edge, 0.0, 1.0); @@ -356,7 +356,7 @@ vec3 pbrIbl(vec3 diffuseColor, float perceptualRough) { // retrieve a scale and bias to F0. See [1], Figure 3 - vec2 brdf = BRDF(clamp(nv, 0, 1), 1.0-perceptualRough); + vec2 brdf = BRDF(clamp(nv, 0.0, 1.0), 1.0-perceptualRough); vec3 diffuseLight = irradiance; vec3 specularLight = radiance; @@ -553,7 +553,7 @@ uniform float waterSign; void waterClip(vec3 pos) { // TODO: make this less branchy - if (waterSign > 0) + if (waterSign > 0.0) { if ((dot(pos.xyz, waterPlane.xyz) + waterPlane.w) < 0.0) { diff --git a/indra/newview/app_settings/shaders/class1/deferred/globalF.glsl b/indra/newview/app_settings/shaders/class1/deferred/globalF.glsl index a1b7a4b11f..d493976eba 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/globalF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/globalF.glsl @@ -34,7 +34,7 @@ uniform float clipSign; void mirrorClip(vec3 pos) { - if (mirror_flag > 0) + if (mirror_flag > 0.0) { if ((dot(pos.xyz, clipPlane.xyz) + clipPlane.w) < 0.0) { diff --git a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl index 1ae9efe544..d1a380bf94 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pbrterrainUtilF.glsl @@ -251,7 +251,7 @@ vec3 _t_normal_post_1(vec3 vNt0, float sign_or_zero) sign = (2.0*sign) + 1.0; sign /= abs(sign); // If the sign is negative, rotate normal by 180 degrees - vNt1.xy = (min(0, sign) * vNt1.xy) + (min(0, -sign) * -vNt1.xy); + vNt1.xy = (min(0.0, sign) * vNt1.xy) + (min(0.0, -sign) * -vNt1.xy); return vNt1; } diff --git a/indra/newview/app_settings/shaders/class1/deferred/screenSpaceReflUtil.glsl b/indra/newview/app_settings/shaders/class1/deferred/screenSpaceReflUtil.glsl index e77e972873..6791fe44d9 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/screenSpaceReflUtil.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/screenSpaceReflUtil.glsl @@ -25,7 +25,7 @@ // debug stub -float random (vec2 uv) +float random (vec2 uv) { return 0.f; } diff --git a/indra/newview/app_settings/shaders/class1/effects/glowExtractF.glsl b/indra/newview/app_settings/shaders/class1/effects/glowExtractF.glsl index 72eda80716..bfb592be9b 100644 --- a/indra/newview/app_settings/shaders/class1/effects/glowExtractF.glsl +++ b/indra/newview/app_settings/shaders/class1/effects/glowExtractF.glsl @@ -49,7 +49,7 @@ void main() float warmth = smoothstep(minLuminance, minLuminance+1.0, max(col.r * warmthWeights.r, max(col.g * warmthWeights.g, col.b * warmthWeights.b)) ); #if HAS_NOISE - float TRUE_NOISE_RES = 128; // See mTrueNoiseMap + float TRUE_NOISE_RES = 128.0; // See mTrueNoiseMap // *NOTE: Usually this is vary_fragcoord not vary_texcoord0, but glow extraction is in screen space vec3 glow_noise = texture(glowNoiseMap, vary_texcoord0.xy * (screen_res / TRUE_NOISE_RES)).xyz; // Dithering. Reduces banding effects in the reduced precision glow buffer. diff --git a/indra/newview/app_settings/shaders/class1/interface/gaussianF.glsl b/indra/newview/app_settings/shaders/class1/interface/gaussianF.glsl index 09eb7a6a6a..82f32da048 100644 --- a/indra/newview/app_settings/shaders/class1/interface/gaussianF.glsl +++ b/indra/newview/app_settings/shaders/class1/interface/gaussianF.glsl @@ -45,7 +45,7 @@ void main() for (int i = 0; i < 9; ++i) { - vec2 tc = vary_texcoord0 + (i-4)*direction*resScale; + vec2 tc = vary_texcoord0 + float(i-4)*direction*resScale; col += texture(diffuseRect, tc).rgb * w[i]; } diff --git a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsFuncs.glsl b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsFuncs.glsl index 359bfe8253..af10ecce9a 100644 --- a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsFuncs.glsl +++ b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsFuncs.glsl @@ -98,7 +98,7 @@ void calcAtmosphericVars(vec3 inPositionEye, vec3 light_dir, float ambFactor, ou haze_glow = max(haze_glow, .001); // set a minimum "angle" (smaller glow.y allows tighter, brighter hotspot) haze_glow *= glow.x; // higher glow.x gives dimmer glow (because next step is 1 / "angle") - haze_glow = clamp(pow(haze_glow, glow.z), -100000, 100000); + haze_glow = clamp(pow(haze_glow, glow.z), -100000.0, 100000.0); // glow.z should be negative, so we're doing a sort of (1 / "angle") function // add "minimum anti-solar illumination" diff --git a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsV.glsl b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsV.glsl index 1372ddbcfa..bdc5b58060 100644 --- a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsV.glsl +++ b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsV.glsl @@ -47,7 +47,7 @@ void calcAtmospherics(vec3 inPositionEye) { vec3 tmpaddlit = vec3(1); vec3 tmpattenlit = vec3(1); vec3 light_dir = (sun_up_factor == 1) ? sun_dir : moon_dir; - calcAtmosphericVars(inPositionEye, light_dir, 1, tmpsunlit, tmpamblit, tmpaddlit, tmpattenlit); + calcAtmosphericVars(inPositionEye, light_dir, 1.0, tmpsunlit, tmpamblit, tmpaddlit, tmpattenlit); setSunlitColor(tmpsunlit); setAmblitColor(tmpamblit); setAdditiveColor(tmpaddlit); diff --git a/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl b/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl index 210ecce8db..e9f849a8c0 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl @@ -79,7 +79,7 @@ float getAmbientClamp(); void mirrorClip(vec3 pos); -void sampleReflectionProbesLegacy(inout vec3 ambenv, inout vec3 glossenv, inout vec3 legacyenv, +void sampleReflectionProbesLegacy(out vec3 ambenv, out vec3 glossenv, out vec3 legacyenv, vec2 tc, vec3 pos, vec3 norm, float glossiness, float envIntensity, bool transparent, vec3 amblit_linear); vec3 calcPointLightOrSpotLight(vec3 light_col, vec3 diffuse, vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float fa, float is_pointlight, float ambiance) diff --git a/indra/newview/app_settings/shaders/class2/deferred/reflectionProbeF.glsl b/indra/newview/app_settings/shaders/class2/deferred/reflectionProbeF.glsl index d178bf22b6..35848ff4cd 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/reflectionProbeF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/reflectionProbeF.glsl @@ -37,7 +37,7 @@ void sampleReflectionProbes(inout vec3 ambenv, inout vec3 glossenv, vec2 tc, vec3 pos, vec3 norm, float glossiness, bool transparent, vec3 amblit_linear) { ambenv = vec3(reflection_probe_ambiance * 0.25); - + vec3 refnormpersp = normalize(reflect(pos.xyz, norm.xyz)); vec3 env_vec = env_mat * refnormpersp; glossenv = srgb_to_linear(texture(environmentMap, env_vec).rgb); @@ -55,11 +55,11 @@ vec4 sampleReflectionProbesDebug(vec3 pos) return vec4(0, 0, 0, 0); } -void sampleReflectionProbesLegacy(inout vec3 ambenv, inout vec3 glossenv, inout vec3 legacyenv, +void sampleReflectionProbesLegacy(out vec3 ambenv, out vec3 glossenv, out vec3 legacyenv, vec2 tc, vec3 pos, vec3 norm, float glossiness, float envIntensity, bool transparent, vec3 amblit_linear) { ambenv = vec3(reflection_probe_ambiance * 0.25); - + vec3 refnormpersp = normalize(reflect(pos.xyz, norm.xyz)); vec3 env_vec = env_mat * refnormpersp; @@ -70,7 +70,7 @@ void sampleReflectionProbesLegacy(inout vec3 ambenv, inout vec3 glossenv, inout void applyGlossEnv(inout vec3 color, vec3 glossenv, vec4 spec, vec3 pos, vec3 norm) { - + } void applyLegacyEnv(inout vec3 color, vec3 legacyenv, vec4 spec, vec3 pos, vec3 norm, float envIntensity) diff --git a/indra/newview/app_settings/shaders/class3/deferred/fullbrightShinyF.glsl b/indra/newview/app_settings/shaders/class3/deferred/fullbrightShinyF.glsl index 03dc3d7113..5e38864d38 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/fullbrightShinyF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/fullbrightShinyF.glsl @@ -48,7 +48,7 @@ vec3 linear_to_srgb(vec3 c); vec3 srgb_to_linear(vec3 c); // reflection probe interface -void sampleReflectionProbesLegacy(inout vec3 ambenv, inout vec3 glossenv, inout vec3 legacyenv, +void sampleReflectionProbesLegacy(out vec3 ambenv, out vec3 glossenv, out vec3 legacyenv, vec2 tc, vec3 pos, vec3 norm, float glossiness, float envIntensity, bool transparent, vec3 amblit_linear); void applyLegacyEnv(inout vec3 color, vec3 legacyenv, vec4 spec, vec3 pos, vec3 norm, float envIntensity); diff --git a/indra/newview/app_settings/shaders/class3/deferred/materialF.glsl b/indra/newview/app_settings/shaders/class3/deferred/materialF.glsl index 26ab0406f6..5ee9aea09d 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/materialF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/materialF.glsl @@ -60,7 +60,7 @@ out vec4 frag_color; float sampleDirectionalShadow(vec3 pos, vec3 norm, vec2 pos_screen); #endif -void sampleReflectionProbesLegacy(inout vec3 ambenv, inout vec3 glossenv, inout vec3 legacyenv, +void sampleReflectionProbesLegacy(out vec3 ambenv, out vec3 glossenv, out vec3 legacyenv, vec2 tc, vec3 pos, vec3 norm, float glossiness, float envIntensity, bool transparent, vec3 amblit_linear); void applyGlossEnv(inout vec3 color, vec3 glossenv, vec4 spec, vec3 pos, vec3 norm); void applyLegacyEnv(inout vec3 color, vec3 legacyenv, vec4 spec, vec3 pos, vec3 norm, float envIntensity); @@ -280,10 +280,10 @@ float getShadow(vec3 pos, vec3 norm) #if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND) return sampleDirectionalShadow(pos, norm, vary_texcoord0.xy); #else - return 1; + return 1.; #endif #else - return 1; + return 1.; #endif } diff --git a/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl b/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl index 5dfa196cf6..4bae7b6deb 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl @@ -837,7 +837,7 @@ vec4 sampleReflectionProbesDebug(vec3 pos) return col; } -void sampleReflectionProbesLegacy(inout vec3 ambenv, inout vec3 glossenv, inout vec3 legacyenv, +void sampleReflectionProbesLegacy(out vec3 ambenv, out vec3 glossenv, out vec3 legacyenv, vec2 tc, vec3 pos, vec3 norm, float glossiness, float envIntensity, bool transparent, vec3 amblit) { float reflection_lods = max_probe_lod; diff --git a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl index ca88fe7482..4231d8580e 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl @@ -69,7 +69,7 @@ vec3 scaleSoftClipFragLinear(vec3 l); // reflection probe interface void sampleReflectionProbes(inout vec3 ambenv, inout vec3 glossenv, vec2 tc, vec3 pos, vec3 norm, float glossiness, bool transparent, vec3 amblit_linear); -void sampleReflectionProbesLegacy(inout vec3 ambenv, inout vec3 glossenv, inout vec3 legacyenv, +void sampleReflectionProbesLegacy(out vec3 ambenv, out vec3 glossenv, out vec3 legacyenv, vec2 tc, vec3 pos, vec3 norm, float glossiness, float envIntensity, bool transparent, vec3 amblit_linear); void applyGlossEnv(inout vec3 color, vec3 glossenv, vec4 spec, vec3 pos, vec3 norm); void applyLegacyEnv(inout vec3 color, vec3 legacyenv, vec4 spec, vec3 pos, vec3 norm, float envIntensity); diff --git a/indra/newview/app_settings/shaders/class3/environment/waterF.glsl b/indra/newview/app_settings/shaders/class3/environment/waterF.glsl index a5592188a9..03da5b020f 100644 --- a/indra/newview/app_settings/shaders/class3/environment/waterF.glsl +++ b/indra/newview/app_settings/shaders/class3/environment/waterF.glsl @@ -145,7 +145,7 @@ void main() //get wave normals vec2 bigwave = vec2(refCoord.w, view.w); - vec3 wave1_a = texture(bumpMap, bigwave, -2 ).xyz*2.0-1.0; + vec3 wave1_a = texture(bumpMap, bigwave, -2.0 ).xyz*2.0-1.0; vec3 wave2_a = texture(bumpMap, littleWave.xy).xyz*2.0-1.0; vec3 wave3_a = texture(bumpMap, littleWave.zw).xyz*2.0-1.0; @@ -167,10 +167,10 @@ void main() vec3 wavef = (wave1 + wave2 * 0.4 + wave3 * 0.6) * 0.5; - vec3 waver = wavef*3; + vec3 waver = wavef*3.0; vec3 up = transform_normal(vec3(0,0,1)); - float vdu = -dot(viewVec, up)*2; + float vdu = -dot(viewVec, up)*2.0; vec3 wave_ibl = wavef; wave_ibl.z *= 2.0; @@ -178,7 +178,7 @@ void main() vec3 norm = transform_normal(normalize(wavef)); - vdu = clamp(vdu, 0, 1); + vdu = clamp(vdu, 0.0, 1.0); wavef.z *= max(vdu*vdu*vdu, 0.1); wavef = normalize(wavef); @@ -266,7 +266,7 @@ void main() color += ibl; float nv = clamp(abs(dot(norm.xyz, v)), 0.001, 1.0); - vec2 brdf = BRDF(clamp(nv, 0, 1), 1.0); + vec2 brdf = BRDF(clamp(nv, 0.0, 1.0), 1.0); float f = 1.0-brdf.y; //1.0 - (brdf.x+brdf.y); f *= 0.9; f *= f; @@ -279,7 +279,7 @@ void main() // shift from -1 to 1 f += (fresnelOffset - 0.5) * 2.0; - f = clamp(f, 0, 1); + f = clamp(f, 0.0, 1.0); color = ((1.0 - f) * color) + fb.rgb; diff --git a/indra/newview/app_settings/toolbars.xml b/indra/newview/app_settings/toolbars.xml index a1c9d6d9ee..cd900b6c60 100644 --- a/indra/newview/app_settings/toolbars.xml +++ b/indra/newview/app_settings/toolbars.xml @@ -4,27 +4,24 @@ button_display_mode="icons_with_text"> <command name="chat"/> <command name="speak"/> - <command name="destinations"/> <command name="people"/> <command name="profile"/> - <command name="map"/> - <command name="move"/> <command name="view"/> - <command name="howto"/> + <command name="appearance"/> + <command name="inventory"/> </bottom_toolbar> <left_toolbar button_display_mode="icons_only"> - <command name="avatar"/> - <command name="appearance"/> - <command name="inventory"/> <command name="search"/> - <command name="places"/> - <command name="voice"/> + <command name="map"/> + <command name="build"/> <command name="minimap"/> <command name="snapshot"/> - <command name="performance"/> + <command name="aboutland"/> </left_toolbar> <right_toolbar button_display_mode="icons_only"> + <command name="performance"/> + <command name="howto"/> </right_toolbar> </toolbars> diff --git a/indra/newview/character/attentions.xml b/indra/newview/character/attentions.xml index be9a2b28fc..9bda3309ac 100644 --- a/indra/newview/character/attentions.xml +++ b/indra/newview/character/attentions.xml @@ -33,7 +33,7 @@ MOUSELOOK: Tracks center of view when in mouselook view mode. <param attention="hover" priority="4.0" timeout="1.0" /> <param attention="conversation" priority="0.0" timeout="-1" /> <param attention="select" priority="6.0" timeout="-1" /> - <param attention="focus" priority="6.0" timeout="-1" /> + <param attention="focus" priority="0.0" timeout="-1" /> <param attention="mouselook" priority="7.0" timeout="-1" /> </gender> <gender name="Feminine"> @@ -44,7 +44,7 @@ MOUSELOOK: Tracks center of view when in mouselook view mode. <param attention="hover" priority="4.0" timeout="1.0" /> <param attention="conversation" priority="0.0" timeout="-1" /> <param attention="select" priority="6.0" timeout="-1" /> - <param attention="focus" priority="6.0" timeout="-1" /> + <param attention="focus" priority="0.0" timeout="-1" /> <param attention="mouselook" priority="7.0" timeout="-1" /> </gender> </linden_attentions> diff --git a/indra/newview/featuretable_mac.txt b/indra/newview/featuretable_mac.txt index 2ecbf311ca..42a85a347d 100644 --- a/indra/newview/featuretable_mac.txt +++ b/indra/newview/featuretable_mac.txt @@ -81,26 +81,27 @@ RenderMirrors 1 1 // list Low RenderAnisotropic 1 0 -RenderAvatarLODFactor 1 0 -RenderAvatarPhysicsLODFactor 1 0 +RenderAvatarLODFactor 1 0.5 +RenderAvatarMaxComplexity 1 35000 +RenderAvatarPhysicsLODFactor 1 0.5 RenderAvatarMaxNonImpostors 1 3 -RenderAvatarMaxComplexity 1 35000 RenderFarClip 1 64 -RenderFlexTimeFactor 1 0 +RenderFlexTimeFactor 1 1.0 RenderGlowResolutionPow 1 8 -RenderLocalLightCount 1 8 -RenderMaxPartCount 1 0 -RenderTerrainDetail 1 0 -RenderTerrainLODFactor 1 1 -RenderTerrainPBRDetail 1 -4 +RenderMaxPartCount 1 512 +RenderLocalLightCount 1 256 +RenderTerrainDetail 1 1 +RenderTerrainLODFactor 1 1.0 +RenderTerrainPBRDetail 1 -1 RenderTerrainPBRPlanarSampleCount 1 1 -RenderTransparentWater 1 0 -RenderTreeLODFactor 1 0 +RenderTransparentWater 1 1 +RenderTreeLODFactor 1 0.5 RenderVolumeLODFactor 1 1.125 RenderDeferredSSAO 1 0 RenderUseAdvancedAtmospherics 1 0 RenderShadowDetail 1 0 -WLSkyDetail 1 96 +WLSkyDetail 1 64 +RenderTransparentWater 1 0 RenderFSAASamples 1 0 RenderReflectionsEnabled 1 1 RenderReflectionProbeDetail 1 0 @@ -112,6 +113,7 @@ RenderHeroProbeDistance 1 4 RenderHeroProbeUpdateRate 1 6 RenderHeroProbeConservativeUpdateMultiplier 1 16 + // // Medium Low Graphics Settings // diff --git a/indra/newview/fsfloatersearch.cpp b/indra/newview/fsfloatersearch.cpp new file mode 100644 index 0000000000..7e0a873452 --- /dev/null +++ b/indra/newview/fsfloatersearch.cpp @@ -0,0 +1,3212 @@ +/** + * @file fsfloatersearch.cpp + * @brief Firestorm Search Floater + * + * $LicenseInfo:firstyear=2012&license=fsviewerlgpl$ + * Phoenix Firestorm Viewer Source Code + * Copyright (C) 2012, Cinder Roxley <cinder.roxley@phoenixviewer.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * The Phoenix Firestorm Project, Inc., 1831 Oakwood Drive, Fairmont, Minnesota 56031-3225 USA + * http://www.firestormviewer.org + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "fsfloatersearch.h" + +#include "lldispatcher.h" +#include "llagent.h" +#include "llavataractions.h" +#include "llavatarname.h" +#include "llavatarnamecache.h" +#include "llavatarpropertiesprocessor.h" +#include "llclassifiedflags.h" +#include "llclassifiedinfo.h" +#include "llcombobox.h" +#include "lldateutil.h" +#include "lleventflags.h" +#include "lleventnotifier.h" +#include "llfloaterreg.h" +#include "llfloaterworldmap.h" +#include "llgroupactions.h" +#include "llgroupmgr.h" +#include "llloadingindicator.h" +#include "lllogininstance.h" +#include "llnotificationsutil.h" +#include "llpanelprofile.h" +#include "llpanelprofileclassifieds.h" +#include "llparcel.h" +#include "llproductinforequest.h" +#include "llqueryflags.h" +#include "llregionhandle.h" +#include "llremoteparcelrequest.h" +#include "lltimer.h" +#include "lltrans.h" +#include "llviewercontrol.h" +#include "llviewergenericmessage.h" +#include "llviewernetwork.h" +#include "llviewerregion.h" +#include "llworldmapmessage.h" +#include "message.h" +#include <boost/tokenizer.hpp> +#include <boost/algorithm/string.hpp> +#include <string> + +#include <chrono> + +static const S32 MIN_SEARCH_STRING_SIZE = 2; +static const S32 RESULT_PAGE_SIZE = 100; + +// (observeur) Hack to avoid Find to be called several times (due to a bug in llsearchcombobox) +static std::chrono::time_point<std::chrono::system_clock> lastRequestTime; +static const S32 REQUEST_MIN_ELAPSED_TIME = 500; + +std::string filterShortWords(std::string query_string); +void fillSearchComboBox(LLSearchComboBox* search_combo); + +//////////////////////////////////////// +// Observer Classes // +//////////////////////////////////////// + +class FSSearchRemoteParcelInfoObserver : public LLRemoteParcelInfoObserver +{ +public: + FSSearchRemoteParcelInfoObserver(FSFloaterSearch* floater, bool for_events) : LLRemoteParcelInfoObserver(), + mParent(floater), + mForEvents(for_events) + {} + + ~FSSearchRemoteParcelInfoObserver() + { + // remove any in-flight observers + std::set<LLUUID>::iterator it; + for (it = mParcelIDs.begin(); it != mParcelIDs.end(); ++it) + { + const LLUUID &id = *it; + LLRemoteParcelInfoProcessor::getInstance()->removeObserver(id, this); + } + mParcelIDs.clear(); + } + + /*virtual*/ void processParcelInfo(const LLParcelData& parcel_data) + { + if (mParent) + { + if (mForEvents) + { + mParent->displayEventParcelImage(parcel_data); + } + else + { + mParent->displayParcelDetails(parcel_data); + } + } + mParcelIDs.erase(parcel_data.parcel_id); + LLRemoteParcelInfoProcessor::getInstance()->removeObserver(parcel_data.parcel_id, this); + } + + /*virtual*/ void setParcelID(const LLUUID& parcel_id) + { + if (!parcel_id.isNull()) + { + mParcelIDs.insert(parcel_id); + LLRemoteParcelInfoProcessor::getInstance()->addObserver(parcel_id, this); + LLRemoteParcelInfoProcessor::getInstance()->sendParcelInfoRequest(parcel_id); + } + } + + /*virtual*/ void setErrorStatus(S32 status, const std::string& reason) + { + LL_WARNS("Search") << "Can't complete remote parcel request. Http Status: " << status << ". Reason : " << reason << LL_ENDL; + } +private: + std::set<LLUUID> mParcelIDs; + FSFloaterSearch* mParent; + bool mForEvents; +}; + +///// Avatar Properties Observer ///// + +class FSSearchAvatarPropertiesObserver : public LLAvatarPropertiesObserver +{ +public: + FSSearchAvatarPropertiesObserver(FSFloaterSearch* floater) : LLAvatarPropertiesObserver(), + mParent(floater) + {} + + ~FSSearchAvatarPropertiesObserver() + { + // remove any in-flight observers + std::set<LLUUID>::iterator it; + for (it = mAvatarIDs.begin(); it != mAvatarIDs.end(); ++it) + { + const LLUUID &id = *it; + LLAvatarPropertiesProcessor::getInstance()->removeObserver(id, this); + } + mAvatarIDs.clear(); + } + + void processProperties(void* data, EAvatarProcessorType type) + { + if (!data) + return; + + if (APT_PROPERTIES == type) + { + LLAvatarData* avatar_data = static_cast<LLAvatarData*>(data); + if (avatar_data) + { + mParent->displayAvatarDetails(avatar_data); + LLAvatarPropertiesProcessor::getInstance()->removeObserver(avatar_data->avatar_id, this); + } + } + else if (APT_PROPERTIES_LEGACY == type) + { + LLAvatarData avatar_data(*static_cast<LLAvatarLegacyData*>(data)); + mParent->displayAvatarDetails(&avatar_data); + LLAvatarPropertiesProcessor::getInstance()->removeObserver(avatar_data.avatar_id, this); + } + if (APT_CLASSIFIED_INFO == type) + { + LLAvatarClassifiedInfo* c_info = static_cast<LLAvatarClassifiedInfo*>(data); + if (c_info) + { + mParent->displayClassifiedDetails(c_info); + LLAvatarPropertiesProcessor::getInstance()->removeObserver(c_info->classified_id, this); + std::string url = gAgent.getRegionCapability("SearchStatRequest"); + if (!url.empty()) + { + LL_INFOS("Search") << "Classified stat request via capability" << LL_ENDL; + LLSD body; + body["classified_id"] = c_info->classified_id; + LLCoreHttpUtil::HttpCoroutineAdapter::callbackHttpPost(url, body, boost::bind(&LLPanelProfileClassified::handleSearchStatResponse, c_info->classified_id, _1)); + } + } + } + } +private: + std::set<LLUUID> mAvatarIDs; + FSFloaterSearch* mParent; +}; + +///// Group Info Observer ///// + +class FSSearchGroupInfoObserver : public LLGroupMgrObserver +{ +public: + FSSearchGroupInfoObserver(const LLUUID& group_id, FSFloaterSearch* parent) : + LLGroupMgrObserver(group_id), + mParent(parent) + { + LLGroupMgr* groupmgr = LLGroupMgr::getInstance(); + if (!group_id.isNull() && groupmgr) + { + groupmgr->addObserver(this); + mID = group_id; + groupmgr->sendGroupPropertiesRequest(group_id); + } + } + + ~FSSearchGroupInfoObserver() + { + LLGroupMgr::getInstance()->removeObserver(this); + } + + void changed(LLGroupChange gc) + { + if (gc == GC_PROPERTIES) + { + LLGroupMgrGroupData* group_data = LLGroupMgr::getInstance()->getGroupData(mID); + mParent->displayGroupDetails(group_data); + LLGroupMgr::getInstance()->removeObserver(this); + } + } +private: + FSFloaterSearch* mParent; + LLUUID mID; +}; + +///// Silly Classified Clickthrough Class ///// +class FSDispatchClassifiedClickThrough : public LLDispatchHandler +{ +public: + virtual bool operator()( + const LLDispatcher* dispatcher, + const std::string& key, + const LLUUID& invoice, + const sparam_t& strings) + { + if (strings.size() != 4) return false; + LLUUID classified_id(strings[0]); + S32 teleport_clicks = atoi(strings[1].c_str()); + S32 map_clicks = atoi(strings[2].c_str()); + S32 profile_clicks = atoi(strings[3].c_str()); + + LLPanelProfileClassified::setClickThrough( + classified_id, teleport_clicks, map_clicks, profile_clicks, false); + + return true; + } +}; +static FSDispatchClassifiedClickThrough sClassifiedClickThrough; + +SearchQuery::SearchQuery() +: category("category", "") +, query("query") +{} + +//////////////////////////////////////// +// The floater itself // +//////////////////////////////////////// + +FSFloaterSearch::FSFloaterSearch(const Params& key) +: LLFloater(key) +{ + mRemoteParcelObserver = new FSSearchRemoteParcelInfoObserver(this, false); + mRemoteParcelEventLocationObserver = new FSSearchRemoteParcelInfoObserver(this, true); + mAvatarPropertiesObserver = new FSSearchAvatarPropertiesObserver(this); + mEventNotifierConnection = gEventNotifier.setNewEventCallback(boost::bind(&FSFloaterSearch::displayEventDetails, this, boost::placeholders::_1)); +} + +FSFloaterSearch::~FSFloaterSearch() +{ + mEventNotifierConnection.disconnect(); + delete mRemoteParcelObserver; + delete mRemoteParcelEventLocationObserver; + delete mAvatarPropertiesObserver; + gGenericDispatcher.addHandler("classifiedclickthrough", nullptr); +} + +// virtual +void FSFloaterSearch::onOpen(const LLSD& key) +{ + Params p(key); + mPanelWeb->loadURL(p.search); + if (key.has("query")) + { + mTabContainer->selectTabPanel(mPanelWeb); + } + else if (key.has("tab") && key["tab"].asString() == "groups") + { + mTabContainer->selectTabPanel(mPanelGroups); + } + + FSSearchPanelBase* current_panel = dynamic_cast<FSSearchPanelBase*>(mTabContainer->getCurrentPanel()); + if (current_panel) + { + current_panel->focusDefaultElement(); + } +} + +//virtual +void FSFloaterSearch::onClose(bool app_quitting) +{ + if (mTabContainer) + { + gSavedSettings.setS32("FSLastSearchTab", mTabContainer->getCurrentPanelIndex()); + } +} + +bool FSFloaterSearch::postBuild() +{ + childSetAction("people_profile_btn", boost::bind(&FSFloaterSearch::onBtnPeopleProfile, this)); + childSetAction("people_message_btn", boost::bind(&FSFloaterSearch::onBtnPeopleIM, this)); + childSetAction("people_friend_btn", boost::bind(&FSFloaterSearch::onBtnPeopleFriend, this)); + childSetAction("group_profile_btn", boost::bind(&FSFloaterSearch::onBtnGroupProfile, this)); + childSetAction("group_message_btn", boost::bind(&FSFloaterSearch::onBtnGroupChat, this)); + childSetAction("group_join_btn", boost::bind(&FSFloaterSearch::onBtnGroupJoin, this)); + childSetAction("event_reminder_btn", boost::bind(&FSFloaterSearch::onBtnEventReminder, this)); + childSetAction("teleport_btn", boost::bind(&FSFloaterSearch::onBtnTeleport, this)); + childSetAction("map_btn", boost::bind(&FSFloaterSearch::onBtnMap, this)); + resetVerbs(); + + mPanelPeople = findChild<FSPanelSearchPeople>("panel_ls_people"); + mPanelGroups = findChild<FSPanelSearchGroups>("panel_ls_groups"); + mPanelPlaces = findChild<FSPanelSearchPlaces>("panel_ls_places"); + mPanelEvents = findChild<FSPanelSearchEvents>("panel_ls_events"); + mPanelLand = findChild<FSPanelSearchLand>("panel_ls_land"); + mPanelClassifieds = findChild<FSPanelSearchClassifieds>("panel_ls_classifieds"); + mPanelWeb = findChild<FSPanelSearchWeb>("panel_ls_web"); + + mDetailsPanel = getChild<LLPanel>("panel_ls_details"); + mDetailTitle = getChild<LLTextEditor>("title"); + mDetailDesc = getChild<LLTextEditor>("desc"); + mDetailAux1 = getChild<LLTextEditor>("aux1"); + mDetailAux2 = getChild<LLTextEditor>("aux2"); + mDetailLocation = getChild<LLTextEditor>("location"); + mDetailSnapshot = getChild<LLTextureCtrl>("snapshot"); + mDetailSnapshotParcel = getChild<LLTextureCtrl>("snapshot_parcel"); + mDetailMaturity = getChild<LLIconCtrl>("maturity_icon"); + mTabContainer = getChild<LLTabContainer>("ls_tabs"); + + mTabContainer->setCommitCallback(boost::bind(&FSFloaterSearch::onTabChange, this)); + + flushDetails(); + + mDetailsPanel->setVisible(false); + + mHasSelection = false; + + if (!mTabContainer->selectTab(gSavedSettings.getS32("FSLastSearchTab"))) + { + mTabContainer->selectFirstTab(); + } + + return TRUE; +} + +void FSFloaterSearch::onTabChange() +{ + LL_INFOS() << "onTabChange()()" << LL_ENDL; + + flushDetails(); + + LLPanel* active_panel = mTabContainer->getCurrentPanel(); + + if (active_panel == mPanelWeb) + { + mDetailsPanel->setVisible(false); + mPanelWeb->resetFocusOnLoad(); + } + else if (active_panel == mPanelPeople) + { + mDetailsPanel->setVisible(mHasSelection); + } + + if (active_panel == mPanelPeople || active_panel == mPanelGroups) + { + mDetailSnapshotParcel->setVisible(FALSE); + mDetailSnapshot->setVisible(TRUE); + } + else if (active_panel == mPanelPlaces || active_panel == mPanelLand || + active_panel == mPanelEvents || active_panel == mPanelClassifieds) + { + mDetailSnapshot->setVisible(FALSE); + mDetailSnapshotParcel->setVisible(TRUE); + } +} + +//static +template <class T> +T* FSFloaterSearch::getSearchPanel(const std::string& panel_name) +{ + FSFloaterSearch* search_instance = LLFloaterReg::findTypedInstance<FSFloaterSearch>("search"); + if (search_instance && search_instance->mTabContainer) + { + return dynamic_cast<T*>(search_instance->mTabContainer->getPanelByName(panel_name)); + } + else + { + return nullptr; + } +} + +void FSFloaterSearch::onSelectedItem(const LLUUID& selected_item, ESearchCategory type) +{ + LL_INFOS() << "onSelectedItem()" << LL_ENDL; + + if (!selected_item.isNull()) + { + mSelectedID = selected_item; + resetVerbs(); + flushDetails(); + switch (type) + { + case SC_AVATAR: + { + LLAvatarPropertiesProcessor::getInstance()->addObserver(selected_item, mAvatarPropertiesObserver); + LLAvatarPropertiesProcessor::getInstance()->sendAvatarPropertiesRequest(selected_item); + } + break; + case SC_GROUP: + mGroupPropertiesRequest = new FSSearchGroupInfoObserver(selected_item, this); + break; + case SC_PLACE: + mRemoteParcelObserver->setParcelID(selected_item); + break; + case SC_CLASSIFIED: + LLAvatarPropertiesProcessor::getInstance()->addObserver(selected_item, mAvatarPropertiesObserver); + LLAvatarPropertiesProcessor::getInstance()->sendClassifiedInfoRequest(selected_item); + gGenericDispatcher.addHandler("classifiedclickthrough", &sClassifiedClickThrough); + break; + } + setLoadingProgress(true); + } +} + +void FSFloaterSearch::onSelectedEvent(const S32 selected_event) +{ + LL_INFOS() << "onSelectedEvent()()" << LL_ENDL; + + resetVerbs(); + flushDetails(); + + gMessageSystem->newMessageFast(_PREHASH_EventInfoRequest); + gMessageSystem->nextBlockFast(_PREHASH_AgentData); + gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgentID); + gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgentSessionID); + gMessageSystem->nextBlockFast(_PREHASH_EventData); + gMessageSystem->addU32Fast(_PREHASH_EventID, selected_event); + gAgent.sendReliableMessage(); +} + +void FSFloaterSearch::displayParcelDetails(const LLParcelData& parcel_data) +{ + S32 region_x; + S32 region_y; + S32 region_z; + region_x = ll_round(parcel_data.global_x) % REGION_WIDTH_UNITS; + region_y = ll_round(parcel_data.global_y) % REGION_WIDTH_UNITS; + region_z = ll_round(parcel_data.global_z); + // HACK: Flag 0x2 == adult region, + // Flag 0x1 == mature region, otherwise assume PG + if (parcel_data.flags & 0x2) + { + mDetailMaturity->setValue("Parcel_R_Dark"); + } + else if (parcel_data.flags & 0x1) + { + mDetailMaturity->setValue("Parcel_M_Dark"); + } + else + { + mDetailMaturity->setValue("Parcel_PG_Dark"); + } + + LLStringUtil::format_map_t map; + map["DWELL"] = llformat("%.0f", (F64)parcel_data.dwell); + map["AREA"] = llformat("%d m²", parcel_data.actual_area); + map["LOCATION"] = llformat("%s (%d, %d, %d)", parcel_data.sim_name.c_str(), region_x, region_y, region_z); + + mParcelGlobal = LLVector3d(parcel_data.global_x, parcel_data.global_y, parcel_data.global_z); + mDetailsPanel->setVisible(mTabContainer->getCurrentPanel()->getName() == "panel_ls_places" || mTabContainer->getCurrentPanel()->getName() == "panel_ls_land"); + mHasSelection = true; + mDetailMaturity->setVisible(true); + mDetailTitle->setValue(parcel_data.name); + mDetailDesc->setValue(parcel_data.desc); + mDetailAux1->setValue(getString("string.traffic", map)); + mDetailAux2->setValue(getString("string.area", map)); + mDetailLocation->setValue(getString("string.location", map)); + mDetailSnapshotParcel->setValue(parcel_data.snapshot_id); + childSetVisible("teleport_btn", true); + childSetVisible("map_btn", true); + setLoadingProgress(false); +} + +void FSFloaterSearch::displayAvatarDetails(LLAvatarData* avatar_data) +{ + if (avatar_data) + { + LLStringUtil::format_map_t map; + map["AGE"] = LLDateUtil::ageFromDate(avatar_data->born_on, LLDate::now()); + if (avatar_data->partner_id.notNull()) + { + map["PARTNER"] = LLSLURL("agent", avatar_data->partner_id, "inspect").getSLURLString(); + mDetailAux2->setValue(getString("string.partner", map)); + } + + mDetailsPanel->setVisible(mTabContainer->getCurrentPanel()->getName() == "panel_ls_people"); + mHasSelection = true; + mDetailTitle->setValue(LLTrans::getString("LoadingData")); + mDetailDesc->setValue(avatar_data->about_text); + mDetailSnapshot->setValue(avatar_data->image_id); + mDetailAux1->setValue(avatar_data->hide_age ? "" : getString("string.age", map)); + LLAvatarNameCache::get(avatar_data->avatar_id, boost::bind(&FSFloaterSearch::avatarNameUpdatedCallback,this, _1, _2)); + childSetVisible("people_profile_btn", true); + childSetVisible("people_message_btn", true); + childSetVisible("people_friend_btn", true); + getChildView("people_friend_btn")->setEnabled(!LLAvatarActions::isFriend(avatar_data->avatar_id)); + } +} + +void FSFloaterSearch::displayGroupDetails(LLGroupMgrGroupData*& group_data) +{ + if (group_data) + { + LLStringUtil::format_map_t map; + map["MEMBER_COUNT"] = llformat("%d",group_data->mMemberCount); + map["FOUNDER"] = LLSLURL("agent", group_data->mFounderID, "inspect").getSLURLString(); + + mDetailsPanel->setVisible(mTabContainer->getCurrentPanel()->getName() == "panel_ls_groups"); + mHasSelection = true; + mDetailTitle->setValue(LLTrans::getString("LoadingData")); + mDetailDesc->setValue(group_data->mCharter); + mDetailSnapshot->setValue(group_data->mInsigniaID); + mDetailAux1->setValue(getString("string.members", map)); + mDetailAux2->setValue(getString("string.founder", map)); + LLGroupData agent_gdatap; + bool is_member = gAgent.getGroupData(getSelectedID(),agent_gdatap) || gAgent.isGodlike(); + bool join_btn_enabled = !is_member && group_data->mOpenEnrollment; + childSetVisible("group_profile_btn", true); + childSetVisible("group_message_btn", true); + childSetVisible("group_join_btn", true); + getChildView("group_join_btn")->setEnabled(join_btn_enabled); + getChildView("group_message_btn")->setEnabled(is_member); + gCacheName->getGroup(getSelectedID(), boost::bind(&FSFloaterSearch::groupNameUpdatedCallback, this, _1, _2, _3)); + } +} + +void FSFloaterSearch::displayClassifiedDetails(LLAvatarClassifiedInfo*& c_info) +{ + if (c_info) + { + if (c_info->flags & CLASSIFIED_FLAG_MATURE) + { + mDetailMaturity->setValue("Parcel_M_Dark"); + } + else + { + mDetailMaturity->setValue("Parcel_PG_Dark"); + } + + LLStringUtil::format_map_t map; + map["LISTING_PRICE"] = llformat("L$%d", c_info->price_for_listing); + map["SLURL"] = LLSLURL("parcel", c_info->parcel_id, "about").getSLURLString(); + + mDetailsPanel->setVisible(mTabContainer->getCurrentPanel()->getName() == "panel_ls_classifieds"); + mHasSelection = true; + mDetailMaturity->setVisible(true); + mParcelGlobal = c_info->pos_global; + mDetailTitle->setValue(c_info->name); + mDetailDesc->setValue(c_info->description); + mDetailSnapshotParcel->setValue(c_info->snapshot_id); + mDetailAux1->setValue(getString("string.listing_price", map)); + mDetailLocation->setValue(getString("string.slurl", map)); + childSetVisible("teleport_btn", true); + childSetVisible("map_btn", true); + setLoadingProgress(false); + } +} + +bool FSFloaterSearch::displayEventDetails(LLEventStruct event) +{ + if (event.flags == EVENT_FLAG_ADULT) + { + mDetailMaturity->setValue("Parcel_R_Dark"); + } + else if (event.flags == EVENT_FLAG_MATURE) + { + mDetailMaturity->setValue("Parcel_M_Dark"); + } + else + { + mDetailMaturity->setValue("Parcel_PG_Dark"); + } + + S32 region_x; + S32 region_y; + S32 region_z; + region_x = (S64)ll_round(event.globalPos.mdV[VX]) % REGION_WIDTH_UNITS; + region_y = (S64)ll_round(event.globalPos.mdV[VY]) % REGION_WIDTH_UNITS; + region_z = (S32)ll_round(event.globalPos.mdV[VZ]); + LLStringUtil::format_map_t map; + map["DURATION"] = llformat("%d:%.2d", event.duration / 60, event.duration % 60); + map["LOCATION"] = llformat("%s (%d, %d, %d)", event.simName.c_str(), region_x, region_y, region_z); + if (event.cover > 0) + { + map["COVERCHARGE"] = llformat("L$%d", event.cover); + mDetailAux2->setValue(getString("string.covercharge", map)); + } + + mParcelGlobal = event.globalPos; + mEventID = event.eventId; + mDetailsPanel->setVisible(mTabContainer->getCurrentPanel()->getName() == "panel_ls_events"); + mHasSelection = true; + mDetailMaturity->setVisible(true); + mDetailTitle->setValue(event.eventName); + mDetailDesc->setValue(event.desc); + mDetailAux1->setValue(getString("string.duration", map)); + mDetailLocation->setValue(getString("string.location", map)); + mDetailSnapshotParcel->setValue(LLUUID::null); + childSetVisible("teleport_btn", true); + childSetVisible("map_btn", true); + childSetVisible("event_reminder_btn", true); + + LLWorldMapMessage::getInstance()->sendNamedRegionRequest(event.simName, boost::bind(&FSFloaterSearch::regionHandleCallback, this, _1, event.globalPos), "", false); + return true; +} + +void FSFloaterSearch::regionHandleCallback(U64 region_handle, LLVector3d pos_global) +{ + std::string url = gAgent.getRegionCapability("RemoteParcelRequest"); + if (!url.empty()) + { + auto region_origin = from_region_handle(region_handle); + LLVector3 pos_region(LLVector3(pos_global - region_origin)); + + LLRemoteParcelInfoProcessor::getInstance()->requestRegionParcelInfo(url, + LLUUID::null, pos_region, pos_global, mRemoteParcelEventLocationObserver->getObserverHandle()); + } + else + { + setLoadingProgress(false); + } +} + +void FSFloaterSearch::displayEventParcelImage(const LLParcelData& parcel_data) +{ + mDetailSnapshotParcel->setValue(parcel_data.snapshot_id); + setLoadingProgress(false); +} + +void FSFloaterSearch::avatarNameUpdatedCallback(const LLUUID& id, const LLAvatarName& av_name) +{ + if (id == getSelectedID()) + { + mDetailTitle->setValue(av_name.getCompleteName()); + setLoadingProgress(false); + } + // Otherwise possibly a request for an older selection, ignore it. +} + +void FSFloaterSearch::groupNameUpdatedCallback(const LLUUID& id, const std::string& name, bool is_group) +{ + if (id == getSelectedID()) + { + mDetailTitle->setValue( LLSD(name) ); + setLoadingProgress(false); + } + // Otherwise possibly a request for an older selection, ignore it. +} + +void FSFloaterSearch::setLoadingProgress(bool started) +{ + LLLoadingIndicator* indicator = getChild<LLLoadingIndicator>("loading"); + + indicator->setVisible(started); + + if (started) + { + indicator->start(); + } + else + { + indicator->stop(); + } +} + +void FSFloaterSearch::resetVerbs() +{ + childSetVisible("people_profile_btn", false); + childSetVisible("people_message_btn", false); + childSetVisible("people_friend_btn", false); + childSetVisible("group_profile_btn", false); + childSetVisible("group_message_btn", false); + childSetVisible("group_join_btn", false); + childSetVisible("event_reminder_btn", false); + childSetVisible("teleport_btn", false); + childSetVisible("map_btn", false); +} + +void FSFloaterSearch::flushDetails() +{ + LL_INFOS() << "flushDetails()" << LL_ENDL; + mDetailTitle->setValue(""); + mDetailDesc->setValue(""); + mDetailAux1->setValue(""); + mDetailAux2->setValue(""); + mDetailLocation->setValue(""); + mDetailSnapshot->setValue(LLSD()); + mDetailMaturity->setVisible(false); + mParcelGlobal.setZero(); +} + +void FSFloaterSearch::onBtnPeopleProfile() +{ + LLAvatarActions::showProfile(getSelectedID()); +} + +void FSFloaterSearch::onBtnPeopleIM() +{ + LLAvatarActions::startIM(getSelectedID()); +} + +void FSFloaterSearch::onBtnPeopleFriend() +{ + LLAvatarActions::requestFriendshipDialog(getSelectedID()); +} + +void FSFloaterSearch::onBtnGroupProfile() +{ + LLGroupActions::show(getSelectedID()); +} + +void FSFloaterSearch::onBtnGroupChat() +{ + LLGroupActions::startIM(getSelectedID()); +} + +void FSFloaterSearch::onBtnGroupJoin() +{ + LLGroupActions::join(getSelectedID()); +} + +void FSFloaterSearch::onBtnTeleport() +{ + if (!mParcelGlobal.isExactlyZero()) + { + gAgent.teleportViaLocationLookAt(mParcelGlobal); + LLFloaterWorldMap::getInstance()->trackLocation(mParcelGlobal); + /// <FS:CR> What should we do when when we teleport? The default (1) is to close the floater, + /// the user may elect to minimize the floater (2), or to do nothing (any other setting) + static LLCachedControl<U32> teleport_action(gSavedSettings, "FSLegacySearchActionOnTeleport"); + if (teleport_action == 1) + { + closeFloater(); + } + else if (teleport_action == 2) + { + setMinimized(TRUE); + } + } +} + +void FSFloaterSearch::onBtnMap() +{ + if (!mParcelGlobal.isExactlyZero()) + { + LLFloaterWorldMap::getInstance()->trackLocation(mParcelGlobal); + LLFloaterReg::showInstance("world_map", "center"); + } +} + +void FSFloaterSearch::onBtnEventReminder() +{ + gEventNotifier.add(mEventID); +} + +//////////////////////////////////////// +// People Search Panel // +//////////////////////////////////////// + +static LLPanelInjector<FSPanelSearchPeople> t_panel_fs_search_people("panel_ls_people"); + +FSPanelSearchPeople::FSPanelSearchPeople() : FSSearchPanelBase() +, mQueryID(nullptr) +, mStartSearch(0) +, mResultsReceived(0) +, mResultsContent() +, mAvatarNameCallbackConnection() +{ +} + +FSPanelSearchPeople::~FSPanelSearchPeople() +{ + if (mAvatarNameCallbackConnection.connected()) + { + mAvatarNameCallbackConnection.disconnect(); + } +} + +bool FSPanelSearchPeople::postBuild() +{ + mSearchComboBox = findChild<LLSearchComboBox>("people_edit"); + mSearchResults = findChild<LLScrollListCtrl>("search_results_people"); + if (mSearchComboBox) + { + mSearchComboBox->setCommitCallback(boost::bind(&FSPanelSearchPeople::onBtnFind, this)); + fillSearchComboBox(mSearchComboBox); + } + if (mSearchResults) + { + mSearchResults->setCommitCallback(boost::bind(&FSPanelSearchPeople::onSelectItem, this)); + mSearchResults->setEnabled(FALSE); + mSearchResults->setCommentText(LLTrans::getString("no_results")); + mSearchResults->setContextMenu(LLScrollListCtrl::MENU_AVATAR); + } + + childSetAction("people_next", boost::bind(&FSPanelSearchPeople::onBtnNext, this)); + childSetAction("people_back", boost::bind(&FSPanelSearchPeople::onBtnBack, this)); + getChildView("people_next")->setEnabled(FALSE); + getChildView("people_back")->setEnabled(FALSE); + + return TRUE; +} + +void FSPanelSearchPeople::focusDefaultElement() +{ + mSearchComboBox->focusTextEntry(); +} + +void FSPanelSearchPeople::find() +{ + std::string text = mSearchComboBox->getSimple(); + boost::trim(text); + + if (text.size() <= MIN_SEARCH_STRING_SIZE) + { + mSearchResults->setCommentText(LLTrans::getString("search_short")); + return; + } + + if (LLUUID::validate(text)) + { + LLUUID id(text); + + mSearchResults->deleteAllItems(); + mSearchResults->setCommentText(LLTrans::getString("searching")); + mResultsReceived = 0; + mNumResultsReturned = 0; + + if (mAvatarNameCallbackConnection.connected()) + { + mAvatarNameCallbackConnection.disconnect(); + } + mAvatarNameCallbackConnection = LLAvatarNameCache::get(id, boost::bind(&FSPanelSearchPeople::onAvatarNameCallback, this, _1, _2)); + + return; + } + + LLStringUtil::replaceChar(text, '.', ' '); + + mResultsReceived = 0; + if (mQueryID.notNull()) + { + mQueryID.setNull(); + } + mQueryID.generate(); + + if (mStartSearch < 0) + { + mStartSearch = 0; + } + + gMessageSystem->newMessage("DirFindQuery"); + gMessageSystem->nextBlock("AgentData"); + gMessageSystem->addUUID("AgentID", gAgentID); + gMessageSystem->addUUID("SessionID", gAgentSessionID); + gMessageSystem->nextBlock("QueryData"); + gMessageSystem->addUUID("QueryID", getQueryID()); + gMessageSystem->addString("QueryText", text); + gMessageSystem->addU32("QueryFlags", DFQ_PEOPLE); + gMessageSystem->addS32("QueryStart", mStartSearch); + gAgent.sendReliableMessage(); + LL_INFOS("Search") << "Firing off search request: " << getQueryID() << LL_ENDL; + + mSearchResults->deleteAllItems(); + mSearchResults->setCommentText(LLTrans::getString("searching")); + mNumResultsReturned = 0; +} + +void FSPanelSearchPeople::onBtnFind() +{ + std::chrono::time_point<std::chrono::system_clock> now = std::chrono::system_clock::now(); + auto elapsed = now - lastRequestTime; + U64 elapsedMS = std::chrono::duration_cast<std::chrono::milliseconds>(elapsed).count(); + if(elapsedMS < REQUEST_MIN_ELAPSED_TIME) return; + lastRequestTime = now; + + std::string text = mSearchComboBox->getSimple(); + + if (!text.empty()) + { + LLSearchHistory::getInstance()->addEntry(text); + } + + resetSearch(); + + find(); +} + +void FSPanelSearchPeople::onBtnNext() +{ + mStartSearch += RESULT_PAGE_SIZE; + getChildView("people_back")->setEnabled(TRUE); + + find(); +} + +void FSPanelSearchPeople::onBtnBack() +{ + mStartSearch -= RESULT_PAGE_SIZE; + getChildView("people_back")->setEnabled(mStartSearch > 0); + + find(); +} + +void FSPanelSearchPeople::resetSearch() +{ + mStartSearch = 0; + getChildView("people_back")->setEnabled(FALSE); + getChildView("people_next")->setEnabled(FALSE); +} + +S32 FSPanelSearchPeople::showNextButton(S32 rows) +{ + bool show_next_button = (mResultsReceived > RESULT_PAGE_SIZE); + getChildView("people_next")->setEnabled(show_next_button); + if (show_next_button) + { + rows -= (mResultsReceived - RESULT_PAGE_SIZE); + } + return rows; +} + +void FSPanelSearchPeople::onSelectItem() +{ + if (!mSearchResults) + { + return; + } + FSFloaterSearch* search_instance = LLFloaterReg::findTypedInstance<FSFloaterSearch>("search"); + if (search_instance) + { + search_instance->FSFloaterSearch::onSelectedItem(mSearchResults->getSelectedValue(), FSFloaterSearch::SC_AVATAR); + } +} + +// static +void FSPanelSearchPeople::processSearchReply(LLMessageSystem* msg, void**) +{ + LLUUID query_id; + std::string first_name; + std::string last_name; + LLUUID agent_id; + + msg->getUUIDFast(_PREHASH_QueryData, _PREHASH_QueryID, query_id); + msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id); + + // This result is not for us. + if (agent_id != gAgentID) + { + return; + } + LL_INFOS("Search") << "received search results - QueryID: " << query_id << " AgentID: " << agent_id << LL_ENDL; + + FSPanelSearchPeople* self = FSFloaterSearch::getSearchPanel<FSPanelSearchPeople>("panel_ls_people"); + + // floater is closed or these are not results from our last request + if (!self || query_id != self->getQueryID()) + { + return; + } + + LLScrollListCtrl* search_results = self->getChild<LLScrollListCtrl>("search_results_people"); + + if (self->mNumResultsReturned++ == 0) + { + search_results->deleteAllItems(); + } + + // Check for status messages + if (msg->getNumberOfBlocks("StatusData")) + { + U32 status; + msg->getU32("StatusData", "Status", status); + if (status & STATUS_SEARCH_PLACES_FOUNDNONE) + { + LLStringUtil::format_map_t map; + map["[TEXT]"] = self->getChild<LLUICtrl>("people_edit")->getValue().asString(); + search_results->setEnabled(FALSE); + search_results->setCommentText(LLTrans::getString("not_found", map)); + return; + } + else if (status & STATUS_SEARCH_PLACES_SHORTSTRING) + { + search_results->setEnabled(FALSE); + search_results->setCommentText(LLTrans::getString("search_short")); + return; + } + else if (status & STATUS_SEARCH_PLACES_BANNEDWORD) + { + search_results->setEnabled(FALSE); + search_results->setCommentText(LLTrans::getString("search_banned")); + return; + } + else if (status & STATUS_SEARCH_PLACES_SEARCHDISABLED) + { + search_results->setEnabled(FALSE); + search_results->setCommentText(LLTrans::getString("search_disabled")); + return; + } + } + + bool found_one = false; + S32 num_new_rows = msg->getNumberOfBlocksFast(_PREHASH_QueryReplies); + if (num_new_rows == 0 && self->mResultsReceived == 0) + { + LLStringUtil::format_map_t map; + map["[TEXT]"] = self->getChild<LLUICtrl>("people_edit")->getValue().asString(); + search_results->setEnabled(FALSE); + search_results->setCommentText(LLTrans::getString("not_found", map)); + } + + self->mResultsReceived += num_new_rows; + num_new_rows = self->showNextButton(num_new_rows); + + for (S32 i = 0; i < num_new_rows; i++) + { + msg->getStringFast( _PREHASH_QueryReplies, _PREHASH_FirstName, first_name, i); + msg->getStringFast( _PREHASH_QueryReplies, _PREHASH_LastName, last_name, i); + msg->getUUIDFast( _PREHASH_QueryReplies, _PREHASH_AgentID, agent_id, i); + //msg->getU8Fast( _PREHASH_QueryReplies, _PREHASH_Online, online, i); + + if (agent_id.isNull()) + { + LL_INFOS("Search") << "Null result returned for QueryID: " << query_id << LL_ENDL; + LLStringUtil::format_map_t map; + map["[TEXT]"] = self->getChild<LLUICtrl>("people_edit")->getValue().asString(); + search_results->setEnabled(FALSE); + search_results->setCommentText(LLTrans::getString("not_found", map)); + } + else + { + LL_DEBUGS("Search") << "Got: " << first_name << " " << last_name << " AgentID: " << agent_id << LL_ENDL; + search_results->setEnabled(TRUE); + found_one = true; + + std::string avatar_name; + avatar_name = LLCacheName::buildFullName(first_name, last_name); + + LLSD content; + LLSD element; + + element["id"] = agent_id; + + element["columns"][0]["column"] = "icon"; + element["columns"][0]["type"] = "icon"; + element["columns"][0]["value"] = "icon_avatar_offline.tga"; + + element["columns"][1]["column"] = "username"; + element["columns"][1]["value"] = avatar_name; + + content["name"] = avatar_name; + + search_results->addElement(element, ADD_BOTTOM); + self->mResultsContent[agent_id.asString()] = content; + } + } + if (found_one) + { + search_results->selectFirstItem(); + search_results->setFocus(TRUE); + self->onSelectItem(); + } +} + +void FSPanelSearchPeople::onAvatarNameCallback(const LLUUID& id, const LLAvatarName& av_name) +{ + if (mAvatarNameCallbackConnection.connected()) + { + mAvatarNameCallbackConnection.disconnect(); + } + + LLScrollListCtrl* search_results = getChild<LLScrollListCtrl>("search_results_people"); + + if (av_name.getAccountName() != "(?\?\?).(?\?\?)") + { + LLSD content; + LLSD data; + data["id"] = id; + + data["columns"][0]["column"] = "icon"; + data["columns"][0]["type"] = "icon"; + data["columns"][0]["value"] = "icon_avatar_offline.tga"; + + data["columns"][1]["name"] = "username"; + data["columns"][1]["value"] = av_name.getUserName(); + + content["name"] = av_name.getUserName(); + + search_results->addElement(data); + + mResultsContent[id.asString()] = content; + mResultsReceived = 1; + mNumResultsReturned = 1; + + search_results->setEnabled(TRUE); + search_results->selectFirstItem(); + search_results->setFocus(TRUE); + onSelectItem(); + } + else + { + LLStringUtil::format_map_t map; + map["[TEXT]"] = getChild<LLUICtrl>("people_edit")->getValue().asString(); + search_results->setEnabled(FALSE); + search_results->setCommentText(LLTrans::getString("not_found", map)); + } +} + +//////////////////////////////////////// +// Groups Search Panel // +//////////////////////////////////////// + +static LLPanelInjector<FSPanelSearchGroups> t_panel_fs_search_groups("panel_ls_groups"); + +FSPanelSearchGroups::FSPanelSearchGroups() : FSSearchPanelBase() +, mQueryID(nullptr) +, mStartSearch(0) +, mResultsReceived(0) +, mResultsContent() +{ +} + +FSPanelSearchGroups::~FSPanelSearchGroups() +{ +} + +bool FSPanelSearchGroups::postBuild() +{ + mSearchComboBox = findChild<LLSearchComboBox>("groups_edit"); + mSearchResults = findChild<LLScrollListCtrl>("search_results_groups"); + if (mSearchComboBox) + { + mSearchComboBox->setCommitCallback(boost::bind(&FSPanelSearchGroups::onBtnFind, this)); + fillSearchComboBox(mSearchComboBox); + } + if (mSearchResults) + { + mSearchResults->setCommitCallback(boost::bind(&FSPanelSearchGroups::onSelectItem, this)); + mSearchResults->setEnabled(FALSE); + mSearchResults->setCommentText(LLTrans::getString("no_results")); + } + + childSetAction("groups_next", boost::bind(&FSPanelSearchGroups::onBtnNext, this)); + childSetAction("groups_back", boost::bind(&FSPanelSearchGroups::onBtnBack, this)); + getChildView("groups_next")->setEnabled(FALSE); + getChildView("groups_back")->setEnabled(FALSE); + + lastRequestTime = std::chrono::system_clock::now(); + + return TRUE; +} + +void FSPanelSearchGroups::focusDefaultElement() +{ + mSearchComboBox->focusTextEntry(); +} + +void FSPanelSearchGroups::find() +{ + std::string text = filterShortWords(mSearchComboBox->getSimple()); + if (text.size() == 0) + { + mSearchResults->setCommentText(LLTrans::getString("search_short")); + return; + } + + static LLUICachedControl<bool> inc_pg("ShowPGSims", 1); + static LLUICachedControl<bool> inc_mature("ShowMatureSims", 0); + static LLUICachedControl<bool> inc_adult("ShowAdultSims", 0); + if (!(inc_pg || inc_mature || inc_adult)) + { + LLNotificationsUtil::add("NoContentToSearch"); + return; + } + U32 scope = 0; + if (gAgent.wantsPGOnly()) + { + scope |= DFQ_PG_SIMS_ONLY; + } + bool adult_enabled = gAgent.canAccessAdult(); + bool mature_enabled = gAgent.canAccessMature(); + if (inc_pg) + { + scope |= DFQ_INC_PG; + } + if (inc_mature && mature_enabled) + { + scope |= DFQ_INC_MATURE; + } + if (inc_adult && adult_enabled) + { + scope |= DFQ_INC_ADULT; + } + scope |= DFQ_GROUPS; + + mResultsReceived = 0; + if (mQueryID.notNull()) + { + mQueryID.setNull(); + } + mQueryID.generate(); + + if (mStartSearch < 0) + { + mStartSearch = 0; + } + + gMessageSystem->newMessage("DirFindQuery"); + gMessageSystem->nextBlock("AgentData"); + gMessageSystem->addUUID("AgentID", gAgentID); + gMessageSystem->addUUID("SessionID", gAgentSessionID); + gMessageSystem->nextBlock("QueryData"); + gMessageSystem->addUUID("QueryID", getQueryID()); + gMessageSystem->addString("QueryText", text); + gMessageSystem->addU32("QueryFlags", scope); + gMessageSystem->addS32("QueryStart", mStartSearch); + gAgent.sendReliableMessage(); + LL_DEBUGS("Search") << "Firing off search request: " << getQueryID() << LL_ENDL; + + mSearchResults->deleteAllItems(); + mSearchResults->setCommentText(LLTrans::getString("searching")); + mNumResultsReturned = 0; +} + +void FSPanelSearchGroups::onBtnFind() +{ + std::chrono::time_point<std::chrono::system_clock> now = std::chrono::system_clock::now(); + auto elapsed = now - lastRequestTime; + U64 elapsedMS = std::chrono::duration_cast<std::chrono::milliseconds>(elapsed).count(); + if(elapsedMS < REQUEST_MIN_ELAPSED_TIME) return; + lastRequestTime = now; + + std::string text = mSearchComboBox->getSimple(); + if (!text.empty()) + { + LLSearchHistory::getInstance()->addEntry(text); + } + + resetSearch(); + + find(); +} + +void FSPanelSearchGroups::onBtnNext() +{ + mStartSearch += RESULT_PAGE_SIZE; + getChildView("groups_back")->setEnabled(TRUE); + + find(); +} + +void FSPanelSearchGroups::onBtnBack() +{ + mStartSearch -= RESULT_PAGE_SIZE; + getChildView("groups_back")->setEnabled(mStartSearch > 0); + + find(); +} + +void FSPanelSearchGroups::resetSearch() +{ + mStartSearch = 0; + getChildView("groups_back")->setEnabled(FALSE); + getChildView("groups_next")->setEnabled(FALSE); +} + +S32 FSPanelSearchGroups::showNextButton(S32 rows) +{ + bool show_next_button = (mResultsReceived > RESULT_PAGE_SIZE); + getChildView("groups_next")->setEnabled(show_next_button); + if (show_next_button) + { + rows -= (mResultsReceived - RESULT_PAGE_SIZE); + } + return rows; +} + +void FSPanelSearchGroups::onSelectItem() +{ + if (!mSearchResults) + { + return; + } + FSFloaterSearch* search_instance = LLFloaterReg::findTypedInstance<FSFloaterSearch>("search"); + if (search_instance) + { + search_instance->FSFloaterSearch::onSelectedItem(mSearchResults->getSelectedValue(), FSFloaterSearch::SC_GROUP); + } +} + +// static +void FSPanelSearchGroups::processSearchReply(LLMessageSystem* msg, void**) +{ + LLUUID query_id; + LLUUID group_id; + LLUUID agent_id; + std::string group_name; + S32 members; + F32 search_order; + + msg->getUUIDFast( _PREHASH_QueryData, _PREHASH_QueryID, query_id); + msg->getUUIDFast( _PREHASH_AgentData, _PREHASH_AgentID, agent_id); + + // Not for us + if (agent_id != gAgentID) + { + return; + } + LL_DEBUGS("Search") << "received directory request - QueryID: " << query_id << " AgentID: " << agent_id << LL_ENDL; + + FSPanelSearchGroups* self = FSFloaterSearch::getSearchPanel<FSPanelSearchGroups>("panel_ls_groups"); + + // floater is closed or these are not results from our last request + if (!self || query_id != self->mQueryID) + { + return; + } + + LLScrollListCtrl* search_results = self->getChild<LLScrollListCtrl>("search_results_groups"); + + // Clear "Searching" label on first results + if (self->mNumResultsReturned++ == 0) + { + search_results->deleteAllItems(); + } + + // Check for status messages + if (msg->getNumberOfBlocks("StatusData")) + { + U32 status; + msg->getU32("StatusData", "Status", status); + if (status & STATUS_SEARCH_PLACES_FOUNDNONE) + { + LLStringUtil::format_map_t map; + map["[TEXT]"] = self->getChild<LLUICtrl>("groups_edit")->getValue().asString(); + search_results->setEnabled(FALSE); + search_results->setCommentText(LLTrans::getString("not_found", map)); + return; + } + else if(status & STATUS_SEARCH_PLACES_SHORTSTRING) + { + search_results->setEnabled(FALSE); + search_results->setCommentText(LLTrans::getString("search_short")); + return; + } + else if (status & STATUS_SEARCH_PLACES_BANNEDWORD) + { + search_results->setEnabled(FALSE); + search_results->setCommentText(LLTrans::getString("search_banned")); + return; + } + else if (status & STATUS_SEARCH_PLACES_SEARCHDISABLED) + { + search_results->setEnabled(FALSE); + search_results->setCommentText(LLTrans::getString("search_disabled")); + return; + } + } + + bool found_one = false; + S32 num_new_rows = msg->getNumberOfBlocksFast(_PREHASH_QueryReplies); + if (num_new_rows == 0 && self->mResultsReceived == 0) + { + LLStringUtil::format_map_t map; + map["[TEXT]"] = self->getChild<LLUICtrl>("groups_edit")->getValue().asString(); + search_results->setEnabled(FALSE); + search_results->setCommentText(LLTrans::getString("not_found", map)); + } + + self->mResultsReceived += num_new_rows; + num_new_rows = self->showNextButton(num_new_rows); + + for (S32 i = 0; i < num_new_rows; i++) + { + msg->getUUIDFast( _PREHASH_QueryReplies, _PREHASH_GroupID, group_id, i); + msg->getStringFast( _PREHASH_QueryReplies, _PREHASH_GroupName, group_name, i); + msg->getS32Fast( _PREHASH_QueryReplies, _PREHASH_Members, members, i); + msg->getF32Fast( _PREHASH_QueryReplies, _PREHASH_SearchOrder, search_order,i); + if (group_id.isNull()) + { + LL_DEBUGS("Search") << "No results returned for QueryID: " << query_id << LL_ENDL; + LLStringUtil::format_map_t map; + map["[TEXT]"] = self->getChild<LLUICtrl>("groups_edit")->getValue().asString(); + search_results->setEnabled(FALSE); + search_results->setCommentText(LLTrans::getString("not_found", map)); + } + else + { + LL_DEBUGS("Search") << "Got: " << group_name << " GroupID: " << group_id << LL_ENDL; + search_results->setEnabled(TRUE); + found_one = true; + + LLSD content; + LLSD element; + + element["id"] = group_id; + + element["columns"][0]["column"] = "icon"; + element["columns"][0]["type"] = "icon"; + element["columns"][0]["value"] = "Icon_Group"; + + element["columns"][1]["column"] = "group_name"; + element["columns"][1]["value"] = group_name; + + element["columns"][2]["column"] = "members"; + element["columns"][2]["value"] = members; + + element["columns"][3]["column"] = "score"; + element["columns"][3]["value"] = search_order; + + content["name"] = group_name; + + search_results->addElement(element, ADD_BOTTOM); + self->mResultsContent[group_id.asString()] = content; + } + } + if (found_one) + { + search_results->selectFirstItem(); + search_results->setFocus(TRUE); + self->onSelectItem(); + } +} + +//////////////////////////////////////// +// Places Search Panel // +//////////////////////////////////////// + +static LLPanelInjector<FSPanelSearchPlaces> t_panel_fs_search_places("panel_ls_places"); + +FSPanelSearchPlaces::FSPanelSearchPlaces() : FSSearchPanelBase() +, mQueryID(nullptr) +, mStartSearch(0) +, mResultsReceived(0) +, mResultsContent() +{ + mCommitCallbackRegistrar.add("CommitSearch", boost::bind(&FSPanelSearchPlaces::find, this)); +} + +FSPanelSearchPlaces::~FSPanelSearchPlaces() +{ +} + +bool FSPanelSearchPlaces::postBuild() +{ + mSearchComboBox = findChild<LLSearchComboBox>("places_edit"); + mSearchResults = findChild<LLScrollListCtrl>("search_results_places"); + mPlacesCategory = findChild<LLComboBox>("places_category"); + if (mSearchComboBox) + { + mSearchComboBox->setCommitCallback(boost::bind(&FSPanelSearchPlaces::onBtnFind, this)); + fillSearchComboBox(mSearchComboBox); + } + if (mSearchResults) + { + mSearchResults->setCommitCallback(boost::bind(&FSPanelSearchPlaces::onSelectItem, this)); + mSearchResults->setEnabled(FALSE); + mSearchResults->setCommentText(LLTrans::getString("no_results")); + } + if (mPlacesCategory) + { + mPlacesCategory->add(LLTrans::getString("all_categories"), LLSD("any")); + mPlacesCategory->addSeparator(); + for (int category = LLParcel::C_LINDEN; category < LLParcel::C_COUNT; category++) + { + LLParcel::ECategory eCategory = (LLParcel::ECategory)category; + mPlacesCategory->add(LLTrans::getString(LLParcel::getCategoryUIString(eCategory)), LLParcel::getCategoryString(eCategory)); + } + } + childSetAction("places_next", boost::bind(&FSPanelSearchPlaces::onBtnNext, this)); + childSetAction("places_back", boost::bind(&FSPanelSearchPlaces::onBtnBack, this)); + getChildView("places_next")->setEnabled(FALSE); + getChildView("places_back")->setEnabled(FALSE); + + return TRUE; +} + +void FSPanelSearchPlaces::focusDefaultElement() +{ + mSearchComboBox->focusTextEntry(); +} + +void FSPanelSearchPlaces::find() +{ + std::string text = filterShortWords(mSearchComboBox->getSimple()); + if (text.empty()) + { + mSearchResults->setCommentText(LLTrans::getString("search_short")); + return; + } + + static LLUICachedControl<bool> inc_pg("ShowPGSims", 1); + static LLUICachedControl<bool> inc_mature("ShowMatureSims", 0); + static LLUICachedControl<bool> inc_adult("ShowAdultSims", 0); + if (!(inc_pg || inc_mature || inc_adult)) + { + LLNotificationsUtil::add("NoContentToSearch"); + return; + } + S8 category; + std::string category_string = mPlacesCategory->getSelectedValue(); + if (category_string == "any") + { + category = LLParcel::C_ANY; + } + else + { + category = LLParcel::getCategoryFromString(category_string); + } + U32 scope = 0; + if (gAgent.wantsPGOnly()) + { + scope |= DFQ_PG_SIMS_ONLY; + } + bool adult_enabled = gAgent.canAccessAdult(); + bool mature_enabled = gAgent.canAccessMature(); + if (inc_pg) + { + scope |= DFQ_INC_PG; + } + if (inc_mature && mature_enabled) + { + scope |= DFQ_INC_MATURE; + } + if (inc_adult && adult_enabled) + { + scope |= DFQ_INC_ADULT; + } + scope |= DFQ_DWELL_SORT; + + mResultsReceived = 0; + if (mQueryID.notNull()) + { + mQueryID.setNull(); + } + mQueryID.generate(); + + if (mStartSearch < 0) + { + mStartSearch = 0; + } + + gMessageSystem->newMessage("DirPlacesQuery"); + gMessageSystem->nextBlock("AgentData"); + gMessageSystem->addUUID("AgentID", gAgentID); + gMessageSystem->addUUID("SessionID", gAgentSessionID); + gMessageSystem->nextBlock("QueryData"); + gMessageSystem->addUUID("QueryID", getQueryID()); + gMessageSystem->addString("QueryText", text); + gMessageSystem->addU32("QueryFlags", scope); + gMessageSystem->addS8("Category", category); + // TODO: Search filter by region name. + gMessageSystem->addString("SimName", ""); + gMessageSystem->addS32("QueryStart", mStartSearch); + gAgent.sendReliableMessage(); + LL_INFOS("Search") << "Firing off places search request: " << getQueryID() << LL_ENDL; + + mSearchResults->deleteAllItems(); + mSearchResults->setCommentText(LLTrans::getString("searching")); + mNumResultsReturned = 0; +} + +void FSPanelSearchPlaces::onBtnFind() +{ + std::chrono::time_point<std::chrono::system_clock> now = std::chrono::system_clock::now(); + auto elapsed = now - lastRequestTime; + U64 elapsedMS = std::chrono::duration_cast<std::chrono::milliseconds>(elapsed).count(); + if(elapsedMS < REQUEST_MIN_ELAPSED_TIME) return; + lastRequestTime = now; + + std::string text = mSearchComboBox->getSimple(); + if (!text.empty()) + { + LLSearchHistory::getInstance()->addEntry(text); + } + + resetSearch(); + + find(); +} + +void FSPanelSearchPlaces::onBtnNext() +{ + mStartSearch += RESULT_PAGE_SIZE; + getChildView("places_back")->setEnabled(TRUE); + + find(); +} + +void FSPanelSearchPlaces::onBtnBack() +{ + mStartSearch -= RESULT_PAGE_SIZE; + getChildView("places_back")->setEnabled(mStartSearch > 0); + + find(); +} + +void FSPanelSearchPlaces::resetSearch() +{ + mStartSearch = 0; + getChildView("places_back")->setEnabled(FALSE); + getChildView("places_next")->setEnabled(FALSE); +} + +S32 FSPanelSearchPlaces::showNextButton(S32 rows) +{ + bool show_next_button = (mResultsReceived > RESULT_PAGE_SIZE); + getChildView("places_next")->setEnabled(show_next_button); + if (show_next_button) + { + rows -= (mResultsReceived - RESULT_PAGE_SIZE); + } + return rows; +} + +void FSPanelSearchPlaces::onSelectItem() +{ + if (!mSearchResults) + { + return; + } + FSFloaterSearch* search_instance = LLFloaterReg::findTypedInstance<FSFloaterSearch>("search"); + if (search_instance) + { + search_instance->FSFloaterSearch::onSelectedItem(mSearchResults->getSelectedValue(), FSFloaterSearch::SC_PLACE); + } +} + +// static +void FSPanelSearchPlaces::processSearchReply(LLMessageSystem* msg, void**) +{ + LLUUID agent_id; + LLUUID query_id; + LLUUID parcel_id; + std::string name; + bool for_sale; + bool auction; + F32 dwell; + + msg->getUUID("AgentData", "AgentID", agent_id); + msg->getUUID("QueryData", "QueryID", query_id); + + // Not for us + if (agent_id != gAgentID) + { + return; + } + LL_DEBUGS("Search") << "received directory request - QueryID: " << query_id << " AgentID: " << agent_id << LL_ENDL; + + FSPanelSearchPlaces* self = FSFloaterSearch::getSearchPanel<FSPanelSearchPlaces>("panel_ls_places"); + + // floater is closed or these are not results from our last request + if (!self || query_id != self->getQueryID()) + { + return; + } + + LLScrollListCtrl* search_results = self->getChild<LLScrollListCtrl>("search_results_places"); + + // Clear "Searching" label on first results + if (self->mNumResultsReturned++ == 0) + { + search_results->deleteAllItems(); + } + + // Check for status messages + if (msg->getNumberOfBlocks("StatusData")) + { + U32 status; + msg->getU32("StatusData", "Status", status); + if (status & STATUS_SEARCH_PLACES_FOUNDNONE) + { + LLStringUtil::format_map_t map; + map["[TEXT]"] = self->getChild<LLUICtrl>("places_edit")->getValue().asString(); + search_results->setEnabled(FALSE); + search_results->setCommentText(LLTrans::getString("not_found", map)); + return; + } + else if(status & STATUS_SEARCH_PLACES_SHORTSTRING) + { + search_results->setEnabled(FALSE); + search_results->setCommentText(LLTrans::getString("search_short")); + return; + } + else if (status & STATUS_SEARCH_PLACES_BANNEDWORD) + { + search_results->setEnabled(FALSE); + search_results->setCommentText(LLTrans::getString("search_banned")); + return; + } + else if (status & STATUS_SEARCH_PLACES_SEARCHDISABLED) + { + search_results->setEnabled(FALSE); + search_results->setCommentText(LLTrans::getString("search_disabled")); + return; + } + else if (status & STATUS_SEARCH_PLACES_ESTATEEMPTY) + { + search_results->setEnabled(FALSE); + search_results->setCommentText(LLTrans::getString("search_disabled")); + return; + } + } + + bool found_one = false; + S32 num_new_rows = msg->getNumberOfBlocks("QueryReplies"); + if (num_new_rows == 0 && self->mResultsReceived == 0) + { + LLStringUtil::format_map_t map; + map["[TEXT]"] = self->getChild<LLUICtrl>("places_edit")->getValue().asString(); + search_results->setEnabled(FALSE); + search_results->setCommentText(LLTrans::getString("not_found", map)); + } + + self->mResultsReceived += num_new_rows; + num_new_rows = self->showNextButton(num_new_rows); + + for (S32 i = 0; i < num_new_rows; i++) + { + msg->getUUID( "QueryReplies", "ParcelID", parcel_id, i); + msg->getString( "QueryReplies", "Name", name, i); + msg->getBOOL( "QueryReplies", "ForSale", for_sale,i); + msg->getBOOL( "QueryReplies", "Auction", auction, i); + msg->getF32( "QueryReplies", "Dwell", dwell, i); + if (parcel_id.isNull()) + { + LL_DEBUGS("Search") << "Null result returned for QueryID: " << query_id << LL_ENDL; + LLStringUtil::format_map_t map; + map["[TEXT]"] = self->getChild<LLUICtrl>("places_edit")->getValue().asString(); + search_results->setEnabled(FALSE); + search_results->setCommentText(LLTrans::getString("not_found", map)); + } + else + { + LL_DEBUGS("Search") << "Got: " << name << " ParcelID: " << parcel_id << LL_ENDL; + search_results->setEnabled(TRUE); + found_one = true; + + LLSD content; + LLSD element; + + element["id"] = parcel_id; + + if (auction) + { + element["columns"][0]["column"] = "icon"; + element["columns"][0]["type"] = "icon"; + element["columns"][0]["value"] = "Icon_Auction"; + } + else if (for_sale) + { + element["columns"][0]["column"] = "icon"; + element["columns"][0]["type"] = "icon"; + element["columns"][0]["value"] = "Icon_For_Sale"; + } + else + { + element["columns"][0]["column"] = "icon"; + element["columns"][0]["type"] = "icon"; + element["columns"][0]["value"] = "Icon_Place"; + } + + element["columns"][1]["column"] = "place_name"; + element["columns"][1]["value"] = name; + + content["name"] = name; + + std::string buffer = llformat("%.0f", (F64)dwell); + element["columns"][2]["column"] = "dwell"; + element["columns"][2]["value"] = buffer; + + search_results->addElement(element, ADD_BOTTOM); + self->mResultsContent[parcel_id.asString()] = content; + } + } + if (found_one) + { + search_results->selectFirstItem(); + search_results->setFocus(TRUE); + self->onSelectItem(); + } +} + +//////////////////////////////////////// +// Land Search Panel // +//////////////////////////////////////// + +static LLPanelInjector<FSPanelSearchLand> t_panel_fs_search_land("panel_ls_land"); + +FSPanelSearchLand::FSPanelSearchLand() : FSSearchPanelBase() +, mQueryID(nullptr) +, mStartSearch(0) +, mResultsReceived(0) +, mResultsContent() +{ + mCommitCallbackRegistrar.add("CommitSearch", boost::bind(&FSPanelSearchLand::find, this)); +} + +FSPanelSearchLand::~FSPanelSearchLand() +{ +} + +bool FSPanelSearchLand::postBuild() +{ + mSearchResults = getChild<LLScrollListCtrl>("search_results_land"); + mPriceEditor = findChild<LLLineEditor>("price_edit"); + mAreaEditor = findChild<LLLineEditor>("area_edit"); + if (mSearchResults) + { + mSearchResults->setCommitCallback(boost::bind(&FSPanelSearchLand::onSelectItem, this)); + mSearchResults->setEnabled(FALSE); + mSearchResults->setCommentText(LLTrans::getString("no_results")); + } + if (mPriceEditor) + { + mPriceEditor->setCommitOnFocusLost(false); + mPriceEditor->setCommitCallback(boost::bind(&FSPanelSearchLand::onBtnFind, this)); + } + if (mAreaEditor) + { + mAreaEditor->setCommitOnFocusLost(false); + mAreaEditor->setCommitCallback(boost::bind(&FSPanelSearchLand::find, this)); + } + childSetAction("land_find", boost::bind(&FSPanelSearchLand::onBtnFind, this)); + childSetAction("land_next", boost::bind(&FSPanelSearchLand::onBtnNext, this)); + childSetAction("land_back", boost::bind(&FSPanelSearchLand::onBtnBack, this)); + + getChildView("land_next")->setEnabled(FALSE); + getChildView("land_back")->setEnabled(FALSE); + + return TRUE; +} + +void FSPanelSearchLand::find() +{ + static LLUICachedControl<bool> inc_pg("ShowPGLand", 1); + static LLUICachedControl<bool> inc_mature("ShowMatureLand", 0); + static LLUICachedControl<bool> inc_adult("ShowAdultLand", 0); + static LLUICachedControl<bool> limit_price("FindLandPrice", 1); + static LLUICachedControl<bool> limit_area("FindLandArea", 1); + if (!(inc_pg || inc_mature || inc_adult)) + { + LLNotificationsUtil::add("NoContentToSearch"); + return; + } + + U32 category = ST_ALL; + const std::string& selection = findChild<LLComboBox>("land_category")->getSelectedValue().asString(); + if (!selection.empty()) + { + if (selection == "Auction") + { + category = ST_AUCTION; + } + else if (selection == "Mainland") + { + category = ST_MAINLAND; + } + else if (selection == "Estate") + { + category = ST_ESTATE; + } + } + + U32 scope = 0; + if (gAgent.wantsPGOnly()) + { + scope |= DFQ_PG_SIMS_ONLY; + } + bool mature_enabled = gAgent.canAccessMature(); + bool adult_enabled = gAgent.canAccessAdult(); + if (inc_pg) + { + scope |= DFQ_INC_PG; + } + if (inc_mature && mature_enabled) + { + scope |= DFQ_INC_MATURE; + } + if (inc_adult && adult_enabled) + { + scope |= DFQ_INC_ADULT; + } + const std::string& sort = findChild<LLComboBox>("land_sort_combo")->getSelectedValue().asString(); + if (!sort.empty()) + { + if (sort == "Name") + { + scope |= DFQ_NAME_SORT; + } + else if (sort == "Price") + { + scope |= DFQ_PRICE_SORT; + } + else if (sort == "PPM") + { + scope |= DFQ_PER_METER_SORT; + } + else if (sort == "Area") + { + scope |= DFQ_AREA_SORT; + } + } + else + { + scope |= DFQ_PRICE_SORT; + } + if (childGetValue("ascending_check").asBoolean()) + { + scope |= DFQ_SORT_ASC; + } + if (limit_price) + { + scope |= DFQ_LIMIT_BY_PRICE; + } + if (limit_area) + { + scope |= DFQ_LIMIT_BY_AREA; + } + S32 price = childGetValue("edit_price").asInteger(); + S32 area = childGetValue("edit_area").asInteger(); + + mResultsReceived = 0; + if (mQueryID.notNull()) + { + mQueryID.setNull(); + } + mQueryID.generate(); + + if (mStartSearch < 0) + { + mStartSearch = 0; + } + + gMessageSystem->newMessage("DirLandQuery"); + gMessageSystem->nextBlock("AgentData"); + gMessageSystem->addUUID("AgentID", gAgentID); + gMessageSystem->addUUID("SessionID", gAgentSessionID); + gMessageSystem->nextBlock("QueryData"); + gMessageSystem->addUUID("QueryID", getQueryID()); + gMessageSystem->addU32("QueryFlags", scope); + gMessageSystem->addU32("SearchType", category); + gMessageSystem->addS32("Price", price); + gMessageSystem->addS32("Area", area); + gMessageSystem->addS32("QueryStart", mStartSearch); + gAgent.sendReliableMessage(); + LL_DEBUGS("Search") << "Firing off places search request: " << getQueryID() << category << LL_ENDL; + + mSearchResults->deleteAllItems(); + mSearchResults->setCommentText(LLTrans::getString("searching")); + mNumResultsReturned = 0; +} + +void FSPanelSearchLand::onBtnFind() +{ + std::chrono::time_point<std::chrono::system_clock> now = std::chrono::system_clock::now(); + auto elapsed = now - lastRequestTime; + U64 elapsedMS = std::chrono::duration_cast<std::chrono::milliseconds>(elapsed).count(); + if(elapsedMS < REQUEST_MIN_ELAPSED_TIME) return; + lastRequestTime = now; + + resetSearch(); + + find(); +} + +void FSPanelSearchLand::onBtnNext() +{ + mStartSearch += RESULT_PAGE_SIZE; + getChildView("land_back")->setEnabled(TRUE); + + find(); +} + +void FSPanelSearchLand::onBtnBack() +{ + mStartSearch -= RESULT_PAGE_SIZE; + getChildView("land_back")->setEnabled(mStartSearch > 0); + + find(); +} + +void FSPanelSearchLand::resetSearch() +{ + mStartSearch = 0; + getChildView("land_back")->setEnabled(FALSE); + getChildView("land_next")->setEnabled(FALSE); +} + +S32 FSPanelSearchLand::showNextButton(S32 rows) +{ + bool show_next_button = (mResultsReceived > RESULT_PAGE_SIZE); + getChildView("land_next")->setEnabled(show_next_button); + if (show_next_button) + { + rows -= (mResultsReceived - RESULT_PAGE_SIZE); + } + return rows; +} + +void FSPanelSearchLand::onSelectItem() +{ + if (!mSearchResults) + { + return; + } + FSFloaterSearch* search_instance = LLFloaterReg::findTypedInstance<FSFloaterSearch>("search"); + if (search_instance) + { + search_instance->FSFloaterSearch::onSelectedItem(mSearchResults->getSelectedValue(), FSFloaterSearch::SC_PLACE); + } +} + +// static +void FSPanelSearchLand::processSearchReply(LLMessageSystem* msg, void**) +{ + LLUUID agent_id; + LLUUID query_id; + LLUUID parcel_id; + std::string name; + std::string land_sku; + std::string land_type; + bool auction; + bool for_sale; + S32 price; + S32 area; + + msg->getUUID("AgentData", "AgentID", agent_id); + msg->getUUID("QueryData", "QueryID", query_id); + + // Not for us + if (agent_id != gAgentID) + { + return; + } + LL_DEBUGS("Search") << "received directory request - QueryID: " << query_id << " AgentID: " << agent_id << LL_ENDL; + + FSPanelSearchLand* self = FSFloaterSearch::getSearchPanel<FSPanelSearchLand>("panel_ls_land"); + + // floater is closed or these are not results from our last request + if (!self || query_id != self->mQueryID) + { + return; + } + + LLScrollListCtrl* search_results = self->getChild<LLScrollListCtrl>("search_results_land"); + // clear "Searching" label on first results + if (self->mNumResultsReturned++ == 0) + { + search_results->deleteAllItems(); + } + + static LLUICachedControl<bool> use_price("FindLandPrice", 1); + static LLUICachedControl<bool> use_area("FindLandArea", 1); + S32 limit_price = self->childGetValue("edit_price").asInteger(); + S32 limit_area = self->childGetValue("edit_area").asInteger(); + + bool found_one = false; + S32 num_new_rows = msg->getNumberOfBlocks("QueryReplies"); + if (num_new_rows == 0 && self->mResultsReceived == 0) + { + LLStringUtil::format_map_t map; + map["[TEXT]"] = self->getChild<LLUICtrl>("events_edit")->getValue().asString(); + search_results->setEnabled(FALSE); + search_results->setCommentText(LLTrans::getString("not_found", map)); + } + self->mResultsReceived += num_new_rows; + + S32 not_auction = 0; + for (S32 i = 0; i < num_new_rows; i++) + { + msg->getUUID( "QueryReplies", "ParcelID", parcel_id, i); + msg->getString( "QueryReplies", "Name", name, i); + msg->getBOOL( "QueryReplies", "Auction", auction, i); + msg->getBOOL( "QueryReplies", "ForSale", for_sale, i); + msg->getS32( "QueryReplies", "SalePrice", price, i); + msg->getS32( "QueryReplies", "ActualArea", area, i); + if (parcel_id.isNull()) + { + LL_DEBUGS("Search") << "Null result returned for QueryID: " << query_id << LL_ENDL; + search_results->setEnabled(FALSE); + search_results->setCommentText(LLTrans::getString("no_results")); + } + else + { + LL_DEBUGS("Search") << "Got: " << name << " ClassifiedID: " << parcel_id << LL_ENDL; + search_results->setEnabled(TRUE); + found_one = true; + if (msg->getSizeFast(_PREHASH_QueryReplies, i, _PREHASH_ProductSKU) > 0) + { + msg->getStringFast( _PREHASH_QueryReplies, _PREHASH_ProductSKU, land_sku, i); + land_type = LLProductInfoRequestManager::instance().getDescriptionForSku(land_sku); + } + else + { + land_sku.clear(); + land_type = LLTrans::getString("land_type_unknown"); + } + if (parcel_id.isNull()) + { + continue; + } + if (use_price && (price > limit_price)) + { + continue; + } + if (use_area && (area < limit_area)) + { + continue; + } + + LLSD content; + LLSD element; + + element["id"] = parcel_id; + if (auction) + { + element["columns"][0]["column"] = "icon"; + element["columns"][0]["type"] = "icon"; + element["columns"][0]["value"] = "Icon_Auction"; + } + else if (for_sale) + { + element["columns"][0]["column"] = "icon"; + element["columns"][0]["type"] = "icon"; + element["columns"][0]["value"] = "Icon_For_Sale"; + } + else + { + element["columns"][0]["column"] = "icon"; + element["columns"][0]["type"] = "icon"; + element["columns"][0]["value"] = "Icon_Place"; + } + + element["columns"][1]["column"] = "land_name"; + element["columns"][1]["value"] = name; + + content["place_name"] = name; + + std::string buffer = "Auction"; + if (!auction) + { + buffer = llformat("%d", price); + not_auction++; + } + element["columns"][2]["column"] = "price"; + element["columns"][2]["value"] = price; + + element["columns"][3]["column"] = "area"; + element["columns"][3]["value"] = area; + if (!auction) + { + F32 ppm; + if (area > 0) + { + ppm = (F32)price / (F32)area; + } + else + { + ppm = 0.f; + } + std::string ppm_buffer = llformat("%.1f", ppm); + element["columns"][4]["column"] = "ppm"; + element["columns"][4]["value"] = ppm_buffer; + } + else + { + element["columns"][4]["column"] = "ppm"; + element["columns"][4]["value"] = "1.0"; + } + + element["columns"][5]["column"] = "land_type"; + element["columns"][5]["value"] = land_type; + + search_results->addElement(element, ADD_BOTTOM); + self->mResultsContent[parcel_id.asString()] = content; + } + // We test against non-auction properties because they don't count towards the page limit. + self->showNextButton(not_auction); + } + if (found_one) + { + search_results->selectFirstItem(); + search_results->setFocus(TRUE); + self->onSelectItem(); + } +} + +//////////////////////////////////////// +// Classifieds Search Panel // +//////////////////////////////////////// + +static LLPanelInjector<FSPanelSearchClassifieds> t_panel_fs_search_classifieds("panel_ls_classifieds"); + +FSPanelSearchClassifieds::FSPanelSearchClassifieds() : FSSearchPanelBase() +, mQueryID(nullptr) +, mStartSearch(0) +, mResultsReceived(0) +, mResultsContent() +{ + mCommitCallbackRegistrar.add("CommitSearch", boost::bind(&FSPanelSearchClassifieds::find, this)); +} + +FSPanelSearchClassifieds::~FSPanelSearchClassifieds() +{ +} + +bool FSPanelSearchClassifieds::postBuild() +{ + mSearchComboBox = findChild<LLSearchComboBox>("classifieds_edit"); + mSearchResults = getChild<LLScrollListCtrl>("search_results_classifieds"); + if (mSearchComboBox) + { + mSearchComboBox->setCommitCallback(boost::bind(&FSPanelSearchClassifieds::onBtnFind, this)); + fillSearchComboBox(mSearchComboBox); + } + if (mSearchResults) + { + mSearchResults->setCommitCallback(boost::bind(&FSPanelSearchClassifieds::onSelectItem, this)); + mSearchResults->setEnabled(FALSE); + mSearchResults->setCommentText(LLTrans::getString("no_results")); + } + + mClassifiedsCategory = getChild<LLComboBox>("classifieds_category"); + if (mClassifiedsCategory) + { + LLClassifiedInfo::cat_map::iterator iter; + mClassifiedsCategory->add(LLTrans::getString("all_categories"), LLSD(0)); + mClassifiedsCategory->addSeparator(); + for (iter = LLClassifiedInfo::sCategories.begin(); + iter != LLClassifiedInfo::sCategories.end(); + iter++) + { + mClassifiedsCategory->add(LLTrans::getString(iter->second), LLSD((S32)iter->first)); + } + } + childSetAction("classifieds_next", boost::bind(&FSPanelSearchClassifieds::onBtnNext, this)); + childSetAction("classifieds_back", boost::bind(&FSPanelSearchClassifieds::onBtnBack, this)); + + getChildView("classifieds_next")->setEnabled(FALSE); + getChildView("classifieds_back")->setEnabled(FALSE); + + return TRUE; +} + +void FSPanelSearchClassifieds::focusDefaultElement() +{ + mSearchComboBox->focusTextEntry(); +} + +void FSPanelSearchClassifieds::find() +{ + std::string text = filterShortWords(mSearchComboBox->getSimple()); + if (text.size() == 0) + { + mSearchResults->setCommentText(LLTrans::getString("search_short")); + return; + } + + static LLUICachedControl<bool> inc_pg("ShowPGClassifieds", 1); + static LLUICachedControl<bool> inc_mature("ShowMatureClassifieds", 0); + static LLUICachedControl<bool> inc_adult("ShowAdultClassifieds", 0); + if (!(inc_pg || inc_mature || inc_adult)) + { + LLNotificationsUtil::add("NoContentToSearch"); + return; + } + U32 category = mClassifiedsCategory->getValue().asInteger(); + bool auto_renew = FALSE; + U32 flags = pack_classified_flags_request(auto_renew, inc_pg, inc_mature, inc_adult); + + mResultsReceived = 0; + if (mQueryID.notNull()) + { + mQueryID.setNull(); + } + mQueryID.generate(); + + if (mStartSearch < 0) + { + mStartSearch = 0; + } + + gMessageSystem->newMessageFast(_PREHASH_DirClassifiedQuery); + gMessageSystem->nextBlockFast(_PREHASH_AgentData); + gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgentID); + gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgentSessionID); + gMessageSystem->nextBlockFast(_PREHASH_QueryData); + gMessageSystem->addUUIDFast(_PREHASH_QueryID, getQueryID()); + gMessageSystem->addStringFast(_PREHASH_QueryText, text); + gMessageSystem->addU32Fast(_PREHASH_QueryFlags, flags); + gMessageSystem->addU32Fast(_PREHASH_Category, category); + gMessageSystem->addS32Fast(_PREHASH_QueryStart, mStartSearch); + gAgent.sendReliableMessage(); + LL_DEBUGS("Search") << "Firing off classified ad search request: " << getQueryID() << LL_ENDL; + + mSearchResults->deleteAllItems(); + mSearchResults->setCommentText(LLTrans::getString("searching")); + mNumResultsReturned = 0; +} + +void FSPanelSearchClassifieds::onBtnFind() +{ + std::chrono::time_point<std::chrono::system_clock> now = std::chrono::system_clock::now(); + auto elapsed = now - lastRequestTime; + U64 elapsedMS = std::chrono::duration_cast<std::chrono::milliseconds>(elapsed).count(); + if(elapsedMS < REQUEST_MIN_ELAPSED_TIME) return; + lastRequestTime = now; + + std::string text = mSearchComboBox->getSimple(); + if (!text.empty()) + { + LLSearchHistory::getInstance()->addEntry(text); + } + + resetSearch(); + + find(); +} + +void FSPanelSearchClassifieds::onBtnNext() +{ + mStartSearch += RESULT_PAGE_SIZE; + getChildView("classifieds_back")->setEnabled(TRUE); + + find(); +} + +void FSPanelSearchClassifieds::onBtnBack() +{ + mStartSearch -= RESULT_PAGE_SIZE; + getChildView("classifieds_back")->setEnabled(mStartSearch > 0); + + find(); +} + +void FSPanelSearchClassifieds::resetSearch() +{ + mStartSearch = 0; + getChildView("classifieds_back")->setEnabled(FALSE); + getChildView("classifieds_next")->setEnabled(FALSE); +} + +S32 FSPanelSearchClassifieds::showNextButton(S32 rows) +{ + bool show_next_button = (mResultsReceived > RESULT_PAGE_SIZE); + getChildView("classifieds_next")->setEnabled(show_next_button); + if (show_next_button) + { + rows -= (mResultsReceived - RESULT_PAGE_SIZE); + } + return rows; +} + +void FSPanelSearchClassifieds::onSelectItem() +{ + if (!mSearchResults) + { + return; + } + FSFloaterSearch* search_instance = LLFloaterReg::findTypedInstance<FSFloaterSearch>("search"); + if (search_instance) + { + search_instance->FSFloaterSearch::onSelectedItem(mSearchResults->getSelectedValue(), FSFloaterSearch::SC_CLASSIFIED); + } +} + +// static +void FSPanelSearchClassifieds::processSearchReply(LLMessageSystem* msg, void**) +{ + LLUUID agent_id; + LLUUID query_id; + LLUUID classified_id; + std::string name; + U32 creation_date; + U32 expiration_date; + S32 price_for_listing; + + msg->getUUID("AgentData", "AgentID", agent_id); + msg->getUUID("QueryData", "QueryID", query_id); + + // Not for us + if (agent_id != gAgentID) + { + return; + } + LL_DEBUGS("Search") << "received directory request - QueryID: " << query_id << " AgentID: " << agent_id << LL_ENDL; + + FSPanelSearchClassifieds* self = FSFloaterSearch::getSearchPanel<FSPanelSearchClassifieds>("panel_ls_classifieds"); + + if (msg->getNumberOfBlocks("StatusData")) + { + U32 status; + msg->getU32("StatusData", "Status", status); + if (status & STATUS_SEARCH_CLASSIFIEDS_BANNEDWORD) + { + LLNotificationsUtil::add("SearchWordBanned"); + } + } + + // floater is closed or these are not results from our last request + if (!self || query_id != self->mQueryID) + { + return; + } + + LLScrollListCtrl* search_results = self->getChild<LLScrollListCtrl>("search_results_classifieds"); + + // Clear "Searching" label on first results + if (self->mNumResultsReturned++ == 0) + { + search_results->deleteAllItems(); + } + + // Check for status messages + if (msg->getNumberOfBlocks("StatusData")) + { + U32 status; + msg->getU32("StatusData", "Status", status); + if (status & STATUS_SEARCH_PLACES_FOUNDNONE) + { + LLStringUtil::format_map_t map; + map["[TEXT]"] = self->getChild<LLUICtrl>("classifieds_edit")->getValue().asString(); + search_results->setEnabled(FALSE); + search_results->setCommentText(LLTrans::getString("not_found", map)); + return; + } + else if(status & STATUS_SEARCH_PLACES_SHORTSTRING) + { + search_results->setEnabled(FALSE); + search_results->setCommentText(LLTrans::getString("search_short")); + return; + } + else if (status & STATUS_SEARCH_CLASSIFIEDS_BANNEDWORD) + { + search_results->setEnabled(FALSE); + search_results->setCommentText(LLTrans::getString("search_banned")); + return; + } + else if (status & STATUS_SEARCH_PLACES_SEARCHDISABLED) + { + search_results->setEnabled(FALSE); + search_results->setCommentText(LLTrans::getString("search_disabled")); + return; + } + } + + bool found_one = false; + S32 num_new_rows = msg->getNumberOfBlocks("QueryReplies"); + if (num_new_rows == 0 && self->mResultsReceived == 0) + { + LLStringUtil::format_map_t map; + map["[TEXT]"] = self->getChild<LLUICtrl>("classifieds_edit")->getValue().asString(); + search_results->setEnabled(FALSE); + search_results->setCommentText(LLTrans::getString("not_found", map)); + } + self->mResultsReceived += num_new_rows; + num_new_rows = self->showNextButton(num_new_rows); + + for (S32 i = 0; i < num_new_rows; i++) + { + msg->getUUID( "QueryReplies", "ClassifiedID", classified_id, i); + msg->getString( "QueryReplies", "Name", name, i); + msg->getU32( "QueryReplies", "CreationDate", creation_date, i); + msg->getU32( "QueryReplies", "ExpirationDate", expiration_date,i); + msg->getS32( "QueryReplies", "PriceForListing", price_for_listing,i); + if (classified_id.isNull()) + { + LL_DEBUGS("Search") << "Null result returned for QueryID: " << query_id << LL_ENDL; + LLStringUtil::format_map_t map; + map["[TEXT]"] = self->getChild<LLUICtrl>("classifieds_edit")->getValue().asString(); + search_results->setEnabled(FALSE); + search_results->setCommentText(LLTrans::getString("not_found", map)); + } + else + { + LL_DEBUGS("Search") << "Got: " << name << " ClassifiedID: " << classified_id << LL_ENDL; + search_results->setEnabled(TRUE); + found_one = true; + + LLSD content; + LLSD element; + + element["id"] = classified_id; + + element["columns"][0]["column"] = "icon"; + element["columns"][0]["type"] = "icon"; + element["columns"][0]["value"] = "icon_top_pick.tga"; + + element["columns"][1]["column"] = "classified_name"; + element["columns"][1]["value"] = name; + + element["columns"][2]["column"] = "price"; + element["columns"][2]["value"] = price_for_listing; + + content["name"] = name; + + search_results->addElement(element, ADD_BOTTOM); + self->mResultsContent[classified_id.asString()] = content; + } + } + if (found_one) + { + search_results->selectFirstItem(); + search_results->setFocus(TRUE); + self->onSelectItem(); + } +} + +//////////////////////////////////////// +// Events Search Panel // +//////////////////////////////////////// + +static LLPanelInjector<FSPanelSearchEvents> t_panel_fs_search_events("panel_ls_events"); + +FSPanelSearchEvents::FSPanelSearchEvents() : FSSearchPanelBase() +, mQueryID(nullptr) +, mResultsReceived(0) +, mStartSearch(0) +, mDay(0) +, mResultsContent() +{ + mCommitCallbackRegistrar.add("CommitSearch", boost::bind(&FSPanelSearchEvents::find, this)); +} + +FSPanelSearchEvents::~FSPanelSearchEvents() +{ +} + +bool FSPanelSearchEvents::postBuild() +{ + mSearchComboBox = findChild<LLSearchComboBox>("events_edit"); + mSearchResults = getChild<LLScrollListCtrl>("search_results_events"); + mEventsMode = findChild<LLRadioGroup>("events_search_mode"); + if (mSearchComboBox) + { + mSearchComboBox->setCommitCallback(boost::bind(&FSPanelSearchEvents::onBtnFind, this)); + fillSearchComboBox(mSearchComboBox); + } + if (mSearchResults) + { + mSearchResults->setCommitCallback(boost::bind(&FSPanelSearchEvents::onSelectItem, this)); + mSearchResults->setEnabled(FALSE); + mSearchResults->setCommentText(LLTrans::getString("no_results")); + } + if (mEventsMode) + { + mEventsMode->setCommitCallback(boost::bind(&FSPanelSearchEvents::onSearchModeChanged, this)); + mEventsMode->selectFirstItem(); + } + + childSetAction("events_next", boost::bind(&FSPanelSearchEvents::onBtnNext, this)); + childSetAction("events_back", boost::bind(&FSPanelSearchEvents::onBtnBack, this)); + childSetAction("events_tomorrow", boost::bind(&FSPanelSearchEvents::onBtnTomorrow, this)); + childSetAction("events_yesterday", boost::bind(&FSPanelSearchEvents::onBtnYesterday, this)); + childSetAction("events_today", boost::bind(&FSPanelSearchEvents::onBtnToday, this)); + + getChildView("events_next")->setEnabled(FALSE); + getChildView("events_back")->setEnabled(FALSE); + getChildView("events_tomorrow")->setEnabled(FALSE); + getChildView("events_yesterday")->setEnabled(FALSE); + getChildView("events_today")->setEnabled(FALSE); + setDay(0); + + return TRUE; +} + +void FSPanelSearchEvents::focusDefaultElement() +{ + mSearchComboBox->focusTextEntry(); +} + +void FSPanelSearchEvents::find() +{ + std::string text = filterShortWords(mSearchComboBox->getSimple()); + + static LLUICachedControl<bool> inc_pg("ShowPGEvents", 1); + static LLUICachedControl<bool> inc_mature("ShowMatureEvents", 0); + static LLUICachedControl<bool> inc_adult("ShowAdultEvents", 0); + if (!(inc_pg || inc_mature || inc_adult)) + { + LLNotificationsUtil::add("NoContentToSearch"); + return; + } + + U32 category = findChild<LLComboBox>("events_category")->getSelectedValue().asInteger(); + U32 scope = DFQ_DATE_EVENTS; + if (gAgent.wantsPGOnly()) + { + scope |= DFQ_PG_SIMS_ONLY; + } + bool mature_enabled = gAgent.canAccessMature(); + bool adult_enabled = gAgent.canAccessAdult(); + if (inc_pg) + { + scope |= DFQ_INC_PG; + } + if (inc_mature && mature_enabled) + { + scope |= DFQ_INC_MATURE; + } + if (inc_adult && adult_enabled) + { + scope |= DFQ_INC_ADULT; + } + + std::ostringstream string; + + if ("current" == childGetValue("events_search_mode").asString()) + { + string << "u|"; + } + else + { + string << mDay << "|"; + } + string << category << "|"; + string << text; + + mResultsReceived = 0; + if (mQueryID.notNull()) + { + mQueryID.setNull(); + } + mQueryID.generate(); + + if (mStartSearch < 0) + { + mStartSearch = 0; + } + + gMessageSystem->newMessage("DirFindQuery"); + gMessageSystem->nextBlock("AgentData"); + gMessageSystem->addUUID("AgentID", gAgentID); + gMessageSystem->addUUID("SessionID", gAgentSessionID); + gMessageSystem->nextBlock("QueryData"); + gMessageSystem->addUUID("QueryID", getQueryID()); + gMessageSystem->addString("QueryText", string.str()); + gMessageSystem->addU32("QueryFlags", scope); + gMessageSystem->addS32("QueryStart", mStartSearch); + gAgent.sendReliableMessage(); + LL_INFOS("Search") << "Firing off search request: " << getQueryID() << " Search Text: " << string.str() << LL_ENDL; + + mSearchResults->deleteAllItems(); + mSearchResults->setCommentText(LLTrans::getString("searching")); + mNumResultsReturned = 0; +} + +void FSPanelSearchEvents::onBtnFind() +{ + std::chrono::time_point<std::chrono::system_clock> now = std::chrono::system_clock::now(); + auto elapsed = now - lastRequestTime; + U64 elapsedMS = std::chrono::duration_cast<std::chrono::milliseconds>(elapsed).count(); + if(elapsedMS < REQUEST_MIN_ELAPSED_TIME) return; + lastRequestTime = now; + + std::string text = mSearchComboBox->getSimple(); + if (!text.empty()) + { + LLSearchHistory::getInstance()->addEntry(text); + } + + resetSearch(); + + find(); +} + +void FSPanelSearchEvents::onBtnNext() +{ + mStartSearch += RESULT_PAGE_SIZE; + getChildView("events_back")->setEnabled(TRUE); + + find(); +} + +void FSPanelSearchEvents::onBtnBack() +{ + mStartSearch -= RESULT_PAGE_SIZE; + getChildView("events_back")->setEnabled(mStartSearch > 0); + + find(); +} + +void FSPanelSearchEvents::onBtnTomorrow() +{ + resetSearch(); + setDay(mDay + 1); + + find(); +} + +void FSPanelSearchEvents::onBtnYesterday() +{ + resetSearch(); + setDay(mDay - 1); + + find(); +} + +void FSPanelSearchEvents::onBtnToday() +{ + resetSearch(); + setDay(0); + + find(); +} + +void FSPanelSearchEvents::resetSearch() +{ + mStartSearch = 0; + getChildView("events_back")->setEnabled(FALSE); + getChildView("events_next")->setEnabled(FALSE); +} + +void FSPanelSearchEvents::onSearchModeChanged() +{ + if (mEventsMode->getValue().asString() == "current") + { + getChildView("events_yesterday")->setEnabled(FALSE); + getChildView("events_tomorrow")->setEnabled(FALSE); + getChildView("events_today")->setEnabled(FALSE); + } + else + { + getChildView("events_yesterday")->setEnabled(TRUE); + getChildView("events_tomorrow")->setEnabled(TRUE); + getChildView("events_today")->setEnabled(TRUE); + } +} + +void FSPanelSearchEvents::setDay(S32 day) +{ + mDay = day; + struct tm* internal_time; + + time_t utc = time_corrected(); + utc += day * 24 * 60 * 60; + internal_time = utc_to_pacific_time(utc, is_daylight_savings()); + std::string buffer = llformat("%d/%d", 1 + internal_time->tm_mon, internal_time->tm_mday); + childSetValue("events_date", buffer); +} + +S32 FSPanelSearchEvents::showNextButton(S32 rows) +{ + bool show_next_button = (mResultsReceived > RESULT_PAGE_SIZE); + getChildView("events_next")->setEnabled(show_next_button); + if (show_next_button) + { + rows -= (mResultsReceived - RESULT_PAGE_SIZE); + } + return rows; +} + +void FSPanelSearchEvents::onSelectItem() +{ + if (!mSearchResults) + { + return; + } + S32 event_id = mSearchResults->getSelectedValue(); + FSFloaterSearch* search_instance = LLFloaterReg::findTypedInstance<FSFloaterSearch>("search"); + if (search_instance) + { + search_instance->FSFloaterSearch::onSelectedEvent(event_id); + } +} + +// static +void FSPanelSearchEvents::processSearchReply(LLMessageSystem* msg, void**) +{ + LLUUID agent_id; + LLUUID query_id; + LLUUID owner_id; + std::string name; + std::string date; + + msg->getUUID("AgentData", "AgentID", agent_id); + msg->getUUID("QueryData", "QueryID", query_id); + + // Not for us + if (agent_id != gAgentID) + { + return; + } + LL_DEBUGS("Search") << "received directory request - QueryID: " << query_id << " AgentID: " << agent_id << LL_ENDL; + + FSPanelSearchEvents* self = FSFloaterSearch::getSearchPanel<FSPanelSearchEvents>("panel_ls_events"); + + // floater is closed or these are not results from our last request + if (!self || query_id != self->mQueryID) + { + return; + } + + LLScrollListCtrl* search_results = self->getChild<LLScrollListCtrl>("search_results_events"); + + // Clear "Searching" label on first results + if (self->mNumResultsReturned++ == 0) + { + search_results->deleteAllItems(); + } + // Check for status messages + if (msg->getNumberOfBlocks("StatusData")) + { + U32 status; + msg->getU32("StatusData", "Status", status); + if (status & STATUS_SEARCH_EVENTS_FOUNDNONE) + { + LLStringUtil::format_map_t map; + map["[TEXT]"] = self->getChild<LLUICtrl>("events_edit")->getValue().asString(); + search_results->setEnabled(FALSE); + search_results->setCommentText(LLTrans::getString("not_found", map)); + return; + } + else if(status & STATUS_SEARCH_EVENTS_SHORTSTRING) + { + search_results->setEnabled(FALSE); + search_results->setCommentText(LLTrans::getString("search_short")); + return; + } + else if (status & STATUS_SEARCH_EVENTS_BANNEDWORD) + { + search_results->setEnabled(FALSE); + search_results->setCommentText(LLTrans::getString("search_banned")); + return; + } + else if (status & STATUS_SEARCH_EVENTS_SEARCHDISABLED) + { + search_results->setEnabled(FALSE); + search_results->setCommentText(LLTrans::getString("search_disabled")); + return; + } + else if (status & STATUS_SEARCH_EVENTS_NODATEOFFSET) + { + search_results->setEnabled(FALSE); + search_results->setCommentText(LLTrans::getString("search_no_date_offset")); + return; + } + else if (status & STATUS_SEARCH_EVENTS_NOCATEGORY) + { + search_results->setEnabled(FALSE); + search_results->setCommentText(LLTrans::getString("search_no_events_category")); + return; + } + else if (status & STATUS_SEARCH_EVENTS_NOQUERY) + { + search_results->setEnabled(FALSE); + search_results->setCommentText(LLTrans::getString("search_no_query")); + return; + } + } + + S32 num_new_rows = msg->getNumberOfBlocks("QueryReplies"); + if (num_new_rows == 0 && self->mResultsReceived == 0) + { + LLStringUtil::format_map_t map; + map["[TEXT]"] = self->getChild<LLUICtrl>("events_edit")->getValue().asString(); + search_results->setEnabled(FALSE); + search_results->setCommentText(LLTrans::getString("not_found", map)); + } + + self->mResultsReceived += num_new_rows; + num_new_rows = self->showNextButton(num_new_rows); + static LLUICachedControl<bool> inc_pg("ShowPGEvents", 1); + static LLUICachedControl<bool> inc_mature("ShowMatureEvents", 0); + static LLUICachedControl<bool> inc_adult("ShowAdultEvents", 0); + bool found_one = false; + + for (S32 i = 0; i < num_new_rows; i++) + { + U32 event_id; + U32 unix_time; + U32 event_flags; + + msg->getUUID( "QueryReplies", "OwnerID", owner_id, i); + msg->getString( "QueryReplies", "Name", name, i); + msg->getU32( "QueryReplies", "EventID", event_id, i); + msg->getString( "QueryReplies", "Date", date, i); + msg->getU32( "QueryReplies", "UnixTime", unix_time, i); + msg->getU32( "QueryReplies", "EventFlags", event_flags,i); + + // Skip empty events... + if (owner_id.isNull()) + { + LL_INFOS("Search") << "Skipped " << event_id << " because of a nullptr owner result" << LL_ENDL; + continue; + } + // Skips events that don't match our scope... + if (((event_flags & (EVENT_FLAG_ADULT | EVENT_FLAG_MATURE)) == EVENT_FLAG_NONE) && !inc_pg) + { + LL_INFOS("Search") << "Skipped " << event_id << " because it was out of scope" << LL_ENDL; + continue; + } + if ((event_flags & EVENT_FLAG_MATURE) && !inc_mature) + { + LL_INFOS("Search") << "Skipped " << event_id << " because it was out of scope" << LL_ENDL; + continue; + } + if ((event_flags & EVENT_FLAG_ADULT) && !inc_adult) + { + LL_INFOS("Search") << "Skipped " << event_id << " because it was out of scope" << LL_ENDL; + continue; + } + search_results->setEnabled(TRUE); + found_one = true; + + LLSD content; + LLSD element; + + element["id"] = llformat("%u", event_id); + + if (event_flags == EVENT_FLAG_ADULT) + { + element["columns"][0]["column"] = "icon"; + element["columns"][0]["type"] = "icon"; + element["columns"][0]["value"] = "Icon_Legacy_Event_Adult"; + } + else if (event_flags == EVENT_FLAG_MATURE) + { + element["columns"][0]["column"] = "icon"; + element["columns"][0]["type"] = "icon"; + element["columns"][0]["value"] = "Icon_Legacy_Event_Mature"; + } + else + { + element["columns"][0]["column"] = "icon"; + element["columns"][0]["type"] = "icon"; + element["columns"][0]["value"] = "Icon_Legacy_Event_PG"; + } + element["columns"][1]["column"] = "name"; + element["columns"][1]["value"] = name; + + element["columns"][2]["column"] = "date"; + element["columns"][2]["value"] = date; + + element["columns"][3]["column"] = "time"; + element["columns"][3]["value"] = llformat("%u", unix_time); + + content["name"] = name; + content["event_id"] = (S32)event_id; + + search_results->addElement(element, ADD_BOTTOM); + std::string event = llformat("%u", event_id); + self->mResultsContent[event] = content; + } + if (found_one) + { + search_results->selectFirstItem(); + search_results->setFocus(TRUE); + self->onSelectItem(); + } +} + +//////////////////////////////////////// +// WebSearch Panel // +//////////////////////////////////////// + +static LLPanelInjector<FSPanelSearchWeb> t_panel_fs_search_web("panel_ls_web"); + +FSPanelSearchWeb::FSPanelSearchWeb() : FSSearchPanelBase() +, mWebBrowser(nullptr) +, mResetFocusOnLoad(false) +{ + // Second Life grids use a different URL format now + mCategoryPaths = LLSD::emptyMap(); + if (LLGridManager::getInstance()->isInSecondlife()) + { + // declare a map that transforms a category name into + // the parameter list that is used to search that category + mCategoryPaths["people"] = "collection_chosen=people"; + mCategoryPaths["places"] = "collection_chosen=places"; + mCategoryPaths["events"] = "collection_chosen=events"; + mCategoryPaths["groups"] = "collection_chosen=groups"; + mCategoryPaths["destinations"] = "collection_chosen=destinations"; + + mCategoryPaths["classifieds"] = "search_type=classified"; + mCategoryPaths["wiki"] = "search/wiki"; // not sure if this is still a thing in the new search + + mCategoryPaths["all"] = mCategoryPaths["people"].asString() + "&" + + mCategoryPaths["places"].asString() + "&" + + mCategoryPaths["events"].asString() + "&" + + mCategoryPaths["groups"].asString() + "&" + + mCategoryPaths["destinations"].asString(); + } + // OpenSim currently still uses the old URL format + else + { + // declare a map that transforms a category name into + // the URL suffix that is used to search that category + mCategoryPaths["all"] = "search"; + mCategoryPaths["people"] = "search/people"; + mCategoryPaths["places"] = "search/places"; + mCategoryPaths["events"] = "search/events"; + mCategoryPaths["groups"] = "search/groups"; + mCategoryPaths["wiki"] = "search/wiki"; + mCategoryPaths["destinations"] = "destinations"; + mCategoryPaths["classifieds"] = "classifieds"; + } +} + +bool FSPanelSearchWeb::postBuild() +{ + mWebBrowser = getChild<LLMediaCtrl>("search_browser"); + return TRUE; +} + +void FSPanelSearchWeb::loadURL(const SearchQuery &p) +{ + if (!mWebBrowser || !p.validateBlock()) + { + return; + } + + // CATEGORY is no longer used as part of the path on Second Life grids + LLSD subs = LLSD().with("CATEGORY", ""); + + // on OpenSim grids it probably is currently still being used, so keep the old behavior + if (!LLGridManager::getInstance()->isInSecondlife()) + { + // work out the subdir to use based on the requested category + LLSD subs = LLSD().with("CATEGORY", (mCategoryPaths.has(p.category.getValue()) ? mCategoryPaths[p.category.getValue()].asString() : mCategoryPaths["all"].asString())); + } + + // add the search query string + subs["QUERY"] = LLURI::escape(p.query.getValue()); + + // add the permissions token that login.cgi gave us + // We use "search_token", and fallback to "auth_token" if not present. + LLSD search_token = LLLoginInstance::getInstance()->getResponse("search_token"); + if (search_token.asString().empty()) + { + search_token = LLLoginInstance::getInstance()->getResponse("auth_token"); + } + subs["AUTH_TOKEN"] = search_token.asString(); + + // add the user's preferred maturity (can be changed via prefs) + std::string maturity; + + // on Second Life grids, the maturity level is now a "&maturity" parameter that's not in the provided search URL + if (LLGridManager::getInstance()->isInSecondlife()) + { + if (gAgent.prefersAdult()) + { + maturity = "gma"; // PG,Mature,Adult + } + else if (gAgent.prefersMature()) + { + maturity = "gm"; // PG,Mature + } + else + { + maturity = "g"; // PG + } + + // not used on the SL search anymore, so clear out the respective parameter + subs["MATURITY"] = ""; + } + // OpenSim probably still uses the old maturity variant, so keep the old behavior here + else + { + if (gAgent.prefersAdult()) + { + maturity = "42"; // PG,Mature,Adult + } + else if (gAgent.prefersMature()) + { + maturity = "21"; // PG,Mature + } + else + { + maturity = "13"; // PG + } + subs["MATURITY"] = maturity; + } + + // add the user's god status + subs["GODLIKE"] = gAgent.isGodlike() ? "1" : "0"; + + // Get the search URL and expand all of the substitutions + // (also adds things like [LANGUAGE], [VERSION], [OS], etc.) + + // add the maturity and category variables to the new Second Life search URL + //std::string url = gAgent.getRegion() != nullptr ? gAgent.getRegion()->getSearchServerURL() : gSavedSettings.getString(LLGridManager::getInstance()->isInOpenSim() ? "OpenSimSearchURL" : "SearchURL"); + + std::string url = gSavedSettings.getString("SearchURL"); + + if (LLGridManager::getInstance()->isInSecondlife()) + { + url.append("&maturity=" + maturity + "&" + mCategoryPaths[p.category.getValue()].asString()); + } + + url = LLWeb::expandURLSubstitutions(url, subs); + + // Finally, load the URL in the webpanel + mWebBrowser->navigateTo(url, HTTP_CONTENT_TEXT_HTML); +} + +void FSPanelSearchWeb::focusDefaultElement() +{ + mWebBrowser->setFocus(TRUE); +} + +void FSPanelSearchWeb::draw() +{ + if (mResetFocusOnLoad) + { + focusDefaultElement(); + mResetFocusOnLoad = false; + } + + FSSearchPanelBase::draw(); +} + +//////////////////////////////////////// +// Local functions // +//////////////////////////////////////// + +std::string filterShortWords(std::string query_string) +{ + if (query_string.length() < 1) + { + return ""; + } + + std::string final_query; + bool filtered = false; + boost::char_separator<char> sep(" "); + boost::tokenizer<boost::char_separator<char> > tokens(query_string, sep); + boost::tokenizer<boost::char_separator<char> >::iterator iter = tokens.begin(); + boost::tokenizer<boost::char_separator<char> >::iterator last = tokens.end(); + boost::tokenizer<boost::char_separator<char> >::iterator temp; + for (; iter != last; ++iter) + { + if ((*iter).length() > MIN_SEARCH_STRING_SIZE) + { + final_query.append((*iter)); + temp = iter; ++temp; + if (temp != last) + { + final_query.append(" "); + } + } + else + { + filtered = true; + } + } + + if (filtered) + { + LLSD args = LLSD().with("FINALQUERY", final_query); + LLNotificationsUtil::add("SeachFilteredOnShortWords", args); + } + + return final_query; +} + +void fillSearchComboBox(LLSearchComboBox* search_combo) +{ + if (search_combo == nullptr) + { + return; + } + + LLSearchHistory::getInstance()->load(); + + LLSearchHistory::search_history_list_t search_list = + LLSearchHistory::getInstance()->getSearchHistoryList(); + LLSearchHistory::search_history_list_t::const_iterator it = search_list.begin(); + for ( ; search_list.end() != it; ++it) + { + LLSearchHistory::LLSearchHistoryItem item = *it; + search_combo->add(item.search_query); + } +} diff --git a/indra/newview/fsfloatersearch.h b/indra/newview/fsfloatersearch.h new file mode 100644 index 0000000000..90e2a8cb89 --- /dev/null +++ b/indra/newview/fsfloatersearch.h @@ -0,0 +1,404 @@ +/** + * @file fsfloatersearch.h + * @brief Firestorm search definitions + * + * $LicenseInfo:firstyear=2012&license=fsviewerlgpl$ + * Phoenix Firestorm Viewer Source Code + * Copyright (C) 2012, Cinder Roxley <cinder.roxley@phoenixviewer.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * The Phoenix Firestorm Project, Inc., 1831 Oakwood Drive, Fairmont, Minnesota 56031-3225 USA + * http://www.firestormviewer.org + * $/LicenseInfo$ + */ + +#ifndef FS_FLOATERSEARCH_H +#define FS_FLOATERSEARCH_H + +#include "llfloater.h" +#include "lliconctrl.h" +#include "lltexteditor.h" +#include "lltexturectrl.h" +#include "llremoteparcelrequest.h" +#include "llavatarpropertiesprocessor.h" +#include "llgroupmgr.h" +#include "llavatarnamecache.h" +#include "llmediactrl.h" +#include "llradiogroup.h" +#include "llsearchcombobox.h" +#include "llscrolllistctrl.h" +#include "lltabcontainer.h" +#include "lleventnotifier.h" + +class FSSearchRemoteParcelInfoObserver; +class LLAvatarPropertiesObserver; +class LLGroupMgrObserver; +class LLSearchEditor; +class LLSearchComboBox; +class FSFloaterSearch; +class LLPanelProfile; +class FSScrollListCtrl; + +struct SearchQuery : public LLInitParam::Block<SearchQuery> +{ + Optional<std::string> category; + Optional<std::string> query; + + SearchQuery(); +}; + +/////////////////////////////// +// Search Panels // +/////////////////////////////// + +class FSSearchPanelBase : public LLPanel +{ +public: + FSSearchPanelBase() : LLPanel() { } + virtual ~FSSearchPanelBase() = default; + virtual void focusDefaultElement() { } +}; + +class FSPanelSearchPeople : public FSSearchPanelBase +{ + LOG_CLASS(FSFloaterSearch); +public: + FSPanelSearchPeople(); + static void processSearchReply(LLMessageSystem* msg, void**); + + /*virtual*/ void focusDefaultElement(); + +protected: + const S32& getNumResultsReturned() const { return mNumResultsReturned; }; + const S32& getNumResultsReceived() const { return mResultsReceived; }; + +private: + /*virtual*/ bool postBuild(); + virtual ~FSPanelSearchPeople(); + + void onBtnFind(); + void onSelectItem(); + void onBtnNext(); + void onBtnBack(); + + void find(); + void resetSearch(); + S32 showNextButton(S32); + + const LLUUID& getQueryID() const { return mQueryID; } + + void onAvatarNameCallback(const LLUUID& id, const LLAvatarName& av_name); + + typedef boost::signals2::connection avatar_name_callback_connection_t; + avatar_name_callback_connection_t mAvatarNameCallbackConnection; + + S32 mNumResultsReturned; + S32 mStartSearch; + S32 mResultsReceived; + LLSD mResultsContent; + LLUUID mQueryID; + + LLSearchComboBox* mSearchComboBox; + LLScrollListCtrl* mSearchResults; +}; + +class FSPanelSearchGroups : public FSSearchPanelBase +{ + LOG_CLASS(FSFloaterSearch); +public: + FSPanelSearchGroups(); + static void processSearchReply(LLMessageSystem* msg, void**); + + /*virtual*/ void focusDefaultElement(); + +private: + /*virtual*/ bool postBuild(); + virtual ~FSPanelSearchGroups(); + + void onBtnFind(); + void onSelectItem(); + void onBtnNext(); + void onBtnBack(); + + void find(); + void resetSearch(); + S32 showNextButton(S32); + + const LLUUID& getQueryID() const { return mQueryID; } + + S32 mNumResultsReturned; + S32 mStartSearch; + S32 mResultsReceived; + LLSD mResultsContent; + LLUUID mQueryID; + + LLSearchComboBox* mSearchComboBox; + LLScrollListCtrl* mSearchResults; +}; + +class FSPanelSearchPlaces : public FSSearchPanelBase +{ + LOG_CLASS(FSFloaterSearch); +public: + FSPanelSearchPlaces(); + static void processSearchReply(LLMessageSystem* msg, void**); + + /*virtual*/ void focusDefaultElement(); + +private: + /*virtual*/ bool postBuild(); + virtual ~FSPanelSearchPlaces(); + + void onBtnFind(); + void onSelectItem(); + void onBtnNext(); + void onBtnBack(); + + void find(); + void resetSearch(); + S32 showNextButton(S32); + + const LLUUID& getQueryID() const { return mQueryID; } + + S32 mNumResultsReturned; + S32 mStartSearch; + S32 mResultsReceived; + LLSD mResultsContent; + LLUUID mQueryID; + + LLSearchComboBox* mSearchComboBox; + LLScrollListCtrl* mSearchResults; + LLComboBox* mPlacesCategory; +}; + +class FSPanelSearchLand : public FSSearchPanelBase +{ + LOG_CLASS(FSFloaterSearch); +public: + FSPanelSearchLand(); + static void processSearchReply(LLMessageSystem* msg, void**); + +private: + /*virtual*/ bool postBuild(); + virtual ~FSPanelSearchLand(); + + void onBtnFind(); + void onSelectItem(); + void onBtnNext(); + void onBtnBack(); + + void find(); + void resetSearch(); + S32 showNextButton(S32); + + const LLUUID& getQueryID() const { return mQueryID; } + + S32 mNumResultsReturned; + S32 mStartSearch; + S32 mResultsReceived; + LLSD mResultsContent; + LLUUID mQueryID; + + LLLineEditor* mPriceEditor; + LLLineEditor* mAreaEditor; + LLScrollListCtrl* mSearchResults; +}; + +class FSPanelSearchClassifieds : public FSSearchPanelBase +{ + LOG_CLASS(FSFloaterSearch); +public: + FSPanelSearchClassifieds(); + static void processSearchReply(LLMessageSystem* msg, void**); + + /*virtual*/ void focusDefaultElement(); + +private: + /*virtual*/ bool postBuild(); + virtual ~FSPanelSearchClassifieds(); + + void onBtnFind(); + void onSelectItem(); + void onBtnNext(); + void onBtnBack(); + + void find(); + void resetSearch(); + S32 showNextButton(S32); + + const LLUUID& getQueryID() const { return mQueryID; } + + S32 mNumResultsReturned; + S32 mStartSearch; + S32 mResultsReceived; + LLSD mResultsContent; + LLUUID mQueryID; + + LLSearchComboBox* mSearchComboBox; + LLScrollListCtrl* mSearchResults; + LLComboBox* mClassifiedsCategory; +}; + +class FSPanelSearchEvents : public FSSearchPanelBase +{ + LOG_CLASS(FSFloaterSearch); +public: + FSPanelSearchEvents(); + static void processSearchReply(LLMessageSystem* msg, void**); + + /*virtual*/ void focusDefaultElement(); + +private: + /*virtual*/ bool postBuild(); + virtual ~FSPanelSearchEvents(); + + void onBtnFind(); + void onSelectItem(); + void onBtnNext(); + void onBtnBack(); + void onBtnTomorrow(); + void onBtnYesterday(); + void onBtnToday(); + + void find(); + void setDay(S32 day); + void onSearchModeChanged(); + void resetSearch(); + S32 showNextButton(S32); + + const LLUUID& getQueryID() const { return mQueryID; } + + S32 mNumResultsReturned; + S32 mResultsReceived; + S32 mStartSearch; + S32 mDay; + LLSD mResultsContent; + LLUUID mQueryID; + + LLSearchComboBox* mSearchComboBox; + LLScrollListCtrl* mSearchResults; + LLRadioGroup* mEventsMode; +}; + +class FSPanelSearchWeb : public FSSearchPanelBase +{ + LOG_CLASS(FSFloaterSearch); +public: + FSPanelSearchWeb(); + /*virtual*/ bool postBuild(); + void loadURL(const SearchQuery &query); + /*virtual*/ void focusDefaultElement(); + /*virtual*/ void draw(); + void resetFocusOnLoad() { mResetFocusOnLoad = true; } + +private: + virtual ~FSPanelSearchWeb() {}; + + LLMediaCtrl* mWebBrowser; + LLSD mCategoryPaths; + + bool mResetFocusOnLoad; +}; + +class FSFloaterSearch : public LLFloater +{ + LOG_CLASS(FSFloaterSearch); +public: + typedef enum e_search_category + { + SC_AVATAR, + SC_GROUP, + SC_PLACE, + SC_CLASSIFIED + } ESearchCategory; + + struct _Params : public LLInitParam::Block<_Params, LLFloater::Params> + { + Optional<SearchQuery> search; + }; + + typedef LLSDParamAdapter<_Params> Params; + + FSFloaterSearch(const Params& key); + ~FSFloaterSearch(); + void onOpen(const LLSD& key); + bool postBuild(); + + void avatarNameUpdatedCallback(const LLUUID& id, const LLAvatarName& av_name); + void groupNameUpdatedCallback(const LLUUID& id, const std::string& name, bool is_group); + void onSelectedItem(const LLUUID& selected_item, ESearchCategory type); + void onSelectedEvent(const S32 selected_event); + void displayParcelDetails(const LLParcelData& parcel_data); + void displayClassifiedDetails(LLAvatarClassifiedInfo*& c_info); + void displayAvatarDetails(LLAvatarData* avatar_data); + void displayGroupDetails(LLGroupMgrGroupData*& group_data); + bool displayEventDetails(LLEventStruct event); + void displayEventParcelImage(const LLParcelData& parcel_data); + void setLoadingProgress(bool started); + + template <class T> + static T* getSearchPanel(const std::string& panel_name); + +private: + virtual void onClose(bool app_quitting); + const LLUUID& getSelectedID() { return mSelectedID; } + LLVector3d mParcelGlobal; + LLUUID mSelectedID; + U32 mEventID; + bool mHasSelection; + + void resetVerbs(); + void flushDetails(); + void onTabChange(); + void onBtnPeopleProfile(); + void onBtnPeopleIM(); + void onBtnPeopleFriend(); + void onBtnGroupProfile(); + void onBtnGroupChat(); + void onBtnGroupJoin(); + void onBtnEventReminder(); + void onBtnTeleport(); + void onBtnMap(); + + void regionHandleCallback(U64 region_handle, LLVector3d pos_global); + + FSSearchRemoteParcelInfoObserver* mRemoteParcelObserver; + FSSearchRemoteParcelInfoObserver* mRemoteParcelEventLocationObserver; + LLAvatarPropertiesObserver* mAvatarPropertiesObserver; + LLGroupMgrObserver* mGroupPropertiesRequest; + boost::signals2::connection mEventNotifierConnection; + + FSPanelSearchPeople* mPanelPeople; + FSPanelSearchGroups* mPanelGroups; + FSPanelSearchPlaces* mPanelPlaces; + FSPanelSearchEvents* mPanelEvents; + FSPanelSearchLand* mPanelLand; + FSPanelSearchClassifieds* mPanelClassifieds; + FSPanelSearchWeb* mPanelWeb; + + LLPanel* mDetailsPanel; + LLTextEditor* mDetailTitle; + LLTextEditor* mDetailDesc; + LLTextEditor* mDetailAux1; + LLTextEditor* mDetailAux2; + LLTextEditor* mDetailLocation; + LLTextureCtrl* mDetailSnapshot; + LLTextureCtrl* mDetailSnapshotParcel; + LLIconCtrl* mDetailMaturity; + LLTabContainer* mTabContainer; +}; + +#endif // FS_FLOATERSEARCH_H diff --git a/indra/newview/gltf/asset.cpp b/indra/newview/gltf/asset.cpp index a454e68a92..24df41c6b3 100644 --- a/indra/newview/gltf/asset.cpp +++ b/indra/newview/gltf/asset.cpp @@ -903,7 +903,7 @@ bool Asset::save(const std::string& filename) // save .gltf object obj; serialize(obj); - std::string buffer = boost::json::serialize(obj, {}); + std::string buffer = boost::json::serialize(obj); std::ofstream file(filename, std::ios::binary); file.write(buffer.c_str(), buffer.size()); diff --git a/indra/newview/gltf/primitive.cpp b/indra/newview/gltf/primitive.cpp index e1579374d4..7613d81af4 100644 --- a/indra/newview/gltf/primitive.cpp +++ b/indra/newview/gltf/primitive.cpp @@ -32,7 +32,11 @@ #include "mikktspace/mikktspace.hh" +#if LL_USESYSTEMLIBS +#include <meshoptimizer.h> +#else #include "meshoptimizer/meshoptimizer.h" +#endif using namespace LL::GLTF; diff --git a/indra/newview/gltfscenemanager.cpp b/indra/newview/gltfscenemanager.cpp index 7b2de4d6de..f3be0e24b4 100644 --- a/indra/newview/gltfscenemanager.cpp +++ b/indra/newview/gltfscenemanager.cpp @@ -458,7 +458,7 @@ void GLTFSceneManager::update() { boost::json::object obj; mUploadingAsset->serialize(obj); - std::string buffer = boost::json::serialize(obj, {}); + std::string buffer = boost::json::serialize(obj); LLNewBufferedResourceUploadInfo::uploadFailure_f failure = [this](LLUUID assetId, LLSD response, std::string reason) { diff --git a/indra/newview/icons/hicolor/128x128/apps/megapahit.png b/indra/newview/icons/hicolor/128x128/apps/megapahit.png Binary files differnew file mode 100644 index 0000000000..5ed63802d3 --- /dev/null +++ b/indra/newview/icons/hicolor/128x128/apps/megapahit.png diff --git a/indra/newview/icons/hicolor/256x256/apps/megapahit.png b/indra/newview/icons/hicolor/256x256/apps/megapahit.png Binary files differnew file mode 100644 index 0000000000..07deb76090 --- /dev/null +++ b/indra/newview/icons/hicolor/256x256/apps/megapahit.png diff --git a/indra/newview/icons/hicolor/48x48/apps/megapahit.png b/indra/newview/icons/hicolor/48x48/apps/megapahit.png Binary files differnew file mode 100644 index 0000000000..3189bb2c3d --- /dev/null +++ b/indra/newview/icons/hicolor/48x48/apps/megapahit.png diff --git a/indra/newview/icons/hicolor/512x512/apps/megapahit.png b/indra/newview/icons/hicolor/512x512/apps/megapahit.png Binary files differnew file mode 100644 index 0000000000..fdbec7e739 --- /dev/null +++ b/indra/newview/icons/hicolor/512x512/apps/megapahit.png diff --git a/indra/newview/icons/hicolor/64x64/apps/megapahit.png b/indra/newview/icons/hicolor/64x64/apps/megapahit.png Binary files differnew file mode 100644 index 0000000000..4917b1a825 --- /dev/null +++ b/indra/newview/icons/hicolor/64x64/apps/megapahit.png diff --git a/indra/newview/icons/hicolor/96x96/apps/megapahit.png b/indra/newview/icons/hicolor/96x96/apps/megapahit.png Binary files differnew file mode 100644 index 0000000000..ffe9066f4a --- /dev/null +++ b/indra/newview/icons/hicolor/96x96/apps/megapahit.png diff --git a/indra/newview/installers/darwin/dmg-cleanup.applescript b/indra/newview/installers/darwin/dmg-cleanup.applescript index 8a71b392f9..866bf31e8f 100755 --- a/indra/newview/installers/darwin/dmg-cleanup.applescript +++ b/indra/newview/installers/darwin/dmg-cleanup.applescript @@ -4,25 +4,43 @@ tell application "Finder" - set foo to every item in front window - repeat with i in foo - if the name of i is "Applications" then - set the position of i to {391, 165} - else if the name of i ends with ".app" then - set the position of i to {121, 166} - end if - end repeat + -- set foo to every item in front window + -- repeat with i in foo + -- if the name of i is "Applications" then + -- set the position of i to {391, 165} + -- else if the name of i ends with ".app" then + -- set the position of i to {121, 166} + -- end if + -- end repeat -- There doesn't seem to be a way to set the background picture with applescript, but all the saved .DS_Store files should already have that set correctly. - set foo to front window - set current view of foo to icon view - set toolbar visible of foo to false - set statusbar visible of foo to false - set the bounds of foo to {100, 100, 600, 449} + -- set foo to front window + -- set current view of foo to icon view + -- set toolbar visible of foo to false + -- set statusbar visible of foo to false + -- set the bounds of foo to {100, 100, 600, 449} -- set the position of front window to {100, 100} -- get {name, position} of every item of front window - get properties of front window + -- get properties of front window + + tell disk "Megapahit Installer" + open + set current view of container window to icon view + set toolbar visible of container window to false + set statusbar visible of container window to false + set the bounds of container window to {400, 100, 900, 500} + set theViewOptions to the icon view options of container window + set arrangement of theViewOptions to not arranged + set icon size of theViewOptions to 128 + set background picture of theViewOptions to file ".background:background.jpg" + make new alias file at container window to POSIX file "/Applications" with properties {name:"Applications"} + set position of item "Megapahit" of container window to {125, 160} + set position of item "Applications" of container window to {375, 160} + update without registering applications + delay 5 + close + end tell end tell diff --git a/indra/newview/installers/darwin/release-dmg/_VolumeIcon.icns b/indra/newview/installers/darwin/release-dmg/_VolumeIcon.icns Binary files differindex 272b496e7d..1be2300130 100644 --- a/indra/newview/installers/darwin/release-dmg/_VolumeIcon.icns +++ b/indra/newview/installers/darwin/release-dmg/_VolumeIcon.icns diff --git a/indra/newview/installers/darwin/release-dmg/background.jpg b/indra/newview/installers/darwin/release-dmg/background.jpg Binary files differindex e7064d9545..41c2bc320b 100644 --- a/indra/newview/installers/darwin/release-dmg/background.jpg +++ b/indra/newview/installers/darwin/release-dmg/background.jpg diff --git a/indra/newview/licenses-linux.txt b/indra/newview/licenses-linux.txt index e53ba94a36..23dace4de0 100644 --- a/indra/newview/licenses-linux.txt +++ b/indra/newview/licenses-linux.txt @@ -1,21 +1,3 @@ -=========== -APR License -=========== - -Copyright 2000-2004 The Apache Software Foundation - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. - ============== Base32 License ============== @@ -69,43 +51,65 @@ NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +=========== +CEF License +=========== -Except as contained in this notice, the name of a copyright holder shall not -be used in advertising or otherwise to promote the sale, use or other dealings -in this Software without prior written authorization of the copyright holder. - +// Copyright (c) 2008-2020 Marshall A. Greenblatt. Portions Copyright (c) +// 2006-2009 Google Inc. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the name Chromium Embedded +// Framework nor the names of its contributors may be used to endorse +// or promote products derived from this software without specific prior +// written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -============= -expat License -============= -Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd +================ +Dullahan License +================ -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: +Copyright (c) 2016, Linden Research, Inc. -The above copyright notice and this permission notice shall be included -in all copies or substantial portions of the Software. +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. -================ -FreeType License -================ +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. -Portions of this software are copyright (c) 2003 The FreeType -Project (www.freetype.org). All rights reserved. ========================== FSI FontShop International @@ -126,10 +130,10 @@ obtain a license from FSI FontShop International at www.fontfont.com. GL License ========== -Mesa 3-D graphics library -Version: 6.2 +Mesa 3-D graphics library and Mesa Demos +Version: 6.2 and 8.5.0 -Copyright (C) 1999-2004 Brian Paul All Rights Reserved. +Copyright (C) 1999-2014 Brian Paul All Rights Reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -191,122 +195,50 @@ Redistribution and use in source and binary forms, with or Cass Everitt - cass@r3.nu -======================= -JPEG Library 6b License -======================= - -This software is based in part on the work of the Independent JPEG Group - ================ -JPEG2000 License +OpenJPEG License ================ -Copyright 2001, David Taubman, The University of New South Wales (UNSW) -The copyright owner is Unisearch Ltd, Australia (commercial arm of UNSW) -Neither this copyright statement, nor the licensing details below -may be removed from this file or dissociated from its contents. - -Licensee: Linden Research, Inc. -License number: 00024 -The licensee has been granted a COMMERCIAL license to the contents of -this source file. A brief summary of this license appears below. This -summary is not to be relied upon in preference to the full text of the -license agreement, accepted at purchase of the license. -1. The Licensee has the right to Commercial Use of the Kakadu software, - including distribution of one or more Applications built using the - software. -2. The Licensee has the right to Internal Use of the Kakadu software, - including use by employees of the Licensee or an Affiliate for the - purpose of performing services on behalf of the Licensee or Affiliate, - or in the performance of services for Third Parties who engage Licensee - or an Affiliate for such services. -3. The Licensee has the right to distribute Reusable Code (including - source code and dynamically or statically linked libraries) to a Third - Party, provided the Third Party possesses a license to use the Kakadu - software. - -================== -ogg/vorbis License -================== - -Copyright (c) 2001, Xiphophorus - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - -- Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - -- Redistributions in binary form must reproduce the above copyright -notice, this list of conditions and the following disclaimer in the -documentation and/or other materials provided with the distribution. - -- Neither the name of the Xiphophorus nor the names of its contributors -may be used to endorse or promote products derived from this software -without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR -CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - -=========== -SDL License -=========== - -SDL - Simple DirectMedia Layer -Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga - -This library is free software; you can redistribute it and/or -modify it under the terms of the GNU Library General Public -License as published by the Free Software Foundation; either -version 2 of the License, or (at your option) any later version. - -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 -Library General Public License for more details. - -You should have received a copy of the GNU Library General Public -License along with this library; if not, write to the Free -Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -Sam Lantinga -slouken@libsdl.org - -The GNU Library GPL is available at http://www.gnu.org/copyleft/lesser.html - -============= -ELFIO License -============= - -ELFIO.h - ELF reader and producer. -Copyright (C) 2001 Serge Lamikhov-Center <to_serge@users.sourceforge.net> - -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; either -version 2.1 of the License, or (at your option) any later version. - -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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +/* + * The copyright in this software is being made available under the 2-clauses + * BSD License, included below. This software may be subject to other third + * party and contributor rights, including patent rights, and no such rights + * are granted under this license. + * + * Copyright (c) 2002-2014, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2014, Professor Benoit Macq + * Copyright (c) 2003-2014, Antonin Descampe + * Copyright (c) 2003-2009, Francois-Olivier Devaux + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2011-2012, Centre National d'Etudes Spatiales (CNES), France + * Copyright (c) 2012, CS Systemes d'Information, France + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ -The GNU Library GPL is available at http://www.gnu.org/copyleft/lesser.html =============== OpenSSL License @@ -426,321 +358,6 @@ copied and put under another distribution licence [including the GNU Public Licence.] -================== -xmlrpc-epi License -================== - -Copyright 2000 Epinions, Inc. - -Subject to the following 3 conditions, Epinions, Inc. permits you, free of charge, to (a) use, copy, distribute, modify, perform and display this software and associated documentation files (the "Software"), and (b) permit others to whom the Software is furnished to do so as well. - -1) The above copyright notice and this permission notice shall be included without modification in all copies or substantial portions of the Software. - -2) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT ANY WARRANTY OR CONDITION OF ANY KIND, EXPRESS, IMPLIED OR STATUTORY, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OF ACCURACY, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT. - -3) IN NO EVENT SHALL EPINIONS, INC. BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES OR LOST PROFITS ARISING OUT OF OR IN CONNECTION WITH THE SOFTWARE (HOWEVER ARISING, INCLUDING NEGLIGENCE), EVEN IF EPINIONS, INC. IS AWARE OF THE POSSIBILITY OF SUCH DAMAGES. - - -=============== -libuuid License -=============== - -Copyright (C) 1999, 2000, 2003, 2004 by Theodore Ts'o - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: -1. Redistributions of source code must retain the above copyright - notice, and the entire permission notice in its entirety, - including the disclaimer of warranties. -2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. -3. The name of the author may not be used to endorse or promote - products derived from this software without specific prior - written permission. - -THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED -WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF -WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT -OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR -BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE -USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH -DAMAGE. - - -============ -zlib License -============ - -'zlib' general purpose compression library version 1.1.4, March 11th, 2002 - -Copyright (C) 1995-2002 Jean-loup Gailly and Mark Adler - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the -use of this software. - -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it -freely, subject to the following restrictions: - -The origin of this software must not be misrepresented; you must not claim -that you wrote the original software. If you use this software in a product, -an acknowledgment in the product documentation would be appreciated but is -not required. - -Altered source versions must be plainly marked as such, and must not be -misrepresented as being the original software. - -This notice may not be removed or altered from any source distribution. - -Jean-loup Gailly -jloup@gzip.org - -Mark Adler -madler@alumni.caltech.edu - -================================= -tcmalloc/Google perftools license -================================= - -Copyright (c) 2005, Google Inc. -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -============== -libpng license -============== - -COPYRIGHT NOTICE, DISCLAIMER, and LICENSE: - -If you modify libpng you may insert additional notices immediately following -this sentence. - -libpng versions 1.2.6, August 15, 2004, through 1.2.18, May 15, 2007, are -Copyright (c) 2004, 2006-2007 Glenn Randers-Pehrson, and are -distributed according to the same disclaimer and license as libpng-1.2.5 -with the following individual added to the list of Contributing Authors: - - Cosmin Truta - -libpng versions 1.0.7, July 1, 2000, through 1.2.5, October 3, 2002, are -Copyright (c) 2000-2002 Glenn Randers-Pehrson, and are -distributed according to the same disclaimer and license as libpng-1.0.6 -with the following individuals added to the list of Contributing Authors: - - Simon-Pierre Cadieux - Eric S. Raymond - Gilles Vollant - -and with the following additions to the disclaimer: - - There is no warranty against interference with your enjoyment of the - library or against infringement. There is no warranty that our - efforts or the library will fulfill any of your particular purposes - or needs. This library is provided with all faults, and the entire - risk of satisfactory quality, performance, accuracy, and effort is with - the user. - -libpng versions 0.97, January 1998, through 1.0.6, March 20, 2000, are -Copyright (c) 1998, 1999, 2000 Glenn Randers-Pehrson, and are -distributed according to the same disclaimer and license as libpng-0.96, -with the following individuals added to the list of Contributing Authors: - - Tom Lane - Glenn Randers-Pehrson - Willem van Schaik - -libpng versions 0.89, June 1996, through 0.96, May 1997, are -Copyright (c) 1996, 1997 Andreas Dilger -Distributed according to the same disclaimer and license as libpng-0.88, -with the following individuals added to the list of Contributing Authors: - - John Bowler - Kevin Bracey - Sam Bushell - Magnus Holmgren - Greg Roelofs - Tom Tanner - -libpng versions 0.5, May 1995, through 0.88, January 1996, are -Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc. - -For the purposes of this copyright and license, "Contributing Authors" -is defined as the following set of individuals: - - Andreas Dilger - Dave Martindale - Guy Eric Schalnat - Paul Schmidt - Tim Wegner - -The PNG Reference Library is supplied "AS IS". The Contributing Authors -and Group 42, Inc. disclaim all warranties, expressed or implied, -including, without limitation, the warranties of merchantability and of -fitness for any purpose. The Contributing Authors and Group 42, Inc. -assume no liability for direct, indirect, incidental, special, exemplary, -or consequential damages, which may result from the use of the PNG -Reference Library, even if advised of the possibility of such damage. - -Permission is hereby granted to use, copy, modify, and distribute this -source code, or portions hereof, for any purpose, without fee, subject -to the following restrictions: - -1. The origin of this source code must not be misrepresented. - -2. Altered versions must be plainly marked as such and -must not be misrepresented as being the original source. - -3. This Copyright notice may not be removed or altered from - any source or altered source distribution. - -The Contributing Authors and Group 42, Inc. specifically permit, without -fee, and encourage the use of this source code as a component to -supporting the PNG file format in commercial products. If you use this -source code in a product, acknowledgment is not required but would be -appreciated. - -================= -Vivox SDK License -================= - -RSA Data Security, Inc. MD5 Message-Digest Algorithm - -Audio coding: Polycom(R) Siren14TM (ITU-T Rec. G.722.1 Annex C) - -Open Source Software Licensing -Each open source software component utilized by this product is subject to its own copyright and licensing terms, as listed below. - - -************************************************************* -************************************************************* - -/** - * OpenAL cross platform audio library - * Copyright (C) 1999-2000 by authors. - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * Or go to http://www.gnu.org/copyleft/lgpl.html - */ - -************************************************************* -************************************************************* -RTP code under Lesser General Public License - -/* - The oRTP library is an RTP (Realtime Transport Protocol - rfc3550) stack. - Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org - - 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; either - version 2.1 of the License, or (at your option) any later version. - - 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -************************************************************ -************************************************************* - -/* - * The Vovida Software License, Version 1.0 - * - * Copyright (c) 2000 Vovida Networks, Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The names "VOCAL", "Vovida Open Communication Application Library", - * and "Vovida Open Communication Application Library (VOCAL)" must - * not be used to endorse or promote products derived from this - * software without prior written permission. For written - * permission, please contact vocal@vovida.org. - * - * 4. Products derived from this software may not be called "VOCAL", nor - * may "VOCAL" appear in their name, without prior written - * permission of Vovida Networks, Inc. - * - * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND - * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA - * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES - * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE - * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. - * - * - * This software consists of voluntary contributions made by Vovida - * Networks, Inc. and many individuals on behalf of Vovida Networks, - * Inc. For more information on Vovida Networks, Inc., please see - * - * - */ ************************************************************* ************************************************************* @@ -763,49 +380,54 @@ Internet Software Consortium code * SOFTWARE. */ -************************************************************* - -************************************************************* - -************************************************************ - -http://tinyxpath.sourceforge.net/ - -TinyXPath is covered by the zlib license : - - www.sourceforge.net/projects/tinyxpath - Copyright (c) 2002-2006 Yves Berquin (yvesb@users.sourceforge.net) +============= +meshoptimizer +============= +MIT License - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any - damages arising from the use of this software. +Copyright (c) 2016-2021 Arseny Kapoulkine - Permission is granted to anyone to use this software for any - purpose, including commercial applications, and to alter it and - redistribute it freely, subject to the following restrictions: +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: - 1. The origin of this software must not be misrepresented; you must - not claim that you wrote the original software. If you use this - software in a product, an acknowledgment in the product documentation - would be appreciated but is not required. +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. - 2. Altered source versions must be plainly marked as such, and - must not be misrepresented as being the original software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. - 3. This notice may not be removed or altered from any source distribution. +============ +tinygltf +============ +MIT License -************************************************************ -************************************************************ +Copyright (c) 2017 Syoyo Fujita, Aurélien Chatelain and many contributors -THE FREE SOFTWARE FOUNDATION +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: -Any customer may request the source code for all open source portions of this product which are covered by the Free Software Foundation's General Public License (GPL), for a period of three years from purchase. Please contact the vendor from whom you obtained this product for instructions. A fee equivalent to the cost of making the code available may be charged. Alternatively, customers may choose to download desired GPL components directly from their original vendors. Specifically, this product contains the following GPL-licensed components: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. -From Vivox: - - Assorted software components. To request source, contact Vivox at: - Vivox, Inc. - Attn: customer support - 40 Speen Street Suite 402 - Framingham, MA 01701 diff --git a/indra/newview/licenses-mac.txt b/indra/newview/licenses-mac.txt index 29b5a919bd..a3792f0b6b 100644 --- a/indra/newview/licenses-mac.txt +++ b/indra/newview/licenses-mac.txt @@ -48,6 +48,42 @@ Base32 License * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. + +=========== +CEF License +=========== + +// Copyright (c) 2008-2020 Marshall A. Greenblatt. Portions Copyright (c) +// 2006-2009 Google Inc. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the name Chromium Embedded +// Framework nor the names of its contributors may be used to endorse +// or promote products derived from this software without specific prior +// written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + ============ cURL License ============ @@ -75,6 +111,31 @@ be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization of the copyright holder. +================ +Dullahan License +================ + +Copyright (c) 2016, Linden Research, Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + ============= expat License ============= @@ -198,32 +259,48 @@ JPEG Library 6b License This software is based in part on the work of the Independent JPEG Group ================ -JPEG2000 License +OpenJPEG License ================ -Copyright 2001, David Taubman, The University of New South Wales (UNSW) -The copyright owner is Unisearch Ltd, Australia (commercial arm of UNSW) -Neither this copyright statement, nor the licensing details below -may be removed from this file or dissociated from its contents. - -Licensee: Linden Research, Inc. -License number: 00024 -The licensee has been granted a COMMERCIAL license to the contents of -this source file. A brief summary of this license appears below. This -summary is not to be relied upon in preference to the full text of the -license agreement, accepted at purchase of the license. -1. The Licensee has the right to Commercial Use of the Kakadu software, - including distribution of one or more Applications built using the - software. -2. The Licensee has the right to Internal Use of the Kakadu software, - including use by employees of the Licensee or an Affiliate for the - purpose of performing services on behalf of the Licensee or Affiliate, - or in the performance of services for Third Parties who engage Licensee - or an Affiliate for such services. -3. The Licensee has the right to distribute Reusable Code (including - source code and dynamically or statically linked libraries) to a Third - Party, provided the Third Party possesses a license to use the Kakadu - software. +/* + * The copyright in this software is being made available under the 2-clauses + * BSD License, included below. This software may be subject to other third + * party and contributor rights, including patent rights, and no such rights + * are granted under this license. + * + * Copyright (c) 2002-2014, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2014, Professor Benoit Macq + * Copyright (c) 2003-2014, Antonin Descampe + * Copyright (c) 2003-2009, Francois-Olivier Devaux + * Copyright (c) 2005, Herve Drolon, FreeImage Team + * Copyright (c) 2002-2003, Yannick Verschueren + * Copyright (c) 2001-2003, David Janssens + * Copyright (c) 2011-2012, Centre National d'Etudes Spatiales (CNES), France + * Copyright (c) 2012, CS Systemes d'Information, France + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ ================== ogg/vorbis License @@ -259,6 +336,30 @@ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +=========== +SDL License +=========== + +SDL - Simple DirectMedia Layer +Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org> + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. + + =============== OpenSSL License =============== @@ -516,18 +617,6 @@ supporting the PNG file format in commercial products. If you use this source code in a product, acknowledgment is not required but would be appreciated. -================= -Vivox SDK License -================= - -RSA Data Security, Inc. MD5 Message-Digest Algorithm - -Audio coding: Polycom(R) Siren14TM (ITU-T Rec. G.722.1 Annex C) - -Open Source Software Licensing -Each open source software component utilized by this product is subject to its own copyright and licensing terms, as listed below. - - ************************************************************* ************************************************************* @@ -553,80 +642,6 @@ Each open source software component utilized by this product is subject to its o ************************************************************* ************************************************************* -RTP code under Lesser General Public License - -/* - The oRTP library is an RTP (Realtime Transport Protocol - rfc3550) stack. - Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org - - 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; either - version 2.1 of the License, or (at your option) any later version. - - 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -************************************************************ -************************************************************* - -/* - * The Vovida Software License, Version 1.0 - * - * Copyright (c) 2000 Vovida Networks, Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The names "VOCAL", "Vovida Open Communication Application Library", - * and "Vovida Open Communication Application Library (VOCAL)" must - * not be used to endorse or promote products derived from this - * software without prior written permission. For written - * permission, please contact vocal@vovida.org. - * - * 4. Products derived from this software may not be called "VOCAL", nor - * may "VOCAL" appear in their name, without prior written - * permission of Vovida Networks, Inc. - * - * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND - * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA - * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES - * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE - * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. - * - * - * This software consists of voluntary contributions made by Vovida - * Networks, Inc. and many individuals on behalf of Vovida Networks, - * Inc. For more information on Vovida Networks, Inc., please see - * - * - */ -************************************************************* -************************************************************* Internet Software Consortium code @@ -647,54 +662,6 @@ Internet Software Consortium code * SOFTWARE. */ -************************************************************* - -************************************************************* - -************************************************************ - -http://tinyxpath.sourceforge.net/ - -TinyXPath is covered by the zlib license : - - www.sourceforge.net/projects/tinyxpath - Copyright (c) 2002-2006 Yves Berquin (yvesb@users.sourceforge.net) - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any - damages arising from the use of this software. - - Permission is granted to anyone to use this software for any - purpose, including commercial applications, and to alter it and - redistribute it freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must - not claim that you wrote the original software. If you use this - software in a product, an acknowledgment in the product documentation - would be appreciated but is not required. - - 2. Altered source versions must be plainly marked as such, and - must not be misrepresented as being the original software. - - 3. This notice may not be removed or altered from any source distribution. - - -************************************************************ -************************************************************ - -THE FREE SOFTWARE FOUNDATION - -Any customer may request the source code for all open source portions of this product which are covered by the Free Software Foundation's General Public License (GPL), for a period of three years from purchase. Please contact the vendor from whom you obtained this product for instructions. A fee equivalent to the cost of making the code available may be charged. Alternatively, customers may choose to download desired GPL components directly from their original vendors. Specifically, this product contains the following GPL-licensed components: - - -From Vivox: - - Assorted software components. To request source, contact Vivox at: - Vivox, Inc. - Attn: customer support - 40 Speen Street Suite 402 - Framingham, MA 01701 - - ============= meshoptimizer ============= @@ -771,3 +738,47 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +======== +sse2neon +======== +/* + * sse2neon is freely redistributable under the MIT License. + * + * Copyright (c) 2015-2024 SSE2NEON Contributors. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +=============================== +libwebrtc binaries (unofficial) +=============================== + +Copyright 2019 Zenichi Amano + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/indra/newview/linux_tools/launch_url.sh b/indra/newview/linux_tools/launch_url.sh index 404ea36f26..7c4ebf2291 100755 --- a/indra/newview/linux_tools/launch_url.sh +++ b/indra/newview/linux_tools/launch_url.sh @@ -61,6 +61,7 @@ fi # will be tried first, which is a debian alternative. BROWSER_COMMANDS=" \ x-www-browser \ + chrome \ firefox \ mozilla-firefox \ iceweasel \ diff --git a/indra/newview/linux_tools/megapahit.desktop b/indra/newview/linux_tools/megapahit.desktop new file mode 100755 index 0000000000..05e5d0175a --- /dev/null +++ b/indra/newview/linux_tools/megapahit.desktop @@ -0,0 +1,10 @@ +[Desktop Entry] +Name=Megapahit +Comment=A fork of the Second Life viewer +Exec=megapahit +Icon=megapahit +Terminal=false +Type=Application +Categories=Application;Network; +StartupNotify=true +X-Desktop-File-Install-Version=3.0" diff --git a/indra/newview/linux_tools/wrapper.sh b/indra/newview/linux_tools/wrapper.sh index eb3ead433b..a027aaf6d1 100755 --- a/indra/newview/linux_tools/wrapper.sh +++ b/indra/newview/linux_tools/wrapper.sh @@ -58,21 +58,14 @@ fi ## - Avoids an often-buggy X feature that doesn't really benefit us anyway. export SDL_VIDEO_X11_DGAMOUSE=0 -## - Works around a problem with misconfigured 64-bit systems not finding GL -I386_MULTIARCH="$(dpkg-architecture -ai386 -qDEB_HOST_MULTIARCH 2>/dev/null)" -MULTIARCH_ERR=$? -if [ $MULTIARCH_ERR -eq 0 ]; then - echo 'Multi-arch support detected.' - MULTIARCH_GL_DRIVERS="/usr/lib/${I386_MULTIARCH}/dri" - export LIBGL_DRIVERS_PATH="${LIBGL_DRIVERS_PATH}:${MULTIARCH_GL_DRIVERS}:/usr/lib64/dri:/usr/lib32/dri:/usr/lib/dri" -else - export LIBGL_DRIVERS_PATH="${LIBGL_DRIVERS_PATH}:/usr/lib64/dri:/usr/lib32/dri:/usr/lib/dri" -fi - ## - The 'scim' GTK IM module widely crashes the viewer. Avoid it. if [ "$GTK_IM_MODULE" = "scim" ]; then export GTK_IM_MODULE=xim fi +if [ "$XMODIFIERS" = "" ]; then + ## IME is valid only for fcitx, not when using ibus + export XMODIFIERS="@im=fcitx" +fi ## - Automatically work around the ATI mouse cursor crash bug: ## (this workaround is disabled as most fglrx users do not see the bug) @@ -98,25 +91,6 @@ cd "${RUN_PATH}" ## Before we mess with LD_LIBRARY_PATH, save the old one to restore for ## subprocesses that care. export SAVED_LD_LIBRARY_PATH="${LD_LIBRARY_PATH}" - -# if [ -n "$LL_TCMALLOC" ]; then -# tcmalloc_libs='/usr/lib/libtcmalloc.so.0 /usr/lib/libstacktrace.so.0 /lib/libpthread.so.0' -# all=1 -# for f in $tcmalloc_libs; do -# if [ ! -f $f ]; then -# all=0 -# fi -# done -# if [ $all != 1 ]; then -# echo 'Cannot use tcmalloc libraries: components missing' 1>&2 -# else -# export LD_PRELOAD=$(echo $tcmalloc_libs | tr ' ' :) -# if [ -z "$HEAPCHECK" -a -z "$HEAPPROFILE" ]; then -# export HEAPCHECK=${HEAPCHECK:-normal} -# fi -# fi -#fi - export LD_LIBRARY_PATH="$PWD/lib:${LD_LIBRARY_PATH}" # Copy "$@" to ARGS array specifically to delete the --skip-gridargs switch. @@ -140,18 +114,6 @@ LL_RUN_ERR=$? if [ $LL_RUN_ERR -ne 0 ]; then # generic error running the binary echo '*** Bad shutdown ($LL_RUN_ERR). ***' - if [ "$(uname -m)" = "x86_64" ]; then - echo - cat << EOFMARKER -You are running the Second Life Viewer on a x86_64 platform. The -most common problems when launching the Viewer (particularly -'bin/do-not-directly-run-secondlife-bin: not found' and 'error while -loading shared libraries') may be solved by installing your Linux -distribution's 32-bit compatibility packages. -For example, on Ubuntu and other Debian-based Linuxes you might run: -$ sudo apt-get install ia32-libs ia32-libs-gtk ia32-libs-kde ia32-libs-sdl -EOFMARKER - fi fi echo diff --git a/indra/newview/llagentcamera.cpp b/indra/newview/llagentcamera.cpp index 25e777191f..15d3b93818 100644 --- a/indra/newview/llagentcamera.cpp +++ b/indra/newview/llagentcamera.cpp @@ -2662,9 +2662,9 @@ void LLAgentCamera::setCameraPosAndFocusGlobal(const LLVector3d& camera_pos, con if (mCameraAnimating) { - const F64 ANIM_METERS_PER_SECOND = 10.0; + const F64 ANIM_METERS_PER_SECOND = 15.0; const F64 MIN_ANIM_SECONDS = 0.5; - const F64 MAX_ANIM_SECONDS = 10.0; + const F64 MAX_ANIM_SECONDS = 3.0; F64 anim_duration = llmax( MIN_ANIM_SECONDS, sqrt(focus_delta_squared) / ANIM_METERS_PER_SECOND ); anim_duration = llmin( anim_duration, MAX_ANIM_SECONDS ); setAnimationDuration( (F32)anim_duration ); diff --git a/indra/newview/llaisapi.cpp b/indra/newview/llaisapi.cpp index ce4e8e9392..11c5ffecb6 100644 --- a/indra/newview/llaisapi.cpp +++ b/indra/newview/llaisapi.cpp @@ -1385,8 +1385,6 @@ void AISUpdate::parseCategory(const LLSD& category_map, S32 depth) && curr_cat->getVersion() > LLViewerInventoryCategory::VERSION_UNKNOWN && version > curr_cat->getVersion()) { - // Potentially should new_cat->setVersion(unknown) here, - // but might be waiting for a callback that would increment LL_DEBUGS("Inventory") << "Category " << category_id << " is stale. Known version: " << curr_cat->getVersion() << " server version: " << version << LL_ENDL; diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 85ede793e2..2459f49952 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -132,13 +132,17 @@ #include "stringize.h" #include "llcoros.h" #include "llexception.h" -#if !LL_LINUX +#if LL_DARWIN || LL_LINUX || __FreeBSD__ #include "cef/dullahan_version.h" +#endif #include "vlc/libvlc_version.h" -#endif // LL_LINUX #if LL_DARWIN +#if LL_SDL +#include "llwindowsdl.h" +#else #include "llwindowmacosx.h" +#endif // LL_SDL #endif // Third party library includes @@ -251,6 +255,8 @@ using namespace LL; #include "llcoproceduremanager.h" #include "llviewereventrecorder.h" +#include <chrono> + // *FIX: These extern globals should be cleaned up. // The globals either represent state/config/resource-storage of either // this app, or another 'component' of the viewer. App globals should be @@ -265,10 +271,6 @@ using namespace LL; // define a self-registering event API object #include "llappviewerlistener.h" -#if LL_LINUX && LL_GTK -#include "glib.h" -#endif // (LL_LINUX) && LL_GTK - #if LL_MSVC // disable boost::lexical_cast warning #pragma warning (disable:4702) @@ -311,6 +313,8 @@ S32 gLastExecDuration = -1; // (<0 indicates unknown) # define LL_PLATFORM_KEY "mac" #elif LL_LINUX # define LL_PLATFORM_KEY "lnx" +#elif __FreeBSD__ +# define LL_PLATFORM_KEY "bsd" #else # error "Unknown Platform" #endif @@ -387,6 +391,7 @@ static std::string gLaunchFileOnQuit; // Used on Win32 for other apps to identify our window (eg, win_setup) const char* const VIEWER_WINDOW_CLASSNAME = "Second Life"; + //---------------------------------------------------------------------------- // List of entries from strings.xml to always replace @@ -530,11 +535,13 @@ static void settings_to_globals() { LLSurface::setTextureSize(gSavedSettings.getU32("RegionTextureSize")); -#if LL_DARWIN +//#if LL_DARWIN LLRender::sGLCoreProfile = true; +/* #else LLRender::sGLCoreProfile = gSavedSettings.getBOOL("RenderGLContextCoreProfile"); #endif +*/ LLRender::sNsightDebugSupport = gSavedSettings.getBOOL("RenderNsightDebugSupport"); LLImageGL::sGlobalUseAnisotropic = gSavedSettings.getBOOL("RenderAnisotropic"); LLImageGL::sCompressTextures = gSavedSettings.getBOOL("RenderCompressTextures"); @@ -561,7 +568,11 @@ static void settings_to_globals() LLWorldMapView::setScaleSetting(gSavedSettings.getF32("MapScale")); #if LL_DARWIN +#if LL_SDL + LLWindowSDL::sUseMultGL = gSavedSettings.getBOOL("RenderAppleUseMultGL"); +#else LLWindowMacOSX::sUseMultGL = gSavedSettings.getBOOL("RenderAppleUseMultGL"); +#endif // LL_SDL gHiDPISupport = gSavedSettings.getBOOL("RenderHiDPI"); #endif } @@ -667,7 +678,7 @@ LLAppViewer::LLAppViewer() // Need to do this initialization before we do anything else, since anything // that touches files should really go through the lldir API - gDirUtilp->initAppDirs("SecondLife"); + gDirUtilp->initAppDirs("Megapahit"); // // IMPORTANT! Do NOT put anything that will write // into the log files during normal startup until AFTER @@ -886,7 +897,7 @@ bool LLAppViewer::init() std::string mime_types_name; #if LL_DARWIN mime_types_name = "mime_types_mac.xml"; -#elif LL_LINUX +#elif LL_LINUX || __FreeBSD__ mime_types_name = "mime_types_linux.xml"; #else mime_types_name = "mime_types.xml"; @@ -962,6 +973,7 @@ bool LLAppViewer::init() return 0; } +#if defined(__i386__) || defined(__x86_64__) || defined(__amd64__) // Without SSE2 support we will crash almost immediately, warn here. if (!gSysCPU.hasSSE2()) { @@ -973,6 +985,7 @@ bool LLAppViewer::init() OSMB_OK); return 0; } +#endif // alert the user if they are using unsupported hardware if(!gSavedSettings.getBOOL("AlertedUnsupportedHardware")) @@ -1125,7 +1138,7 @@ bool LLAppViewer::init() gGLActive = false; -#if LL_RELEASE_FOR_DOWNLOAD +#if 0 // LL_RELEASE_FOR_DOWNLOAD && !LL_LINUX // Skip updater if this is a non-interactive instance if (!gSavedSettings.getBOOL("CmdLineSkipUpdater") && !gNonInteractive) { @@ -1357,6 +1370,13 @@ bool LLAppViewer::frame() bool LLAppViewer::doFrame() { + static LLCachedControl<U32> fpsLimitMaxFps(gSavedSettings, "MaxFPS", 0); + + using TimePoint = std::chrono::steady_clock::time_point; + + U64 fpsLimitSleepFor = 0; + TimePoint fpsLimitFrameStartTime = std::chrono::steady_clock::now(); + LL_RECORD_BLOCK_TIME(FTM_FRAME); { // and now adjust the visuals from previous frame. @@ -1527,6 +1547,18 @@ bool LLAppViewer::doFrame() } } + if(fpsLimitMaxFps > 0) + { + auto elapsed = std::chrono::steady_clock::now() - fpsLimitFrameStartTime; + + long long fpsLimitFrameTime = std::chrono::duration_cast<std::chrono::microseconds>(elapsed).count(); + U64 desired_time_us = (U32)(1000000.f / fpsLimitMaxFps); + if((fpsLimitFrameTime+1000) < desired_time_us) + { + fpsLimitSleepFor = (desired_time_us - fpsLimitFrameTime - 1000) * 1.0; + } + } + { LL_PROFILE_ZONE_NAMED_CATEGORY_APP( "df pauseMainloopTimeout" ) pingMainloopTimeout("Main:Sleep"); @@ -1539,6 +1571,11 @@ bool LLAppViewer::doFrame() //LL_RECORD_BLOCK_TIME(SLEEP2); LL_PROFILE_ZONE_WARN( "Sleep2" ) + if(fpsLimitSleepFor) + { + usleep(fpsLimitSleepFor); + } + // yield some time to the os based on command line option static LLCachedControl<S32> yield_time(gSavedSettings, "YieldTime", -1); if(yield_time >= 0) @@ -1728,7 +1765,7 @@ bool LLAppViewer::cleanup() // one because it happens just after mFastTimerLogThread is deleted. This // comment is in case we guessed wrong, so we can move it here instead. -#if LL_LINUX +#if LL_LINUX || __FreeBSD__ // remove any old breakpad minidump files from the log directory if (! isError()) { @@ -2355,6 +2392,14 @@ void LLAppViewer::initLoggingAndGetLastDuration() { LL_WARNS("MarkerFile") << duration_log_msg << LL_ENDL; } + + std::string user_data_path_cef_log = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "cef.log"); + if (gDirUtilp->fileExists(user_data_path_cef_log)) + { + std::string user_data_path_cef_old = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "cef.old"); + LLFile::remove(user_data_path_cef_old, ENOENT); + LLFile::rename(user_data_path_cef_log, user_data_path_cef_old); + } } } @@ -2995,9 +3040,10 @@ void LLAppViewer::initStrings() std::string strings_path_full = gDirUtilp->findSkinnedFilenameBaseLang(LLDir::XUI, strings_file); if (strings_path_full.empty() || !LLFile::isfile(strings_path_full)) { + std::string crash_reason; if (strings_path_full.empty()) { - LL_WARNS() << "The file '" << strings_file << "' is not found" << LL_ENDL; + crash_reason = "The file '" + strings_file + "' is not found"; } else { @@ -3005,24 +3051,23 @@ void LLAppViewer::initStrings() int rc = LLFile::stat(strings_path_full, &st); if (rc != 0) { - LL_WARNS() << "The file '" << strings_path_full << "' failed to get status. Error code: " << rc << LL_ENDL; + crash_reason = "The file '" + strings_path_full + "' failed to get status. Error code: " + std::to_string(rc); } else if (S_ISDIR(st.st_mode)) { - LL_WARNS() << "The filename '" << strings_path_full << "' is a directory name" << LL_ENDL; + crash_reason = "The filename '" + strings_path_full + "' is a directory name"; } else { - LL_WARNS() << "The filename '" << strings_path_full << "' doesn't seem to be a regular file name" << LL_ENDL; + crash_reason = "The filename '" + strings_path_full + "' doesn't seem to be a regular file name"; } } // initial check to make sure files are there failed gDirUtilp->dumpCurrentDirectories(LLError::LEVEL_WARN); LLError::LLUserWarningMsg::showMissingFiles(); - LL_ERRS() << "Viewer failed to find localization and UI files." - << " Please reinstall viewer from https://secondlife.com/support/downloads" - << " and contact https://support.secondlife.com if issue persists after reinstall." << LL_ENDL; + LL_ERRS() << "Viewer failed to open some of localization and UI files." + << " " << crash_reason << "." << LL_ENDL; } LLTransUtil::parseStrings(strings_file, default_trans_args); LLTransUtil::parseLanguageStrings("language_settings.xml"); @@ -3376,7 +3421,7 @@ LLSD LLAppViewer::getViewerInfo() const info["VOICE_VERSION"] = LLTrans::getString("NotConnected"); } -#if !LL_LINUX +#if LL_DARWIN || LL_LINUX || __FreeBSD__ std::ostringstream cef_ver_codec; cef_ver_codec << "Dullahan: "; cef_ver_codec << DULLAHAN_VERSION_MAJOR; @@ -3406,7 +3451,7 @@ LLSD LLAppViewer::getViewerInfo() const info["LIBCEF_VERSION"] = "Undefined"; #endif -#if !LL_LINUX +//#if !LL_LINUX std::ostringstream vlc_ver_codec; vlc_ver_codec << LIBVLC_VERSION_MAJOR; vlc_ver_codec << "."; @@ -3414,9 +3459,11 @@ LLSD LLAppViewer::getViewerInfo() const vlc_ver_codec << "."; vlc_ver_codec << LIBVLC_VERSION_REVISION; info["LIBVLC_VERSION"] = vlc_ver_codec.str(); +/* #else info["LIBVLC_VERSION"] = "Undefined"; #endif +*/ S32 packets_in = LLViewerStats::instance().getRecording().getSum(LLStatViewer::PACKETS_IN); if (packets_in > 0) @@ -5446,7 +5493,7 @@ void LLAppViewer::forceErrorBreakpoint() LL_WARNS() << "Forcing a deliberate breakpoint" << LL_ENDL; #ifdef LL_WINDOWS DebugBreak(); -#else +#elif __i386__ || __x86_64__ asm ("int $3"); #endif return; @@ -5699,4 +5746,3 @@ void LLAppViewer::metricsSend(bool enable_reporting) // resolution in time. gViewerAssetStats->restart(); } - diff --git a/indra/newview/llappviewerlinux.cpp b/indra/newview/llappviewerlinux.cpp index 1709970156..c1e8f38c51 100644 --- a/indra/newview/llappviewerlinux.cpp +++ b/indra/newview/llappviewerlinux.cpp @@ -40,15 +40,60 @@ #include <exception> -#if LL_DBUS_ENABLED -# include "llappviewerlinux_api_dbus.h" - -// regrettable hacks to give us better runtime compatibility with older systems inside llappviewerlinux_api.h: -#define llg_return_if_fail(COND) do{if (!(COND)) return;}while(0) -#undef g_return_if_fail -#define g_return_if_fail(COND) llg_return_if_fail(COND) -// The generated API -# include "llappviewerlinux_api.h" +#if LL_GLIB +#include <gio/gio.h> +#endif +#include <netinet/in.h> +#include <resolv.h> + +#if (__GLIBC__*1000 + __GLIBC_MINOR__) >= 2034 +extern "C" +{ + int __res_nquery(res_state statep, + const char *dname, int qclass, int type, + unsigned char *answer, int anslen) + { + return res_nquery( statep, dname, qclass, type, answer, anslen ); + } + + int __dn_expand(const unsigned char *msg, + const unsigned char *eomorig, + const unsigned char *comp_dn, char *exp_dn, + int length) + { + return dn_expand( msg,eomorig,comp_dn,exp_dn,length); + } +} +#endif + +#if LL_SEND_CRASH_REPORTS +#include "breakpad/client/linux/handler/exception_handler.h" +#include "breakpad/common/linux/http_upload.h" +#include "lldir.h" +#include "../llcrashlogger/llcrashlogger.h" +#include "jsoncpp/reader.h" // JSON + +#endif + +#define VIEWERAPI_SERVICE "com.secondlife.ViewerAppAPIService" +#define VIEWERAPI_PATH "/com/secondlife/ViewerAppAPI" +#define VIEWERAPI_INTERFACE "com.secondlife.ViewerAppAPI" + +#if LL_GLIB +static const char * DBUS_SERVER = "<node name=\"/com/secondlife/ViewerAppAPI\">\n" + " <interface name=\"com.secondlife.ViewerAppAPI\">\n" + " <annotation name=\"org.freedesktop.DBus.GLib.CSymbol\" value=\"viewer_app_api\"/>\n" + " <method name=\"GoSLURL\">\n" + " <annotation name=\"org.freedesktop.DBus.GLib.CSymbol\" value=\"dispatchSLURL\"/>\n" + " <arg type=\"s\" name=\"slurl\" direction=\"in\" />\n" + " </method>\n" + " </interface>\n" + "</node>"; + +typedef struct +{ + GObject parent; +} ViewerAppAPI; #endif namespace @@ -81,6 +126,8 @@ int main( int argc, char **argv ) // install unexpected exception handler gOldTerminateHandler = std::set_terminate(exceptionTerminateHandler); + unsetenv( "LD_PRELOAD" ); // <FS:ND/> Get rid of any preloading, we do not want this to happen during startup of plugins. + bool ok = viewer_app_ptr->init(); if(!ok) { @@ -114,21 +161,74 @@ LLAppViewerLinux::~LLAppViewerLinux() { } -bool LLAppViewerLinux::init() +#if LL_SEND_CRASH_REPORTS +std::string gCrashLogger; +std::string gVersion; +std::string gBugsplatDB; +std::string gCrashBehavior; + +static bool dumpCallback(const google_breakpad::MinidumpDescriptor& descriptor, void* context, bool succeeded) +{ + if( fork() == 0 ) + execl( gCrashLogger.c_str(), gCrashLogger.c_str(), descriptor.path(), gVersion.c_str(), gBugsplatDB.c_str(), gCrashBehavior.c_str(), nullptr ); + return succeeded; +} + +void setupBreadpad() { - // g_thread_init() must be called before *any* use of glib, *and* - // before any mutexes are held, *and* some of our third-party - // libraries likes to use glib functions; in short, do this here - // really early in app startup! - if (!g_thread_supported ()) g_thread_init (NULL); + std::string build_data_fname(gDirUtilp->getExpandedFilename(LL_PATH_EXECUTABLE, "build_data.json")); + gCrashLogger = gDirUtilp->getExpandedFilename(LL_PATH_EXECUTABLE, "linux-crash-logger.bin"); + + llifstream inf(build_data_fname.c_str()); + if(!inf.is_open()) + { + LL_WARNS("BUGSPLAT") << "Can't initialize BugSplat, can't read '" << build_data_fname << "'" << LL_ENDL; + return; + } + + Json::Reader reader; + Json::Value build_data; + if(!reader.parse(inf, build_data, false)) + { + LL_WARNS("BUGSPLAT") << "Can't initialize BugSplat, can't parse '" << build_data_fname << "': " + << reader.getFormatedErrorMessages() << LL_ENDL; + return; + } + Json::Value BugSplat_DB = build_data["BugSplat DB"]; + if(!BugSplat_DB) + { + LL_WARNS("BUGSPLAT") << "Can't initialize BugSplat, no 'BugSplat DB' entry in '" << build_data_fname + << "'" << LL_ENDL; + return; + } + gVersion = STRINGIZE( + LL_VIEWER_VERSION_MAJOR << '.' << LL_VIEWER_VERSION_MINOR << '.' << LL_VIEWER_VERSION_PATCH + << '.' << LL_VIEWER_VERSION_BUILD); + gBugsplatDB = BugSplat_DB.asString(); + + LL_INFOS("BUGSPLAT") << "Initializing with crash logger: " << gCrashLogger << " database: " << gBugsplatDB << " version: " << gVersion << LL_ENDL; + + google_breakpad::MinidumpDescriptor *descriptor = new google_breakpad::MinidumpDescriptor(gDirUtilp->getExpandedFilename(LL_PATH_DUMP, "")); + google_breakpad::ExceptionHandler *eh = new google_breakpad::ExceptionHandler(*descriptor, NULL, dumpCallback, NULL, true, -1); +} +#endif + +bool LLAppViewerLinux::init() +{ bool success = LLAppViewer::init(); #if LL_SEND_CRASH_REPORTS - if (success) + S32 nCrashSubmitBehavior = gCrashSettings.getS32("CrashSubmitBehavior"); + + // For the first version we just consider always send and create a nice dialog for CRASH_BEHAVIOR_ASK later. + if (success && nCrashSubmitBehavior != CRASH_BEHAVIOR_NEVER_SEND ) { - LLAppViewer* pApp = LLAppViewer::instance(); - pApp->initCrashReporting(); + if( nCrashSubmitBehavior == CRASH_BEHAVIOR_ASK ) + gCrashBehavior = "ask"; + else + gCrashBehavior = "send"; + setupBreadpad(); } #endif @@ -143,7 +243,7 @@ bool LLAppViewerLinux::restoreErrorTrap() } ///////////////////////////////////////// -#if LL_DBUS_ENABLED +#if LL_GLIB typedef struct { @@ -153,101 +253,77 @@ typedef struct static void viewerappapi_init(ViewerAppAPI *server); static void viewerappapi_class_init(ViewerAppAPIClass *klass); -/// - -// regrettable hacks to give us better runtime compatibility with older systems in general -static GType llg_type_register_static_simple_ONCE(GType parent_type, - const gchar *type_name, - guint class_size, - GClassInitFunc class_init, - guint instance_size, - GInstanceInitFunc instance_init, - GTypeFlags flags) -{ - static GTypeInfo type_info; - memset(&type_info, 0, sizeof(type_info)); - - type_info.class_size = class_size; - type_info.class_init = class_init; - type_info.instance_size = instance_size; - type_info.instance_init = instance_init; - - return g_type_register_static(parent_type, type_name, &type_info, flags); -} -#define llg_intern_static_string(S) (S) -#define g_intern_static_string(S) llg_intern_static_string(S) -#define g_type_register_static_simple(parent_type, type_name, class_size, class_init, instance_size, instance_init, flags) llg_type_register_static_simple_ONCE(parent_type, type_name, class_size, class_init, instance_size, instance_init, flags) - G_DEFINE_TYPE(ViewerAppAPI, viewerappapi, G_TYPE_OBJECT); void viewerappapi_class_init(ViewerAppAPIClass *klass) { } -static bool dbus_server_init = false; - -void viewerappapi_init(ViewerAppAPI *server) +static void dispatchSLURL(gchar const *slurl) { - // Connect to the default DBUS, register our service/API. - - if (!dbus_server_init) - { - GError *error = NULL; - - server->connection = lldbus_g_bus_get(DBUS_BUS_SESSION, &error); - if (server->connection) - { - lldbus_g_object_type_install_info(viewerappapi_get_type(), &dbus_glib_viewerapp_object_info); + LL_INFOS() << "Was asked to go to slurl: " << slurl << LL_ENDL; - lldbus_g_connection_register_g_object(server->connection, VIEWERAPI_PATH, G_OBJECT(server)); + std::string url = slurl; + LLMediaCtrl* web = NULL; + const bool trusted_browser = false; + LLURLDispatcher::dispatch(url, "", web, trusted_browser); +} - DBusGProxy *serverproxy = lldbus_g_proxy_new_for_name(server->connection, DBUS_SERVICE_DBUS, DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS); +static void DoMethodeCall (GDBusConnection *connection, + const gchar *sender, + const gchar *object_path, + const gchar *interface_name, + const gchar *method_name, + GVariant *parameters, + GDBusMethodInvocation *invocation, + gpointer user_data) +{ + LL_INFOS() << "DBUS message " << method_name << " from: " << sender << " interface: " << interface_name << LL_ENDL; + const gchar *slurl; - guint request_name_ret_unused; - // akin to org_freedesktop_DBus_request_name - if (lldbus_g_proxy_call(serverproxy, "RequestName", &error, G_TYPE_STRING, VIEWERAPI_SERVICE, G_TYPE_UINT, 0, G_TYPE_INVALID, G_TYPE_UINT, &request_name_ret_unused, G_TYPE_INVALID)) - { - // total success. - dbus_server_init = true; - } - else - { - LL_WARNS() << "Unable to register service name: " << error->message << LL_ENDL; - } + g_variant_get (parameters, "(&s)", &slurl); + dispatchSLURL(slurl); +} - g_object_unref(serverproxy); - } - else +GDBusNodeInfo *gBusNodeInfo = nullptr; +static const GDBusInterfaceVTable interface_vtable = { - g_warning("Unable to connect to dbus: %s", error->message); - } - - if (error) - g_error_free(error); - } + DoMethodeCall + }; +static void busAcquired(GDBusConnection *connection, const gchar *name, gpointer user_data) +{ + auto id = g_dbus_connection_register_object(connection, + VIEWERAPI_PATH, + gBusNodeInfo->interfaces[0], + &interface_vtable, + NULL, /* user_data */ + NULL, /* user_data_free_func */ + NULL); /* GError** */ + g_assert (id > 0); } -gboolean viewer_app_api_GoSLURL(ViewerAppAPI *obj, gchar *slurl, gboolean **success_rtn, GError **error) +static void nameAcquired(GDBusConnection *connection, const gchar *name, gpointer user_data) { - bool success = false; - - LL_INFOS() << "Was asked to go to slurl: " << slurl << LL_ENDL; +} - std::string url = slurl; - LLMediaCtrl* web = NULL; - const bool trusted_browser = false; - if (LLURLDispatcher::dispatch(url, "", web, trusted_browser)) - { - // bring window to foreground, as it has just been "launched" from a URL - // todo: hmm, how to get there from here? - //xxx->mWindow->bringToFront(); - success = true; - } +static void nameLost(GDBusConnection *connection, const gchar *name, gpointer user_data) +{ - *success_rtn = g_new (gboolean, 1); - (*success_rtn)[0] = (gboolean)success; +} +void viewerappapi_init(ViewerAppAPI *server) +{ + gBusNodeInfo = g_dbus_node_info_new_for_xml (DBUS_SERVER, NULL); + g_assert (gBusNodeInfo != NULL); + + g_bus_own_name(G_BUS_TYPE_SESSION, + VIEWERAPI_SERVICE, + G_BUS_NAME_OWNER_FLAGS_NONE, + busAcquired, + nameAcquired, + nameLost, + NULL, + NULL); - return TRUE; // the invokation succeeded, even if the actual dispatch didn't. } /// @@ -255,13 +331,6 @@ gboolean viewer_app_api_GoSLURL(ViewerAppAPI *obj, gchar *slurl, gboolean **succ //virtual bool LLAppViewerLinux::initSLURLHandler() { - if (!grab_dbus_syms(DBUSGLIB_DYLIB_DEFAULT_NAME)) - { - return false; // failed - } - - g_type_init(); - //ViewerAppAPI *api_server = (ViewerAppAPI*) g_object_new(viewerappapi_get_type(), NULL); @@ -271,49 +340,49 @@ bool LLAppViewerLinux::initSLURLHandler() //virtual bool LLAppViewerLinux::sendURLToOtherInstance(const std::string& url) { - if (!grab_dbus_syms(DBUSGLIB_DYLIB_DEFAULT_NAME)) + auto *pBus = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, nullptr); + + if( !pBus ) { - return false; // failed + LL_WARNS() << "Getting dbus failed." << LL_ENDL; + return false; } - bool success = false; - DBusGConnection *bus; - GError *error = NULL; - - g_type_init(); + auto pProxy = g_dbus_proxy_new_sync(pBus, G_DBUS_PROXY_FLAGS_NONE, nullptr, + VIEWERAPI_SERVICE, VIEWERAPI_PATH, + VIEWERAPI_INTERFACE, nullptr, nullptr); - bus = lldbus_g_bus_get (DBUS_BUS_SESSION, &error); - if (bus) + if( !pProxy ) { - gboolean rtn = FALSE; - DBusGProxy *remote_object = - lldbus_g_proxy_new_for_name(bus, VIEWERAPI_SERVICE, VIEWERAPI_PATH, VIEWERAPI_INTERFACE); - - if (lldbus_g_proxy_call(remote_object, "GoSLURL", &error, - G_TYPE_STRING, url.c_str(), G_TYPE_INVALID, - G_TYPE_BOOLEAN, &rtn, G_TYPE_INVALID)) - { - success = rtn; - } - else - { - LL_INFOS() << "Call-out to other instance failed (perhaps not running): " << error->message << LL_ENDL; - } - - g_object_unref(G_OBJECT(remote_object)); + LL_WARNS() << "Cannot create new dbus proxy." << LL_ENDL; + g_object_unref( pBus ); + return false; } - else + + auto *pArgs = g_variant_new( "(s)", url.c_str() ); + if( !pArgs ) { - LL_WARNS() << "Couldn't connect to session bus: " << error->message << LL_ENDL; + LL_WARNS() << "Cannot create new variant." << LL_ENDL; + g_object_unref( pBus ); + return false; } - if (error) - g_error_free(error); + auto pRes = g_dbus_proxy_call_sync(pProxy, + "GoSLURL", + pArgs, + G_DBUS_CALL_FLAGS_NONE, + -1, nullptr, nullptr); - return success; + + + if( pRes ) + g_variant_unref( pRes ); + g_object_unref( pProxy ); + g_object_unref( pBus ); + return true; } -#else // LL_DBUS_ENABLED +#else // LL_GLIB bool LLAppViewerLinux::initSLURLHandler() { return false; // not implemented without dbus @@ -322,31 +391,36 @@ bool LLAppViewerLinux::sendURLToOtherInstance(const std::string& url) { return false; // not implemented without dbus } -#endif // LL_DBUS_ENABLED +#endif // LL_GLIB void LLAppViewerLinux::initCrashReporting(bool reportFreeze) { std::string cmd =gDirUtilp->getExecutableDir(); cmd += gDirUtilp->getDirDelimiter(); -#if LL_LINUX +//#if LL_LINUX cmd += "linux-crash-logger.bin"; +/* #else # error Unknown platform #endif +*/ std::stringstream pid_str; pid_str << LLApp::getPid(); std::string logdir = gDirUtilp->getExpandedFilename(LL_PATH_DUMP, ""); std::string appname = gDirUtilp->getExecutableFilename(); + std::string grid{ LLGridManager::getInstance()->getGridId() }; + std::string title{ LLAppViewer::instance()->getSecondLifeTitle() }; + std::string pidstr{ pid_str.str() }; // launch the actual crash logger const char * cmdargv[] = {cmd.c_str(), "-user", - (char*)LLGridManager::getInstance()->getGridId().c_str(), + grid.c_str(), "-name", - LLAppViewer::instance()->getSecondLifeTitle().c_str(), + title.c_str(), "-pid", - pid_str.str().c_str(), + pidstr.c_str(), "-dumpdir", logdir.c_str(), "-procname", diff --git a/indra/newview/llappviewerlinux.h b/indra/newview/llappviewerlinux.h index dde223878d..460ca721f1 100644 --- a/indra/newview/llappviewerlinux.h +++ b/indra/newview/llappviewerlinux.h @@ -27,17 +27,6 @@ #ifndef LL_LLAPPVIEWERLINUX_H #define LL_LLAPPVIEWERLINUX_H -extern "C" { -# include <glib.h> -} - -#if LL_DBUS_ENABLED -extern "C" { -# include <glib-object.h> -# include <dbus/dbus-glib.h> -} -#endif - #ifndef LL_LLAPPVIEWER_H #include "llappviewer.h" #endif @@ -70,21 +59,4 @@ protected: virtual bool sendURLToOtherInstance(const std::string& url); }; -#if LL_DBUS_ENABLED -typedef struct -{ - GObject parent; - DBusGConnection *connection; -} ViewerAppAPI; - -extern "C" { - gboolean viewer_app_api_GoSLURL(ViewerAppAPI *obj, gchar *slurl, gboolean **success_rtn, GError **error); -} - -#define VIEWERAPI_SERVICE "com.secondlife.ViewerAppAPIService" -#define VIEWERAPI_PATH "/com/secondlife/ViewerAppAPI" -#define VIEWERAPI_INTERFACE "com.secondlife.ViewerAppAPI" - -#endif // LL_DBUS_ENABLED - #endif // LL_LLAPPVIEWERLINUX_H diff --git a/indra/newview/llappviewerlinux_api.h b/indra/newview/llappviewerlinux_api.h deleted file mode 100644 index 3d1324dd19..0000000000 --- a/indra/newview/llappviewerlinux_api.h +++ /dev/null @@ -1,143 +0,0 @@ -/* Generated by dbus-binding-tool; do not edit! */ -/** - * $LicenseInfo:firstyear=2008&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 __dbus_glib_marshal_viewerapp_MARSHAL_H__ -#define __dbus_glib_marshal_viewerapp_MARSHAL_H__ - -#include <glib-object.h> - -G_BEGIN_DECLS - -#ifdef G_ENABLE_DEBUG -#define g_marshal_value_peek_boolean(v) g_value_get_boolean (v) -#define g_marshal_value_peek_char(v) g_value_get_char (v) -#define g_marshal_value_peek_uchar(v) g_value_get_uchar (v) -#define g_marshal_value_peek_int(v) g_value_get_int (v) -#define g_marshal_value_peek_uint(v) g_value_get_uint (v) -#define g_marshal_value_peek_long(v) g_value_get_long (v) -#define g_marshal_value_peek_ulong(v) g_value_get_ulong (v) -#define g_marshal_value_peek_int64(v) g_value_get_int64 (v) -#define g_marshal_value_peek_uint64(v) g_value_get_uint64 (v) -#define g_marshal_value_peek_enum(v) g_value_get_enum (v) -#define g_marshal_value_peek_flags(v) g_value_get_flags (v) -#define g_marshal_value_peek_float(v) g_value_get_float (v) -#define g_marshal_value_peek_double(v) g_value_get_double (v) -#define g_marshal_value_peek_string(v) (char*) g_value_get_string (v) -#define g_marshal_value_peek_param(v) g_value_get_param (v) -#define g_marshal_value_peek_boxed(v) g_value_get_boxed (v) -#define g_marshal_value_peek_pointer(v) g_value_get_pointer (v) -#define g_marshal_value_peek_object(v) g_value_get_object (v) -#else /* !G_ENABLE_DEBUG */ -/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API. - * Do not access GValues directly in your code. Instead, use the - * g_value_get_*() functions - */ -#define g_marshal_value_peek_boolean(v) (v)->data[0].v_int -#define g_marshal_value_peek_char(v) (v)->data[0].v_int -#define g_marshal_value_peek_uchar(v) (v)->data[0].v_uint -#define g_marshal_value_peek_int(v) (v)->data[0].v_int -#define g_marshal_value_peek_uint(v) (v)->data[0].v_uint -#define g_marshal_value_peek_long(v) (v)->data[0].v_long -#define g_marshal_value_peek_ulong(v) (v)->data[0].v_ulong -#define g_marshal_value_peek_int64(v) (v)->data[0].v_int64 -#define g_marshal_value_peek_uint64(v) (v)->data[0].v_uint64 -#define g_marshal_value_peek_enum(v) (v)->data[0].v_long -#define g_marshal_value_peek_flags(v) (v)->data[0].v_ulong -#define g_marshal_value_peek_float(v) (v)->data[0].v_float -#define g_marshal_value_peek_double(v) (v)->data[0].v_double -#define g_marshal_value_peek_string(v) (v)->data[0].v_pointer -#define g_marshal_value_peek_param(v) (v)->data[0].v_pointer -#define g_marshal_value_peek_boxed(v) (v)->data[0].v_pointer -#define g_marshal_value_peek_pointer(v) (v)->data[0].v_pointer -#define g_marshal_value_peek_object(v) (v)->data[0].v_pointer -#endif /* !G_ENABLE_DEBUG */ - - -/* BOOLEAN:STRING,POINTER,POINTER (/tmp/dbus-binding-tool-c-marshallers.5XXD8T:1) */ -extern void dbus_glib_marshal_viewerapp_BOOLEAN__STRING_POINTER_POINTER (GClosure *closure, - GValue *return_value, - guint n_param_values, - const GValue *param_values, - gpointer invocation_hint, - gpointer marshal_data); -void -dbus_glib_marshal_viewerapp_BOOLEAN__STRING_POINTER_POINTER (GClosure *closure, - GValue *return_value, - guint n_param_values, - const GValue *param_values, - gpointer invocation_hint, - gpointer marshal_data) -{ - typedef gboolean (*GMarshalFunc_BOOLEAN__STRING_POINTER_POINTER) (gpointer data1, - gpointer arg_1, - gpointer arg_2, - gpointer arg_3, - gpointer data2); - register GMarshalFunc_BOOLEAN__STRING_POINTER_POINTER callback; - register GCClosure *cc = (GCClosure*) closure; - register gpointer data1, data2; - gboolean v_return; - - g_return_if_fail (return_value != NULL); - g_return_if_fail (n_param_values == 4); - - if (G_CCLOSURE_SWAP_DATA (closure)) - { - data1 = closure->data; - data2 = g_value_peek_pointer (param_values + 0); - } - else - { - data1 = g_value_peek_pointer (param_values + 0); - data2 = closure->data; - } - callback = (GMarshalFunc_BOOLEAN__STRING_POINTER_POINTER) (marshal_data ? marshal_data : cc->callback); - - v_return = callback (data1, - g_marshal_value_peek_string (param_values + 1), - g_marshal_value_peek_pointer (param_values + 2), - g_marshal_value_peek_pointer (param_values + 3), - data2); - - g_value_set_boolean (return_value, v_return); -} - -G_END_DECLS - -#endif /* __dbus_glib_marshal_viewerapp_MARSHAL_H__ */ - -#include <dbus/dbus-glib.h> -static const DBusGMethodInfo dbus_glib_viewerapp_methods[] = { - { (GCallback) viewer_app_api_GoSLURL, dbus_glib_marshal_viewerapp_BOOLEAN__STRING_POINTER_POINTER, 0 }, -}; - -const DBusGObjectInfo dbus_glib_viewerapp_object_info = { - 0, - dbus_glib_viewerapp_methods, - 1, -"com.secondlife.ViewerAppAPI\0GoSLURL\0S\0slurl\0I\0s\0success_ret\0O\0F\0N\0b\0\0\0", -"\0", -"\0" -}; - diff --git a/indra/newview/llappviewerlinux_api.xml b/indra/newview/llappviewerlinux_api.xml deleted file mode 100644 index fac35b7adc..0000000000 --- a/indra/newview/llappviewerlinux_api.xml +++ /dev/null @@ -1,14 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" ?> - -<!-- dbus-binding-tool -mode=glib-server llappviewerlinux_api.xml -prefix=viewerapp -output=llappviewerlinux_api.h --> - -<node name="/com/secondlife/ViewerAppAPI"> - <interface name="com.secondlife.ViewerAppAPI"> - <annotation name="org.freedesktop.DBus.GLib.CSymbol" value="viewer_app_api"/> - <method name="GoSLURL"> - <annotation name="org.freedesktop.DBus.GLib.CSymbol" value="viewer_app_api_GoSLURL"/> - <arg type="s" name="slurl" direction="in" /> - <arg type="b" name="success_ret" direction="out" /> - </method> - </interface> -</node> diff --git a/indra/newview/llappviewerlinux_api_dbus.cpp b/indra/newview/llappviewerlinux_api_dbus.cpp deleted file mode 100644 index 9aed8a98d4..0000000000 --- a/indra/newview/llappviewerlinux_api_dbus.cpp +++ /dev/null @@ -1,126 +0,0 @@ -/** - * @file llappviewerlinux_api_dbus.cpp - * @brief dynamic DBus symbol-grabbing code - * - * $LicenseInfo:firstyear=2008&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$ - */ - -#if LL_DBUS_ENABLED - -#include "linden_common.h" - -extern "C" { -#include <dbus/dbus-glib.h> - -#include "apr_pools.h" -#include "apr_dso.h" -} - -#define DEBUGMSG(...) do { LL_DEBUGS() << llformat(__VA_ARGS__) << LL_ENDL; } while(0) -#define INFOMSG(...) do { LL_INFOS() << llformat(__VA_ARGS__) << LL_ENDL; } while(0) -#define WARNMSG(...) do { LL_WARNS() << llformat(__VA_ARGS__) << LL_ENDL; } while(0) - -#define LL_DBUS_SYM(REQUIRED, DBUSSYM, RTN, ...) RTN (*ll##DBUSSYM)(__VA_ARGS__) = NULL -#include "llappviewerlinux_api_dbus_syms_raw.inc" -#undef LL_DBUS_SYM - -static bool sSymsGrabbed = false; -static apr_pool_t *sSymDBUSDSOMemoryPool = NULL; -static apr_dso_handle_t *sSymDBUSDSOHandleG = NULL; - -bool grab_dbus_syms(std::string dbus_dso_name) -{ - if (sSymsGrabbed) - { - // already have grabbed good syms - return true; - } - - bool sym_error = false; - bool rtn = false; - apr_status_t rv; - apr_dso_handle_t *sSymDBUSDSOHandle = NULL; - -#define LL_DBUS_SYM(REQUIRED, DBUSSYM, RTN, ...) do{rv = apr_dso_sym((apr_dso_handle_sym_t*)&ll##DBUSSYM, sSymDBUSDSOHandle, #DBUSSYM); if (rv != APR_SUCCESS) {INFOMSG("Failed to grab symbol: %s", #DBUSSYM); if (REQUIRED) sym_error = true;} else DEBUGMSG("grabbed symbol: %s from %p", #DBUSSYM, (void*)ll##DBUSSYM);}while(0) - - //attempt to load the shared library - apr_pool_create(&sSymDBUSDSOMemoryPool, NULL); - - if ( APR_SUCCESS == (rv = apr_dso_load(&sSymDBUSDSOHandle, - dbus_dso_name.c_str(), - sSymDBUSDSOMemoryPool) )) - { - INFOMSG("Found DSO: %s", dbus_dso_name.c_str()); - -#include "llappviewerlinux_api_dbus_syms_raw.inc" - - if ( sSymDBUSDSOHandle ) - { - sSymDBUSDSOHandleG = sSymDBUSDSOHandle; - sSymDBUSDSOHandle = NULL; - } - - rtn = !sym_error; - } - else - { - INFOMSG("Couldn't load DSO: %s", dbus_dso_name.c_str()); - rtn = false; // failure - } - - if (sym_error) - { - WARNMSG("Failed to find necessary symbols in DBUS-GLIB libraries."); - } -#undef LL_DBUS_SYM - - sSymsGrabbed = rtn; - return rtn; -} - - -void ungrab_dbus_syms() -{ - // should be safe to call regardless of whether we've - // actually grabbed syms. - - if ( sSymDBUSDSOHandleG ) - { - apr_dso_unload(sSymDBUSDSOHandleG); - sSymDBUSDSOHandleG = NULL; - } - - if ( sSymDBUSDSOMemoryPool ) - { - apr_pool_destroy(sSymDBUSDSOMemoryPool); - sSymDBUSDSOMemoryPool = NULL; - } - - // NULL-out all of the symbols we'd grabbed -#define LL_DBUS_SYM(REQUIRED, DBUSSYM, RTN, ...) do{ll##DBUSSYM = NULL;}while(0) -#include "llappviewerlinux_api_dbus_syms_raw.inc" -#undef LL_DBUS_SYM - - sSymsGrabbed = false; -} - -#endif // LL_DBUS_ENABLED diff --git a/indra/newview/llappviewerlinux_api_dbus.h b/indra/newview/llappviewerlinux_api_dbus.h deleted file mode 100644 index 2f4492bd7a..0000000000 --- a/indra/newview/llappviewerlinux_api_dbus.h +++ /dev/null @@ -1,44 +0,0 @@ -/** - * @file llappviewerlinux_api_dbus.h - * @brief DBus-glib symbol handling - * - * $LicenseInfo:firstyear=2008&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 "linden_common.h" - -#if LL_DBUS_ENABLED - -extern "C" { -#include <dbus/dbus-glib.h> -} - -#define DBUSGLIB_DYLIB_DEFAULT_NAME "libdbus-glib-1.so.2" - -bool grab_dbus_syms(std::string dbus_dso_name); -void ungrab_dbus_syms(); - -#define LL_DBUS_SYM(REQUIRED, DBUSSYM, RTN, ...) extern RTN (*ll##DBUSSYM)(__VA_ARGS__) -#include "llappviewerlinux_api_dbus_syms_raw.inc" -#undef LL_DBUS_SYM - -#endif // LL_DBUS_ENABLED diff --git a/indra/newview/llappviewerlinux_api_dbus_syms_raw.inc b/indra/newview/llappviewerlinux_api_dbus_syms_raw.inc deleted file mode 100644 index c0548e2fba..0000000000 --- a/indra/newview/llappviewerlinux_api_dbus_syms_raw.inc +++ /dev/null @@ -1,9 +0,0 @@ - -// required symbols to grab -LL_DBUS_SYM(true, dbus_g_bus_get, DBusGConnection*, DBusBusType, GError**); -LL_DBUS_SYM(true, dbus_g_proxy_new_for_name, DBusGProxy*, DBusGConnection*, const char *, const char*, const char*); -LL_DBUS_SYM(true, dbus_g_proxy_call, gboolean, DBusGProxy*, const char*, GError**, GType, ...); -LL_DBUS_SYM(true, dbus_g_object_type_install_info, void, GType, const DBusGObjectInfo*); -LL_DBUS_SYM(true, dbus_g_connection_register_g_object, void, DBusGConnection*, const char*, GObject*); - -// optional symbols to grab diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp index 3cdae041fc..51a8942192 100644 --- a/indra/newview/llappviewerwin32.cpp +++ b/indra/newview/llappviewerwin32.cpp @@ -402,17 +402,10 @@ void ll_nvapi_init(NvDRSSessionHandle hSession) } } -//#define DEBUGGING_SEH_FILTER 1 -#if DEBUGGING_SEH_FILTER -# define WINMAIN DebuggingWinMain -#else -# define WINMAIN wWinMain -#endif - -int APIENTRY WINMAIN(HINSTANCE hInstance, - HINSTANCE hPrevInstance, - PWSTR pCmdLine, - int nCmdShow) +int APIENTRY wWinMain(HINSTANCE hInstance, + HINSTANCE hPrevInstance, + PWSTR pCmdLine, + int nCmdShow) { // Call Tracy first thing to have it allocate memory // https://github.com/wolfpld/tracy/issues/196 @@ -561,27 +554,6 @@ int APIENTRY WINMAIN(HINSTANCE hInstance, return 0; } -#if DEBUGGING_SEH_FILTER -// The compiler doesn't like it when you use __try/__except blocks -// in a method that uses object destructors. Go figure. -// This winmain just calls the real winmain inside __try. -// The __except calls our exception filter function. For debugging purposes. -int APIENTRY wWinMain(HINSTANCE hInstance, - HINSTANCE hPrevInstance, - PWSTR lpCmdLine, - int nCmdShow) -{ - __try - { - WINMAIN(hInstance, hPrevInstance, lpCmdLine, nCmdShow); - } - __except( viewer_windows_exception_handler( GetExceptionInformation() ) ) - { - _tprintf( _T("Exception handled.\n") ); - } -} -#endif - void LLAppViewerWin32::disableWinErrorReporting() { std::string executable_name = gDirUtilp->getExecutableFilename(); diff --git a/indra/newview/llavatarlist.cpp b/indra/newview/llavatarlist.cpp index 8f858fe4e1..52cd86951d 100644 --- a/indra/newview/llavatarlist.cpp +++ b/indra/newview/llavatarlist.cpp @@ -36,6 +36,7 @@ #include "lltextutil.h" // newview +#include "llagent.h" #include "llagentdata.h" // for comparator #include "llavatariconctrl.h" #include "llavatarnamecache.h" @@ -47,11 +48,12 @@ #include "llvoiceclient.h" #include "llviewercontrol.h" // for gSavedSettings #include "lltooldraganddrop.h" +#include "llworld.h" static LLDefaultChildRegistry::Register<LLAvatarList> r("avatar_list"); // Last interaction time update period. -static const F32 LIT_UPDATE_PERIOD = 5; +static const F32 LIT_UPDATE_PERIOD = 1; // Maximum number of avatars that can be added to a list in one pass. // Used to limit time spent for avatar list update per frame. @@ -119,6 +121,8 @@ static const LLFlatListView::ItemReverseComparator REVERSE_NAME_COMPARATOR(NAME_ LLAvatarList::Params::Params() : ignore_online_status("ignore_online_status", false) +, show_avatar_arrival_time("show_avatar_arrival_time", false) +, show_avatar_distance("show_avatar_distance", false) , show_last_interaction_time("show_last_interaction_time", false) , show_info_btn("show_info_btn", true) , show_profile_btn("show_profile_btn", true) @@ -131,6 +135,8 @@ LLAvatarList::LLAvatarList(const Params& p) : LLFlatListViewEx(p) , mIgnoreOnlineStatus(p.ignore_online_status) , mShowLastInteractionTime(p.show_last_interaction_time) +, mAvatarDistance(p.show_avatar_distance) +, mAvatarArrivalTime(p.show_avatar_arrival_time) , mContextMenu(NULL) , mDirty(true) // to force initial update , mNeedUpdateNames(false) @@ -147,7 +153,7 @@ LLAvatarList::LLAvatarList(const Params& p) // Set default sort order. setComparator(&NAME_COMPARATOR); - if (mShowLastInteractionTime) + if (mShowLastInteractionTime || mAvatarDistance || mAvatarArrivalTime) { mLITUpdateTimer = new LLTimer(); mLITUpdateTimer->setTimerExpirySec(0); // zero to force initial update @@ -196,9 +202,20 @@ void LLAvatarList::draw() if (mDirty) refresh(); - if (mShowLastInteractionTime && mLITUpdateTimer->hasExpired()) + if ((mShowLastInteractionTime || mAvatarDistance || mAvatarArrivalTime) && mLITUpdateTimer->hasExpired()) { + if (mAvatarArrivalTime) + { + updateAvatarArrivalTime(); + } + if (mAvatarDistance) + { + updateAvatarDistance(); + } + if (mShowLastInteractionTime) + { updateLastInteractionTimes(); + } mLITUpdateTimer->setTimerExpirySec(LIT_UPDATE_PERIOD); // restart the timer } } @@ -422,6 +439,8 @@ void LLAvatarList::addNewItem(const LLUUID& id, const std::string& name, bool is // This sets the name as a side effect item->setAvatarId(id, mSessionID, mIgnoreOnlineStatus); item->setOnline(mIgnoreOnlineStatus ? true : is_online); + item->showAvatarArrivalTime(mAvatarArrivalTime); + item->showAvatarDistance(mAvatarDistance); item->showLastInteractionTime(mShowLastInteractionTime); item->setAvatarIconVisible(mShowIcons); @@ -528,6 +547,46 @@ void LLAvatarList::computeDifference( LLCommonUtils::computeDifference(vnew_unsorted, vcur, vadded, vremoved); } +void LLAvatarList::updateAvatarArrivalTime() +{ + std::vector<LLPanel*> items; + getItems(items); + auto uuids = getIDs(); + std::vector<LLVector3d> positions; + auto me_pos = gAgent.getPositionGlobal(); + LLWorld::getInstance()->getAvatars(&uuids, &positions, me_pos, gSavedSettings.getF32("MPVNearMeRange")); + LLRecentPeople::instance().updateAvatarsArrivalTime(uuids); + for (auto it = items.begin(); it != items.end(); it++) + { + auto item = static_cast<LLAvatarListItem*>(*it); + auto secs_since = LLDate::now().secondsSinceEpoch() - LLRecentPeople::instance().getArrivalTimeByID(item->getAvatarId()); + if (secs_since >= 0) + item->setAvatarArrivalTime(secs_since); + } +} + + void LLAvatarList::updateAvatarDistance() +{ + std::vector<LLPanel*> items; + getItems(items); + auto uuids = getIDs(); + std::vector<LLVector3d> positions; + auto me_pos = gAgent.getPositionGlobal(); + LLWorld::getInstance()->getAvatars(&uuids, &positions, me_pos, gSavedSettings.getF32("MPVNearMeRange")); + std::map <LLUUID, LLVector3d> avatarsPositions; + auto pos_it = positions.begin(); + auto id_it = uuids.begin(); + for (;pos_it != positions.end() && id_it != uuids.end(); ++pos_it, ++id_it) + { + avatarsPositions[*id_it] = *pos_it; + } + for (auto it = items.begin(); it != items.end(); it++) + { + auto item = static_cast<LLAvatarListItem*>(*it); + item->setAvatarDistance(dist_vec(avatarsPositions[item->getAvatarId()], me_pos)); + } +} + // Refresh shown time of our last interaction with all listed avatars. void LLAvatarList::updateLastInteractionTimes() { diff --git a/indra/newview/llavatarlist.h b/indra/newview/llavatarlist.h index af5bfefcde..37ad578a20 100644 --- a/indra/newview/llavatarlist.h +++ b/indra/newview/llavatarlist.h @@ -50,6 +50,8 @@ public: struct Params : public LLInitParam::Block<Params, LLFlatListViewEx::Params> { Optional<bool> ignore_online_status, // show all items as online + show_avatar_arrival_time, + show_avatar_distance, show_last_interaction_time, // show most recent interaction time. *HACK: move this to a derived class show_info_btn, show_profile_btn, @@ -110,6 +112,8 @@ protected: const uuid_vec_t& vnew, uuid_vec_t& vadded, uuid_vec_t& vremoved); + void updateAvatarArrivalTime(); + void updateAvatarDistance(); void updateLastInteractionTimes(); void rebuildNames(); void onItemDoubleClicked(LLUICtrl* ctrl, S32 x, S32 y, MASK mask); @@ -118,6 +122,8 @@ protected: private: bool mIgnoreOnlineStatus; + bool mAvatarArrivalTime; + bool mAvatarDistance; bool mShowLastInteractionTime; bool mDirty; bool mNeedUpdateNames; diff --git a/indra/newview/llavatarlistitem.cpp b/indra/newview/llavatarlistitem.cpp index 880910d18e..7be4f4eeb8 100644 --- a/indra/newview/llavatarlistitem.cpp +++ b/indra/newview/llavatarlistitem.cpp @@ -65,6 +65,8 @@ LLAvatarListItem::LLAvatarListItem(bool not_from_ui_factory/* = true*/) LLFriendObserver(), mAvatarIcon(NULL), mAvatarName(NULL), + mAvatarArrivalTime(NULL), + mAvatarDistance(NULL), mLastInteractionTime(NULL), mIconPermissionOnline(NULL), mIconPermissionMap(NULL), @@ -107,6 +109,8 @@ bool LLAvatarListItem::postBuild() { mAvatarIcon = getChild<LLAvatarIconCtrl>("avatar_icon"); mAvatarName = getChild<LLTextBox>("avatar_name"); + mAvatarArrivalTime = getChild<LLTextBox>("avatar_arrival_time"); + mAvatarDistance = getChild<LLTextBox>("avatar_distance"); mLastInteractionTime = getChild<LLTextBox>("last_interaction"); mIconPermissionOnline = getChild<LLIconCtrl>("permission_online_icon"); @@ -301,6 +305,28 @@ void LLAvatarListItem::setAvatarId(const LLUUID& id, const LLUUID& session_id, b } } +void LLAvatarListItem::showAvatarArrivalTime(bool show) +{ + mAvatarArrivalTime->setVisible(show); + updateChildren(); +} + +void LLAvatarListItem::setAvatarArrivalTime(F32 arrival_time) +{ + mAvatarArrivalTime->setValue(formatSeconds(arrival_time)); +} + +void LLAvatarListItem::showAvatarDistance(bool show) +{ + mAvatarDistance->setVisible(show); + updateChildren(); +} + +void LLAvatarListItem::setAvatarDistance(F32 distance) +{ + mAvatarDistance->setValue(llformat("%.1f m", distance)); +} + void LLAvatarListItem::showLastInteractionTime(bool show) { mLastInteractionTime->setVisible(show); @@ -538,6 +564,12 @@ void LLAvatarListItem::initChildrenWidths(LLAvatarListItem* avatar_item) // last interaction time textbox width + padding S32 last_interaction_time_width = avatar_item->mIconPermissionEditTheirs->getRect().mLeft - avatar_item->mLastInteractionTime->getRect().mLeft; + // avatar distance textbox width + padding + S32 avatar_distance_width = avatar_item->mAvatarDistance->getRect().mLeft - avatar_item->mAvatarArrivalTime->getRect().mLeft; + + // avatar arrival time textbox width + padding + S32 avatar_arrival_time = avatar_item->mAvatarArrivalTime->getRect().mLeft - avatar_item->mAvatarName->getRect().mLeft; + // avatar icon width + padding S32 icon_width = avatar_item->mAvatarName->getRect().mLeft - avatar_item->mAvatarIcon->getRect().mLeft; @@ -546,6 +578,8 @@ void LLAvatarListItem::initChildrenWidths(LLAvatarListItem* avatar_item) S32 index = ALIC_COUNT; sChildrenWidths[--index] = icon_width; sChildrenWidths[--index] = 0; // for avatar name we don't need its width, it will be calculated as "left available space" + sChildrenWidths[--index] = avatar_arrival_time; + sChildrenWidths[--index] = avatar_distance_width; sChildrenWidths[--index] = last_interaction_time_width; sChildrenWidths[--index] = permission_edit_theirs_width; sChildrenWidths[--index] = permission_edit_mine_width; @@ -666,6 +700,12 @@ LLView* LLAvatarListItem::getItemChildView(EAvatarListItemChildIndex child_view_ case ALIC_NAME: child_view = mAvatarName; break; + case ALIC_ARRIVAL_TIME: + child_view = mAvatarArrivalTime; + break; + case ALIC_DISTANCE: + child_view = mAvatarDistance; + break; case ALIC_INTERACTION_TIME: child_view = mLastInteractionTime; break; diff --git a/indra/newview/llavatarlistitem.h b/indra/newview/llavatarlistitem.h index 2e4c597d30..630a7ec751 100644 --- a/indra/newview/llavatarlistitem.h +++ b/indra/newview/llavatarlistitem.h @@ -98,12 +98,16 @@ public: void setHighlight(const std::string& highlight); void setState(EItemState item_style); void setAvatarId(const LLUUID& id, const LLUUID& session_id, bool ignore_status_changes = false, bool is_resident = true); + void setAvatarArrivalTime(F32 arrival_time); + void setAvatarDistance(F32 distance); void setLastInteractionTime(U32 secs_since); //Show/hide profile/info btn, translating speaker indicator and avatar name coordinates accordingly void setShowProfileBtn(bool show); void setShowInfoBtn(bool show); void showSpeakingIndicator(bool show); void setShowPermissions(bool show) { mShowPermissions = show; }; + void showAvatarArrivalTime(bool show); + void showAvatarDistance(bool show); void showLastInteractionTime(bool show); void setAvatarIconVisible(bool visible); void setShowCompleteName(bool show) { mShowCompleteName = show;}; @@ -158,6 +162,8 @@ private: ALIC_PERMISSION_EDIT_MINE, ALIC_PERMISSION_EDIT_THEIRS, ALIC_INTERACTION_TIME, + ALIC_DISTANCE, + ALIC_ARRIVAL_TIME, ALIC_NAME, ALIC_ICON, ALIC_COUNT, @@ -199,6 +205,8 @@ private: LLView* getItemChildView(EAvatarListItemChildIndex child_index); LLTextBox* mAvatarName; + LLTextBox* mAvatarArrivalTime; + LLTextBox* mAvatarDistance; LLTextBox* mLastInteractionTime; LLStyle::Params mAvatarNameStyle; diff --git a/indra/newview/llavatarpropertiesprocessor.cpp b/indra/newview/llavatarpropertiesprocessor.cpp index 65e32610c3..edbf81526d 100644 --- a/indra/newview/llavatarpropertiesprocessor.cpp +++ b/indra/newview/llavatarpropertiesprocessor.cpp @@ -468,6 +468,8 @@ void LLAvatarPropertiesProcessor::processClassifiedInfoReply(LLMessageSystem* ms // Request processed, no longer pending self->removePendingRequest(c_info.creator_id, APT_CLASSIFIED_INFO); self->notifyObservers(c_info.creator_id, &c_info, APT_CLASSIFIED_INFO); + self->removePendingRequest(c_info.classified_id, APT_CLASSIFIED_INFO); + self->notifyObservers(c_info.classified_id, &c_info, APT_CLASSIFIED_INFO); } diff --git a/indra/newview/llavatarpropertiesprocessor.h b/indra/newview/llavatarpropertiesprocessor.h index 1592629fca..a490f3da10 100644 --- a/indra/newview/llavatarpropertiesprocessor.h +++ b/indra/newview/llavatarpropertiesprocessor.h @@ -52,6 +52,9 @@ enum EAvatarProcessorType { APT_PROPERTIES_LEGACY, // APT_PROPERTIES via udp request (Truncates data!!!) APT_PROPERTIES, // APT_PROPERTIES via http request + APT_NOTES, + APT_GROUPS, + APT_PICKS, APT_PICK_INFO, APT_TEXTURES, APT_CLASSIFIEDS, @@ -105,6 +108,24 @@ struct LLAvatarData typedef std::pair<LLUUID, std::string> pick_data_t; typedef std::list< pick_data_t> picks_list_t; picks_list_t picks_list; + BOOL allow_publish; + LLAvatarData() = default; + LLAvatarData(const LLAvatarLegacyData& legacy_data) + { + agent_id = legacy_data.agent_id; + avatar_id = legacy_data.avatar_id; + image_id = legacy_data.image_id; + fl_image_id = legacy_data.fl_image_id; + partner_id = legacy_data.partner_id; + about_text = legacy_data.about_text; + fl_about_text = legacy_data.fl_about_text; + born_on = legacy_data.born_on; + profile_url = legacy_data.profile_url; + caption_index = legacy_data.caption_index; + caption_text = legacy_data.caption_text; + customer_type = legacy_data.customer_type; + flags = legacy_data.flags; + } }; struct LLAvatarData::LLGroupData @@ -140,6 +161,45 @@ struct LLPickData LLUUID session_id; }; +struct LLAvatarPicks +{ + LLUUID agent_id; + LLUUID target_id; //target id + + typedef std::pair<LLUUID,std::string> pick_data_t; + typedef std::list< pick_data_t> picks_list_t; + picks_list_t picks_list; +}; + +struct LLAvatarNotes +{ + LLUUID agent_id; + LLUUID target_id; //target id + std::string notes; +}; + +struct LLAvatarGroups +{ + LLUUID agent_id; + LLUUID avatar_id; //target id + BOOL list_in_profile; + + struct LLGroupData; + typedef std::list<LLGroupData> group_list_t; + + group_list_t group_list; + + struct LLGroupData + { + U64 group_powers; + BOOL accept_notices; + std::string group_title; + LLUUID group_id; + std::string group_name; + LLUUID group_insignia_id; + }; +}; + struct LLAvatarClassifieds { LLUUID agent_id; diff --git a/indra/newview/lldirpicker.cpp b/indra/newview/lldirpicker.cpp index 1423ca1b9b..defbbdec25 100644 --- a/indra/newview/lldirpicker.cpp +++ b/indra/newview/lldirpicker.cpp @@ -37,10 +37,15 @@ #include "llviewercontrol.h" #include "llwin32headerslean.h" -#if LL_LINUX || LL_DARWIN +#if LL_LINUX || LL_DARWIN || __FreeBSD__ # include "llfilepicker.h" #endif +#ifdef LL_FLTK + #include "FL/Fl.H" + #include "FL/Fl_Native_File_Chooser.H" +#endif + #if LL_WINDOWS #include <shlobj.h> #endif @@ -208,26 +213,34 @@ std::string LLDirPicker::getDirName() return mFilePicker->getFirstFile(); } -#elif LL_LINUX +#elif LL_LINUX || __FreeBSD__ LLDirPicker::LLDirPicker() : mFileName(NULL), mLocked(false) { +#ifndef LL_FLTK mFilePicker = new LLFilePicker(); +#endif reset(); } LLDirPicker::~LLDirPicker() { +#ifndef LL_FLTK delete mFilePicker; +#endif } void LLDirPicker::reset() { +#ifndef LL_FLTK if (mFilePicker) mFilePicker->reset(); +#else + mDir = ""; +#endif } bool LLDirPicker::getDir(std::string* filename, bool blocking) @@ -240,33 +253,38 @@ bool LLDirPicker::getDir(std::string* filename, bool blocking) return false; } -#if !LL_MESA_HEADLESS - - if (mFilePicker) +#ifdef LL_FLTK + gViewerWindow->getWindow()->beforeDialog(); + Fl_Native_File_Chooser flDlg; + flDlg.title(LLTrans::getString("choose_the_directory").c_str()); + flDlg.type(Fl_Native_File_Chooser::BROWSE_DIRECTORY ); + int res = flDlg.show(); + gViewerWindow->getWindow()->afterDialog(); + if( res == 0 ) { - GtkWindow* picker = mFilePicker->buildFilePicker(false, true, - "dirpicker"); - - if (picker) - { - gtk_window_set_title(GTK_WINDOW(picker), LLTrans::getString("choose_the_directory").c_str()); - gtk_widget_show_all(GTK_WIDGET(picker)); - gtk_main(); - return (!mFilePicker->getFirstFile().empty()); - } + char const *pDir = flDlg.filename(0); + if( pDir ) + mDir = pDir; } -#endif // !LL_MESA_HEADLESS - - return false; + else if( res == -1 ) + { + LL_WARNS() << "FLTK failed: " << flDlg.errmsg() << LL_ENDL; + } + return !mDir.empty(); +#endif } std::string LLDirPicker::getDirName() { +#ifndef LL_FLTK if (mFilePicker) { return mFilePicker->getFirstFile(); } return ""; +#else + return mDir; +#endif } #else // not implemented diff --git a/indra/newview/lldirpicker.h b/indra/newview/lldirpicker.h index dc740caab2..4bbe7db144 100644 --- a/indra/newview/lldirpicker.h +++ b/indra/newview/lldirpicker.h @@ -75,10 +75,12 @@ private: void buildDirname( void ); bool check_local_file_access_enabled(); -#if LL_LINUX || LL_DARWIN +#if LL_LINUX || LL_DARWIN || __FreeBSD__ // On Linux we just implement LLDirPicker on top of LLFilePicker +#ifndef LL_FLTK LLFilePicker *mFilePicker; #endif +#endif std::string* mFileName; diff --git a/indra/newview/lldrawpool.cpp b/indra/newview/lldrawpool.cpp index 739975eab4..ba7d17cf21 100644 --- a/indra/newview/lldrawpool.cpp +++ b/indra/newview/lldrawpool.cpp @@ -365,7 +365,9 @@ void LLFacePool::LLOverrideFaceColor::setColor(const LLColor4& color) void LLFacePool::LLOverrideFaceColor::setColor(const LLColor4U& color) { +#if GL_VERSION_1_1 glColor4ubv(color.mV); +#endif } void LLFacePool::LLOverrideFaceColor::setColor(F32 r, F32 g, F32 b, F32 a) diff --git a/indra/newview/lldrawpoolbump.cpp b/indra/newview/lldrawpoolbump.cpp index 055f99d764..4ca8a184e8 100644 --- a/indra/newview/lldrawpoolbump.cpp +++ b/indra/newview/lldrawpoolbump.cpp @@ -1054,7 +1054,11 @@ void LLBumpImageList::onSourceLoaded( bool success, LLViewerTexture *src_vi, LLI if (!LLPipeline::sRenderDeferred) { +#if GL_VERSION_1_1 bump->setExplicitFormat(GL_ALPHA8, GL_ALPHA); +#else + bump->setExplicitFormat(GL_ALPHA8_EXT, GL_ALPHA); +#endif #if LL_BUMPLIST_MULTITHREADED auto tex_queue = LLImageGLThread::sEnabledTextures ? sTexUpdateQueue.lock() : nullptr; diff --git a/indra/newview/lldrawpoolterrain.cpp b/indra/newview/lldrawpoolterrain.cpp index afc5cc9d4e..c8af45a907 100644 --- a/indra/newview/lldrawpoolterrain.cpp +++ b/indra/newview/lldrawpoolterrain.cpp @@ -629,6 +629,7 @@ void LLDrawPoolTerrain::renderFull4TU() gGL.getTexUnit(0)->activate(); gGL.getTexUnit(0)->bind(detail_texture0p); +#if GL_VERSION_1_1 glEnable(GL_TEXTURE_GEN_S); glEnable(GL_TEXTURE_GEN_T); glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); @@ -636,6 +637,7 @@ void LLDrawPoolTerrain::renderFull4TU() glTexGenfv(GL_S, GL_OBJECT_PLANE, tp0.mV); glTexGenfv(GL_T, GL_OBJECT_PLANE, tp1.mV); +#endif // // Stage 1: Generate alpha ramp for detail0/detail1 transition @@ -652,12 +654,14 @@ void LLDrawPoolTerrain::renderFull4TU() gGL.getTexUnit(2)->enable(LLTexUnit::TT_TEXTURE); gGL.getTexUnit(2)->activate(); +#if GL_VERSION_1_1 glEnable(GL_TEXTURE_GEN_S); glEnable(GL_TEXTURE_GEN_T); glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); glTexGenfv(GL_S, GL_OBJECT_PLANE, tp0.mV); glTexGenfv(GL_T, GL_OBJECT_PLANE, tp1.mV); +#endif // // Stage 3: Modulate with primary (vertex) color for lighting @@ -679,12 +683,14 @@ void LLDrawPoolTerrain::renderFull4TU() gGL.getTexUnit(0)->activate(); gGL.getTexUnit(0)->bind(detail_texture3p); +#if GL_VERSION_1_1 glEnable(GL_TEXTURE_GEN_S); glEnable(GL_TEXTURE_GEN_T); glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); glTexGenfv(GL_S, GL_OBJECT_PLANE, tp0.mV); glTexGenfv(GL_T, GL_OBJECT_PLANE, tp1.mV); +#endif // // Stage 1: Generate alpha ramp for detail2/detail3 transition @@ -705,12 +711,14 @@ void LLDrawPoolTerrain::renderFull4TU() gGL.getTexUnit(2)->enable(LLTexUnit::TT_TEXTURE); gGL.getTexUnit(2)->activate(); +#if GL_VERSION_1_1 glEnable(GL_TEXTURE_GEN_S); glEnable(GL_TEXTURE_GEN_T); glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); glTexGenfv(GL_S, GL_OBJECT_PLANE, tp0.mV); glTexGenfv(GL_T, GL_OBJECT_PLANE, tp1.mV); +#endif // // Stage 3: Generate alpha ramp for detail1/detail2 transition @@ -745,8 +753,10 @@ void LLDrawPoolTerrain::renderFull4TU() gGL.getTexUnit(2)->disable(); gGL.getTexUnit(2)->activate(); +#if GL_VERSION_1_1 glDisable(GL_TEXTURE_GEN_S); glDisable(GL_TEXTURE_GEN_T); +#endif gGL.matrixMode(LLRender::MM_TEXTURE); gGL.loadIdentity(); gGL.matrixMode(LLRender::MM_MODELVIEW); @@ -769,8 +779,10 @@ void LLDrawPoolTerrain::renderFull4TU() gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); +#if GL_VERSION_1_1 glDisable(GL_TEXTURE_GEN_S); glDisable(GL_TEXTURE_GEN_T); +#endif gGL.matrixMode(LLRender::MM_TEXTURE); gGL.loadIdentity(); gGL.matrixMode(LLRender::MM_MODELVIEW); @@ -804,6 +816,7 @@ void LLDrawPoolTerrain::renderFull2TU() // Stage 0: Render detail 0 into base // gGL.getTexUnit(0)->bind(detail_texture0p); +#if GL_VERSION_1_1 glEnable(GL_TEXTURE_GEN_S); glEnable(GL_TEXTURE_GEN_T); glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); @@ -811,6 +824,7 @@ void LLDrawPoolTerrain::renderFull2TU() glTexGenfv(GL_S, GL_OBJECT_PLANE, tp0.mV); glTexGenfv(GL_T, GL_OBJECT_PLANE, tp1.mV); +#endif drawLoop(); @@ -822,8 +836,10 @@ void LLDrawPoolTerrain::renderFull2TU() // gGL.getTexUnit(0)->bind(m2DAlphaRampImagep); +#if GL_VERSION_1_1 glDisable(GL_TEXTURE_GEN_S); glDisable(GL_TEXTURE_GEN_T); +#endif // // Stage 1: Write detail1 @@ -832,12 +848,14 @@ void LLDrawPoolTerrain::renderFull2TU() gGL.getTexUnit(1)->enable(LLTexUnit::TT_TEXTURE); gGL.getTexUnit(1)->activate(); +#if GL_VERSION_1_1 glEnable(GL_TEXTURE_GEN_S); glEnable(GL_TEXTURE_GEN_T); glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); glTexGenfv(GL_S, GL_OBJECT_PLANE, tp0.mV); glTexGenfv(GL_T, GL_OBJECT_PLANE, tp1.mV); +#endif gGL.getTexUnit(0)->activate(); { @@ -865,12 +883,14 @@ void LLDrawPoolTerrain::renderFull2TU() gGL.getTexUnit(1)->enable(LLTexUnit::TT_TEXTURE); gGL.getTexUnit(1)->activate(); +#if GL_VERSION_1_1 glEnable(GL_TEXTURE_GEN_S); glEnable(GL_TEXTURE_GEN_T); glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); glTexGenfv(GL_S, GL_OBJECT_PLANE, tp0.mV); glTexGenfv(GL_T, GL_OBJECT_PLANE, tp1.mV); +#endif { LLGLEnable blend(GL_BLEND); @@ -896,12 +916,14 @@ void LLDrawPoolTerrain::renderFull2TU() gGL.getTexUnit(1)->enable(LLTexUnit::TT_TEXTURE); gGL.getTexUnit(1)->activate(); +#if GL_VERSION_1_1 glEnable(GL_TEXTURE_GEN_S); glEnable(GL_TEXTURE_GEN_T); glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); glTexGenfv(GL_S, GL_OBJECT_PLANE, tp0.mV); glTexGenfv(GL_T, GL_OBJECT_PLANE, tp1.mV); +#endif gGL.getTexUnit(0)->activate(); { @@ -918,8 +940,10 @@ void LLDrawPoolTerrain::renderFull2TU() gGL.getTexUnit(1)->disable(); gGL.getTexUnit(1)->activate(); +#if GL_VERSION_1_1 glDisable(GL_TEXTURE_GEN_S); glDisable(GL_TEXTURE_GEN_T); +#endif gGL.matrixMode(LLRender::MM_TEXTURE); gGL.loadIdentity(); gGL.matrixMode(LLRender::MM_MODELVIEW); @@ -930,8 +954,10 @@ void LLDrawPoolTerrain::renderFull2TU() gGL.getTexUnit(0)->activate(); gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); +#if GL_VERSION_1_1 glDisable(GL_TEXTURE_GEN_S); glDisable(GL_TEXTURE_GEN_T); +#endif gGL.matrixMode(LLRender::MM_TEXTURE); gGL.loadIdentity(); gGL.matrixMode(LLRender::MM_MODELVIEW); diff --git a/indra/newview/llenvironment.h b/indra/newview/llenvironment.h index f1205a72b7..e56548d618 100644 --- a/indra/newview/llenvironment.h +++ b/indra/newview/llenvironment.h @@ -27,6 +27,8 @@ #ifndef LL_ENVIRONMENT_H #define LL_ENVIRONMENT_H +#include <array> + #include "llsingleton.h" #include "llmemory.h" #include "llsd.h" diff --git a/indra/newview/lleventnotifier.cpp b/indra/newview/lleventnotifier.cpp index 25983f4add..16897e9ebd 100644 --- a/indra/newview/lleventnotifier.cpp +++ b/indra/newview/lleventnotifier.cpp @@ -182,6 +182,23 @@ bool LLEventNotifier::add(U32 eventId, F64 eventEpoch, const std::string& eventD } +bool LLEventNotifier::add(const LLEventStruct& event) +{ + if (mNewEventSignal(event)) return false; + LLEventNotification *new_enp = new LLEventNotification(event.eventId, event.eventEpoch, event.eventDateStr, event.eventName); + + LL_INFOS() << "Add event " << event.eventName << " id " << event.eventId << " date " << event.eventDateStr << LL_ENDL; + if(!new_enp->isValid()) + { + delete new_enp; + return false; + } + + mEventNotifications[new_enp->getEventID()] = new_enp; + return true; + +} + void LLEventNotifier::add(U32 eventId) { @@ -211,7 +228,21 @@ void LLEventNotifier::processEventInfoReply(LLMessageSystem *msg, void **) msg->getString("EventData", "Date", eventd_date); msg->getU32("EventData", "DateUTC", event_time_utc); - gEventNotifier.add(event_id, (F64)event_time_utc, eventd_date, event_name); + //gEventNotifier.add(event_id, (F64)event_time_utc, eventd_date, event_name); + + LLEventStruct event(event_id, (F64)event_time_utc, eventd_date, event_name); + msg->getString("EventData", "Creator", event.creator); + msg->getString("EventData", "Category", event.category); + msg->getString("EventData", "Desc", event.desc); + msg->getU32("EventData", "Duration", event.duration); + msg->getU32("EventData", "Cover", event.cover); + msg->getU32("EventData", "Amount", event.amount); + msg->getString("EventData", "SimName", event.simName); + msg->getVector3d("EventData", "GlobalPos", event.globalPos); + msg->getU32("EventData", "EventFlags", event.flags); + + gEventNotifier.add(event); + } @@ -249,11 +280,15 @@ void LLEventNotifier::load(const LLSD& event_options) substitution["datetime"] = date; LLStringUtil::format(dateStr, substitution); - add(response["event_id"].asInteger(), response["event_date_ut"], dateStr, response["event_name"].asString()); + //add(response["event_id"].asInteger(), response["event_date_ut"], dateStr, response["event_name"].asString()); + LLEventStruct event(response["event_id"].asInteger(), response["event_date_ut"], dateStr, response["event_name"].asString()); + add(event); } else { - add(response["event_id"].asInteger(), response["event_date_ut"], response["event_date"].asString(), response["event_name"].asString()); + //add(response["event_id"].asInteger(), response["event_date_ut"], response["event_date"].asString(), response["event_name"].asString()); + LLEventStruct event(response["event_id"].asInteger(), response["event_date_ut"], response["event_date"].asString(), response["event_name"].asString()); + add(event); } } } @@ -287,21 +322,21 @@ void LLEventNotifier::remove(const U32 event_id) void LLEventNotifier::serverPushRequest(U32 event_id, bool add) { // Push up a message to tell the server we have this notification. - gMessageSystem->newMessage(add?"EventNotificationAddRequest":"EventNotificationRemoveRequest"); + gMessageSystem->newMessageFast(add ? _PREHASH_EventNotificationAddRequest : _PREHASH_EventNotificationRemoveRequest); gMessageSystem->nextBlockFast(_PREHASH_AgentData); gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - gMessageSystem->nextBlock("EventData"); - gMessageSystem->addU32("EventID", event_id); + gMessageSystem->nextBlockFast(_PREHASH_EventData); + gMessageSystem->addU32Fast(_PREHASH_EventID, event_id); gAgent.sendReliableMessage(); } -LLEventNotification::LLEventNotification(U32 eventId, F64 eventEpoch, const std::string& eventDateStr, const std::string &eventName) : +LLEventNotification::LLEventNotification(U32 eventId, F64 eventEpoch, std::string eventDateStr, std::string eventName) : mEventID(eventId), - mEventName(eventName), + mEventName(std::move(eventName)), mEventDateEpoch(eventEpoch), - mEventDateStr(eventDateStr) + mEventDateStr(std::move(eventDateStr)) { } diff --git a/indra/newview/lleventnotifier.h b/indra/newview/lleventnotifier.h index 030c9abb87..f013f6d02e 100644 --- a/indra/newview/lleventnotifier.h +++ b/indra/newview/lleventnotifier.h @@ -27,12 +27,31 @@ #ifndef LL_LLEVENTNOTIFIER_H #define LL_LLEVENTNOTIFIER_H +#include <utility> #include "llframetimer.h" #include "v3dmath.h" class LLEventNotification; class LLMessageSystem; +typedef struct event_st{ + U32 eventId = 0; + F64 eventEpoch = 0.0; + std::string eventDateStr; + std::string eventName; + std::string creator; + std::string category; + std::string desc; + U32 duration = 0; + U32 cover = 0; + U32 amount = 0; + std::string simName; + LLVector3d globalPos; + U32 flags = 0; + event_st(U32 id, F64 epoch, std::string date_str, std::string name) + : eventId(id), eventEpoch(epoch), eventDateStr(std::move(date_str)), eventName(std::move(name)){} + event_st() = default; +} LLEventStruct; class LLEventNotifier { @@ -41,6 +60,7 @@ public: virtual ~LLEventNotifier(); void update(); // Notify the user of the event if it's coming up + bool add(const LLEventStruct& event); bool add(U32 eventId, F64 eventEpoch, const std::string& eventDateStr, const std::string &eventName); void add(U32 eventId); @@ -56,6 +76,13 @@ public: static void processEventInfoReply(LLMessageSystem *msg, void **); + typedef boost::signals2::signal<bool(LLEventStruct event)> new_event_signal_t; + new_event_signal_t mNewEventSignal; + boost::signals2::connection setNewEventCallback(const new_event_signal_t::slot_type& cb) + { + return mNewEventSignal.connect(cb); + }; + protected: en_map mEventNotifications; LLFrameTimer mNotificationTimer; @@ -65,7 +92,7 @@ protected: class LLEventNotification { public: - LLEventNotification(U32 eventId, F64 eventEpoch, const std::string& eventDateStr, const std::string &eventName); + LLEventNotification(U32 eventId, F64 eventEpoch, std::string eventDateStr, std::string eventName); U32 getEventID() const { return mEventID; } diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp index 0e8e64af69..a25879ab3a 100644 --- a/indra/newview/llface.cpp +++ b/indra/newview/llface.cpp @@ -57,12 +57,6 @@ #include "llsculptidsize.h" #include "llmeshrepository.h" -#if LL_LINUX -// Work-around spurious used before init warning on Vector4a -// -#pragma GCC diagnostic ignored "-Wuninitialized" -#endif - #define LL_MAX_INDICES_COUNT 1000000 static LLStaticHashedString sTextureIndexIn("texture_index_in"); @@ -548,15 +542,21 @@ void LLFace::renderSelected(LLViewerTexture *imagep, const LLColor4& color) gGL.multMatrix((F32*) volume->getRelativeXform().mMatrix); const LLVolumeFace& vol_face = rigged->getVolumeFace(getTEOffset()); LLVertexBuffer::unbind(); +#if GL_VERSION_1_1 glVertexPointer(3, GL_FLOAT, 16, vol_face.mPositions); +#endif if (vol_face.mTexCoords) { +#if GL_VERSION_1_1 glEnableClientState(GL_TEXTURE_COORD_ARRAY); glTexCoordPointer(2, GL_FLOAT, 8, vol_face.mTexCoords); +#endif } gGL.syncMatrices(); glDrawElements(GL_TRIANGLES, vol_face.mNumIndices, GL_UNSIGNED_SHORT, vol_face.mIndices); +#if GL_VERSION_1_1 glDisableClientState(GL_TEXTURE_COORD_ARRAY); +#endif } } #endif @@ -629,10 +629,14 @@ void LLFace::renderOneWireframe(const LLColor4 &color, F32 fogCfx, bool wirefram { LLGLDisable depth(wireframe_selection ? 0 : GL_BLEND); +#if GL_VERSION_1_1 LLGLEnable offset(GL_POLYGON_OFFSET_LINE); +#endif glPolygonOffset(3.f, 3.f); glLineWidth(5.f); +#if GL_VERSION_1_1 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); +#endif renderFace(mDrawablep, this); } } @@ -832,7 +836,6 @@ bool LLFace::genVolumeBBoxes(const LLVolume &volume, S32 f, //VECTORIZE THIS LLMatrix4a mat_vert; mat_vert.loadu(mat_vert_in); - LLVector4a new_extents[2]; llassert(less_than_max_mag(face.mExtents[0])); llassert(less_than_max_mag(face.mExtents[1])); diff --git a/indra/newview/llfasttimerview.cpp b/indra/newview/llfasttimerview.cpp index 67d55c53e4..7391209935 100644 --- a/indra/newview/llfasttimerview.cpp +++ b/indra/newview/llfasttimerview.cpp @@ -1098,7 +1098,7 @@ void LLFastTimerView::drawLineGraph() cur_max_calls = llmax(cur_max_calls, calls); } F32 x = mGraphRect.mRight - j * (F32)(mGraphRect.getWidth())/(mRecording.getNumRecordedPeriods()-1); - F32 y; + F32 y = 0.0; switch(mDisplayType) { case DISPLAY_TIME: diff --git a/indra/newview/llfeaturemanager.cpp b/indra/newview/llfeaturemanager.cpp index aa04221f4b..ac7d7b755b 100644 --- a/indra/newview/llfeaturemanager.cpp +++ b/indra/newview/llfeaturemanager.cpp @@ -40,6 +40,7 @@ #include "llappviewer.h" #include "llbufferstream.h" +#include "llexception.h" #include "llnotificationsutil.h" #include "llviewercontrol.h" #include "llworld.h" @@ -62,7 +63,7 @@ #if LL_DARWIN const char FEATURE_TABLE_FILENAME[] = "featuretable_mac.txt"; -#elif LL_LINUX +#elif LL_LINUX || __FreeBSD__ const char FEATURE_TABLE_FILENAME[] = "featuretable_linux.txt"; #else const char FEATURE_TABLE_FILENAME[] = "featuretable.txt"; @@ -377,33 +378,6 @@ bool LLFeatureManager::parseFeatureTable(std::string filename) F32 gpu_benchmark(); -#if LL_WINDOWS - -F32 logExceptionBenchmark() -{ - // FIXME: gpu_benchmark uses many C++ classes on the stack to control state. - // SEH exceptions with our current exception handling options do not call - // destructors for these classes, resulting in an undefined state should - // this handler be invoked. - F32 gbps = -1; - __try - { - gbps = gpu_benchmark(); - } - __except (msc_exception_filter(GetExceptionCode(), GetExceptionInformation())) - { - // HACK - ensure that profiling is disabled - LLGLSLShader::finishProfile(false); - - // convert to C++ styled exception - char integer_string[32]; - sprintf(integer_string, "SEH, code: %lu\n", GetExceptionCode()); - throw std::exception(integer_string); - } - return gbps; -} -#endif - bool LLFeatureManager::loadGPUClass() { if (!gSavedSettings.getBOOL("SkipBenchmark")) @@ -413,14 +387,12 @@ bool LLFeatureManager::loadGPUClass() F32 gbps; try { -#if LL_WINDOWS - gbps = logExceptionBenchmark(); -#else - gbps = gpu_benchmark(); -#endif + gbps = LL::seh::catcher(gpu_benchmark); } catch (const std::exception& e) { + // HACK - ensure that profiling is disabled + LLGLSLShader::finishProfile(false); gbps = -1.f; LL_WARNS("RenderInit") << "GPU benchmark failed: " << e.what() << LL_ENDL; } diff --git a/indra/newview/llfilepicker.cpp b/indra/newview/llfilepicker.cpp index 0afb275d13..2516bece8d 100644 --- a/indra/newview/llfilepicker.cpp +++ b/indra/newview/llfilepicker.cpp @@ -40,7 +40,12 @@ #include "llwindowsdl.h" // for some X/GTK utils to help with filepickers #endif // LL_SDL -#if LL_LINUX +#ifdef LL_FLTK + #include "FL/Fl.H" + #include "FL/Fl_Native_File_Chooser.H" +#endif + +#if LL_LINUX || __FreeBSD__ #include "llhttpconstants.h" // file picker uses some of thes constants on Linux #endif @@ -670,6 +675,7 @@ std::unique_ptr<std::vector<std::string>> LLFilePicker::navOpenFilterProc(ELoadF break; case FFLOAD_HDRI: allowedv->push_back("exr"); + case FFLOAD_MODEL: case FFLOAD_COLLADA: allowedv->push_back("dae"); break; @@ -1100,490 +1106,233 @@ bool LLFilePicker::getSaveFileModeless(ESaveFilter filter, } //END LL_DARWIN -#elif LL_LINUX - -# if LL_GTK - -// static -void LLFilePicker::add_to_selectedfiles(gpointer data, gpointer user_data) -{ - // We need to run g_filename_to_utf8 in the user's locale - std::string saved_locale(setlocale(LC_ALL, NULL)); - setlocale(LC_ALL, ""); - - LLFilePicker* picker = (LLFilePicker*) user_data; - GError *error = NULL; - gchar* filename_utf8 = g_filename_to_utf8((gchar*)data, - -1, NULL, NULL, &error); - if (error) - { - // *FIXME. - // This condition should really be notified to the user, e.g. - // through a message box. Just logging it is inappropriate. - - // g_filename_display_name is ideal, but >= glib 2.6, so: - // a hand-rolled hacky makeASCII which disallows control chars - std::string display_name; - for (const gchar *str = (const gchar *)data; *str; str++) - { - display_name += (char)((*str >= 0x20 && *str <= 0x7E) ? *str : '?'); - } - LL_WARNS() << "g_filename_to_utf8 failed on \"" << display_name << "\": " << error->message << LL_ENDL; - } - - if (filename_utf8) - { - picker->mFiles.push_back(std::string(filename_utf8)); - LL_DEBUGS() << "ADDED FILE " << filename_utf8 << LL_ENDL; - g_free(filename_utf8); - } - - setlocale(LC_ALL, saved_locale.c_str()); -} - -// static -void LLFilePicker::chooser_responder(GtkWidget *widget, gint response, gpointer user_data) -{ - LLFilePicker* picker = (LLFilePicker*)user_data; - - LL_DEBUGS() << "GTK DIALOG RESPONSE " << response << LL_ENDL; - - if (response == GTK_RESPONSE_ACCEPT) - { - GSList *file_list = gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(widget)); - g_slist_foreach(file_list, (GFunc)add_to_selectedfiles, user_data); - g_slist_foreach(file_list, (GFunc)g_free, NULL); - g_slist_free (file_list); - } - - // let's save the extension of the last added file(considering current filter) - GtkFileFilter *gfilter = gtk_file_chooser_get_filter(GTK_FILE_CHOOSER(widget)); - if(gfilter) - { - std::string filter = gtk_file_filter_get_name(gfilter); - - if(filter == LLTrans::getString("png_image_files")) - { - picker->mCurrentExtension = ".png"; - } - else if(filter == LLTrans::getString("targa_image_files")) - { - picker->mCurrentExtension = ".tga"; - } - } - - // set the default path for this usage context. - const char* cur_folder = gtk_file_chooser_get_current_folder(GTK_FILE_CHOOSER(widget)); - if (cur_folder != NULL) - { - picker->mContextToPathMap[picker->mCurContextName] = cur_folder; - } - - gtk_widget_destroy(widget); - gtk_main_quit(); -} - - -GtkWindow* LLFilePicker::buildFilePicker(bool is_save, bool is_folder, std::string context) -{ -#ifndef LL_MESA_HEADLESS - if (LLWindowSDL::ll_try_gtk_init()) - { - GtkWidget *win = NULL; - GtkFileChooserAction pickertype = - is_save? - (is_folder? - GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER : - GTK_FILE_CHOOSER_ACTION_SAVE) : - (is_folder? - GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER : - GTK_FILE_CHOOSER_ACTION_OPEN); - - win = gtk_file_chooser_dialog_new(NULL, NULL, - pickertype, - GTK_STOCK_CANCEL, - GTK_RESPONSE_CANCEL, - is_folder ? - GTK_STOCK_APPLY : - (is_save ? - GTK_STOCK_SAVE : - GTK_STOCK_OPEN), - GTK_RESPONSE_ACCEPT, - (gchar *)NULL); - mCurContextName = context; - - // get the default path for this usage context if it's been - // seen before. - std::map<std::string,std::string>::iterator - this_path = mContextToPathMap.find(context); - if (this_path != mContextToPathMap.end()) - { - gtk_file_chooser_set_current_folder - (GTK_FILE_CHOOSER(win), - this_path->second.c_str()); - } - -# if LL_X11 - // Make GTK tell the window manager to associate this - // dialog with our non-GTK raw X11 window, which should try - // to keep it on top etc. - Window XWindowID = LLWindowSDL::get_SDL_XWindowID(); - if (None != XWindowID) - { - gtk_widget_realize(GTK_WIDGET(win)); // so we can get its gdkwin - GdkWindow *gdkwin = gdk_window_foreign_new(XWindowID); - gdk_window_set_transient_for(GTK_WIDGET(win)->window, - gdkwin); - } - else - { - LL_WARNS() << "Hmm, couldn't get xwid to use for transient." << LL_ENDL; - } -# endif //LL_X11 - - g_signal_connect (GTK_FILE_CHOOSER(win), - "response", - G_CALLBACK(LLFilePicker::chooser_responder), - this); - - gtk_window_set_modal(GTK_WINDOW(win), TRUE); +#elif LL_LINUX || __FreeBSD__ - /* GTK 2.6: if (is_folder) - gtk_file_chooser_set_show_hidden(GTK_FILE_CHOOSER(win), - TRUE); */ +#if LL_FLTK - return GTK_WINDOW(win); - } - else - { - return NULL; - } -#else - return NULL; -#endif //LL_MESA_HEADLESS -} - -static void add_common_filters_to_gtkchooser(GtkFileFilter *gfilter, - GtkWindow *picker, - std::string filtername) -{ - gtk_file_filter_set_name(gfilter, filtername.c_str()); - gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(picker), - gfilter); - GtkFileFilter *allfilter = gtk_file_filter_new(); - gtk_file_filter_add_pattern(allfilter, "*"); - gtk_file_filter_set_name(allfilter, LLTrans::getString("all_files").c_str()); - gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(picker), allfilter); - gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(picker), gfilter); -} - -static std::string add_simple_pattern_filter_to_gtkchooser(GtkWindow *picker, - std::string pattern, - std::string filtername) -{ - GtkFileFilter *gfilter = gtk_file_filter_new(); - gtk_file_filter_add_pattern(gfilter, pattern.c_str()); - add_common_filters_to_gtkchooser(gfilter, picker, filtername); - return filtername; -} - -static std::string add_simple_mime_filter_to_gtkchooser(GtkWindow *picker, - std::string mime, - std::string filtername) -{ - GtkFileFilter *gfilter = gtk_file_filter_new(); - gtk_file_filter_add_mime_type(gfilter, mime.c_str()); - add_common_filters_to_gtkchooser(gfilter, picker, filtername); - return filtername; -} - -static std::string add_wav_filter_to_gtkchooser(GtkWindow *picker) +bool LLFilePicker::getSaveFileModeless(ESaveFilter filter, + const std::string& filename, + void (*callback)(bool, std::string&, void*), + void *userdata) { - return add_simple_mime_filter_to_gtkchooser(picker, "audio/x-wav", - LLTrans::getString("sound_files") + " (*.wav)"); + LL_ERRS() << "NOT IMPLEMENTED" << LL_ENDL; + return FALSE; } -static std::string add_anim_filter_to_gtkchooser(GtkWindow *picker) +bool LLFilePicker::getOpenFileModeless(ELoadFilter filter, + void (*callback)(bool, std::vector<std::string> &, void*), + void *userdata) { - GtkFileFilter *gfilter = gtk_file_filter_new(); - gtk_file_filter_add_pattern(gfilter, "*.bvh"); - gtk_file_filter_add_pattern(gfilter, "*.anim"); - std::string filtername = LLTrans::getString("animation_files") + " (*.bvh; *.anim)"; - add_common_filters_to_gtkchooser(gfilter, picker, filtername); - return filtername; + LL_ERRS() << "NOT IMPLEMENTED" << LL_ENDL; + return FALSE; } -static std::string add_xml_filter_to_gtkchooser(GtkWindow *picker) +bool LLFilePicker::getMultipleOpenFilesModeless(ELoadFilter filter, + void (*callback)(bool, std::vector<std::string> &, void*), + void *userdata ) { - return add_simple_pattern_filter_to_gtkchooser(picker, "*.xml", - LLTrans::getString("xml_files") + " (*.xml)"); + LL_ERRS() << "NOT IMPLEMENTED" << LL_ENDL; + return FALSE; } -static std::string add_collada_filter_to_gtkchooser(GtkWindow *picker) -{ - return add_simple_pattern_filter_to_gtkchooser(picker, "*.dae", - LLTrans::getString("scene_files") + " (*.dae)"); -} -static std::string add_imageload_filter_to_gtkchooser(GtkWindow *picker) -{ - GtkFileFilter *gfilter = gtk_file_filter_new(); - gtk_file_filter_add_pattern(gfilter, "*.tga"); - gtk_file_filter_add_mime_type(gfilter, HTTP_CONTENT_IMAGE_JPEG.c_str()); - gtk_file_filter_add_mime_type(gfilter, HTTP_CONTENT_IMAGE_PNG.c_str()); - gtk_file_filter_add_mime_type(gfilter, HTTP_CONTENT_IMAGE_BMP.c_str()); - std::string filtername = LLTrans::getString("image_files") + " (*.tga; *.bmp; *.jpg; *.png)"; - add_common_filters_to_gtkchooser(gfilter, picker, filtername); - return filtername; -} -static std::string add_script_filter_to_gtkchooser(GtkWindow *picker) +bool LLFilePicker::getSaveFile( ESaveFilter filter, const std::string& filename, bool blocking ) { - return add_simple_mime_filter_to_gtkchooser(picker, HTTP_CONTENT_TEXT_PLAIN, - LLTrans::getString("script_files") + " (*.lsl)"); + return openFileDialog( filter, blocking, eSaveFile ); } -static std::string add_dictionary_filter_to_gtkchooser(GtkWindow *picker) +bool LLFilePicker::getOpenFile( ELoadFilter filter, bool blocking ) { - return add_simple_mime_filter_to_gtkchooser(picker, HTTP_CONTENT_TEXT_PLAIN, - LLTrans::getString("dictionary_files") + " (*.dic; *.xcu)"); + return openFileDialog( filter, blocking, eOpenFile ); } -static std::string add_save_texture_filter_to_gtkchooser(GtkWindow *picker) +bool LLFilePicker::getMultipleOpenFiles( ELoadFilter filter, bool blocking) { - GtkFileFilter *gfilter_tga = gtk_file_filter_new(); - GtkFileFilter *gfilter_png = gtk_file_filter_new(); - - gtk_file_filter_add_pattern(gfilter_tga, "*.tga"); - gtk_file_filter_add_mime_type(gfilter_png, "image/png"); - std::string caption = LLTrans::getString("save_texture_image_files") + " (*.tga; *.png)"; - gtk_file_filter_set_name(gfilter_tga, LLTrans::getString("targa_image_files").c_str()); - gtk_file_filter_set_name(gfilter_png, LLTrans::getString("png_image_files").c_str()); - - gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(picker), - gfilter_png); - gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(picker), - gfilter_tga); - return caption; + return openFileDialog( filter, blocking, eOpenMultiple ); } -bool LLFilePicker::getSaveFile( ESaveFilter filter, const std::string& filename, bool blocking ) +bool LLFilePicker::openFileDialog( int32_t filter, bool blocking, EType aType ) { - bool rtn = false; - - // if local file browsing is turned off, return without opening dialog - if (!check_local_file_access_enabled()) - { + if ( check_local_file_access_enabled() == false ) return false; - } - gViewerWindow->getWindow()->beforeDialog(); - reset(); - - GtkWindow* picker = buildFilePicker(true, false, "savefile"); - - if (picker) - { - std::string suggest_name = "untitled"; - std::string suggest_ext = ""; - std::string caption = LLTrans::getString("save_file_verb") + " "; - switch (filter) + Fl_Native_File_Chooser::Type flType = Fl_Native_File_Chooser::BROWSE_FILE; + if( aType == eOpenMultiple ) + flType = Fl_Native_File_Chooser::BROWSE_MULTI_FILE; + else if( aType == eSaveFile ) + flType = Fl_Native_File_Chooser::BROWSE_SAVE_FILE; + Fl_Native_File_Chooser flDlg; + std::string file_dialog_title; + std::string file_dialog_filter; + if (aType == EType::eSaveFile) + { + std::string file_type("all_files"); + switch ((ESaveFilter) filter) { - case FFSAVE_WAV: - caption += add_wav_filter_to_gtkchooser(picker); - suggest_ext = ".wav"; - break; - case FFSAVE_TGA: - caption += add_simple_pattern_filter_to_gtkchooser - (picker, "*.tga", LLTrans::getString("targa_image_files") + " (*.tga)"); - suggest_ext = ".tga"; - break; - case FFSAVE_BMP: - caption += add_simple_mime_filter_to_gtkchooser - (picker, HTTP_CONTENT_IMAGE_BMP, LLTrans::getString("bitmap_image_files") + " (*.bmp)"); - suggest_ext = ".bmp"; - break; - case FFSAVE_PNG: - caption += add_simple_mime_filter_to_gtkchooser - (picker, "image/png", LLTrans::getString("png_image_files") + " (*.png)"); - suggest_ext = ".png"; - break; - case FFSAVE_TGAPNG: - caption += add_save_texture_filter_to_gtkchooser(picker); - suggest_ext = ".png"; - break; - case FFSAVE_AVI: - caption += add_simple_mime_filter_to_gtkchooser - (picker, "video/x-msvideo", - LLTrans::getString("avi_movie_file") + " (*.avi)"); - suggest_ext = ".avi"; - break; - case FFSAVE_ANIM: - caption += add_simple_pattern_filter_to_gtkchooser - (picker, "*.xaf", LLTrans::getString("xaf_animation_file") + " (*.xaf)"); - suggest_ext = ".xaf"; - break; - case FFSAVE_XML: - caption += add_simple_pattern_filter_to_gtkchooser - (picker, "*.xml", LLTrans::getString("xml_file") + " (*.xml)"); - suggest_ext = ".xml"; - break; - case FFSAVE_RAW: - caption += add_simple_pattern_filter_to_gtkchooser - (picker, "*.raw", LLTrans::getString("raw_file") + " (*.raw)"); - suggest_ext = ".raw"; - break; - case FFSAVE_J2C: - // *TODO: Should this be 'image/j2c' ? - caption += add_simple_mime_filter_to_gtkchooser - (picker, "images/jp2", - LLTrans::getString("compressed_image_files") + " (*.j2c)"); - suggest_ext = ".j2c"; - break; - case FFSAVE_SCRIPT: - caption += add_script_filter_to_gtkchooser(picker); - suggest_ext = ".lsl"; - break; - default:; - break; + case FFSAVE_ALL: + break; + case FFSAVE_TGA: + file_type = "targa_image_files"; + file_dialog_filter = "*.tga"; + break; + case FFSAVE_BMP: + file_type = "bitmap_image_files"; + file_dialog_filter = "*.bmp"; + break; + case FFSAVE_AVI: + file_type = "avi_movie_file"; + file_dialog_filter = "*.avi"; + break; + case FFSAVE_ANIM: + file_type = "xaf_animation_file"; + file_dialog_filter = "*.xaf"; + break; + case FFSAVE_XML: + file_type = "xml_file"; + file_dialog_filter = "*.xml"; + break; + case FFSAVE_COLLADA: + file_type = "collada_files"; + file_dialog_filter = "*.dae"; + break; + case FFSAVE_RAW: + file_type = "raw_file"; + file_dialog_filter = "*.raw"; + break; + case FFSAVE_J2C: + file_type = "compressed_image_files"; + file_dialog_filter = "*.j2c"; + break; + case FFSAVE_PNG: + file_type = "png_image_files"; + file_dialog_filter = "*.png"; + break; + case FFSAVE_JPEG: + file_type = "jpeg_image_files"; + file_dialog_filter = "*.{jpg,jpeg}"; + break; + case FFSAVE_SCRIPT: + file_type = "script_files"; + file_dialog_filter = "*.lsl"; + break; + case FFSAVE_TGAPNG: + file_type = "save_texture_image_files"; + file_dialog_filter = "*.{tga,png}"; + break; + case FFSAVE_WAV: + file_type = "sound_files"; + file_dialog_filter = "*.wav"; + break; + case FFSAVE_GLTF: + file_type = "gltf_asset_file"; + file_dialog_filter = "*.{gltf,glb}"; + break; } - - gtk_window_set_title(GTK_WINDOW(picker), caption.c_str()); - - if (filename.empty()) + file_dialog_title = LLTrans::getString("save_file_verb") + " " + LLTrans::getString(file_type); + file_dialog_filter = LLTrans::getString(file_type) + " \t" + file_dialog_filter; + } + else + { + std::string file_type("all_files"); + switch ((ELoadFilter) filter) { - suggest_name += suggest_ext; + case FFLOAD_ALL: + break; + case FFLOAD_WAV: + file_type = "sound_files"; + file_dialog_filter = "*.wav"; + break; + case FFLOAD_IMAGE: + file_type = "image_files"; + file_dialog_filter = "*.{tga,bmp,jpg,jpeg,png}"; + break; + case FFLOAD_ANIM: + file_type = "animation_files"; + file_dialog_filter = "*.{bvh,anim}"; + break; + case FFLOAD_XML: + file_type = "xml_file"; + file_dialog_filter = "*.xml"; + break; + case FFLOAD_SLOBJECT: + file_type = "xml_file"; + file_dialog_filter = "*.slobject"; + break; + case FFLOAD_RAW: + file_type = "raw_file"; + file_dialog_filter = "*.raw"; + break; + case FFLOAD_MODEL: + case FFLOAD_COLLADA: + file_type = "collada_files"; + file_dialog_filter = "*.dae"; + break; + case FFLOAD_SCRIPT: + file_type = "script_files"; + file_dialog_filter = "*.lsl"; + break; + case FFLOAD_DICTIONARY: + file_type = "dictionary_files"; + file_dialog_filter = "*.{dic,xcu}"; + break; + case FFLOAD_DIRECTORY: + file_type = "choose_the_directory"; + break; + case FFLOAD_EXE: + file_type = "executable_files"; + break; + case FFLOAD_GLTF: + case FFLOAD_MATERIAL: + file_type = "gltf_asset_file"; + file_dialog_filter = "*.{gltg,glb}"; + break; + case FFLOAD_MATERIAL_TEXTURE: + file_dialog_filter = "*.{gltf,glb,tga,bmp,jpg,jpeg,png}"; + file_type = "image_files"; + break; + case FFLOAD_HDRI: + file_dialog_filter = "*.exr"; - gtk_file_chooser_set_current_name - (GTK_FILE_CHOOSER(picker), - suggest_name.c_str()); } - else + if (aType == EType::eOpenMultiple) { - gtk_file_chooser_set_current_name - (GTK_FILE_CHOOSER(picker), filename.c_str()); + file_dialog_title = LLTrans::getString("load_files"); } - - gtk_widget_show_all(GTK_WIDGET(picker)); - - gtk_main(); - - rtn = (getFileCount() == 1); - - if(rtn && filter == FFSAVE_TGAPNG) + else { - std::string selected_file = mFiles.back(); - mFiles.pop_back(); - mFiles.push_back(selected_file + mCurrentExtension); + file_dialog_title = LLTrans::getString("load_file_verb") + " " + LLTrans::getString(file_type); + file_dialog_filter = LLTrans::getString(file_type) + " \t" + file_dialog_filter; } } - - gViewerWindow->getWindow()->afterDialog(); - - return rtn; -} - -bool LLFilePicker::getOpenFile( ELoadFilter filter, bool blocking ) -{ - bool rtn = false; - - // if local file browsing is turned off, return without opening dialog - if (!check_local_file_access_enabled()) + flDlg.title(file_dialog_title.c_str()); + flDlg.type(flType); + if (!file_dialog_filter.empty()) { - return false; + flDlg.filter(file_dialog_filter.c_str()); } - - gViewerWindow->getWindow()->beforeDialog(); - - reset(); - - GtkWindow* picker = buildFilePicker(false, false, "openfile"); - - if (picker) + int res = flDlg.show(); + gViewerWindow->getWindow()->afterDialog(); + if( res == 0 ) { - std::string caption = LLTrans::getString("load_file_verb") + " "; - std::string filtername = ""; - switch (filter) + int32_t count = flDlg.count(); + if( count < 0 ) + count = 0; + for( int32_t i = 0; i < count; ++i ) { - case FFLOAD_WAV: - filtername = add_wav_filter_to_gtkchooser(picker); - break; - case FFLOAD_ANIM: - filtername = add_anim_filter_to_gtkchooser(picker); - break; - case FFLOAD_XML: - filtername = add_xml_filter_to_gtkchooser(picker); - break; - case FFLOAD_GLTF: - filtername = dead_code_should_blow_up_here(picker); - break; - case FFLOAD_COLLADA: - filtername = add_collada_filter_to_gtkchooser(picker); - break; - case FFLOAD_IMAGE: - filtername = add_imageload_filter_to_gtkchooser(picker); - break; - case FFLOAD_SCRIPT: - filtername = add_script_filter_to_gtkchooser(picker); - break; - case FFLOAD_DICTIONARY: - filtername = add_dictionary_filter_to_gtkchooser(picker); - break; - default:; - break; + char const *pFile = flDlg.filename(i); + if( pFile && strlen(pFile) > 0 ) + mFiles.push_back( pFile ); } - - caption += filtername; - - gtk_window_set_title(GTK_WINDOW(picker), caption.c_str()); - - gtk_widget_show_all(GTK_WIDGET(picker)); - gtk_main(); - - rtn = (getFileCount() == 1); - } - - gViewerWindow->getWindow()->afterDialog(); - - return rtn; -} - -bool LLFilePicker::getMultipleOpenFiles( ELoadFilter filter, bool blocking) -{ - bool rtn = false; - - // if local file browsing is turned off, return without opening dialog - if (!check_local_file_access_enabled()) - { - return false; } - - gViewerWindow->getWindow()->beforeDialog(); - - reset(); - - GtkWindow* picker = buildFilePicker(false, false, "openfile"); - - if (picker) + else if( res == -1 ) { - gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER(picker), - TRUE); - - gtk_window_set_title(GTK_WINDOW(picker), LLTrans::getString("load_files").c_str()); - - gtk_widget_show_all(GTK_WIDGET(picker)); - gtk_main(); - rtn = !mFiles.empty(); + LL_WARNS() << "FLTK failed: " << flDlg.errmsg() << LL_ENDL; } - - gViewerWindow->getWindow()->afterDialog(); - - return rtn; + return mFiles.empty()?FALSE:TRUE; } - -# else // LL_GTK - +#else // Hacky stubs designed to facilitate fake getSaveFile and getOpenFile with // static results, when we don't have a real filepicker. @@ -1671,17 +1420,17 @@ bool LLFilePicker::getMultipleOpenFilesModeless(ELoadFilter filter, return false; } -#endif // LL_GTK +#endif // LL_FLTK #else // not implemented -bool LLFilePicker::getSaveFile( ESaveFilter filter, const std::string& filename ) +bool LLFilePicker::getSaveFile( ESaveFilter filter, const std::string& filename, bool blocking ) { reset(); return false; } -bool LLFilePicker::getOpenFile( ELoadFilter filter ) +bool LLFilePicker::getOpenFile( ELoadFilter filter, bool blocking ) { reset(); return false; diff --git a/indra/newview/llfilepicker.h b/indra/newview/llfilepicker.h index 75ff14f4cf..b99156c61e 100644 --- a/indra/newview/llfilepicker.h +++ b/indra/newview/llfilepicker.h @@ -54,19 +54,8 @@ #include <commdlg.h> #endif -extern "C" { -// mostly for Linux, possible on others -#if LL_GTK -# include "gtk/gtk.h" -#endif // LL_GTK -} - class LLFilePicker { -#ifdef LL_GTK - friend class LLDirPicker; - friend void chooser_responder(GtkWidget *, gint, gpointer); -#endif // LL_GTK public: // calling this before main() is undefined static LLFilePicker& instance( void ) { return sInstance; } @@ -184,14 +173,12 @@ private: void *userdata); #endif -#if LL_GTK - static void add_to_selectedfiles(gpointer data, gpointer user_data); - static void chooser_responder(GtkWidget *widget, gint response, gpointer user_data); - // we remember the last path that was accessed for a particular usage - std::map <std::string, std::string> mContextToPathMap; - std::string mCurContextName; - // we also remember the extension of the last added file. - std::string mCurrentExtension; +#if LL_FLTK + enum EType + { + eSaveFile, eOpenFile, eOpenMultiple + }; + bool openFileDialog( int32_t filter, bool blocking, EType aType ); #endif std::vector<std::string> mFiles; @@ -200,12 +187,6 @@ private: static LLFilePicker sInstance; -protected: -#if LL_GTK - GtkWindow* buildFilePicker(bool is_save, bool is_folder, - std::string context = "generic"); -#endif - public: // don't call these directly please. LLFilePicker(); diff --git a/indra/newview/llfloatercamera.cpp b/indra/newview/llfloatercamera.cpp index 4a5a755696..76ac730362 100644 --- a/indra/newview/llfloatercamera.cpp +++ b/indra/newview/llfloatercamera.cpp @@ -478,10 +478,8 @@ bool LLFloaterCamera::postBuild() mZoom = getChild<LLPanelCameraZoom>(ZOOM); mTrack = getChild<LLJoystickCameraTrack>(PAN); mPresetCombo = getChild<LLComboBox>("preset_combo"); - mPreciseCtrls = getChild<LLTextBox>("precise_ctrs_label"); + mPreciseCtrls = getChild<LLButton>("precise_btn"); - mPreciseCtrls->setShowCursorHand(false); - mPreciseCtrls->setSoundFlags(LLView::MOUSE_UP); mPreciseCtrls->setClickedCallback(boost::bind(&LLFloaterReg::showInstance, "prefs_view_advanced", LLSD(), false)); mPresetCombo->setCommitCallback(boost::bind(&LLFloaterCamera::onCustomPresetSelected, this)); @@ -492,6 +490,11 @@ bool LLFloaterCamera::postBuild() // ensure that appearance mode is handled while building. See EXT-7796. handleAvatarEditingAppearance(sAppearanceEditing); + mCollapseCtrl = getChild<LLButton>("collapse_btn"); + mCollapseCtrl->setCommitCallback(boost::bind(&LLFloaterCamera::toggleCollapsedView, this)); + + updateCollapsedView(); + return LLFloater::postBuild(); } @@ -736,3 +739,19 @@ void LLFloaterCamera::onCustomPresetSelected() switchToPreset(selected_preset); } } + +void LLFloaterCamera::toggleCollapsedView() +{ + BOOL isCollapsed = gSavedSettings.getBOOL("MPVCameraCollapsed"); + gSavedSettings.setBOOL("MPVCameraCollapsed", !isCollapsed); + updateCollapsedView(); +} + +void LLFloaterCamera::updateCollapsedView() +{ + BOOL isCollapsed = gSavedSettings.getBOOL("MPVCameraCollapsed"); + mCollapseCtrl->setImageOverlay(!isCollapsed ? "Conv_toolbar_collapse" : "Conv_toolbar_expand"); + getChild<LLPanel>("buttons_panel")->setVisible(!isCollapsed); + //mPreciseCtrls->setVisible(!collapse); + reshape(!isCollapsed ? 410 : 220, getRect().getHeight(), FALSE); +} diff --git a/indra/newview/llfloatercamera.h b/indra/newview/llfloatercamera.h index ece3d8218e..7db903f470 100644 --- a/indra/newview/llfloatercamera.h +++ b/indra/newview/llfloatercamera.h @@ -122,6 +122,9 @@ private: void showDebugInfo(bool show); + void toggleCollapsedView(); + void updateCollapsedView(); + // set to true when free camera mode is selected in modes list // remains true until preset camera mode is chosen, or pan button is clicked, or escape pressed static bool sFreeCamera; @@ -135,7 +138,8 @@ private: LLPanel* mViewerCameraInfo { nullptr }; LLPanel* mAgentCameraInfo { nullptr }; LLComboBox* mPresetCombo { nullptr }; - LLTextBox* mPreciseCtrls { nullptr }; + LLButton* mPreciseCtrls { nullptr }; + LLButton* mCollapseCtrl { nullptr }; }; /** diff --git a/indra/newview/llfloatercreatelandmark.cpp b/indra/newview/llfloatercreatelandmark.cpp index 2ce8a7a212..77ea544c5d 100644 --- a/indra/newview/llfloatercreatelandmark.cpp +++ b/indra/newview/llfloatercreatelandmark.cpp @@ -31,6 +31,7 @@ #include "llagent.h" #include "llagentui.h" #include "llcombobox.h" +#include "llfloaterreg.h" #include "llinventoryfunctions.h" #include "llinventoryobserver.h" #include "lllandmarkactions.h" @@ -286,8 +287,7 @@ void LLFloaterCreateLandmark::onCreateFolderClicked() std::string folder_name = resp["message"].asString(); if (!folder_name.empty()) { - inventory_func_type func = boost::bind(&LLFloaterCreateLandmark::folderCreatedCallback, this, _1); - gInventory.createNewCategory(mLandmarksID, LLFolderType::FT_NONE, folder_name, func); + gInventory.createNewCategory(mLandmarksID, LLFolderType::FT_NONE, folder_name, folderCreatedCallback); gInventory.notifyObservers(); } } @@ -296,7 +296,11 @@ void LLFloaterCreateLandmark::onCreateFolderClicked() void LLFloaterCreateLandmark::folderCreatedCallback(LLUUID folder_id) { - populateFoldersList(folder_id); + LLFloaterCreateLandmark* floater = LLFloaterReg::findTypedInstance<LLFloaterCreateLandmark>("add_landmark"); + if (floater && !floater->isDead()) + { + floater->populateFoldersList(folder_id); + } } void LLFloaterCreateLandmark::onSaveClicked() @@ -389,6 +393,7 @@ void LLFloaterCreateLandmark::setItem(const uuid_set_t& items) { mItem = item; mAssetID = mItem->getAssetUUID(); + mParentID = mItem->getParentUUID(); setVisibleAndFrontmost(true); break; } @@ -418,8 +423,7 @@ void LLFloaterCreateLandmark::updateItem(const uuid_set_t& items, U32 mask) closeFloater(); } - LLUUID folder_id = mFolderCombo->getValue().asUUID(); - if (folder_id != mItem->getParentUUID()) + if (mParentID != mItem->getParentUUID()) { // user moved landmark in inventory, // assume that we are done all other changes should already be commited diff --git a/indra/newview/llfloatercreatelandmark.h b/indra/newview/llfloatercreatelandmark.h index fa6d001b8e..bcf9d8578c 100644 --- a/indra/newview/llfloatercreatelandmark.h +++ b/indra/newview/llfloatercreatelandmark.h @@ -62,13 +62,14 @@ private: void onSaveClicked(); void onCancelClicked(); - void folderCreatedCallback(LLUUID folder_id); + static void folderCreatedCallback(LLUUID folder_id); LLComboBox* mFolderCombo; LLLineEditor* mLandmarkTitleEditor; LLTextEditor* mNotesEditor; LLUUID mLandmarksID; LLUUID mAssetID; + LLUUID mParentID; LLLandmarksInventoryObserver* mInventoryObserver; LLPointer<LLInventoryItem> mItem; diff --git a/indra/newview/llfloateremojipicker.cpp b/indra/newview/llfloateremojipicker.cpp index d38f53eed6..a8eea23e4b 100644 --- a/indra/newview/llfloateremojipicker.cpp +++ b/indra/newview/llfloateremojipicker.cpp @@ -57,8 +57,7 @@ static const S32 USED_EMOJIS_IMAGE_INDEX = 0x23F2; // https://www.compart.com/en/unicode/U+1F6D1 static const S32 EMPTY_LIST_IMAGE_INDEX = 0x1F6D1; // The following categories should follow the required alphabetic order -static const std::string RECENTLY_USED_CATEGORY = "1 recently used"; -static const std::string FREQUENTLY_USED_CATEGORY = "2 frequently used"; +static const std::string FREQUENTLY_USED_CATEGORY = "frequently used"; // Floater state related variables static std::list<llwchar> sRecentlyUsed; @@ -436,6 +435,7 @@ void LLFloaterEmojiPicker::fillGroups() LLButton::Params params; params.font = LLFontGL::getFontEmojiLarge(); + params.name = "all_categories"; LLRect rect; rect.mTop = mGroups->getRect().getHeight(); @@ -444,11 +444,10 @@ void LLFloaterEmojiPicker::fillGroups() // Create button for "All categories" createGroupButton(params, rect, ALL_EMOJIS_IMAGE_INDEX); - // Create group and button for "Recently used" and/or "Frequently used" - if (!sRecentlyUsed.empty() || !sFrequentlyUsed.empty()) + // Create group and button for "Frequently used" + if (!sFrequentlyUsed.empty()) { std::map<std::string, std::vector<LLEmojiSearchResult>> cats; - fillCategoryRecentlyUsed(cats); fillCategoryFrequentlyUsed(cats); if (!cats.empty()) @@ -479,40 +478,6 @@ void LLFloaterEmojiPicker::fillGroups() resizeGroupButtons(); } -void LLFloaterEmojiPicker::fillCategoryRecentlyUsed(std::map<std::string, std::vector<LLEmojiSearchResult>>& cats) -{ - if (sRecentlyUsed.empty()) - return; - - std::vector<LLEmojiSearchResult> emojis; - - // In case of empty mFilterPattern we'd use sRecentlyUsed directly - if (!mFilterPattern.empty()) - { - // List all emojis in "Recently used" - const LLEmojiDictionary::emoji2descr_map_t& emoji2descr = LLEmojiDictionary::instance().getEmoji2Descr(); - std::size_t begin, end; - for (llwchar emoji : sRecentlyUsed) - { - auto e2d = emoji2descr.find(emoji); - if (e2d != emoji2descr.end() && !e2d->second->ShortCodes.empty()) - { - for (const std::string& shortcode : e2d->second->ShortCodes) - { - if (LLEmojiDictionary::searchInShortCode(begin, end, shortcode, mFilterPattern)) - { - emojis.emplace_back(emoji, shortcode, begin, end); - } - } - } - } - if (emojis.empty()) - return; - } - - cats.emplace(std::make_pair(RECENTLY_USED_CATEGORY, emojis)); -} - void LLFloaterEmojiPicker::fillCategoryFrequentlyUsed(std::map<std::string, std::vector<LLEmojiSearchResult>>& cats) { if (sFrequentlyUsed.empty()) @@ -754,7 +719,6 @@ void LLFloaterEmojiPicker::fillEmojisCategory(const std::vector<LLEmojiSearchRes { // Place the category title std::string title = - category == RECENTLY_USED_CATEGORY ? getString("title_for_recently_used") : category == FREQUENTLY_USED_CATEGORY ? getString("title_for_frequently_used") : isupper(category.front()) ? category : LLStringUtil::capitalize(category); LLEmojiGridDivider* div = new LLEmojiGridDivider(row_panel_params, title); @@ -767,21 +731,7 @@ void LLFloaterEmojiPicker::fillEmojisCategory(const std::vector<LLEmojiSearchRes { const LLEmojiDictionary::emoji2descr_map_t& emoji2descr = LLEmojiDictionary::instance().getEmoji2Descr(); LLEmojiSearchResult emoji { 0, "", 0, 0 }; - if (category == RECENTLY_USED_CATEGORY) - { - for (llwchar code : sRecentlyUsed) - { - const LLEmojiDictionary::emoji2descr_map_t::const_iterator& e2d = emoji2descr.find(code); - if (e2d != emoji2descr.end() && !e2d->second->ShortCodes.empty()) - { - emoji.Character = code; - emoji.String = e2d->second->ShortCodes.front(); - createEmojiIcon(emoji, category, row_panel_params, row_list_params, icon_params, - icon_rect, max_icons, bg, row, icon_index); - } - } - } - else if (category == FREQUENTLY_USED_CATEGORY) + if (category == FREQUENTLY_USED_CATEGORY) { for (const auto& code : sFrequentlyUsed) { diff --git a/indra/newview/llfloateremojipicker.h b/indra/newview/llfloateremojipicker.h index 669683eb9e..b807adb67d 100644 --- a/indra/newview/llfloateremojipicker.h +++ b/indra/newview/llfloateremojipicker.h @@ -60,7 +60,6 @@ public: private: void initialize(); void fillGroups(); - void fillCategoryRecentlyUsed(std::map<std::string, std::vector<LLEmojiSearchResult>>& cats); void fillCategoryFrequentlyUsed(std::map<std::string, std::vector<LLEmojiSearchResult>>& cats); void fillGroupEmojis(std::map<std::string, std::vector<LLEmojiSearchResult>>& cats, U32 index); void createGroupButton(LLButton::Params& params, const LLRect& rect, llwchar emoji); diff --git a/indra/newview/llfloaterperformance.cpp b/indra/newview/llfloaterperformance.cpp index 3a633a7ff8..01579ac165 100644 --- a/indra/newview/llfloaterperformance.cpp +++ b/indra/newview/llfloaterperformance.cpp @@ -115,12 +115,12 @@ bool LLFloaterPerformance::postBuild() mHUDList = mHUDsPanel->getChild<LLNameListCtrl>("hud_list"); mHUDList->setNameListType(LLNameListCtrl::SPECIAL); mHUDList->setHoverIconName("StopReload_Off"); - mHUDList->setIconClickedCallback(boost::bind(&LLFloaterPerformance::detachItem, this, _1)); + mHUDList->setIconClickedCallback(boost::bind(&LLFloaterPerformance::detachObject, this, _1)); mObjectList = mComplexityPanel->getChild<LLNameListCtrl>("obj_list"); mObjectList->setNameListType(LLNameListCtrl::SPECIAL); mObjectList->setHoverIconName("StopReload_Off"); - mObjectList->setIconClickedCallback(boost::bind(&LLFloaterPerformance::detachItem, this, _1)); + mObjectList->setIconClickedCallback(boost::bind(&LLFloaterPerformance::detachObject, this, _1)); mSettingsPanel->getChild<LLButton>("advanced_btn")->setCommitCallback(boost::bind(&LLFloaterPerformance::onClickAdvanced, this)); mSettingsPanel->getChild<LLButton>("defaults_btn")->setCommitCallback(boost::bind(&LLFloaterPerformance::onClickDefaults, this)); @@ -524,9 +524,13 @@ void LLFloaterPerformance::setFPSText() getChild<LLTextBox>("fps_lbl")->setValue(fps_text); } -void LLFloaterPerformance::detachItem(const LLUUID& item_id) +void LLFloaterPerformance::detachObject(const LLUUID& obj_id) { - LLAppearanceMgr::instance().removeItemFromAvatar(item_id); + LLViewerObject* obj = gObjectList.findObject(obj_id); + if (obj) + { + LLAppearanceMgr::instance().removeItemFromAvatar(obj->getAttachmentItemID()); + } } void LLFloaterPerformance::onClickAdvanced() diff --git a/indra/newview/llfloaterperformance.h b/indra/newview/llfloaterperformance.h index 089a508455..797b800b62 100644 --- a/indra/newview/llfloaterperformance.h +++ b/indra/newview/llfloaterperformance.h @@ -46,7 +46,7 @@ public: void hidePanels(); void showAutoadjustmentsPanel(); - void detachItem(const LLUUID& item_id); + void detachObject(const LLUUID& obj_id); void onAvatarListRightClick(LLUICtrl* ctrl, S32 x, S32 y); diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index 85a07f23a4..1b62f94a13 100644 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -329,6 +329,7 @@ LLFloaterPreference::LLFloaterPreference(const LLSD& key) mCommitCallbackRegistrar.add("Pref.AutoAdjustments", boost::bind(&LLFloaterPreference::onClickAutoAdjustments, this)); mCommitCallbackRegistrar.add("Pref.HardwareDefaults", boost::bind(&LLFloaterPreference::setHardwareDefaults, this)); mCommitCallbackRegistrar.add("Pref.AvatarImpostorsEnable", boost::bind(&LLFloaterPreference::onAvatarImpostorsEnable, this)); + mCommitCallbackRegistrar.add("Pref.UpdateIndirectMaxNonImpostors", boost::bind(&LLFloaterPreference::updateMaxNonImpostors, this)); mCommitCallbackRegistrar.add("Pref.UpdateIndirectMaxComplexity", boost::bind(&LLFloaterPreference::updateMaxComplexity, this)); mCommitCallbackRegistrar.add("Pref.RenderOptionUpdate", boost::bind(&LLFloaterPreference::onRenderOptionEnable, this)); mCommitCallbackRegistrar.add("Pref.WindowedMod", boost::bind(&LLFloaterPreference::onCommitWindowedMode, this)); @@ -360,6 +361,7 @@ LLFloaterPreference::LLFloaterPreference(const LLSD& key) LLAvatarPropertiesProcessor::getInstance()->addObserver( gAgent.getID(), this ); mComplexityChangedSignal = gSavedSettings.getControl("RenderAvatarMaxComplexity")->getCommitSignal()->connect(boost::bind(&LLFloaterPreference::updateComplexityText, this)); + mImpostorsChangedSignal = gSavedSettings.getControl("RenderAvatarMaxNonImpostors")->getSignal()->connect(boost::bind(&LLFloaterPreference::updateIndirectMaxNonImpostors, this, _2)); mCommitCallbackRegistrar.add("Pref.ClearLog", boost::bind(&LLConversationLog::onClearLog, &LLConversationLog::instance())); mCommitCallbackRegistrar.add("Pref.DeleteTranscripts", boost::bind(&LLFloaterPreference::onDeleteTranscripts, this)); @@ -536,6 +538,7 @@ LLFloaterPreference::~LLFloaterPreference() { LLConversationLog::instance().removeObserver(this); mComplexityChangedSignal.disconnect(); + mImpostorsChangedSignal.disconnect(); } void LLFloaterPreference::draw() @@ -1290,6 +1293,9 @@ void LLAvatarComplexityControls::setIndirectMaxArc() void LLFloaterPreference::refresh() { LLPanel::refresh(); + setMaxNonImpostorsText( + gSavedSettings.getU32("RenderAvatarMaxNonImpostors"), + getChild<LLTextBox>("IndirectMaxNonImpostorsText", true)); LLAvatarComplexityControls::setText( gSavedSettings.getU32("RenderAvatarMaxComplexity"), getChild<LLTextBox>("IndirectMaxComplexityText", true)); @@ -1568,6 +1574,44 @@ void LLAvatarComplexityControls::setRenderTimeText(F32 value, LLTextBox* text_bo } } +void LLFloaterPreference::updateMaxNonImpostors() +{ + // Called when the IndirectMaxNonImpostors control changes + // Responsible for fixing the slider label (IndirectMaxNonImpostorsText) and setting RenderAvatarMaxNonImpostors + LLSliderCtrl* ctrl = getChild<LLSliderCtrl>("IndirectMaxNonImpostors", true); + U32 value = ctrl->getValue().asInteger(); + + if (0 == value || LLVOAvatar::NON_IMPOSTORS_MAX_SLIDER <= value) + { + value = 0; + } + gSavedSettings.setU32("RenderAvatarMaxNonImpostors", value); + LLVOAvatar::updateImpostorRendering(value); // make it effective immediately + setMaxNonImpostorsText(value, getChild<LLTextBox>("IndirectMaxNonImpostorsText")); +} + +void LLFloaterPreference::updateIndirectMaxNonImpostors(const LLSD& newvalue) +{ + U32 value = newvalue.asInteger(); + if ((value != 0) && (value != gSavedSettings.getU32("IndirectMaxNonImpostors"))) + { + gSavedSettings.setU32("IndirectMaxNonImpostors", value); + } + setMaxNonImpostorsText(value, getChild<LLTextBox>("IndirectMaxNonImpostorsText")); +} + +void LLFloaterPreference::setMaxNonImpostorsText(U32 value, LLTextBox* text_box) +{ + if (0 == value) + { + text_box->setText(LLTrans::getString("no_limit")); + } + else + { + text_box->setText(llformat("%d", value)); + } +} + void LLFloaterPreference::updateMaxComplexity() { // Called when the IndirectMaxComplexity control changes diff --git a/indra/newview/llfloaterpreference.h b/indra/newview/llfloaterpreference.h index c8b98d8e1b..c26569f17c 100644 --- a/indra/newview/llfloaterpreference.h +++ b/indra/newview/llfloaterpreference.h @@ -206,6 +206,9 @@ private: void onDeleteTranscripts(); void onDeleteTranscriptsResponse(const LLSD& notification, const LLSD& response); void updateDeleteTranscriptsButton(); + void updateMaxNonImpostors(); + void updateIndirectMaxNonImpostors(const LLSD& newvalue); + void setMaxNonImpostorsText(U32 value, LLTextBox* text_box); void updateMaxComplexity(); void updateComplexityText(); static bool loadFromFilename(const std::string& filename, std::map<std::string, std::string> &label_map); @@ -229,6 +232,7 @@ private: std::unique_ptr< ll::prefs::SearchData > mSearchData; bool mSearchDataDirty; + boost::signals2::connection mImpostorsChangedSignal; boost::signals2::connection mComplexityChangedSignal; void onUpdateFilterTerm( bool force = false ); diff --git a/indra/newview/llfloaterpreferencesgraphicsadvanced.cpp b/indra/newview/llfloaterpreferencesgraphicsadvanced.cpp index 082a77d741..7c9fa161d5 100644 --- a/indra/newview/llfloaterpreferencesgraphicsadvanced.cpp +++ b/indra/newview/llfloaterpreferencesgraphicsadvanced.cpp @@ -250,8 +250,8 @@ void LLFloaterPreferenceGraphicsAdvanced::updateIndirectMaxNonImpostors(const LL if ((value != 0) && (value != gSavedSettings.getU32("IndirectMaxNonImpostors"))) { gSavedSettings.setU32("IndirectMaxNonImpostors", value); - setMaxNonImpostorsText(value, getChild<LLTextBox>("IndirectMaxNonImpostorsText")); } + setMaxNonImpostorsText(value, getChild<LLTextBox>("IndirectMaxNonImpostorsText")); } void LLFloaterPreferenceGraphicsAdvanced::setMaxNonImpostorsText(U32 value, LLTextBox* text_box) diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp index 3ef44bf74a..14ae03d9ce 100644 --- a/indra/newview/llfloaterregioninfo.cpp +++ b/indra/newview/llfloaterregioninfo.cpp @@ -4283,7 +4283,6 @@ void LLPanelRegionEnvironment::onChkAllowOverride(bool value) mAllowOverrideRestore = mAllowOverride; mAllowOverride = value; - std::string notification("EstateParcelEnvironmentOverride"); if (LLPanelEstateInfo::isLindenEstate()) notification = "ChangeLindenEstate"; diff --git a/indra/newview/llfloatertos.cpp b/indra/newview/llfloatertos.cpp index 8eec5b753a..63ba51e559 100644 --- a/indra/newview/llfloatertos.cpp +++ b/indra/newview/llfloatertos.cpp @@ -96,6 +96,8 @@ bool LLFloaterTOS::postBuild() external_prompt->setVisible(true); web_browser->setVisible(false); + + updateAgreeEnabled(true); #else web_browser->addObserver(this); diff --git a/indra/newview/llfloateruipreview.cpp b/indra/newview/llfloateruipreview.cpp index 6f526e1905..69459a4e98 100644 --- a/indra/newview/llfloateruipreview.cpp +++ b/indra/newview/llfloateruipreview.cpp @@ -73,6 +73,7 @@ #if LL_DARWIN #include <CoreFoundation/CFURL.h> +#include <CoreFoundation/CFBundle.h> #endif // Static initialization diff --git a/indra/newview/llhttpretrypolicy.cpp b/indra/newview/llhttpretrypolicy.cpp index 44d33eec93..de82952b9d 100644 --- a/indra/newview/llhttpretrypolicy.cpp +++ b/indra/newview/llhttpretrypolicy.cpp @@ -91,14 +91,14 @@ void LLAdaptiveRetryPolicy::onSuccess() void LLAdaptiveRetryPolicy::onFailure(S32 status, const LLSD& headers) { - F32 retry_header_time; + F32 retry_header_time{}; bool has_retry_header_time = getRetryAfter(headers,retry_header_time); onFailureCommon(status, has_retry_header_time, retry_header_time); } void LLAdaptiveRetryPolicy::onFailure(const LLCore::HttpResponse *response) { - F32 retry_header_time; + F32 retry_header_time{}; const LLCore::HttpHeaders::ptr_t headers = response->getHeaders(); bool has_retry_header_time = getRetryAfter(headers,retry_header_time); onFailureCommon(response->getStatus().getType(), has_retry_header_time, retry_header_time); @@ -184,4 +184,3 @@ bool LLAdaptiveRetryPolicy::getSecondsUntilRetryAfter(const std::string& retry_a return true; } - diff --git a/indra/newview/llhudrender.cpp b/indra/newview/llhudrender.cpp index 5608ab763f..ead45b7dcc 100644 --- a/indra/newview/llhudrender.cpp +++ b/indra/newview/llhudrender.cpp @@ -117,9 +117,11 @@ void hud_render_text(const LLWString &wstr, const LLVector3 &pos_agent, proj[i] = (F64) gGLProjection[i]; } +#if GLU_VERSION_1_1 gluProject(render_pos.mV[0], render_pos.mV[1], render_pos.mV[2], mdlv, proj, (GLint*) viewport, &winX, &winY, &winZ); +#endif //fonts all render orthographically, set up projection`` gGL.matrixMode(LLRender::MM_PROJECTION); diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index cab71a4a37..75d96cbe26 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -24,6 +24,8 @@ * $/LicenseInfo$ */ +#include <array> + #include "llviewerprecompiledheaders.h" #include "llimview.h" diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index bfa8e39b70..d40806ec2e 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -846,7 +846,7 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id, disabled_items.push_back(std::string("Copy")); } - if (isAgentInventory() && !single_folder_root) + if (isAgentInventory() && !single_folder_root && !isMarketplaceListingsFolder()) { items.push_back(std::string("New folder from selected")); items.push_back(std::string("Subfolder Separator")); @@ -5301,7 +5301,7 @@ void LLFolderBridge::dropToMyOutfits(LLInventoryCategory* inv_cat, LLPointer<LLI // Note: creation will take time, so passing folder id to callback is slightly unreliable, // but so is collecting and passing descendants' ids - inventory_func_type func = boost::bind(&LLFolderBridge::outfitFolderCreatedCallback, this, inv_cat->getUUID(), _1, cb); + inventory_func_type func = boost::bind(outfitFolderCreatedCallback, inv_cat->getUUID(), _1, cb, mInventoryPanel); gInventory.createNewCategory(dest_id, LLFolderType::FT_OUTFIT, inv_cat->getName(), @@ -5309,11 +5309,25 @@ void LLFolderBridge::dropToMyOutfits(LLInventoryCategory* inv_cat, LLPointer<LLI inv_cat->getThumbnailUUID()); } -void LLFolderBridge::outfitFolderCreatedCallback(LLUUID cat_source_id, LLUUID cat_dest_id, LLPointer<LLInventoryCallback> cb) +void LLFolderBridge::outfitFolderCreatedCallback(LLUUID cat_source_id, + LLUUID cat_dest_id, + LLPointer<LLInventoryCallback> cb, + LLHandle<LLInventoryPanel> inventory_panel) { LLInventoryModel::cat_array_t* categories; LLInventoryModel::item_array_t* items; - getInventoryModel()->getDirectDescendentsOf(cat_source_id, categories, items); + + LLInventoryPanel* panel = inventory_panel.get(); + if (!panel) + { + return; + } + LLInventoryModel* model = panel->getModel(); + if (!model) + { + return; + } + model->getDirectDescendentsOf(cat_source_id, categories, items); LLInventoryObject::const_object_list_t link_array; diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h index 746b79ce87..3e7f74384b 100644 --- a/indra/newview/llinventorybridge.h +++ b/indra/newview/llinventorybridge.h @@ -378,7 +378,10 @@ public: static void staticFolderOptionsMenu(); protected: - void outfitFolderCreatedCallback(LLUUID cat_source_id, LLUUID cat_dest_id, LLPointer<LLInventoryCallback> cb); + static void outfitFolderCreatedCallback(LLUUID cat_source_id, + LLUUID cat_dest_id, + LLPointer<LLInventoryCallback> cb, + LLHandle<LLInventoryPanel> inventory_panel); void callback_pasteFromClipboard(const LLSD& notification, const LLSD& response); void perform_pasteFromClipboard(); void gatherMessage(std::string& message, S32 depth, LLError::ELevel log_level); diff --git a/indra/newview/llinventorygallerymenu.cpp b/indra/newview/llinventorygallerymenu.cpp index 8e56ccc01d..dbf4821ca1 100644 --- a/indra/newview/llinventorygallerymenu.cpp +++ b/indra/newview/llinventorygallerymenu.cpp @@ -810,7 +810,7 @@ void LLInventoryGalleryContextMenu::updateMenuItemsVisibility(LLContextMenu* men items.push_back(std::string("Copy Asset UUID")); items.push_back(std::string("Copy Separator")); - bool is_asset_knowable = is_asset_knowable = LLAssetType::lookupIsAssetIDKnowable(obj->getType()); + bool is_asset_knowable = LLAssetType::lookupIsAssetIDKnowable(obj->getType()); if ( !is_asset_knowable // disable menu item for Inventory items with unknown asset. EXT-5308 || (! ( is_full_perm_item || gAgent.isGodlike()))) { diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index d57cb13362..53ea02983a 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -2037,8 +2037,8 @@ void LLInventoryModel::deleteObject(const LLUUID& id, bool fix_broken_links, boo { LL_WARNS(LOG_INV) << "Deleting cat " << id << " while it still has child cats" << LL_ENDL; } - delete cat_list; mParentChildCategoryTree.erase(id); + delete cat_list; } addChangedMask(LLInventoryObserver::REMOVE, id); @@ -5035,4 +5035,3 @@ void LLInventoryModel::FetchItemHttpHandler::processFailure(const char * const r << LLCoreHttpUtil::responseToString(response) << "]" << LL_ENDL; gInventory.notifyObservers(); } - diff --git a/indra/newview/llinventorymodelbackgroundfetch.cpp b/indra/newview/llinventorymodelbackgroundfetch.cpp index 9cb94b313e..d9ace1542b 100644 --- a/indra/newview/llinventorymodelbackgroundfetch.cpp +++ b/indra/newview/llinventorymodelbackgroundfetch.cpp @@ -30,6 +30,7 @@ #include "llaisapi.h" #include "llagent.h" #include "llappviewer.h" +#include "llappearancemgr.h" #include "llcallbacklist.h" #include "llinventorymodel.h" #include "llinventorypanel.h" @@ -470,6 +471,22 @@ void LLInventoryModelBackgroundFetch::fetchCOF(nullary_func_t callback) callback(); LLUUID cat_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT); LLInventoryModelBackgroundFetch::getInstance()->onAISFolderCalback(cat_id, id, FT_DEFAULT); + + if (id.notNull()) + { + // COF might have fetched base outfit folder through a link, but it hasn't + // fetched base outfit's content, which doesn't nessesary match COF, + // so make sure it's up to date + LLUUID baseoutfit_id = LLAppearanceMgr::getInstance()->getBaseOutfitUUID(); + if (baseoutfit_id.notNull()) + { + LLViewerInventoryCategory* cat = gInventory.getCategory(baseoutfit_id); + if (!cat || cat->getVersion() == LLViewerInventoryCategory::VERSION_UNKNOWN) + { + LLInventoryModelBackgroundFetch::getInstance()->fetchFolderAndLinks(baseoutfit_id, no_op); + } + } + } }); // start idle loop to track completion diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index 442da455ef..4106ce8186 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -578,8 +578,8 @@ void LLInventoryPanel::itemChanged(const LLUUID& item_id, U32 mask, const LLInve if (model_item && view_item && viewmodel_item) { const LLUUID& idp = viewmodel_item->getUUID(); - view_item->destroyView(); removeItemID(idp); + view_item->destroyView(); } LLInventoryObject const* objectp = mInventory->getObject(item_id); @@ -2022,7 +2022,7 @@ void LLInventoryPanel::removeItemID(const LLUUID& id) ++it) { mItemMap.erase((*it)->getUUID()); -} + } for (LLInventoryModel::item_array_t::iterator it = items.begin(), end_it = items.end(); it != end_it; diff --git a/indra/newview/llmanip.cpp b/indra/newview/llmanip.cpp index 2adb506c0f..3e39a52813 100644 --- a/indra/newview/llmanip.cpp +++ b/indra/newview/llmanip.cpp @@ -574,9 +574,6 @@ void LLManip::renderTickValue(const LLVector3& pos, F32 value, const std::string gGL.scalef(inv_zoom_amt, inv_zoom_amt, inv_zoom_amt); } - LLColor4 shadow_color = LLColor4::black; - shadow_color.mV[VALPHA] = color.mV[VALPHA] * 0.5f; - if (fractional_portion != 0) { fraction_string = llformat("%c%02d%s", LLResMgr::getInstance()->getDecimalPoint(), fractional_portion, suffix.c_str()); diff --git a/indra/newview/llmaniprotate.cpp b/indra/newview/llmaniprotate.cpp index 5bdf3f81b5..b63b8be095 100644 --- a/indra/newview/llmaniprotate.cpp +++ b/indra/newview/llmaniprotate.cpp @@ -274,7 +274,9 @@ void LLManipRotate::render() } LLGLEnable cull_face(GL_CULL_FACE); +#if GL_VERSION_1_1 LLGLEnable clip_plane0(GL_CLIP_PLANE0); +#endif LLGLDepthTest gls_depth(GL_FALSE); //LLGLDisable gls_stencil(GL_STENCIL_TEST); diff --git a/indra/newview/llmodelpreview.cpp b/indra/newview/llmodelpreview.cpp index b1a48db0ee..9af9f7fd53 100644 --- a/indra/newview/llmodelpreview.cpp +++ b/indra/newview/llmodelpreview.cpp @@ -134,25 +134,17 @@ std::string getLodSuffix(S32 lod) void FindModel(LLModelLoader::scene& scene, const std::string& name_to_match, LLModel*& baseModelOut, LLMatrix4& matOut) { - LLModelLoader::scene::iterator base_iter = scene.begin(); - bool found = false; - while (!found && (base_iter != scene.end())) + for (auto scene_iter = scene.begin(); scene_iter != scene.end(); scene_iter++) { - matOut = base_iter->first; - - LLModelLoader::model_instance_list::iterator base_instance_iter = base_iter->second.begin(); - while (!found && (base_instance_iter != base_iter->second.end())) + for (auto model_iter = scene_iter->second.begin(); model_iter != scene_iter->second.end(); model_iter++) { - LLModelInstance& base_instance = *base_instance_iter++; - LLModel* base_model = base_instance.mModel; - - if (base_model && (base_model->mLabel == name_to_match)) + if (model_iter->mModel && (model_iter->mModel->mLabel == name_to_match)) { - baseModelOut = base_model; + baseModelOut = model_iter->mModel; + matOut = scene_iter->first; return; } } - base_iter++; } } @@ -212,9 +204,12 @@ LLModelPreview::LLModelPreview(S32 width, S32 height, LLFloater* fmp) LLModelPreview::~LLModelPreview() { + LLMutexLock lock(this); + if (mModelLoader) { mModelLoader->shutdown(); + mModelLoader = NULL; } if (mPreviewAvatar) @@ -262,7 +257,7 @@ void LLModelPreview::updateDimentionsAndOffsets() accounted.insert(instance.mModel); // update instance skin info for each lods pelvisZoffset - for (int j = 0; j<LLModel::NUM_LODS; ++j) + for (int j = 0; j < LLModel::NUM_LODS; ++j) { if (instance.mLOD[j]) { @@ -303,7 +298,7 @@ void LLModelPreview::rebuildUploadData() bool legacyMatching = gSavedSettings.getBOOL("ImporterLegacyMatching"); U32 load_state = 0; - for (LLModelLoader::scene::iterator iter = mBaseScene.begin(); iter != mBaseScene.end(); ++iter) + for (auto iter = mBaseScene.begin(); iter != mBaseScene.end(); ++iter) { //for each transform in scene LLMatrix4 mat = iter->first; @@ -322,9 +317,9 @@ void LLModelPreview::rebuildUploadData() mat *= scale_mat; - for (LLModelLoader::model_instance_list::iterator model_iter = iter->second.begin(); model_iter != iter->second.end();) + for (auto model_iter = iter->second.begin(); model_iter != iter->second.end(); ++model_iter) { // for each instance with said transform applied - LLModelInstance instance = *model_iter++; + LLModelInstance instance = *model_iter; LLModel* base_model = instance.mModel; @@ -910,7 +905,7 @@ void LLModelPreview::clearIncompatible(S32 lod) { mBaseModel = mModel[lod]; mBaseScene = mScene[lod]; - mVertexBuffer[5].clear(); + mVertexBuffer[LLModel::NUM_LODS].clear(); replaced_base_model = true; } } @@ -1132,7 +1127,7 @@ void LLModelPreview::loadModelCallback(S32 loaded_lod) mBaseModel = mModel[loaded_lod]; mBaseScene = mScene[loaded_lod]; - mVertexBuffer[5].clear(); + mVertexBuffer[LLModel::NUM_LODS].clear(); } else { @@ -1248,7 +1243,7 @@ void LLModelPreview::loadModelCallback(S32 loaded_lod) { if (!mBaseModel.empty()) { - const std::string& model_name = mBaseModel[0]->getName(); + std::string model_name = mBaseModel.front()->getName(); LLLineEditor* description_form = mFMP->getChild<LLLineEditor>("description_form"); if (description_form->getText().empty()) { @@ -1269,6 +1264,8 @@ void LLModelPreview::loadModelCallback(S32 loaded_lod) void LLModelPreview::resetPreviewTarget() { + LLMutexLock lock(this); + if (mModelLoader) { mPreviewTarget = (mModelLoader->mExtents[0] + mModelLoader->mExtents[1]) * 0.5f; @@ -1314,7 +1311,7 @@ void LLModelPreview::generateNormals() (*it)->generateNormals(angle_cutoff); } - mVertexBuffer[5].clear(); + mVertexBuffer[LLModel::NUM_LODS].clear(); } bool perform_copy = mModelFacesCopy[which_lod].empty(); @@ -2156,7 +2153,7 @@ void LLModelPreview::updateStatusMessages() S32 total_verts[LLModel::NUM_LODS]; S32 total_submeshes[LLModel::NUM_LODS]; - for (U32 i = 0; i < LLModel::NUM_LODS - 1; i++) + for (U32 i = 0; i < LLModel::NUM_LODS; i++) { total_tris[i] = 0; total_verts[i] = 0; @@ -2460,12 +2457,16 @@ void LLModelPreview::updateStatusMessages() } } - if (mModelNoErrors && mModelLoader) + if (mModelNoErrors) { - if (!mModelLoader->areTexturesReady() && mFMP->childGetValue("upload_textures").asBoolean()) + LLMutexLock lock(this); + if (mModelLoader) { - // Some textures are still loading, prevent upload until they are done - mModelNoErrors = false; + if (!mModelLoader->areTexturesReady() && mFMP->childGetValue("upload_textures").asBoolean()) + { + // Some textures are still loading, prevent upload until they are done + mModelNoErrors = false; + } } } @@ -2794,10 +2795,10 @@ void LLModelPreview::genBuffers(S32 lod, bool include_skin_weights) { LLModelLoader::model_list* model = NULL; - if (lod < 0 || lod > 4) + if (lod < 0 || lod >= LLModel::NUM_LODS) { model = &mBaseModel; - lod = 5; + lod = LLModel::NUM_LODS; } else { @@ -3034,8 +3035,9 @@ void LLModelPreview::loadedCallback( S32 lod, void* opaque) { - LLModelPreview* pPreview = static_cast< LLModelPreview* >(opaque); - if (pPreview && !LLModelPreview::sIgnoreLoadedCallback) + LLModelPreview* pPreview = static_cast<LLModelPreview*>(opaque); + LLMutexLock lock(pPreview); + if (pPreview && pPreview->mModelLoader && !LLModelPreview::sIgnoreLoadedCallback) { // Load loader's warnings into floater's log tab const LLSD out = pPreview->mModelLoader->logOut(); @@ -3056,7 +3058,9 @@ void LLModelPreview::loadedCallback( } const LLVOAvatar* avatarp = pPreview->getPreviewAvatar(); - if (avatarp) { // set up ground plane for possible rendering + if (avatarp && avatarp->mRoot && avatarp->mDrawable) + { + // set up ground plane for possible rendering const LLVector3 root_pos = avatarp->mRoot->getPosition(); const LLVector4a* ext = avatarp->mDrawable->getSpatialExtents(); const LLVector4a min = ext[0], max = ext[1]; @@ -3193,12 +3197,12 @@ bool LLModelPreview::render() LLMutexLock lock(this); mNeedsUpdate = false; - bool edges = mViewOption["show_edges"]; - bool joint_overrides = mViewOption["show_joint_overrides"]; - bool joint_positions = mViewOption["show_joint_positions"]; - bool skin_weight = mViewOption["show_skin_weight"]; - bool textures = mViewOption["show_textures"]; - bool physics = mViewOption["show_physics"]; + bool show_edges = mViewOption["show_edges"]; + bool show_joint_overrides = mViewOption["show_joint_overrides"]; + bool show_joint_positions = mViewOption["show_joint_positions"]; + bool show_skin_weight = mViewOption["show_skin_weight"]; + bool show_textures = mViewOption["show_textures"]; + bool show_physics = mViewOption["show_physics"]; S32 width = getWidth(); S32 height = getHeight(); @@ -3275,15 +3279,15 @@ bool LLModelPreview::render() fmp->childSetValue("upload_skin", true); mFirstSkinUpdate = false; upload_skin = true; - skin_weight = true; + show_skin_weight = true; mViewOption["show_skin_weight"] = true; } fmp->enableViewOption("show_skin_weight"); - fmp->setViewOptionEnabled("show_joint_overrides", skin_weight); - fmp->setViewOptionEnabled("show_joint_positions", skin_weight); + fmp->setViewOptionEnabled("show_joint_overrides", show_skin_weight); + fmp->setViewOptionEnabled("show_joint_positions", show_skin_weight); mFMP->childEnable("upload_skin"); - mFMP->childSetValue("show_skin_weight", skin_weight); + mFMP->childSetValue("show_skin_weight", show_skin_weight); } else if ((flags & LEGACY_RIG_FLAG_TOO_MANY_JOINTS) > 0) @@ -3306,11 +3310,12 @@ bool LLModelPreview::render() fmp->disableViewOption("show_joint_overrides"); fmp->disableViewOption("show_joint_positions"); - skin_weight = false; + show_skin_weight = false; mFMP->childSetValue("show_skin_weight", false); - fmp->setViewOptionEnabled("show_skin_weight", skin_weight); + fmp->setViewOptionEnabled("show_skin_weight", show_skin_weight); } } + //if (this) return TRUE; if (upload_skin && !has_skin_weights) { //can't upload skin weights if model has no skin weights @@ -3353,7 +3358,7 @@ bool LLModelPreview::render() mFMP->childSetEnabled("upload_joints", upload_skin); } - F32 explode = mFMP->childGetValue("physics_explode").asReal(); + F32 physics_explode = mFMP->childGetValue("physics_explode").asReal(); LLGLDepthTest gls_depth(GL_TRUE); // SL-12781 re-enable z-buffer for 3D model preview @@ -3373,7 +3378,7 @@ bool LLModelPreview::render() F32 z_near = 0.001f; F32 z_far = mCameraDistance*10.0f + mPreviewScale.magVec() + mCameraOffset.magVec(); - if (skin_weight) + if (show_skin_weight) { target_pos = getPreviewAvatar()->getPositionAgent() + offset; z_near = 0.01f; @@ -3383,7 +3388,7 @@ bool LLModelPreview::render() refresh(); } - gObjectPreviewProgram.bind(skin_weight); + gObjectPreviewProgram.bind(show_skin_weight); gGL.loadIdentity(); gPipeline.enableLightsPreview(); @@ -3392,7 +3397,7 @@ bool LLModelPreview::render() LLQuaternion(mCameraYaw, LLVector3::z_axis); LLQuaternion av_rot = camera_rot; - F32 camera_distance = skin_weight ? SKIN_WEIGHT_CAMERA_DISTANCE : mCameraDistance; + F32 camera_distance = show_skin_weight ? SKIN_WEIGHT_CAMERA_DISTANCE : mCameraDistance; LLViewerCamera::getInstance()->setOriginAndLookAt( target_pos + ((LLVector3(camera_distance, 0.f, 0.f) + offset) * av_rot), // camera LLVector3::z_axis, // up @@ -3408,9 +3413,9 @@ bool LLModelPreview::render() gGL.pushMatrix(); gGL.color4fv(PREVIEW_EDGE_COL.mV); - if (!mBaseModel.empty() && mVertexBuffer[5].empty()) + if (!mBaseModel.empty() && mVertexBuffer[LLModel::NUM_LODS].empty()) { - genBuffers(-1, skin_weight); + genBuffers(-1, show_skin_weight); //genBuffers(3); } @@ -3425,7 +3430,7 @@ bool LLModelPreview::render() if (!vb_vec.empty()) { const LLVertexBuffer* buff = vb_vec[0]; - regen = buff->hasDataType(LLVertexBuffer::TYPE_WEIGHT4) != skin_weight; + regen = buff->hasDataType(LLVertexBuffer::TYPE_WEIGHT4) != show_skin_weight; } else { @@ -3436,15 +3441,15 @@ bool LLModelPreview::render() if (regen) { - genBuffers(mPreviewLOD, skin_weight); + genBuffers(mPreviewLOD, show_skin_weight); } - if (physics && mVertexBuffer[LLModel::LOD_PHYSICS].empty()) + if (show_physics && mVertexBuffer[LLModel::LOD_PHYSICS].empty()) { genBuffers(LLModel::LOD_PHYSICS, false); } - if (!skin_weight) + if (!show_skin_weight) { for (LLMeshUploadThread::instance_list::iterator iter = mUploadData.begin(); iter != mUploadData.end(); ++iter) { @@ -3466,11 +3471,7 @@ bool LLModelPreview::render() auto num_models = mVertexBuffer[mPreviewLOD][model].size(); for (size_t i = 0; i < num_models; ++i) { - LLVertexBuffer* buffer = mVertexBuffer[mPreviewLOD][model][i]; - - buffer->setBuffer(); - - if (textures) + if (show_textures) { auto materialCnt = instance.mModel->mMaterialList.size(); if (i < materialCnt) @@ -3494,15 +3495,25 @@ bool LLModelPreview::render() gGL.diffuseColor4fv(PREVIEW_BASE_COL.mV); } + // Zero this variable for an obligatory buffer initialization + // See https://github.com/secondlife/viewer/issues/912 + LLVertexBuffer::sGLRenderBuffer = 0; + LLVertexBuffer* buffer = mVertexBuffer[mPreviewLOD][model][i]; + buffer->setBuffer(); buffer->drawRange(LLRender::TRIANGLES, 0, buffer->getNumVerts() - 1, buffer->getNumIndices(), 0); + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); gGL.diffuseColor4fv(PREVIEW_EDGE_COL.mV); - if (edges) + if (show_edges) { glLineWidth(PREVIEW_EDGE_WIDTH); +#if GL_VERSION_1_1 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); +#endif buffer->drawRange(LLRender::TRIANGLES, 0, buffer->getNumVerts() - 1, buffer->getNumIndices(), 0); +#if GL_VERSION_1_1 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); +#endif glLineWidth(1.f); } buffer->unmapBuffer(); @@ -3510,7 +3521,7 @@ bool LLModelPreview::render() gGL.popMatrix(); } - if (physics) + if (show_physics) { glClear(GL_DEPTH_BUFFER_BIT); @@ -3576,12 +3587,12 @@ bool LLModelPreview::render() for (U32 i = 0; i < physics.mMesh.size(); ++i) { - if (explode > 0.f) + if (physics_explode > 0.f) { gGL.pushMatrix(); LLVector3 offset = model->mHullCenter[i] - model->mCenterOfHullCenters; - offset *= explode; + offset *= physics_explode; gGL.translatef(offset.mV[0], offset.mV[1], offset.mV[2]); } @@ -3596,7 +3607,7 @@ bool LLModelPreview::render() gGL.diffuseColor4ubv(hull_colors[i].mV); LLVertexBuffer::drawArrays(LLRender::TRIANGLES, physics.mMesh[i].mPositions); - if (explode > 0.f) + if (physics_explode > 0.f) { gGL.popMatrix(); } @@ -3614,20 +3625,26 @@ bool LLModelPreview::render() if (pass > 0){ for (size_t i = 0; i < num_models; ++i) { - LLVertexBuffer* buffer = mVertexBuffer[LLModel::LOD_PHYSICS][model][i]; - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); gGL.diffuseColor4fv(PREVIEW_PSYH_FILL_COL.mV); + // Zero this variable for an obligatory buffer initialization + // See https://github.com/secondlife/viewer/issues/912 + LLVertexBuffer::sGLRenderBuffer = 0; + LLVertexBuffer* buffer = mVertexBuffer[LLModel::LOD_PHYSICS][model][i]; buffer->setBuffer(); buffer->drawRange(LLRender::TRIANGLES, 0, buffer->getNumVerts() - 1, buffer->getNumIndices(), 0); gGL.diffuseColor4fv(PREVIEW_PSYH_EDGE_COL.mV); glLineWidth(PREVIEW_PSYH_EDGE_WIDTH); +#if GL_VERSION_1_1 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); +#endif buffer->drawRange(LLRender::TRIANGLES, 0, buffer->getNumVerts() - 1, buffer->getNumIndices(), 0); +#if GL_VERSION_1_1 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); +#endif glLineWidth(1.f); buffer->unmapBuffer(); @@ -3641,7 +3658,9 @@ bool LLModelPreview::render() if (mHasDegenerate) { glLineWidth(PREVIEW_DEG_EDGE_WIDTH); +#if GL_VERSION_1_1 glPointSize(PREVIEW_DEG_POINT_SIZE); +#endif gPipeline.enableLightsFullbright(); //show degenerate triangles LLGLDepthTest depth(GL_TRUE, GL_TRUE, GL_ALWAYS); @@ -3678,10 +3697,11 @@ bool LLModelPreview::render() auto num_models = mVertexBuffer[LLModel::LOD_PHYSICS][model].size(); for (size_t v = 0; v < num_models; ++v) { + // Zero this variable for an obligatory buffer initialization + // See https://github.com/secondlife/viewer/issues/912 + LLVertexBuffer::sGLRenderBuffer = 0; LLVertexBuffer* buffer = mVertexBuffer[LLModel::LOD_PHYSICS][model][v]; - buffer->setBuffer(); - LLStrider<LLVector3> pos_strider; buffer->getVertexStrider(pos_strider, 0); LLVector4a* pos = (LLVector4a*)pos_strider.get(); @@ -3710,7 +3730,9 @@ bool LLModelPreview::render() gGL.popMatrix(); } glLineWidth(1.f); +#if GL_VERSION_1_1 glPointSize(1.f); +#endif gPipeline.enableLightsPreview(); gGL.setSceneBlendType(LLRender::BT_ALPHA); } @@ -3745,7 +3767,7 @@ bool LLModelPreview::render() U32 joint_count = LLSkinningUtil::getMeshJointCount(skin); auto bind_count = skin->mAlternateBindMatrix.size(); - if (joint_overrides + if (show_joint_overrides && bind_count > 0 && joint_count == bind_count) { @@ -3790,14 +3812,12 @@ bool LLModelPreview::render() for (U32 i = 0, e = static_cast<U32>(mVertexBuffer[mPreviewLOD][model].size()); i < e; ++i) { - LLVertexBuffer* buffer = mVertexBuffer[mPreviewLOD][model][i]; - model->mSkinInfo.updateHash(); LLRenderPass::uploadMatrixPalette(mPreviewAvatar, &model->mSkinInfo); gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - if (textures) + if (show_textures) { auto materialCnt = instance.mModel->mMaterialList.size(); if (i < materialCnt) @@ -3821,17 +3841,25 @@ bool LLModelPreview::render() gGL.diffuseColor4fv(PREVIEW_BASE_COL.mV); } + // Zero this variable for an obligatory buffer initialization + // See https://github.com/secondlife/viewer/issues/912 + LLVertexBuffer::sGLRenderBuffer = 0; + LLVertexBuffer* buffer = mVertexBuffer[mPreviewLOD][model][i]; buffer->setBuffer(); buffer->draw(LLRender::TRIANGLES, buffer->getNumIndices(), 0); - if (edges) + if (show_edges) { gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); gGL.diffuseColor4fv(PREVIEW_EDGE_COL.mV); glLineWidth(PREVIEW_EDGE_WIDTH); +#if GL_VERSION_1_1 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); +#endif buffer->draw(LLRender::TRIANGLES, buffer->getNumIndices(), 0); +#if GL_VERSION_1_1 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); +#endif glLineWidth(1.f); } } @@ -3839,7 +3867,7 @@ bool LLModelPreview::render() } } - if (joint_positions) + if (show_joint_positions) { LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr; if (shader) diff --git a/indra/newview/llpanelemojicomplete.cpp b/indra/newview/llpanelemojicomplete.cpp index 3faa01ae0c..9814745bc7 100644 --- a/indra/newview/llpanelemojicomplete.cpp +++ b/indra/newview/llpanelemojicomplete.cpp @@ -68,6 +68,9 @@ LLPanelEmojiComplete::LLPanelEmojiComplete(const LLPanelEmojiComplete::Params& p { LLScrollbar::Params sbparams; sbparams.orientation(LLScrollbar::VERTICAL); + sbparams.doc_size(mTotalEmojis); + sbparams.doc_pos(0); + sbparams.page_size(mVisibleEmojis); sbparams.change_callback([this](S32 index, LLScrollbar*) { onScrollbarChange(index); }); mScrollbar = LLUICtrlFactory::create<LLScrollbar>(sbparams); addChild(mScrollbar); diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp index 89af765bb7..8a89c5a1aa 100644 --- a/indra/newview/llpanelface.cpp +++ b/indra/newview/llpanelface.cpp @@ -5540,4 +5540,3 @@ void LLPanelFace::LLSelectedTE::getMaxDiffuseRepeats(F32& repeats, bool& identic } max_diff_repeats_func; identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &max_diff_repeats_func, repeats ); } - diff --git a/indra/newview/llpanelface.h b/indra/newview/llpanelface.h index 7e1553c80a..602b05d240 100644 --- a/indra/newview/llpanelface.h +++ b/indra/newview/llpanelface.h @@ -396,7 +396,7 @@ private: ReturnType (LLMaterial::* const MaterialGetFunc)() const > static void getTEMaterialValue(DataType& data_to_return, bool& identical,DataType default_value, bool has_tolerance = false, DataType tolerance = DataType()) { - DataType data_value; + DataType data_value{}; struct GetTEMaterialVal : public LLSelectedTEGetFunctor<DataType> { GetTEMaterialVal(DataType default_value) : _default(default_value) {} @@ -429,7 +429,7 @@ private: ReturnType (LLTextureEntry::* const TEGetFunc)() const > static void getTEValue(DataType& data_to_return, bool& identical, DataType default_value, bool has_tolerance = false, DataType tolerance = DataType()) { - DataType data_value; + DataType data_value {}; struct GetTEVal : public LLSelectedTEGetFunctor<DataType> { GetTEVal(DataType default_value) : _default(default_value) {} @@ -622,4 +622,3 @@ public: }; #endif - diff --git a/indra/newview/llpanelpeople.cpp b/indra/newview/llpanelpeople.cpp index 0b02d3c9c6..0e8036eea6 100644 --- a/indra/newview/llpanelpeople.cpp +++ b/indra/newview/llpanelpeople.cpp @@ -827,7 +827,7 @@ void LLPanelPeople::updateNearbyList() std::vector<LLVector3d> positions; - LLWorld::getInstance()->getAvatars(&mNearbyList->getIDs(), &positions, gAgent.getPositionGlobal(), gSavedSettings.getF32("NearMeRange")); + LLWorld::getInstance()->getAvatars(&mNearbyList->getIDs(), &positions, gAgent.getPositionGlobal(), gSavedSettings.getF32("MPVNearMeRange")); mNearbyList->setDirty(); DISTANCE_COMPARATOR.updateAvatarsPositions(positions, mNearbyList->getIDs()); diff --git a/indra/newview/llpanelpeoplemenus.cpp b/indra/newview/llpanelpeoplemenus.cpp index 172c7d0828..1719f1b4aa 100644 --- a/indra/newview/llpanelpeoplemenus.cpp +++ b/indra/newview/llpanelpeoplemenus.cpp @@ -74,6 +74,7 @@ LLContextMenu* PeopleContextMenu::createMenu() registrar.add("Avatar.Call", boost::bind(&LLAvatarActions::startCall, id)); registrar.add("Avatar.OfferTeleport", boost::bind(&PeopleContextMenu::offerTeleport, this)); registrar.add("Avatar.ZoomIn", boost::bind(&handle_zoom_to_object, id)); + registrar.add("Avatar.TeleportTo", boost::bind(&handle_teleport_to_object, id)); registrar.add("Avatar.ShowOnMap", boost::bind(&LLAvatarActions::showOnMap, id)); registrar.add("Avatar.Share", boost::bind(&LLAvatarActions::share, id)); registrar.add("Avatar.Pay", boost::bind(&LLAvatarActions::pay, id)); @@ -401,6 +402,7 @@ void NearbyPeopleContextMenu::buildContextMenu(class LLMenuGL& menu, U32 flags) items.push_back(std::string("invite_to_group")); items.push_back(std::string("separator_invite_to_group")); items.push_back(std::string("zoom_in")); + items.push_back(std::string("teleport_to")); items.push_back(std::string("map")); items.push_back(std::string("share")); items.push_back(std::string("pay")); diff --git a/indra/newview/llpanelprofile.cpp b/indra/newview/llpanelprofile.cpp index 9711729498..4e74a19adb 100644 --- a/indra/newview/llpanelprofile.cpp +++ b/indra/newview/llpanelprofile.cpp @@ -1429,6 +1429,11 @@ void LLPanelProfileSecondLife::onCommitMenu(const LLSD& userdata) LLWString wstr = utf8str_to_wstring(getAvatarId().asString()); LLClipboard::instance().copyToClipboard(wstr, 0, static_cast<S32>(wstr.size())); } + else if (item_name == "copy_profile_link") + { + LLWString wstr = utf8str_to_wstring(llformat("secondlife:///app/agent/%s/about", getAvatarId().asString().c_str())); + LLClipboard::instance().copyToClipboard(wstr, 0, wstr.size()); + } else if (item_name == "agent_permissions") { onShowAgentPermissionsDialog(); @@ -1611,7 +1616,7 @@ void LLPanelProfileSecondLife::onShowInSearchCallback() if (value == mAllowPublish) return; - mAllowPublish = value; + mAllowPublish = value; saveAgentUserInfoCoro("allow_publish", value); } @@ -1765,7 +1770,7 @@ void LLPanelProfileSecondLife::onCommitProfileImage(const LLUUID& id) if (mSecondLifePic->getImageAssetId() == id) return; - std::function<void(bool)> callback = [id](bool result) + std::function<void(bool)> callback = [id](bool result) { if (result) { diff --git a/indra/newview/llpanelprofileclassifieds.h b/indra/newview/llpanelprofileclassifieds.h index 9f0b27139a..42cd5f8975 100644 --- a/indra/newview/llpanelprofileclassifieds.h +++ b/indra/newview/llpanelprofileclassifieds.h @@ -324,8 +324,11 @@ private: S32 mPriceForListing; +public: static void handleSearchStatResponse(LLUUID classifiedId, LLSD result); +private: + typedef std::list<LLPanelProfileClassified*> panel_list_t; static panel_list_t sAllPanels; diff --git a/indra/newview/llphysicsshapebuilderutil.cpp b/indra/newview/llphysicsshapebuilderutil.cpp index 37534feadc..eb0df1194e 100644 --- a/indra/newview/llphysicsshapebuilderutil.cpp +++ b/indra/newview/llphysicsshapebuilderutil.cpp @@ -28,6 +28,26 @@ #include "llphysicsshapebuilderutil.h" +#include "llmeshrepository.h" + +bool LLPhysicsVolumeParams::hasDecomposition() const + { + if (!isMeshSculpt()) + { + return false; + } + + LLUUID mesh_id = getSculptID(); + if (mesh_id.isNull()) + { + return false; + } + + LLModel::Decomposition* decomp = gMeshRepo.getDecomposition(mesh_id); + + return decomp != NULL; +} + /* static */ void LLPhysicsShapeBuilderUtil::determinePhysicsShape( const LLPhysicsVolumeParams& volume_params, const LLVector3& scale, PhysicsShapeSpecification& specOut) { @@ -200,19 +220,32 @@ void LLPhysicsShapeBuilderUtil::determinePhysicsShape( const LLPhysicsVolumePara { specOut.mType = PhysicsShapeSpecification::PRIM_CONVEX; } - else if (volume_params.isMeshSculpt() && - // Check overall dimensions, not individual triangles. - (scale.mV[0] < SHAPE_BUILDER_USER_MESH_CONVEXIFICATION_SIZE || - scale.mV[1] < SHAPE_BUILDER_USER_MESH_CONVEXIFICATION_SIZE || - scale.mV[2] < SHAPE_BUILDER_USER_MESH_CONVEXIFICATION_SIZE - ) ) + else if (volume_params.isMeshSculpt()) { - // Server distinguishes between user-specified or default convex mesh, vs server's thin-triangle override, but we don't. - specOut.mType = PhysicsShapeSpecification::PRIM_CONVEX; + // Check overall dimensions, not individual triangles. + if (scale.mV[0] < SHAPE_BUILDER_USER_MESH_CONVEXIFICATION_SIZE + || scale.mV[1] < SHAPE_BUILDER_USER_MESH_CONVEXIFICATION_SIZE + || scale.mV[2] < SHAPE_BUILDER_USER_MESH_CONVEXIFICATION_SIZE + ) + { + if (volume_params.hasDecomposition()) + { + specOut.mType = PhysicsShapeSpecification::USER_MESH; + } + else + { + // Server distinguishes between user-specified or default convex mesh, vs server's thin-triangle override, but we don't. + specOut.mType = PhysicsShapeSpecification::PRIM_CONVEX; + } + } + else + { + specOut.mType = PhysicsShapeSpecification::USER_MESH; + } } - else if ( volume_params.isSculpt() ) // Is a sculpt of any kind (mesh or legacy) + else if ( volume_params.isSculpt() ) { - specOut.mType = volume_params.isMeshSculpt() ? PhysicsShapeSpecification::USER_MESH : PhysicsShapeSpecification::SCULPT; + specOut.mType = PhysicsShapeSpecification::SCULPT; } else // Resort to mesh { diff --git a/indra/newview/llphysicsshapebuilderutil.h b/indra/newview/llphysicsshapebuilderutil.h index 33c2d0a8b6..01c173523b 100644 --- a/indra/newview/llphysicsshapebuilderutil.h +++ b/indra/newview/llphysicsshapebuilderutil.h @@ -79,6 +79,8 @@ public: bool shouldForceConvex() const { return mForceConvex; } + bool hasDecomposition() const; + private: bool mForceConvex; }; diff --git a/indra/newview/llprogressview.cpp b/indra/newview/llprogressview.cpp index e03984a44c..1f6353d1b4 100644 --- a/indra/newview/llprogressview.cpp +++ b/indra/newview/llprogressview.cpp @@ -379,9 +379,10 @@ void LLProgressView::initLogos() { mLogosList.clear(); +#if LL_FMODSTUDIO || LL_HAVOK const U8 image_codec = IMG_CODEC_PNG; const LLRectf default_clip(0.f, 1.f, 1.f, 0.f); - const S32 default_height = 28; + //const S32 default_height = 28; const S32 default_pad = 15; S32 icon_width, icon_height; @@ -390,6 +391,7 @@ void LLProgressView::initLogos() LLTextBox *logos_label = getChild<LLTextBox>("logos_lbl"); S32 texture_start_x = logos_label->getFont()->getWidthF32(logos_label->getText()) + default_pad; S32 texture_start_y = -7; +#endif //LL_FMODSTUDIO || LL_HAVOK // Normally we would just preload these textures from textures.xml, // and display them via icon control, but they are only needed on @@ -399,6 +401,21 @@ void LLProgressView::initLogos() temp_str += gDirUtilp->getDirDelimiter(); +#ifdef LL_FMODSTUDIO + // original image size is 264x96, it is on longer side but + // with no internal paddings so it gets additional padding + icon_width = 77; + icon_height = 21; + S32 pad_fmod_y = 4; + texture_start_x++; + loadLogo(temp_str + "fmod_logo.png", + image_codec, + LLRect(texture_start_x, texture_start_y + pad_fmod_y + icon_height, texture_start_x + icon_width, texture_start_y + pad_fmod_y), + default_clip, + default_clip); + + texture_start_x += icon_width + default_pad + 1; +#endif //LL_FMODSTUDIO #ifdef LL_HAVOK // original image size is 342x113, central element is on a larger side // plus internal padding, so it gets slightly more height than desired 32 @@ -414,6 +431,7 @@ void LLProgressView::initLogos() texture_start_x += icon_width + default_pad; #endif //LL_HAVOK +/* // 108x41 icon_width = 74; icon_height = default_height; @@ -422,6 +440,7 @@ void LLProgressView::initLogos() LLRect(texture_start_x, texture_start_y + icon_height, texture_start_x + icon_width, texture_start_y), default_clip, default_clip); +*/ } void LLProgressView::initStartTexture(S32 location_id, bool is_in_production) diff --git a/indra/newview/llreflectionmapmanager.cpp b/indra/newview/llreflectionmapmanager.cpp index cb1ab0dac2..3130fe3bac 100644 --- a/indra/newview/llreflectionmapmanager.cpp +++ b/indra/newview/llreflectionmapmanager.cpp @@ -794,7 +794,9 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face) LL_PROFILE_GPU_ZONE("probe mip copy"); mTexture->bind(0); //glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, mip, 0, 0, probe->mCubeIndex * 6 + face, 0, 0, res, res); +#if GL_VERSION_4_0 glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, mip, 0, 0, sourceIdx * 6 + face, 0, 0, res, res); +#endif //if (i == 0) //{ //glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, mip, 0, 0, probe->mCubeIndex * 6 + face, 0, 0, res, res); @@ -853,7 +855,9 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face) mVertexBuffer->drawArrays(gGL.TRIANGLE_STRIP, 0, 4); +#if GL_VERSION_4_0 glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, i, 0, 0, probe->mCubeIndex * 6 + cf, 0, 0, res, res); +#endif } if (i != mMipChain.size() - 1) @@ -904,7 +908,9 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face) S32 res = mMipChain[i].getWidth(); mIrradianceMaps->bind(channel); +#if GL_VERSION_4_0 glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, i - start_mip, 0, 0, probe->mCubeIndex * 6 + cf, 0, 0, res, res); +#endif mTexture->bind(channel); } } diff --git a/indra/newview/llsearchcombobox.h b/indra/newview/llsearchcombobox.h index e0162bac80..17787ca5e6 100644 --- a/indra/newview/llsearchcombobox.h +++ b/indra/newview/llsearchcombobox.h @@ -61,6 +61,11 @@ public: ~LLSearchComboBox(); + /** + * Sets focus to text box + */ + void focusTextEntry(); + protected: LLSearchComboBox(const Params&p); @@ -93,11 +98,6 @@ protected: */ void onSelectionCommit(); - /** - * Sets focus to text box - */ - void focusTextEntry(); - LLButton* mSearchButton; }; diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp index b3420f9c57..aed35939a6 100644 --- a/indra/newview/llselectmgr.cpp +++ b/indra/newview/llselectmgr.cpp @@ -6441,7 +6441,9 @@ void LLSelectMgr::renderSilhouettes(bool for_hud) } } +#if GL_VERSION_1_1 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); +#endif S32 num_tes = llmin((S32)objectp->getNumTEs(), (S32)objectp->getNumFaces()); // avatars have TEs but no faces for (S32 te = 0; te < num_tes; ++te) @@ -6456,7 +6458,9 @@ void LLSelectMgr::renderSilhouettes(bool for_hud) gGL.popMatrix(); glLineWidth(1.f); +#if GL_VERSION_1_1 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); +#endif if (shader) { diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp index 782d57aed8..c8643a06c0 100644 --- a/indra/newview/llspatialpartition.cpp +++ b/indra/newview/llspatialpartition.cpp @@ -1663,7 +1663,9 @@ void renderOctree(LLSpatialGroup* group) { LLGLDepthTest gl_depth(false, false); +#if GL_VERSION_1_1 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); +#endif gGL.diffuseColor4f(1,0,0,group->mBuilt); gGL.flush(); @@ -1765,7 +1767,9 @@ void renderOctree(LLSpatialGroup* group) gGL.popMatrix(); } } +#if GL_VERSION_1_1 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); +#endif gDebugProgram.bind(); // make sure non-rigged variant is bound gGL.diffuseColor4f(1,1,1,1); } @@ -2504,7 +2508,9 @@ void renderPhysicsShape(LLDrawable* drawable, LLVOVolume* volume, bool wireframe llassert(LLGLSLShader::sCurBoundShader != 0); LLVertexBuffer::unbind(); +#if GL_VERSION_1_1 glVertexPointer(3, GL_FLOAT, 16, phys_volume->mHullPoints); +#endif gGL.diffuseColor4fv(color.mV); @@ -2701,7 +2707,9 @@ void renderTextureAnim(LLDrawInfo* params) void renderBatchSize(LLDrawInfo* params) { +#if GL_VERSION_1_1 LLGLEnable offset(GL_POLYGON_OFFSET_FILL); +#endif glPolygonOffset(-1.f, 1.f); LLGLSLShader* old_shader = LLGLSLShader::sCurBoundShaderPtr; bool bind = false; @@ -3007,7 +3015,9 @@ void renderRaycast(LLDrawable* drawablep) dir.setSub(end, start); gGL.flush(); +#if GL_VERSION_1_1 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); +#endif { //render face positions @@ -3026,7 +3036,9 @@ void renderRaycast(LLDrawable* drawablep) } gGL.popMatrix(); +#if GL_VERSION_1_1 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); +#endif } } } @@ -3614,16 +3626,22 @@ void LLSpatialPartition::renderDebug() LLGLEnable blend(GL_BLEND); LLGLDepthTest depth_under(GL_TRUE, GL_FALSE, GL_GREATER); +#if GL_VERSION_1_1 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); +#endif gGL.diffuseColor4f(0.5f, 0.0f, 0, 0.25f); +#if GL_VERSION_1_1 LLGLEnable offset(GL_POLYGON_OFFSET_LINE); +#endif glPolygonOffset(-1.f, -1.f); LLOctreeRenderXRay xray(camera); xray.traverse(mOctree); +#if GL_VERSION_1_1 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); +#endif } } gDebugProgram.unbind(); diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index dd005874a5..0765dc47b7 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -40,6 +40,10 @@ #include "llviewermedia_streamingaudio.h" #include "llaudioengine.h" +#ifdef LL_FMODSTUDIO +# include "llaudioengine_fmodstudio.h" +#endif + #ifdef LL_OPENAL #include "llaudioengine_openal.h" #endif @@ -211,6 +215,9 @@ #include "lldxhardware.h" #endif +#include "fsfloatersearch.h" + + // // exported globals // @@ -653,6 +660,15 @@ bool idle_startup() delete gAudiop; gAudiop = NULL; +#ifdef LL_FMODSTUDIO +#if !LL_WINDOWS + if (NULL == getenv("LL_BAD_FMODSTUDIO_DRIVER")) +#endif // !LL_WINDOWS + { + gAudiop = (LLAudioEngine *) new LLAudioEngine_FMODSTUDIO(gSavedSettings.getBOOL("FMODExProfilerEnable")); + } +#endif + #ifdef LL_OPENAL #if !LL_WINDOWS if (NULL == getenv("LL_BAD_OPENAL_DRIVER")) @@ -673,8 +689,19 @@ bool idle_startup() #endif if (gAudiop->init(window_handle, LLAppViewer::instance()->getSecondLifeTitle())) { - LL_INFOS("AppInit") << "Using media plugins to render streaming audio" << LL_ENDL; - gAudiop->setStreamingAudioImpl(new LLStreamingAudio_MediaPlugins()); + if (FALSE == gSavedSettings.getBOOL("UseMediaPluginsForStreamingAudio")) + { + LL_INFOS("AppInit") << "Using default impl to render streaming audio" << LL_ENDL; + gAudiop->setStreamingAudioImpl(gAudiop->createDefaultStreamingAudioImpl()); + } + + // if the audio engine hasn't set up its own preferred handler for streaming audio + // then set up the generic streaming audio implementation which uses media plugins + if (NULL == gAudiop->getStreamingAudioImpl()) + { + LL_INFOS("AppInit") << "Using media plugins to render streaming audio" << LL_ENDL; + gAudiop->setStreamingAudioImpl(new LLStreamingAudio_MediaPlugins()); + } gAudiop->setMuted(true); } @@ -2763,6 +2790,14 @@ void register_viewer_callbacks(LLMessageSystem* msg) msg->setHandlerFunc("AvatarPickerReply", LLFloaterAvatarPicker::processAvatarPickerReply); + // directory search + msg->setHandlerFuncFast(_PREHASH_DirPeopleReply, FSPanelSearchPeople::processSearchReply); + msg->setHandlerFuncFast(_PREHASH_DirPlacesReply, FSPanelSearchPlaces::processSearchReply); + msg->setHandlerFuncFast(_PREHASH_DirGroupsReply, FSPanelSearchGroups::processSearchReply); + msg->setHandlerFuncFast(_PREHASH_DirEventsReply, FSPanelSearchEvents::processSearchReply); + msg->setHandlerFuncFast(_PREHASH_DirLandReply, FSPanelSearchLand::processSearchReply); + msg->setHandlerFuncFast(_PREHASH_DirClassifiedReply, FSPanelSearchClassifieds::processSearchReply); + msg->setHandlerFunc("MapBlockReply", LLWorldMapMessage::processMapBlockReply); msg->setHandlerFunc("MapItemReply", LLWorldMapMessage::processMapItemReply); msg->setHandlerFunc("EventInfoReply", LLEventNotifier::processEventInfoReply); diff --git a/indra/newview/llstatusbar.cpp b/indra/newview/llstatusbar.cpp index ecbbc4b2c5..1bab602364 100644 --- a/indra/newview/llstatusbar.cpp +++ b/indra/newview/llstatusbar.cpp @@ -109,6 +109,7 @@ static void onClickVolume(void*); LLStatusBar::LLStatusBar(const LLRect& rect) : LLPanel(), mTextTime(NULL), + mTextFps(NULL), mSGBandwidth(NULL), mSGPacketLoss(NULL), mBtnVolume(NULL), @@ -127,6 +128,7 @@ LLStatusBar::LLStatusBar(const LLRect& rect) mBalanceTimer = new LLFrameTimer(); mHealthTimer = new LLFrameTimer(); + mFpsUpdateTimer = new LLFrameTimer(); buildFromFile("panel_status_bar.xml"); } @@ -165,6 +167,9 @@ bool LLStatusBar::postBuild() mTextTime = getChild<LLTextBox>("TimeText" ); + mTextFps = getChild<LLButton>("FpsText"); + mTextFps->setClickedCallback( &LLStatusBar::onClickFps, this ); + getChild<LLUICtrl>("buyL")->setCommitCallback( boost::bind(&LLStatusBar::onClickBuyCurrency, this)); @@ -297,6 +302,16 @@ void LLStatusBar::refresh() //mSGBandwidth->setThreshold(2, bwtotal); } + if(mFpsUpdateTimer->getElapsedTimeF32() >= 1.0f) + { + mFpsUpdateTimer->reset(); + + S32 fps = (S32) llround(LLTrace::get_frame_recording().getPeriodMedianPerSec(LLStatViewer::FPS, 50)); + std::string fpsStr = std::to_string(fps); + //mTextFps->setText(fpsStr); + mTextFps->setLabel(fpsStr); + } + // update clock every 10 seconds if(mClockUpdateTimer.getElapsedTimeF32() > 10.f) { @@ -637,6 +652,12 @@ void LLStatusBar::onClickMediaToggle(void* data) LLViewerMedia::getInstance()->setAllMediaPaused(pause); } +//static +void LLStatusBar::onClickFps(void* data) +{ + LLFloaterReg::toggleInstance("mpv_performance"); +} + bool can_afford_transaction(S32 cost) { return((cost <= 0)||((gStatusBar) && (gStatusBar->getBalance() >=cost))); diff --git a/indra/newview/llstatusbar.h b/indra/newview/llstatusbar.h index 4c9d3e0c08..7e1ecf08ca 100644 --- a/indra/newview/llstatusbar.h +++ b/indra/newview/llstatusbar.h @@ -109,6 +109,8 @@ private: static void onClickMediaToggle(void* data); static void onClickBalance(void* data); + static void onClickFps(void* data); + LLSearchEditor *mFilterEdit; LLPanel *mSearchPanel; void onUpdateFilterTerm(); @@ -121,6 +123,7 @@ private: private: LLTextBox *mTextTime; + LLButton *mTextFps; LLStatGraph *mSGBandwidth; LLStatGraph *mSGPacketLoss; @@ -131,6 +134,7 @@ private: LLTextBox *mBoxBalance; LLButton *mMediaToggle; LLFrameTimer mClockUpdateTimer; + LLFrameTimer *mFpsUpdateTimer; S32 mBalance; S32 mHealth; diff --git a/indra/newview/lltoastalertpanel.h b/indra/newview/lltoastalertpanel.h index 167a7b2363..c2cdd775f1 100644 --- a/indra/newview/lltoastalertpanel.h +++ b/indra/newview/lltoastalertpanel.h @@ -82,14 +82,10 @@ private: struct ButtonData { - ButtonData() - : mWidth(0) - {} - - LLButton* mButton; + LLButton* mButton = nullptr; std::string mURL; - U32 mURLExternal; - S32 mWidth; + U32 mURLExternal = 0; + S32 mWidth = 0; }; std::vector<ButtonData> mButtonData; diff --git a/indra/newview/lltracker.cpp b/indra/newview/lltracker.cpp index a28bbb3bf1..ac93d1693a 100644 --- a/indra/newview/lltracker.cpp +++ b/indra/newview/lltracker.cpp @@ -493,7 +493,7 @@ void draw_shockwave(F32 center_z, F32 t, S32 steps, LLColor4 color) void LLTracker::drawBeacon(LLVector3 pos_agent, std::string direction, LLColor4 fogged_color, F32 dist) { const F32 MAX_HEIGHT = 5020.f; - const U32 BEACON_ROWS = 256; + const U32 BEACON_ROWS = 128; U32 nRows; F32 height; @@ -517,11 +517,10 @@ void LLTracker::drawBeacon(LLVector3 pos_agent, std::string direction, LLColor4 } nRows = ceil((BEACON_ROWS * height) / MAX_HEIGHT); + if(nRows<2) nRows=2; rowHeight = height / nRows; - gGL.color4fv(fogged_color.mV); - LLVector3 x_axis = LLViewerCamera::getInstance()->getLeftAxis(); F32 t = gRenderStartTime.getElapsedTimeF32(); @@ -536,6 +535,8 @@ void LLTracker::drawBeacon(LLVector3 pos_agent, std::string direction, LLColor4 bool tracking_avatar = getTrackingStatus() == TRACKING_AVATAR; + gGL.color4fv(fogged_color.mV); + gGL.begin(LLRender::TRIANGLES); for (U32 i = 0; i < nRows; i++) diff --git a/indra/newview/llversioninfo.cpp b/indra/newview/llversioninfo.cpp index a571b5544b..e598303305 100644 --- a/indra/newview/llversioninfo.cpp +++ b/indra/newview/llversioninfo.cpp @@ -158,9 +158,9 @@ LLVersionInfo::ViewerMaturity LLVersionInfo::getViewerMaturity() else { LL_WARNS() << "Channel '" << channel - << "' does not follow naming convention, assuming Test" + << "' does not follow naming convention, assuming Release" << LL_ENDL; - maturity = TEST_VIEWER; + maturity = RELEASE_VIEWER; } return maturity; } diff --git a/indra/newview/llviewercamera.cpp b/indra/newview/llviewercamera.cpp index ab7953846f..7b9aba96ed 100644 --- a/indra/newview/llviewercamera.cpp +++ b/indra/newview/llviewercamera.cpp @@ -204,6 +204,7 @@ void LLViewerCamera::calcProjection(const F32 far_distance) const //static void LLViewerCamera::updateFrustumPlanes(LLCamera& camera, bool ortho, bool zflip, bool no_hacks) { +#if GLU_VERSION_1_1 GLint* viewport = (GLint*) gGLViewport; F64 model[16]; F64 proj[16]; @@ -296,6 +297,7 @@ void LLViewerCamera::updateFrustumPlanes(LLCamera& camera, bool ortho, bool zfli } camera.calcAgentFrustumPlanes(frust); +#endif // GLU_VERSION_1_1 } void LLViewerCamera::setPerspective(bool for_selection, @@ -438,12 +440,14 @@ void LLViewerCamera::projectScreenToPosAgent(const S32 screen_x, const S32 scree proj[i] = (F64) gGLProjection[i]; } +#if GLU_VERSION_1_1 gluUnProject( GLdouble(screen_x), GLdouble(screen_y), 0.0, mdlv, proj, (GLint*)gGLViewport, &x, &y, &z ); +#endif pos_agent->setVec( (F32)x, (F32)y, (F32)z ); } @@ -486,6 +490,7 @@ bool LLViewerCamera::projectPosAgentToScreen(const LLVector3 &pos_agent, LLCoord proj[i] = (F64) gGLProjection[i]; } +#if GLU_VERSION_1_1 if (GL_TRUE == gluProject(pos_agent.mV[VX], pos_agent.mV[VY], pos_agent.mV[VZ], mdlv, proj, (GLint*)viewport, &x, &y, &z)) @@ -562,6 +567,7 @@ bool LLViewerCamera::projectPosAgentToScreen(const LLVector3 &pos_agent, LLCoord } } else +#endif // GLU_VERSION_1_1 { return false; } @@ -573,6 +579,7 @@ bool LLViewerCamera::projectPosAgentToScreen(const LLVector3 &pos_agent, LLCoord bool LLViewerCamera::projectPosAgentToScreenEdge(const LLVector3 &pos_agent, LLCoordGL &out_point) const { +#if GLU_VERSION_1_1 LLVector3 dir_to_point = pos_agent - getOrigin(); dir_to_point /= dir_to_point.magVec(); @@ -719,6 +726,7 @@ bool LLViewerCamera::projectPosAgentToScreenEdge(const LLVector3 &pos_agent, out_point.mY = int_y + world_rect.mBottom; return true; } +#endif // GLU_VERSION_1_1 return false; } diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp index 09f77c0c29..3183b39e98 100644 --- a/indra/newview/llviewerdisplay.cpp +++ b/indra/newview/llviewerdisplay.cpp @@ -1552,7 +1552,9 @@ void render_ui_2d() // Render 2D UI elements that overlay the world (no z compare) // Disable wireframe mode below here, as this is HUD/menus +#if GL_VERSION_1_1 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); +#endif // Menu overlays, HUD, etc gViewerWindow->setup2DRender(); diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index ceda2675d5..945d75351c 100644 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -81,6 +81,7 @@ #include "llfloatergroups.h" #include "llfloaterhelpbrowser.h" #include "llfloaterhoverheight.h" +#include "mpfloatertuning.h" #include "llfloaterhowto.h" #include "llfloaterhud.h" #include "llfloaterimagepreview.h" @@ -173,6 +174,8 @@ #include "llscriptfloater.h" #include "llsyswellwindow.h" +#include "fsfloatersearch.h" + // *NOTE: Please add files in alphabetical order to keep merges easy. // handle secondlife:///app/openfloater/{NAME} URLs @@ -380,6 +383,9 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("edit_hover_height", "floater_edit_hover_height.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterHoverHeight>); LLFloaterReg::add("hud", "floater_hud.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterHUD>); + LLFloaterReg::add("mpv_performance", "floater_mp_performance.xml", (LLFloaterBuildFunc)& + LLFloaterReg::build<MPFloaterTuning>); + LLFloaterReg::add("impanel", "floater_im_session.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterIMSession>); LLFloaterReg::add("im_container", "floater_im_container.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterIMContainer>); LLFloaterReg::add("im_well_window", "floater_sys_well.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLIMWellWindow>); @@ -486,7 +492,8 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("stop_queue", "floater_script_queue.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterNotRunQueue>); LLFloaterReg::add("snapshot", "floater_snapshot.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSnapshot>); LLFloaterReg::add("simple_snapshot", "floater_simple_snapshot.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSimpleSnapshot>); - LLFloaterReg::add("search", "floater_search.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSearch>); + LLFloaterReg::add("search", "floater_fs_search.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<FSFloaterSearch>); + //LLFloaterReg::add("search", "floater_search.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSearch>); LLFloaterReg::add("profile", "floater_profile.xml",(LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterProfile>); LLFloaterReg::add("guidebook", "floater_how_to.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterHowTo>); diff --git a/indra/newview/llviewerinput.cpp b/indra/newview/llviewerinput.cpp index ea3088613f..ffcbd1b4d8 100644 --- a/indra/newview/llviewerinput.cpp +++ b/indra/newview/llviewerinput.cpp @@ -48,6 +48,9 @@ #include "llinitparam.h" #include "llselectmgr.h" +#include "llfloaterwebcontent.h" +#include "fsfloatersearch.h" + // // Constants // @@ -648,6 +651,12 @@ bool start_chat( EKeystate s ) bool start_gesture( EKeystate s ) { + LLFloater* focused_floater = gFloaterView->getFocusedFloater(); + if (focused_floater && (dynamic_cast<LLFloaterWebContent*>(focused_floater) || dynamic_cast<FSFloaterSearch*>(focused_floater))) + { + return true; + } + LLUICtrl* focus_ctrlp = dynamic_cast<LLUICtrl*>(gFocusMgr.getKeyboardFocus()); if (KEYSTATE_UP == s && ! (focus_ctrlp && focus_ctrlp->acceptsTextInput())) diff --git a/indra/newview/llviewerjointmesh.cpp b/indra/newview/llviewerjointmesh.cpp index f0567b18c4..3ecf3c39b2 100644 --- a/indra/newview/llviewerjointmesh.cpp +++ b/indra/newview/llviewerjointmesh.cpp @@ -56,7 +56,7 @@ #include "llmatrix4a.h" #include "llperfstats.h" -#if !LL_DARWIN && !LL_LINUX +#if !LL_DARWIN && !LL_LINUX && !__FreeBSD__ extern PFNGLWEIGHTPOINTERARBPROC glWeightPointerARB; extern PFNGLWEIGHTFVARBPROC glWeightfvARB; extern PFNGLVERTEXBLENDARBPROC glVertexBlendARB; @@ -242,7 +242,9 @@ U32 LLViewerJointMesh::drawShape( F32 pixelArea, bool first_pass, bool is_dummy) stop_glerror(); +#if GL_VERSION_1_1 LLGLSSpecular specular(LLColor4(1.f,1.f,1.f,1.f), 0.f); +#endif //---------------------------------------------------------------- // setup current texture @@ -407,10 +409,16 @@ void LLViewerJointMesh::updateFaceData(LLFace *face, F32 pixel_area, bool damp_w F32* vw = (F32*) vertex_weightsp.get(); F32* cw = (F32*) clothing_weightsp.get(); - S32 tc_size = (num_verts*2*sizeof(F32)+0xF) & ~0xF; - LLVector4a::memcpyNonAliased16(tc, (F32*) mMesh->getTexCoords(), tc_size); - S32 vw_size = (num_verts*sizeof(F32)+0xF) & ~0xF; - LLVector4a::memcpyNonAliased16(vw, (F32*) mMesh->getWeights(), vw_size); + //S32 tc_size = (num_verts*2*sizeof(F32)+0xF) & ~0xF; + //LLVector4a::memcpyNonAliased16(tc, (F32*) mMesh->getTexCoords(), tc_size); + //S32 vw_size = (num_verts*sizeof(F32)+0xF) & ~0xF; + //LLVector4a::memcpyNonAliased16(vw, (F32*) mMesh->getWeights(), vw_size); + + // Both allocated in LLPolyMeshSharedData::allocateVertexData(unsigned int) + + memcpy(tc, mMesh->getTexCoords(), num_verts*2*sizeof(F32) ); + memcpy(vw, mMesh->getWeights(), num_verts*sizeof(F32) ); + LLVector4a::memcpyNonAliased16(cw, (F32*) mMesh->getClothingWeights(), num_verts*4*sizeof(F32)); } diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index 49b483d0d0..3a2d1c400b 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -397,7 +397,7 @@ std::string LLViewerMedia::getCurrentUserAgent() // This was also helpful: // http://www.mozilla.org/build/revised-user-agent-strings.html std::ostringstream codec; - codec << "SecondLife/"; + codec << "Megapahit/"; codec << LLVersionInfo::instance().getVersion(); codec << " (" << channel << "; " << skin_name << " skin)"; LL_INFOS() << codec.str() << LL_ENDL; @@ -1719,12 +1719,17 @@ LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_ { std::string launcher_name = gDirUtilp->getLLPluginLauncher(); std::string plugin_name = gDirUtilp->getLLPluginFilename(plugin_basename); +#if __FreeBSD__ + if (plugin_basename == "media_plugin_cef") + { + launcher_name = "/compat/linux/usr/libexec/megapahit/SLPlugin"; + plugin_name = "/compat/linux/usr/lib/x86_64-linux-gnu/libmedia_plugin_cef.so"; + } +#endif std::string user_data_path_cache = gDirUtilp->getCacheDir(false); user_data_path_cache += gDirUtilp->getDirDelimiter(); - std::string user_data_path_cef_log = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "cef_log.txt"); - // See if the plugin executable exists llstat s; if(LLFile::stat(launcher_name, &s)) @@ -1733,14 +1738,13 @@ LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_ } else if(LLFile::stat(plugin_name, &s)) { -#if !LL_LINUX LL_WARNS_ONCE("Media") << "Couldn't find plugin at " << plugin_name << LL_ENDL; -#endif } else { media_source = new LLPluginClassMedia(owner); media_source->setSize(default_width, default_height); + std::string user_data_path_cef_log = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "cef.log"); media_source->setUserDataPath(user_data_path_cache, gDirUtilp->getUserName(), user_data_path_cef_log); media_source->setLanguageCode(LLUI::getLanguage()); media_source->setZoomFactor(zoom_factor); @@ -1766,6 +1770,11 @@ LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_ bool media_plugin_debugging_enabled = gSavedSettings.getBOOL("MediaPluginDebugging"); media_source->enableMediaPluginDebugging( media_plugin_debugging_enabled || clean_browser); +#if LL_LINUX + bool media_plugin_pipewire_volume_catcher = gSavedSettings.getBOOL("MediaPluginPipeWireVolumeCatcher"); + media_source->enablePipeWireVolumeCatcher( media_plugin_pipewire_volume_catcher ); +#endif + // need to set agent string here before instance created media_source->setBrowserUserAgent(LLViewerMedia::getInstance()->getCurrentUserAgent()); @@ -1775,7 +1784,16 @@ LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_ media_source->setTarget(target); +#if __FreeBSD__ + std::string plugin_dir = gDirUtilp->getLLPluginDir(); + if (plugin_basename == "media_plugin_cef") + { + plugin_dir = "/compat/linux/usr/lib/x86_64-linux-gnu"; + plugin_name = "/usr/lib/x86_64-linux-gnu/libmedia_plugin_cef.so"; + } +#else const std::string plugin_dir = gDirUtilp->getLLPluginDir(); +#endif if (media_source->init(launcher_name, plugin_dir, plugin_name, gSavedSettings.getBOOL("PluginAttachDebuggerToPlugins"))) { return media_source; @@ -1787,9 +1805,7 @@ LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_ } } } -#if !LL_LINUX LL_WARNS_ONCE("Plugin") << "plugin initialization failed for mime type: " << media_type << LL_ENDL; -#endif if(gAgent.isInitialized()) { diff --git a/indra/newview/llviewermedia_streamingaudio.cpp b/indra/newview/llviewermedia_streamingaudio.cpp index af3a21c183..15b6e3f802 100644 --- a/indra/newview/llviewermedia_streamingaudio.cpp +++ b/indra/newview/llviewermedia_streamingaudio.cpp @@ -34,6 +34,7 @@ #include "llmimetypes.h" #include "lldir.h" +#include "llnotificationmanager.h" LLStreamingAudio_MediaPlugins::LLStreamingAudio_MediaPlugins() : mMediaPlugin(NULL), @@ -114,6 +115,12 @@ int LLStreamingAudio_MediaPlugins::isPlaying() LLPluginClassMediaOwner::EMediaStatus status = mMediaPlugin->getStatus(); + auto nowPlaying = mMediaPlugin->getMediaNowPlaying(); + if (mNowPlaying != nowPlaying) + { + LLNotificationsUI::LLNotificationManager::instance().onChat(LLChat{llformat("Now playing %s.", nowPlaying.c_str())}, LLSD{}); + mNowPlaying = nowPlaying; + } switch (status) { diff --git a/indra/newview/llviewermedia_streamingaudio.h b/indra/newview/llviewermedia_streamingaudio.h index bf4d92c29e..5abefcdb0b 100644 --- a/indra/newview/llviewermedia_streamingaudio.h +++ b/indra/newview/llviewermedia_streamingaudio.h @@ -56,6 +56,7 @@ private: LLPluginClassMedia *mMediaPlugin; std::string mURL; + std::string mNowPlaying; F32 mGain; }; diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 9a9a316adf..75bef846fe 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -72,6 +72,7 @@ #include "llfloaterpay.h" #include "llfloaterreporter.h" #include "llfloatersearch.h" +#include "fsfloatersearch.h" #include "llfloaterscriptdebug.h" #include "llfloatersnapshot.h" #include "llfloatertools.h" @@ -6553,6 +6554,26 @@ void handle_zoom_to_object(LLUUID object_id) } } +void handle_teleport_to_object(LLUUID object_id) +{ + LLViewerObject* object = gObjectList.findObject(object_id); + + if (object) + { + gAgentCamera.setFocusOnAvatar(FALSE, ANIMATE); + + LLBBox bbox = object->getBoundingBoxAgent() ; + + LLVector3 obj_to_cam = LLViewerCamera::getInstance()->getOrigin() - bbox.getCenterAgent(); + obj_to_cam.normVec(); + + + LLVector3d object_center_global = gAgent.getPosGlobalFromAgent(bbox.getCenterAgent()); + + gAgent.teleportViaLocation(object_center_global); + } +} + class LLAvatarInviteToGroup : public view_listener_t { bool handleEvent(const LLSD& userdata) diff --git a/indra/newview/llviewermenu.h b/indra/newview/llviewermenu.h index 8c5e0705d0..49c2b6272c 100644 --- a/indra/newview/llviewermenu.h +++ b/indra/newview/llviewermenu.h @@ -107,6 +107,7 @@ void handle_take(bool take_separate = false); void handle_take_copy(); void handle_look_at_selection(const LLSD& param); void handle_zoom_to_object(LLUUID object_id); +void handle_teleport_to_object(LLUUID object_id); void handle_object_return(); void handle_object_delete(); void handle_object_edit(); diff --git a/indra/newview/llviewernetwork.cpp b/indra/newview/llviewernetwork.cpp index 16ddc2f89c..b8c9594aa7 100644 --- a/indra/newview/llviewernetwork.cpp +++ b/indra/newview/llviewernetwork.cpp @@ -629,6 +629,18 @@ bool LLGridManager::isInProductionGrid() return mIsInProductionGrid; } +bool LLGridManager::isInSecondlife() +{ + //return (isInSLMain() || isInSLBeta()); + return true; +} + +bool LLGridManager::isInOpenSim() +{ + // FIX THIS TO SUPPORT OPENSIM + return false; +} + bool LLGridManager::isSystemGrid(const std::string& grid) { std::string grid_name = getGrid(grid); diff --git a/indra/newview/llviewernetwork.h b/indra/newview/llviewernetwork.h index 2ed663e038..7d9c70994c 100644 --- a/indra/newview/llviewernetwork.h +++ b/indra/newview/llviewernetwork.h @@ -174,6 +174,20 @@ class LLGridManager : public LLSingleton<LLGridManager> //@} + typedef enum e_grid_platform { + NOPLATFORM = 0, + SLMAIN, + SLBETA, + OPENSIM, + HALCYON + } EGridPlatform; + + typedef enum e_add_grid { + ADD_MANUAL = 0, + ADD_HYPERGRID, + ADD_LINK + } EAddGridType; + /* ================================================================ * @name Selecting the current grid * @{ @@ -198,6 +212,11 @@ class LLGridManager : public LLSingleton<LLGridManager> /// Is the selected grid one of the hard-coded default grids (Agni or Aditi) bool isSystemGrid() { return isSystemGrid(mGrid); } + /// Is the selected grid Second Life? + bool isInSecondlife(); + + bool isInOpenSim(); + /// Is the selected grid a production grid? bool isInProductionGrid(); /** diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index 9ad2474e9b..8ea5ee33f3 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -2915,24 +2915,33 @@ void LLViewerObject::fetchInventoryFromServer() delete mInventory; mInventory = NULL; - // Results in processTaskInv - LLMessageSystem* msg = gMessageSystem; - msg->newMessageFast(_PREHASH_RequestTaskInventory); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->nextBlockFast(_PREHASH_InventoryData); - msg->addU32Fast(_PREHASH_LocalID, mLocalID); - msg->sendReliable(mRegionp->getHost()); - // This will get reset by doInventoryCallback or processTaskInv mInvRequestState = INVENTORY_REQUEST_PENDING; + + if (mRegionp && !mRegionp->getCapability("RequestTaskInventory").empty()) + { + LLCoros::instance().launch("LLViewerObject::fetchInventoryFromCapCoro()", + boost::bind(&LLViewerObject::fetchInventoryFromCapCoro, mID)); + } + else + { + LL_WARNS() << "Using old task inventory path!" << LL_ENDL; + // Results in processTaskInv + LLMessageSystem *msg = gMessageSystem; + msg->newMessageFast(_PREHASH_RequestTaskInventory); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->nextBlockFast(_PREHASH_InventoryData); + msg->addU32Fast(_PREHASH_LocalID, mLocalID); + msg->sendReliable(mRegionp->getHost()); + } } } void LLViewerObject::fetchInventoryDelayed(const F64 &time_seconds) { - // unless already waiting, drop previous request and shedule an update + // unless already waiting, drop previous request and schedule an update if (mInvRequestState != INVENTORY_REQUEST_WAIT) { if (mInvRequestXFerId != 0) @@ -2963,6 +2972,80 @@ void LLViewerObject::fetchInventoryDelayedCoro(const LLUUID task_inv, const F64 } } +//static +void LLViewerObject::fetchInventoryFromCapCoro(const LLUUID task_inv) +{ + LLViewerObject *obj = gObjectList.findObject(task_inv); + if (obj) + { + LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID); + LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t + httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("TaskInventoryRequest", httpPolicy)); + LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest); + std::string url = obj->mRegionp->getCapability("RequestTaskInventory") + "?task_id=" + obj->mID.asString(); + // If we already have a copy of the inventory then add it so the server won't re-send something we already have. + // We expect this case to crop up in the case of failed inventory mutations, but it might happen otherwise as well. + if (obj->mInventorySerialNum && obj->mInventory) + url += "&inventory_serial=" + std::to_string(obj->mInventorySerialNum); + + obj->mInvRequestState = INVENTORY_XFER; + LLSD result = httpAdapter->getAndSuspend(httpRequest, url); + + LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; + LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); + + // Object may have gone away while we were suspended, double-check that it still exists + obj = gObjectList.findObject(task_inv); + if (!obj) + { + LL_WARNS() << "Object " << task_inv << " went away while fetching inventory, dropping result" << LL_ENDL; + return; + } + + bool potentially_stale = false; + if (status) + { + // Dealing with inventory serials is kind of funky. They're monotonically increasing and 16 bits, + // so we expect them to overflow, but we can use inv serial < expected serial as a signal that we may + // have mutated the task inventory since we kicked off the request, and those mutations may have not + // been taken into account yet. Of course, those mutations may have actually failed which would result + // in the inv serial never increasing. + // + // When we detect this case, set the expected inv serial to the inventory serial we actually received + // and kick off a re-request after a slight delay. + S16 serial = (S16)result["inventory_serial"].asInteger(); + potentially_stale = serial < obj->mExpectedInventorySerialNum; + LL_INFOS() << "Inventory loaded for " << task_inv << LL_ENDL; + obj->mInventorySerialNum = serial; + obj->mExpectedInventorySerialNum = serial; + obj->loadTaskInvLLSD(result); + } + else if (status.getType() == 304) + { + LL_INFOS() << "Inventory wasn't changed on server!" << LL_ENDL; + obj->mInvRequestState = INVENTORY_REQUEST_STOPPED; + // Even though it wasn't necessary to send a response, we still may have mutated + // the inventory since we kicked off the request, check for that case. + potentially_stale = obj->mInventorySerialNum < obj->mExpectedInventorySerialNum; + // Set this to what we already have so that we don't re-request a second time. + obj->mExpectedInventorySerialNum = obj->mInventorySerialNum; + } + else + { + // Not sure that there's anything sensible we can do to recover here, retrying in a loop would be bad. + LL_WARNS() << "Error status while requesting task inventory: " << status.toString() << LL_ENDL; + obj->mInvRequestState = INVENTORY_REQUEST_STOPPED; + } + + if (potentially_stale) + { + // Stale? I guess we can use what we got for now, but we'll have to re-request + LL_WARNS() << "Stale inv_serial? Re-requesting." << LL_ENDL; + obj->fetchInventoryDelayed(INVENTORY_UPDATE_WAIT_TIME_OUTDATED); + } + } +} + LLControlAvatar *LLViewerObject::getControlAvatar() { return getRootEdit()->mControlAvatar.get(); @@ -3138,6 +3221,20 @@ void LLViewerObject::processTaskInv(LLMessageSystem* msg, void** user_data) S16 serial = 0; msg->getS16Fast(_PREHASH_InventoryData, _PREHASH_Serial, serial); + if (object->mRegionp && !object->mRegionp->getCapability("RequestTaskInventory").empty()) + { + // It seems that simulator may ask us to re-download the task inventory if an update to the inventory + // happened out-of-band while we had the object selected (like if a script is saved.) + // + // If we're meant to use the HTTP capability, ignore the contents of the UDP message and fetch the + // inventory via the CAP so that we don't flow down the UDP inventory request path unconditionally here. + // We shouldn't need to wait, as any updates should already be ready to fetch by this point. + LL_INFOS() << "Handling unsolicited ReplyTaskInventory for " << task_id << LL_ENDL; + object->mExpectedInventorySerialNum = serial; + object->fetchInventoryFromServer(); + return; + } + if (serial == object->mInventorySerialNum && serial < object->mExpectedInventorySerialNum) { @@ -3345,6 +3442,47 @@ bool LLViewerObject::loadTaskInvFile(const std::string& filename) return true; } +void LLViewerObject::loadTaskInvLLSD(const LLSD& inv_result) +{ + if (inv_result.has("contents")) + { + if(mInventory) + { + mInventory->clear(); // will deref and delete it + } + else + { + mInventory = new LLInventoryObject::object_list_t; + } + + // Synthesize the "Contents" category, the viewer expects it, but it isn't sent. + LLPointer<LLInventoryObject> inv = new LLInventoryObject(mID, LLUUID::null, LLAssetType::AT_CATEGORY, "Contents"); + mInventory->push_front(inv); + + const LLSD& inventory = inv_result["contents"]; + for (const auto& inv_entry : llsd::inArray(inventory)) + { + if (inv_entry.has("item_id")) + { + LLPointer<LLViewerInventoryItem> inv = new LLViewerInventoryItem; + inv->unpackMessage(inv_entry); + mInventory->push_front(inv); + } + else + { + LL_WARNS_ONCE() << "Unknown inventory entry while reading from inventory file. Entry: '" + << inv_entry << "'" << LL_ENDL; + } + } + } + else + { + LL_WARNS() << "unable to load task inventory: " << inv_result << LL_ENDL; + return; + } + doInventoryCallback(); +} + void LLViewerObject::doInventoryCallback() { for (callback_list_t::iterator iter = mInventoryCallbacks.begin(); diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h index b6846c6716..09f813accc 100644 --- a/indra/newview/llviewerobject.h +++ b/indra/newview/llviewerobject.h @@ -688,6 +688,7 @@ private: // forms task inventory request after some time passed, marks request as pending void fetchInventoryDelayed(const F64 &time_seconds); static void fetchInventoryDelayedCoro(const LLUUID task_inv, const F64 time_seconds); + static void fetchInventoryFromCapCoro(const LLUUID task_inv); public: // @@ -822,6 +823,7 @@ protected: static void processTaskInvFile(void** user_data, S32 error_code, LLExtStat ext_status); bool loadTaskInvFile(const std::string& filename); + void loadTaskInvLLSD(const LLSD &inv_result); void doInventoryCallback(); bool isOnMap(); diff --git a/indra/newview/llvieweroctree.cpp b/indra/newview/llvieweroctree.cpp index b1673d2232..a1c2e0f9ff 100644 --- a/indra/newview/llvieweroctree.cpp +++ b/indra/newview/llvieweroctree.cpp @@ -1217,7 +1217,15 @@ void LLOcclusionCullingGroup::doOcclusion(LLCamera* camera, const LLVector4a* sh LLGLEnable clamp(use_depth_clamp ? GL_DEPTH_CLAMP : 0); - U32 mode = gGLManager.mGLVersion >= 3.3f ? GL_ANY_SAMPLES_PASSED : GL_SAMPLES_PASSED; + U32 mode = +#if GL_VERSION_1_5 + gGLManager.mGLVersion >= 3.3f ? +#endif + GL_ANY_SAMPLES_PASSED +#if GL_VERSION_1_5 + : GL_SAMPLES_PASSED +#endif + ; #if LL_TRACK_PENDING_OCCLUSION_QUERIES sPendingQueries.insert(mOcclusionQuery[LLViewerCamera::sCurCameraID]); diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index 19a1990665..052c222d9a 100755 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -3218,6 +3218,7 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames) capabilityNames.append("FetchInventory2"); capabilityNames.append("FetchInventoryDescendents2"); capabilityNames.append("IncrementCOFVersion"); + capabilityNames.append("RequestTaskInventory"); AISAPI::getCapNames(capabilityNames); capabilityNames.append("InterestList"); diff --git a/indra/newview/llviewerstats.cpp b/indra/newview/llviewerstats.cpp index 3499c7eb7d..fb874f9d7f 100644 --- a/indra/newview/llviewerstats.cpp +++ b/indra/newview/llviewerstats.cpp @@ -827,6 +827,8 @@ void send_viewer_stats(bool include_preferences) LL_INFOS("LogViewerStatsPacket") << "Sending viewer statistics: " << body << LL_ENDL; + + // <ND> Do those lines even do anything sane in regard of debug logging? LL_DEBUGS("LogViewerStatsPacket"); std::string filename("viewer_stats_packet.xml"); llofstream of(filename.c_str()); diff --git a/indra/newview/llviewerstatsrecorder.cpp b/indra/newview/llviewerstatsrecorder.cpp index 88edb96fbb..2e4002479d 100644 --- a/indra/newview/llviewerstatsrecorder.cpp +++ b/indra/newview/llviewerstatsrecorder.cpp @@ -317,5 +317,3 @@ F32 LLViewerStatsRecorder::getTimeSinceStart() { return (F32) (LLFrameTimer::getTotalSeconds() - mFileOpenTime); } - - diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp index b90c1868fc..c812504f9b 100644 --- a/indra/newview/llviewertexturelist.cpp +++ b/indra/newview/llviewertexturelist.cpp @@ -171,15 +171,25 @@ void LLViewerTextureList::doPreloadImages() image->setAddressMode(LLTexUnit::TAM_WRAP); mImagePreloads.insert(image); } +#if GL_VERSION_1_1 image = LLViewerTextureManager::getFetchedTextureFromFile("alpha_gradient.tga", FTT_LOCAL_FILE, MIPMAP_YES, LLViewerFetchedTexture::BOOST_UI, LLViewerTexture::FETCHED_TEXTURE, GL_ALPHA8, GL_ALPHA, IMG_ALPHA_GRAD); +#else + image = LLViewerTextureManager::getFetchedTextureFromFile("alpha_gradient.tga", FTT_LOCAL_FILE, MIPMAP_YES, LLViewerFetchedTexture::BOOST_UI, LLViewerTexture::FETCHED_TEXTURE, + GL_ALPHA8_EXT, GL_ALPHA, IMG_ALPHA_GRAD); +#endif if (image) { image->setAddressMode(LLTexUnit::TAM_CLAMP); mImagePreloads.insert(image); } +#if GL_VERSION_1_1 image = LLViewerTextureManager::getFetchedTextureFromFile("alpha_gradient_2d.j2c", FTT_LOCAL_FILE, MIPMAP_YES, LLViewerFetchedTexture::BOOST_UI, LLViewerTexture::FETCHED_TEXTURE, GL_ALPHA8, GL_ALPHA, IMG_ALPHA_GRAD_2D); +#else + image = LLViewerTextureManager::getFetchedTextureFromFile("alpha_gradient_2d.j2c", FTT_LOCAL_FILE, MIPMAP_YES, LLViewerFetchedTexture::BOOST_UI, LLViewerTexture::FETCHED_TEXTURE, + GL_ALPHA8_EXT, GL_ALPHA, IMG_ALPHA_GRAD_2D); +#endif if (image) { image->setAddressMode(LLTexUnit::TAM_CLAMP); diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 48439765e4..ffba4756fc 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -2008,6 +2008,8 @@ LLViewerWindow::LLViewerWindow(const Params& p) mDebugText = new LLDebugText(this); mWorldViewRectScaled = calcScaledRect(mWorldViewRectRaw, mDisplayScale); + + mWindow->toggleVSync(gSavedSettings.getBOOL("RenderVSyncEnabled")); } std::string LLViewerWindow::getLastSnapshotDir() @@ -3153,6 +3155,14 @@ bool LLViewerWindow::handleUnicodeChar(llwchar uni_char, MASK mask) return false; } +bool LLViewerWindow::handleUnicodeString(char *uni_str, bool editing) +{ + auto keyboard_focus = gFocusMgr.getKeyboardFocus(); + if (keyboard_focus) + keyboard_focus->handleUnicodeString(uni_str, editing, FALSE); + + return TRUE; +} void LLViewerWindow::handleScrollWheel(S32 clicks) { diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h index 4a6b901b33..1f34495f23 100644 --- a/indra/newview/llviewerwindow.h +++ b/indra/newview/llviewerwindow.h @@ -195,6 +195,7 @@ public: /*virtual*/ bool handleTranslatedKeyUp(KEY key, MASK mask); /*virtual*/ void handleScanKey(KEY key, bool key_down, bool key_up, bool key_level); /*virtual*/ bool handleUnicodeChar(llwchar uni_char, MASK mask); // NOT going to handle extended + /*virtual*/ bool handleUnicodeString(char *uni_str, bool editing); /*virtual*/ bool handleMouseDown(LLWindow *window, LLCoordGL pos, MASK mask); /*virtual*/ bool handleMouseUp(LLWindow *window, LLCoordGL pos, MASK mask); /*virtual*/ bool handleCloseRequest(LLWindow *window); diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index c68ce8d956..2634e0d12a 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -70,6 +70,7 @@ #include "llmeshrepository.h" #include "llmutelist.h" #include "llmoveview.h" +#include "llnotificationmanager.h" #include "llnotificationsutil.h" #include "llphysicsshapebuilderutil.h" #include "llquantize.h" @@ -815,6 +816,10 @@ void LLVOAvatar::debugAvatarRezTime(std::string notification_name, std::string c //------------------------------------------------------------------------ LLVOAvatar::~LLVOAvatar() { + if (gSavedSettings.getBOOL("IMShowArrivalsDepartures") && !getFullname().empty()) + { + LLNotificationsUI::LLNotificationManager::instance().onChat(LLChat{llformat("%s left.", getFullname().c_str())}, LLSD{}); + } if (!mFullyLoaded) { debugAvatarRezTime("AvatarRezLeftCloudNotification","left after ruth seconds as cloud"); @@ -2495,6 +2500,23 @@ U32 LLVOAvatar::processUpdateMessage(LLMessageSystem *mesgsys, { mDebugExistenceTimer.reset(); debugAvatarRezTime("AvatarRezArrivedNotification", "avatar arrived"); + if (gSavedSettings.getBOOL("IMShowArrivalsDepartures")) + { + uuid_vec_t uuids; + std::vector<LLVector3d> positions; + LLWorld::getInstance()->getAvatars(&uuids, &positions, gAgent.getPositionGlobal(), gSavedSettings.getF32("MPVNearMeRange")); + auto pos_it = positions.begin(); + auto id_it = uuids.begin(); + for (;pos_it != positions.end() && id_it != uuids.end(); ++pos_it, ++id_it) + { + if (*id_it == getID() && !isSelf()) + { + LLNotificationsUI::LLNotificationManager::instance() + .onChat(LLChat{llformat("%s arrived (%.1f m).", getFullname().c_str(), dist_vec(*pos_it, gAgent.getPositionGlobal()))}, LLSD{}); + break; + } + } + } } if (retval & LLViewerObject::INVALID_UPDATE) @@ -11653,24 +11675,38 @@ void LLVOAvatar::placeProfileQuery() glGenQueries(1, &mGPUTimerQuery); } - glBeginQuery(GL_TIME_ELAPSED, mGPUTimerQuery); +#if GL_EXT_timer_query || GL_EXT_disjoint_timer_query + glBeginQuery(GL_TIME_ELAPSED_EXT, mGPUTimerQuery); +#endif } void LLVOAvatar::readProfileQuery(S32 retries) { if (!mGPUProfilePending) { - glEndQuery(GL_TIME_ELAPSED); +#if GL_EXT_timer_query || GL_EXT_disjoint_timer_query + glEndQuery(GL_TIME_ELAPSED_EXT); +#endif mGPUProfilePending = true; } +#if GL_ARB_timer_query GLuint64 result = 0; glGetQueryObjectui64v(mGPUTimerQuery, GL_QUERY_RESULT_AVAILABLE, &result); +#else + GLuint result = 0; + glGetQueryObjectuiv(mGPUTimerQuery, GL_QUERY_RESULT_AVAILABLE, &result); +#endif if (result == GL_TRUE || --retries <= 0) { // query available, readback result +#if GL_ARB_timer_query GLuint64 time_elapsed = 0; glGetQueryObjectui64v(mGPUTimerQuery, GL_QUERY_RESULT, &time_elapsed); +#else + GLuint time_elapsed = 0; + glGetQueryObjectuiv(mGPUTimerQuery, GL_QUERY_RESULT, &time_elapsed); +#endif mGPURenderTime = time_elapsed / 1000000.f; mGPUProfilePending = false; diff --git a/indra/newview/llvoiceclient.cpp b/indra/newview/llvoiceclient.cpp index 5af7528ada..5fee254354 100644 --- a/indra/newview/llvoiceclient.cpp +++ b/indra/newview/llvoiceclient.cpp @@ -26,7 +26,9 @@ #include "llvoiceclient.h" #include "llvoicevivox.h" +#if !__FreeBSD__ #include "llvoicewebrtc.h" +#endif #include "llviewernetwork.h" #include "llviewercontrol.h" #include "llcommandhandler.h" @@ -120,10 +122,12 @@ LLVoiceModuleInterface *getVoiceModule(const std::string &voice_server_type) { return (LLVoiceModuleInterface *) LLVivoxVoiceClient::getInstance(); } +#if !__FreeBSD__ else if (voice_server_type == WEBRTC_VOICE_SERVER_TYPE) { return (LLVoiceModuleInterface *) LLWebRTCVoiceClient::getInstance(); } +#endif else { LLNotificationsUtil::add("VoiceVersionMismatch"); @@ -165,14 +169,18 @@ void LLVoiceClient::init(LLPumpIO *pump) { // Initialize all of the voice modules m_servicePump = pump; +#if !__FreeBSD__ LLWebRTCVoiceClient::getInstance()->init(pump); +#endif LLVivoxVoiceClient::getInstance()->init(pump); } void LLVoiceClient::userAuthorized(const std::string& user_id, const LLUUID &agentID) { gAgent.addRegionChangedCallback(boost::bind(&LLVoiceClient::onRegionChanged, this)); +#if !__FreeBSD__ LLWebRTCVoiceClient::getInstance()->userAuthorized(user_id, agentID); +#endif LLVivoxVoiceClient::getInstance()->userAuthorized(user_id, agentID); } @@ -281,7 +289,9 @@ void LLVoiceClient::setNonSpatialVoiceModule(const std::string &voice_server_typ void LLVoiceClient::setHidden(bool hidden) { +#if !__FreeBSD__ LLWebRTCVoiceClient::getInstance()->setHidden(hidden); +#endif LLVivoxVoiceClient::getInstance()->setHidden(hidden); } @@ -322,7 +332,9 @@ void LLVoiceClient::updateSettings() updateMicMuteLogic(); +#if !__FreeBSD__ LLWebRTCVoiceClient::getInstance()->updateSettings(); +#endif LLVivoxVoiceClient::getInstance()->updateSettings(); } @@ -331,34 +343,54 @@ void LLVoiceClient::updateSettings() void LLVoiceClient::tuningStart() { +#if !__FreeBSD__ LLWebRTCVoiceClient::getInstance()->tuningStart(); +#endif LLVivoxVoiceClient::getInstance()->tuningStart(); } void LLVoiceClient::tuningStop() { +#if !__FreeBSD__ LLWebRTCVoiceClient::getInstance()->tuningStop(); +#endif LLVivoxVoiceClient::getInstance()->tuningStop(); } bool LLVoiceClient::inTuningMode() { +#if __FreeBSD__ + return LLVivoxVoiceClient::getInstance()->inTuningMode(); +#else return LLWebRTCVoiceClient::getInstance()->inTuningMode(); +#endif } void LLVoiceClient::tuningSetMicVolume(float volume) { +#if __FreeBSD__ + LLVivoxVoiceClient::getInstance()->tuningSetMicVolume(volume); +#else LLWebRTCVoiceClient::getInstance()->tuningSetMicVolume(volume); +#endif } void LLVoiceClient::tuningSetSpeakerVolume(float volume) { +#if __FreeBSD__ + LLVivoxVoiceClient::getInstance()->tuningSetSpeakerVolume(volume); +#else LLWebRTCVoiceClient::getInstance()->tuningSetSpeakerVolume(volume); +#endif } float LLVoiceClient::tuningGetEnergy(void) { +#if __FreeBSD__ + return LLVivoxVoiceClient::getInstance()->tuningGetEnergy(); +#else return LLWebRTCVoiceClient::getInstance()->tuningGetEnergy(); +#endif } //------------------------------------------------ @@ -366,40 +398,64 @@ float LLVoiceClient::tuningGetEnergy(void) bool LLVoiceClient::deviceSettingsAvailable() { +#if __FreeBSD__ + return LLVivoxVoiceClient::getInstance()->deviceSettingsAvailable(); +#else return LLWebRTCVoiceClient::getInstance()->deviceSettingsAvailable(); +#endif } bool LLVoiceClient::deviceSettingsUpdated() { +#if __FreeBSD__ + return LLVivoxVoiceClient::getInstance()->deviceSettingsUpdated(); +#else return LLWebRTCVoiceClient::getInstance()->deviceSettingsUpdated(); +#endif } void LLVoiceClient::refreshDeviceLists(bool clearCurrentList) { +#if __FreeBSD__ + LLVivoxVoiceClient::getInstance()->refreshDeviceLists(clearCurrentList); +#else LLWebRTCVoiceClient::getInstance()->refreshDeviceLists(clearCurrentList); +#endif } void LLVoiceClient::setCaptureDevice(const std::string& name) { LLVivoxVoiceClient::getInstance()->setCaptureDevice(name); +#if !__FreeBSD__ LLWebRTCVoiceClient::getInstance()->setCaptureDevice(name); +#endif } void LLVoiceClient::setRenderDevice(const std::string& name) { LLVivoxVoiceClient::getInstance()->setRenderDevice(name); +#if !__FreeBSD__ LLWebRTCVoiceClient::getInstance()->setRenderDevice(name); +#endif } const LLVoiceDeviceList& LLVoiceClient::getCaptureDevices() { +#if __FreeBSD__ + return LLVivoxVoiceClient::getInstance()->getCaptureDevices(); +#else return LLWebRTCVoiceClient::getInstance()->getCaptureDevices(); +#endif } const LLVoiceDeviceList& LLVoiceClient::getRenderDevices() { +#if __FreeBSD__ + return LLVivoxVoiceClient::getInstance()->getRenderDevices(); +#else return LLWebRTCVoiceClient::getInstance()->getRenderDevices(); +#endif } @@ -408,13 +464,18 @@ const LLVoiceDeviceList& LLVoiceClient::getRenderDevices() void LLVoiceClient::getParticipantList(std::set<LLUUID> &participants) const { +#if !__FreeBSD__ LLWebRTCVoiceClient::getInstance()->getParticipantList(participants); +#endif LLVivoxVoiceClient::getInstance()->getParticipantList(participants); } bool LLVoiceClient::isParticipant(const LLUUID &speaker_id) const { - return LLWebRTCVoiceClient::getInstance()->isParticipant(speaker_id) || + return +#if !__FreeBSD__ + LLWebRTCVoiceClient::getInstance()->isParticipant(speaker_id) || +#endif LLVivoxVoiceClient::getInstance()->isParticipant(speaker_id); } @@ -507,13 +568,19 @@ void LLVoiceClient::activateSpatialChannel(bool activate) bool LLVoiceClient::isCurrentChannel(const LLSD& channelInfo) { - return LLWebRTCVoiceClient::getInstance()->isCurrentChannel(channelInfo) || + return +#if !__FreeBSD__ + LLWebRTCVoiceClient::getInstance()->isCurrentChannel(channelInfo) || +#endif LLVivoxVoiceClient::getInstance()->isCurrentChannel(channelInfo); } bool LLVoiceClient::compareChannels(const LLSD &channelInfo1, const LLSD &channelInfo2) { - return LLWebRTCVoiceClient::getInstance()->compareChannels(channelInfo1, channelInfo2) || + return +#if !__FreeBSD__ + LLWebRTCVoiceClient::getInstance()->compareChannels(channelInfo1, channelInfo2) || +#endif LLVivoxVoiceClient::getInstance()->compareChannels(channelInfo1, channelInfo2); } @@ -555,13 +622,17 @@ LLVoiceP2POutgoingCallInterface *LLVoiceClient::getOutgoingCallInterface(const L void LLVoiceClient::setVoiceVolume(F32 volume) { +#if !__FreeBSD__ LLWebRTCVoiceClient::getInstance()->setVoiceVolume(volume); +#endif LLVivoxVoiceClient::getInstance()->setVoiceVolume(volume); } void LLVoiceClient::setMicGain(F32 gain) { +#if !__FreeBSD__ LLWebRTCVoiceClient::getInstance()->setMicGain(gain); +#endif LLVivoxVoiceClient::getInstance()->setMicGain(gain); } @@ -608,7 +679,9 @@ bool LLVoiceClient::voiceEnabled() void LLVoiceClient::setVoiceEnabled(bool enabled) { +#if !__FreeBSD__ LLWebRTCVoiceClient::getInstance()->setVoiceEnabled(enabled); +#endif LLVivoxVoiceClient::getInstance()->setVoiceEnabled(enabled); } @@ -628,7 +701,9 @@ void LLVoiceClient::updateMicMuteLogic() // Either of these always overrides any other PTT setting. new_mic_mute = true; } +#if !__FreeBSD__ LLWebRTCVoiceClient::getInstance()->setMuteMic(new_mic_mute); +#endif LLVivoxVoiceClient::getInstance()->setMuteMic(new_mic_mute); } @@ -723,18 +798,26 @@ bool LLVoiceClient::getVoiceEnabled(const LLUUID& id) const std::string LLVoiceClient::getDisplayName(const LLUUID& id) const { +#if __FreeBSD__ + return LLVivoxVoiceClient::getInstance()->getDisplayName(id); +#else std::string result = LLWebRTCVoiceClient::getInstance()->getDisplayName(id); if (result.empty()) { result = LLVivoxVoiceClient::getInstance()->getDisplayName(id); } return result; +#endif } bool LLVoiceClient::isVoiceWorking() const { +#if __FreeBSD__ + return LLVivoxVoiceClient::getInstance()->isVoiceWorking(); +#else return LLVivoxVoiceClient::getInstance()->isVoiceWorking() || LLWebRTCVoiceClient::getInstance()->isVoiceWorking(); +#endif } bool LLVoiceClient::isParticipantAvatar(const LLUUID& id) @@ -749,7 +832,10 @@ bool LLVoiceClient::isOnlineSIP(const LLUUID& id) bool LLVoiceClient::getIsSpeaking(const LLUUID& id) { - return LLWebRTCVoiceClient::getInstance()->getIsSpeaking(id) || + return +#if !__FreeBSD__ + LLWebRTCVoiceClient::getInstance()->getIsSpeaking(id) || +#endif LLVivoxVoiceClient::getInstance()->getIsSpeaking(id); } @@ -757,14 +843,21 @@ bool LLVoiceClient::getIsModeratorMuted(const LLUUID& id) { // don't bother worrying about p2p calls, as // p2p calls don't have mute. - return LLWebRTCVoiceClient::getInstance()->getIsModeratorMuted(id) || + return +#if !__FreeBSD__ + LLWebRTCVoiceClient::getInstance()->getIsModeratorMuted(id) || +#endif LLVivoxVoiceClient::getInstance()->getIsModeratorMuted(id); } F32 LLVoiceClient::getCurrentPower(const LLUUID& id) { +#if __FreeBSD__ + return LLVivoxVoiceClient::getInstance()->getCurrentPower(id); +#else return std::fmax(LLVivoxVoiceClient::getInstance()->getCurrentPower(id), LLWebRTCVoiceClient::getInstance()->getCurrentPower(id)); +#endif } bool LLVoiceClient::getOnMuteList(const LLUUID& id) @@ -776,12 +869,18 @@ bool LLVoiceClient::getOnMuteList(const LLUUID& id) F32 LLVoiceClient::getUserVolume(const LLUUID& id) { +#if __FreeBSD__ + return LLVivoxVoiceClient::getInstance()->getUserVolume(id); +#else return std::fmax(LLVivoxVoiceClient::getInstance()->getUserVolume(id), LLWebRTCVoiceClient::getInstance()->getUserVolume(id)); +#endif } void LLVoiceClient::setUserVolume(const LLUUID& id, F32 volume) { +#if !__FreeBSD__ LLWebRTCVoiceClient::getInstance()->setUserVolume(id, volume); +#endif LLVivoxVoiceClient::getInstance()->setUserVolume(id, volume); } @@ -791,7 +890,9 @@ void LLVoiceClient::setUserVolume(const LLUUID& id, F32 volume) void LLVoiceClient::addObserver(LLVoiceClientStatusObserver* observer) { LLVivoxVoiceClient::getInstance()->addObserver(observer); +#if !__FreeBSD__ LLWebRTCVoiceClient::getInstance()->addObserver(observer); +#endif } void LLVoiceClient::removeObserver(LLVoiceClientStatusObserver* observer) @@ -800,16 +901,20 @@ void LLVoiceClient::removeObserver(LLVoiceClientStatusObserver* observer) { LLVivoxVoiceClient::getInstance()->removeObserver(observer); } +#if !__FreeBSD__ if (LLWebRTCVoiceClient::instanceExists()) { LLWebRTCVoiceClient::getInstance()->removeObserver(observer); } +#endif } void LLVoiceClient::addObserver(LLFriendObserver* observer) { LLVivoxVoiceClient::getInstance()->addObserver(observer); +#if !__FreeBSD__ LLWebRTCVoiceClient::getInstance()->addObserver(observer); +#endif } void LLVoiceClient::removeObserver(LLFriendObserver* observer) @@ -818,16 +923,20 @@ void LLVoiceClient::removeObserver(LLFriendObserver* observer) { LLVivoxVoiceClient::getInstance()->removeObserver(observer); } +#if !__FreeBSD__ if (LLWebRTCVoiceClient::instanceExists()) { LLWebRTCVoiceClient::getInstance()->removeObserver(observer); } +#endif } void LLVoiceClient::addObserver(LLVoiceClientParticipantObserver* observer) { LLVivoxVoiceClient::getInstance()->addObserver(observer); +#if !__FreeBSD__ LLWebRTCVoiceClient::getInstance()->addObserver(observer); +#endif } void LLVoiceClient::removeObserver(LLVoiceClientParticipantObserver* observer) @@ -836,10 +945,12 @@ void LLVoiceClient::removeObserver(LLVoiceClientParticipantObserver* observer) { LLVivoxVoiceClient::getInstance()->removeObserver(observer); } +#if !__FreeBSD__ if (LLWebRTCVoiceClient::instanceExists()) { LLWebRTCVoiceClient::getInstance()->removeObserver(observer); } +#endif } std::string LLVoiceClient::sipURIFromID(const LLUUID &id) const @@ -902,10 +1013,12 @@ class LLViewerRequiredVoiceVersion : public LLHTTPNode { voiceModule = (LLVoiceModuleInterface *) LLVivoxVoiceClient::getInstance(); } +#if !__FreeBSD__ else if (voice_server_type == "webrtc") { voiceModule = (LLVoiceModuleInterface *) LLWebRTCVoiceClient::getInstance(); } +#endif else { LL_WARNS("Voice") << "Unknown voice server type " << voice_server_type << LL_ENDL; diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp index a489f96fe7..90f0f2eba9 100644 --- a/indra/newview/llvoicevivox.cpp +++ b/indra/newview/llvoicevivox.cpp @@ -940,7 +940,7 @@ bool LLVivoxVoiceClient::startAndLaunchDaemon() gDirUtilp->append(exe_path, "SLVoice"); #else std::string exe_path = gDirUtilp->getExecutableDir(); - gDirUtilp->append(exe_path, "SLVoice"); + gDirUtilp->append(exe_path, "SLVoice.exe"); #endif // See if the vivox executable exists llstat s; @@ -948,7 +948,16 @@ bool LLVivoxVoiceClient::startAndLaunchDaemon() { // vivox executable exists. Build the command line and launch the daemon. LLProcess::Params params; +#if LL_LINUX || __FreeBSD__ +#if __FreeBSD__ + params.envs.add("WINEARCH=win32"); + params.envs.add("WINEPREFIX=~/.i386-wine-pkg"); +#endif // __FreeBSD__ + params.executable = "wine"; + params.args.add(exe_path); +#else params.executable = exe_path; +#endif // LL_LINUX || __FreeBSD__ // VOICE-88: Cycle through [portbase..portbase+portrange) on // successive tries because attempting to relaunch (after manually @@ -1014,6 +1023,7 @@ bool LLVivoxVoiceClient::startAndLaunchDaemon() std::string old_log = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "SLVoice.old"); if (gDirUtilp->fileExists(new_log)) { + LLFile::remove(old_log, ENOENT); LLFile::rename(new_log, old_log); } diff --git a/indra/newview/llvoicevivox.h b/indra/newview/llvoicevivox.h index 7862e492b2..f94da7bd7a 100644 --- a/indra/newview/llvoicevivox.h +++ b/indra/newview/llvoicevivox.h @@ -39,6 +39,8 @@ class LLVivoxProtocolParser; #include "llcallingcard.h" // for LLFriendObserver #include "lleventcoro.h" #include "llcoros.h" +#include "llparcel.h" +#include "llmutelist.h" #include <queue> #ifdef LL_USESYSTEMLIBS diff --git a/indra/newview/llvoicewebrtc.cpp b/indra/newview/llvoicewebrtc.cpp index 4c3ab11623..2b22aa12d6 100644 --- a/indra/newview/llvoicewebrtc.cpp +++ b/indra/newview/llvoicewebrtc.cpp @@ -24,7 +24,9 @@ * $/LicenseInfo$ */ #include <algorithm> +#if !LL_LINUX #include <format> +#endif #include "llvoicewebrtc.h" #include "llsdutil.h" diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 2f03531f1d..0804f8f3c0 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -5824,8 +5824,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) { type = LLDrawPool::POOL_GLTF_PBR; } - else - if (type != LLDrawPool::POOL_ALPHA && force_simple) + else if (type != LLDrawPool::POOL_ALPHA && force_simple) { type = LLDrawPool::POOL_SIMPLE; } diff --git a/indra/newview/llworldmipmap.cpp b/indra/newview/llworldmipmap.cpp index e226fd4748..5555072e10 100644 --- a/indra/newview/llworldmipmap.cpp +++ b/indra/newview/llworldmipmap.cpp @@ -148,6 +148,11 @@ LLPointer<LLViewerFetchedTexture> LLWorldMipmap::getObjectsTile(U32 grid_x, U32 { // Load it LLPointer<LLViewerFetchedTexture> img = loadObjectsTile(grid_x, grid_y, level); + if(img == nullptr) + { + LL_ERRS() << "loadObjectsTile() failed" << LL_ENDL; + return NULL; + } // Insert the image in the map level_mipmap.insert(sublevel_tiles_t::value_type( handle, img )); // Find the element again in the map (it's there now...) @@ -162,6 +167,12 @@ LLPointer<LLViewerFetchedTexture> LLWorldMipmap::getObjectsTile(U32 grid_x, U32 // Get the image pointer and check if this asset is missing LLPointer<LLViewerFetchedTexture> img = found->second; + if(img == nullptr) + { + LL_ERRS() << "img is NULL" << LL_ENDL; + return NULL; + } + if (img->isMissingAsset()) { // Return NULL if asset missing @@ -190,6 +201,12 @@ LLPointer<LLViewerFetchedTexture> LLWorldMipmap::loadObjectsTile(U32 grid_x, U32 //LL_INFOS("WorldMap") << "LLWorldMipmap::loadObjectsTile(), URL = " << imageurl << LL_ENDL; LLPointer<LLViewerFetchedTexture> img = LLViewerTextureManager::getFetchedTextureFromUrl(imageurl, FTT_MAP_TILE, true, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); + + if(img == nullptr) + { + LL_ERRS() << "fetching map tile FAILED from " << imageurl << LL_ENDL; + return nullptr; + } LL_INFOS("MAPURL") << "fetching map tile from " << imageurl << LL_ENDL; img->setBoostLevel(LLGLTexture::BOOST_MAP); diff --git a/indra/newview/llxmlrpctransaction.cpp b/indra/newview/llxmlrpctransaction.cpp index ec6e22cd7a..1d8253830b 100644 --- a/indra/newview/llxmlrpctransaction.cpp +++ b/indra/newview/llxmlrpctransaction.cpp @@ -384,7 +384,7 @@ void LLXMLRPCTransaction::Impl::init(XMLRPC_REQUEST request, bool useGzip, const mCertStore = gSavedSettings.getString("CertStore"); httpOpts->setSSLVerifyPeer( vefifySSLCert ); - httpOpts->setSSLVerifyHost( vefifySSLCert ? 2 : 0); + httpOpts->setSSLVerifyHost( vefifySSLCert ); // LLRefCounted starts with a 1 ref, so don't add a ref in the smart pointer httpHeaders = LLCore::HttpHeaders::ptr_t(new LLCore::HttpHeaders()); diff --git a/indra/newview/mpfloatertuning.cpp b/indra/newview/mpfloatertuning.cpp new file mode 100644 index 0000000000..bfa96a8764 --- /dev/null +++ b/indra/newview/mpfloatertuning.cpp @@ -0,0 +1,97 @@ +/** +* @file mpfloatertuning.cpp +* @brief Controller for viewer tuning +* @author observeur@megapahit.net +* +* $LicenseInfo:firstyear=2014&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2014, 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 "mpfloatertuning.h" +#include "llsliderctrl.h" +#include "llcheckboxctrl.h" +#include "llcombobox.h" +#include "llviewercontrol.h" +#include "llsdserialize.h" + +#include "../llrender/llvertexbuffer.cpp" + +MPFloaterTuning::MPFloaterTuning(const LLSD& key) : LLFloater(key) +{ +} + +void MPFloaterTuning::syncFromPreferenceSetting(void *user_data) +{ + MPFloaterTuning *self = static_cast<MPFloaterTuning*>(user_data); + + U32 fps = gSavedSettings.getU32("MaxFPS"); + LLSliderCtrl* fpsSliderCtrl = self->getChild<LLSliderCtrl>("fpsSlider"); + fpsSliderCtrl->setValue(fps,FALSE); + + U32 optBuf = gSavedSettings.getU32("MPVBufferOptiMode"); + + if(optBuf == 0) + { + if(gGLManager.mIsApple) optBuf = 2; + else optBuf = 1; + } + + LLComboBox * optBufCtrl = self->getChild<LLComboBox>("MPVBuffModeComboBox"); + optBufCtrl->setCurrentByIndex(optBuf-1); + + LL_INFOS() << "syncFromPreferenceSetting optBuf=" << optBuf << LL_ENDL; +} + +bool MPFloaterTuning::postBuild() +{ + LLSliderCtrl* fpsSliderCtrl = getChild<LLSliderCtrl>("fpsSlider"); + fpsSliderCtrl->setMinValue(0); + fpsSliderCtrl->setMaxValue(165); + fpsSliderCtrl->setSliderMouseUpCallback(boost::bind(&MPFloaterTuning::onFinalCommit,this)); + + LLComboBox* optBufCtrl = getChild<LLComboBox>("MPVBuffModeComboBox"); + optBufCtrl->setCommitCallback(boost::bind(&MPFloaterTuning::onFinalCommit,this)); + + syncFromPreferenceSetting(this); + + return TRUE; +} + +// Do send-to-the-server work when slider drag completes, or new +// value entered as text. +void MPFloaterTuning::onFinalCommit() +{ + LLSliderCtrl* fpsSliderCtrl = getChild<LLSliderCtrl>("fpsSlider"); + U32 fps = (U32)fpsSliderCtrl->getValueF32(); + gSavedSettings.setU32("MaxFPS",fps); + + LLComboBox* optBufCtrl = getChild<LLComboBox>("MPVBuffModeComboBox"); + S16 optBuf = optBufCtrl->getCurrentIndex() + 1; + gSavedSettings.setU32("MPVBufferOptiMode",optBuf); + + //LLVertexBuffer::sMappingMode = optBuf; +} + +void MPFloaterTuning::onClose(bool app_quitting) +{ +} diff --git a/indra/newview/mpfloatertuning.h b/indra/newview/mpfloatertuning.h new file mode 100644 index 0000000000..9e9c7f174f --- /dev/null +++ b/indra/newview/mpfloatertuning.h @@ -0,0 +1,48 @@ +/** +* @file mpfloatertuning.h +* @brief Controller for viewer tuning +* @author observeur@megapahit.net +* +* $LicenseInfo:firstyear=2014&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2014, 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_MPFLOATERTUNING_H +#define LL_MPFLOATERTUNING_H + +#include "llfloater.h" + +class MPFloaterTuning: public LLFloater +{ +public: + MPFloaterTuning(const LLSD& key); + + bool postBuild(); + + void onFinalCommit(); + + static void syncFromPreferenceSetting(void *user_data); + + //void updateEditEnabled(); + + /*virtual*/ void onClose(bool app_quitting); +}; + +#endif diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 6c9c4751d7..5b0a73269f 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -942,7 +942,7 @@ bool LLPipeline::allocateShadowBuffer(U32 resX, U32 resY) gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_ANISOTROPIC); gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL); } } @@ -959,7 +959,7 @@ bool LLPipeline::allocateShadowBuffer(U32 resX, U32 resY) gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_ANISOTROPIC); gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL); } } @@ -3780,10 +3780,12 @@ void LLPipeline::renderGeomDeferred(LLCamera& camera, bool do_occlusion) llassert(!sRenderingHUDs); +#if GL_VERSION_1_1 if (gUseWireframe) { glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); } +#endif if (&camera == LLViewerCamera::getInstance()) { // a bit hacky, this is the start of the main render frame, figure out delta between last modelview matrix and @@ -3906,10 +3908,12 @@ void LLPipeline::renderGeomDeferred(LLCamera& camera, bool do_occlusion) } // Tracy ZoneScoped +#if GL_VERSION_1_1 if (gUseWireframe) { glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); } +#endif } void LLPipeline::renderGeomPostDeferred(LLCamera& camera) @@ -3917,10 +3921,12 @@ void LLPipeline::renderGeomPostDeferred(LLCamera& camera) LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL; LL_PROFILE_GPU_ZONE("renderGeomPostDeferred"); +#if GL_VERSION_1_1 if (gUseWireframe) { glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); } +#endif U32 cur_type = 0; @@ -4031,10 +4037,12 @@ void LLPipeline::renderGeomPostDeferred(LLCamera& camera) renderDebug(); } +#if GL_VERSION_1_1 if (gUseWireframe) { glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); } +#endif } void LLPipeline::renderGeomShadow(LLCamera& camera) @@ -4127,7 +4135,9 @@ void LLPipeline::renderPhysicsDisplay() gGL.flush(); gDebugProgram.bind(); +#if GL_VERSION_1_1 LLGLEnable(GL_POLYGON_OFFSET_LINE); +#endif glPolygonOffset(3.f, 3.f); glLineWidth(3.f); LLGLEnable blend(GL_BLEND); @@ -4143,10 +4153,12 @@ void LLPipeline::renderPhysicsDisplay() bool wireframe = (pass == 2); +#if GL_VERSION_1_1 if (wireframe) { glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); } +#endif for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); iter != LLWorld::getInstance()->getRegionList().end(); ++iter) @@ -4166,10 +4178,12 @@ void LLPipeline::renderPhysicsDisplay() } gGL.flush(); +#if GL_VERSION_1_1 if (wireframe) { glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); } +#endif } glLineWidth(1.f); gDebugProgram.unbind(); @@ -4249,7 +4263,9 @@ void LLPipeline::renderDebug() glClearColor(clearColor.mV[0],clearColor.mV[1],clearColor.mV[2],0); glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); // no stencil -- deprecated | GL_STENCIL_BUFFER_BIT); gGL.setColorMask(true, false); +#if GL_VERSION_1_1 glPolygonMode( GL_FRONT_AND_BACK, GL_FILL ); +#endif } //NavMesh @@ -4279,7 +4295,9 @@ void LLPipeline::renderDebug() gPathfindingProgram.bind(); gGL.flush(); +#if GL_VERSION_1_1 glPolygonMode( GL_FRONT_AND_BACK, GL_FILL ); +#endif glLineWidth(1.0f); gGL.flush(); } @@ -4336,7 +4354,9 @@ void LLPipeline::renderDebug() LLGLDisable cull(i >= 2 ? GL_CULL_FACE : 0); gGL.flush(); +#if GL_VERSION_1_1 glPolygonMode( GL_FRONT_AND_BACK, GL_FILL ); +#endif //get rid of some z-fighting LLGLEnable polyOffset(GL_POLYGON_OFFSET_FILL); @@ -4361,8 +4381,10 @@ void LLPipeline::renderDebug() gGL.flush(); } +#if GL_VERSION_1_1 LLGLEnable lineOffset(GL_POLYGON_OFFSET_LINE); glPolygonMode( GL_FRONT_AND_BACK, GL_LINE ); +#endif F32 offset = gSavedSettings.getF32("PathfindingLineOffset"); @@ -4382,10 +4404,14 @@ void LLPipeline::renderDebug() } else { +#if GL_VERSION_1_1 glPolygonMode( GL_FRONT_AND_BACK, GL_FILL ); +#endif gPathfindingProgram.uniform1f(sAmbiance, ambiance); llPathingLibInstance->renderNavMeshShapesVBO( render_order[i] ); +#if GL_VERSION_1_1 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); +#endif } } @@ -4402,7 +4428,9 @@ void LLPipeline::renderDebug() glLineWidth(1.f); } +#if GL_VERSION_1_1 glPolygonMode( GL_FRONT_AND_BACK, GL_FILL ); +#endif } } } @@ -4413,7 +4441,9 @@ void LLPipeline::renderDebug() { //render navmesh xray F32 ambiance = gSavedSettings.getF32("PathfindingAmbiance"); +#if GL_VERSION_1_1 LLGLEnable lineOffset(GL_POLYGON_OFFSET_LINE); +#endif LLGLEnable polyOffset(GL_POLYGON_OFFSET_FILL); F32 offset = gSavedSettings.getF32("PathfindingLineOffset"); @@ -4430,10 +4460,14 @@ void LLPipeline::renderDebug() if (gSavedSettings.getBOOL("PathfindingXRayWireframe")) { //draw hidden wireframe as darker and less opaque +#if GL_VERSION_1_1 glPolygonMode( GL_FRONT_AND_BACK, GL_LINE ); +#endif gPathfindingProgram.uniform1f(sAmbiance, 1.f); llPathingLibInstance->renderNavMesh(); +#if GL_VERSION_1_1 glPolygonMode( GL_FRONT_AND_BACK, GL_FILL ); +#endif } else { @@ -4473,7 +4507,9 @@ void LLPipeline::renderDebug() gGL.getTexUnit(0)->bind(LLViewerFetchedTexture::sWhiteImagep, true); +#if GL_VERSION_1_1 glPointSize(8.f); +#endif LLGLDepthTest depth(GL_TRUE, GL_TRUE, GL_ALWAYS); gGL.begin(LLRender::POINTS); @@ -4498,7 +4534,9 @@ void LLPipeline::renderDebug() } gGL.end(); gGL.flush(); +#if GL_VERSION_1_1 glPointSize(1.f); +#endif } // Debug stuff. @@ -4683,7 +4721,9 @@ void LLPipeline::renderDebug() { //render visible point cloud gGL.flush(); +#if GL_VERSION_1_1 glPointSize(8.f); +#endif gGL.begin(LLRender::POINTS); F32* c = col+i*4; @@ -4697,7 +4737,9 @@ void LLPipeline::renderDebug() gGL.end(); gGL.flush(); +#if GL_VERSION_1_1 glPointSize(1.f); +#endif LLVector3* ext = mShadowExtents[i]; LLVector3 pos = (ext[0]+ext[1])*0.5f; @@ -6738,7 +6780,7 @@ void apply_cube_face_rotation(U32 face) void validate_framebuffer_object() { GLenum status; - status = glCheckFramebufferStatus(GL_FRAMEBUFFER_EXT); + status = glCheckFramebufferStatus(GL_FRAMEBUFFER); switch(status) { case GL_FRAMEBUFFER_COMPLETE: diff --git a/indra/newview/secondlife.icns b/indra/newview/secondlife.icns Binary files differindex 4560d4bb24..f082c8872b 100644 --- a/indra/newview/secondlife.icns +++ b/indra/newview/secondlife.icns diff --git a/indra/newview/skins/default/colors.xml b/indra/newview/skins/default/colors.xml index 92f63a1820..1fd46fc637 100644 --- a/indra/newview/skins/default/colors.xml +++ b/indra/newview/skins/default/colors.xml @@ -4,13 +4,13 @@ <!-- Named Colors --> <color name="EmphasisColor" - value="0.38 0.694 0.573 1" /> + value="0.34 0.51 0.64 1" /> <color name="EmphasisColor_13" - value="0.38 0.694 0.573 0.13" /> + value="0.34 0.51 0.64 0.13" /> <color name="EmphasisColor_35" - value="0.38 0.694 0.573 0.35" /> + value="0.34 0.51 0.64 0.35" /> <color name="BeaconColor" value="0.749 0.298 0 1" /> @@ -70,7 +70,8 @@ value="0 0 0 0.5" /> <color name="FrogGreen" - value="0.26 0.345 0.263 1" /> + value="0.26 0.33 0.42 1" /> + <!-- ^(Not actually green) --> <color name="Red" value="1 0 0 1" /> @@ -338,7 +339,7 @@ reference="EmphasisColor" /> <color name="ConversationFriendColor" - value="0.42 0.85 0.71 1" /> + value="0.5 0.7 0.85 1" /> <color name="DefaultHighlightDark" reference="White_10" /> @@ -359,7 +360,7 @@ reference="Black" /> <color name="FilterTextColor" - value="0.38 0.69 0.57 1" /> + reference="EmphasisColor" /> <color name="FloaterButtonImageColor" reference="LtGray" /> @@ -380,7 +381,10 @@ reference="EmphasisColor" /> <color name="FolderViewLoadingMessageTextColor" - value="0.3344 0.5456 0.5159 1" /> + value="0.3344 0.545 0.645 1" /> + <color + name="FpsTextColor" + value="0.34 0.51 0.64 0.8" /> <color name="GridFocusPointColor" reference="White_50" /> @@ -407,7 +411,7 @@ value="0.43 0.06 0.06 1" /> <color name="HTMLLinkColor" - value="0.3 0.82 1 1" /> + reference="EmphasisColor" /> <color name="HealthTextColor" reference="White" /> @@ -437,7 +441,7 @@ value="1 0 1 1" /> <color name="HighlightParentColor" - value="0.67 0.83 0.96 1" /> + value="0.5 0.65 0.8 1" /> <color name="IMHistoryBgColor" reference="Unused?" /> @@ -503,10 +507,10 @@ reference="White" /> <color name="MapAvatarColor" - reference="Green" /> + reference="White" /> <color name="MapAvatarFriendColor" - reference="Yellow" /> + value="0.5 0.7 0.85 1" /> <color name="MapAvatarSelfColor" value="0.53125 0 0.498047 1" /> @@ -515,7 +519,7 @@ reference="White_10" /> <color name="MapParcelOutlineColor" - value="1 1 0 0.5" /> + value="1 1 1 0.5" /> <color name="MapTrackColor" reference="Red" /> @@ -527,7 +531,7 @@ value="0.5 0 0 1" /> <color name="MenuBarBgColor" - reference="DkGray" /> + reference="MouseGray" /> <color name="MenuBarGodBgColor" reference="FrogGreen" /> @@ -592,7 +596,7 @@ reference="White" /> <color name="NameTagFriend" - value="0.447 0.784 0.663 1" /> + value="0.5 0.7 0.85 1" /> <color name="NameTagLegacy" reference="White" /> @@ -640,7 +644,7 @@ reference="DkGray_66" /> <color name="ObjectChatColor" - reference="EmphasisColor" /> + reference="LtYellow" /> <color name="OverdrivenColor" reference="Red" /> @@ -835,10 +839,10 @@ reference="LtGray" /> <color name="UserChatColor" - reference="Yellow" /> + reference="White" /> <color name="llOwnerSayChatColor" - reference="LtYellow" /> + reference="LtOrange" /> <!-- New Colors --> <color @@ -975,10 +979,10 @@ value="1 0.14 0 1" /> <color name="OutfitGalleryItemSelected" - value="0.22 0.45 0.35 1" /> + reference="EmphasisColor_35" /> <color name="OutfitGalleryItemWorn" - value="0.33 0.58 0.47 1" /> + reference="EmphasisColor_13" /> <color name="OutfitGalleryItemUnselected" value="0.4 0.4 0.4 1" /> diff --git a/indra/newview/skins/default/textures/bottomtray/Cam_Rotate_Center.png b/indra/newview/skins/default/textures/bottomtray/Cam_Rotate_Center.png Binary files differindex ffc3c85ea2..90389734e5 100644 --- a/indra/newview/skins/default/textures/bottomtray/Cam_Rotate_Center.png +++ b/indra/newview/skins/default/textures/bottomtray/Cam_Rotate_Center.png diff --git a/indra/newview/skins/default/textures/bottomtray/Cam_Rotate_In.png b/indra/newview/skins/default/textures/bottomtray/Cam_Rotate_In.png Binary files differindex c8560c0869..a540674662 100644 --- a/indra/newview/skins/default/textures/bottomtray/Cam_Rotate_In.png +++ b/indra/newview/skins/default/textures/bottomtray/Cam_Rotate_In.png diff --git a/indra/newview/skins/default/textures/bottomtray/Cam_Tracking_Center.png b/indra/newview/skins/default/textures/bottomtray/Cam_Tracking_Center.png Binary files differindex 2812d614e6..a507127fda 100644 --- a/indra/newview/skins/default/textures/bottomtray/Cam_Tracking_Center.png +++ b/indra/newview/skins/default/textures/bottomtray/Cam_Tracking_Center.png diff --git a/indra/newview/skins/default/textures/bottomtray/Cam_Tracking_In.png b/indra/newview/skins/default/textures/bottomtray/Cam_Tracking_In.png Binary files differindex ae2c57c207..61b1085e96 100644 --- a/indra/newview/skins/default/textures/bottomtray/Cam_Tracking_In.png +++ b/indra/newview/skins/default/textures/bottomtray/Cam_Tracking_In.png diff --git a/indra/newview/skins/default/textures/bottomtray/Movement_Backward_On.png b/indra/newview/skins/default/textures/bottomtray/Movement_Backward_On.png Binary files differindex 9f31d461b5..1af8e6b956 100644 --- a/indra/newview/skins/default/textures/bottomtray/Movement_Backward_On.png +++ b/indra/newview/skins/default/textures/bottomtray/Movement_Backward_On.png diff --git a/indra/newview/skins/default/textures/bottomtray/Movement_Down_On.png b/indra/newview/skins/default/textures/bottomtray/Movement_Down_On.png Binary files differindex f7ed4c25fb..4f97611db1 100644 --- a/indra/newview/skins/default/textures/bottomtray/Movement_Down_On.png +++ b/indra/newview/skins/default/textures/bottomtray/Movement_Down_On.png diff --git a/indra/newview/skins/default/textures/bottomtray/Movement_Forward_On.png b/indra/newview/skins/default/textures/bottomtray/Movement_Forward_On.png Binary files differindex d0a825a682..f01c9f3c63 100644 --- a/indra/newview/skins/default/textures/bottomtray/Movement_Forward_On.png +++ b/indra/newview/skins/default/textures/bottomtray/Movement_Forward_On.png diff --git a/indra/newview/skins/default/textures/bottomtray/Movement_Left_On.png b/indra/newview/skins/default/textures/bottomtray/Movement_Left_On.png Binary files differindex 2f81fb1588..a120d46e99 100644 --- a/indra/newview/skins/default/textures/bottomtray/Movement_Left_On.png +++ b/indra/newview/skins/default/textures/bottomtray/Movement_Left_On.png diff --git a/indra/newview/skins/default/textures/bottomtray/Movement_Right_On.png b/indra/newview/skins/default/textures/bottomtray/Movement_Right_On.png Binary files differindex 4f86e81a15..c241ac75df 100644 --- a/indra/newview/skins/default/textures/bottomtray/Movement_Right_On.png +++ b/indra/newview/skins/default/textures/bottomtray/Movement_Right_On.png diff --git a/indra/newview/skins/default/textures/bottomtray/Movement_TurnLeft_On.png b/indra/newview/skins/default/textures/bottomtray/Movement_TurnLeft_On.png Binary files differindex b211371e64..20ce7b9296 100644 --- a/indra/newview/skins/default/textures/bottomtray/Movement_TurnLeft_On.png +++ b/indra/newview/skins/default/textures/bottomtray/Movement_TurnLeft_On.png diff --git a/indra/newview/skins/default/textures/bottomtray/Movement_TurnRight_On.png b/indra/newview/skins/default/textures/bottomtray/Movement_TurnRight_On.png Binary files differindex e937c3f012..7b3d2e8dd8 100644 --- a/indra/newview/skins/default/textures/bottomtray/Movement_TurnRight_On.png +++ b/indra/newview/skins/default/textures/bottomtray/Movement_TurnRight_On.png diff --git a/indra/newview/skins/default/textures/bottomtray/Movement_Up_On.png b/indra/newview/skins/default/textures/bottomtray/Movement_Up_On.png Binary files differindex ed4902f3ee..ecce0d0192 100644 --- a/indra/newview/skins/default/textures/bottomtray/Movement_Up_On.png +++ b/indra/newview/skins/default/textures/bottomtray/Movement_Up_On.png diff --git a/indra/newview/skins/default/textures/bottomtray/VoicePTT_Lvl1.png b/indra/newview/skins/default/textures/bottomtray/VoicePTT_Lvl1.png Binary files differindex cd18ae310d..3072512301 100644 --- a/indra/newview/skins/default/textures/bottomtray/VoicePTT_Lvl1.png +++ b/indra/newview/skins/default/textures/bottomtray/VoicePTT_Lvl1.png diff --git a/indra/newview/skins/default/textures/bottomtray/VoicePTT_Lvl2.png b/indra/newview/skins/default/textures/bottomtray/VoicePTT_Lvl2.png Binary files differindex b0ed6ee8eb..28872be28f 100644 --- a/indra/newview/skins/default/textures/bottomtray/VoicePTT_Lvl2.png +++ b/indra/newview/skins/default/textures/bottomtray/VoicePTT_Lvl2.png diff --git a/indra/newview/skins/default/textures/bottomtray/VoicePTT_On.png b/indra/newview/skins/default/textures/bottomtray/VoicePTT_On.png Binary files differindex be4881b64c..823acfc583 100644 --- a/indra/newview/skins/default/textures/bottomtray/VoicePTT_On.png +++ b/indra/newview/skins/default/textures/bottomtray/VoicePTT_On.png diff --git a/indra/newview/skins/default/textures/bottomtray/WellButton_Lit.png b/indra/newview/skins/default/textures/bottomtray/WellButton_Lit.png Binary files differindex 6cb33efb93..84711ddc29 100644 --- a/indra/newview/skins/default/textures/bottomtray/WellButton_Lit.png +++ b/indra/newview/skins/default/textures/bottomtray/WellButton_Lit.png diff --git a/indra/newview/skins/default/textures/bottomtray/WellButton_Lit_Selected.png b/indra/newview/skins/default/textures/bottomtray/WellButton_Lit_Selected.png Binary files differindex 6cb33efb93..9b9468c574 100644 --- a/indra/newview/skins/default/textures/bottomtray/WellButton_Lit_Selected.png +++ b/indra/newview/skins/default/textures/bottomtray/WellButton_Lit_Selected.png diff --git a/indra/newview/skins/default/textures/build/Object_Cone_Selected.png b/indra/newview/skins/default/textures/build/Object_Cone_Selected.png Binary files differindex d50dc69ffe..4aeb96c3ae 100644 --- a/indra/newview/skins/default/textures/build/Object_Cone_Selected.png +++ b/indra/newview/skins/default/textures/build/Object_Cone_Selected.png diff --git a/indra/newview/skins/default/textures/build/Object_Cube_Selected.png b/indra/newview/skins/default/textures/build/Object_Cube_Selected.png Binary files differindex 3d6964530d..9c9d4f506a 100644 --- a/indra/newview/skins/default/textures/build/Object_Cube_Selected.png +++ b/indra/newview/skins/default/textures/build/Object_Cube_Selected.png diff --git a/indra/newview/skins/default/textures/build/Object_Cylinder_Selected.png b/indra/newview/skins/default/textures/build/Object_Cylinder_Selected.png Binary files differindex 3ed0389961..50bd865cfc 100644 --- a/indra/newview/skins/default/textures/build/Object_Cylinder_Selected.png +++ b/indra/newview/skins/default/textures/build/Object_Cylinder_Selected.png diff --git a/indra/newview/skins/default/textures/build/Object_Grass_Selected.png b/indra/newview/skins/default/textures/build/Object_Grass_Selected.png Binary files differindex 3ebd5ea7a1..19cf732d91 100644 --- a/indra/newview/skins/default/textures/build/Object_Grass_Selected.png +++ b/indra/newview/skins/default/textures/build/Object_Grass_Selected.png diff --git a/indra/newview/skins/default/textures/build/Object_Hemi_Cone_Selected.png b/indra/newview/skins/default/textures/build/Object_Hemi_Cone_Selected.png Binary files differindex 3bdc4d1fd5..ae65f1d5e6 100644 --- a/indra/newview/skins/default/textures/build/Object_Hemi_Cone_Selected.png +++ b/indra/newview/skins/default/textures/build/Object_Hemi_Cone_Selected.png diff --git a/indra/newview/skins/default/textures/build/Object_Hemi_Cylinder_Selected.png b/indra/newview/skins/default/textures/build/Object_Hemi_Cylinder_Selected.png Binary files differindex 0912442e29..c837e953da 100644 --- a/indra/newview/skins/default/textures/build/Object_Hemi_Cylinder_Selected.png +++ b/indra/newview/skins/default/textures/build/Object_Hemi_Cylinder_Selected.png diff --git a/indra/newview/skins/default/textures/build/Object_Hemi_Sphere_Selected.png b/indra/newview/skins/default/textures/build/Object_Hemi_Sphere_Selected.png Binary files differindex 33db4a2de8..2d1e035d41 100644 --- a/indra/newview/skins/default/textures/build/Object_Hemi_Sphere_Selected.png +++ b/indra/newview/skins/default/textures/build/Object_Hemi_Sphere_Selected.png diff --git a/indra/newview/skins/default/textures/build/Object_Prism_Selected.png b/indra/newview/skins/default/textures/build/Object_Prism_Selected.png Binary files differindex 9e80fe2b84..6ec9e72c54 100644 --- a/indra/newview/skins/default/textures/build/Object_Prism_Selected.png +++ b/indra/newview/skins/default/textures/build/Object_Prism_Selected.png diff --git a/indra/newview/skins/default/textures/build/Object_Pyramid_Selected.png b/indra/newview/skins/default/textures/build/Object_Pyramid_Selected.png Binary files differindex d36bfa55d4..ffb878dc72 100644 --- a/indra/newview/skins/default/textures/build/Object_Pyramid_Selected.png +++ b/indra/newview/skins/default/textures/build/Object_Pyramid_Selected.png diff --git a/indra/newview/skins/default/textures/build/Object_Ring_Selected.png b/indra/newview/skins/default/textures/build/Object_Ring_Selected.png Binary files differindex 962f6efb93..ccc1f6d221 100644 --- a/indra/newview/skins/default/textures/build/Object_Ring_Selected.png +++ b/indra/newview/skins/default/textures/build/Object_Ring_Selected.png diff --git a/indra/newview/skins/default/textures/build/Object_Sphere_Selected.png b/indra/newview/skins/default/textures/build/Object_Sphere_Selected.png Binary files differindex 715d597144..ee015e1786 100644 --- a/indra/newview/skins/default/textures/build/Object_Sphere_Selected.png +++ b/indra/newview/skins/default/textures/build/Object_Sphere_Selected.png diff --git a/indra/newview/skins/default/textures/build/Object_Tetrahedron_Selected.png b/indra/newview/skins/default/textures/build/Object_Tetrahedron_Selected.png Binary files differindex b2ea680f23..1afb115ce5 100644 --- a/indra/newview/skins/default/textures/build/Object_Tetrahedron_Selected.png +++ b/indra/newview/skins/default/textures/build/Object_Tetrahedron_Selected.png diff --git a/indra/newview/skins/default/textures/build/Object_Torus_Selected.png b/indra/newview/skins/default/textures/build/Object_Torus_Selected.png Binary files differindex 1fc22686eb..ff1cce3a79 100644 --- a/indra/newview/skins/default/textures/build/Object_Torus_Selected.png +++ b/indra/newview/skins/default/textures/build/Object_Torus_Selected.png diff --git a/indra/newview/skins/default/textures/build/Object_Tree_Selected.png b/indra/newview/skins/default/textures/build/Object_Tree_Selected.png Binary files differindex 5bd87f8a2f..f21b0e4043 100644 --- a/indra/newview/skins/default/textures/build/Object_Tree_Selected.png +++ b/indra/newview/skins/default/textures/build/Object_Tree_Selected.png diff --git a/indra/newview/skins/default/textures/build/Object_Tube_Selected.png b/indra/newview/skins/default/textures/build/Object_Tube_Selected.png Binary files differindex a4c3f39e14..5653f06af1 100644 --- a/indra/newview/skins/default/textures/build/Object_Tube_Selected.png +++ b/indra/newview/skins/default/textures/build/Object_Tube_Selected.png diff --git a/indra/newview/skins/default/textures/containers/Accordion_Selected.png b/indra/newview/skins/default/textures/containers/Accordion_Selected.png Binary files differindex 0616dea6a3..0c193cd2b8 100644 --- a/indra/newview/skins/default/textures/containers/Accordion_Selected.png +++ b/indra/newview/skins/default/textures/containers/Accordion_Selected.png diff --git a/indra/newview/skins/default/textures/containers/TabTop_Left_Off.png b/indra/newview/skins/default/textures/containers/TabTop_Left_Off.png Binary files differindex 1951413f8d..c5b232d9ab 100644 --- a/indra/newview/skins/default/textures/containers/TabTop_Left_Off.png +++ b/indra/newview/skins/default/textures/containers/TabTop_Left_Off.png diff --git a/indra/newview/skins/default/textures/containers/TabTop_Left_Selected.png b/indra/newview/skins/default/textures/containers/TabTop_Left_Selected.png Binary files differindex 8364716e02..b075aa27cf 100644 --- a/indra/newview/skins/default/textures/containers/TabTop_Left_Selected.png +++ b/indra/newview/skins/default/textures/containers/TabTop_Left_Selected.png diff --git a/indra/newview/skins/default/textures/containers/TabTop_Middle_Off.png b/indra/newview/skins/default/textures/containers/TabTop_Middle_Off.png Binary files differindex 21f1c2d8a8..be624ab273 100644 --- a/indra/newview/skins/default/textures/containers/TabTop_Middle_Off.png +++ b/indra/newview/skins/default/textures/containers/TabTop_Middle_Off.png diff --git a/indra/newview/skins/default/textures/containers/TabTop_Middle_Selected.png b/indra/newview/skins/default/textures/containers/TabTop_Middle_Selected.png Binary files differindex 3946917c7c..446f3b7ca6 100644 --- a/indra/newview/skins/default/textures/containers/TabTop_Middle_Selected.png +++ b/indra/newview/skins/default/textures/containers/TabTop_Middle_Selected.png diff --git a/indra/newview/skins/default/textures/containers/TabTop_Right_Off.png b/indra/newview/skins/default/textures/containers/TabTop_Right_Off.png Binary files differindex eeef28e5a5..db28e9e13a 100644 --- a/indra/newview/skins/default/textures/containers/TabTop_Right_Off.png +++ b/indra/newview/skins/default/textures/containers/TabTop_Right_Off.png diff --git a/indra/newview/skins/default/textures/containers/TabTop_Right_Selected.png b/indra/newview/skins/default/textures/containers/TabTop_Right_Selected.png Binary files differindex b0f1f16398..418dc2b195 100644 --- a/indra/newview/skins/default/textures/containers/TabTop_Right_Selected.png +++ b/indra/newview/skins/default/textures/containers/TabTop_Right_Selected.png diff --git a/indra/newview/skins/default/textures/containers/Toolbar_Left_Off.png b/indra/newview/skins/default/textures/containers/Toolbar_Left_Off.png Binary files differindex 41b5d24d87..f347505772 100644 --- a/indra/newview/skins/default/textures/containers/Toolbar_Left_Off.png +++ b/indra/newview/skins/default/textures/containers/Toolbar_Left_Off.png diff --git a/indra/newview/skins/default/textures/containers/Toolbar_Left_Over.png b/indra/newview/skins/default/textures/containers/Toolbar_Left_Over.png Binary files differindex 083acc0156..fd24e5b430 100644 --- a/indra/newview/skins/default/textures/containers/Toolbar_Left_Over.png +++ b/indra/newview/skins/default/textures/containers/Toolbar_Left_Over.png diff --git a/indra/newview/skins/default/textures/containers/Toolbar_Left_Selected.png b/indra/newview/skins/default/textures/containers/Toolbar_Left_Selected.png Binary files differindex ee4649a8f9..2adf67a8a0 100644 --- a/indra/newview/skins/default/textures/containers/Toolbar_Left_Selected.png +++ b/indra/newview/skins/default/textures/containers/Toolbar_Left_Selected.png diff --git a/indra/newview/skins/default/textures/containers/Toolbar_Middle_Off.png b/indra/newview/skins/default/textures/containers/Toolbar_Middle_Off.png Binary files differindex 55c02160e3..cf30330f1c 100644 --- a/indra/newview/skins/default/textures/containers/Toolbar_Middle_Off.png +++ b/indra/newview/skins/default/textures/containers/Toolbar_Middle_Off.png diff --git a/indra/newview/skins/default/textures/containers/Toolbar_Middle_Over.png b/indra/newview/skins/default/textures/containers/Toolbar_Middle_Over.png Binary files differindex 2f6ea90196..6ac1ce3ffb 100644 --- a/indra/newview/skins/default/textures/containers/Toolbar_Middle_Over.png +++ b/indra/newview/skins/default/textures/containers/Toolbar_Middle_Over.png diff --git a/indra/newview/skins/default/textures/containers/Toolbar_Middle_Selected.png b/indra/newview/skins/default/textures/containers/Toolbar_Middle_Selected.png Binary files differindex 642113b135..1d9f2a166d 100644 --- a/indra/newview/skins/default/textures/containers/Toolbar_Middle_Selected.png +++ b/indra/newview/skins/default/textures/containers/Toolbar_Middle_Selected.png diff --git a/indra/newview/skins/default/textures/containers/Toolbar_Right_Off.png b/indra/newview/skins/default/textures/containers/Toolbar_Right_Off.png Binary files differindex 01fd765c3d..d4881e21d3 100644 --- a/indra/newview/skins/default/textures/containers/Toolbar_Right_Off.png +++ b/indra/newview/skins/default/textures/containers/Toolbar_Right_Off.png diff --git a/indra/newview/skins/default/textures/containers/Toolbar_Right_Over.png b/indra/newview/skins/default/textures/containers/Toolbar_Right_Over.png Binary files differindex 74e00635f1..bf2a72d6f4 100644 --- a/indra/newview/skins/default/textures/containers/Toolbar_Right_Over.png +++ b/indra/newview/skins/default/textures/containers/Toolbar_Right_Over.png diff --git a/indra/newview/skins/default/textures/containers/Toolbar_Right_Selected.png b/indra/newview/skins/default/textures/containers/Toolbar_Right_Selected.png Binary files differindex 8a0d98a780..d10fd495bf 100644 --- a/indra/newview/skins/default/textures/containers/Toolbar_Right_Selected.png +++ b/indra/newview/skins/default/textures/containers/Toolbar_Right_Selected.png diff --git a/indra/newview/skins/default/textures/icon_auction.tga b/indra/newview/skins/default/textures/icon_auction.tga Binary files differnew file mode 100644 index 0000000000..baf7d0d000 --- /dev/null +++ b/indra/newview/skins/default/textures/icon_auction.tga diff --git a/indra/newview/skins/default/textures/icon_group.tga b/indra/newview/skins/default/textures/icon_group.tga Binary files differnew file mode 100644 index 0000000000..79cd71689d --- /dev/null +++ b/indra/newview/skins/default/textures/icon_group.tga diff --git a/indra/newview/skins/default/textures/icon_legacy_event.tga b/indra/newview/skins/default/textures/icon_legacy_event.tga Binary files differnew file mode 100644 index 0000000000..7805dbce60 --- /dev/null +++ b/indra/newview/skins/default/textures/icon_legacy_event.tga diff --git a/indra/newview/skins/default/textures/icon_legacy_event_adult.tga b/indra/newview/skins/default/textures/icon_legacy_event_adult.tga Binary files differnew file mode 100644 index 0000000000..c344fb1e78 --- /dev/null +++ b/indra/newview/skins/default/textures/icon_legacy_event_adult.tga diff --git a/indra/newview/skins/default/textures/icon_legacy_event_mature.tga b/indra/newview/skins/default/textures/icon_legacy_event_mature.tga Binary files differnew file mode 100644 index 0000000000..61c879bc92 --- /dev/null +++ b/indra/newview/skins/default/textures/icon_legacy_event_mature.tga diff --git a/indra/newview/skins/default/textures/icon_place.tga b/indra/newview/skins/default/textures/icon_place.tga Binary files differnew file mode 100644 index 0000000000..e10655c6ec --- /dev/null +++ b/indra/newview/skins/default/textures/icon_place.tga diff --git a/indra/newview/skins/default/textures/icons/Icon_Attachment_Large.png b/indra/newview/skins/default/textures/icons/Icon_Attachment_Large.png Binary files differindex 74ec3d7e69..fb57265dac 100644 --- a/indra/newview/skins/default/textures/icons/Icon_Attachment_Large.png +++ b/indra/newview/skins/default/textures/icons/Icon_Attachment_Large.png diff --git a/indra/newview/skins/default/textures/icons/Icon_Attachment_Small.png b/indra/newview/skins/default/textures/icons/Icon_Attachment_Small.png Binary files differindex 9ea7c48871..907113cbb7 100644 --- a/indra/newview/skins/default/textures/icons/Icon_Attachment_Small.png +++ b/indra/newview/skins/default/textures/icons/Icon_Attachment_Small.png diff --git a/indra/newview/skins/default/textures/icons/Info_Over.png b/indra/newview/skins/default/textures/icons/Info_Over.png Binary files differindex 0efd596d3e..82d650ef4b 100644 --- a/indra/newview/skins/default/textures/icons/Info_Over.png +++ b/indra/newview/skins/default/textures/icons/Info_Over.png diff --git a/indra/newview/skins/default/textures/icons/Inv_Shape.png b/indra/newview/skins/default/textures/icons/Inv_Shape.png Binary files differnew file mode 100644 index 0000000000..e5db447b36 --- /dev/null +++ b/indra/newview/skins/default/textures/icons/Inv_Shape.png diff --git a/indra/newview/skins/default/textures/icons/Inv_SysClosed.png b/indra/newview/skins/default/textures/icons/Inv_SysClosed.png Binary files differindex 9af3b60cbd..2550cae0d4 100644 --- a/indra/newview/skins/default/textures/icons/Inv_SysClosed.png +++ b/indra/newview/skins/default/textures/icons/Inv_SysClosed.png diff --git a/indra/newview/skins/default/textures/icons/Inv_SysOpen.png b/indra/newview/skins/default/textures/icons/Inv_SysOpen.png Binary files differindex 01e7dbff8f..5b56d86184 100644 --- a/indra/newview/skins/default/textures/icons/Inv_SysOpen.png +++ b/indra/newview/skins/default/textures/icons/Inv_SysOpen.png diff --git a/indra/newview/skins/default/textures/icons/MP_Logo.png b/indra/newview/skins/default/textures/icons/MP_Logo.png Binary files differnew file mode 100644 index 0000000000..b01e8f4ea3 --- /dev/null +++ b/indra/newview/skins/default/textures/icons/MP_Logo.png diff --git a/indra/newview/skins/default/textures/icons/MusicNote.png b/indra/newview/skins/default/textures/icons/MusicNote.png Binary files differnew file mode 100644 index 0000000000..8d3534a94b --- /dev/null +++ b/indra/newview/skins/default/textures/icons/MusicNote.png diff --git a/indra/newview/skins/default/textures/icons/OutboxPush_Disabled.png b/indra/newview/skins/default/textures/icons/OutboxPush_Disabled.png Binary files differindex ab8983b545..1d2dbd6349 100644 --- a/indra/newview/skins/default/textures/icons/OutboxPush_Disabled.png +++ b/indra/newview/skins/default/textures/icons/OutboxPush_Disabled.png diff --git a/indra/newview/skins/default/textures/icons/OutboxPush_Off.png b/indra/newview/skins/default/textures/icons/OutboxPush_Off.png Binary files differindex 17e152a901..f8f3367c42 100644 --- a/indra/newview/skins/default/textures/icons/OutboxPush_Off.png +++ b/indra/newview/skins/default/textures/icons/OutboxPush_Off.png diff --git a/indra/newview/skins/default/textures/icons/OutboxPush_On.png b/indra/newview/skins/default/textures/icons/OutboxPush_On.png Binary files differindex 7ed854b9eb..b1fd734100 100644 --- a/indra/newview/skins/default/textures/icons/OutboxPush_On.png +++ b/indra/newview/skins/default/textures/icons/OutboxPush_On.png diff --git a/indra/newview/skins/default/textures/icons/OutboxPush_On_Over.png b/indra/newview/skins/default/textures/icons/OutboxPush_On_Over.png Binary files differindex 1b77ccdaaa..e234400b72 100644 --- a/indra/newview/skins/default/textures/icons/OutboxPush_On_Over.png +++ b/indra/newview/skins/default/textures/icons/OutboxPush_On_Over.png diff --git a/indra/newview/skins/default/textures/icons/OutboxPush_Over.png b/indra/newview/skins/default/textures/icons/OutboxPush_Over.png Binary files differindex 3d352af9a1..9e1b0e2dfc 100644 --- a/indra/newview/skins/default/textures/icons/OutboxPush_Over.png +++ b/indra/newview/skins/default/textures/icons/OutboxPush_Over.png diff --git a/indra/newview/skins/default/textures/icons/OutboxPush_Press.png b/indra/newview/skins/default/textures/icons/OutboxPush_Press.png Binary files differindex bf040e3662..14d9eacc52 100644 --- a/indra/newview/skins/default/textures/icons/OutboxPush_Press.png +++ b/indra/newview/skins/default/textures/icons/OutboxPush_Press.png diff --git a/indra/newview/skins/default/textures/icons/OutboxPush_Progress_1.png b/indra/newview/skins/default/textures/icons/OutboxPush_Progress_1.png Binary files differindex 0e1252082f..85015fc913 100644 --- a/indra/newview/skins/default/textures/icons/OutboxPush_Progress_1.png +++ b/indra/newview/skins/default/textures/icons/OutboxPush_Progress_1.png diff --git a/indra/newview/skins/default/textures/icons/OutboxPush_Progress_2.png b/indra/newview/skins/default/textures/icons/OutboxPush_Progress_2.png Binary files differindex 6684b70ca8..6158242b68 100644 --- a/indra/newview/skins/default/textures/icons/OutboxPush_Progress_2.png +++ b/indra/newview/skins/default/textures/icons/OutboxPush_Progress_2.png diff --git a/indra/newview/skins/default/textures/icons/OutboxPush_Progress_3.png b/indra/newview/skins/default/textures/icons/OutboxPush_Progress_3.png Binary files differindex b8d2a86662..7105380bff 100644 --- a/indra/newview/skins/default/textures/icons/OutboxPush_Progress_3.png +++ b/indra/newview/skins/default/textures/icons/OutboxPush_Progress_3.png diff --git a/indra/newview/skins/default/textures/icons/OutboxPush_Progress_4.png b/indra/newview/skins/default/textures/icons/OutboxPush_Progress_4.png Binary files differindex f93e844a00..0e65a60fc8 100644 --- a/indra/newview/skins/default/textures/icons/OutboxPush_Progress_4.png +++ b/indra/newview/skins/default/textures/icons/OutboxPush_Progress_4.png diff --git a/indra/newview/skins/default/textures/icons/OutboxPush_Progress_5.png b/indra/newview/skins/default/textures/icons/OutboxPush_Progress_5.png Binary files differindex 631b8475af..7acef05891 100644 --- a/indra/newview/skins/default/textures/icons/OutboxPush_Progress_5.png +++ b/indra/newview/skins/default/textures/icons/OutboxPush_Progress_5.png diff --git a/indra/newview/skins/default/textures/icons/OutboxPush_Progress_6.png b/indra/newview/skins/default/textures/icons/OutboxPush_Progress_6.png Binary files differindex 39283fa162..4f5b34a643 100644 --- a/indra/newview/skins/default/textures/icons/OutboxPush_Progress_6.png +++ b/indra/newview/skins/default/textures/icons/OutboxPush_Progress_6.png diff --git a/indra/newview/skins/default/textures/icons/OutboxPush_Selected.png b/indra/newview/skins/default/textures/icons/OutboxPush_Selected.png Binary files differindex c5576561d5..d58826da67 100644 --- a/indra/newview/skins/default/textures/icons/OutboxPush_Selected.png +++ b/indra/newview/skins/default/textures/icons/OutboxPush_Selected.png diff --git a/indra/newview/skins/default/textures/icons/OutboxPush_Selected_Disabled.png b/indra/newview/skins/default/textures/icons/OutboxPush_Selected_Disabled.png Binary files differindex 5899b766d6..cad9f118b1 100644 --- a/indra/newview/skins/default/textures/icons/OutboxPush_Selected_Disabled.png +++ b/indra/newview/skins/default/textures/icons/OutboxPush_Selected_Disabled.png diff --git a/indra/newview/skins/default/textures/icons/OutboxPush_Selected_Over.png b/indra/newview/skins/default/textures/icons/OutboxPush_Selected_Over.png Binary files differindex de290d8228..65d914c6b3 100644 --- a/indra/newview/skins/default/textures/icons/OutboxPush_Selected_Over.png +++ b/indra/newview/skins/default/textures/icons/OutboxPush_Selected_Over.png diff --git a/indra/newview/skins/default/textures/icons/OutboxPush_Selected_Press.png b/indra/newview/skins/default/textures/icons/OutboxPush_Selected_Press.png Binary files differindex 532cdff222..cd50d41903 100644 --- a/indra/newview/skins/default/textures/icons/OutboxPush_Selected_Press.png +++ b/indra/newview/skins/default/textures/icons/OutboxPush_Selected_Press.png diff --git a/indra/newview/skins/default/textures/icons/Permission_Ungranted.png b/indra/newview/skins/default/textures/icons/Permission_Ungranted.png Binary files differnew file mode 100644 index 0000000000..d206af4433 --- /dev/null +++ b/indra/newview/skins/default/textures/icons/Permission_Ungranted.png diff --git a/indra/newview/skins/default/textures/icons/ProgressLarge_1.png b/indra/newview/skins/default/textures/icons/ProgressLarge_1.png Binary files differnew file mode 100644 index 0000000000..ff277fc431 --- /dev/null +++ b/indra/newview/skins/default/textures/icons/ProgressLarge_1.png diff --git a/indra/newview/skins/default/textures/icons/ProgressLarge_10.png b/indra/newview/skins/default/textures/icons/ProgressLarge_10.png Binary files differnew file mode 100644 index 0000000000..1c94e21d89 --- /dev/null +++ b/indra/newview/skins/default/textures/icons/ProgressLarge_10.png diff --git a/indra/newview/skins/default/textures/icons/ProgressLarge_11.png b/indra/newview/skins/default/textures/icons/ProgressLarge_11.png Binary files differnew file mode 100644 index 0000000000..89bea9b474 --- /dev/null +++ b/indra/newview/skins/default/textures/icons/ProgressLarge_11.png diff --git a/indra/newview/skins/default/textures/icons/ProgressLarge_12.png b/indra/newview/skins/default/textures/icons/ProgressLarge_12.png Binary files differnew file mode 100644 index 0000000000..da38475ba4 --- /dev/null +++ b/indra/newview/skins/default/textures/icons/ProgressLarge_12.png diff --git a/indra/newview/skins/default/textures/icons/ProgressLarge_2.png b/indra/newview/skins/default/textures/icons/ProgressLarge_2.png Binary files differnew file mode 100644 index 0000000000..c024275ebe --- /dev/null +++ b/indra/newview/skins/default/textures/icons/ProgressLarge_2.png diff --git a/indra/newview/skins/default/textures/icons/ProgressLarge_3.png b/indra/newview/skins/default/textures/icons/ProgressLarge_3.png Binary files differnew file mode 100644 index 0000000000..87b931e72e --- /dev/null +++ b/indra/newview/skins/default/textures/icons/ProgressLarge_3.png diff --git a/indra/newview/skins/default/textures/icons/ProgressLarge_4.png b/indra/newview/skins/default/textures/icons/ProgressLarge_4.png Binary files differnew file mode 100644 index 0000000000..6dbef74361 --- /dev/null +++ b/indra/newview/skins/default/textures/icons/ProgressLarge_4.png diff --git a/indra/newview/skins/default/textures/icons/ProgressLarge_5.png b/indra/newview/skins/default/textures/icons/ProgressLarge_5.png Binary files differnew file mode 100644 index 0000000000..daccf9b375 --- /dev/null +++ b/indra/newview/skins/default/textures/icons/ProgressLarge_5.png diff --git a/indra/newview/skins/default/textures/icons/ProgressLarge_6.png b/indra/newview/skins/default/textures/icons/ProgressLarge_6.png Binary files differnew file mode 100644 index 0000000000..cafddcb88d --- /dev/null +++ b/indra/newview/skins/default/textures/icons/ProgressLarge_6.png diff --git a/indra/newview/skins/default/textures/icons/ProgressLarge_7.png b/indra/newview/skins/default/textures/icons/ProgressLarge_7.png Binary files differnew file mode 100644 index 0000000000..8acf6472d4 --- /dev/null +++ b/indra/newview/skins/default/textures/icons/ProgressLarge_7.png diff --git a/indra/newview/skins/default/textures/icons/ProgressLarge_8.png b/indra/newview/skins/default/textures/icons/ProgressLarge_8.png Binary files differnew file mode 100644 index 0000000000..df0e825cef --- /dev/null +++ b/indra/newview/skins/default/textures/icons/ProgressLarge_8.png diff --git a/indra/newview/skins/default/textures/icons/ProgressLarge_9.png b/indra/newview/skins/default/textures/icons/ProgressLarge_9.png Binary files differnew file mode 100644 index 0000000000..293a7b8f5c --- /dev/null +++ b/indra/newview/skins/default/textures/icons/ProgressLarge_9.png diff --git a/indra/newview/skins/default/textures/icons/SL_Logo.png b/indra/newview/skins/default/textures/icons/SL_Logo.png Binary files differindex 1eafc304f5..8234387058 100644 --- a/indra/newview/skins/default/textures/icons/SL_Logo.png +++ b/indra/newview/skins/default/textures/icons/SL_Logo.png diff --git a/indra/newview/skins/default/textures/icons/Sync_Enabled.png b/indra/newview/skins/default/textures/icons/Sync_Enabled.png Binary files differindex 43c8707995..0e7e5157cb 100644 --- a/indra/newview/skins/default/textures/icons/Sync_Enabled.png +++ b/indra/newview/skins/default/textures/icons/Sync_Enabled.png diff --git a/indra/newview/skins/default/textures/icons/VoicePTT_Lvl1.png b/indra/newview/skins/default/textures/icons/VoicePTT_Lvl1.png Binary files differindex 3ad6a5ba5b..3072512301 100644 --- a/indra/newview/skins/default/textures/icons/VoicePTT_Lvl1.png +++ b/indra/newview/skins/default/textures/icons/VoicePTT_Lvl1.png diff --git a/indra/newview/skins/default/textures/icons/VoicePTT_Lvl2.png b/indra/newview/skins/default/textures/icons/VoicePTT_Lvl2.png Binary files differindex deae5cb989..28872be28f 100644 --- a/indra/newview/skins/default/textures/icons/VoicePTT_Lvl2.png +++ b/indra/newview/skins/default/textures/icons/VoicePTT_Lvl2.png diff --git a/indra/newview/skins/default/textures/icons/VoicePTT_On.png b/indra/newview/skins/default/textures/icons/VoicePTT_On.png Binary files differindex f673671082..823acfc583 100644 --- a/indra/newview/skins/default/textures/icons/VoicePTT_On.png +++ b/indra/newview/skins/default/textures/icons/VoicePTT_On.png diff --git a/indra/newview/skins/default/textures/icons/add_icon.png b/indra/newview/skins/default/textures/icons/add_icon.png Binary files differindex daedd49933..b5b09ae6e0 100644 --- a/indra/newview/skins/default/textures/icons/add_icon.png +++ b/indra/newview/skins/default/textures/icons/add_icon.png diff --git a/indra/newview/skins/default/textures/icons/back_arrow_off.png b/indra/newview/skins/default/textures/icons/back_arrow_off.png Binary files differindex ab82dfc0a7..d0d8b31006 100644 --- a/indra/newview/skins/default/textures/icons/back_arrow_off.png +++ b/indra/newview/skins/default/textures/icons/back_arrow_off.png diff --git a/indra/newview/skins/default/textures/icons/back_arrow_over.png b/indra/newview/skins/default/textures/icons/back_arrow_over.png Binary files differindex ad8c1f8d2c..4a247e0f1f 100644 --- a/indra/newview/skins/default/textures/icons/back_arrow_over.png +++ b/indra/newview/skins/default/textures/icons/back_arrow_over.png diff --git a/indra/newview/skins/default/textures/icons/back_arrow_press.png b/indra/newview/skins/default/textures/icons/back_arrow_press.png Binary files differindex 8aecc3d876..3e9f1a6e96 100644 --- a/indra/newview/skins/default/textures/icons/back_arrow_press.png +++ b/indra/newview/skins/default/textures/icons/back_arrow_press.png diff --git a/indra/newview/skins/default/textures/icons/check_mark.png b/indra/newview/skins/default/textures/icons/check_mark.png Binary files differindex 5431dd31c8..ea59769d38 100644 --- a/indra/newview/skins/default/textures/icons/check_mark.png +++ b/indra/newview/skins/default/textures/icons/check_mark.png diff --git a/indra/newview/skins/default/textures/icons/copy_clipboard.png b/indra/newview/skins/default/textures/icons/copy_clipboard.png Binary files differindex c6f267e944..9ce67d8547 100644 --- a/indra/newview/skins/default/textures/icons/copy_clipboard.png +++ b/indra/newview/skins/default/textures/icons/copy_clipboard.png diff --git a/indra/newview/skins/default/textures/icons/delete_icon.png b/indra/newview/skins/default/textures/icons/delete_icon.png Binary files differindex 0700e52a8c..5a80155d8b 100644 --- a/indra/newview/skins/default/textures/icons/delete_icon.png +++ b/indra/newview/skins/default/textures/icons/delete_icon.png diff --git a/indra/newview/skins/default/textures/icons/file_upload.png b/indra/newview/skins/default/textures/icons/file_upload.png Binary files differindex 52f75172c1..78b75fdd72 100644 --- a/indra/newview/skins/default/textures/icons/file_upload.png +++ b/indra/newview/skins/default/textures/icons/file_upload.png diff --git a/indra/newview/skins/default/textures/icons/hand.png b/indra/newview/skins/default/textures/icons/hand.png Binary files differindex d8ef2e22fa..3f497eefbb 100644 --- a/indra/newview/skins/default/textures/icons/hand.png +++ b/indra/newview/skins/default/textures/icons/hand.png diff --git a/indra/newview/skins/default/textures/icons/multi_folder_mode.png b/indra/newview/skins/default/textures/icons/multi_folder_mode.png Binary files differindex 13762173a5..b363848aba 100644 --- a/indra/newview/skins/default/textures/icons/multi_folder_mode.png +++ b/indra/newview/skins/default/textures/icons/multi_folder_mode.png diff --git a/indra/newview/skins/default/textures/icons/paste_clipboard.png b/indra/newview/skins/default/textures/icons/paste_clipboard.png Binary files differindex 810e603ef0..ff8493d4ad 100644 --- a/indra/newview/skins/default/textures/icons/paste_clipboard.png +++ b/indra/newview/skins/default/textures/icons/paste_clipboard.png diff --git a/indra/newview/skins/default/textures/icons/profile_badge_beta.png b/indra/newview/skins/default/textures/icons/profile_badge_beta.png Binary files differindex e378eebf9a..95e277aab0 100644 --- a/indra/newview/skins/default/textures/icons/profile_badge_beta.png +++ b/indra/newview/skins/default/textures/icons/profile_badge_beta.png diff --git a/indra/newview/skins/default/textures/icons/profile_badge_beta_lifetime.png b/indra/newview/skins/default/textures/icons/profile_badge_beta_lifetime.png Binary files differindex f2fc8e0853..fb145901e2 100644 --- a/indra/newview/skins/default/textures/icons/profile_badge_beta_lifetime.png +++ b/indra/newview/skins/default/textures/icons/profile_badge_beta_lifetime.png diff --git a/indra/newview/skins/default/textures/icons/profile_badge_lifetime.png b/indra/newview/skins/default/textures/icons/profile_badge_lifetime.png Binary files differindex 85b8e688b4..3f7fd343b3 100644 --- a/indra/newview/skins/default/textures/icons/profile_badge_lifetime.png +++ b/indra/newview/skins/default/textures/icons/profile_badge_lifetime.png diff --git a/indra/newview/skins/default/textures/icons/profile_badge_linden.png b/indra/newview/skins/default/textures/icons/profile_badge_linden.png Binary files differindex 6ff3a97fdc..6ab9fcebea 100644 --- a/indra/newview/skins/default/textures/icons/profile_badge_linden.png +++ b/indra/newview/skins/default/textures/icons/profile_badge_linden.png diff --git a/indra/newview/skins/default/textures/icons/profile_badge_pplus_lifetime.png b/indra/newview/skins/default/textures/icons/profile_badge_pplus_lifetime.png Binary files differindex aebd10f4b3..5c68ad40ce 100644 --- a/indra/newview/skins/default/textures/icons/profile_badge_pplus_lifetime.png +++ b/indra/newview/skins/default/textures/icons/profile_badge_pplus_lifetime.png diff --git a/indra/newview/skins/default/textures/icons/profile_badge_premium_lifetime.png b/indra/newview/skins/default/textures/icons/profile_badge_premium_lifetime.png Binary files differindex 06669bb228..58957b7b96 100644 --- a/indra/newview/skins/default/textures/icons/profile_badge_premium_lifetime.png +++ b/indra/newview/skins/default/textures/icons/profile_badge_premium_lifetime.png diff --git a/indra/newview/skins/default/textures/icons/remove_icon.png b/indra/newview/skins/default/textures/icons/remove_icon.png Binary files differindex 0df57d6c64..d8a45cc21c 100644 --- a/indra/newview/skins/default/textures/icons/remove_icon.png +++ b/indra/newview/skins/default/textures/icons/remove_icon.png diff --git a/indra/newview/skins/default/textures/icons/see_me_online.png b/indra/newview/skins/default/textures/icons/see_me_online.png Binary files differindex 4059035b20..5684e27f43 100644 --- a/indra/newview/skins/default/textures/icons/see_me_online.png +++ b/indra/newview/skins/default/textures/icons/see_me_online.png diff --git a/indra/newview/skins/default/textures/icons/see_on_map.png b/indra/newview/skins/default/textures/icons/see_on_map.png Binary files differindex c9e8d721af..fc7057cacd 100644 --- a/indra/newview/skins/default/textures/icons/see_on_map.png +++ b/indra/newview/skins/default/textures/icons/see_on_map.png diff --git a/indra/newview/skins/default/textures/icons/see_them_on_map.png b/indra/newview/skins/default/textures/icons/see_them_on_map.png Binary files differnew file mode 100644 index 0000000000..d309980c13 --- /dev/null +++ b/indra/newview/skins/default/textures/icons/see_them_on_map.png diff --git a/indra/newview/skins/default/textures/icons/see_them_online.png b/indra/newview/skins/default/textures/icons/see_them_online.png Binary files differnew file mode 100644 index 0000000000..135e6cdd82 --- /dev/null +++ b/indra/newview/skins/default/textures/icons/see_them_online.png diff --git a/indra/newview/skins/default/textures/icons/single_folder_back.png b/indra/newview/skins/default/textures/icons/single_folder_back.png Binary files differindex 4ccea718c6..b93bb2525a 100644 --- a/indra/newview/skins/default/textures/icons/single_folder_back.png +++ b/indra/newview/skins/default/textures/icons/single_folder_back.png diff --git a/indra/newview/skins/default/textures/icons/single_folder_forward.png b/indra/newview/skins/default/textures/icons/single_folder_forward.png Binary files differindex 614ad18f48..12a21b2bba 100644 --- a/indra/newview/skins/default/textures/icons/single_folder_forward.png +++ b/indra/newview/skins/default/textures/icons/single_folder_forward.png diff --git a/indra/newview/skins/default/textures/icons/single_folder_mode.png b/indra/newview/skins/default/textures/icons/single_folder_mode.png Binary files differindex 1382e8750b..0fc8475917 100644 --- a/indra/newview/skins/default/textures/icons/single_folder_mode.png +++ b/indra/newview/skins/default/textures/icons/single_folder_mode.png diff --git a/indra/newview/skins/default/textures/icons/single_folder_up.png b/indra/newview/skins/default/textures/icons/single_folder_up.png Binary files differindex 55d55434d2..c1c8c63870 100644 --- a/indra/newview/skins/default/textures/icons/single_folder_up.png +++ b/indra/newview/skins/default/textures/icons/single_folder_up.png diff --git a/indra/newview/skins/default/textures/icons/snapshot_icon.png b/indra/newview/skins/default/textures/icons/snapshot_icon.png Binary files differindex 990a41e5b7..9b6ac6eeb0 100644 --- a/indra/newview/skins/default/textures/icons/snapshot_icon.png +++ b/indra/newview/skins/default/textures/icons/snapshot_icon.png diff --git a/indra/newview/skins/default/textures/icons/texture_icon.png b/indra/newview/skins/default/textures/icons/texture_icon.png Binary files differindex e87ba4ba99..f5c205208c 100644 --- a/indra/newview/skins/default/textures/icons/texture_icon.png +++ b/indra/newview/skins/default/textures/icons/texture_icon.png diff --git a/indra/newview/skins/default/textures/icons/thumbnail_fallback_icon.png b/indra/newview/skins/default/textures/icons/thumbnail_fallback_icon.png Binary files differindex 9199697375..19629aba04 100644 --- a/indra/newview/skins/default/textures/icons/thumbnail_fallback_icon.png +++ b/indra/newview/skins/default/textures/icons/thumbnail_fallback_icon.png diff --git a/indra/newview/skins/default/textures/megapahit/icon_group.png b/indra/newview/skins/default/textures/megapahit/icon_group.png Binary files differnew file mode 100644 index 0000000000..f3872dea3f --- /dev/null +++ b/indra/newview/skins/default/textures/megapahit/icon_group.png diff --git a/indra/newview/skins/default/textures/megapahit/icon_land_auction.png b/indra/newview/skins/default/textures/megapahit/icon_land_auction.png Binary files differnew file mode 100644 index 0000000000..550703968f --- /dev/null +++ b/indra/newview/skins/default/textures/megapahit/icon_land_auction.png diff --git a/indra/newview/skins/default/textures/megapahit/icon_land_forsale.png b/indra/newview/skins/default/textures/megapahit/icon_land_forsale.png Binary files differnew file mode 100644 index 0000000000..209bb868ea --- /dev/null +++ b/indra/newview/skins/default/textures/megapahit/icon_land_forsale.png diff --git a/indra/newview/skins/default/textures/megapahit/icon_place.png b/indra/newview/skins/default/textures/megapahit/icon_place.png Binary files differnew file mode 100644 index 0000000000..60cf42424a --- /dev/null +++ b/indra/newview/skins/default/textures/megapahit/icon_place.png diff --git a/indra/newview/skins/default/textures/model_wizard/progress_light.png b/indra/newview/skins/default/textures/model_wizard/progress_light.png Binary files differindex c8ab151c44..be6b263fb6 100644 --- a/indra/newview/skins/default/textures/model_wizard/progress_light.png +++ b/indra/newview/skins/default/textures/model_wizard/progress_light.png diff --git a/indra/newview/skins/default/textures/navbar/BuyArrow_Over.png b/indra/newview/skins/default/textures/navbar/BuyArrow_Over.png Binary files differindex 0b3f252ccf..3d9c758574 100644 --- a/indra/newview/skins/default/textures/navbar/BuyArrow_Over.png +++ b/indra/newview/skins/default/textures/navbar/BuyArrow_Over.png diff --git a/indra/newview/skins/default/textures/navbar/BuyArrow_Press.png b/indra/newview/skins/default/textures/navbar/BuyArrow_Press.png Binary files differindex 5c4c150bed..69b0d43900 100644 --- a/indra/newview/skins/default/textures/navbar/BuyArrow_Press.png +++ b/indra/newview/skins/default/textures/navbar/BuyArrow_Press.png diff --git a/indra/newview/skins/default/textures/navbar/Favorite_Star_Active.png b/indra/newview/skins/default/textures/navbar/Favorite_Star_Active.png Binary files differindex e27dbe2cad..6d42f52963 100644 --- a/indra/newview/skins/default/textures/navbar/Favorite_Star_Active.png +++ b/indra/newview/skins/default/textures/navbar/Favorite_Star_Active.png diff --git a/indra/newview/skins/default/textures/navbar/Favorite_Star_Over.png b/indra/newview/skins/default/textures/navbar/Favorite_Star_Over.png Binary files differindex 7909d54f2b..74861fdb58 100644 --- a/indra/newview/skins/default/textures/navbar/Favorite_Star_Over.png +++ b/indra/newview/skins/default/textures/navbar/Favorite_Star_Over.png diff --git a/indra/newview/skins/default/textures/navbar/NavBar_BG.png b/indra/newview/skins/default/textures/navbar/NavBar_BG.png Binary files differindex 38eea783e6..6a91700ae0 100644 --- a/indra/newview/skins/default/textures/navbar/NavBar_BG.png +++ b/indra/newview/skins/default/textures/navbar/NavBar_BG.png diff --git a/indra/newview/skins/default/textures/navbar/NavBar_BG_NoFav_Bevel.png b/indra/newview/skins/default/textures/navbar/NavBar_BG_NoFav_Bevel.png Binary files differindex a79d999932..c61dcde58c 100644 --- a/indra/newview/skins/default/textures/navbar/NavBar_BG_NoFav_Bevel.png +++ b/indra/newview/skins/default/textures/navbar/NavBar_BG_NoFav_Bevel.png diff --git a/indra/newview/skins/default/textures/navbar/NavBar_BG_NoNav_Bevel.png b/indra/newview/skins/default/textures/navbar/NavBar_BG_NoNav_Bevel.png Binary files differindex b692ed92da..9e3da34596 100644 --- a/indra/newview/skins/default/textures/navbar/NavBar_BG_NoNav_Bevel.png +++ b/indra/newview/skins/default/textures/navbar/NavBar_BG_NoNav_Bevel.png diff --git a/indra/newview/skins/default/textures/navbar/Row_Selection.png b/indra/newview/skins/default/textures/navbar/Row_Selection.png Binary files differindex fc4f0c07ef..aededa12e0 100644 --- a/indra/newview/skins/default/textures/navbar/Row_Selection.png +++ b/indra/newview/skins/default/textures/navbar/Row_Selection.png diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml index 97468c3b2e..11eafcb45d 100644 --- a/indra/newview/skins/default/textures/textures.xml +++ b/indra/newview/skins/default/textures/textures.xml @@ -87,7 +87,7 @@ with the same filename but different name <texture name="BreadCrumbBtn_Left_Off" file_name="widgets/BreadCrumbBtn_Left_Off.png" preload="false"/> <texture name="BreadCrumbBtn_Left_Over" file_name="widgets/BreadCrumbBtn_Left_Over.png" preload="false"/> <texture name="BreadCrumbBtn_Left_Press" file_name="widgets/BreadCrumbBtn_Left_Press.png" preload="false"/> - + <texture name="BreadCrumbBtn_Middle_Disabled" file_name="widgets/BreadCrumbBtn_Middle_Disabled.png" preload="false"/> <texture name="BreadCrumbBtn_Middle_Off" file_name="widgets/BreadCrumbBtn_Middle_Off.png" preload="false"/> <texture name="BreadCrumbBtn_Middle_Over" file_name="widgets/BreadCrumbBtn_Middle_Over.png" preload="false"/> @@ -192,7 +192,7 @@ with the same filename but different name <texture name="Copy" file_name="icons/Copy.png" preload="false" /> <texture name="CopyBright" file_name="icons/CopyBright.png" preload="false" /> - + <texture name="DisclosureArrow_Opened_Off" file_name="widgets/DisclosureArrow_Opened_Off.png" preload="true" /> <texture name="ChatBarHandle" file_name="bottomtray/ChatBarHandle.png" preload="false" /> @@ -244,7 +244,7 @@ with the same filename but different name <texture name="Group_Notices" file_name="icons/Group_Notices.png" preload="false" /> <texture name="Hand" file_name="icons/hand.png" preload="false" /> - + <texture name="Help_Press" file_name="navbar/Help_Press.png" preload="false" /> <texture name="Hierarchy_View_Disabled" file_name="icons/Hierarchy_View_Disabled.png" preload="false" /> @@ -257,16 +257,16 @@ with the same filename but different name <texture name="Icon_Close_Foreground" file_name="windows/Icon_Close_Foreground.png" preload="true" /> <texture name="Icon_Close_Press" file_name="windows/Icon_Close_Press.png" preload="true" /> <texture name="Icon_Close_Toast" file_name="windows/Icon_Close_Toast.png" preload="true" /> - + <texture name="Icon_Copy" file_name="icons/copy_clipboard.png" preload="true" /> - + <texture name="Icon_Delete" file_name="icons/delete_icon.png" preload="true" /> <texture name="Icon_Dock_Foreground" file_name="windows/Icon_Dock_Foreground.png" preload="true" /> <texture name="Icon_Dock_Press" file_name="windows/Icon_Dock_Press.png" preload="true" /> <texture name="Icon_File_Upload" file_name="icons/file_upload.png" preload="true" /> - + <texture name="Icon_For_Sale" file_name="icons/Icon_For_Sale.png" preload="false" /> <texture name="Icon_Gear_Background" file_name="windows/Icon_Gear_Background.png" preload="false" /> @@ -279,14 +279,14 @@ with the same filename but different name <texture name="Icon_Minimize_Foreground" file_name="windows/Icon_Minimize_Foreground.png" preload="true" /> <texture name="Icon_Minimize_Press" file_name="windows/Icon_Minimize_Press.png" preload="true" /> - + <texture name="Icon_Paste" file_name="icons/paste_clipboard.png" preload="true" /> <texture name="Icon_Restore_Foreground" file_name="windows/Icon_Restore_Foreground.png" preload="false" /> <texture name="Icon_Restore_Press" file_name="windows/Icon_Restore_Press.png" preload="false" /> <texture name="Icon_Snapshot" file_name="icons/snapshot_icon.png" preload="true" /> - + <texture name="Icon_Use_Texture" file_name="icons/texture_icon.png" preload="true" /> <texture name="Info" file_name="icons/Info.png" preload="false" /> @@ -320,7 +320,7 @@ with the same filename but different name <texture name="Inv_LostOpen" file_name="icons/Inv_LostOpen.png" preload="false" /> <texture name="Inv_Landmark" file_name="icons/Inv_Landmark.png" preload="false" /> <texture name="Inv_Material" file_name="icons/Inv_Material.png" preload="false" /> - <texture name="Inv_Mesh" file_name="icons/Inv_Mesh.png" preload="false" /> + <texture name="Inv_Mesh" file_name="icons/Inv_Mesh.png" preload="false" /> <texture name="Inv_Notecard" file_name="icons/Inv_Notecard.png" preload="false" /> <texture name="Inv_Object" file_name="icons/Inv_Object.png" preload="false" /> <texture name="Inv_Object_Multi" file_name="icons/Inv_Object_Multi.png" preload="false" /> @@ -375,7 +375,7 @@ with the same filename but different name <texture name="Locked_Icon" file_name="icons/Locked_Icon.png" preload="false" /> <texture name="Map_Placeholder_Icon" file_name="icons/map_placeholder.png" preload="true" /> - + <texture name="Marketplace_Dropzone_Background" file_name="widgets/Marketplace_Dropzone_Background.png" preload="true" /> <texture name="MarketplaceBtn_Off" file_name="widgets/MarketplaceBtn_Off.png" preload="true" scale.left="30" scale.top="19" scale.right="35" scale.bottom="4" /> <texture name="MarketplaceBtn_Selected" file_name="widgets/MarketplaceBtn_Selected.png" preload="true" scale.left="30" scale.top="19" scale.right="35" scale.bottom="4" /> @@ -391,7 +391,7 @@ with the same filename but different name <texture name="ModelImport_Status_Good" file_name="green_checkmark.png" preload="false"/> <texture name="ModelImport_Status_Warning" file_name="lag_status_warning.tga" preload="false"/> <texture name="ModelImport_Status_Error" file_name="red_x.png" preload="false"/> - + <texture name="MouseLook_View_Off" file_name="bottomtray/Mouselook_View_Off.png" preload="false" /> <texture name="MouseLook_View_On" file_name="bottomtray/Mouselook_View_On.png" preload="false" /> @@ -547,7 +547,7 @@ with the same filename but different name <texture name="Profile_Perm_Objects_Enabled" file_name="icons/Profile_Perm_Objects_Enabled.png" preload="true"/> <texture name="Profile_Perm_Online_Disabled" file_name="icons/Profile_Perm_Online_Disabled.png" preload="true"/> <texture name="Profile_Perm_Online_Enabled" file_name="icons/Profile_Perm_Online_Enabled.png" preload="true"/> - + <texture name="ProgressBar" file_name="widgets/ProgressBar.png" preload="true" scale.left="4" scale.top="11" scale.right="48" scale.bottom="3" /> <texture name="ProgressBarSolid" file_name="widgets/ProgressBarSolid.png" preload="true" scale.left="4" scale.top="11" scale.right="48" scale.bottom="3" /> <texture name="ProgressTrack" file_name="widgets/ProgressTrack.png" preload="true" scale.left="4" scale.top="13" scale.right="148" scale.bottom="2" /> @@ -642,7 +642,7 @@ with the same filename but different name <texture name="SliderThumb_Disabled" file_name="widgets/SliderThumb_Disabled.png" /> <texture name="SliderThumb_Press" file_name="widgets/SliderThumb_Press.png" /> - <texture name="SL_Logo" file_name="icons/SL_Logo.png" preload="true" /> + <texture name="SL_Logo" file_name="icons/MP_Logo.png" preload="true" /> <texture name="OBJECT_Icon" file_name="icons/object_icon.png" preload="true" /> <texture name="Unknown_Icon" file_name="icons/unknown_icon.png" preload="true" /> @@ -653,8 +653,8 @@ with the same filename but different name <texture name="Snapshot_Profile" file_name="toolbar_icons/profile.png" preload="false" /> <texture name="startup_logo" file_name="windows/startup_logo.png" preload="true" /> - <texture name="login_sl_logo" file_name="windows/login_sl_logo.png" preload="true" /> - <texture name="login_sl_logo_small" file_name="windows/login_sl_logo_small.png" preload="true" /> + <texture name="login_mp_logo" file_name="windows/login_mp_logo.png" preload="true" /> + <texture name="login_mp_logo_small" file_name="windows/login_mp_logo_small.png" preload="true" /> <texture name="first_login_image" file_name="windows/first_login_image.jpg" preload="true" /> <texture name="Stepper_Down_Off" file_name="widgets/Stepper_Down_Off.png" preload="false" /> @@ -740,7 +740,7 @@ with the same filename but different name <texture name="UpArrow_Off" file_name="icons/UpArrow_Off.png" preload="false" /> <texture name="Video_URL_Off" file_name="icons/Video_URL_Off.png" preload="true" /> - + <texture name="Vertical Drag Handle" file_name="widgets/vertical_drag_handle.png" scale.left="2" scale.right="7" scale.bottom="8" scale.top="120" scale_type="scale_outer"/> <texture name="VirtualTrackball_Moon_Back" file_name="widgets/track_control_moon_back.png" /> @@ -756,7 +756,7 @@ with the same filename but different name <texture name="VirtualTrackball_Sphere" file_name="widgets/track_control_sphere.png" /> <texture name="VirtualTrackball_Sun_Back" file_name="widgets/track_control_sun_back.png" /> <texture name="VirtualTrackball_Sun_Front" file_name="widgets/track_control_sun_front.png" /> - + <texture name="Volume_Background" file_name="windows/Volume_Background.png" preload="false" scale.left="6" scale.top="33" scale.right="63" scale.bottom="10" /> @@ -765,7 +765,7 @@ with the same filename but different name <texture name="VoicePTT_Lvl3" file_name="bottomtray/VoicePTT_Lvl3.png" preload="false" /> <texture name="VoicePTT_Off" file_name="bottomtray/VoicePTT_Off.png" preload="false" /> <texture name="VoicePTT_On" file_name="bottomtray/VoicePTT_On.png" preload="false" /> - + <texture name="Wearables_Divider" file_name="windows/Wearables_Divider.png" preload="false" /> <texture name="Add_Icon" file_name="icons/add_icon.png" preload="false" /> @@ -780,9 +780,9 @@ with the same filename but different name scale.left="4" scale.top="24" scale.right="26" scale.bottom="4" /> <texture name="Window_Foreground" file_name="windows/Window_Foreground.png" preload="true" scale.left="4" scale.top="24" scale.right="26" scale.bottom="4" /> - <texture name="Window_NoTitle_Background" file_name="windows/Window_NoTitle_Background.png" preload="true" + <texture name="Window_NoTitle_Background" file_name="windows/Window_Background.png" preload="true" scale.left="4" scale.top="24" scale.right="26" scale.bottom="4" /> - <texture name="Window_NoTitle_Foreground" file_name="windows/Window_NoTitle_Foreground.png" preload="true" + <texture name="Window_NoTitle_Foreground" file_name="windows/Window_Foreground.png" preload="true" scale.left="4" scale.top="24" scale.right="26" scale.bottom="4" /> <texture name="YouAreHere_Badge" file_name="icons/YouAreHere_Badge.png" preload="false" /> @@ -880,7 +880,7 @@ with the same filename but different name <texture name="buy_off" file_name="widgets/buy_off.png" preload="true" scale.left="2" scale.top="15" scale.right="67" scale.bottom="4"/> <texture name="buy_over" file_name="widgets/buy_over.png" preload="true" scale.left="2" scale.top="15" scale.right="67" scale.bottom="4"/> <texture name="buy_press" file_name="widgets/buy_press.png" preload="true" scale.left="2" scale.top="15" scale.right="67" scale.bottom="4"/> - + <texture name="hint_background" file_name="windows/hint_background.png" preload="false" scale.left="8" scale.top="70" scale.right="195" scale.bottom="11"/> <texture name="hint_arrow_left" file_name="windows/hint_arrow_left.png" preload="false"/> <texture name="hint_arrow_right" file_name="windows/hint_arrow_right.png" preload="false"/> @@ -896,7 +896,7 @@ with the same filename but different name <texture name="Default_Outfit_Photo" file_name="icons/Default_Outfit_Photo.png" preload="true"/> <texture name="Notification_Condense" file_name="icons/Icon_Notification_Condense.png" preload="true"/> <texture name="Notification_Expand" file_name="icons/Icon_Notification_Expand.png" preload="true"/> - <texture name="System_Notification" file_name="icons/SL_Logo.png" preload="true"/> + <texture name="System_Notification" file_name="icons/MP_Logo.png" preload="true"/> <texture name="Icon_Attachment_Small" file_name="icons/Icon_Attachment_Small.png" preload="true"/> <texture name="Icon_Attachment_Large" file_name="icons/Icon_Attachment_Large.png" preload="true"/> @@ -907,4 +907,26 @@ with the same filename but different name <texture name="Single_Folder_Up" file_name="icons/single_folder_up.png" preload="true"/> <texture name="Icon_Color_Palette" file_name="icons/Icon_Color_Palette.png" preload="false"/> <texture name="Icon_Font_Size" file_name="icons/Icon_Font_Size.png" preload="false"/> + + <texture name="Icon_Place" file_name="megapahit/icon_place.png" preload="false" /> + <texture name="Icon_Auction" file_name="megapahit/icon_land_auction.png" preload="false" /> + <texture name="Icon_For_Sale" file_name="megapahit/icon_land_forsale.png" preload="false" /> + <texture name="Icon_Group" file_name="megapahit/icon_group.png" preload="false" /> + <texture name="Icon_Legacy_Event_PG" file_name="icons/Parcel_PG_Dark.png" preload="false" /> + <texture name="Icon_Legacy_Event_Mature" file_name="icons/Parcel_M_Dark.png" preload="false" /> + <texture name="Icon_Legacy_Event_Adult" file_name="icons/Parcel_R_Dark.png" preload="false" /> + + <texture name="ProgressLarge_1" file_name="icons/ProgressLarge_1.png" preload="true" /> + <texture name="ProgressLarge_2" file_name="icons/ProgressLarge_2.png" preload="true" /> + <texture name="ProgressLarge_3" file_name="icons/ProgressLarge_3.png" preload="true" /> + <texture name="ProgressLarge_4" file_name="icons/ProgressLarge_4.png" preload="true" /> + <texture name="ProgressLarge_5" file_name="icons/ProgressLarge_5.png" preload="true" /> + <texture name="ProgressLarge_6" file_name="icons/ProgressLarge_6.png" preload="true" /> + <texture name="ProgressLarge_7" file_name="icons/ProgressLarge_7.png" preload="true" /> + <texture name="ProgressLarge_8" file_name="icons/ProgressLarge_8.png" preload="true" /> + <texture name="ProgressLarge_9" file_name="icons/ProgressLarge_9.png" preload="true" /> + <texture name="ProgressLarge_10" file_name="icons/ProgressLarge_10.png" preload="true" /> + <texture name="ProgressLarge_11" file_name="icons/ProgressLarge_11.png" preload="true" /> + <texture name="ProgressLarge_12" file_name="icons/ProgressLarge_12.png" preload="true" /> + </textures> diff --git a/indra/newview/skins/default/textures/toolbar_icons/highlighting_selected.png b/indra/newview/skins/default/textures/toolbar_icons/highlighting_selected.png Binary files differindex aa1bb26a56..bce67be463 100644 --- a/indra/newview/skins/default/textures/toolbar_icons/highlighting_selected.png +++ b/indra/newview/skins/default/textures/toolbar_icons/highlighting_selected.png diff --git a/indra/newview/skins/default/textures/toolbar_icons/twitter.png b/indra/newview/skins/default/textures/toolbar_icons/twitter.png Binary files differindex a99c490887..0ad56f7802 100644 --- a/indra/newview/skins/default/textures/toolbar_icons/twitter.png +++ b/indra/newview/skins/default/textures/toolbar_icons/twitter.png diff --git a/indra/newview/skins/default/textures/widgets/Arrow_Small_Down.png b/indra/newview/skins/default/textures/widgets/Arrow_Small_Down.png Binary files differnew file mode 100644 index 0000000000..8694cdf2d4 --- /dev/null +++ b/indra/newview/skins/default/textures/widgets/Arrow_Small_Down.png diff --git a/indra/newview/skins/default/textures/widgets/BreadCrumbBtn_Left_Off.png b/indra/newview/skins/default/textures/widgets/BreadCrumbBtn_Left_Off.png Binary files differindex 24bcfc4524..e61e7a29a1 100644 --- a/indra/newview/skins/default/textures/widgets/BreadCrumbBtn_Left_Off.png +++ b/indra/newview/skins/default/textures/widgets/BreadCrumbBtn_Left_Off.png diff --git a/indra/newview/skins/default/textures/widgets/BreadCrumbBtn_Left_Over.png b/indra/newview/skins/default/textures/widgets/BreadCrumbBtn_Left_Over.png Binary files differindex ca7ff3687a..7e278e1065 100644 --- a/indra/newview/skins/default/textures/widgets/BreadCrumbBtn_Left_Over.png +++ b/indra/newview/skins/default/textures/widgets/BreadCrumbBtn_Left_Over.png diff --git a/indra/newview/skins/default/textures/widgets/BreadCrumbBtn_Left_Press.png b/indra/newview/skins/default/textures/widgets/BreadCrumbBtn_Left_Press.png Binary files differindex 6ae73ffcdd..31038e28ae 100644 --- a/indra/newview/skins/default/textures/widgets/BreadCrumbBtn_Left_Press.png +++ b/indra/newview/skins/default/textures/widgets/BreadCrumbBtn_Left_Press.png diff --git a/indra/newview/skins/default/textures/widgets/BreadCrumbBtn_Middle_Off.png b/indra/newview/skins/default/textures/widgets/BreadCrumbBtn_Middle_Off.png Binary files differindex 0147c4b9a7..52bcf88258 100644 --- a/indra/newview/skins/default/textures/widgets/BreadCrumbBtn_Middle_Off.png +++ b/indra/newview/skins/default/textures/widgets/BreadCrumbBtn_Middle_Off.png diff --git a/indra/newview/skins/default/textures/widgets/BreadCrumbBtn_Middle_Over.png b/indra/newview/skins/default/textures/widgets/BreadCrumbBtn_Middle_Over.png Binary files differindex 497642a620..efdd13003a 100644 --- a/indra/newview/skins/default/textures/widgets/BreadCrumbBtn_Middle_Over.png +++ b/indra/newview/skins/default/textures/widgets/BreadCrumbBtn_Middle_Over.png diff --git a/indra/newview/skins/default/textures/widgets/BreadCrumbBtn_Middle_Press.png b/indra/newview/skins/default/textures/widgets/BreadCrumbBtn_Middle_Press.png Binary files differindex 7bfe8e5d8d..3c66b1f1cc 100644 --- a/indra/newview/skins/default/textures/widgets/BreadCrumbBtn_Middle_Press.png +++ b/indra/newview/skins/default/textures/widgets/BreadCrumbBtn_Middle_Press.png diff --git a/indra/newview/skins/default/textures/widgets/BreadCrumbBtn_Right_Off.png b/indra/newview/skins/default/textures/widgets/BreadCrumbBtn_Right_Off.png Binary files differindex dbf133cea6..4c433ec42a 100644 --- a/indra/newview/skins/default/textures/widgets/BreadCrumbBtn_Right_Off.png +++ b/indra/newview/skins/default/textures/widgets/BreadCrumbBtn_Right_Off.png diff --git a/indra/newview/skins/default/textures/widgets/BreadCrumbBtn_Right_Over.png b/indra/newview/skins/default/textures/widgets/BreadCrumbBtn_Right_Over.png Binary files differindex f7990c37ae..5915f34bb6 100644 --- a/indra/newview/skins/default/textures/widgets/BreadCrumbBtn_Right_Over.png +++ b/indra/newview/skins/default/textures/widgets/BreadCrumbBtn_Right_Over.png diff --git a/indra/newview/skins/default/textures/widgets/BreadCrumbBtn_Right_Press.png b/indra/newview/skins/default/textures/widgets/BreadCrumbBtn_Right_Press.png Binary files differindex 71da02ae1d..ab939cc99f 100644 --- a/indra/newview/skins/default/textures/widgets/BreadCrumbBtn_Right_Press.png +++ b/indra/newview/skins/default/textures/widgets/BreadCrumbBtn_Right_Press.png diff --git a/indra/newview/skins/default/textures/widgets/ComboButton_On.png b/indra/newview/skins/default/textures/widgets/ComboButton_On.png Binary files differindex 2739cb4684..1d1ea1bd87 100644 --- a/indra/newview/skins/default/textures/widgets/ComboButton_On.png +++ b/indra/newview/skins/default/textures/widgets/ComboButton_On.png diff --git a/indra/newview/skins/default/textures/widgets/ComboButton_Selected.png b/indra/newview/skins/default/textures/widgets/ComboButton_Selected.png Binary files differindex 1a834bfbbc..d87e46aba7 100644 --- a/indra/newview/skins/default/textures/widgets/ComboButton_Selected.png +++ b/indra/newview/skins/default/textures/widgets/ComboButton_Selected.png diff --git a/indra/newview/skins/default/textures/widgets/ComboButton_UpSelected.png b/indra/newview/skins/default/textures/widgets/ComboButton_UpSelected.png Binary files differindex ff56367147..34b0c70cb0 100644 --- a/indra/newview/skins/default/textures/widgets/ComboButton_UpSelected.png +++ b/indra/newview/skins/default/textures/widgets/ComboButton_UpSelected.png diff --git a/indra/newview/skins/default/textures/widgets/DropDown_On.png b/indra/newview/skins/default/textures/widgets/DropDown_On.png Binary files differindex 613a8c2ff6..4a3c8c8e3a 100644 --- a/indra/newview/skins/default/textures/widgets/DropDown_On.png +++ b/indra/newview/skins/default/textures/widgets/DropDown_On.png diff --git a/indra/newview/skins/default/textures/widgets/DropDown_Press.png b/indra/newview/skins/default/textures/widgets/DropDown_Press.png Binary files differindex fa3a152df1..9d09871e58 100644 --- a/indra/newview/skins/default/textures/widgets/DropDown_Press.png +++ b/indra/newview/skins/default/textures/widgets/DropDown_Press.png diff --git a/indra/newview/skins/default/textures/widgets/Linden_Dollar_Background.png b/indra/newview/skins/default/textures/widgets/Linden_Dollar_Background.png Binary files differindex ba4ab2d0c9..6e71ef7b72 100644 --- a/indra/newview/skins/default/textures/widgets/Linden_Dollar_Background.png +++ b/indra/newview/skins/default/textures/widgets/Linden_Dollar_Background.png diff --git a/indra/newview/skins/default/textures/widgets/ListItem_Over.png b/indra/newview/skins/default/textures/widgets/ListItem_Over.png Binary files differindex e72c1c4020..0ec8de776e 100644 --- a/indra/newview/skins/default/textures/widgets/ListItem_Over.png +++ b/indra/newview/skins/default/textures/widgets/ListItem_Over.png diff --git a/indra/newview/skins/default/textures/widgets/ListItem_Select.png b/indra/newview/skins/default/textures/widgets/ListItem_Select.png Binary files differindex 0e16a8b454..6dd7b3c638 100644 --- a/indra/newview/skins/default/textures/widgets/ListItem_Select.png +++ b/indra/newview/skins/default/textures/widgets/ListItem_Select.png diff --git a/indra/newview/skins/default/textures/widgets/MarketplaceBtn_Selected.png b/indra/newview/skins/default/textures/widgets/MarketplaceBtn_Selected.png Binary files differindex 8bfa3acb42..d76d1246fb 100644 --- a/indra/newview/skins/default/textures/widgets/MarketplaceBtn_Selected.png +++ b/indra/newview/skins/default/textures/widgets/MarketplaceBtn_Selected.png diff --git a/indra/newview/skins/default/textures/widgets/ProgressBar.png b/indra/newview/skins/default/textures/widgets/ProgressBar.png Binary files differindex 4d0d123987..492d9b6fc4 100644 --- a/indra/newview/skins/default/textures/widgets/ProgressBar.png +++ b/indra/newview/skins/default/textures/widgets/ProgressBar.png diff --git a/indra/newview/skins/default/textures/widgets/PushButton_Off.png b/indra/newview/skins/default/textures/widgets/PushButton_Off.png Binary files differindex 29eeed7c78..c74cea62d3 100644 --- a/indra/newview/skins/default/textures/widgets/PushButton_Off.png +++ b/indra/newview/skins/default/textures/widgets/PushButton_Off.png diff --git a/indra/newview/skins/default/textures/widgets/PushButton_On.png b/indra/newview/skins/default/textures/widgets/PushButton_On.png Binary files differindex 65d92a9d82..af65a960b6 100644 --- a/indra/newview/skins/default/textures/widgets/PushButton_On.png +++ b/indra/newview/skins/default/textures/widgets/PushButton_On.png diff --git a/indra/newview/skins/default/textures/widgets/PushButton_On_Selected.png b/indra/newview/skins/default/textures/widgets/PushButton_On_Selected.png Binary files differindex 8588576fb0..2e9097a7dc 100644 --- a/indra/newview/skins/default/textures/widgets/PushButton_On_Selected.png +++ b/indra/newview/skins/default/textures/widgets/PushButton_On_Selected.png diff --git a/indra/newview/skins/default/textures/widgets/PushButton_Over.png b/indra/newview/skins/default/textures/widgets/PushButton_Over.png Binary files differindex 819f27c0ba..34a64a3ade 100644 --- a/indra/newview/skins/default/textures/widgets/PushButton_Over.png +++ b/indra/newview/skins/default/textures/widgets/PushButton_Over.png diff --git a/indra/newview/skins/default/textures/widgets/PushButton_Press.png b/indra/newview/skins/default/textures/widgets/PushButton_Press.png Binary files differindex b0a92d8ffe..4591305bff 100644 --- a/indra/newview/skins/default/textures/widgets/PushButton_Press.png +++ b/indra/newview/skins/default/textures/widgets/PushButton_Press.png diff --git a/indra/newview/skins/default/textures/widgets/PushButton_Selected.png b/indra/newview/skins/default/textures/widgets/PushButton_Selected.png Binary files differindex b0a92d8ffe..aa949c65cb 100644 --- a/indra/newview/skins/default/textures/widgets/PushButton_Selected.png +++ b/indra/newview/skins/default/textures/widgets/PushButton_Selected.png diff --git a/indra/newview/skins/default/textures/widgets/PushButton_Selected_Disabled.png b/indra/newview/skins/default/textures/widgets/PushButton_Selected_Disabled.png Binary files differindex 65d92a9d82..0b306d8816 100644 --- a/indra/newview/skins/default/textures/widgets/PushButton_Selected_Disabled.png +++ b/indra/newview/skins/default/textures/widgets/PushButton_Selected_Disabled.png diff --git a/indra/newview/skins/default/textures/widgets/PushButton_Selected_Press.png b/indra/newview/skins/default/textures/widgets/PushButton_Selected_Press.png Binary files differindex 8588576fb0..ca9870d078 100644 --- a/indra/newview/skins/default/textures/widgets/PushButton_Selected_Press.png +++ b/indra/newview/skins/default/textures/widgets/PushButton_Selected_Press.png diff --git a/indra/newview/skins/default/textures/widgets/SegmentedBtn_Left_Selected_Disabled.png b/indra/newview/skins/default/textures/widgets/SegmentedBtn_Left_Selected_Disabled.png Binary files differindex 300a7d73cd..7146900b30 100644 --- a/indra/newview/skins/default/textures/widgets/SegmentedBtn_Left_Selected_Disabled.png +++ b/indra/newview/skins/default/textures/widgets/SegmentedBtn_Left_Selected_Disabled.png diff --git a/indra/newview/skins/default/textures/widgets/SegmentedBtn_Left_Selected_Over.png b/indra/newview/skins/default/textures/widgets/SegmentedBtn_Left_Selected_Over.png Binary files differindex c7ee699210..8fffd72633 100644 --- a/indra/newview/skins/default/textures/widgets/SegmentedBtn_Left_Selected_Over.png +++ b/indra/newview/skins/default/textures/widgets/SegmentedBtn_Left_Selected_Over.png diff --git a/indra/newview/skins/default/textures/widgets/SegmentedBtn_Left_Selected_Press.png b/indra/newview/skins/default/textures/widgets/SegmentedBtn_Left_Selected_Press.png Binary files differindex f9cb95ff4b..5e8f0d12b4 100644 --- a/indra/newview/skins/default/textures/widgets/SegmentedBtn_Left_Selected_Press.png +++ b/indra/newview/skins/default/textures/widgets/SegmentedBtn_Left_Selected_Press.png diff --git a/indra/newview/skins/default/textures/widgets/SegmentedBtn_Middle_Selected_Disabled.png b/indra/newview/skins/default/textures/widgets/SegmentedBtn_Middle_Selected_Disabled.png Binary files differindex 6223ad8dfe..09d10e6feb 100644 --- a/indra/newview/skins/default/textures/widgets/SegmentedBtn_Middle_Selected_Disabled.png +++ b/indra/newview/skins/default/textures/widgets/SegmentedBtn_Middle_Selected_Disabled.png diff --git a/indra/newview/skins/default/textures/widgets/SegmentedBtn_Middle_Selected_Press.png b/indra/newview/skins/default/textures/widgets/SegmentedBtn_Middle_Selected_Press.png Binary files differindex 101d5a0930..cdc4abb15c 100644 --- a/indra/newview/skins/default/textures/widgets/SegmentedBtn_Middle_Selected_Press.png +++ b/indra/newview/skins/default/textures/widgets/SegmentedBtn_Middle_Selected_Press.png diff --git a/indra/newview/skins/default/textures/widgets/SegmentedBtn_Right_On_Selected.png b/indra/newview/skins/default/textures/widgets/SegmentedBtn_Right_On_Selected.png Binary files differindex fd1dd4207c..cee5d77931 100644 --- a/indra/newview/skins/default/textures/widgets/SegmentedBtn_Right_On_Selected.png +++ b/indra/newview/skins/default/textures/widgets/SegmentedBtn_Right_On_Selected.png diff --git a/indra/newview/skins/default/textures/widgets/SegmentedBtn_Right_Selected_Disabled.png b/indra/newview/skins/default/textures/widgets/SegmentedBtn_Right_Selected_Disabled.png Binary files differindex fdf09e920d..237503fe32 100644 --- a/indra/newview/skins/default/textures/widgets/SegmentedBtn_Right_Selected_Disabled.png +++ b/indra/newview/skins/default/textures/widgets/SegmentedBtn_Right_Selected_Disabled.png diff --git a/indra/newview/skins/default/textures/widgets/SegmentedBtn_Right_Selected_Press.png b/indra/newview/skins/default/textures/widgets/SegmentedBtn_Right_Selected_Press.png Binary files differindex 144d23cc6c..de081c2a4f 100644 --- a/indra/newview/skins/default/textures/widgets/SegmentedBtn_Right_Selected_Press.png +++ b/indra/newview/skins/default/textures/widgets/SegmentedBtn_Right_Selected_Press.png diff --git a/indra/newview/skins/default/textures/widgets/Stepper_Down_Off.png b/indra/newview/skins/default/textures/widgets/Stepper_Down_Off.png Binary files differindex 51d269bd45..ff21034095 100644 --- a/indra/newview/skins/default/textures/widgets/Stepper_Down_Off.png +++ b/indra/newview/skins/default/textures/widgets/Stepper_Down_Off.png diff --git a/indra/newview/skins/default/textures/widgets/Stepper_Down_Press.png b/indra/newview/skins/default/textures/widgets/Stepper_Down_Press.png Binary files differindex b4f19b7dbb..7349132503 100644 --- a/indra/newview/skins/default/textures/widgets/Stepper_Down_Press.png +++ b/indra/newview/skins/default/textures/widgets/Stepper_Down_Press.png diff --git a/indra/newview/skins/default/textures/widgets/Stepper_Up_Off.png b/indra/newview/skins/default/textures/widgets/Stepper_Up_Off.png Binary files differindex a01d928aef..133845bdbc 100644 --- a/indra/newview/skins/default/textures/widgets/Stepper_Up_Off.png +++ b/indra/newview/skins/default/textures/widgets/Stepper_Up_Off.png diff --git a/indra/newview/skins/default/textures/widgets/Stepper_Up_Press.png b/indra/newview/skins/default/textures/widgets/Stepper_Up_Press.png Binary files differindex d5b672d943..3dce7733c2 100644 --- a/indra/newview/skins/default/textures/widgets/Stepper_Up_Press.png +++ b/indra/newview/skins/default/textures/widgets/Stepper_Up_Press.png diff --git a/indra/newview/skins/default/textures/widgets/TextField_Active.png b/indra/newview/skins/default/textures/widgets/TextField_Active.png Binary files differindex 9eb5b6a36e..66c3867b81 100644 --- a/indra/newview/skins/default/textures/widgets/TextField_Active.png +++ b/indra/newview/skins/default/textures/widgets/TextField_Active.png diff --git a/indra/newview/skins/default/textures/widgets/TextField_Disabled.png b/indra/newview/skins/default/textures/widgets/TextField_Disabled.png Binary files differindex 3b1ac6b9ed..baf747f581 100644 --- a/indra/newview/skins/default/textures/widgets/TextField_Disabled.png +++ b/indra/newview/skins/default/textures/widgets/TextField_Disabled.png diff --git a/indra/newview/skins/default/textures/widgets/TextField_Off.png b/indra/newview/skins/default/textures/widgets/TextField_Off.png Binary files differindex afe091d613..a35562f950 100644 --- a/indra/newview/skins/default/textures/widgets/TextField_Off.png +++ b/indra/newview/skins/default/textures/widgets/TextField_Off.png diff --git a/indra/newview/skins/default/textures/widgets/buy_off.png b/indra/newview/skins/default/textures/widgets/buy_off.png Binary files differindex 7af02357ac..f623b501e2 100644 --- a/indra/newview/skins/default/textures/widgets/buy_off.png +++ b/indra/newview/skins/default/textures/widgets/buy_off.png diff --git a/indra/newview/skins/default/textures/widgets/buy_over.png b/indra/newview/skins/default/textures/widgets/buy_over.png Binary files differindex 5dafd9f47e..25d4173242 100644 --- a/indra/newview/skins/default/textures/widgets/buy_over.png +++ b/indra/newview/skins/default/textures/widgets/buy_over.png diff --git a/indra/newview/skins/default/textures/widgets/buy_press.png b/indra/newview/skins/default/textures/widgets/buy_press.png Binary files differindex 83db005fd7..3195431c84 100644 --- a/indra/newview/skins/default/textures/widgets/buy_press.png +++ b/indra/newview/skins/default/textures/widgets/buy_press.png diff --git a/indra/newview/skins/default/textures/widgets/track_control_sphere.png b/indra/newview/skins/default/textures/widgets/track_control_sphere.png Binary files differindex 60a81d1fea..6ba8d3877f 100644 --- a/indra/newview/skins/default/textures/widgets/track_control_sphere.png +++ b/indra/newview/skins/default/textures/widgets/track_control_sphere.png diff --git a/indra/newview/skins/default/textures/windows/Inspector_I.png b/indra/newview/skins/default/textures/windows/Inspector_I.png Binary files differindex 843f6e9fbe..82d650ef4b 100644 --- a/indra/newview/skins/default/textures/windows/Inspector_I.png +++ b/indra/newview/skins/default/textures/windows/Inspector_I.png diff --git a/indra/newview/skins/default/textures/windows/Resize_Corner.png b/indra/newview/skins/default/textures/windows/Resize_Corner.png Binary files differindex f52b7ced4a..8cdcc1f99d 100644 --- a/indra/newview/skins/default/textures/windows/Resize_Corner.png +++ b/indra/newview/skins/default/textures/windows/Resize_Corner.png diff --git a/indra/newview/skins/default/textures/windows/Window_Background.png b/indra/newview/skins/default/textures/windows/Window_Background.png Binary files differindex 9864ec0db8..f19fb0300b 100644 --- a/indra/newview/skins/default/textures/windows/Window_Background.png +++ b/indra/newview/skins/default/textures/windows/Window_Background.png diff --git a/indra/newview/skins/default/textures/windows/Window_Foreground.png b/indra/newview/skins/default/textures/windows/Window_Foreground.png Binary files differindex a86b236504..15d2ff72b6 100644 --- a/indra/newview/skins/default/textures/windows/Window_Foreground.png +++ b/indra/newview/skins/default/textures/windows/Window_Foreground.png diff --git a/indra/newview/skins/default/textures/windows/add_payment_image_center.png b/indra/newview/skins/default/textures/windows/add_payment_image_center.png Binary files differindex fa3575f53d..0b99a72f32 100644 --- a/indra/newview/skins/default/textures/windows/add_payment_image_center.png +++ b/indra/newview/skins/default/textures/windows/add_payment_image_center.png diff --git a/indra/newview/skins/default/textures/windows/add_payment_image_left.png b/indra/newview/skins/default/textures/windows/add_payment_image_left.png Binary files differindex a3c154477f..a5b28d7023 100644 --- a/indra/newview/skins/default/textures/windows/add_payment_image_left.png +++ b/indra/newview/skins/default/textures/windows/add_payment_image_left.png diff --git a/indra/newview/skins/default/textures/windows/add_payment_image_right.png b/indra/newview/skins/default/textures/windows/add_payment_image_right.png Binary files differindex 1edc10064d..5724d39744 100644 --- a/indra/newview/skins/default/textures/windows/add_payment_image_right.png +++ b/indra/newview/skins/default/textures/windows/add_payment_image_right.png diff --git a/indra/newview/skins/default/textures/windows/first_login_image.jpg b/indra/newview/skins/default/textures/windows/first_login_image.jpg Binary files differindex 30f31341ed..860fed4ac7 100644 --- a/indra/newview/skins/default/textures/windows/first_login_image.jpg +++ b/indra/newview/skins/default/textures/windows/first_login_image.jpg diff --git a/indra/newview/skins/default/textures/windows/login_mp_logo.png b/indra/newview/skins/default/textures/windows/login_mp_logo.png Binary files differnew file mode 100644 index 0000000000..7526374ba2 --- /dev/null +++ b/indra/newview/skins/default/textures/windows/login_mp_logo.png diff --git a/indra/newview/skins/default/textures/windows/login_mp_logo_small.png b/indra/newview/skins/default/textures/windows/login_mp_logo_small.png Binary files differnew file mode 100644 index 0000000000..779d8ff649 --- /dev/null +++ b/indra/newview/skins/default/textures/windows/login_mp_logo_small.png diff --git a/indra/newview/skins/default/textures/world/NoEntryLines.png b/indra/newview/skins/default/textures/world/NoEntryLines.png Binary files differindex d7496b8bd0..b295ba1281 100644 --- a/indra/newview/skins/default/textures/world/NoEntryLines.png +++ b/indra/newview/skins/default/textures/world/NoEntryLines.png diff --git a/indra/newview/skins/default/textures/world/NoEntryPassLines.png b/indra/newview/skins/default/textures/world/NoEntryPassLines.png Binary files differindex e4b8fc6ae2..34900e2c02 100644 --- a/indra/newview/skins/default/textures/world/NoEntryPassLines.png +++ b/indra/newview/skins/default/textures/world/NoEntryPassLines.png diff --git a/indra/newview/skins/default/xui/da/language_settings.xml b/indra/newview/skins/default/xui/da/language_settings.xml index 0e3cbfd2d2..fd3fa6c6fd 100644 --- a/indra/newview/skins/default/xui/da/language_settings.xml +++ b/indra/newview/skins/default/xui/da/language_settings.xml @@ -7,6 +7,7 @@ <string name="MacLocale">da_DK.UTF-8</string> <string name="DarwinLocale">da_DK.UTF-8</string> <string name="LinuxLocale">da_DK.UTF-8</string> + <string name="FreeBSDLocale">da_DK.UTF-8</string> <!-- datetimeToCodes["wkday"] = "%a"; // Thu diff --git a/indra/newview/skins/default/xui/da/strings.xml b/indra/newview/skins/default/xui/da/strings.xml index e4f99d14e9..a7dff91311 100644 --- a/indra/newview/skins/default/xui/da/strings.xml +++ b/indra/newview/skins/default/xui/da/strings.xml @@ -5,7 +5,7 @@ that are returned from one component and may appear in many places--> <strings> <string name="CAPITALIZED_APP_NAME"> - SECOND LIFE + MEGAPAHIT </string> <string name="SUPPORT_SITE"> Second Life Support Portal @@ -429,7 +429,7 @@ Prøv venligst om lidt igen. Noter om version </string> <string name="RELEASE_NOTES_BASE_URL"> - https://releasenotes.secondlife.com/viewer/ + https://megapahit.net/ </string> <string name="LoadingData"> Henter... diff --git a/indra/newview/skins/default/xui/de/language_settings.xml b/indra/newview/skins/default/xui/de/language_settings.xml index f9346eef7d..912b30615e 100644 --- a/indra/newview/skins/default/xui/de/language_settings.xml +++ b/indra/newview/skins/default/xui/de/language_settings.xml @@ -7,6 +7,7 @@ <string name="MacLocale">de_DE.UTF-8</string> <string name="DarwinLocale">de_DE.UTF-8</string> <string name="LinuxLocale">de_DE.UTF-8</string> + <string name="FreeBSDLocale">de_DE.UTF-8</string> <!-- datetimeToCodes["wkday"] = "%a"; // Thu diff --git a/indra/newview/skins/default/xui/de/strings.xml b/indra/newview/skins/default/xui/de/strings.xml index a9e7626dc5..b147c49224 100644 --- a/indra/newview/skins/default/xui/de/strings.xml +++ b/indra/newview/skins/default/xui/de/strings.xml @@ -1,8 +1,8 @@ <?xml version="1.0" ?> <strings> <string name="SECOND_LIFE">Second Life</string> - <string name="APP_NAME">Second Life</string> - <string name="CAPITALIZED_APP_NAME">SECOND LIFE</string> + <string name="APP_NAME">Megapahit</string> + <string name="CAPITALIZED_APP_NAME">MEGAPAHIT</string> <string name="SECOND_LIFE_GRID">Second Life-Grid:</string> <string name="SUPPORT_SITE">Second Life Support-Portal</string> <string name="StartupDetectingHardware">Hardware wird erfasst...</string> @@ -267,7 +267,7 @@ nächsten Eigentümer angehängt werden.</string> <string name="NoneFound">Nicht gefunden.</string> <string name="RetrievingData">Laden...</string> <string name="ReleaseNotes">Versionshinweise</string> - <string name="RELEASE_NOTES_BASE_URL">https://releasenotes.secondlife.com/viewer/</string> + <string name="RELEASE_NOTES_BASE_URL">https://megapahit.net/</string> <string name="LoadingData">Wird geladen...</string> <string name="AvatarNameNobody">(niemand)</string> <string name="AvatarNameWaiting">(wartet)</string> diff --git a/indra/newview/skins/default/xui/en/floater_about.xml b/indra/newview/skins/default/xui/en/floater_about.xml index ff2fa93cbb..ffc163dcb0 100644 --- a/indra/newview/skins/default/xui/en/floater_about.xml +++ b/indra/newview/skins/default/xui/en/floater_about.xml @@ -2,7 +2,7 @@ <floater positioning="centered" legacy_header_height="18" - height="440" + height="520" layout="topleft" name="floater_about" help_topic="floater_about" @@ -14,7 +14,7 @@ follows="all" top="25" left="10" - height="405" + height="490" width="480" name="about_tab" tab_position="top"> @@ -27,7 +27,7 @@ parse_urls="true" follows="top|left" font="SansSerif" - height="343" + height="432" bg_readonly_color="Transparent" left="5" max_length="65536" @@ -46,17 +46,120 @@ </panel> <panel border="true" + has_border="true" label="Credits" help_topic="about_credits_tab" name="credits_panel"> + <accordion + fit_parent="false" + follows="all" + layout="topleft" + left="2" + name="credits_accordion" + single_expansion="true" + top="0" + right="-1"> + <accordion_tab + expanded="true" + fit_panel="false" + layout="topleft" + name="mp_credits_tab" + title="Megapahit"> + <panel + border="false" + follows="all" + left="10" + name="megapahit_credits_panel" + height="320" + top="10"> <text follows="top|left|right" + font.style="BOLD" + height="10" + layout="topleft" + left="5" + top="0" + width="435" + wrap="true"> +Megapahit is brought to you by (in order of appearance): + </text> + <text_editor + enabled="false" + follows="top|left" + height="160" + bg_readonly_color="Transparent" + left="5" + text_color="LtGray" + max_length="65536" + top_pad="5" + width="545" + word_wrap="true"> +Erik Kundiman +milo (observeur) +Fritigern Gothly +Hadet Sonnenkern +Remmy (Secret Foxtail) +Eris Ravenwood +EmilyAmiee +Bavid Dailey +Aria (Tashia Redrose) +Cate (32a) +Melodey + </text_editor> + <text + follows="top|left" + font.style="BOLD" + height="10" + layout="topleft" + left="5" + top_pad="5" + width="465" + wrap="true"> +with special thanks to (in order of appearance): + </text> +<text_editor + enabled="false" + follows="top|left" + height="130" + bg_readonly_color="Transparent" + left="5" + text_color="LtGray" + max_length="65536" + name="megapahit_contributors" + top_pad="5" + width="450" + word_wrap="true"> +Chorazin Allen and Nicky Perian for involving Erik Kundiman in viewer developments; +LinneNoir for the moral support and initial testing; +Vir Linden for making it possible for the project to have a place (in every sense of the word) in SL; +nutsobvious for the early testing and video proof; +Soft Linden for the security testing; and +Kyle Linden for selling TPV parcel 2 to Erik Kundiman at L$0 price. + </text_editor> + </panel> + </accordion_tab> + <accordion_tab + expanded="true" + fit_panel="false" + layout="topleft" + name="sl_credits_tab" + title="Second Life"> + <panel + border="false" + follows="all" + left="10" + name="sl_credits_panel" + height="500" + top="10"> + <text + follows="top|left|right" + font.style="BOLD" height="20" layout="topleft" left="5" name="linden_intro" - top="10" - width="465" + top="0" + width="365" wrap="true"> Second Life is brought to you by the Lindens, with open source contributions from: @@ -64,18 +167,21 @@ with open source contributions from: <text_editor enabled="false" follows="top|left" - height="340" + height="375" bg_readonly_color="Transparent" left="5" text_color="LtGray" max_length="65536" name="contrib_names" top_pad="10" - width="465" + width="415" word_wrap="true"> Dummy Name replaced at run time </text_editor> </panel> + </accordion_tab> +</accordion> + </panel> <panel border="true" label="Licenses" @@ -97,31 +203,23 @@ Dummy Name replaced at run time APR Copyright (C) 2011 The Apache Software Foundation Collada DOM Copyright 2006 Sony Computer Entertainment Inc. cURL Copyright (C) 1996-2010, Daniel Stenberg, (daniel@haxx.se) - DBus/dbus-glib Copyright (C) 2002, 2003 CodeFactory AB / Copyright (C) 2003, 2004 Red Hat, Inc. expat Copyright (C) 1998, 1999, 2000 Thai Open Source Software Center Ltd. FreeType Copyright (C) 1996-2002, 2006 David Turner, Robert Wilhelm, and Werner Lemberg. GL Copyright (C) 1999-2004 Brian Paul. - google-perftools Copyright (c) 2005, Google Inc. - Havok.com(TM) Copyright (C) 1999-2001, Telekinesys Research Limited. - jpeg2000 Copyright (C) 2001, David Taubman, The University of New South Wales (UNSW) jpeglib Copyright (C) 1991-1998, Thomas G. Lane. meshoptimizer Copyright (c) 2016-2021 Arseny Kapoulkine ogg/vorbis Copyright (C) 2002, Xiphophorus OpenSSL Copyright (C) 1998-2008 The OpenSSL Project. PCRE Copyright (c) 1997-2012 University of Cambridge - SDL Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga + SDL Copyright (C) 1997-2024 Sam Lantinga SSLeay Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) xmlrpc-epi Copyright (C) 2000 Epinions, Inc. xxHash Copyright (C) 2012-2020 Yann Collet. zlib Copyright (C) 1995-2012 Jean-loup Gailly and Mark Adler. - Second Life Viewer uses Havok (TM) Physics. (c)Copyright 1999-2010 Havok.com Inc. (and its Licensors). All Rights Reserved. See www.havok.com for details. - This software contains source code provided by NVIDIA Corporation. All rights reserved. See licenses.txt for details. - - Voice chat Audio coding: Polycom(R) Siren14(TM) (ITU-T Rec. G.722.1 Annex C) </text_editor> </panel> </tab_container> diff --git a/indra/newview/skins/default/xui/en/floater_camera.xml b/indra/newview/skins/default/xui/en/floater_camera.xml index 93b306d7d7..44a5638bc4 100644 --- a/indra/newview/skins/default/xui/en/floater_camera.xml +++ b/indra/newview/skins/default/xui/en/floater_camera.xml @@ -5,9 +5,11 @@ bottom="-50" follows="left|bottom" legacy_header_height="18" - can_minimize="true" + can_minimize="false" + can_collapse="false" can_close="true" - height="135" + width="410" + height="114" layout="topleft" name="camera_floater" help_topic="camera_floater" @@ -15,8 +17,7 @@ single_instance="true" title="CAMERA CONTROLS" chrome="true" - save_rect="true" - width="400"> + save_rect="true"> <floater.string name="rotate_tooltip"> Rotate Camera Around Focus @@ -36,18 +37,19 @@ <string name="inactive_combo_text">Use preset</string> <panel border="false" - height="123" + width="220" + height="90" layout="topleft" left="2" - top="0" + top="18" mouse_opaque="false" name="controls" - width="220"> + > <!--TODO: replace + - images --> <panel border="false" class="camera_zoom_panel" - height="123" + height="90" layout="topleft" left="0" mouse_opaque="false" @@ -56,54 +58,59 @@ width="220"> <joystick_rotate follows="top|left" + width="78" height="78" layout="topleft" left="7" + top="8" name="cam_rotate_stick" quadrant="left" sound_flags="3" visible="true" + scale_image="true" tool_tip="Orbit camera around focus" - top="25" - width="78" /> + /> <button follows="top|left" + width="18" height="18" + left_pad="4" + top="2" + layout="topleft" image_disabled="AddItem_Disabled" image_selected="AddItem_Press" image_unselected="AddItem_Off" - layout="topleft" - left_pad="14" name="zoom_plus_btn" - width="18" - top="23"> + > <commit_callback function="Zoom.plus" /> <mouse_held_callback function="Zoom.plus" /> </button> <slider_bar + width="18" height="50" + top_pad="0" layout="topleft" name="zoom_slider" orientation="vertical" tool_tip="Zoom camera toward focus" - top_pad="0" min_val="0" - max_val="1" - width="18"> + max_val="1" + > <commit_callback function="Slider.value_changed"/> </slider_bar> <button follows="top|left" + width="18" height="18" + top_pad="0" + layout="topleft" image_disabled="MinusItem_Disabled" image_selected="MinusItem_Press" image_unselected="MinusItem_Off" - layout="topleft" name="zoom_minus_btn" - top_pad="0" - width="18"> + > <commit_callback function="Zoom.minus" /> <mouse_held_callback @@ -111,35 +118,46 @@ </button> <joystick_track follows="top|left" + width="78" height="78" + left_pad="4" image_selected="Cam_Tracking_In" image_unselected="Cam_Tracking_Out" layout="topleft" - left="133" name="cam_track_stick" quadrant="left" - scale_image="false" + scale_image="true" sound_flags="3" tool_tip="Move camera up and down, left and right" - top="25" - width="78"/> - <text - type="string" - length="1" - follows="left|top" - height="15" + /> + <button + follows="top|left" + width="18" + height="18" + top="8" + left_pad="6" + layout="topleft" + name="collapse_btn" + > + </button> + <button + follows="top|left" + width="18" + height="18" + top_pad="4" layout="topleft" - left="41" - top_pad="9" - name="precise_ctrs_label" - width="200"> - Use precise controls - </text> + name="precise_btn" + image_disabled="Cam_FreeCam_Off" + image_selected="Cam_FreeCam_Off" + image_unselected="Cam_FreeCam_Off" + tool_tip="Use precise controls" + > + </button> </panel> </panel> <panel follows="left|top" - height="102" + height="90" layout="topleft" left_pad="2" right="-2" @@ -216,7 +234,7 @@ mouse_opaque="true" name="preset_combo" top_pad="10" - width="136"> + width="124"> <combo_list mouse_wheel_opaque="true"/> <combo_box.item @@ -226,13 +244,13 @@ </combo_box> <button height="16" - width="16" + width="16" layout="topleft" mouse_opaque="true" name="gear_btn" tool_tip="My Camera Presets" top_delta="3" - left_pad="10" + left_pad="10" image_selected="Icon_Gear" image_pressed="Icon_Gear" image_unselected="Icon_Gear" @@ -242,13 +260,16 @@ </button> <button follows="top|left" - height="25" - label="Save as preset..." + width="18" + height="18" + left_pad="4" + tooltip_text="Save as preset..." layout="topleft" - left="0" name="save_preset_btn" - top_pad="18" - width="150"> + image_disabled="Conv_toolbar_plus" + image_selected="Conv_toolbar_plus" + image_unselected="Conv_toolbar_plus" + > <button.commit_callback function="CameraPresets.Save"/> </button> @@ -259,7 +280,7 @@ top="135" width="400" height="150" - border="true" + border="false" visible="false" background_visible="true"/> <panel @@ -268,7 +289,7 @@ top="285" width="400" height="150" - border="true" + border="false" visible="false" background_visible="true"/> </floater> diff --git a/indra/newview/skins/default/xui/en/floater_emoji_picker.xml b/indra/newview/skins/default/xui/en/floater_emoji_picker.xml index e4b8f13df7..f642ca93b7 100644 --- a/indra/newview/skins/default/xui/en/floater_emoji_picker.xml +++ b/indra/newview/skins/default/xui/en/floater_emoji_picker.xml @@ -13,7 +13,6 @@ chrome="true" height="350" width="304"> - <floater.string name="title_for_recently_used" value="Recently used"/> <floater.string name="title_for_frequently_used" value="Frequently used"/> <floater.string name="text_no_emoji_for_filter" value="No emoji found for '[FILTER]'"/> <scroll_container diff --git a/indra/newview/skins/default/xui/en/floater_fast_timers.xml b/indra/newview/skins/default/xui/en/floater_fast_timers.xml index f5852fdfaf..4dc9876ac8 100644 --- a/indra/newview/skins/default/xui/en/floater_fast_timers.xml +++ b/indra/newview/skins/default/xui/en/floater_fast_timers.xml @@ -74,6 +74,8 @@ orientation="vertical" step_size="16" doc_size="3000" + page_size="50" + doc_pos="0" /> </layout_panel> <layout_panel name="timers_panel" diff --git a/indra/newview/skins/default/xui/en/floater_fs_search.xml b/indra/newview/skins/default/xui/en/floater_fs_search.xml new file mode 100644 index 0000000000..2372bc03ba --- /dev/null +++ b/indra/newview/skins/default/xui/en/floater_fs_search.xml @@ -0,0 +1,337 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<floater + can_resize="true" + default_tab_group="1" + height="590" + help_topic="search" + layout="topleft" + legacy_header_height="0" + min_height="590" + min_width="660" + name="floater_search" + positioning="centered" + save_rect="true" + single_instance="true" + title="SEARCH" + width="780"> + <!-- Strings --> + <floater.string name="string.location"> + Location: [LOCATION] + </floater.string> + <floater.string name="string.traffic"> + Traffic: [DWELL] + </floater.string> + <floater.string name="string.area"> + Area: [AREA] + </floater.string> + <floater.string name="string.members"> + Members: [MEMBER_COUNT] + </floater.string> + <floater.string name="string.founder"> + Founder: [FOUNDER] + </floater.string> + <floater.string name="string.age"> + Age: [AGE] + </floater.string> + <floater.string name="string.partner"> + Partner: [PARTNER] + </floater.string> + <floater.string name="string.listing_price"> + Listing Price: [LISTING_PRICE] + </floater.string> + <floater.string name="string.slurl"> + [SLURL] + </floater.string> + <floater.string name="string.duration"> + Duration: [DURATION] + </floater.string> + <floater.string name="string.covercharge"> + Cover: [COVERCHARGE] + </floater.string> + <!-- Tab time --> + <tab_container + layout="topleft" + follows="all" + top="1" + left="0" + name="ls_tabs" + tab_min_width="90" + tab_position="top" + width="780" + height="585"> + <panel + class="panel_ls_web" + filename="panel_fs_search_legacy_web.xml" + label="Websearch" + layout="topleft" + name="panel_ls_web" /> + <panel + class="panel_ls_people" + filename="panel_fs_search_legacy_people.xml" + label="People" + layout="topleft" + name="panel_ls_people" /> + <panel + class="panel_ls_groups" + filename="panel_fs_search_legacy_groups.xml" + label="Groups" + layout="topleft" + name="panel_ls_groups" /> + <panel + class="panel_ls_places" + filename="panel_fs_search_legacy_places.xml" + label="Places" + layout="topleft" + name="panel_ls_places" /> + <panel + class="panel_ls_land" + filename="panel_fs_search_legacy_land.xml" + label="Land Sales" + layout="topleft" + name="panel_ls_land" /> + <panel + class="panel_ls_events" + filename="panel_fs_search_legacy_events.xml" + label="Events" + layout="topleft" + name="panel_ls_events" /> + <panel + class="panel_ls_classifieds" + filename="panel_fs_search_legacy_classifieds.xml" + label="Classifieds" + layout="topleft" + name="panel_ls_classifieds" /> + </tab_container> + <!-- Details/Action Panes --> + <panel + border="true" + follows="top|right|bottom" + height="508" + layout="topleft" + left="412" + top="80" + width="366" + name="panel_ls_details"> + <text_editor + left="12" + top="5" + height="24" + width="340" + layout="topleft" + follows="left|top|right" + name="title" + bg_visible="false" + border_visible="false" + allow_scroll="false" + h_pad="0" + v_pad="0" + halign="center" + enabled="false" + use_ellipses="true" + font="SansSerifHugeBold" + value="Undefined name" /> + <texture_picker + enabled="false" + fallback_image="Generic_Person_Large" + follows="left|top|right" + height="210" + layout="topleft" + left="78" + name="snapshot" + top_pad="4" + width="210"/> + <texture_picker + enabled="false" + fallback_image="default_land_picture.j2c" + follows="left|top|right" + height="210" + layout="topleft" + left_delta="0" + name="snapshot_parcel" + top_delta="0" + visible="false" + width="210"/> + <text_editor + left="20" + top_pad="2" + height="16" + width="180" + layout="topleft" + follows="left|top|right" + name="aux1" + bg_visible="false" + border_visible="false" + h_pad="0" + v_pad="0" + word_wrap="true" + enabled="false" + max_length="117" + allow_scroll="false" + parse_urls="true" + value="Auxilary info field 1"/> + <text_editor + left_pad="4" + top_delta="0" + height="16" + width="140" + layout="topleft" + follows="left|top|right" + name="aux2" + bg_visible="false" + border_visible="false" + h_pad="0" + v_pad="0" + word_wrap="true" + enabled="false" + max_length="117" + allow_scroll="false" + parse_urls="true" + value="Auxilary info field 2"/> + <icon + follows="top|right" + height="16" + image_name="Unknown_Icon" + layout="topleft" + left="20" + top_pad="2" + name="maturity_icon" + width="18" /> + <text_editor + left_pad="4" + top_delta="0" + height="28" + width="302" + layout="topleft" + follows="left|top|right" + name="location" + bg_visible="false" + border_visible="false" + h_pad="0" + v_pad="0" + word_wrap="true" + enabled="false" + max_length="117" + allow_scroll="false" + parse_urls="true" + value="Location info field"/> + <text_editor + left="20" + top_pad="12" + height="154" + width="324" + layout="topleft" + follows="left|top|right" + name="desc" + bg_visible="false" + border_visible="false" + h_pad="0" + v_pad="0" + word_wrap="true" + parse_urls="true" + enabled="false" + max_length="1000" + trusted_content="false" + value="You unlock this door with the key of imagination. Beyond it is another dimension: a dimension of sound, a dimension of sight, a dimension of mind. You're moving into a land of both shadow and substance, of things and ideas; you've just crossed over into the Twilight Zone. What you are about to see is real; the litigants on the screen are not actors. They are genuine citizens who, having filed their claims in a real small claims court, have been persuaded to drop their suits there and have them settled here, in this forum... the People's Court."/> + <button + layout="topleft" + follows="left|bottom" + height="23" + label="Open Profile" + name="people_profile_btn" + top="484" + left="3" + width="120" /> + <button + layout="topleft" + follows="left|bottom" + height="23" + label="Send Message" + name="people_message_btn" + width="120" + left_pad="1" /> + <button + layout="topleft" + follows="left|bottom" + height="23" + label="Add Friend" + name="people_friend_btn" + width="120" + left_pad="1" /> + <button + layout="topleft" + follows="left|bottom" + height="23" + label="Open Profile" + name="group_profile_btn" + top="484" + left="3" + width="120" /> + <button + layout="topleft" + follows="left|bottom" + height="23" + label="Join Chat" + name="group_message_btn" + width="120" + left_pad="1" /> + <button + layout="topleft" + follows="left|bottom" + height="23" + label="Join Group" + name="group_join_btn" + width="120" + left_pad="1" /> + <button + layout="topleft" + follows="left|bottom" + height="23" + label="Teleport" + name="teleport_btn" + top="484" + left="3" + width="120" /> + <button + layout="topleft" + follows="left|bottom" + height="23" + label="Show on Map" + name="map_btn" + width="120" + left_pad="1" /> + <button + layout="topleft" + follows="left|bottom" + height="23" + label="Remind me" + name="event_reminder_btn" + width="120" + left_pad="1" /> + <loading_indicator + left="134" + top="320" + follows="left|top|right" + mouse_opaque="false" + name="loading" + images_per_sec="1.0" + tab_stop="false" + height="100" + width="100" + visible="false" > + <images> + <image name="ProgressLarge_1"/> + <image name="ProgressLarge_2"/> + <image name="ProgressLarge_3"/> + <image name="ProgressLarge_4"/> + <image name="ProgressLarge_5"/> + <image name="ProgressLarge_6"/> + <image name="ProgressLarge_7"/> + <image name="ProgressLarge_8"/> + <image name="ProgressLarge_9"/> + <image name="ProgressLarge_10"/> + <image name="ProgressLarge_11"/> + <image name="ProgressLarge_12"/> + </images> + </loading_indicator> + </panel> +</floater> diff --git a/indra/newview/skins/default/xui/en/floater_gesture.xml b/indra/newview/skins/default/xui/en/floater_gesture.xml index 832716c600..7fce91a2c3 100644 --- a/indra/newview/skins/default/xui/en/floater_gesture.xml +++ b/indra/newview/skins/default/xui/en/floater_gesture.xml @@ -52,7 +52,7 @@ width="80" /> </scroll_list> <panel - background_visible="true" + background_visible="false" bevel_style="none" top_pad="0" follows="left|right|bottom" diff --git a/indra/newview/skins/default/xui/en/floater_im_session.xml b/indra/newview/skins/default/xui/en/floater_im_session.xml index 738d448f00..c46cc4f504 100644 --- a/indra/newview/skins/default/xui/en/floater_im_session.xml +++ b/indra/newview/skins/default/xui/en/floater_im_session.xml @@ -291,7 +291,6 @@ height="20" is_expandable="true" text_tentative_color="TextFgTentativeColor" - bg_writeable_color="ScriptBackground" name="chat_editor" max_length="1023" spellcheck="true" diff --git a/indra/newview/skins/default/xui/en/floater_live_material_editor.xml b/indra/newview/skins/default/xui/en/floater_live_material_editor.xml index 5b7dab6a52..fbd3c81bad 100644 --- a/indra/newview/skins/default/xui/en/floater_live_material_editor.xml +++ b/indra/newview/skins/default/xui/en/floater_live_material_editor.xml @@ -20,8 +20,8 @@ width="250" follows="all" layout="topleft" - color="DkGray2" - opaque="true" + color="Transparent" + opaque="false" tab_stop="true" border="false" reserve_scroll_corner="false"> diff --git a/indra/newview/skins/default/xui/en/floater_map.xml b/indra/newview/skins/default/xui/en/floater_map.xml index eba5684819..5e7af80e42 100644 --- a/indra/newview/skins/default/xui/en/floater_map.xml +++ b/indra/newview/skins/default/xui/en/floater_map.xml @@ -50,6 +50,7 @@ Mini-map </floater.string> <net_map + bg_color="Transparent" follows="top|left|bottom|right" layout="topleft" left="0" diff --git a/indra/newview/skins/default/xui/en/floater_mp_performance.xml b/indra/newview/skins/default/xui/en/floater_mp_performance.xml new file mode 100644 index 0000000000..d943a13f66 --- /dev/null +++ b/indra/newview/skins/default/xui/en/floater_mp_performance.xml @@ -0,0 +1,100 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater + positioning="cascading" + legacy_header_height="40" + top="12" + right="-324" + height="120" + min_height="120" + width="320" + min_width="320" + can_minimize="true" + can_close="true" + can_resize="false" + layout="topright" + name="mpv_performance" + single_instance="true" + save_rect="true" + save_visibility="true" + title="Megapahit Tuning"> + + <panel + name="panel_fps" + border="false" + width="300" + height="36" + left="10" + top="40" + follows="top|left" + layout="topleft" + > + + <slider + name="fpsSlider" + width="300" + height="15" + layout="topleft" + enabled="true" + control_name="fpsSlider" + decimal_digits="0" + increment="5" + initial_value="0" + label="Max FPS" + label_width="50" + text_width="30" + can_edit_text="false" + show_text="true" + > + </slider> + + </panel> + + <panel + name="panel_mapping" + border="false" + width="300" + height="36" + left="10" + top="78" + follows="top|left" + layout="topleft" + > + + <text + name="MPVBuffModeLabel" + width="100" + height="15" + left="2" + top="8"> + Optimisations: + (needs restart): + </text> + + <combo_box + control_name="MPVBuffModeControl" + name="MPVBuffModeComboBox" + width="150" + height="23" + left="130" + top="4" + > + <combo_box.item + enabled="true" + label="Normal" + name="Normal" + value="1" /> + <combo_box.item + enabled="true" + label="Apple GPU (smoothie)" + name="Megapahit Optimisations" + value="2" /> + <combo_box.item + enabled="true" + label="Apple GPU (LL)" + name="LL Optimisations" + value="3" /> + </combo_box> + + </panel> + +</floater> diff --git a/indra/newview/skins/default/xui/en/floater_my_environments.xml b/indra/newview/skins/default/xui/en/floater_my_environments.xml index 8c9c450d7c..dd0795305e 100644 --- a/indra/newview/skins/default/xui/en/floater_my_environments.xml +++ b/indra/newview/skins/default/xui/en/floater_my_environments.xml @@ -26,8 +26,8 @@ bottom="-5" orientation="vertical"> <layout_panel - border="true" - bevel_style="in" + border="false" + bevel_style="none" auto_resize="false" tab_group="1" height="54" @@ -147,7 +147,7 @@ name="pnl_control" font="SansSerifBold"> <panel - background_visible="true" + background_visible="false" bevel_style="none" top_pad="1" follows="top|left|right" diff --git a/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml b/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml index 7bc81a1f79..8c4019a668 100644 --- a/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml +++ b/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml @@ -222,7 +222,7 @@ height="16" increment="1" initial_value="12" - label="Max. # of non-impostors:" + label="Max. # animated avatars:" label_width="185" layout="topleft" left="30" diff --git a/indra/newview/skins/default/xui/en/floater_script.xml b/indra/newview/skins/default/xui/en/floater_script.xml index ae6e68de17..900319620d 100644 --- a/indra/newview/skins/default/xui/en/floater_script.xml +++ b/indra/newview/skins/default/xui/en/floater_script.xml @@ -7,7 +7,8 @@ name="script_floater" can_dock="true" can_minimize="true" - visible="false" + save_rect="true" + visible="false" width="350" can_resize="false" min_width="350" diff --git a/indra/newview/skins/default/xui/en/floater_tools.xml b/indra/newview/skins/default/xui/en/floater_tools.xml index e43143c8c3..c88e4163be 100644 --- a/indra/newview/skins/default/xui/en/floater_tools.xml +++ b/indra/newview/skins/default/xui/en/floater_tools.xml @@ -1194,7 +1194,7 @@ even though the user gets a free copy. follows="left|top" layout="topleft" mouse_opaque="false" - background_visible="true" + background_visible="false" bg_alpha_color="DkGray" name="perms_build" left="0" diff --git a/indra/newview/skins/default/xui/en/floater_world_map.xml b/indra/newview/skins/default/xui/en/floater_world_map.xml index 7efa81d263..3acae704c6 100644 --- a/indra/newview/skins/default/xui/en/floater_world_map.xml +++ b/indra/newview/skins/default/xui/en/floater_world_map.xml @@ -34,7 +34,8 @@ top="16" left="0" right="-1" - bottom="-1"> + bottom="-1" + orientation="horizontal"> <layout_panel name="map_lp" width="385" @@ -85,8 +86,8 @@ height="22" width="238" follows="right|top" - top="6" - background_visible="true" + top="6" + background_visible="false" bg_alpha_color="DkGray2"> <text text_color="White" @@ -429,7 +430,7 @@ height="22" top_pad="0" width="238" - background_visible="true" + background_visible="false" bg_alpha_color="DkGray2" name="layout_panel_3"> <text @@ -570,7 +571,7 @@ </button> <scroll_list draw_stripes="false" - bg_writeable_color="MouseGray" + bg_writeable_color="0.75 0.75 0.75 0.15" follows="all" height="145" layout="topleft" @@ -604,7 +605,7 @@ Location: </text> <spinner - control_name="Teleport_Coordinate_X" + control_name="teleport_coordinate_x" decimal_digits="0" follows="right|bottom" height="23" @@ -616,11 +617,11 @@ min_val="0" name="teleport_coordinate_x" width="44" > - <spinner.commit_callback + <spinner.commit_callback function="WMap.Coordinates" /> </spinner> <spinner - control_name="Teleport_Coordinate_Y" + control_name="teleport_coordinate_y" decimal_digits="0" follows="right|bottom" height="23" @@ -636,7 +637,7 @@ function="WMap.Coordinates" /> </spinner> <spinner - control_name="Teleport_Coordinate_Z" + control_name="teleport_coordinate_z" decimal_digits="0" follows="right|bottom" height="23" @@ -697,7 +698,7 @@ height="22" top_pad="0" width="238" - background_visible="true" + background_visible="false" bg_alpha_color="DkGray2" name="layout_panel_5"> <text diff --git a/indra/newview/skins/default/xui/en/language_settings.xml b/indra/newview/skins/default/xui/en/language_settings.xml index dd521c09d0..24e58c9936 100644 --- a/indra/newview/skins/default/xui/en/language_settings.xml +++ b/indra/newview/skins/default/xui/en/language_settings.xml @@ -7,6 +7,7 @@ <string name="MacLocale">C</string> <string name="DarwinLocale">C</string> <string name="LinuxLocale">C</string> + <string name="FreeBSDLocale">C</string> <!-- Note: for plural nouns, see strings.xml. For example: AgeYearsA = singular, diff --git a/indra/newview/skins/default/xui/en/menu_im_session_showmodes.xml b/indra/newview/skins/default/xui/en/menu_im_session_showmodes.xml index 94022ef1e3..f1cf8b9995 100644 --- a/indra/newview/skins/default/xui/en/menu_im_session_showmodes.xml +++ b/indra/newview/skins/default/xui/en/menu_im_session_showmodes.xml @@ -46,4 +46,12 @@ function="IMSession.Menu.ShowModes.Enable" parameter="IMShowNamesForP2PConv" /> </menu_item_check> + <menu_item_check name="IMShowArrivalsDepartures" label="Show arrivals and departures"> + <menu_item_check.on_click + function="IMSession.Menu.Action" + parameter="IMShowArrivalsDepartures" /> + <menu_item_check.on_check + function="IMSession.Menu.ShowModes.CheckItem" + parameter="IMShowArrivalsDepartures" /> + </menu_item_check> </toggleable_menu> diff --git a/indra/newview/skins/default/xui/en/menu_people_nearby.xml b/indra/newview/skins/default/xui/en/menu_people_nearby.xml index 7bd2c845a6..b7a296bf31 100644 --- a/indra/newview/skins/default/xui/en/menu_people_nearby.xml +++ b/indra/newview/skins/default/xui/en/menu_people_nearby.xml @@ -101,6 +101,16 @@ parameter="can_zoom_in"/> </menu_item_call> <menu_item_call + label="Teleport To" + layout="topleft" + name="teleport_to"> + <menu_item_call.on_click + function="Avatar.TeleportTo" /> + <menu_item_call.on_enable + function="Avatar.EnableItem" + parameter="can_zoom_in"/> + </menu_item_call> + <menu_item_call label="Map" layout="topleft" name="map"> diff --git a/indra/newview/skins/default/xui/en/menu_profile_other.xml b/indra/newview/skins/default/xui/en/menu_profile_other.xml index 101ae33778..a505b38087 100644 --- a/indra/newview/skins/default/xui/en/menu_profile_other.xml +++ b/indra/newview/skins/default/xui/en/menu_profile_other.xml @@ -168,4 +168,12 @@ function="Profile.Commit" parameter="copy_user_id"/> </menu_item_call> + <menu_item_call + label="Copy Profile Link" + layout="topleft" + name="copy_link"> + <menu_item_call.on_click + function="Profile.Commit" + parameter="copy_profile_link"/> + </menu_item_call> </toggleable_menu> diff --git a/indra/newview/skins/default/xui/en/menu_profile_self.xml b/indra/newview/skins/default/xui/en/menu_profile_self.xml index 1b21c7ae61..0a03d7ac2b 100644 --- a/indra/newview/skins/default/xui/en/menu_profile_self.xml +++ b/indra/newview/skins/default/xui/en/menu_profile_self.xml @@ -82,4 +82,12 @@ function="Profile.Commit" parameter="copy_user_id"/> </menu_item_call> + <menu_item_call + label="Copy Profile Link" + layout="topleft" + name="copy_link"> + <menu_item_call.on_click + function="Profile.Commit" + parameter="copy_profile_link"/> + </menu_item_call> </toggleable_menu> diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index d5d2d00630..46056e884d 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -987,6 +987,7 @@ </menu_item_check> <menu_item_check label="Use Shared Environment" + shortcut="control|shift|X" name="Use Shared Environment"> <menu_item_check.on_click function="World.EnvSettings" @@ -4149,16 +4150,6 @@ function="World.EnvPreset" <menu_item_separator/> - <menu_item_check - label="HTTP Textures" - name="HTTP Textures"> - <menu_item_check.on_check - function="CheckControl" - parameter="ImagePipelineUseHTTP" /> - <menu_item_check.on_click - function="ToggleControl" - parameter="ImagePipelineUseHTTP" /> - </menu_item_check> <menu_item_call label="Compress Images" name="Compress Images"> diff --git a/indra/newview/skins/default/xui/en/mime_types_linux.xml b/indra/newview/skins/default/xui/en/mime_types_linux.xml index d0ecd0a11c..e5c33809c8 100644 --- a/indra/newview/skins/default/xui/en/mime_types_linux.xml +++ b/indra/newview/skins/default/xui/en/mime_types_linux.xml @@ -7,7 +7,7 @@ none </defaultwidget> <defaultimpl> - media_plugin_webkit + media_plugin_cef </defaultimpl> <widgetset name="web"> <label name="web_label"> @@ -141,7 +141,7 @@ none </widgettype> <impl> - media_plugin_webkit + media_plugin_cef </impl> </mimetype> <mimetype name="none/none"> @@ -152,7 +152,7 @@ none </widgettype> <impl> - media_plugin_webkit + media_plugin_cef </impl> </mimetype> <mimetype name="audio/*"> @@ -185,7 +185,7 @@ image </widgettype> <impl> - media_plugin_webkit + media_plugin_cef </impl> </mimetype> <mimetype menu="1" name="video/vnd.secondlife.qt.legacy"> @@ -207,7 +207,7 @@ web </widgettype> <impl> - media_plugin_webkit + media_plugin_cef </impl> </mimetype> <mimetype name="application/ogg"> @@ -229,7 +229,7 @@ image </widgettype> <impl> - media_plugin_webkit + media_plugin_cef </impl> </mimetype> <mimetype name="application/postscript"> @@ -240,7 +240,7 @@ image </widgettype> <impl> - media_plugin_webkit + media_plugin_cef </impl> </mimetype> <mimetype name="application/rtf"> @@ -251,7 +251,7 @@ image </widgettype> <impl> - media_plugin_webkit + media_plugin_cef </impl> </mimetype> <mimetype name="application/smil"> @@ -262,7 +262,7 @@ movie </widgettype> <impl> - media_plugin_webkit + media_plugin_cef </impl> </mimetype> <mimetype name="application/xhtml+xml"> @@ -273,7 +273,7 @@ web </widgettype> <impl> - media_plugin_webkit + media_plugin_cef </impl> </mimetype> <mimetype name="application/x-director"> @@ -284,7 +284,7 @@ image </widgettype> <impl> - media_plugin_webkit + media_plugin_cef </impl> </mimetype> <mimetype name="audio/mid"> @@ -339,7 +339,7 @@ image </widgettype> <impl> - media_plugin_webkit + media_plugin_cef </impl> </mimetype> <mimetype menu="1" name="image/gif"> @@ -350,7 +350,7 @@ image </widgettype> <impl> - media_plugin_webkit + media_plugin_cef </impl> </mimetype> <mimetype menu="1" name="image/jpeg"> @@ -361,7 +361,7 @@ image </widgettype> <impl> - media_plugin_webkit + media_plugin_cef </impl> </mimetype> <mimetype menu="1" name="image/png"> @@ -372,7 +372,7 @@ image </widgettype> <impl> - media_plugin_webkit + media_plugin_cef </impl> </mimetype> <mimetype name="image/svg+xml"> @@ -383,7 +383,7 @@ image </widgettype> <impl> - media_plugin_webkit + media_plugin_cef </impl> </mimetype> <mimetype menu="1" name="image/tiff"> @@ -394,7 +394,7 @@ image </widgettype> <impl> - media_plugin_webkit + media_plugin_cef </impl> </mimetype> <mimetype menu="1" name="text/html"> @@ -405,7 +405,7 @@ web </widgettype> <impl> - media_plugin_webkit + media_plugin_cef </impl> </mimetype> <mimetype menu="1" name="text/plain"> @@ -416,7 +416,7 @@ text </widgettype> <impl> - media_plugin_webkit + media_plugin_cef </impl> </mimetype> <mimetype name="text/xml"> @@ -427,7 +427,7 @@ text </widgettype> <impl> - media_plugin_webkit + media_plugin_cef </impl> </mimetype> <mimetype menu="1" name="video/mpeg"> diff --git a/indra/newview/skins/default/xui/en/panel_avatar_list_item.xml b/indra/newview/skins/default/xui/en/panel_avatar_list_item.xml index ca6e94397d..cfca246321 100644 --- a/indra/newview/skins/default/xui/en/panel_avatar_list_item.xml +++ b/indra/newview/skins/default/xui/en/panel_avatar_list_item.xml @@ -66,6 +66,28 @@ value="(loading)" width="180" /> <text + follows="left|right" + font="SansSerifSmall" + height="15" + layout="topleft" + left_pad="5" + name="avatar_arrival_time" + top="6" + text_color="LtGray_50" + value="0s" + width="35" /> + <text + follows="left|right" + font="SansSerifSmall" + height="15" + layout="topleft" + left_pad="5" + name="avatar_distance" + top="6" + text_color="LtGray_50" + value="0m" + width="35" /> + <text follows="right" font="SansSerifSmall" height="15" diff --git a/indra/newview/skins/default/xui/en/panel_edit_alpha.xml b/indra/newview/skins/default/xui/en/panel_edit_alpha.xml index 30fee7361f..7bce8d9bca 100644 --- a/indra/newview/skins/default/xui/en/panel_edit_alpha.xml +++ b/indra/newview/skins/default/xui/en/panel_edit_alpha.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <panel - background_visible="true" + background_visible="false" follows="all" height="400" layout="topleft" @@ -23,8 +23,8 @@ border="false" bg_alpha_color="DkGray2" bg_opaque_color="DkGray2" - background_visible="true" - background_opaque="true" + background_visible="false" + background_opaque="false" follows="top|left|right" height="400" left="0" diff --git a/indra/newview/skins/default/xui/en/panel_edit_eyes.xml b/indra/newview/skins/default/xui/en/panel_edit_eyes.xml index f1b2653340..89fa69bcef 100644 --- a/indra/newview/skins/default/xui/en/panel_edit_eyes.xml +++ b/indra/newview/skins/default/xui/en/panel_edit_eyes.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <panel - background_visible="true" + background_visible="false" follows="all" height="400" layout="topleft" @@ -12,8 +12,8 @@ border="false" bg_alpha_color="DkGray2" bg_opaque_color="DkGray2" - background_visible="true" - background_opaque="true" + background_visible="false" + background_opaque="false" follows="top|left|right" height="90" left="10" @@ -41,8 +41,8 @@ border="false" bg_alpha_color="DkGray2" bg_opaque_color="DkGray2" - background_visible="true" - background_opaque="true" + background_visible="false" + background_opaque="false" follows="all" height="300" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/panel_edit_gloves.xml b/indra/newview/skins/default/xui/en/panel_edit_gloves.xml index 6ae21e1273..14b20c7ba1 100644 --- a/indra/newview/skins/default/xui/en/panel_edit_gloves.xml +++ b/indra/newview/skins/default/xui/en/panel_edit_gloves.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <panel - background_visible="true" + background_visible="false" follows="all" height="400" layout="topleft" @@ -12,8 +12,8 @@ border="false" bg_alpha_color="DkGray2" bg_opaque_color="DkGray2" - background_visible="true" - background_opaque="true" + background_visible="false" + background_opaque="false" follows="top|left|right" height="90" left="10" diff --git a/indra/newview/skins/default/xui/en/panel_edit_hair.xml b/indra/newview/skins/default/xui/en/panel_edit_hair.xml index 25f7d8a572..9eec1120e3 100644 --- a/indra/newview/skins/default/xui/en/panel_edit_hair.xml +++ b/indra/newview/skins/default/xui/en/panel_edit_hair.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <panel - background_visible="true" + background_visible="false" follows="all" height="400" layout="topleft" @@ -12,8 +12,8 @@ border="false" bg_alpha_color="DkGray2" bg_opaque_color="DkGray2" - background_visible="true" - background_opaque="true" + background_visible="false" + background_opaque="false" follows="top|left|right" height="90" left="10" @@ -41,8 +41,8 @@ border="false" bg_alpha_color="DkGray2" bg_opaque_color="DkGray2" - background_visible="true" - background_opaque="true" + background_visible="false" + background_opaque="false" follows="all" height="300" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/panel_edit_jacket.xml b/indra/newview/skins/default/xui/en/panel_edit_jacket.xml index 62ee69b43c..c76a04ccf0 100644 --- a/indra/newview/skins/default/xui/en/panel_edit_jacket.xml +++ b/indra/newview/skins/default/xui/en/panel_edit_jacket.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <panel - background_visible="true" + background_visible="false" follows="all" height="400" layout="topleft" @@ -12,8 +12,8 @@ border="false" bg_alpha_color="DkGray2" bg_opaque_color="DkGray2" - background_visible="true" - background_opaque="true" + background_visible="false" + background_opaque="false" follows="top|left|right" height="90" left="10" diff --git a/indra/newview/skins/default/xui/en/panel_edit_pants.xml b/indra/newview/skins/default/xui/en/panel_edit_pants.xml index d2ba71f905..2f4d47f334 100644 --- a/indra/newview/skins/default/xui/en/panel_edit_pants.xml +++ b/indra/newview/skins/default/xui/en/panel_edit_pants.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <panel - background_visible="true" + background_visible="false" follows="all" height="400" layout="topleft" @@ -12,8 +12,8 @@ border="false" bg_alpha_color="DkGray2" bg_opaque_color="DkGray2" - background_visible="true" - background_opaque="true" + background_visible="false" + background_opaque="false" follows="top|left|right" height="90" left="10" diff --git a/indra/newview/skins/default/xui/en/panel_edit_physics.xml b/indra/newview/skins/default/xui/en/panel_edit_physics.xml index 837fb83b64..235025b1ef 100644 --- a/indra/newview/skins/default/xui/en/panel_edit_physics.xml +++ b/indra/newview/skins/default/xui/en/panel_edit_physics.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <panel - background_visible="true" + background_visible="false" follows="all" height="400" layout="topleft" @@ -12,8 +12,8 @@ border="false" bg_alpha_color="DkGray2" bg_opaque_color="DkGray2" - background_visible="true" - background_opaque="true" + background_visible="false" + background_opaque="false" follows="all" height="388" label="" diff --git a/indra/newview/skins/default/xui/en/panel_edit_shape.xml b/indra/newview/skins/default/xui/en/panel_edit_shape.xml index c1d743c3da..bd0335df6e 100644 --- a/indra/newview/skins/default/xui/en/panel_edit_shape.xml +++ b/indra/newview/skins/default/xui/en/panel_edit_shape.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <panel - background_visible="true" + background_visible="false" follows="all" height="400" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/panel_edit_shirt.xml b/indra/newview/skins/default/xui/en/panel_edit_shirt.xml index 059103e233..faca0ab2e7 100644 --- a/indra/newview/skins/default/xui/en/panel_edit_shirt.xml +++ b/indra/newview/skins/default/xui/en/panel_edit_shirt.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <panel - background_visible="true" + background_visible="false" follows="all" height="400" layout="topleft" @@ -12,8 +12,8 @@ border="false" bg_alpha_color="DkGray2" bg_opaque_color="DkGray2" - background_visible="true" - background_opaque="true" + background_visible="false" + background_opaque="false" follows="top|left|right" height="90" left="10" diff --git a/indra/newview/skins/default/xui/en/panel_edit_shoes.xml b/indra/newview/skins/default/xui/en/panel_edit_shoes.xml index 199b143719..2068f48327 100644 --- a/indra/newview/skins/default/xui/en/panel_edit_shoes.xml +++ b/indra/newview/skins/default/xui/en/panel_edit_shoes.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <panel - background_visible="true" + background_visible="false" follows="all" height="400" layout="topleft" @@ -12,8 +12,8 @@ border="false" bg_alpha_color="DkGray2" bg_opaque_color="DkGray2" - background_visible="true" - background_opaque="true" + background_visible="false" + background_opaque="false" follows="top|left|right" height="90" left="10" diff --git a/indra/newview/skins/default/xui/en/panel_edit_skin.xml b/indra/newview/skins/default/xui/en/panel_edit_skin.xml index f3a5791ef8..8e80283bbb 100644 --- a/indra/newview/skins/default/xui/en/panel_edit_skin.xml +++ b/indra/newview/skins/default/xui/en/panel_edit_skin.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <panel - background_visible="true" + background_visible="false" follows="all" height="400" layout="topleft" @@ -12,8 +12,8 @@ border="false" bg_alpha_color="DkGray2" bg_opaque_color="DkGray2" - background_visible="true" - background_opaque="true" + background_visible="false" + background_opaque="false" follows="top|left|right" height="90" left="10" diff --git a/indra/newview/skins/default/xui/en/panel_edit_skirt.xml b/indra/newview/skins/default/xui/en/panel_edit_skirt.xml index adb7632e0a..ef93c8d8d2 100644 --- a/indra/newview/skins/default/xui/en/panel_edit_skirt.xml +++ b/indra/newview/skins/default/xui/en/panel_edit_skirt.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <panel - background_visible="true" + background_visible="false" follows="all" height="400" layout="topleft" @@ -12,8 +12,8 @@ border="false" bg_alpha_color="DkGray2" bg_opaque_color="DkGray2" - background_visible="true" - background_opaque="true" + background_visible="false" + background_opaque="false" follows="top|left|right" height="90" left="10" diff --git a/indra/newview/skins/default/xui/en/panel_edit_socks.xml b/indra/newview/skins/default/xui/en/panel_edit_socks.xml index 1658e5707b..8fb19c34bb 100644 --- a/indra/newview/skins/default/xui/en/panel_edit_socks.xml +++ b/indra/newview/skins/default/xui/en/panel_edit_socks.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <panel - background_visible="true" + background_visible="false" follows="all" height="400" layout="topleft" @@ -12,8 +12,8 @@ border="false" bg_alpha_color="DkGray2" bg_opaque_color="DkGray2" - background_visible="true" - background_opaque="true" + background_visible="false" + background_opaque="false" follows="top|left|right" height="90" left="10" diff --git a/indra/newview/skins/default/xui/en/panel_edit_tattoo.xml b/indra/newview/skins/default/xui/en/panel_edit_tattoo.xml index b4f09e262f..9cb2157896 100644 --- a/indra/newview/skins/default/xui/en/panel_edit_tattoo.xml +++ b/indra/newview/skins/default/xui/en/panel_edit_tattoo.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <panel - background_visible="true" + background_visible="false" follows="all" height="400" layout="topleft" @@ -22,8 +22,8 @@ border="false" bg_alpha_color="DkGray2" bg_opaque_color="DkGray2" - background_visible="true" - background_opaque="true" + background_visible="false" + background_opaque="false" follows="all" height="800" left="10" diff --git a/indra/newview/skins/default/xui/en/panel_edit_underpants.xml b/indra/newview/skins/default/xui/en/panel_edit_underpants.xml index 9ca67ed562..6376787b3c 100644 --- a/indra/newview/skins/default/xui/en/panel_edit_underpants.xml +++ b/indra/newview/skins/default/xui/en/panel_edit_underpants.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <panel - background_visible="true" + background_visible="false" follows="all" height="400" layout="topleft" @@ -12,8 +12,8 @@ border="false" bg_alpha_color="DkGray2" bg_opaque_color="DkGray2" - background_visible="true" - background_opaque="true" + background_visible="false" + background_opaque="false" follows="top|left|right" height="90" left="10" diff --git a/indra/newview/skins/default/xui/en/panel_edit_undershirt.xml b/indra/newview/skins/default/xui/en/panel_edit_undershirt.xml index 4a340fe340..88e1d9bc3b 100644 --- a/indra/newview/skins/default/xui/en/panel_edit_undershirt.xml +++ b/indra/newview/skins/default/xui/en/panel_edit_undershirt.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <panel - background_visible="true" + background_visible="false" follows="all" height="400" layout="topleft" @@ -12,8 +12,8 @@ border="false" bg_alpha_color="DkGray2" bg_opaque_color="DkGray2" - background_visible="true" - background_opaque="true" + background_visible="false" + background_opaque="false" follows="top|left|right" height="90" left="10" diff --git a/indra/newview/skins/default/xui/en/panel_edit_universal.xml b/indra/newview/skins/default/xui/en/panel_edit_universal.xml index a71f6c6c2e..3a84f1733f 100644 --- a/indra/newview/skins/default/xui/en/panel_edit_universal.xml +++ b/indra/newview/skins/default/xui/en/panel_edit_universal.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <panel - background_visible="true" + background_visible="false" follows="all" height="400" layout="topleft" @@ -22,8 +22,8 @@ border="false" bg_alpha_color="DkGray2" bg_opaque_color="DkGray2" - background_visible="true" - background_opaque="true" + background_visible="false" + background_opaque="false" follows="all" height="800" left="10" diff --git a/indra/newview/skins/default/xui/en/panel_edit_wearable.xml b/indra/newview/skins/default/xui/en/panel_edit_wearable.xml index 4d2069c9fe..df67f6ad46 100644 --- a/indra/newview/skins/default/xui/en/panel_edit_wearable.xml +++ b/indra/newview/skins/default/xui/en/panel_edit_wearable.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <panel - background_visible="true" + background_visible="false" bevel_style="in" follows="all" height="570" @@ -178,8 +178,8 @@ use_ellipses="true" width="274" /> <panel - background_opaque="true" - background_visible="true" + background_opaque="false" + background_visible="false" bg_alpha_color="DkGray2" bg_opaque_color="DkGray2" border="false" diff --git a/indra/newview/skins/default/xui/en/panel_fs_search_legacy_classifieds.xml b/indra/newview/skins/default/xui/en/panel_fs_search_legacy_classifieds.xml new file mode 100644 index 0000000000..66c35558b1 --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_fs_search_legacy_classifieds.xml @@ -0,0 +1,169 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<panel + border="false" + follows="all" + height="566" + layout="topleft" + left="1" + width="780" + label="Classifieds" + name="panel_ls_classifieds"> + <panel + border="false" + follows="top|left|right" + height="53" + layout="topleft" + left="0" + width="780" + name="panel_ls_input"> + <text + type="string" + length="1" + follows="left|top" + top_pad="5" + layout="topleft" + left="6" + name="search_text" + top="12" + height="16" + width="156"> + Enter search terms: + </text> + <search_combo_box + layout="topleft" + follows="left|top|right" + height="23" + left_delta="0" + name="classifieds_edit" + top="29" + width="651" /> + <combo_box + follows="right|top" + layout="topleft" + height="23" + allow_text_entry="false" + top_delta="0" + left_pad="2" + name="classifieds_category" + width="122"> + <combo_box.commit_callback + function="CommitSearch" /> + </combo_box> + <check_box + control_name="ShowPGClassifieds" + follows="right|top" + height="16" + label="" + layout="topleft" + left="660" + name="pg_all" + top="12" + width="15"> + <check_box.commit_callback + function="CommitSearch" /> + </check_box> + <icon + follows="right|top" + height="16" + image_name="Parcel_PG_Dark" + layout="topleft" + left_pad="2" + name="rating_icon_general" + top_delta="-1" + width="18"/> + <check_box + control_name="ShowMatureClassifieds" + follows="right|top" + height="16" + label="" + layout="topleft" + left_pad="2" + name="mature_all" + top_delta="1" + width="15"> + <check_box.commit_callback + function="CommitSearch" /> + </check_box> + <icon + follows="right|top" + height="16" + image_name="Parcel_M_Dark" + layout="topleft" + left_pad="2" + name="rating_icon_moderate" + top_delta="-1" + width="18"/> + <check_box + control_name="ShowAdultClassifieds" + follows="right|top" + height="16" + label="" + layout="topleft" + left_pad="2" + name="adult_all" + top_delta="1" + width="15"> + <check_box.commit_callback + function="CommitSearch" /> + </check_box> + <icon + follows="right|top" + height="16" + image_name="Parcel_R_Dark" + layout="topleft" + left_pad="2" + name="rating_icon_adult" + top_delta="-1" + width="18"/> + </panel> + <!-- Search Pane --> + <panel + border="true" + follows="all" + height="510" + layout="topleft" + left="1" + width="410" + top_pad="1" + name="panel_ls_scrolllist"> + <scroll_list + draw_heading="true" + follows="all" + height="485" + layout="topleft" + left="0" + name="search_results_classifieds" + top="0" + width="410"> + <columns + label="" + name="icon" + width="20" /> + <columns + label="Name" + name="classified_name" + relwidth="0.70" /> + <columns + label="Listing Price" + name="price" + relwidth="0.3"/> + </scroll_list> + <button + layout="topleft" + follows="left|bottom" + height="23" + label="Back" + name="classifieds_back" + top_pad="2" + left="3" + width="100" /> + <button + layout="topleft" + follows="left|bottom" + height="23" + label="Next" + name="classifieds_next" + width="100" + left_pad="1" /> + </panel> +</panel> diff --git a/indra/newview/skins/default/xui/en/panel_fs_search_legacy_events.xml b/indra/newview/skins/default/xui/en/panel_fs_search_legacy_events.xml new file mode 100644 index 0000000000..57cb4990e4 --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_fs_search_legacy_events.xml @@ -0,0 +1,258 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<panel + border="false" + follows="all" + height="566" + layout="topleft" + left="1" + width="780" + label="Events" + name="panel_ls_events"> + <panel + border="false" + follows="top|left|right" + height="53" + layout="topleft" + left="0" + width="780" + name="panel_ls_input"> + <text + type="string" + length="1" + follows="left|top" + top_pad="5" + layout="topleft" + left="6" + name="search_text" + top="12" + height="16" + width="156"> + Enter search terms: + </text> + <radio_group + left_pad="20" + height="16" + width="300" + layout="topleft" + name="events_search_mode"> + <radio_item + height="16" + label="Ongoing and Upcoming" + layout="topleft" + name="current" + value="current" + top_pad="0" + width="120" /> + <radio_item + height="16" + label="By Date" + layout="topleft" + name="date" + value="date" + left_pad="70" + width="120" /> + <radio_group.commit_callback + function="CommitSearch" /> + </radio_group> + <text + type="string" + length="1" + follows="left|top" + top_delta="0" + layout="topleft" + left_pad="5" + name="events_date" + font.style="BOLD" + height="16" + width="80"> + 4/20 + </text> + <search_combo_box + layout="topleft" + follows="left|top|right" + height="23" + left="6" + name="events_edit" + top="29" + width="651" /> + <combo_box + follows="right|top" + layout="topleft" + height="23" + top_delta="0" + left_pad="2" + name="events_category" + width="122"> + <combo_box.item label="Any Category" name="any" value="0" /> + <combo_box.item label="" value="filter_separator" enabled="false" /> + <combo_box.item label="Discussion" name="discussion" value="18" /> + <combo_box.item label="Sports" name="sports" value="19" /> + <combo_box.item label="Live DJ" name="dj" value="30" /> + <combo_box.item label="Live Music" name="music" value="20" /> + <!-- <combo_box.item label="???" name="mystery_category" value="21" /> --> + <combo_box.item label="Commercial" name="commercial" value="22" /> + <combo_box.item label="Nightlife/Entertainment" name="nightlife" value="23" /> + <combo_box.item label="Games/Contests" name="games" value="24" /> + <combo_box.item label="Pageants" name="pageants" value="25" /> + <combo_box.item label="Education" name="education" value="26" /> + <combo_box.item label="Arts and Culture" name="arts" value="27" /> + <combo_box.item label="Charity/Support Groups" name="charity" value="28" /> + <combo_box.item label="Miscellaneous" name="misc" value="29" /> + <combo_box.commit_callback + function="CommitSearch" /> + </combo_box> + <check_box + control_name="ShowPGEvents" + follows="right|top" + height="16" + label="" + layout="topleft" + left="660" + name="pg_all" + top="12" + width="15" > + <check_box.commit_callback + function="CommitSearch" /> + </check_box> + <icon + follows="right|top" + height="16" + image_name="Parcel_PG_Dark" + layout="topleft" + left_pad="2" + name="rating_icon_general" + top_delta="-1" + width="18"/> + <check_box + control_name="ShowMatureEvents" + follows="right|top" + height="16" + label="" + layout="topleft" + left_pad="2" + name="mature_all" + top_delta="1" + width="15"> + <check_box.commit_callback + function="CommitSearch" /> + </check_box> + <icon + follows="right|top" + height="16" + image_name="Parcel_M_Dark" + layout="topleft" + left_pad="2" + name="rating_icon_moderate" + top_delta="-1" + width="18"/> + <check_box + control_name="ShowAdultEvents" + follows="right|top" + height="16" + label="" + layout="topleft" + left_pad="2" + name="adult_all" + top_delta="1" + width="15"> + <check_box.commit_callback + function="CommitSearch" /> + </check_box> + <icon + follows="right|top" + height="16" + image_name="Parcel_R_Dark" + layout="topleft" + left_pad="2" + name="rating_icon_adult" + top_delta="-1" + width="18"/> + </panel> + <!-- Search Pane --> + <panel + border="true" + follows="all" + height="510" + layout="topleft" + left="1" + width="410" + top_pad="1" + name="panel_ls_scrolllist"> + <scroll_list + draw_heading="true" + follows="all" + height="485" + layout="topleft" + left="0" + name="search_results_events" + sort_ascending="true" + sort_column="3" + top="0" + width="410"> + <columns + label="" + name="icon" + width="20" /> + <columns + label="Event Name" + name="name" + relwidth="0.72" /> + <columns + label="Date/Time" + name="date" + sort_column="time" + relwidth="0.28" /> + <columns + label="Time" + name="time" + width="0"/> + </scroll_list> + <button + layout="topleft" + follows="left|bottom" + height="23" + label="Yesterday" + name="events_yesterday" + top_pad="2" + left="3" + width="100" /> + <button + layout="topleft" + follows="left|bottom" + height="23" + label="Today" + name="events_today" + width="100" + left_pad="1" /> + <button + layout="topleft" + follows="left|bottom" + height="23" + label="Tomorrow" + name="events_tomorrow" + width="100" + left_pad="1" /> + <button + layout="topleft" + follows="left|bottom" + height="23" + image_bottom_pad="2" + image_overlay="Arrow_Left_Off" + image_overlay_alignment="left" + label="Back" + name="events_back" + width="25" + left_pad="1" /> + <button + layout="topleft" + follows="left|bottom" + height="23" + image_bottom_pad="2" + image_overlay="Arrow_Right_Off" + image_overlay_alignment="left" + label="Next" + name="events_next" + width="25" + left_pad="1" /> + </panel> +</panel> diff --git a/indra/newview/skins/default/xui/en/panel_fs_search_legacy_groups.xml b/indra/newview/skins/default/xui/en/panel_fs_search_legacy_groups.xml new file mode 100644 index 0000000000..90001952f7 --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_fs_search_legacy_groups.xml @@ -0,0 +1,159 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<panel + border="false" + follows="all" + height="566" + layout="topleft" + left="1" + width="780" + label="Groups" + name="panel_ls_groups"> + <panel + border="false" + follows="top|left|right" + height="53" + layout="topleft" + left="0" + width="780" + name="panel_ls_input"> + <text + type="string" + length="1" + follows="left|top" + top_pad="5" + layout="topleft" + left="6" + name="search_text" + top="12" + height="16" + width="156"> + Enter search terms: + </text> + <search_combo_box + layout="topleft" + follows="left|top|right" + height="23" + left_delta="0" + name="groups_edit" + top="29" + width="770"> + </search_combo_box> + <check_box + control_name="ShowPGGroups" + follows="right|top" + height="16" + label="" + layout="topleft" + left="660" + name="pg_all" + top="12" + width="15" + visible="false"/> + <icon + follows="right|top" + height="16" + image_name="Parcel_PG_Dark" + layout="topleft" + left_pad="2" + name="rating_icon_general" + top_delta="-1" + width="18" + visible="false"/> + <check_box + control_name="ShowMatureGroups" + follows="right|top" + height="16" + label="" + layout="topleft" + left_pad="2" + name="mature_all" + top_delta="1" + width="15" + visible="false"/> + <icon + follows="right|top" + height="16" + image_name="Parcel_M_Dark" + layout="topleft" + left_pad="2" + name="rating_icon_moderate" + top_delta="-1" + width="18" + visible="false"/> + <check_box + control_name="ShowAdultGroups" + follows="right|top" + height="16" + label="" + layout="topleft" + left_pad="2" + name="adult_all" + top_delta="1" + width="15" + visible="false"/> + <icon + follows="right|top" + height="16" + image_name="Parcel_R_Dark" + layout="topleft" + left_pad="2" + name="rating_icon_adult" + top_delta="-1" + width="18" + visible="false"/> + </panel> + <!-- Search Pane --> + <panel + border="true" + follows="all" + height="510" + layout="topleft" + left="1" + width="410" + top_pad="1" + name="panel_ls_scrolllist"> + <scroll_list + draw_heading="true" + follows="all" + height="485" + layout="topleft" + left="0" + name="search_results_groups" + top="0" + width="410"> + <columns + label="" + name="icon" + width="20" /> + <columns + label="Group Name" + name="group_name" + relwidth="0.72" /> + <columns + label="Members" + name="members" + relwidth="0.25" /> + <columns + label="Score" + name="score" + width="0" /> + </scroll_list> + <button + layout="topleft" + follows="left|bottom" + height="23" + label="Back" + name="groups_back" + top_pad="2" + left="3" + width="100" /> + <button + layout="topleft" + follows="left|bottom" + height="23" + label="Next" + name="groups_next" + width="100" + left_pad="1" /> + </panel> +</panel> diff --git a/indra/newview/skins/default/xui/en/panel_fs_search_legacy_land.xml b/indra/newview/skins/default/xui/en/panel_fs_search_legacy_land.xml new file mode 100644 index 0000000000..bb03a1e999 --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_fs_search_legacy_land.xml @@ -0,0 +1,281 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<panel + border="false" + follows="all" + height="566" + layout="topleft" + left="1" + width="780" + label="Land Sales" + name="panel_ls_land"> + <panel + border="false" + follows="top|left|right" + height="53" + layout="topleft" + left="0" + width="780" + name="panel_ls_input"> + <check_box + control_name="ShowPGLand" + follows="right|top" + height="16" + label="" + layout="topleft" + left="660" + name="pg_all" + top="12" + width="15"> + <check_box.commit_callback + function="CommitSearch" /> + </check_box> + <icon + follows="right|top" + height="16" + image_name="Parcel_PG_Dark" + layout="topleft" + left_pad="2" + name="rating_icon_general" + top_delta="-1" + width="18"/> + <check_box + control_name="ShowMatureLand" + follows="right|top" + height="16" + label="" + layout="topleft" + left_pad="2" + name="mature_all" + top_delta="1" + width="15"> + <check_box.commit_callback + function="CommitSearch" /> + </check_box> + <icon + follows="right|top" + height="16" + image_name="Parcel_M_Dark" + layout="topleft" + left_pad="2" + name="rating_icon_moderate" + top_delta="-1" + width="18"/> + <check_box + control_name="ShowAdultLand" + follows="right|top" + height="16" + label="" + layout="topleft" + left_pad="2" + name="adult_all" + top_delta="1" + width="15"> + <check_box.commit_callback + function="CommitSearch" /> + </check_box> + <icon + follows="right|top" + height="16" + image_name="Parcel_R_Dark" + layout="topleft" + left_pad="2" + name="rating_icon_adult" + top_delta="-1" + width="18"/> + <text + type="string" + length="1" + follows="left|top" + layout="topleft" + left="6" + name="search_text" + top="12" + height="16" + width="256"> + Enter search terms: + </text> + <combo_box + control_name="FindLandType" + follows="left|top" + layout="topleft" + height="23" + allow_text_entry="false" + top_pad="2" + left="6" + name="land_category" + width="122"> + <combo_box.item label="All Categories" name="All" value="All"/> + <combo_box.item label="Auction" name="Auction" value="Auction"/> + <combo_box.item label="Mainland Sales" name="Mainland" value="Mainland"/> + <combo_box.item label="Estate Sales" name="Estate" value="Estate"/> + <combo_box.commit_callback + function="CommitSearch" /> + </combo_box> + <check_box + control_name="FindLandPrice" + follows="left|top" + height="16" + label="Price <" + layout="topleft" + left_pad="3" + name="price_check" + top_delta="3" + width="40" > + <check_box.commit_callback + function="CommitSearch" /> + </check_box> + <line_editor + enabled_control="FindLandPrice" + bevel_style="none" + border_style="line" + border.border_thickness="0" + commit_on_focus_lost="false" + follows="left|top" + height="18" + left_pad="20" + name="edit_price" + top_delta="-1" + width="40" > + <line_editor.commit_callback + function="CommitSearch" /> + </line_editor> + <check_box + control_name="FindLandArea" + follows="left|top" + height="16" + label="Area >" + layout="topleft" + left_pad="3" + name="area_check" + top_delta="1" + width="40" > + <check_box.commit_callback + function="CommitSearch" /> + </check_box> + <line_editor + enabled_control="FindLandArea" + bevel_style="none" + border_style="line" + border.border_thickness="0" + commit_on_focus_lost="false" + follows="left|top" + height="18" + left_pad="20" + name="edit_area" + top_delta="-1" + width="40" > + <line_editor.commit_callback + function="CommitSearch" /> + </line_editor> + <text + type="string" + length="1" + follows="left|top" + layout="topleft" + left="365" + name="sort_text" + top="12" + height="16" + width="98"> + Sort results by: + </text> + <check_box + follows="left|top" + height="16" + label="Ascending" + layout="topleft" + left_pad="3" + name="ascending_check" + width="100" > + <check_box.commit_callback + function="CommitSearch" /> + </check_box> + <combo_box + follows="left|top" + layout="topleft" + height="23" + allow_text_entry="false" + left_delta="-102" + top_pad="1" + name="land_sort_combo" + width="118"> + <combo_box.item label="Name" name="Name_item" value="Name"/> + <combo_box.item label="Price" name="Price_item" value="Price"/> + <combo_box.item label="Price per meter" name="PPM_item" value="PPM"/> + <combo_box.item label="Area" name="Area_item" value="Area"/> + <combo_box.commit_callback + function="CommitSearch" /> + </combo_box> + <button + follows="top|right" + height="23" + label="Search" + layout="topleft" + left="678" + top_delta="0" + name="land_find" + width="100" /> + </panel> + <!-- Search Pane --> + <panel + border="true" + follows="all" + height="510" + layout="topleft" + left="1" + width="410" + top_pad="1" + name="panel_ls_scrolllist"> + <scroll_list + draw_heading="true" + follows="all" + height="485" + layout="topleft" + left="0" + name="search_results_land" + top="0" + width="410"> + <columns + label="" + name="icon" + width="20" /> + <columns + label="Name" + name="land_name" + relwidth="0.45" /> + <columns + label="Price" + name="price" + relwidth="0.1" /> + <columns + label="Area" + name="area" + relwidth="0.1" /> + <columns + label="L$/m" + name="ppm" + relwidth="0.1" /> + <columns + label="Type" + name="land_type" + relwidth="0.2" /> + </scroll_list> + <button + layout="topleft" + follows="left|bottom" + height="23" + label="Back" + name="land_back" + top_pad="2" + left="3" + width="100" /> + <button + layout="topleft" + follows="left|bottom" + height="23" + label="Next" + name="land_next" + width="100" + left_pad="1" /> + </panel> +</panel> diff --git a/indra/newview/skins/default/xui/en/panel_fs_search_legacy_people.xml b/indra/newview/skins/default/xui/en/panel_fs_search_legacy_people.xml new file mode 100644 index 0000000000..28df02a7e3 --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_fs_search_legacy_people.xml @@ -0,0 +1,89 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<panel + border="false" + follows="all" + height="566" + layout="topleft" + left="1" + width="780" + label="People" + name="panel_ls_people"> + <panel + border="false" + follows="top|left|right" + height="53" + layout="topleft" + left="0" + width="780" + name="panel_ls_input"> + <text + type="string" + length="1" + follows="left|top" + top_pad="5" + layout="topleft" + left="6" + name="search_text" + top="12" + height="16" + width="156"> + Enter search terms: + </text> + <search_combo_box + layout="topleft" + follows="left|top|right" + height="23" + left_delta="0" + name="people_edit" + top="29" + width="770"> + </search_combo_box> + </panel> + <!-- Search Pane --> + <panel + border="true" + follows="all" + height="510" + layout="topleft" + left="1" + width="410" + top_pad="1" + name="panel_ls_scrolllist"> + <scroll_list + content_type="Agents" + draw_heading="true" + follows="all" + height="485" + layout="topleft" + left="0" + name="search_results_people" + top="0" + width="410"> + <columns + label="" + name="icon" + width="20" /> + <columns + label="Name" + name="username" + relwidth="1" /> + </scroll_list> + <button + layout="topleft" + follows="left|bottom" + height="23" + label="Back" + name="people_back" + top_pad="2" + left="3" + width="100" /> + <button + layout="topleft" + follows="left|bottom" + height="23" + label="Next" + name="people_next" + width="100" + left_pad="1" /> + </panel> +</panel>
\ No newline at end of file diff --git a/indra/newview/skins/default/xui/en/panel_fs_search_legacy_places.xml b/indra/newview/skins/default/xui/en/panel_fs_search_legacy_places.xml new file mode 100644 index 0000000000..09c142b8fc --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_fs_search_legacy_places.xml @@ -0,0 +1,169 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<panel + border="false" + follows="all" + height="566" + layout="topleft" + left="1" + width="780" + label="Places" + name="panel_ls_places"> + <panel + border="false" + follows="top|left|right" + height="53" + layout="topleft" + left="0" + width="780" + name="panel_ls_input"> + <text + type="string" + length="1" + follows="left|top" + top_pad="5" + layout="topleft" + left="6" + name="search_text" + top="12" + height="16" + width="156"> + Enter search terms: + </text> + <search_combo_box + layout="topleft" + follows="left|top|right" + height="23" + left_delta="0" + name="places_edit" + top="29" + width="651" /> + <combo_box + follows="right|top" + layout="topleft" + height="23" + allow_text_entry="false" + top_delta="0" + left_pad="2" + name="places_category" + width="122"> + <combo_box.commit_callback + function="CommitSearch" /> + </combo_box> + <check_box + control_name="ShowPGSims" + follows="right|top" + height="16" + label="" + layout="topleft" + left="660" + name="pg_all" + top="12" + width="15"> + <check_box.commit_callback + function="CommitSearch" /> + </check_box> + <icon + follows="right|top" + height="16" + image_name="Parcel_PG_Dark" + layout="topleft" + left_pad="2" + name="rating_icon_general" + top_delta="-1" + width="18"/> + <check_box + control_name="ShowMatureSims" + follows="right|top" + height="16" + label="" + layout="topleft" + left_pad="2" + name="mature_all" + top_delta="1" + width="15"> + <check_box.commit_callback + function="CommitSearch" /> + </check_box> + <icon + follows="right|top" + height="16" + image_name="Parcel_M_Dark" + layout="topleft" + left_pad="2" + name="rating_icon_moderate" + top_delta="-1" + width="18"/> + <check_box + control_name="ShowAdultSims" + follows="right|top" + height="16" + label="" + layout="topleft" + left_pad="2" + name="adult_all" + top_delta="1" + width="15"> + <check_box.commit_callback + function="CommitSearch" /> + </check_box> + <icon + follows="right|top" + height="16" + image_name="Parcel_R_Dark" + layout="topleft" + left_pad="2" + name="rating_icon_adult" + top_delta="-1" + width="18"/> + </panel> + <!-- Search Pane --> + <panel + border="true" + follows="all" + height="510" + layout="topleft" + left="1" + width="410" + top_pad="1" + name="panel_ls_scrolllist"> + <scroll_list + draw_heading="true" + follows="all" + height="485" + layout="topleft" + left="0" + name="search_results_places" + top="0" + width="410"> + <columns + label="" + name="icon" + width="20" /> + <columns + label="Name" + name="place_name" + relwidth="0.81" /> + <columns + label="Traffic" + name="dwell" + relwidth="0.16" /> + </scroll_list> + <button + layout="topleft" + follows="left|bottom" + height="23" + label="Back" + name="places_back" + top_pad="2" + left="3" + width="100" /> + <button + layout="topleft" + follows="left|bottom" + height="23" + label="Next" + name="places_next" + width="100" + left_pad="1" /> + </panel> +</panel> diff --git a/indra/newview/skins/default/xui/en/panel_fs_search_legacy_web.xml b/indra/newview/skins/default/xui/en/panel_fs_search_legacy_web.xml new file mode 100644 index 0000000000..382a5e8945 --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_fs_search_legacy_web.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<panel +border="false" +follows="all" +height="566" +layout="topleft" +left="1" +width="780" +label="Websearch" +name="panel_ls_web"> + <web_browser + top="5" + bottom="-1" + left="5" + right="-5" + layout="topleft" + follows="all" + name="search_browser" + trusted_content="true" + start_url="about:blank" /> +</panel>
\ No newline at end of file diff --git a/indra/newview/skins/default/xui/en/panel_group_info_sidetray.xml b/indra/newview/skins/default/xui/en/panel_group_info_sidetray.xml index ad9dbd1156..da900c783b 100644 --- a/indra/newview/skins/default/xui/en/panel_group_info_sidetray.xml +++ b/indra/newview/skins/default/xui/en/panel_group_info_sidetray.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <panel -background_visible="true" +background_visible="false" follows="all" height="570" label="Group Profile" diff --git a/indra/newview/skins/default/xui/en/panel_landmark_info.xml b/indra/newview/skins/default/xui/en/panel_landmark_info.xml index af68bd7fee..e25145dd2a 100644 --- a/indra/newview/skins/default/xui/en/panel_landmark_info.xml +++ b/indra/newview/skins/default/xui/en/panel_landmark_info.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <panel - background_visible="true" + background_visible="false" follows="all" height="570" layout="topleft" @@ -83,7 +83,7 @@ value="Place Profile" width="280" /> <scroll_container - color="DkGray2" + color="Transparent" follows="all" height="534" layout="topleft" @@ -93,7 +93,7 @@ top_pad="9" width="324"> <panel - bg_alpha_color="DkGray2" + bg_alpha_color="Transparent" follows="left|top|right" height="654" layout="topleft" @@ -280,8 +280,8 @@ <line_editor text_readonly_color="white" enabled="false" - use_bg_color="true" - bg_color="DkGray0" + use_bg_color="false" + bg_color="Transparent" follows="left|top|right" height="22" layout="topleft" @@ -322,7 +322,7 @@ value="My notes:" width="290" /> <text_editor - bg_readonly_color="DkGray0" + bg_readonly_color="Transparent" follows="all" height="75" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/panel_login.xml b/indra/newview/skins/default/xui/en/panel_login.xml index 1801ae1f49..0682a5d680 100644 --- a/indra/newview/skins/default/xui/en/panel_login.xml +++ b/indra/newview/skins/default/xui/en/panel_login.xml @@ -6,7 +6,7 @@ name="panel_login" focus_root="true" background_visible="true" - bg_opaque_color="0.16 0.16 0.16 1" + bg_opaque_color="0.0 0.0 0.0 1" background_opaque="true" width="1024"> <panel.string @@ -41,7 +41,7 @@ <icon height="73" width="165" - image_name="login_sl_logo" + image_name="login_mp_logo" left="0" top="25" name="sl_logo_small" /> @@ -145,7 +145,6 @@ control_name="RememberPassword" follows="left|top" font="SansSerifMedium" - text_color="EmphasisColor" height="24" left="408" bottom_delta="0" diff --git a/indra/newview/skins/default/xui/en/panel_login_first.xml b/indra/newview/skins/default/xui/en/panel_login_first.xml index c906e2f96c..0a8ae48b02 100644 --- a/indra/newview/skins/default/xui/en/panel_login_first.xml +++ b/indra/newview/skins/default/xui/en/panel_login_first.xml @@ -6,7 +6,7 @@ name="panel_login" focus_root="true" background_visible="true" - bg_opaque_color="0.16 0.16 0.16 1" + bg_opaque_color="0.0 0.0 0.0 1" background_opaque="true" width="1024"> <panel.string @@ -61,7 +61,7 @@ height="105"> <icon height="94" - image_name="login_sl_logo" + image_name="login_mp_logo" left="0" name="sl_logo" top="0" /> @@ -179,7 +179,6 @@ control_name="RememberPassword" follows="left|top" font="SansSerifLarge" - text_color="EmphasisColor" height="24" left="262" bottom_delta="0" diff --git a/indra/newview/skins/default/xui/en/panel_navigation_bar.xml b/indra/newview/skins/default/xui/en/panel_navigation_bar.xml index 85cf4419a3..95787c16c5 100644 --- a/indra/newview/skins/default/xui/en/panel_navigation_bar.xml +++ b/indra/newview/skins/default/xui/en/panel_navigation_bar.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <panel - background_opaque="true" - background_visible="true" + background_opaque="false" + background_visible="false" bg_opaque_color="MouseGray" follows="left|top|right" height="34" @@ -19,18 +19,18 @@ left="0" top="0" height="34" - width="600"/> + width="800"/> <icon follows="all" image_name="NavBar_BG_NoFav_Bevel" mouse_opaque="false" name="bg_icon_no_fav_bevel" scale_image="true" - visible="false" + visible="true" left="0" top="0" height="34" - width="600"/> + width="800"/> <icon follows="all" image_name="NavBar_BG_NoNav_Bevel" @@ -41,7 +41,7 @@ left="0" top="0" height="34" - width="600"/> + width="800"/> <icon follows="all" image_name="NavBar Separator" diff --git a/indra/newview/skins/default/xui/en/panel_notify_textbox.xml b/indra/newview/skins/default/xui/en/panel_notify_textbox.xml index 27d0f7d383..544d90a84f 100644 --- a/indra/newview/skins/default/xui/en/panel_notify_textbox.xml +++ b/indra/newview/skins/default/xui/en/panel_notify_textbox.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <panel - background_visible="true" + background_visible="false" height="215" label="instant_message" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/panel_outfit_edit.xml b/indra/newview/skins/default/xui/en/panel_outfit_edit.xml index a0e3344304..dc8ac425b6 100644 --- a/indra/newview/skins/default/xui/en/panel_outfit_edit.xml +++ b/indra/newview/skins/default/xui/en/panel_outfit_edit.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <!-- Side tray Outfit Edit panel --> <panel - background_visible="true" + background_visible="false" border="false" height="600" follows="all" @@ -87,8 +87,8 @@ <!-- "HEADER WITH ICON, STATUS TEXT AND OUTFIT NAME" --> <panel - background_visible="true" - bg_alpha_color="DkGray2" + background_visible="false" + bg_alpha_color="MouseGray" bevel_style="none" follows="top|left|right" height="40" @@ -360,7 +360,7 @@ It is calculated as border_size + 2*UIResizeBarOverlap <!-- BUTTON BAR --> <panel - background_visible="true" + background_visible="false" bevel_style="none" follows="bottom|left|right" height="27" @@ -407,7 +407,7 @@ It is calculated as border_size + 2*UIResizeBarOverlap <!-- BUTTON BAR - WEARABLES ADDING MODE --> <panel - background_visible="true" + background_visible="false" bevel_style="none" follows="left|right|bottom" height="27" diff --git a/indra/newview/skins/default/xui/en/panel_outfit_gallery.xml b/indra/newview/skins/default/xui/en/panel_outfit_gallery.xml index 6bd491f7a3..6166268206 100644 --- a/indra/newview/skins/default/xui/en/panel_outfit_gallery.xml +++ b/indra/newview/skins/default/xui/en/panel_outfit_gallery.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <panel - background_visible="true" + background_visible="false" bg_alpha_color="DkGray" border="false" follows="all" @@ -46,7 +46,7 @@ top_pad="0"> </scroll_container> <panel - background_visible="true" + background_visible="false" follows="bottom|left|right" height="28" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/panel_outfits_inventory.xml b/indra/newview/skins/default/xui/en/panel_outfits_inventory.xml index d58c2ec2e9..8e21b4d5fe 100644 --- a/indra/newview/skins/default/xui/en/panel_outfits_inventory.xml +++ b/indra/newview/skins/default/xui/en/panel_outfits_inventory.xml @@ -1,9 +1,9 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <panel name="Outfits" - bg_alpha_color="DkGray" - bg_opaque_color="DkGray" - background_opaque="true" - background_visible="true" + bg_alpha_color="MouseGray" + bg_opaque_color="MouseGray" + background_opaque="false" + background_visible="false" follows="all" height="575" label="Things" @@ -37,7 +37,7 @@ filename="panel_outfit_gallery.xml" height="520" name="outfit_gallery_tab" - background_visible="true" + background_visible="false" help_topic="outfit_gallery_tab" follows="all" label="OUTFIT GALLERY" @@ -48,15 +48,15 @@ filename="panel_outfits_list.xml" height="520" name="outfitslist_tab" - background_visible="true" + background_visible="false" help_topic="my_outfits_tab" follows="all" label="MY OUTFITS" layout="topleft" width="315" /> <panel - background_visible="true" - bg_alpha_color="DkGray" + background_visible="false" + bg_alpha_color="MouseGray" class="panel_wearing" filename="panel_outfits_wearing.xml" follows="all" @@ -69,7 +69,7 @@ </tab_container> <panel - background_visible="true" + background_visible="false" follows="bottom|left|right" height="27" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/panel_outfits_list.xml b/indra/newview/skins/default/xui/en/panel_outfits_list.xml index 9281a21fbf..e8d8e8f3e2 100644 --- a/indra/newview/skins/default/xui/en/panel_outfits_list.xml +++ b/indra/newview/skins/default/xui/en/panel_outfits_list.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <panel - background_visible="true" + background_visible="false" bg_alpha_color="DkGray" border="false" follows="all" @@ -11,7 +11,7 @@ top="0" width="312"> <accordion - background_visible="true" + background_visible="false" bg_alpha_color="DkGray2" bg_opaque_color="DkGray2" @@ -31,7 +31,7 @@ value="You don't have any outfits yet. Try [secondlife:///app/search/all/ Search]"/> </accordion> <panel - background_visible="true" + background_visible="false" follows="bottom|left|right" height="28" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/panel_outfits_wearing.xml b/indra/newview/skins/default/xui/en/panel_outfits_wearing.xml index a486c03ac7..559917ec0a 100644 --- a/indra/newview/skins/default/xui/en/panel_outfits_wearing.xml +++ b/indra/newview/skins/default/xui/en/panel_outfits_wearing.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <panel - background_visible="true" + background_visible="false" bg_alpha_color="DkGray" follows="all" height="430" @@ -22,7 +22,7 @@ single_expansion="true" top="0" name="wearables_accordion" - background_visible="true" + background_visible="false" bg_alpha_color="DkGray2" width="309"> <accordion_tab @@ -63,7 +63,7 @@ </accordion_tab> </accordion> <panel - background_visible="true" + background_visible="false" follows="bottom|left|right" height="28" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/panel_people.xml b/indra/newview/skins/default/xui/en/panel_people.xml index c31e6c94ea..f1c03fdaa8 100644 --- a/indra/newview/skins/default/xui/en/panel_people.xml +++ b/indra/newview/skins/default/xui/en/panel_people.xml @@ -223,6 +223,8 @@ Learn about [https://community.secondlife.com/knowledgebase/joining-and-particip keep_one_selected="false" multi_select="true" name="avatar_list" + show_avatar_arrival_time="true" + show_avatar_distance="true" right="-1" top="2" /> </layout_panel> diff --git a/indra/newview/skins/default/xui/en/panel_place_profile.xml b/indra/newview/skins/default/xui/en/panel_place_profile.xml index 8f5292c531..9aa0907a38 100644 --- a/indra/newview/skins/default/xui/en/panel_place_profile.xml +++ b/indra/newview/skins/default/xui/en/panel_place_profile.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <panel - background_visible="true" + background_visible="false" follows="all" height="610" layout="topleft" @@ -188,17 +188,18 @@ value="Place Profile" width="280" /> <scroll_container - color="DkGray2" + color="Transparent" follows="all" height="575" layout="topleft" left="9" name="place_scroll" - opaque="true" + opaque="false" top_pad="9" width="324"> <panel - bg_alpha_color="DkGray2" + bg_alpha_color="Transparent" + background_visible="false" follows="left|top|right|bottom" height="597" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/panel_places.xml b/indra/newview/skins/default/xui/en/panel_places.xml index a3a2f7c47e..4d9a03823e 100644 --- a/indra/newview/skins/default/xui/en/panel_places.xml +++ b/indra/newview/skins/default/xui/en/panel_places.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <panel -background_visible="true" +background_visible="false" default_tab_group="1" follows="all" height="570" diff --git a/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml b/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml index 5d347397bf..cb3e0e4b6a 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml @@ -210,26 +210,60 @@ increment="8" initial_value="160" label="Draw distance:" - label_width="90" + label_width="187" layout="topleft" left="30" min_val="64" max_val="512" name="DrawDistance" top_delta="40" - width="330" /> + width="427" /> <text type="string" length="1" follows="left|top" height="12" layout="topleft" - left_delta="330" + left_delta="427" name="DrawDistanceMeterText2" top_delta="0" width="128"> m </text> + <slider + control_name="IndirectMaxNonImpostors" + name="IndirectMaxNonImpostors" + decimal_digits="0" + increment="1" + initial_value="12" + show_text="false" + min_val="1" + max_val="66" + label="Maximum number of animated avatars:" + follows="left|top" + layout="topleft" + height="16" + label_width="240" + left="30" + top_delta="40" + width="393"> + <slider.commit_callback + function="Pref.UpdateIndirectMaxNonImpostors" + parameter="IndirectNonImpostorsText" /> + </slider> + <text + type="string" + length="1" + follows="left|top" + height="16" + layout="topleft" + top_delta="0" + left_delta="397" + text_readonly_color="LabelDisabledColor" + name="IndirectMaxNonImpostorsText" + width="65"> + 0 + </text> <button height="23" diff --git a/indra/newview/skins/default/xui/en/panel_progress.xml b/indra/newview/skins/default/xui/en/panel_progress.xml index 242b96b695..0742cef7c7 100644 --- a/indra/newview/skins/default/xui/en/panel_progress.xml +++ b/indra/newview/skins/default/xui/en/panel_progress.xml @@ -163,7 +163,7 @@ line_spacing.pixels="2" name="logos_lbl" text_color="LoginProgressBoxTextColor"> - Second Life uses + Megapahit uses </text> </layout_panel> </layout_stack> diff --git a/indra/newview/skins/default/xui/en/panel_region_environment.xml b/indra/newview/skins/default/xui/en/panel_region_environment.xml index 6d23592948..6531233696 100644 --- a/indra/newview/skins/default/xui/en/panel_region_environment.xml +++ b/indra/newview/skins/default/xui/en/panel_region_environment.xml @@ -264,8 +264,7 @@ top_pad="1" halign="right" name="txt_alt1"> - Sky [INDEX] - [ALTITUDE]m + Sky [INDEX]
[ALTITUDE]m </text> <line_editor follows="left|top" @@ -310,8 +309,7 @@ top_pad="1" halign="right" name="txt_alt2"> - Sky [INDEX] - [ALTITUDE]m + Sky [INDEX]
[ALTITUDE]m </text> <line_editor follows="left|top" @@ -356,8 +354,7 @@ top_pad="1" halign="right" name="txt_alt3"> - Sky [INDEX] - [ALTITUDE]m + Sky [INDEX]
[ALTITUDE]m </text> <line_editor follows="left|top" diff --git a/indra/newview/skins/default/xui/en/panel_status_bar.xml b/indra/newview/skins/default/xui/en/panel_status_bar.xml index 4501e0df3a..80fa230bba 100644 --- a/indra/newview/skins/default/xui/en/panel_status_bar.xml +++ b/indra/newview/skins/default/xui/en/panel_status_bar.xml @@ -55,11 +55,11 @@ text_pad_left="6" tool_tip="Type the search term you are interested in here. Results will be displayed for partial fulltext matches within the menu." top="0"> - <search_button + <search_button top_pad="4" - left_pad="4" + left_pad="4" width="12" - height="12" + height="12" image_unselected="Search" image_selected="Search"/> <clear_button @@ -77,20 +77,20 @@ left="-398" width="185" top="1" - follows="right|top" + follows="right|top" name="balance_bg"> <text halign="center" font="SansSerifSmall" follows="all" height="18" - left="0" + left="0" name="balance" tool_tip="Click to refresh your L$ balance" v_pad="4" top="0" - wrap="false" - value="L$??" + wrap="false" + value="L$??" width="40" /> <button halign="center" @@ -185,4 +185,19 @@ top="2" name="volume_btn" width="16" /> + <button + type="string" + font="SansSerif" + label_color="FpsTextColor" + follows="right|top" + halign="center" + valign="center" + height="18" + top="1" + left_pad="4" + name="FpsText" + tool_tip="fps" + width="32"> + 60 + </text> </panel> diff --git a/indra/newview/skins/default/xui/en/sidepanel_appearance.xml b/indra/newview/skins/default/xui/en/sidepanel_appearance.xml index c898b0989e..c03fac4aad 100644 --- a/indra/newview/skins/default/xui/en/sidepanel_appearance.xml +++ b/indra/newview/skins/default/xui/en/sidepanel_appearance.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <panel -background_visible="true" +background_visible="false" default_tab_group="1" follows="all" height="570" @@ -25,8 +25,8 @@ width="333"> name="Changing outfits" value="Changing outfits" /> <panel - background_opaque="true" - background_visible="true" + background_opaque="false" + background_visible="false" bg_opaque_color="DkGray2" left="10" top="5" diff --git a/indra/newview/skins/default/xui/en/sidepanel_task_info.xml b/indra/newview/skins/default/xui/en/sidepanel_task_info.xml index 45bc73a0b7..471886aa0d 100644 --- a/indra/newview/skins/default/xui/en/sidepanel_task_info.xml +++ b/indra/newview/skins/default/xui/en/sidepanel_task_info.xml @@ -93,7 +93,7 @@ name="properties_panel" top="45" width="313" - background_visible="true" + background_visible="false" bg_alpha_color="DkGray2"> <text type="string" @@ -299,7 +299,7 @@ follows="left|top" layout="topleft" mouse_opaque="false" - background_visible="true" + background_visible="false" bg_alpha_color="DkGray" name="perms_inv" left="0" diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index 2d04b3e0fe..232586636b 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -7,8 +7,8 @@ <!-- Default Args - these arguments will be replaced in all strings --> <string name="SECOND_LIFE">Second Life</string> - <string name="APP_NAME">Second Life</string> - <string name="CAPITALIZED_APP_NAME">SECOND LIFE</string> + <string name="APP_NAME">Megapahit</string> + <string name="CAPITALIZED_APP_NAME">MEGAPAHIT</string> <string name="SECOND_LIFE_GRID">Second Life Grid</string> <string name="SUPPORT_SITE">Second Life Support Portal</string> @@ -71,7 +71,7 @@ Voice Server Version: [VOICE_VERSION] <string name="LocalTime">[month, datetime, local] [day, datetime, local] [year, datetime, local] [hour, datetime, local]:[min, datetime, local]:[second,datetime, local]</string> <string name="ErrorFetchingServerReleaseNotesURL">Error fetching server release notes URL.</string> <string name="BuildConfiguration">Build Configuration</string> - + <!-- progress --> <string name="ProgressRestoring">Restoring...</string> <string name="ProgressChangingResolution">Changing resolution...</string> @@ -114,10 +114,10 @@ Voice Server Version: [VOICE_VERSION] <string name="LoginFailedHeader">Login failed.</string> <string name="Quit">Quit</string> <string name="create_account_url">http://join.secondlife.com/?sourceid=[sourceid]</string> - + <string name="AgniGridLabel">Second Life Main Grid (Agni)</string> <string name="AditiGridLabel">Second Life Beta Test Grid (Aditi)</string> - + <string name="ViewerDownloadURL">http://secondlife.com/download</string> <string name="LoginFailedViewerNotPermitted"> The viewer you are using can no longer access Second Life. Please visit the following page to download a new viewer: @@ -209,7 +209,7 @@ If you feel this is an error, please contact support@secondlife.com</string> <string name="YouHaveBeenDisconnected">You have been disconnected from the region you were in.</string> <string name="SentToInvalidRegion">You were sent to an invalid region.</string> <string name="TestingDisconnect">Testing viewer disconnect</string> - + <!-- SLShare: User Friendly Filter Names Translation --> <string name="BlackAndWhite">Black & White</string> <string name="Colors1970">1970's Colors</string> @@ -222,7 +222,7 @@ If you feel this is an error, please contact support@secondlife.com</string> <string name="LensFlare">Lens Flare</string> <string name="Miniature">Miniature</string> <string name="Toycamera">Toy Camera</string> - + <!-- Tooltip --> <string name="TooltipPerson">Person</string><!-- Object under mouse pointer is an avatar --> <string name="TooltipNoName">(no name)</string> <!-- No name on an object --> @@ -259,10 +259,10 @@ If you feel this is an error, please contact support@secondlife.com</string> <string name="TooltipOutboxMixedStock">All items in a stock folder must have the same type and permission</string> <string name="TooltipOutfitNotInInventory">You can only put items or outfits from your personal inventory into "My outfits"</string> <string name="TooltipCantCreateOutfit">One or more items can't be used inside "My outfits"</string> - + <string name="TooltipDragOntoOwnChild">You can't move a folder into its child</string> <string name="TooltipDragOntoSelf">You can't move a folder into itself</string> - + <!-- tooltips for Urls --> <string name="TooltipHttpUrl">Click to view this web page</string> <string name="TooltipSLURL">Click to view this location's information</string> @@ -333,7 +333,7 @@ are allowed. <string name="ReleaseNotes">Release Notes</string> <!-- Always mark translate="false" for strings that are nothing but URLs, as they don't need translation. --> - <string name="RELEASE_NOTES_BASE_URL" translate="false">https://releasenotes.secondlife.com/viewer/</string> + <string name="RELEASE_NOTES_BASE_URL" translate="false">https://megapahit.net/</string> <!-- Indicates something is being loaded. Maybe should be merged with RetrievingData --> <string name="LoadingData">Loading...</string> @@ -370,7 +370,7 @@ are allowed. <string name="AssetUploadServerDifficulties">The server is experiencing unexpected difficulties.</string> <string name="AssetUploadServerUnavaliable">Service not available or upload timeout was reached.</string> <string name="AssetUploadRequestInvalid"> -Error in upload request. Please visit +Error in upload request. Please visit http://secondlife.com/support for help fixing this problem. </string> @@ -534,7 +534,7 @@ http://secondlife.com/support for help fixing this problem. <string name="ChangeYourDefaultAnimations">Change your default animations</string> <string name="ForceSitAvatar">Force your avatar to sit</string> <string name="ChangeEnvSettings">Change your environment settings</string> - + <string name="NotConnected">Not Connected</string> <string name="AgentNameSubst">(You)</string> <!-- Substitution for agent name --> <string name="JoinAnExperience"/><!-- intentionally blank --> @@ -2320,7 +2320,7 @@ For AI Character: Get the closest navigable point to the point provided. <!-- inventory --> <string name="InventoryNoMatchingItems">Didn't find what you're looking for? Try [secondlife:///app/search/all/[SEARCH_TERM] Search].</string> - <string name="InventoryNoMatchingRecentItems">Didn't find what you're looking for? Try [secondlife:///app/inventory/filters Show filters].</string> + <string name="InventoryNoMatchingRecentItems">Didn't find what you're looking for? Try [secondlife:///app/inventory/filters Show filters].</string> <string name="PlacesNoMatchingItems">To add a place to your landmarks, click the star to the right of the location name.</string> <string name="FavoritesNoMatchingItems">To add a place to your favorites, click the star to the right of the location name, then save the landmark to "Favorites bar".</string> <string name="MarketplaceNoListing">You have no listings yet.</string> @@ -2503,7 +2503,7 @@ If you continue to receive this message, please contact Second Life support for <string name="InvFolder Materials">Materials</string> <!-- are used for Friends and Friends/All folders in Inventory "Calling cards" folder. See EXT-694--> - <string name="InvFolder Friends">Friends</string> + <string name="InvFolder Friends">Friends</string> <string name="InvFolder All">All</string> <string name="no_attachments">No attachments worn</string> @@ -2672,7 +2672,7 @@ If you continue to receive this message, please contact Second Life support for <string name="UploadFailed">File upload failed: </string> <string name="ObjectOutOfRange">Script (object out of range)</string> <string name="ScriptWasDeleted">Script (deleted from inventory)</string> - + <!-- god tools --> <string name="GodToolsObjectOwnedBy">Object [OBJECT] owned by [OWNER]</string> @@ -2942,12 +2942,14 @@ Expected .wav, .tga, .bmp, .jpg, .jpeg, or .anim <string name="Linden Location">Linden Location</string> <string name="Adult">Adult</string> <string name="Arts&Culture">Arts & Culture</string> + <string name="Arts and Culture">Arts & Culture</string> <string name="Business">Business</string> <string name="Educational">Educational</string> <string name="Gaming">Gaming</string> <string name="Hangout">Hangout</string> <string name="Newcomer Friendly">Newcomer Friendly</string> <string name="Parks&Nature">Parks & Nature</string> + <string name="Parks and Nature">Parks & Nature</string> <string name="Residential">Residential</string> <!--<string name="Shopping">Shopping</string> --> <string name="Stage">Stage</string> @@ -3849,7 +3851,7 @@ Please reinstall viewer from https://secondlife.com/support/downloads/ and cont <string name="uploading_costs">Uploading costs L$ [AMOUNT]</string> <string name="this_costs">This costs L$ [AMOUNT]</string> - + <string name="buying_selected_land">This land costs</string> <string name="this_object_costs">This item costs</string> <string name="giving">You want to give</string> @@ -3930,7 +3932,7 @@ Abuse Report</string> <string name="New Daycycle">New Daycycle</string> <string name="New Water">New Water</string> <string name="New Sky">New Sky</string> - + <string name="/bow">/bow</string> <string name="/clap">/clap</string> @@ -4012,7 +4014,7 @@ Please check http://status.secondlifegrid.net to see if there is a known problem <string name="Accounting">Accounting</string> <string name="Notices">Notices</string> <string name="Chat">Chat</string> - + <!-- SL Membership --> <string name="BaseMembership">Base</string> <string name="PremiumMembership">Premium</string> @@ -4178,7 +4180,7 @@ Try enclosing path to the editor with double quotes. <!-- commands --> - <string + <string name="Command_360_Capture_Label">360 snapshot</string> <string name="Command_AboutLand_Label">About land</string> <string name="Command_Appearance_Label">Outfits</string> @@ -4211,7 +4213,7 @@ name="Command_360_Capture_Label">360 snapshot</string> <string name="Command_View_Label">Camera controls</string> <string name="Command_Voice_Label">Voice settings</string> - <string + <string name="Command_360_Capture_Tooltip">Capture a 360 equirectangular image</string> <string name="Command_AboutLand_Tooltip">Information about the land you're visiting</string> <string name="Command_Appearance_Tooltip">Change your avatar</string> @@ -4276,7 +4278,7 @@ name="Command_360_Capture_Tooltip">Capture a 360 equirectangular image</string> <!-- Spell check settings floater --> <string name="UserDictionary">[User]</string> - + <!-- Experience Tools strings --> <string name="experience_tools_experience">Experience</string> <string name="ExperienceNameNull">(no experience)</string> @@ -4312,7 +4314,7 @@ name="Command_360_Capture_Tooltip">Capture a 360 equirectangular image</string> <!-- PBR Materials --> <string name="Material Texture Name Header">Textures present this material: </string> - + <!-- Conversation log messages --> <string name="logging_calls_disabled_log_empty"> Conversations are not being logged. To begin keeping a log, choose "Save: Log only" or "Save: Log and transcripts" under Preferences > Chat. @@ -4335,7 +4337,7 @@ name="Command_360_Capture_Tooltip">Capture a 360 equirectangular image</string> <string name="Default">Default</string> <string name="none_paren_cap">(None)</string> <string name="no_limit">No limit</string> - + <string name="Mav_Details_MAV_FOUND_DEGENERATE_TRIANGLES"> The physics shape contains triangles which are too small. Try simplifying the physics model. </string> @@ -4375,4 +4377,20 @@ and report the problem. [https://community.secondlife.com/knowledgebase/english/error-messages-r520/#Section__3 Knowledge Base] </string> + <!-- megapahit strings --> + <string name="not_found">'[TEXT]' not found</string> + <string name="no_results">No results</string> + <string name="searching">Searching...</string> + <string name="all_categories">All Categories</string> + <string name="search_banned">Some terms in your search query were excluded due to content restrictions as clarified in the Community Standards.</string> + <string name="search_short">Your search terms were too short so no search was performed.</string> + <string name="search_disabled">Legacy Search has been disabled in this region.</string> + <string name="NotifyIncomingMessage">Incoming message from [NAME]...</string> + <string name="NearbyChatTitleChannel">Nearby chat (on channel [CHANNEL])</string> + <string name="AvatarTyping">Typing</string> + <string name="UnknownAvatar">Unknown Avatar</string> + <string name="NotAvailableOnPlatform">Not available on this platform</string> + <string name="NowPlaying">Now Playing</string> + <string name="GridInfoTitle">GRID INFO</string> + </strings> diff --git a/indra/newview/skins/default/xui/en/widgets/toolbar.xml b/indra/newview/skins/default/xui/en/widgets/toolbar.xml index 8345911525..51852dd6dd 100644 --- a/indra/newview/skins/default/xui/en/widgets/toolbar.xml +++ b/indra/newview/skins/default/xui/en/widgets/toolbar.xml @@ -9,9 +9,9 @@ read_only="false"> <button_panel name="button_panel" bg_opaque_image="Rounded_Rect" - background_visible="true" + background_visible="false" bg_opaque_image_overlay="MouseGray" - background_opaque="true"/> + background_opaque="false"/> <button_icon_and_text imgoverlay_label_space="7" label_color_selected="White" halign="left" diff --git a/indra/newview/skins/default/xui/es/language_settings.xml b/indra/newview/skins/default/xui/es/language_settings.xml index 997293a741..c345ad73ad 100644 --- a/indra/newview/skins/default/xui/es/language_settings.xml +++ b/indra/newview/skins/default/xui/es/language_settings.xml @@ -7,6 +7,7 @@ <string name="MacLocale">es_ES.UTF-8</string> <string name="DarwinLocale">es_ES.UTF-8</string> <string name="LinuxLocale">es_ES.UTF-8</string> + <string name="FreeBSDLocale">es_ES.UTF-8</string> <!-- datetimeToCodes["wkday"] = "%a"; // Thu diff --git a/indra/newview/skins/default/xui/es/strings.xml b/indra/newview/skins/default/xui/es/strings.xml index cd8e7687ae..c6c0e9e77d 100644 --- a/indra/newview/skins/default/xui/es/strings.xml +++ b/indra/newview/skins/default/xui/es/strings.xml @@ -1,6 +1,6 @@ <?xml version="1.0" ?> <strings> - <string name="CAPITALIZED_APP_NAME">SECOND LIFE</string> + <string name="CAPITALIZED_APP_NAME">MEGAPAHIT</string> <string name="SUPPORT_SITE">Portal de Soporte de Second Life</string> <string name="StartupDetectingHardware">Identificando el hardware...</string> <string name="StartupLoading">Instalando [APP_NAME]...</string> @@ -265,7 +265,7 @@ pueden adjuntarse a las notas.</string> <string name="NoneFound">No se ha encontrado.</string> <string name="RetrievingData">Reintentando...</string> <string name="ReleaseNotes">Notas de la versión</string> - <string name="RELEASE_NOTES_BASE_URL">https://releasenotes.secondlife.com/viewer/</string> + <string name="RELEASE_NOTES_BASE_URL">https://megapahit.net/</string> <string name="LoadingData">Cargando...</string> <string name="AvatarNameNobody">(nadie)</string> <string name="AvatarNameWaiting">(esperando)</string> diff --git a/indra/newview/skins/default/xui/fr/language_settings.xml b/indra/newview/skins/default/xui/fr/language_settings.xml index fdac9d65a7..0dc61fc258 100644 --- a/indra/newview/skins/default/xui/fr/language_settings.xml +++ b/indra/newview/skins/default/xui/fr/language_settings.xml @@ -7,6 +7,7 @@ <string name="MacLocale">fr_FR.UTF-8</string> <string name="DarwinLocale">fr_FR.UTF-8</string> <string name="LinuxLocale">fr_FR.UTF-8</string> + <string name="FreeBSDLocale">fr_FR.UTF-8</string> <!-- datetimeToCodes["wkday"] = "%a"; // Thu diff --git a/indra/newview/skins/default/xui/fr/strings.xml b/indra/newview/skins/default/xui/fr/strings.xml index 0a3fbeb603..737b570e98 100644 --- a/indra/newview/skins/default/xui/fr/strings.xml +++ b/indra/newview/skins/default/xui/fr/strings.xml @@ -1,8 +1,8 @@ <?xml version="1.0" ?> <strings> <string name="SECOND_LIFE">Second Life</string> - <string name="APP_NAME">Second Life</string> - <string name="CAPITALIZED_APP_NAME">SECOND LIFE</string> + <string name="APP_NAME">Megapahit</string> + <string name="CAPITALIZED_APP_NAME">MEGAPAHIT</string> <string name="SECOND_LIFE_GRID">Grille de Second Life</string> <string name="SUPPORT_SITE">Portail Assistance Second Life</string> <string name="StartupDetectingHardware">Détection du matériel...</string> @@ -268,7 +268,7 @@ peuvent être joints aux notes.</string> <string name="NoneFound">Aucun résultat.</string> <string name="RetrievingData">En cours d'extraction...</string> <string name="ReleaseNotes">Notes de version</string> - <string name="RELEASE_NOTES_BASE_URL">https://releasenotes.secondlife.com/viewer/</string> + <string name="RELEASE_NOTES_BASE_URL">https://megapahit.net/</string> <string name="LoadingData">Chargement...</string> <string name="AvatarNameNobody">(personne)</string> <string name="AvatarNameWaiting">(en attente)</string> diff --git a/indra/newview/skins/default/xui/it/language_settings.xml b/indra/newview/skins/default/xui/it/language_settings.xml index 5f448fa828..205ee3dbef 100644 --- a/indra/newview/skins/default/xui/it/language_settings.xml +++ b/indra/newview/skins/default/xui/it/language_settings.xml @@ -7,6 +7,7 @@ <string name="MacLocale">it_IT.UTF-8</string> <string name="DarwinLocale">it_IT.UTF-8</string> <string name="LinuxLocale">it_IT.UTF-8</string> + <string name="FreeBSDLocale">it_IT.UTF-8</string> <!-- datetimeToCodes["wkday"] = "%a"; // Thu diff --git a/indra/newview/skins/default/xui/it/strings.xml b/indra/newview/skins/default/xui/it/strings.xml index 178bb90ca6..69381ef00e 100644 --- a/indra/newview/skins/default/xui/it/strings.xml +++ b/indra/newview/skins/default/xui/it/strings.xml @@ -1,8 +1,8 @@ <?xml version="1.0" ?> <strings> <string name="SECOND_LIFE">Second Life</string> - <string name="APP_NAME">Second Life</string> - <string name="CAPITALIZED_APP_NAME">SECOND LIFE</string> + <string name="APP_NAME">Megapahit</string> + <string name="CAPITALIZED_APP_NAME">MEGAPAHIT</string> <string name="SUPPORT_SITE">Portale di supporto di Second Life</string> <string name="StartupDetectingHardware">Ricerca hardware...</string> <string name="StartupLoading">Caricamento di [APP_NAME]...</string> @@ -266,7 +266,7 @@ possono essere allegati ai biglietti.</string> <string name="NoneFound">Nessun risultato.</string> <string name="RetrievingData">Recupero dati in corso...</string> <string name="ReleaseNotes">Note sulla versione</string> - <string name="RELEASE_NOTES_BASE_URL">https://releasenotes.secondlife.com/viewer/</string> + <string name="RELEASE_NOTES_BASE_URL">https://megapahit.net/</string> <string name="LoadingData">In caricamento...</string> <string name="AvatarNameNobody">(nessuno)</string> <string name="AvatarNameWaiting">(in attesa)</string> diff --git a/indra/newview/skins/default/xui/ja/language_settings.xml b/indra/newview/skins/default/xui/ja/language_settings.xml index facae22acf..c6f9ae3e26 100644 --- a/indra/newview/skins/default/xui/ja/language_settings.xml +++ b/indra/newview/skins/default/xui/ja/language_settings.xml @@ -12,6 +12,9 @@ <string name="LinuxLocale"> ja_JP.UTF-8 </string> + <string name="FreeBSDLocale"> + ja_JP.UTF-8 + </string> <string name="TimeHour"> hour,datetime,slt </string> diff --git a/indra/newview/skins/default/xui/ja/strings.xml b/indra/newview/skins/default/xui/ja/strings.xml index fa6c329fe7..d04c514322 100644 --- a/indra/newview/skins/default/xui/ja/strings.xml +++ b/indra/newview/skins/default/xui/ja/strings.xml @@ -4,10 +4,10 @@ Second Life </string> <string name="APP_NAME"> - Second Life + Megapahit </string> <string name="CAPITALIZED_APP_NAME"> - SECOND LIFE + MEGAPAHIT </string> <string name="SECOND_LIFE_GRID"> Second Lifeグリッド @@ -617,7 +617,7 @@ support@secondlife.com にお問い合わせください。 リリースノート </string> <string name="RELEASE_NOTES_BASE_URL" translate="false"> - https://releasenotes.secondlife.com/viewer/ + https://megapahit.net/ </string> <string name="LoadingData"> 読み込んでいます… diff --git a/indra/newview/skins/default/xui/pl/language_settings.xml b/indra/newview/skins/default/xui/pl/language_settings.xml index 0057ca530c..b84d817aa5 100644 --- a/indra/newview/skins/default/xui/pl/language_settings.xml +++ b/indra/newview/skins/default/xui/pl/language_settings.xml @@ -4,6 +4,7 @@ <string name="MacLocale">pl_PL.UTF-8</string> <string name="DarwinLocale">pl_PL.UTF-8</string> <string name="LinuxLocale">pl_PL.UTF-8</string> + <string name="FreeBSDLocale">pl_PL.UTF-8</string> <string name="TimeHour">hour,datetime,slt</string> <string name="TimeMin">min,datetime,slt</string> <string name="TimeSec">second,datetime,slt</string> diff --git a/indra/newview/skins/default/xui/pt/language_settings.xml b/indra/newview/skins/default/xui/pt/language_settings.xml index 8799475ace..e31af58455 100644 --- a/indra/newview/skins/default/xui/pt/language_settings.xml +++ b/indra/newview/skins/default/xui/pt/language_settings.xml @@ -7,6 +7,7 @@ <string name="MacLocale">pt_PT.UTF-8</string> <string name="DarwinLocale">pt_PT.UTF-8</string> <string name="LinuxLocale">pt_PT.UTF-8</string> + <string name="FreeBSDLocale">pt_PT.UTF-8</string> <!-- datetimeToCodes["wkday"] = "%a"; // Thu diff --git a/indra/newview/skins/default/xui/pt/strings.xml b/indra/newview/skins/default/xui/pt/strings.xml index 6db5da2e89..0b12dd2aa0 100644 --- a/indra/newview/skins/default/xui/pt/strings.xml +++ b/indra/newview/skins/default/xui/pt/strings.xml @@ -1,6 +1,6 @@ <?xml version="1.0" ?> <strings> - <string name="CAPITALIZED_APP_NAME">SECOND LIFE</string> + <string name="CAPITALIZED_APP_NAME">MEGAPAHIT</string> <string name="SUPPORT_SITE">Portal de Supporte Second Life</string> <string name="StartupDetectingHardware">Detectando hardware...</string> <string name="StartupLoading">Carregando [APP_NAME]...</string> @@ -230,7 +230,7 @@ ser anexado às anotações.</string> <string name="NoneFound">Não encontrado.</string> <string name="RetrievingData">Buscando...</string> <string name="ReleaseNotes">Notas de versão</string> - <string name="RELEASE_NOTES_BASE_URL">https://releasenotes.secondlife.com/viewer/</string> + <string name="RELEASE_NOTES_BASE_URL">https://megapahit.net/</string> <string name="LoadingData">Carregando...</string> <string name="AvatarNameNobody">(ninguém)</string> <string name="AvatarNameWaiting">(aguardando)</string> diff --git a/indra/newview/skins/default/xui/ru/strings.xml b/indra/newview/skins/default/xui/ru/strings.xml index 61d836a2d1..649d5e7107 100644 --- a/indra/newview/skins/default/xui/ru/strings.xml +++ b/indra/newview/skins/default/xui/ru/strings.xml @@ -8,10 +8,10 @@ Second Life </string> <string name="APP_NAME"> - Second Life + Megapahit </string> <string name="CAPITALIZED_APP_NAME"> - SECOND LIFE + MEGAPAHIT </string> <string name="SECOND_LIFE_GRID"> Сетка Second Life diff --git a/indra/newview/skins/default/xui/tr/strings.xml b/indra/newview/skins/default/xui/tr/strings.xml index e709a4c5d6..f80d8e3382 100644 --- a/indra/newview/skins/default/xui/tr/strings.xml +++ b/indra/newview/skins/default/xui/tr/strings.xml @@ -8,10 +8,10 @@ Second Life </string> <string name="APP_NAME"> - Second Life + Megapahit </string> <string name="CAPITALIZED_APP_NAME"> - SECOND LIFE + MEGAPAHIT </string> <string name="SECOND_LIFE_GRID"> Second Life Ağı diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index 470c8bc8a8..4888b70f0a 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -65,6 +65,8 @@ class ViewerManifest(LLManifest): self.path(src="../../scripts/messages/message_template.msg", dst="app_settings/message_template.msg") self.path(src="../../etc/message.xml", dst="app_settings/message.xml") + os.environ["XZ_DEFAULTS"] = "-T0" + if self.is_packaging_viewer(): with self.prefix(src_dst="app_settings"): self.exclude("logcontrol.xml") @@ -1199,6 +1201,381 @@ class Darwin_x86_64_Manifest(ViewerManifest): self.set_github_output_path('viewer_app', tarpath) +class Darwin_arm64_Manifest(ViewerManifest): + build_data_json_platform = 'mac' + address_size = 64 + + def finish_build_data_dict(self, build_data_dict): + build_data_dict.update({'Bundle Id':self.args['bundleid']}) + return build_data_dict + + def is_packaging_viewer(self): + # darwin requires full app bundle packaging even for debugging. + return True + + def is_rearranging(self): + # That said, some stuff should still only be performed once. + # Are either of these actions in 'actions'? Is the set intersection + # non-empty? + return bool(set(["package", "unpacked"]).intersection(self.args['actions'])) + + def construct(self): + # copy over the build result (this is a no-op if run within the xcode + # script) + self.path(os.path.join(self.args['configuration'], self.channel() + ".app"), dst="") + + pkgdir = os.path.join(self.args['build'], os.pardir, 'packages') + relpkgdir = os.path.join(pkgdir, "lib", "release") + debpkgdir = os.path.join(pkgdir, "lib", "debug") + + with self.prefix(src="", dst="Contents"): # everything goes in Contents + bugsplat_db = self.args.get('bugsplat') + if bugsplat_db: + # Inject BugsplatServerURL into Info.plist if provided. + Info_plist = self.dst_path_of("Info.plist") + with open(Info_plist, 'rb') as f: + Info = plistlib.load(f) + # https://www.bugsplat.com/docs/platforms/os-x#configuration + Info["BugsplatServerURL"] = \ + "https://{}.bugsplat.com/".format(bugsplat_db) + self.put_in_file( + plistlib.dumps(Info), + os.path.basename(Info_plist), + "Info.plist") + + # CEF framework goes inside 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) + + if self.args.get('bugsplat'): + self.path2basename(relpkgdir, "BugsplatMac.framework") + + with self.prefix(dst="MacOS"): + executable = self.dst_path_of(self.channel()) + if self.args.get('bugsplat'): + # According to Apple Technical Note TN2206: + # https://developer.apple.com/library/archive/technotes/tn2206/_index.html#//apple_ref/doc/uid/DTS40007919-CH1-TNTAG207 + # "If an app uses @rpath or an absolute path to link to a + # dynamic library outside of the app, the app will be + # rejected by Gatekeeper. ... Neither the codesign nor the + # spctl tool will show the error." + # (Thanks, Apple. Maybe fix spctl to warn?) + # The BugsplatMac framework embeds @rpath, which is + # causing scary Gatekeeper popups at viewer start. Work + # around this by changing the reference baked into our + # viewer. The install_name_tool -change option needs the + # previous value. Instead of guessing -- which might + # silently be defeated by a BugSplat SDK update that + # changes their baked-in @rpath -- ask for the path + # stamped into the framework. + # Let exception, if any, propagate -- if this doesn't + # work, we need the build to noisily fail! + oldpath = subprocess.check_output( + ['objdump', '--macho', '--dylib-id', '--non-verbose', + os.path.join(relpkgdir, "BugsplatMac.framework", "BugsplatMac")], + text=True + ).splitlines()[-1] # take the last line of output + self.run_command( + ['install_name_tool', '-change', oldpath, + '@executable_path/../Frameworks/BugsplatMac.framework/BugsplatMac', + executable]) + + # 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. + if ("package" in self.args['actions'] or + "unpacked" in self.args['actions']): + self.run_command( + ['strip', '-S', executable]) + + with self.prefix(dst="Resources"): + # defer cross-platform file copies until we're in the + # nested Resources directory + super().construct() + + # need .icns file referenced by Info.plist + with self.prefix(src=self.icon_path(), dst="") : + self.path("secondlife.icns") + + # Copy in the updater script and helper modules + self.path(src=os.path.join(pkgdir, 'VMP'), dst="updater") + + with self.prefix(src="", dst=os.path.join("updater", "icons")): + self.path2basename(self.icon_path(), "secondlife.ico") + with self.prefix(src="vmp_icons", dst=""): + self.path("*.png") + self.path("*.gif") + + with self.prefix(src=relpkgdir, dst=""): + self.path("libndofdev.dylib") + self.path("libhunspell-*.dylib") + + with self.prefix(src_dst="cursors_mac"): + self.path("*.tif") + + self.path("licenses-mac.txt", dst="licenses.txt") + self.path("featuretable_mac.txt") + self.path("cube.dae") + self.path("SecondLife.nib") + + with self.prefix(src=pkgdir,dst=""): + self.path("ca-bundle.crt") + + # Translations + self.path("English.lproj/language.txt") + self.replace_in(src="English.lproj/InfoPlist.strings", + dst="English.lproj/InfoPlist.strings", + searchdict={'%%VERSION%%':'.'.join(self.args['version'])} + ) + self.path("German.lproj") + self.path("Japanese.lproj") + self.path("Korean.lproj") + self.path("da.lproj") + self.path("es.lproj") + self.path("fr.lproj") + self.path("hu.lproj") + self.path("it.lproj") + self.path("nl.lproj") + self.path("pl.lproj") + self.path("pt.lproj") + self.path("ru.lproj") + self.path("tr.lproj") + self.path("uk.lproj") + self.path("zh-Hans.lproj") + + def path_optional(src, dst): + """ + For a number of our self.path() calls, not only do we want + to deal with the absence of src, we also want to remember + which were present. Return either an empty list (absent) + or a list containing dst (present). Concatenate these + return values to get a list of all libs that are present. + """ + # This was simple before we started needing to pass + # wildcards. Fortunately, self.path() ends up appending a + # (source, dest) pair to self.file_list for every expanded + # file processed. Remember its size before the call. + oldlen = len(self.file_list) + try: + self.path(src, dst) + # The dest appended to self.file_list has been prepended + # with self.get_dst_prefix(). Strip it off again. + added = [os.path.relpath(d, self.get_dst_prefix()) + for s, d in self.file_list[oldlen:]] + except MissingError as err: + print("Warning: "+err.msg, file=sys.stderr) + added = [] + if not added: + print("Skipping %s" % dst) + return added + + # dylibs is a list of all the .dylib files we expect to need + # in our bundled sub-apps. For each of these we'll create a + # symlink from sub-app/Contents/Resources to the real .dylib. + # Need to get the llcommon dll from any of the build directories as well. + libfile_parent = self.get_dst_prefix() + dylibs=[] + for libfile in ( + "libapr-1.0.dylib", + "libaprutil-1.0.dylib", + "libexpat.1.dylib", + # libnghttp2.dylib is a symlink to + # libnghttp2.major.dylib, which is a symlink to + # libnghttp2.version.dylib. Get all of them. + "libnghttp2.*dylib", + "liburiparser.*dylib", + ): + dylibs += path_optional(os.path.join(relpkgdir, libfile), libfile) + + # SLVoice executable + with self.prefix(src=os.path.join(pkgdir, 'bin', 'release')): + self.path("SLVoice") + + # Vivox libraries + for libfile in ( + 'libortp.dylib', + 'libvivoxsdk.dylib', + ): + self.path2basename(relpkgdir, libfile) + + # Fmod studio dylibs (vary based on configuration) + if self.args['fmodstudio'] == 'ON': + if self.args['buildtype'].lower() == 'debug': + for libfile in ( + "libfmodL.dylib", + ): + dylibs += path_optional(os.path.join(debpkgdir, libfile), libfile) + else: + for libfile in ( + "libfmod.dylib", + ): + dylibs += path_optional(os.path.join(relpkgdir, libfile), libfile) + + # our apps + executable_path = {} + embedded_apps = [ (os.path.join("llplugin", "slplugin"), "SLPlugin.app") ] + for app_bld_dir, app in embedded_apps: + self.path2basename(os.path.join(os.pardir, + app_bld_dir, self.args['configuration']), + app) + executable_path[app] = \ + self.dst_path_of(os.path.join(app, "Contents", "MacOS")) + + # our apps dependencies on shared libs + # for each app, for each dylib we collected in dylibs, + # create a symlink to the real copy of the dylib. + with self.prefix(dst=os.path.join(app, "Contents", "Resources")): + for libfile in dylibs: + self.relsymlinkf(os.path.join(libfile_parent, libfile)) + + # Dullahan helper apps go inside SLPlugin.app + with self.prefix(dst=os.path.join( + "SLPlugin.app", "Contents", "Frameworks")): + + frameworkname = 'Chromium Embedded Framework' + + # This code constructs a relative symlink from the + # target framework folder back to the real CEF framework. + # It needs to be relative so that the symlink still works when + # (as is normal) the user moves the app bundle out of the DMG + # and into the /Applications folder. Note we pass catch=False, + # letting the uncaught exception terminate the process, since + # without this symlink, Second Life web media can't possibly work. + + # It might seem simpler just to symlink Frameworks back to + # the parent of Chromimum Embedded Framework.framework. But + # that would create a symlink cycle, which breaks our + # packaging step. So make a symlink from Chromium Embedded + # Framework.framework to the directory of the same name, which + # is NOT an ancestor of the symlink. + + # from SLPlugin.app/Contents/Frameworks/Chromium Embedded + # Framework.framework back to + # $viewer_app/Contents/Frameworks/Chromium Embedded Framework.framework + SLPlugin_framework = self.relsymlinkf(CEF_framework, catch=False) + + # for all the multiple CEF/Dullahan (as of CEF 76) helper app bundles we need: + for helper in ( + "DullahanHelper", + "DullahanHelper (GPU)", + "DullahanHelper (Renderer)", + "DullahanHelper (Plugin)", + ): + # app is the directory name of the app bundle, with app/Contents/MacOS/helper as the executable + app = helper + ".app" + + # copy DullahanHelper.app + self.path2basename(relpkgdir, app) + + # and fix that up with a Frameworks/CEF symlink too + with self.prefix(dst=os.path.join( + app, 'Contents', 'Frameworks')): + # from Dullahan Helper *.app/Contents/Frameworks/Chromium Embedded + # Framework.framework back to + # SLPlugin.app/Contents/Frameworks/Chromium Embedded Framework.framework + # Since SLPlugin_framework is itself a + # symlink, don't let relsymlinkf() resolve -- + # explicitly call relpath(symlink=True) and + # create that symlink here. + helper_framework = \ + self.symlinkf(self.relpath(SLPlugin_framework, symlink=True), catch=False) + + # change_command includes install_name_tool, the + # -change subcommand and the old framework rpath + # stamped into the executable. To use it with + # run_command(), we must still append the new + # framework path and the pathname of the + # executable to change. + change_command = [ + 'install_name_tool', '-change', + '@rpath/Frameworks/Chromium Embedded Framework.framework/Chromium Embedded Framework'] + + with self.prefix(dst=os.path.join( + app, 'Contents', 'MacOS')): + # Now self.get_dst_prefix() is, at runtime, + # @executable_path. Locate the helper app + # framework (which is a symlink) from here. + newpath = os.path.join( + '@executable_path', + self.relpath(helper_framework, symlink=True), + frameworkname) + # and restamp the Dullahan Helper executable itself + self.run_command( + change_command + + [newpath, self.dst_path_of(helper)]) + + # SLPlugin plugins + with self.prefix(dst="llplugin"): + dylibexecutable = 'media_plugin_cef.dylib' + self.path2basename("../media_plugins/cef/" + self.args['configuration'], + dylibexecutable) + + # Do this install_name_tool *after* media plugin is copied over. + # Locate the framework lib executable -- relative to + # SLPlugin.app/Contents/MacOS, which will be our + # @executable_path at runtime! + newpath = os.path.join( + '@executable_path', + self.relpath(SLPlugin_framework, executable_path["SLPlugin.app"], + symlink=True), + frameworkname) + # restamp media_plugin_cef.dylib + self.run_command( + change_command + + [newpath, self.dst_path_of(dylibexecutable)]) + + # copy LibVLC plugin itself + dylibexecutable = 'media_plugin_libvlc.dylib' + self.path2basename("../media_plugins/libvlc/" + self.args['configuration'], dylibexecutable) + # add @rpath for the correct LibVLC subfolder + self.run_command(['install_name_tool', '-add_rpath', '@loader_path/lib', self.dst_path_of(dylibexecutable)]) + + # copy LibVLC dynamic libraries + with self.prefix(src=relpkgdir, dst="lib"): + self.path( "libvlc*.dylib*" ) + # copy LibVLC plugins folder + with self.prefix(src='plugins', dst=""): + self.path( "*.dylib" ) + self.path( "plugins.dat" ) + + def package_finish(self): + imagename = self.installer_base_name() + self.set_github_output('imagename', imagename) + finalname = imagename + ".dmg" + self.package_file = finalname + + RUNNER_TEMP = os.getenv('RUNNER_TEMP') + # When running as a GitHub Action job, RUNNER_TEMP is the recommended + # temp directory. If we're not running on GitHub, don't create this + # temp directory or this tarball: we don't clean them up, trusting + # that the runner is itself transient. On a dev machine, that would + # result in temp-directory clutter. + if RUNNER_TEMP: + # Per GitHub's actions/upload-artifact documentation + # https://github.com/actions/upload-artifact#maintaining-file-permissions-and-case-sensitive-files + # we must package the app bundle with tar before posting as an + # artifact. Posting individual files follows symlinks, which + # causes problems, especially with frameworks: a framework's top + # level must contain symlinks into its Versions/Current, which + # must itself be a symlink to some specific Versions subdir. + tarpath = os.path.join(RUNNER_TEMP, "viewer.tar.xz") + print(f'Creating {tarpath} from {self.get_dst_prefix()}') + with tarfile.open(tarpath, mode="w:xz") as tarball: + # Store in the tarball as just 'Second Life Mumble.app' + # instead of 'Users/someone/.../newview/Release/Second...' + # It's at this point that we rename 'Second Life Release.app' + # to 'Second Life Viewer.app'. + tarball.add(self.get_dst_prefix(), + arcname=self.app_name() + ".app") + self.set_github_output_path('viewer_app', tarpath) + + class LinuxManifest(ViewerManifest): build_data_json_platform = 'lnx' @@ -1206,6 +1583,9 @@ class LinuxManifest(ViewerManifest): super(LinuxManifest, self).construct() pkgdir = os.path.join(self.args['build'], os.pardir, 'packages') + if "package_dir" in self.args: + pkgdir = self.args['package_dir'] + relpkgdir = os.path.join(pkgdir, "lib", "release") debpkgdir = os.path.join(pkgdir, "lib", "debug") @@ -1224,49 +1604,123 @@ class LinuxManifest(ViewerManifest): with self.prefix(dst="bin"): self.path("secondlife-bin","do-not-directly-run-secondlife-bin") - self.path("../linux_crash_logger/linux-crash-logger","linux-crash-logger.bin") + #self.path("../linux_crash_logger/linux-crash-logger","linux-crash-logger.bin") self.path2basename("../llplugin/slplugin", "SLPlugin") #this copies over the python wrapper script, associated utilities and required libraries, see SL-321, SL-322 and SL-323 - with self.prefix(src="../viewer_components/manager", dst=""): - self.path("*.py") + #with self.prefix(src="../viewer_components/manager", dst=""): + # self.path("*.py") # recurses, packaged again self.path("res-sdl") + # We copy ll_icon.BMP in CMakeLists.txt to newview/res-sdl and this will let the above self.path step take care of copying + # the correct branded icon # Get the icons based on the channel type icon_path = self.icon_path() - print("DEBUG: icon_path '%s'" % icon_path) + #print("DEBUG: icon_path '%s'" % icon_path) with self.prefix(src=icon_path) : self.path("secondlife_256.png","secondlife_icon.png") with self.prefix(dst="res-sdl") : self.path("secondlife_256.BMP","ll_icon.BMP") # plugins - with self.prefix(src="../media_plugins", dst="bin/llplugin"): - self.path("gstreamer010/libmedia_plugin_gstreamer010.so", - "libmedia_plugin_gstreamer.so") - self.path2basename("libvlc", "libmedia_plugin_libvlc.so") - - with self.prefix(src=os.path.join(pkgdir, 'lib', 'vlc', 'plugins'), dst="bin/llplugin/vlc/plugins"): - self.path( "plugins.dat" ) - self.path( "*/*.so" ) - - with self.prefix(src=os.path.join(pkgdir, 'lib' ), dst="lib"): - self.path( "libvlc*.so*" ) - - # llcommon - if not self.path("../llcommon/libllcommon.so", "lib/libllcommon.so"): - print("Skipping llcommon.so (assuming llcommon was linked statically)") + with self.prefix(src=os.path.join(self.args['build'], os.pardir, 'media_plugins'), dst="bin/llplugin"): + self.path("gstreamer10/libmedia_plugin_gstreamer10.so", "libmedia_plugin_gstreamer.so") + + + with self.prefix(src=os.path.join(self.args['build'], os.pardir, 'media_plugins'), dst="bin/llplugin"): + self.path("cef/libmedia_plugin_cef.so", "libmedia_plugin_cef.so" ) + with self.prefix(src=os.path.join(pkgdir, 'lib', 'release'), dst="lib"): + self.path( "libcef.so" ) + + self.path( "libEGL*" ) + self.path( "libvulkan*" ) + self.path( "libvk_swiftshader*" ) + self.path( "libGLESv2*" ) + self.path( "vk_swiftshader_icd.json") + + with self.prefix(src=os.path.join(pkgdir, 'bin', 'release'), dst="bin"): + self.path( "chrome-sandbox" ) + self.path( "dullahan_host" ) + self.path( "snapshot_blob.bin" ) + self.path( "v8_context_snapshot.bin" ) + with self.prefix(src=os.path.join(pkgdir, 'bin', 'release'), dst="lib"): + self.path( "snapshot_blob.bin" ) + self.path( "v8_context_snapshot.bin" ) + + with self.prefix(src=os.path.join(pkgdir, 'resources'), dst="lib"): + self.path( "chrome_100_percent.pak" ) + self.path( "chrome_200_percent.pak" ) + self.path( "resources.pak" ) + self.path( "icudtl.dat" ) + + with self.prefix(src=os.path.join(pkgdir, 'resources', 'locales'), dst=os.path.join('lib', '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") self.path("featuretable_linux.txt") self.path("cube.dae") - with self.prefix(src=pkgdir): + with self.prefix(src=pkgdir, dst="bin"): self.path("ca-bundle.crt") def package_finish(self): installer_name = self.installer_base_name() + # When running as a GitHub Action job, RUNNER_TEMP is defined as the tmp dir + RUNNER_TEMP = os.getenv('RUNNER_TEMP') + self.strip_binaries() # Fix access permissions @@ -1281,64 +1735,79 @@ class LinuxManifest(ViewerManifest): # temporarily move directory tree so that it has the right # name in the tarfile realname = self.get_dst_prefix() - tempname = self.build_path_of(installer_name) - self.run_command(["mv", realname, tempname]) + versionedName = self.build_path_of(installer_name) + + tarName = versionedName + ".tar.xz" + + # If using a github runner we divert packaging a little. Considering this wil be a VM/docker image + # we can just pack the final installer into RUNNER_TEMP and not into the usual stop we'd pick when + # not building a GHA release + if RUNNER_TEMP: + tarName = os.path.join(RUNNER_TEMP, self.package_file) + + self.run_command(["mv", realname, versionedName]) + try: # only create tarball if it's a release build. if self.args['buildtype'].lower() == 'release': - # --numeric-owner hides the username of the builder for - # security etc. self.run_command(['tar', '-C', self.get_build_prefix(), '--numeric-owner', '-cJf', - tempname + '.tar.xz', installer_name]) + tarName, installer_name]) + self.set_github_output_path('viewer_app', tarName) else: print("Skipping %s.tar.xz for non-Release build (%s)" % \ (installer_name, self.args['buildtype'])) finally: - self.run_command(["mv", tempname, realname]) + self.run_command(["mv", versionedName, realname]) def strip_binaries(self): + doStrip = False if self.args['buildtype'].lower() == 'release' and self.is_packaging_viewer(): - print("* Going strip-crazy on the packaged binaries, since this is a RELEASE build") + doStrip = True + # In case of flatpak flatpak-build will call strip, disable doStrip here to get a flatpak symbol package. Increases flatpak size by about 1G + if "FLATPAK_DEST" in os.environ: + doStrip = True + + if doStrip: + print("* Going strip-crazy on the packaged binaries, since this is a Release build") # makes some small assumptions about our packaged dir structure self.run_command( ["find"] + [os.path.join(self.get_dst_prefix(), dir) for dir in ('bin', 'lib')] + ['-type', 'f', '!', '-name', '*.py', + '!', '-name', '*.pak', + '!', '-name', '*.bin', + '!', '-name', '*.dat', + '!', '-name', '*.crt', + '!', '-name', '*.dll', + '!', '-name', '*.lib', '!', '-name', 'update_install', '-exec', 'strip', '-S', '{}', ';']) -class Linux_i686_Manifest(LinuxManifest): - address_size = 32 +class Linux_x86_64_Manifest(LinuxManifest): + address_size = 64 def construct(self): - super(Linux_i686_Manifest, self).construct() + super(Linux_x86_64_Manifest, self).construct() pkgdir = os.path.join(self.args['build'], os.pardir, 'packages') + if "package_dir" in self.args: + pkgdir = self.args['package_dir'] + relpkgdir = os.path.join(pkgdir, "lib", "release") debpkgdir = os.path.join(pkgdir, "lib", "debug") with self.prefix(src=relpkgdir, dst="lib"): - self.path("libapr-1.so") - self.path("libapr-1.so.0") - self.path("libapr-1.so.0.4.5") - self.path("libaprutil-1.so") - self.path("libaprutil-1.so.0") - self.path("libaprutil-1.so.0.4.1") - self.path("libdb*.so") + self.path("libapr-1.so*") + self.path("libaprutil-1.so*") self.path("libexpat.so.*") - self.path("libuuid.so*") - self.path("libSDL-1.2.so.*") - self.path("libdirectfb-1.*.so.*") - self.path("libfusion-1.*.so.*") - self.path("libdirect-1.*.so.*") - self.path("libopenjp2.so*") - self.path("libdirectfb-1.4.so.5") - self.path("libfusion-1.4.so.5") - self.path("libdirect-1.4.so.5*") + self.path_optional("libSDL*.so.*") + + self.path_optional("libjemalloc*.so") + self.path("libhunspell-1.3.so*") - self.path("libalut.so*") - self.path("libopenal.so*") - self.path("libopenal.so", "libvivoxoal.so.1") # vivox's sdk expects this soname + self.path_optional("libalut.so*") + self.path_optional("libopenal.so*") + self.path_optional("libopenal.so", "libvivoxoal.so.1") # vivox's sdk expects this soname # KLUDGE: As of 2012-04-11, the 'fontconfig' package installs # libfontconfig.so.1.4.4, along with symlinks libfontconfig.so.1 # and libfontconfig.so. Before we added support for library-file @@ -1378,17 +1847,6 @@ class Linux_i686_Manifest(LinuxManifest): self.path("libvivoxsdk.so") self.strip_binaries() - - -class Linux_x86_64_Manifest(LinuxManifest): - address_size = 64 - - def construct(self): - super(Linux_x86_64_Manifest, self).construct() - - # support file for valgrind debug tool - self.path("secondlife-i686.supp") - ################################################################ if __name__ == "__main__": diff --git a/indra/test/test.cpp b/indra/test/test.cpp index cbd1077306..cc2c130072 100644 --- a/indra/test/test.cpp +++ b/indra/test/test.cpp @@ -36,6 +36,7 @@ #include "linden_common.h" #include "llerrorcontrol.h" +#include "llexception.h" #include "lltut.h" #include "chained_callback.h" #include "stringize.h" @@ -63,11 +64,6 @@ #pragma warning (pop) #endif -#include <boost/scoped_ptr.hpp> -#include <boost/shared_ptr.hpp> -#include <boost/make_shared.hpp> -#include <boost/foreach.hpp> - #include <fstream> void wouldHaveCrashed(const std::string& message); @@ -176,10 +172,6 @@ public: LLTestCallback(bool verbose_mode, std::ostream *stream, std::shared_ptr<LLReplayLog> replayer) : mVerboseMode(verbose_mode), - mTotalTests(0), - mPassedTests(0), - mFailedTests(0), - mSkippedTests(0), // By default, capture a shared_ptr to std::cout, with a no-op "deleter" // so that destroying the shared_ptr makes no attempt to delete std::cout. mStream(std::shared_ptr<std::ostream>(&std::cout, [](std::ostream*){})), @@ -215,6 +207,8 @@ public: virtual void group_started(const std::string& name) { LL_INFOS("TestRunner")<<"Unit test group_started name=" << name << LL_ENDL; *mStream << "Unit test group_started name=" << name << std::endl; + mGroup = name; + mGroupTests = 0; super::group_started(name); } @@ -227,6 +221,7 @@ public: virtual void test_completed(const tut::test_result& tr) { ++mTotalTests; + ++mGroupTests; // If this test failed, dump requested log messages BEFORE stating the // test result. @@ -314,12 +309,15 @@ public: super::run_completed(); } + std::string mGroup; + int mGroupTests{ 0 }; + protected: - bool mVerboseMode; - int mTotalTests; - int mPassedTests; - int mFailedTests; - int mSkippedTests; + bool mVerboseMode{ false }; + int mTotalTests{ 0 }; + int mPassedTests{ 0 }; + int mFailedTests{ 0 }; + int mSkippedTests{ 0 }; std::shared_ptr<std::ostream> mStream; std::shared_ptr<LLReplayLog> mReplayer; }; @@ -647,14 +645,47 @@ int main(int argc, char **argv) // a chained_callback subclass must be linked with previous mycallback->link(); - if(test_group.empty()) - { - tut::runner.get().run_tests(); - } - else - { - tut::runner.get().run_tests(test_group); - } + LL::seh::catcher( + // __try + [test_group] + { + if(test_group.empty()) + { + tut::runner.get().run_tests(); + } + else + { + tut::runner.get().run_tests(test_group); + } + }, + // __except + [mycallback](U32 code, const std::string& /*stacktrace*/) + { + static std::map<U32, const char*> codes = { + { 0xC0000005, "Access Violation" }, + { 0xC00000FD, "Stack Overflow" }, + // ... continue filling in as desired + }; + + auto found{ codes.find(code) }; + const char* name = ((found == codes.end())? "unknown" : found->second); + auto msg{ stringize("test threw ", std::hex, code, " (", name, ")") }; + + // Instead of bombing the whole test run, report this as a test + // failure. Arguably, catching structured exceptions should be + // hacked into TUT itself. + mycallback->test_completed(tut::test_result( + mycallback->mGroup, + mycallback->mGroupTests+1, // test within group + "unknown", // test name + tut::test_result::ex, // result: exception + // we don't have to throw this exception subclass to use it to + // populate the test_result struct + Windows_SEH_exception(msg))); + // we've left the TUT framework -- finish up by hand + mycallback->group_completed(mycallback->mGroup); + mycallback->run_completed(); + }); bool success = (mycallback->getFailedTests() == 0); diff --git a/indra/viewer_components/login/CMakeLists.txt b/indra/viewer_components/login/CMakeLists.txt index 8381803b03..d33b6d78f7 100644 --- a/indra/viewer_components/login/CMakeLists.txt +++ b/indra/viewer_components/login/CMakeLists.txt @@ -1,6 +1,6 @@ # -*- cmake -*- -project(login) +project(lllogin) include(00-Common) if(LL_TESTS) @@ -9,21 +9,21 @@ endif(LL_TESTS) include(LLCommon) include(LLCoreHttp) -set(login_SOURCE_FILES +set(lllogin_SOURCE_FILES lllogin.cpp ) -set(login_HEADER_FILES +set(lllogin_HEADER_FILES lllogin.h ) list(APPEND - login_SOURCE_FILES - ${login_HEADER_FILES} + lllogin_SOURCE_FILES + ${lllogin_HEADER_FILES} ) add_library(lllogin - ${login_SOURCE_FILES} + ${lllogin_SOURCE_FILES} ) target_include_directories( lllogin INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) @@ -35,6 +35,8 @@ target_link_libraries(lllogin llxml ) +include(LibraryInstall) + if(LL_TESTS) SET(lllogin_TEST_SOURCE_FILES lllogin.cpp |