diff --git a/doc/contributions.txt b/doc/contributions.txt index 258e139bc..882dca18c 100644 --- a/doc/contributions.txt +++ b/doc/contributions.txt @@ -72,8 +72,10 @@ Aleric Inglewood VWR-14914 VWR-24247 VWR-24312 + VWR-24315 VWR-24320 VWR-24333 + VWR-24334 SNOW-47 SNOW-84 SNOW-86 @@ -112,7 +114,9 @@ Aleric Inglewood IMP-664 IMP-670 IMP-701 + IMP-702 IMP-734 + IMP-735 Alissa Sabre VWR-81 VWR-83 diff --git a/etc/message.xml b/etc/message.xml index 847f483aa..04cdbc8f2 100644 --- a/etc/message.xml +++ b/etc/message.xml @@ -673,9 +673,6 @@ FetchInventoryDescendents false - WebFetchInventoryDescendents - true - FetchInventory true diff --git a/indra/CMakeLists.txt b/indra/CMakeLists.txt index 33637ab1e..c0e8dc408 100644 --- a/indra/CMakeLists.txt +++ b/indra/CMakeLists.txt @@ -44,6 +44,7 @@ endif(NOT STANDALONE) add_custom_target(prepare DEPENDS ${prepare_depends}) add_subdirectory(cmake) +add_subdirectory(${LIBS_OPEN_PREFIX}cwdebug) add_subdirectory(${LIBS_OPEN_PREFIX}llaudio) add_subdirectory(${LIBS_OPEN_PREFIX}llcharacter) add_subdirectory(${LIBS_OPEN_PREFIX}llcommon) @@ -75,8 +76,8 @@ if (VIEWER) add_subdirectory(${LIBS_OPEN_PREFIX}llplugin) add_subdirectory(${LIBS_OPEN_PREFIX}llui) - # viewer media plugins - add_subdirectory(${LIBS_OPEN_PREFIX}media_plugins) + # viewer plugins directory + add_subdirectory(${LIBS_OPEN_PREFIX}plugins) # llplugin testbed code (is this the right way to include it?) #if (NOT LINUX) @@ -105,6 +106,7 @@ if (VIEWER) add_dependencies(viewer solaris-crash-logger) endif (LINUX) + add_subdirectory(${VIEWER_PREFIX}newview/statemachine) add_subdirectory(${VIEWER_PREFIX}newview) add_dependencies(viewer secondlife-bin) endif (VIEWER) diff --git a/indra/cmake/AIStateMachine.cmake b/indra/cmake/AIStateMachine.cmake new file mode 100644 index 000000000..c1bda40c4 --- /dev/null +++ b/indra/cmake/AIStateMachine.cmake @@ -0,0 +1,4 @@ +# -*- cmake -*- + +set(AISTATEMACHINE_INCLUDE_DIRS statemachine) +set(AISTATEMACHINE_LIBRARIES statemachine) diff --git a/indra/cmake/BasicPluginBase.cmake b/indra/cmake/BasicPluginBase.cmake new file mode 100644 index 000000000..a4f339272 --- /dev/null +++ b/indra/cmake/BasicPluginBase.cmake @@ -0,0 +1,8 @@ +# -*- cmake -*- + + +set(BASIC_PLUGIN_BASE_INCLUDE_DIRS + ${LIBS_OPEN_DIR}/plugins/base_basic/ + ) + +set(BASIC_PLUGIN_BASE_LIBRARIES basic_plugin_base) diff --git a/indra/cmake/Cwdebug.cmake b/indra/cmake/Cwdebug.cmake new file mode 100644 index 000000000..9568a625f --- /dev/null +++ b/indra/cmake/Cwdebug.cmake @@ -0,0 +1 @@ +set(CWDEBUG_LIBRARIES cwdebug) diff --git a/indra/cmake/FindMyZLIB.cmake b/indra/cmake/FindMyZLIB.cmake deleted file mode 100644 index 6d630f1ba..000000000 --- a/indra/cmake/FindMyZLIB.cmake +++ /dev/null @@ -1,46 +0,0 @@ -# -*- cmake -*- - -# - Find zlib -# Find the ZLIB includes and library -# This module defines -# ZLIB_INCLUDE_DIRS, where to find zlib.h, etc. -# ZLIB_LIBRARIES, the libraries needed to use zlib. -# ZLIB_FOUND, If false, do not try to use zlib. -# -# This FindZLIB is about 43 times as fast the one provided with cmake (2.8.x), -# because it doesn't look up the version of zlib, resulting in a dramatic -# speed up for configure (from 4 minutes 22 seconds to 6 seconds). -# -# Note: Since this file is only used for standalone, the windows -# specific parts were left out. - -FIND_PATH(ZLIB_INCLUDE_DIR zlib.h - NO_SYSTEM_ENVIRONMENT_PATH - ) - -FIND_LIBRARY(ZLIB_LIBRARY z) - -if (ZLIB_LIBRARY AND ZLIB_INCLUDE_DIR) - SET(ZLIB_INCLUDE_DIRS ${ZLIB_INCLUDE_DIR}) - SET(ZLIB_LIBRARIES ${ZLIB_LIBRARY}) - SET(ZLIB_FOUND "YES") -else (ZLIB_LIBRARY AND ZLIB_INCLUDE_DIR) - SET(ZLIB_FOUND "NO") -endif (ZLIB_LIBRARY AND ZLIB_INCLUDE_DIR) - -if (ZLIB_FOUND) - if (NOT ZLIB_FIND_QUIETLY) - message(STATUS "Found ZLIB: ${ZLIB_LIBRARIES}") - SET(ZLIB_FIND_QUIETLY TRUE) - endif (NOT ZLIB_FIND_QUIETLY) -else (ZLIB_FOUND) - if (ZLIB_FIND_REQUIRED) - message(FATAL_ERROR "Could not find ZLIB library") - endif (ZLIB_FIND_REQUIRED) -endif (ZLIB_FOUND) - -mark_as_advanced( - ZLIB_LIBRARY - ZLIB_INCLUDE_DIR - ) - diff --git a/indra/cmake/GStreamer010Plugin.cmake b/indra/cmake/GStreamer010Plugin.cmake index 2b45a1abc..90ed35c81 100644 --- a/indra/cmake/GStreamer010Plugin.cmake +++ b/indra/cmake/GStreamer010Plugin.cmake @@ -6,11 +6,13 @@ if (STANDALONE) pkg_check_modules(GSTREAMER010 REQUIRED gstreamer-0.10) pkg_check_modules(GSTREAMER010_PLUGINS_BASE REQUIRED gstreamer-plugins-base-0.10) -elseif (LINUX) + +else (STANDALONE) + + # Possibly libxml and glib should have their own .cmake file instead... use_prebuilt_binary(glib) # gstreamer needs glib - use_prebuilt_binary(gstreamer) - # possible libxml should have its own .cmake file instead use_prebuilt_binary(libxml) + use_prebuilt_binary(gstreamer) set(GSTREAMER010_FOUND ON FORCE BOOL) set(GSTREAMER010_PLUGINS_BASE_FOUND ON FORCE BOOL) set(GSTREAMER010_INCLUDE_DIRS @@ -18,23 +20,47 @@ elseif (LINUX) ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include/glib-2.0 ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include/libxml2 ) + +endif (STANDALONE) + +if (WINDOWS) # We don't need to explicitly link against gstreamer itself, because # LLMediaImplGStreamer probes for the system's copy at runtime. - set(GSTREAMER010_LIBRARIES - gobject-2.0 - gmodule-2.0 - dl - gthread-2.0 - rt - glib-2.0 - ) -endif (STANDALONE) + set(GSTREAMER010_LIBRARIES + libgstvideo + libgstaudio + libgstbase-0.10 + libgstreamer-0.10 + gobject-2.0 + gmodule-2.0 + gthread-2.0 + glib-2.0 + ) +else (WINDOWS) + # We don't need to explicitly link against gstreamer itself, because + # LLMediaImplGStreamer probes for the system's copy at runtime. + set(GSTREAMER010_LIBRARIES + gstvideo-0.10 + gstaudio-0.10 + gstbase-0.10 + gstreamer-0.10 + gobject-2.0 + gmodule-2.0 + dl + gthread-2.0 + rt + glib-2.0 + ) + + +endif (WINDOWS) + if (GSTREAMER010_FOUND AND GSTREAMER010_PLUGINS_BASE_FOUND) set(GSTREAMER010 ON CACHE BOOL "Build with GStreamer-0.10 streaming media support.") + add_definitions(-DLL_GSTREAMER010_ENABLED=1) endif (GSTREAMER010_FOUND AND GSTREAMER010_PLUGINS_BASE_FOUND) -if (GSTREAMER010) - add_definitions(-DLL_GSTREAMER010_ENABLED=1) -endif (GSTREAMER010) + + diff --git a/indra/cmake/LLAddBuildTest.cmake b/indra/cmake/LLAddBuildTest.cmake index f9b1ef96f..74f2e0cb1 100644 --- a/indra/cmake/LLAddBuildTest.cmake +++ b/indra/cmake/LLAddBuildTest.cmake @@ -3,6 +3,7 @@ INCLUDE(APR) INCLUDE(LLMath) INCLUDE(Tut) +INCLUDE(Cwdebug) MACRO(ADD_BUILD_TEST_NO_COMMON name parent) # MESSAGE("${CMAKE_CURRENT_SOURCE_DIR}/tests/${name}_test.cpp") diff --git a/indra/cmake/LLCommon.cmake b/indra/cmake/LLCommon.cmake index 2862ba7f0..efb3d004c 100644 --- a/indra/cmake/LLCommon.cmake +++ b/indra/cmake/LLCommon.cmake @@ -6,6 +6,7 @@ include(EXPAT) include(ZLIB) set(LLCOMMON_INCLUDE_DIRS + ${LIBS_OPEN_DIR}/cwdebug ${LIBS_OPEN_DIR}/llcommon ${APR_INCLUDE_DIR} ${Boost_INCLUDE_DIRS} diff --git a/indra/cmake/Linking.cmake b/indra/cmake/Linking.cmake index 2bddb9517..eaa8a6dc2 100644 --- a/indra/cmake/Linking.cmake +++ b/indra/cmake/Linking.cmake @@ -42,6 +42,7 @@ if (WINDOWS) wldap32 gdi32 user32 + dbghelp ) else (WINDOWS) set(WINDOWS_LIBRARIES "") diff --git a/indra/cmake/MediaPluginBase.cmake b/indra/cmake/MediaPluginBase.cmake index 2be035b64..7e2d30dfa 100644 --- a/indra/cmake/MediaPluginBase.cmake +++ b/indra/cmake/MediaPluginBase.cmake @@ -1,8 +1,6 @@ # -*- cmake -*- +include(BasicPluginBase) -set(MEDIA_PLUGIN_BASE_INCLUDE_DIRS - ${LIBS_OPEN_DIR}/media_plugins/base/ - ) - -set(MEDIA_PLUGIN_BASE_LIBRARIES media_plugin_base) +set(MEDIA_PLUGIN_BASE_INCLUDE_DIRS ${LIBS_OPEN_DIR}/plugins/base_media ${BASIC_PLUGIN_BASE_INCLUDE_DIRS}) +set(MEDIA_PLUGIN_BASE_LIBRARIES media_plugin_base ${BASIC_PLUGIN_BASE_LIBRARIES}) diff --git a/indra/cwdebug/CMakeLists.txt b/indra/cwdebug/CMakeLists.txt new file mode 100644 index 000000000..9f423c736 --- /dev/null +++ b/indra/cwdebug/CMakeLists.txt @@ -0,0 +1,39 @@ +# -*- cmake -*- + +project(cwdebug) + +include(00-Common) +include(LLCommon) +include(LLMath) +include(LLMessage) +include(LLVFS) + +include_directories (${CMAKE_CURRENT_SOURCE_DIR}) + +set(cwdebug_SOURCE_FILES + debug.cc + ) + +set(cwdebug_HEADER_FILES + CMakeLists.txt + + cwdebug.h + sys.h + debug.h + debug_ostream_operators.h + ) + +set_source_files_properties(${cwdebug_HEADER_FILES} + PROPERTIES HEADER_FILE_ONLY TRUE) + +if(NOT WORD_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 WORD_SIZE EQUAL 32) + +list(APPEND cwdebug_SOURCE_FILES ${cwdebug_HEADER_FILES}) + +add_library (cwdebug ${cwdebug_SOURCE_FILES}) diff --git a/indra/cwdebug/cwdebug.h b/indra/cwdebug/cwdebug.h new file mode 100644 index 000000000..37415df3f --- /dev/null +++ b/indra/cwdebug/cwdebug.h @@ -0,0 +1,9 @@ +// We support compiling C++ source files that are not +// thread-safe, but in that case we assume that they +// will not be linked with libcwd_r. +#if !defined(_REENTRANT) || !defined(__linux__) +#undef CWDEBUG +#endif + +#include "sys.h" +#include "debug.h" diff --git a/indra/cwdebug/debug.cc b/indra/cwdebug/debug.cc new file mode 100644 index 000000000..48392beae --- /dev/null +++ b/indra/cwdebug/debug.cc @@ -0,0 +1,413 @@ +// slviewer -- Second Life Viewer Source Code +// +//! @file debug.cc +//! @brief This file contains the definitions of debug related objects and functions. +// +// Copyright (C) 2008, by +// +// Carlo Wood, Run on IRC +// RSA-1024 0x624ACAD5 1997-01-26 Sign & Encrypt +// Fingerprint16 = 32 EC A7 B6 AC DB 65 A6 F6 F6 55 DD 1C DC FF 61 +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 2 of the License, or +// (at your option) any later version. +// +// This program 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 General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#ifndef USE_PCH +#include "sys.h" // Needed for platform-specific code +#endif + +#ifdef CWDEBUG + +#ifndef USE_PCH +#include // Needed for std::isprint +#include // Needed for setfill and setw +#include +#include +#include +#include +#include "debug.h" +#ifdef USE_LIBCW +#include // memleak_filter +#endif +#include +#include +#endif // USE_PCH + +#define BACKTRACE_AQUIRE_LOCK libcwd::_private_::mutex_tct::lock() +#define BACKTRACE_RELEASE_LOCK libcwd::_private_::mutex_tct::unlock() + +namespace debug { + +#if CWDEBUG_LOCATION +void BackTrace::dump_backtrace(void) const +{ + for (int frame = 0; frame < frames(); ++frame) + { + libcwd::location_ct loc((char*)buffer()[frame] + libcwd::builtin_return_address_offset); + Dout(dc::notice|continued_cf, '#' << std::left << std::setw(3) << frame << + std::left << std::setw(16) << buffer()[frame] << ' ' << loc << "\n in "); + char const* mangled_function_name = loc.mangled_function_name(); + if (mangled_function_name != libcwd::unknown_function_c) + { + std::string demangled_function_name; + libcwd::demangle_symbol(mangled_function_name, demangled_function_name); + Dout(dc::finish, demangled_function_name); + } + else + Dout(dc::finish, mangled_function_name); + } +} +#endif // CWDEBUG_LOCATION + +#if CWDEBUG_ALLOC && CWDEBUG_LOCATION +typedef std::map, libcwd::_private_::internal_allocator> backtrace_map_t; +backtrace_map_t* backtrace_map; +static int total_calls = 0; +static int number_of_stack_traces = 0; + +void my_backtrace_hook(void** buffer, int frames LIBCWD_COMMA_TSD_PARAM) +{ + ++total_calls; + + backtrace_map_t::iterator iter; + + set_alloc_checking_off(__libcwd_tsd); + { + BackTrace backtrace(buffer, frames); + std::pair res = backtrace_map->insert(backtrace_map_t::value_type(backtrace, 0)); + if (res.second) + ++number_of_stack_traces; + ++res.first->second; + iter = res.first; + } + set_alloc_checking_on(__libcwd_tsd); +#if 0 + // Dump the stack trace. + iter->first.dump_backtrace(); +#endif +} + +void start_recording_backtraces(void) +{ + BACKTRACE_AQUIRE_LOCK; + libcwd::backtrace_hook = my_backtrace_hook; + BACKTRACE_RELEASE_LOCK; + //Debug(dc::malloc.on()); + LIBCWD_TSD_DECLARATION; + set_alloc_checking_off(__libcwd_tsd); + backtrace_map = new backtrace_map_t; + set_alloc_checking_on(__libcwd_tsd); +} + +struct Compare { + bool operator()(backtrace_map_t::const_iterator const& iter1, backtrace_map_t::const_iterator const& iter2) + { + return iter1->second > iter2->second; + } +}; + +void stop_recording_backtraces(void) +{ + //Debug(dc::malloc.off()); + BACKTRACE_AQUIRE_LOCK; + libcwd::backtrace_hook = NULL; + + if (!backtrace_map) + { + Dout(dc::notice, "Not recording; call cwdebug_start() first."); + return; + } + + Dout(dc::notice, "Total number of calls: " << total_calls); + Dout(dc::notice, "Number of different stack traces: " << number_of_stack_traces); + Dout(dc::notice, "First 10 stack traces:"); + std::list entries; + for (backtrace_map_t::const_iterator iter = backtrace_map->begin(); iter != backtrace_map->end(); ++iter) + entries.push_back(iter); + entries.sort(Compare()); + int count = 0; + for (std::list::iterator iter = entries.begin(); iter != entries.end(); ++iter, ++count) + { + Dout(dc::notice, "Used: " << (*iter)->second); + // Dump the stack trace. + (*iter)->first.dump_backtrace(); + if (count == 10) + break; + } + + // Clear all data. + LIBCWD_TSD_DECLARATION; + set_alloc_checking_off(__libcwd_tsd); + delete backtrace_map; + set_alloc_checking_on(__libcwd_tsd); + backtrace_map = NULL; + total_calls = 0; + number_of_stack_traces = 0; + + BACKTRACE_RELEASE_LOCK; +} +#endif // CWDEBUG_ALLOC && CWDEBUG_LOCATION + + namespace channels { // namespace DEBUGCHANNELS + namespace dc { + +#ifndef DOXYGEN +#define DDCN(x) (x) +#endif + // Add new debug channels here. + + channel_ct viewer DDCN("VIEWER"); //!< This debug channel is used for the normal debugging out of the viewer. + channel_ct primbackup DDCN("PRIMBACKUP"); //!< This debug channel is used for output related to primbackup. + channel_ct gtk DDCN("GTK"); //!< This debug channel is used for output related to gtk. + channel_ct sdl DDCN("SDL"); //!< This debug channel is used for output related to sdl locking. + channel_ct backtrace DDCN("BACKTRACE"); //!< This debug channel is used for backtraces. + channel_ct statemachine DDCN("STATEMACHINE"); //!< This debug channel is used class AIStateMachine. + + } // namespace dc + } // namespace DEBUGCHANNELS + + // Anonymous namespace, this map and its initialization functions are private to this file + // for Thead-safeness reasons. + namespace { + + /*! @brief The type of rcfile_dc_states. + * @internal + */ + typedef std::map rcfile_dc_states_type; + + /*! @brief Map containing the default debug channel states used at the start of each new thread. + * @internal + * + * The first thread calls main, which calls debug::init which will initialize this + * map with all debug channel labels and whether or not they were turned on in the + * rcfile or not. + */ + rcfile_dc_states_type rcfile_dc_states; + + /*! @brief Set the default state of debug channel \a dc_label. + * @internal + * + * This function is called once for each debug channel. + */ + void set_state(char const* dc_label, bool is_on) + { + std::pair res = + rcfile_dc_states.insert(rcfile_dc_states_type::value_type(std::string(dc_label), is_on)); + if (!res.second) + Dout(dc::warning, "Calling set_state() more than once for the same label!"); + return; + } + + /*! @brief Save debug channel states. + * @internal + * + * One time initialization function of rcfile_dc_state. + * This must be called from debug::init after reading the rcfile. + */ + void save_dc_states(void) + { + // We may only call this function once: it reflects the states as stored + // in the rcfile and that won't change. Therefore it is not needed to + // lock `rcfile_dc_states', it is only written to by the first thread + // (once, via main -> init) when there are no other threads yet. + static bool second_time = false; + if (second_time) + { + Dout(dc::warning, "Calling save_dc_states() more than once!"); + return; + } + second_time = true; + ForAllDebugChannels( set_state(debugChannel.get_label(), debugChannel.is_on()) ); + } + + } // anonymous namespace + + /*! @brief Returns the the original state of a debug channel. + * @internal + * + * For a given \a dc_label, which must be the exact name (channel_ct::get_label) of an + * existing debug channel, this function returns \c true when the corresponding debug channel was + * on at the startup of the application, directly after reading the libcwd runtime + * configuration file (.libcwdrc). + * + * If the label/channel did not exist at the start of the application, it will return \c false + * (note that libcwd disallows adding debug channels to modules - so this would probably + * a bug). + */ + bool is_on_in_rcfile(char const* dc_label) + { + rcfile_dc_states_type::const_iterator iter = rcfile_dc_states.find(std::string(dc_label)); + if (iter == rcfile_dc_states.end()) + { + Dout(dc::warning, "is_on_in_rcfile(\"" << dc_label << "\"): \"" << dc_label << "\" is an unknown label!"); + return false; + } + return iter->second; + } + +#if LIBCWD_THREAD_SAFE + pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; + // I can cause I'm the maintainer of libcwd ;). + libcwd::_private_::pthread_lock_interface_ct cout_mutex(&mutex); + libcwd::_private_::lock_interface_base_ct* cout_mutex_ptr(&cout_mutex); +#endif + + /*! @brief Initialize debugging code from new threads. + * + * This function needs to be called at the start of each new thread, + * because a new thread starts in a completely reset state. + * + * The function turns on all debug channels that were turned on + * after reading the rcfile at the start of the application. + * Furthermore it initializes the debug ostream, its mutex and the + * margin of the default debug object (Dout). + */ + void init_thread(void) + { + // Turn on all debug channels that are turned on as per rcfile configuration. + ForAllDebugChannels( + if (!debugChannel.is_on() && is_on_in_rcfile(debugChannel.get_label())) + debugChannel.on(); + ); + + // Turn on debug output. + Debug( libcw_do.on() ); + static std::ofstream debug_file; + static bool debug_out_opened = false; + if (!debug_out_opened) + { + debug_out_opened = true; // Thread-safe, cause the main thread calls this first while it's still alone. + std::ostringstream os; + os << "debug.out." << getpid(); + debug_file.open(os.str().c_str()); + } + static debug::TeeStream debug_stream(std::cout, debug_file); +#if LIBCWD_THREAD_SAFE + Debug( libcw_do.set_ostream(&debug_stream, cout_mutex_ptr) ); +#else + Debug( libcw_do.set_ostream(&debug_stream) ); +#endif + + static bool first_thread = true; + if (!first_thread) // So far, the application has only one thread. So don't add a thread id. + { + // Set the thread id in the margin. + char margin[18]; + sprintf(margin, "0x%-14lx ", pthread_self()); + Debug( libcw_do.margin().assign(margin, 17) ); + } + first_thread = false; + } + + /*! @brief Initialize debugging code from main. + * + * This function initializes the debug code. + */ + void init(void) + { +#if CWDEBUG_ALLOC && defined(USE_LIBCW) + // Tell the memory leak detector which parts of the code are + // expected to leak so that we won't get an alarm for those. + { + std::vector > hide_list; + hide_list.push_back(std::pair("libdl.so.2", "_dlerror_run")); + hide_list.push_back(std::pair("libstdc++.so.6", "__cxa_get_globals")); + // The following is actually necessary because of a bug in glibc + // (see http://sources.redhat.com/bugzilla/show_bug.cgi?id=311). + hide_list.push_back(std::pair("libc.so.6", "dl_open_worker")); + memleak_filter().hide_functions_matching(hide_list); + } + { + std::vector hide_list; + // Also because of http://sources.redhat.com/bugzilla/show_bug.cgi?id=311 + hide_list.push_back(std::string("ld-linux.so.2")); + memleak_filter().hide_objectfiles_matching(hide_list); + } + memleak_filter().set_flags(libcwd::show_objectfile|libcwd::show_function); +#endif + + // The following call allocated the filebuf's of cin, cout, cerr, wcin, wcout and wcerr. + // Because this causes a memory leak being reported, make them invisible. + Debug(set_invisible_on()); + + // You want this, unless you mix streams output with C output. + // Read http://gcc.gnu.org/onlinedocs/libstdc++/27_io/howto.html#8 for an explanation. + //std::ios::sync_with_stdio(false); + + // Cancel previous call to set_invisible_on. + Debug(set_invisible_off()); + + // This will warn you when you are using header files that do not belong to the + // shared libcwd object that you linked with. + Debug( check_configuration() ); + + Debug( + libcw_do.on(); // Show which rcfile we are reading! + ForAllDebugChannels( + while (debugChannel.is_on()) + debugChannel.off() // Print as little as possible though. + ); + read_rcfile(); // Put 'silent = on' in the rcfile to suppress most of the output here. + libcw_do.off() + ); + save_dc_states(); + + init_thread(); + } + +#if CWDEBUG_LOCATION + /*! @brief Return call location. + * + * @param return_addr The return address of the call. + */ + std::string call_location(void const* return_addr) + { + libcwd::location_ct loc((char*)return_addr + libcwd::builtin_return_address_offset); + std::ostringstream convert; + convert << loc; + return convert.str(); + } + + std::vector __attribute__ ((visibility("default"))) backtraces; + pthread_mutex_t __attribute__ ((visibility("default"))) backtrace_mutex = PTHREAD_MUTEX_INITIALIZER; +#endif + +} // namespace debug + +#if CWDEBUG_ALLOC +// These can be called from gdb. +void cwdebug_start() +{ + debug::start_recording_backtraces(); +} + +void cwdebug_stop() +{ + debug::stop_recording_backtraces(); +} +#endif + +#if CWDEBUG_LOCATION +void cwdebug_backtrace(int n) +{ + if (0 < n && n <= debug::backtraces.size()) + { + Dout(dc::backtrace, "Backtrace #" << n << ":"); + debug::backtraces[n - 1].dump_backtrace(); + } + else + std::cout << "No such backtrace nr. Max is " << debug::backtraces.size() << std::endl; +} +#endif + +#endif // CWDEBUG diff --git a/indra/cwdebug/debug.h b/indra/cwdebug/debug.h new file mode 100644 index 000000000..e91eab92e --- /dev/null +++ b/indra/cwdebug/debug.h @@ -0,0 +1,257 @@ +// slviewer -- Second Life Viewer Source Code +// +//! @file debug.h +//! @brief This file contains the declaration of debug related macros, objects and functions. +// +// Copyright (C) 2008, by +// +// Carlo Wood, Run on IRC +// RSA-1024 0x624ACAD5 1997-01-26 Sign & Encrypt +// Fingerprint16 = 32 EC A7 B6 AC DB 65 A6 F6 F6 55 DD 1C DC FF 61 +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 2 of the License, or +// (at your option) any later version. +// +// This program 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 General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#ifndef DEBUG_H +#define DEBUG_H + +#ifndef CWDEBUG + +#ifndef DOXYGEN // No need to document this. See http://libcwd.sourceforge.net/ for more info. + +#include +#include // std::exit, EXIT_FAILURE + +#define AllocTag1(p) +#define AllocTag2(p, desc) +#define AllocTag_dynamic_description(p, x) +#define AllocTag(p, x) +#define Debug(x) +#define Dout(a, b) +#define DoutEntering(a, b) +#define DoutFatal(a, b) LibcwDoutFatal(::std, , a, b) +#define ForAllDebugChannels(STATEMENT) +#define ForAllDebugObjects(STATEMENT) +#define LibcwDebug(dc_namespace, x) +#define LibcwDout(a, b, c, d) +#define LibcwDoutFatal(a, b, c, d) do { ::std::cerr << d << ::std::endl; ::std::exit(EXIT_FAILURE); } while (1) +#define NEW(x) new x +#define CWDEBUG_ALLOC 0 +#define CWDEBUG_MAGIC 0 +#define CWDEBUG_LOCATION 0 +#define CWDEBUG_LIBBFD 0 +#define CWDEBUG_DEBUG 0 +#define CWDEBUG_DEBUGOUTPUT 0 +#define CWDEBUG_DEBUGM 0 +#define CWDEBUG_DEBUGT 0 +#define CWDEBUG_MARKER 0 + +#define BACKTRACE do { } while(0) + +#endif // !DOXYGEN + +#include +#ifdef DEBUG +#define ASSERT(x) assert(x) +#else +#define ASSERT(x) +#endif + +#else // CWDEBUG + +//! Assert \a x, if debugging is turned on. +#define ASSERT(x) LIBCWD_ASSERT(x) +#define builtin_return_address(addr) ((char*)__builtin_return_address(addr) + libcwd::builtin_return_address_offset) + +#ifndef DEBUGCHANNELS +//! @brief The namespace in which the \c dc namespace is declared. +// +// Libcwd demands that this macro is defined +// before is included and must be the name of the namespace containing +// the \c dc (Debug Channels) namespace. +// +// @sa debug::channels::dc + +#define DEBUGCHANNELS ::debug::channels +#endif +#include +#include +#if CWDEBUG_LOCATION +#include // Needed for 'backtrace'. +#endif + +#define CWD_API __attribute__ ((visibility("default"))) + +//! Debug specific code. +namespace debug { + +void CWD_API init(void); // Initialize debugging code, called once from main. +void CWD_API init_thread(void); // Initialize debugging code, called once for each thread. + +//! @brief Debug Channels (dc) namespace. +// +// @sa debug::channels::dc +namespace channels { // namespace DEBUGCHANNELS + +//! The namespace containing the actual debug channels. +namespace dc { +using namespace libcwd::channels::dc; +using libcwd::channel_ct; + +#ifndef DOXYGEN // Doxygen bug causes a warning here. +// Add the declaration of new debug channels here +// and add their definition in a custom debug.cc file. +extern CWD_API channel_ct viewer; // The normal logging output of the viewer (normally to stderr). +extern CWD_API channel_ct primbackup; +extern CWD_API channel_ct gtk; +extern CWD_API channel_ct sdl; +extern CWD_API channel_ct backtrace; +extern CWD_API channel_ct statemachine; + +#endif + +} // namespace dc +} // namespace DEBUGCHANNELS + +#if CWDEBUG_LOCATION +std::string call_location(void const* return_addr); +#endif + +//! @brief Interface for marking scopes of invisible memory allocations. +// +// Creation of the object does nothing, you have to explicitly call +// InvisibleAllocations::on. Destruction of the object automatically +// cancels any call to \c on of this object. This makes it exception- +// (stack unwinding) and recursive-safe. +struct InvisibleAllocations { + int M_on; //!< The number of times that InvisibleAllocations::on() was called. + //! Constructor. + InvisibleAllocations() : M_on(0) { } + //! Destructor. + ~InvisibleAllocations() { while (M_on > 0) off(); } + //! Set invisible allocations on. Can be called recursively. + void on(void) { libcwd::set_invisible_on(); ++M_on; } + //! Cancel one call to on(). + void off(void) { assert(M_on > 0); --M_on; libcwd::set_invisible_off(); } +}; + +//! @brief Interface for marking scopes with indented debug output. +// +// Creation of the object increments the debug indentation. Destruction +// of the object automatically decrements the indentation again. +struct Indent { + int M_indent; //!< The extra number of spaces that were added to the indentation. + //! Construct an Indent object. + Indent(int indent) : M_indent(indent) { if (M_indent > 0) libcwd::libcw_do.inc_indent(M_indent); } + //! Destructor. + ~Indent() { if (M_indent > 0) libcwd::libcw_do.dec_indent(M_indent); } +}; + +// A class streambuf that splits what is written to two streambufs. +class TeeBuf : public std::streambuf { + private: + std::streambuf* M_sb1; + std::streambuf* M_sb2; + + public: + TeeBuf(std::streambuf* sb1, std::streambuf* sb2) : M_sb1(sb1), M_sb2(sb2) { } + + protected: + virtual int sync(void) { M_sb2->pubsync(); return M_sb1->pubsync(); } + virtual std::streamsize xsputn(char_type const* p, std::streamsize n) { M_sb2->sputn(p, n); return M_sb1->sputn(p, n); } + virtual int_type overflow(int_type c = traits_type::eof()) { M_sb2->sputc(c); return M_sb1->sputc(c); } +}; + +// An ostream that passes what is written to it on to two other ostreams. +class TeeStream : public std::ostream { + private: + TeeBuf M_teebuf; + public: + TeeStream(std::ostream& os1, std::ostream& os2) : std::ostream(&M_teebuf), M_teebuf(os1.rdbuf(), os2.rdbuf()) { } +}; + +#if CWDEBUG_LOCATION +class BackTrace { + private: + boost::shared_array M_buffer; + int M_frames; + public: + BackTrace(void** buffer, int frames) : M_buffer(new void* [frames]), M_frames(frames) { std::memcpy(M_buffer.get(), buffer, sizeof(void*) * frames); } + + friend bool operator<(BackTrace const& bt1, BackTrace const& bt2) + { + if (bt1.M_frames != bt2.M_frames) + return bt1.M_frames < bt2.M_frames; + for (int frame = 0; frame < bt1.M_frames; ++frame) + if (bt1.M_buffer[frame] < bt2.M_buffer[frame]) + return true; + else if (bt1.M_buffer[frame] > bt2.M_buffer[frame]) + return true; + return false; + } + + void dump_backtrace(void) const; + + int frames(void) const { return M_frames; } + boost::shared_array const& buffer(void) const { return M_buffer; } +}; +extern std::vector backtraces; +extern pthread_mutex_t backtrace_mutex; +#define BACKTRACE do { \ + using namespace debug; \ + void* buffer[32]; \ + int frames = backtrace(buffer, 32); \ + size_t size; \ + { \ + pthread_mutex_lock(&backtrace_mutex); \ + backtraces.push_back(BackTrace(buffer, frames)); \ + size = backtraces.size(); \ + pthread_mutex_unlock(&backtrace_mutex); \ + } \ + Dout(dc::backtrace, "Stored backtrace #" << size); \ + } while(0) +#else +#define BACKTRACE do { } while(0) +#endif // CWDEBUG_LOCATION + +} // namespace debug + +//! Debugging macro. +// +// Print "Entering " << \a data to channel \a cntrl and increment +// debugging output indentation until the end of the current scope. +#define DoutEntering(cntrl, data) \ + int __slviewer_debug_indentation = 2; \ + { \ + LIBCWD_TSD_DECLARATION; \ + if (LIBCWD_DO_TSD_MEMBER_OFF(::libcwd::libcw_do) < 0) \ + { \ + ::libcwd::channel_set_bootstrap_st __libcwd_channel_set(LIBCWD_DO_TSD(::libcwd::libcw_do) LIBCWD_COMMA_TSD); \ + bool on; \ + { \ + using namespace LIBCWD_DEBUGCHANNELS; \ + on = (__libcwd_channel_set|cntrl).on; \ + } \ + if (on) \ + Dout(cntrl, "Entering " << data); \ + else \ + __slviewer_debug_indentation = 0; \ + } \ + } \ + debug::Indent __slviewer_debug_indent(__slviewer_debug_indentation); + +#endif // CWDEBUG + +#include "debug_ostream_operators.h" + +#endif // DEBUG_H diff --git a/indra/cwdebug/debug_ostream_operators.h b/indra/cwdebug/debug_ostream_operators.h new file mode 100644 index 000000000..4459e9fab --- /dev/null +++ b/indra/cwdebug/debug_ostream_operators.h @@ -0,0 +1 @@ +// Empty so far... diff --git a/indra/cwdebug/sys.h b/indra/cwdebug/sys.h new file mode 100644 index 000000000..c18df1701 --- /dev/null +++ b/indra/cwdebug/sys.h @@ -0,0 +1,9 @@ +// The following is the libcwd related mandatory part. +// It must be included before any system header file is included. +#ifdef CWDEBUG +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif +#include +#endif + diff --git a/indra/llaudio/llaudioengine.cpp b/indra/llaudio/llaudioengine.cpp index b61d934dd..fa5444cf5 100644 --- a/indra/llaudio/llaudioengine.cpp +++ b/indra/llaudio/llaudioengine.cpp @@ -1336,16 +1336,17 @@ LLAudioSource::LLAudioSource(const LLUUID& id, const LLUUID& owner_id, const F32 LLAudioSource::~LLAudioSource() { + // + // Record destruction of LLAudioSource object. + if(mType != LLAudioEngine::AUDIO_TYPE_UI) + logSoundStop(mLogID, true); + // if (mChannelp) { // Stop playback of this sound mChannelp->setSource(NULL); - mChannelp = NULL; + setChannel(NULL); } - // - if(mType != LLAudioEngine::AUDIO_TYPE_UI) // && mSourceID.notNull()) - logSoundStop(mLogID); - // } @@ -1356,10 +1357,17 @@ void LLAudioSource::setChannel(LLAudioChannel *channelp) return; } + // + if (!channelp) + { + if(mType != LLAudioEngine::AUDIO_TYPE_UI) + logSoundStop(mLogID, false); + } + // + mChannelp = channelp; } - void LLAudioSource::update() { if (!getCurrentBuffer()) @@ -1434,10 +1442,6 @@ bool LLAudioSource::setupChannel() bool LLAudioSource::play(const LLUUID &audio_uuid) { - // - if(mType != LLAudioEngine::AUDIO_TYPE_UI) //&& mSourceID.notNull()) - logSoundPlay(mLogID, this, mPositionGlobal, mType, audio_uuid, mOwnerID, mSourceID, mIsTrigger, mLoop); // is mID okay for source id? - // // Special abuse of play(); don't play a sound, but kill it. if (audio_uuid.isNull()) { @@ -1453,6 +1457,11 @@ bool LLAudioSource::play(const LLUUID &audio_uuid) return false; } + // + if(mType != LLAudioEngine::AUDIO_TYPE_UI) //&& mSourceID.notNull()) + logSoundPlay(this, audio_uuid); + // + // Reset our age timeout if someone attempts to play the source. mAgeTimer.reset(); @@ -1846,36 +1855,38 @@ bool LLAudioData::load() std::map gSoundHistory; // static -void logSoundPlay(LLUUID id, LLAudioSource* audio_source, LLVector3d position, S32 type, LLUUID assetid, LLUUID ownerid, LLUUID sourceid, bool is_trigger, bool is_looped) +void logSoundPlay(LLAudioSource* audio_source, LLUUID const& assetid) { LLSoundHistoryItem item; - item.mID = id; + item.mID = audio_source->getLogID(); item.mAudioSource = audio_source; - item.mPosition = position; - item.mType = type; + item.mPosition = audio_source->getPositionGlobal(); + item.mType = audio_source->getType(); item.mAssetID = assetid; - item.mOwnerID = ownerid; - item.mSourceID = sourceid; + item.mOwnerID = audio_source->getOwnerID(); + item.mSourceID = audio_source->getSourceID(); item.mPlaying = true; item.mTimeStarted = LLTimer::getElapsedSeconds(); item.mTimeStopped = F64_MAX; - item.mIsTrigger = is_trigger; - item.mIsLooped = is_looped; + item.mIsTrigger = audio_source->getIsTrigger(); + item.mIsLooped = audio_source->isLoop(); item.mReviewed = false; item.mReviewedCollision = false; - gSoundHistory[id] = item; + gSoundHistory[item.mID] = item; } //static -void logSoundStop(LLUUID id) +void logSoundStop(LLUUID const& id, bool destructed) { - if(gSoundHistory.find(id) != gSoundHistory.end()) + std::map::iterator iter = gSoundHistory.find(id); + if(iter != gSoundHistory.end() && iter->second.mAudioSource) { - gSoundHistory[id].mPlaying = false; - gSoundHistory[id].mTimeStopped = LLTimer::getElapsedSeconds(); - gSoundHistory[id].mAudioSource = NULL; // just in case + iter->second.mPlaying = false; + iter->second.mTimeStopped = LLTimer::getElapsedSeconds(); + if (destructed) + iter->second.mAudioSource = NULL; pruneSoundLog(); } } diff --git a/indra/llaudio/llaudioengine.h b/indra/llaudio/llaudioengine.h index 83f7f66a5..c41458553 100644 --- a/indra/llaudio/llaudioengine.h +++ b/indra/llaudio/llaudioengine.h @@ -306,7 +306,11 @@ public: void setPlayedOnce(const bool played_once) { mPlayedOnce = played_once; } void setType(S32 type) { mType = type; } - S32 getType() { return mType; } + S32 getType(void) const { return mType; } + + LLUUID const& getOwnerID(void) const { return mOwnerID; } + LLUUID const& getSourceID(void) const { return mSourceID; } + bool getIsTrigger(void) const { return mIsTrigger; } void setPositionGlobal(const LLVector3d &position_global) { mPositionGlobal = position_global; } LLVector3d getPositionGlobal() const { return mPositionGlobal; } @@ -337,6 +341,7 @@ public: friend class LLAudioChannel; protected: void setChannel(LLAudioChannel *channelp); +public: LLAudioChannel *getChannel() const { return mChannelp; } protected: @@ -430,17 +435,22 @@ public: friend class LLAudioEngine; friend class LLAudioSource; + protected: virtual void play() = 0; virtual void playSynced(LLAudioChannel *channelp) = 0; virtual void cleanup() = 0; + void setWaiting(bool waiting) { mWaiting = waiting; } + +public: virtual bool isPlaying() = 0; - void setWaiting(const bool waiting) { mWaiting = waiting; } bool isWaiting() const { return mWaiting; } +protected: virtual bool updateBuffer(); // Check to see if the buffer associated with the source changed, and update if necessary. virtual void update3DPosition() = 0; virtual void updateLoop() = 0; // Update your loop/completion status, for use by queueing/syncing. + protected: LLAudioSource *mCurrentSourcep; LLAudioBuffer *mCurrentBufferp; @@ -498,12 +508,23 @@ struct LLSoundHistoryItem LLSoundHistoryItem() : mType(0), mPlaying(false), mIsTrigger(false), mIsLooped(false), mReviewed(false), mReviewedCollision(false), mTimeStarted(0), mTimeStopped(0), mAudioSource(0) {} + + bool isPlaying(void) const + { + return mPlaying && mAudioSource && mAudioSource->getChannel() + // It's only REALLY playing if the following also returns true, + // but it's too hard detect when that part is starting/stopping, + // so in the sound explorer we call "playing" (or "looping") + // those audio source that have a channel assigned and call + // it a day. + /*&& mAudioSource->getChannel()->isPlaying()*/ ; + } }; extern std::map gSoundHistory; -extern void logSoundPlay(LLUUID id, LLAudioSource* audio_source, LLVector3d position, S32 type, LLUUID assetid, LLUUID ownerid, LLUUID sourceid, bool is_trigger, bool is_looped); -extern void logSoundStop(LLUUID id); +extern void logSoundPlay(LLAudioSource* audio_source, LLUUID const& assetid); +extern void logSoundStop(LLUUID const& id, bool destructed); extern void pruneSoundLog(); extern int gSoundHistoryPruneCounter; diff --git a/indra/llcharacter/llbvhloader.cpp b/indra/llcharacter/llbvhloader.cpp index 7a516f838..12bcffac2 100644 --- a/indra/llcharacter/llbvhloader.cpp +++ b/indra/llcharacter/llbvhloader.cpp @@ -48,10 +48,10 @@ using namespace std; #define INCHES_TO_METERS 0.02540005f -const F32 POSITION_KEYFRAME_THRESHOLD = 0.03f; +const F32 POSITION_KEYFRAME_THRESHOLD_SQUARED = 0.03f * 0.03f; const F32 ROTATION_KEYFRAME_THRESHOLD = 0.01f; -const F32 POSITION_MOTION_THRESHOLD = 0.001f; +const F32 POSITION_MOTION_THRESHOLD_SQUARED = 0.001f * 0.001f; const F32 ROTATION_MOTION_THRESHOLD = 0.001f; char gInFile[1024]; /* Flawfinder: ignore */ @@ -1202,7 +1202,7 @@ void LLBVHLoader::optimize() if (ki_prev == ki_last_good_pos) { joint->mNumPosKeys++; - if (dist_vec(LLVector3(ki_prev->mPos), first_frame_pos) > POSITION_MOTION_THRESHOLD) + if (dist_vec_squared(LLVector3(ki_prev->mPos), first_frame_pos) > POSITION_MOTION_THRESHOLD_SQUARED) { pos_changed = TRUE; } @@ -1215,12 +1215,12 @@ void LLBVHLoader::optimize() LLVector3 current_pos(ki->mPos); LLVector3 interp_pos = lerp(current_pos, last_good_pos, 1.f / (F32)numPosFramesConsidered); - if (dist_vec(current_pos, first_frame_pos) > POSITION_MOTION_THRESHOLD) + if (dist_vec_squared(current_pos, first_frame_pos) > POSITION_MOTION_THRESHOLD_SQUARED) { pos_changed = TRUE; } - if (dist_vec(interp_pos, test_pos) < POSITION_KEYFRAME_THRESHOLD) + if (dist_vec_squared(interp_pos, test_pos) < POSITION_KEYFRAME_THRESHOLD_SQUARED) { ki_prev->mIgnorePos = TRUE; numPosFramesConsidered++; diff --git a/indra/llcharacter/llcharacter.h b/indra/llcharacter/llcharacter.h index 4de59e9ee..f7206f750 100644 --- a/indra/llcharacter/llcharacter.h +++ b/indra/llcharacter/llcharacter.h @@ -261,7 +261,7 @@ public: } return 0; } - S32 getVisualParamCount() { return (S32)mVisualParamIndexMap.size(); } + S32 getVisualParamCount() const { return (S32)mVisualParamIndexMap.size(); } LLVisualParam* getVisualParam(const char *name); diff --git a/indra/llcharacter/llkeyframemotion.h b/indra/llcharacter/llkeyframemotion.h index 7e8c84488..50d9d0504 100644 --- a/indra/llcharacter/llkeyframemotion.h +++ b/indra/llcharacter/llkeyframemotion.h @@ -47,7 +47,6 @@ #include "llquaternion.h" #include "v3dmath.h" #include "v3math.h" -#include "llapr.h" #include "llbvhconsts.h" class LLKeyframeDataCache; diff --git a/indra/llcharacter/llkeyframestandmotion.cpp b/indra/llcharacter/llkeyframestandmotion.cpp index 1d42298f4..1ae0ddeea 100644 --- a/indra/llcharacter/llkeyframestandmotion.cpp +++ b/indra/llcharacter/llkeyframestandmotion.cpp @@ -190,7 +190,7 @@ BOOL LLKeyframeStandMotion::onUpdate(F32 time, U8* joint_mask) if (dot(mPelvisState->getJoint()->getWorldRotation(), mLastGoodPelvisRotation) < ROTATION_THRESHOLD) { mLastGoodPelvisRotation = mPelvisState->getJoint()->getWorldRotation(); - mLastGoodPelvisRotation.normQuat(); + mLastGoodPelvisRotation.normalize(); mTrackAnkles = TRUE; } else if ((mCharacter->getCharacterPosition() - mLastGoodPosition).magVecSquared() > POSITION_THRESHOLD) diff --git a/indra/llcharacter/llpose.h b/indra/llcharacter/llpose.h index 5698f2161..80487bd12 100644 --- a/indra/llcharacter/llpose.h +++ b/indra/llcharacter/llpose.h @@ -36,12 +36,12 @@ //----------------------------------------------------------------------------- // Header Files //----------------------------------------------------------------------------- -#include -#include "llmap.h" #include "lljointstate.h" #include "lljoint.h" +#include "llmap.h" #include +#include //----------------------------------------------------------------------------- diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index 29fa35619..47cddfdba 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -2,6 +2,7 @@ project(llcommon) +include(Cwdebug) include(00-Common) include(LLCommon) include(Linking) @@ -32,6 +33,7 @@ set(llcommon_SOURCE_FILES llerror.cpp llerrorthread.cpp llevent.cpp + lleventtimer.cpp llfasttimer.cpp llfile.cpp llfindlocale.cpp @@ -39,6 +41,7 @@ set(llcommon_SOURCE_FILES llformat.cpp llframetimer.cpp llheartbeat.cpp + llinstancetracker.cpp llindraconfigfile.cpp llliveappconfig.cpp lllivefile.cpp @@ -60,6 +63,7 @@ set(llcommon_SOURCE_FILES llsdutil.cpp llsecondlifeurls.cpp llstat.cpp + llstacktrace.cpp llstreamtools.cpp llstring.cpp llstringtable.cpp @@ -89,12 +93,12 @@ set(llcommon_HEADER_FILES linden_common.h linked_lists.h llagentconstants.h + llavatarname.h llapp.h llapr.h llassettype.h llassoclist.h llavatarconstants.h - llavatarname.h llbase32.h llbase64.h llboost.h @@ -122,6 +126,7 @@ set(llcommon_HEADER_FILES llevent.h lleventemitter.h llextendedstatus.h + lleventtimer.h llfasttimer.h llfile.h llfindlocale.h @@ -132,6 +137,7 @@ set(llcommon_HEADER_FILES llheartbeat.h llhttpstatuscodes.h llindexedqueue.h + llinstancetracker.h llindraconfigfile.h llkeythrottle.h lllinkedqueue.h @@ -168,6 +174,7 @@ set(llcommon_HEADER_FILES llskiplist.h llskipmap.h llstack.h + llstacktrace.h llstat.h llstatenums.h llstl.h @@ -188,7 +195,6 @@ set(llcommon_HEADER_FILES metaclasst.h metaproperty.h metapropertyt.h - processor.h reflective.h reflectivet.h roles_constants.h @@ -214,8 +220,14 @@ target_link_libraries( ${EXPAT_LIBRARIES} ${ZLIB_LIBRARIES} ${WINDOWS_LIBRARIES} + ${CWDEBUG_LIBRARIES} ) +if (LINUX) + # When linking with llcommon later, we do not want to link with cwdebug.a again. + set_property(TARGET llcommon PROPERTY LINK_INTERFACE_LIBRARIES "-lapr-1 -laprutil-1 -lz") +endif (LINUX) + if (DARWIN) # Don't embed a full path in the library's install name set_target_properties( diff --git a/indra/llcommon/aithreadsafe.h b/indra/llcommon/aithreadsafe.h index 2575ba25f..52c4ac8d2 100644 --- a/indra/llcommon/aithreadsafe.h +++ b/indra/llcommon/aithreadsafe.h @@ -51,6 +51,14 @@ template struct AIReadAccess; template struct AIWriteAccess; template struct AIAccess; +#if LL_WINDOWS +template class AIThreadSafeBits; +template +struct AIThreadSafeWindowsHack { + AIThreadSafeWindowsHack(AIThreadSafeBits& var, T* object); +}; +#endif + template class AIThreadSafeBits { @@ -73,6 +81,9 @@ public: void* memory() const { return const_cast(&mMemory[0]); } protected: +#if LL_WINDOWS + template friend struct AIThreadSafeWindowsHack; +#endif // Accessors. T const* ptr() const { return reinterpret_cast(mMemory); } T* ptr() { return reinterpret_cast(mMemory); } @@ -168,7 +179,12 @@ protected: public: // Only for use by AITHREADSAFE, see below. - AIThreadSafe(T* object) { llassert(object == AIThreadSafeBits::ptr()); } + AIThreadSafe(T* object) + { +#if !LL_WINDOWS + llassert(object == AIThreadSafeBits::ptr()); +#endif + } }; /** @@ -191,7 +207,18 @@ public: * Note: This macro does not allow to allocate such object on the heap. * If that is needed, have a look at AIThreadSafeDC. */ +#if LL_WINDOWS +template +AIThreadSafeWindowsHack::AIThreadSafeWindowsHack(AIThreadSafeBits& var, T* object) +{ + llassert(object == var.ptr()); +} +#define AITHREADSAFE(type, var, paramlist) \ + AIThreadSafe var(NULL); \ + AIThreadSafeWindowsHack dummy_##var(var, new (var.memory()) type paramlist) +#else #define AITHREADSAFE(type, var, paramlist) AIThreadSafe var(new (var.memory()) type paramlist) +#endif /** * @brief A wrapper class for objects that need to be accessed by more than one thread. @@ -278,11 +305,11 @@ struct AIReadAccessConst protected: //! Constructor used by AIReadAccess. AIReadAccessConst(AIThreadSafe& wrapper, state_type state) - : mWrapper(wrapper), mState(state) + : mWrapper(wrapper), mState(state) #if AI_NEED_ACCESS_CC , mIsCopyConstructed(false) #endif - { } + { } AIThreadSafe& mWrapper; //!< Reference to the object that we provide access to. state_type const mState; //!< The lock state that mWrapper is in. @@ -376,7 +403,8 @@ protected: // Locking control. LLMutex mMutex; - // For use by AIThreadSafeSimpleDC + friend struct AIRegisteredStateMachinesList; + // For use by AIThreadSafeSimpleDC and AIRegisteredStateMachinesList. AIThreadSafeSimple(void) { } AIThreadSafeSimple(AIAPRPool& parent) : mMutex(parent) { } diff --git a/indra/llcommon/indra_constants.h b/indra/llcommon/indra_constants.h index 3725b1d84..a95b6499d 100644 --- a/indra/llcommon/indra_constants.h +++ b/indra/llcommon/indra_constants.h @@ -48,7 +48,7 @@ class LLUUID; #define PHYSICS_TIMESTEP (1.f / 45.f) const F32 COLLISION_TOLERANCE = 0.1f; -const F32 HALF_COLLISION_TOLERANCE = COLLISION_TOLERANCE * 0.5f; +const F32 HALF_COLLISION_TOLERANCE = 0.05f; // Time constants const U32 HOURS_PER_LINDEN_DAY = 4; @@ -99,9 +99,9 @@ const F32 MIN_AGENT_WIDTH = 0.40f; const F32 DEFAULT_AGENT_WIDTH = 0.60f; const F32 MAX_AGENT_WIDTH = 0.80f; -const F32 MIN_AGENT_HEIGHT = 1.3f - 2.0f * COLLISION_TOLERANCE; +const F32 MIN_AGENT_HEIGHT = 1.1f; const F32 DEFAULT_AGENT_HEIGHT = 1.9f; -const F32 MAX_AGENT_HEIGHT = 2.65f - 2.0f * COLLISION_TOLERANCE; +const F32 MAX_AGENT_HEIGHT = 2.45f; // For linked sets const S32 MAX_CHILDREN_PER_TASK = 255; @@ -252,9 +252,6 @@ const U8 SIM_ACCESS_ADULT = 42; // Seriously Adult Only const U8 SIM_ACCESS_DOWN = 254; const U8 SIM_ACCESS_MAX = SIM_ACCESS_ADULT; -// group constants -const S32 DEFAULT_MAX_AGENT_GROUPS = 25; - // attachment constants const S32 MAX_AGENT_ATTACHMENTS = 38; const U8 ATTACHMENT_ADD = 0x80; @@ -293,6 +290,7 @@ const U8 UPD_UNIFORM = 0x10; // used with UPD_SCALE // Agent Update Flags (U8) const U8 AU_FLAGS_NONE = 0x00; const U8 AU_FLAGS_HIDETITLE = 0x01; +const U8 AU_FLAGS_CLIENT_AUTOPILOT = 0x02; // start location constants const U32 START_LOCATION_ID_LAST = 0; @@ -306,6 +304,14 @@ const U32 START_LOCATION_ID_COUNT = 6; // group constants const U32 GROUP_MIN_SIZE = 2; +// gMaxAgentGroups is now sent by login.cgi, which +// looks it up from globals.xml. +// +// For now we need an old default value however, +// so the viewer can be deployed ahead of login.cgi. +// +const S32 DEFAULT_MAX_AGENT_GROUPS = 25; + // radius within which a chat message is fully audible const F32 CHAT_WHISPER_RADIUS = 10.f; const F32 CHAT_NORMAL_RADIUS = 20.f; diff --git a/indra/llcommon/linden_common.h b/indra/llcommon/linden_common.h index 6e66e9916..d486359c7 100644 --- a/indra/llcommon/linden_common.h +++ b/indra/llcommon/linden_common.h @@ -33,6 +33,8 @@ #ifndef LL_LINDEN_COMMON_H #define LL_LINDEN_COMMON_H +#include "cwdebug.h" + #if defined(LL_WINDOWS) && defined(_DEBUG) # if _MSC_VER >= 1400 // Visual C++ 2005 or later # define _CRTDBG_MAP_ALLOC diff --git a/indra/llcommon/llapp.cpp b/indra/llcommon/llapp.cpp index 3bb833a94..c35a84255 100644 --- a/indra/llcommon/llapp.cpp +++ b/indra/llcommon/llapp.cpp @@ -38,8 +38,10 @@ #include "llerrorcontrol.h" #include "llerrorthread.h" #include "llframetimer.h" +#include "lllivefile.h" #include "llmemory.h" -#include "lltimer.h" +#include "llstl.h" // for DeletePointer() +#include "lleventtimer.h" // // Signal handling @@ -139,6 +141,11 @@ LLApp::~LLApp() delete sSigChildCount; sSigChildCount = NULL; #endif + + // reclaim live file memory + std::for_each(mLiveFiles.begin(), mLiveFiles.end(), DeletePointer()); + mLiveFiles.clear(); + setStopped(); // HACK: wait for the error thread to clean itself ms_sleep(20); @@ -212,6 +219,15 @@ bool LLApp::parseCommandOptions(int argc, char** argv) return true; } + +void LLApp::manageLiveFile(LLLiveFile* livefile) +{ + if(!livefile) return; + livefile->checkAndReload(); + livefile->addToEventTimer(); + mLiveFiles.push_back(livefile); +} + bool LLApp::setOptionData(OptionPriority level, LLSD data) { if((level < 0) diff --git a/indra/llcommon/llapp.h b/indra/llcommon/llapp.h index d5cf6ea93..05e2bccaf 100644 --- a/indra/llcommon/llapp.h +++ b/indra/llcommon/llapp.h @@ -131,6 +131,19 @@ public: */ bool parseCommandOptions(int argc, char** argv); + /** + * @brief Keep track of live files automatically. + * + * *TODO: it currently uses the addToEventTimer() API + * instead of the runner. I should probalby use the runner. + * + * *NOTE: DO NOT add the livefile instance to any kind of check loop. + * + * @param livefile A valid instance of an LLLiveFile. This LLApp + * instance will delete the livefile instance. + */ + void manageLiveFile(LLLiveFile* livefile); + /** * @brief Set the options at the specified priority. * @@ -285,6 +298,8 @@ private: // The application options. LLSD mOptions; + // The live files for this application + std::vector mLiveFiles; //@} private: diff --git a/indra/llcommon/llapr.cpp b/indra/llcommon/llapr.cpp index 9595707cb..d2169d65e 100644 --- a/indra/llcommon/llapr.cpp +++ b/indra/llcommon/llapr.cpp @@ -81,7 +81,7 @@ bool ll_apr_warn_status(apr_status_t status) { if(APR_SUCCESS == status) return false; char buf[MAX_STRING]; /* Flawfinder: ignore */ - apr_strerror(status, buf, MAX_STRING); + apr_strerror(status, buf, sizeof(buf)); LL_WARNS("APR") << "APR: " << buf << LL_ENDL; return true; } diff --git a/indra/llcommon/llassettype.cpp b/indra/llcommon/llassettype.cpp index f9c73a20a..13c8f649d 100644 --- a/indra/llcommon/llassettype.cpp +++ b/indra/llcommon/llassettype.cpp @@ -33,207 +33,115 @@ #include "linden_common.h" #include "llassettype.h" +#include "lldictionary.h" +#include "llmemory.h" -#include "llstring.h" -#include "lltimer.h" - -// I added lookups for exact text of asset type enums in addition to the ones below, so shoot me. -Steve - -struct asset_info_t +///---------------------------------------------------------------------------- +/// Class LLAssetType +///---------------------------------------------------------------------------- +struct AssetEntry : public LLDictionaryEntry { - LLAssetType::EType type; - const char* desc; + AssetEntry(const char *desc_name, + const char *type_name, // 8 character limit! + const char *human_name, // for decoding to human readable form; put any and as many printable characters you want in each one + bool can_link, // can you create a link to this type? + bool can_fetch, // can you fetch this asset by ID? + bool can_know) // can you see this asset's ID? + : + LLDictionaryEntry(desc_name), + mTypeName(type_name), + mHumanName(human_name), + mCanLink(can_link), + mCanFetch(can_fetch), + mCanKnow(can_know) + { + llassert(strlen(mTypeName) <= 8); + } + + const char *mTypeName; + const char *mHumanName; + bool mCanLink; + bool mCanFetch; + bool mCanKnow; }; -asset_info_t asset_types[] = +class LLAssetDictionary : public LLSingleton, + public LLDictionary { - { LLAssetType::AT_TEXTURE, "TEXTURE" }, - { LLAssetType::AT_SOUND, "SOUND" }, - { LLAssetType::AT_CALLINGCARD, "CALLINGCARD" }, - { LLAssetType::AT_LANDMARK, "LANDMARK" }, - { LLAssetType::AT_SCRIPT, "SCRIPT" }, - { LLAssetType::AT_CLOTHING, "CLOTHING" }, - { LLAssetType::AT_OBJECT, "OBJECT" }, - { LLAssetType::AT_NOTECARD, "NOTECARD" }, - { LLAssetType::AT_CATEGORY, "CATEGORY" }, - { LLAssetType::AT_ROOT_CATEGORY, "ROOT_CATEGORY" }, - { LLAssetType::AT_LSL_TEXT, "LSL_TEXT" }, - { LLAssetType::AT_LSL_BYTECODE, "LSL_BYTECODE" }, - { LLAssetType::AT_TEXTURE_TGA, "TEXTURE_TGA" }, - { LLAssetType::AT_BODYPART, "BODYPART" }, - { LLAssetType::AT_TRASH, "TRASH" }, - { LLAssetType::AT_SNAPSHOT_CATEGORY, "SNAPSHOT_CATEGORY" }, - { LLAssetType::AT_LOST_AND_FOUND, "LOST_AND_FOUND" }, - { LLAssetType::AT_SOUND_WAV, "SOUND_WAV" }, - { LLAssetType::AT_IMAGE_TGA, "IMAGE_TGA" }, - { LLAssetType::AT_IMAGE_JPEG, "IMAGE_JPEG" }, - { LLAssetType::AT_ANIMATION, "ANIMATION" }, - { LLAssetType::AT_GESTURE, "GESTURE" }, - { LLAssetType::AT_SIMSTATE, "SIMSTATE" }, - { LLAssetType::AT_FAVORITE, "FAVORITE" }, - { LLAssetType::AT_LINK, "LINK" }, - { LLAssetType::AT_LINK_FOLDER, "CURRENT" }, - { LLAssetType::AT_CURRENT_OUTFIT, "FOLDER_LINK" }, - { LLAssetType::AT_OUTFIT, "OUTFIT" }, - { LLAssetType::AT_MY_OUTFITS, "MY_OUTFITS" }, - { LLAssetType::AT_NONE, "NONE" } +public: + LLAssetDictionary(); }; -LLAssetType::EType LLAssetType::getType(const std::string& sin) +LLAssetDictionary::LLAssetDictionary() { - std::string s = sin; + // DESCRIPTION TYPE NAME HUMAN NAME CAN LINK? CAN FETCH? CAN KNOW? + // |--------------------|-----------|-------------------|-----------|-----------|---------| + addEntry(LLAssetType::AT_TEXTURE, new AssetEntry("TEXTURE", "texture", "texture", true, false, true)); + addEntry(LLAssetType::AT_SOUND, new AssetEntry("SOUND", "sound", "sound", true, true, true)); + addEntry(LLAssetType::AT_CALLINGCARD, new AssetEntry("CALLINGCARD", "callcard", "calling card", true, false, false)); + addEntry(LLAssetType::AT_LANDMARK, new AssetEntry("LANDMARK", "landmark", "landmark", true, true, true)); + addEntry(LLAssetType::AT_SCRIPT, new AssetEntry("SCRIPT", "script", "legacy script", true, false, false)); + addEntry(LLAssetType::AT_CLOTHING, new AssetEntry("CLOTHING", "clothing", "clothing", true, true, true)); + addEntry(LLAssetType::AT_OBJECT, new AssetEntry("OBJECT", "object", "object", true, false, false)); + addEntry(LLAssetType::AT_NOTECARD, new AssetEntry("NOTECARD", "notecard", "note card", true, false, true)); + addEntry(LLAssetType::AT_CATEGORY, new AssetEntry("CATEGORY", "category", "folder", true, false, false)); + addEntry(LLAssetType::AT_ROOT_CATEGORY, new AssetEntry("ROOT_CATEGORY", "root", "root", false, false, false)); + addEntry(LLAssetType::AT_LSL_TEXT, new AssetEntry("LSL_TEXT", "lsltext", "lsl2 script", true, false, false)); + addEntry(LLAssetType::AT_LSL_BYTECODE, new AssetEntry("LSL_BYTECODE", "lslbyte", "lsl bytecode", true, false, false)); + addEntry(LLAssetType::AT_TEXTURE_TGA, new AssetEntry("TEXTURE_TGA", "txtr_tga", "tga texture", true, false, false)); + addEntry(LLAssetType::AT_BODYPART, new AssetEntry("BODYPART", "bodypart", "body part", true, true, true)); + addEntry(LLAssetType::AT_TRASH, new AssetEntry("TRASH", "trash", "trash", false, false, false)); + addEntry(LLAssetType::AT_SNAPSHOT_CATEGORY, new AssetEntry("SNAPSHOT_CATEGORY", "snapshot", "snapshot", false, false, false)); + addEntry(LLAssetType::AT_LOST_AND_FOUND, new AssetEntry("LOST_AND_FOUND", "lstndfnd", "lost and found", false, false, false)); + addEntry(LLAssetType::AT_SOUND_WAV, new AssetEntry("SOUND_WAV", "snd_wav", "sound", true, false, false)); + addEntry(LLAssetType::AT_IMAGE_TGA, new AssetEntry("IMAGE_TGA", "img_tga", "targa image", true, false, false)); + addEntry(LLAssetType::AT_IMAGE_JPEG, new AssetEntry("IMAGE_JPEG", "jpeg", "jpeg image", true, false, false)); + addEntry(LLAssetType::AT_ANIMATION, new AssetEntry("ANIMATION", "animatn", "animation", true, true, true)); + addEntry(LLAssetType::AT_GESTURE, new AssetEntry("GESTURE", "gesture", "gesture", true, true, true)); + addEntry(LLAssetType::AT_SIMSTATE, new AssetEntry("SIMSTATE", "simstate", "simstate", false, false, false)); + addEntry(LLAssetType::AT_FAVORITE, new AssetEntry("FAVORITE", "favorite", "", false, false, false)); + addEntry(LLAssetType::AT_LINK, new AssetEntry("LINK", "link", "sym link", false, false, true)); + addEntry(LLAssetType::AT_LINK_FOLDER, new AssetEntry("FOLDER_LINK", "link_f", "sym folder link", false, false, true)); + addEntry(LLAssetType::AT_CURRENT_OUTFIT, new AssetEntry("FOLDER_LINK", "current", "current outfit", false, false, false)); + addEntry(LLAssetType::AT_OUTFIT, new AssetEntry("OUTFIT", "outfit", "outfit", false, false, false)); + addEntry(LLAssetType::AT_MY_OUTFITS, new AssetEntry("MY_OUTFITS", "my_otfts", "my outfits", false, false, false)); + addEntry(LLAssetType::AT_NONE, new AssetEntry("NONE", "-1", NULL, false, false, false)); +}; + +// static +LLAssetType::EType LLAssetType::getType(const std::string& desc_name) +{ + std::string s = desc_name; LLStringUtil::toUpper(s); - for (S32 idx = 0; ;idx++) - { - asset_info_t* info = asset_types + idx; - if (info->type == LLAssetType::AT_NONE) - break; - if (s == info->desc) - return info->type; - } - return LLAssetType::AT_NONE; + return LLAssetDictionary::getInstance()->lookup(s); } -std::string LLAssetType::getDesc(LLAssetType::EType type) -{ - for (S32 idx = 0; ;idx++) - { - asset_info_t* info = asset_types + idx; - if (type == info->type) - return info->desc; - if (info->type == LLAssetType::AT_NONE) - break; - } - return "BAD TYPE"; -} - -//============================================================================ - -// The asset type names are limited to 8 characters. // static -const char* LLAssetType::mAssetTypeNames[LLAssetType::AT_COUNT] = -{ - "texture", - "sound", - "callcard", - "landmark", - "script", - "clothing", - "object", - "notecard", - "category", - "root", - "lsltext", - "lslbyte", - "txtr_tga",// Intentionally spelled this way. Limited to eight characters. - "bodypart", - "trash", - "snapshot", - "lstndfnd", - "snd_wav", - "img_tga", - "jpeg", - "animatn", - "gesture", - "simstate", - "favorite", - "link", - "link_f", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "current", - "outfit", - "my_otfts" -}; - -// This table is meant for decoding to human readable form. Put any -// and as many printable characters you want in each one. -// See also llinventory.cpp INVENTORY_TYPE_HUMAN_NAMES -const char* LLAssetType::mAssetTypeHumanNames[LLAssetType::AT_COUNT] = -{ - "texture", - "sound", - "calling card", - "landmark", - "legacy script", - "clothing", - "object", - "note card", - "folder", - "root", - "lsl2 script", - "lsl bytecode", - "tga texture", - "body part", - "trash", - "snapshot", - "lost and found", - "sound", - "targa image", - "jpeg image", - "animation", - "gesture", - "simstate", - "", - "symbolic link", - "symbolic folder link" - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "current outfit", - "outfit", - "my outfits" -}; - -///---------------------------------------------------------------------------- -/// class LLAssetType -///---------------------------------------------------------------------------- - -// static -const char* LLAssetType::lookup( LLAssetType::EType type ) +const std::string &LLAssetType::getDesc(LLAssetType::EType asset_type) { - if( (type >= 0) && (type < AT_COUNT )) + const AssetEntry *entry = LLAssetDictionary::getInstance()->lookup(asset_type); + if (entry) { - return mAssetTypeNames[ S32( type ) ]; + return entry->mName; } else { - return "-1"; + return badLookup(); + } +} + +// static +const char *LLAssetType::lookup(LLAssetType::EType asset_type) +{ + const LLAssetDictionary *dict = LLAssetDictionary::getInstance(); + const AssetEntry *entry = dict->lookup(asset_type); + if (entry) + { + return entry->mTypeName; + } + else + { + return badLookup().c_str(); } } @@ -243,29 +151,35 @@ LLAssetType::EType LLAssetType::lookup( const char* name ) return lookup(ll_safe_string(name)); } -LLAssetType::EType LLAssetType::lookup( const std::string& name ) +// static +LLAssetType::EType LLAssetType::lookup(const std::string& type_name) { - for( S32 i = 0; i < AT_COUNT; i++ ) + const LLAssetDictionary *dict = LLAssetDictionary::getInstance(); + for (LLAssetDictionary::const_iterator iter = dict->begin(); + iter != dict->end(); + iter++) { - if( name == mAssetTypeNames[i] ) + const AssetEntry *entry = iter->second; + if (type_name == entry->mTypeName) { - // match - return (EType)i; + return iter->first; } } return AT_NONE; } // static -const char* LLAssetType::lookupHumanReadable(LLAssetType::EType type) +const char *LLAssetType::lookupHumanReadable(LLAssetType::EType asset_type) { - if( (type >= 0) && (type < AT_COUNT )) + const LLAssetDictionary *dict = LLAssetDictionary::getInstance(); + const AssetEntry *entry = dict->lookup(asset_type); + if (entry) { - return mAssetTypeHumanNames[S32(type)]; + return entry->mHumanName; } else { - return NULL; + return badLookup().c_str(); } } @@ -275,14 +189,18 @@ LLAssetType::EType LLAssetType::lookupHumanReadable( const char* name ) return lookupHumanReadable(ll_safe_string(name)); } -LLAssetType::EType LLAssetType::lookupHumanReadable( const std::string& name ) +// static +LLAssetType::EType LLAssetType::lookupHumanReadable(const std::string& readable_name) { - for( S32 i = 0; i < AT_COUNT; i++ ) + const LLAssetDictionary *dict = LLAssetDictionary::getInstance(); + for (LLAssetDictionary::const_iterator iter = dict->begin(); + iter != dict->end(); + iter++) { - if( name == mAssetTypeHumanNames[i] ) + const AssetEntry *entry = iter->second; + if (entry->mHumanName && (readable_name == entry->mHumanName)) { - // match - return (EType)i; + return iter->first; } } return AT_NONE; @@ -333,6 +251,16 @@ void LLAssetType::generateDescriptionFor(LLAssetType::EType type, // static bool LLAssetType::lookupCanLink(EType asset_type) { + //Check that enabling all these other types as linkable doesn't break things. + /*const LLAssetDictionary *dict = LLAssetDictionary::getInstance(); + const AssetEntry *entry = dict->lookup(asset_type); + if (entry) + { + return entry->mCanLink; + } + return false; + */ + return (asset_type == AT_CLOTHING || asset_type == AT_OBJECT || asset_type == AT_CATEGORY || asset_type == AT_BODYPART || asset_type == AT_GESTURE); } @@ -341,45 +269,42 @@ bool LLAssetType::lookupCanLink(EType asset_type) // Not adding this to dictionary since we probably will only have these two types bool LLAssetType::lookupIsLinkType(EType asset_type) { - return (asset_type == AT_LINK || asset_type == AT_LINK_FOLDER); + if (asset_type == AT_LINK || asset_type == AT_LINK_FOLDER) + { + return true; + } + return false; +} + +// static +const std::string &LLAssetType::badLookup() +{ + static const std::string sBadLookup = "llassettype_bad_lookup"; + return sBadLookup; + } // static bool LLAssetType::lookupIsAssetFetchByIDAllowed(EType asset_type) { - // *FIX: Make this list smaller. - switch(asset_type) + const LLAssetDictionary *dict = LLAssetDictionary::getInstance(); + const AssetEntry *entry = dict->lookup(asset_type); + if (entry) { - case LLAssetType::AT_SOUND: - case LLAssetType::AT_LANDMARK: - case LLAssetType::AT_CLOTHING: - case LLAssetType::AT_BODYPART: - case LLAssetType::AT_ANIMATION: - case LLAssetType::AT_GESTURE: - return true; - default: - return false; + return entry->mCanFetch; } + return false; } // static bool LLAssetType::lookupIsAssetIDKnowable(EType asset_type) { - switch(asset_type) + const LLAssetDictionary *dict = LLAssetDictionary::getInstance(); + const AssetEntry *entry = dict->lookup(asset_type); + if (entry) { - case LLAssetType::AT_TEXTURE: - case LLAssetType::AT_SOUND: - case LLAssetType::AT_LANDMARK: - case LLAssetType::AT_CLOTHING: - case LLAssetType::AT_NOTECARD: - case LLAssetType::AT_BODYPART: - case LLAssetType::AT_ANIMATION: - case LLAssetType::AT_GESTURE: - case LLAssetType::AT_LINK: - case LLAssetType::AT_LINK_FOLDER: - return true; - default: - return false; + return entry->mCanKnow; } + return false; } diff --git a/indra/llcommon/llassettype.h b/indra/llcommon/llassettype.h index a769e165c..0363956d7 100644 --- a/indra/llcommon/llassettype.h +++ b/indra/llcommon/llassettype.h @@ -160,39 +160,41 @@ public: }; // machine transation between type and strings - static EType lookup(const char* name); // safe conversion to std::string, *TODO: deprecate - static EType lookup(const std::string& name); - static const char* lookup(EType type); + static EType lookup(const char* name); // safe conversion to std::string, *TODO: deprecate + static EType lookup(const std::string& type_name); + static const char* lookup(EType asset_type); // translation from a type to a human readable form. - static EType lookupHumanReadable( const char* name ); // safe conversion to std::string, *TODO: deprecate - static EType lookupHumanReadable( const std::string& name ); - static const char* lookupHumanReadable(EType type); + static EType lookupHumanReadable(const char* desc_name); // safe conversion to std::string, *TODO: deprecate + static EType lookupHumanReadable(const std::string& readable_name); + static const char* lookupHumanReadable(EType asset_type); - static EDragAndDropType lookupDragAndDropType( EType ); + static EDragAndDropType lookupDragAndDropType( EType ); // Generate a good default description. You may want to add a verb // or agent name after this depending on your application. static void generateDescriptionFor(LLAssetType::EType type, std::string& desc); - static EType getType(const std::string& sin); - static std::string getDesc(EType type); - + static EType getType(const std::string& desc_name); + static const std::string& getDesc(EType asset_type); + static bool lookupCanLink(EType asset_type); static bool lookupIsLinkType(EType asset_type); static bool lookupIsAssetFetchByIDAllowed(EType asset_type); // the asset allows direct download static bool lookupIsAssetIDKnowable(EType asset_type); // asset data can be known by the viewer -private: - // don't instantiate or derive one of these objects - LLAssetType( void ) {} - ~LLAssetType( void ) {} + static const std::string& badLookup(); // error string when a lookup fails -private: - static const char* mAssetTypeNames[]; - static const char* mAssetTypeHumanNames[]; +protected: + LLAssetType() {} + ~LLAssetType() {} }; +#ifdef CWDEBUG +#include +inline std::ostream& operator<<(std::ostream& os, LLAssetType::EType type) { return os << LLAssetType::getDesc(type); } +#endif + #endif // LL_LLASSETTYPE diff --git a/indra/llcommon/llboost.h b/indra/llcommon/llboost.h index 4df9dbf3b..4901d6689 100644 --- a/indra/llcommon/llboost.h +++ b/indra/llcommon/llboost.h @@ -46,4 +46,18 @@ */ typedef boost::tokenizer > boost_tokenizer; +// Useful combiner for boost signals that return a bool (e.g. validation) +// returns false if any of the callbacks return false +struct boost_boolean_combiner +{ + typedef bool result_type; + template + bool operator()(InputIterator first, InputIterator last) const + { + bool res = true; + while (first != last) + res &= *first++; + return res; + } +}; #endif // LL_LLBOOST_H diff --git a/indra/llcommon/lldate.cpp b/indra/llcommon/lldate.cpp index be294480e..e949cbbb4 100644 --- a/indra/llcommon/lldate.cpp +++ b/indra/llcommon/lldate.cpp @@ -38,10 +38,13 @@ #include "apr_time.h" #include +#include +#include #include #include #include "lltimer.h" +#include "llstring.h" static const F64 DATE_EPOCH = 0.0; @@ -88,47 +91,40 @@ std::string LLDate::asString() const // is one of the standards used and the prefered format std::string LLDate::asRFC1123() const { - std::ostringstream stream; - toHTTPDateStream(stream); - return stream.str(); + return toHTTPDateString (std::string ("%A, %d %b %Y %H:%M:%S GMT")); } -void LLDate::toHTTPDateStream(std::ostream& s) const + +std::string LLDate::toHTTPDateString (std::string fmt) const { - // http://apr.apache.org/docs/apr/0.9/group__apr__time.html - apr_time_t time = (apr_time_t)(mSecondsSinceEpoch * LL_APR_USEC_PER_SEC); + + time_t locSeconds = (time_t) mSecondsSinceEpoch; + struct tm * gmt = gmtime (&locSeconds); + return toHTTPDateString(gmt, fmt); +} - apr_time_exp_t exp_time ; //Apache time module - - if (apr_time_exp_gmt(&exp_time, time) != APR_SUCCESS) - { +std::string LLDate::toHTTPDateString (tm * gmt, std::string fmt) +{ // Return Epoch UTC date - s << "Thursday, 01 Jan 1970 00:00:00 GMT" ; - return; - } - s << std::dec << std::setfill('0'); -#if( LL_WINDOWS || __GNUC__ > 2) - s << std::right ; -#else - s.setf(ios::right); -#endif - static char const* const weekdays[] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}; - static char const* const months[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; - std::string day = weekdays[exp_time.tm_wday]; - std::string month = months[exp_time.tm_mon]; + // avoid calling setlocale() unnecessarily - it's expensive. + static std::string prev_locale = ""; + std::string this_locale = LLStringUtil::getLocale(); + if (this_locale != prev_locale) + { + setlocale(LC_TIME, this_locale.c_str()); + prev_locale = this_locale; + } - s << std::setw(day.length()) << (day) - << ", " << std::setw(2) << (exp_time.tm_mday) - << ' ' << std::setw(month.length()) << (month) - << ' ' << std::setw(4) << (exp_time.tm_year + 1900) - << ' ' << std::setw(2) << (exp_time.tm_hour) - << ':' << std::setw(2) << (exp_time.tm_min) - << ':' << std::setw(2) << (exp_time.tm_sec) - << " GMT"; - - // RFC 1123 date does not use microseconds - //llinfos << "Date in RFC 1123 format is " << s << llendl; + // use strftime() as it appears to be faster than std::time_put + char buffer[128]; + strftime(buffer, 128, fmt.c_str(), gmt); + std::string res(buffer); +#if LL_WINDOWS + // Convert from locale-dependant charset to UTF-8 (EXT-8524). + res = ll_convert_string_to_utf8_string(res); +#endif + return res; } void LLDate::toStream(std::ostream& s) const @@ -159,7 +155,39 @@ void LLDate::toStream(std::ostream& s) const s << '.' << std::setw(2) << (int)(exp_time.tm_usec / (LL_APR_USEC_PER_SEC / 100)); } - s << 'Z'; + s << 'Z' + << std::setfill(' '); +} + +bool LLDate::split(S32 *year, S32 *month, S32 *day, S32 *hour, S32 *min, S32 *sec) const +{ + apr_time_t time = (apr_time_t)(mSecondsSinceEpoch * LL_APR_USEC_PER_SEC); + + apr_time_exp_t exp_time; + if (apr_time_exp_gmt(&exp_time, time) != APR_SUCCESS) + { + return false; + } + + if (year) + *year = exp_time.tm_year + 1900; + + if (month) + *month = exp_time.tm_mon + 1; + + if (day) + *day = exp_time.tm_mday; + + if (hour) + *hour = exp_time.tm_hour; + + if (min) + *min = exp_time.tm_min; + + if (sec) + *sec = exp_time.tm_sec; + + return true; } bool LLDate::fromString(const std::string& iso8601_date) @@ -223,13 +251,62 @@ bool LLDate::fromStream(std::istream& s) s >> fractional; seconds_since_epoch += fractional; } - c = s.get(); // skip the Z - if (c != 'Z') { return false; } + + c = s.peek(); // check for offset + if (c == '+' || c == '-') + { + S32 offset_sign = (c == '+') ? 1 : -1; + S32 offset_hours = 0; + S32 offset_minutes = 0; + S32 offset_in_seconds = 0; + + s >> offset_hours; + + c = s.get(); // skip the colon a get the minutes if there are any + if (c == ':') + { + s >> offset_minutes; + } + + offset_in_seconds = (offset_hours * 60 + offset_sign * offset_minutes) * 60; + seconds_since_epoch -= offset_in_seconds; + } + else if (c != 'Z') { return false; } // skip the Z mSecondsSinceEpoch = seconds_since_epoch; return true; } +bool LLDate::fromYMDHMS(S32 year, S32 month, S32 day, S32 hour, S32 min, S32 sec) +{ + struct apr_time_exp_t exp_time; + + exp_time.tm_year = year - 1900; + exp_time.tm_mon = month - 1; + exp_time.tm_mday = day; + exp_time.tm_hour = hour; + exp_time.tm_min = min; + exp_time.tm_sec = sec; + + // zero out the unused fields + exp_time.tm_usec = 0; + exp_time.tm_wday = 0; + exp_time.tm_yday = 0; + exp_time.tm_isdst = 0; + exp_time.tm_gmtoff = 0; + + // generate a time_t from that + apr_time_t time; + if (apr_time_exp_gmt_get(&time, &exp_time) != APR_SUCCESS) + { + return false; + } + + mSecondsSinceEpoch = time / LL_APR_USEC_PER_SEC; + + return true; +} + F64 LLDate::secondsSinceEpoch() const { return mSecondsSinceEpoch; diff --git a/indra/llcommon/lldate.h b/indra/llcommon/lldate.h index d27da79ad..e116e9cdf 100644 --- a/indra/llcommon/lldate.h +++ b/indra/llcommon/lldate.h @@ -84,7 +84,9 @@ public: std::string asString() const; std::string asRFC1123() const; void toStream(std::ostream&) const; - void toHTTPDateStream(std::ostream&) const; + bool split(S32 *year, S32 *month = NULL, S32 *day = NULL, S32 *hour = NULL, S32 *min = NULL, S32 *sec = NULL) const; + std::string toHTTPDateString (std::string fmt) const; + static std::string toHTTPDateString (tm * gmt, std::string fmt); /** * @brief Set the date from an ISO-8601 string. * @@ -99,6 +101,7 @@ public: */ bool fromString(const std::string& iso8601_date); bool fromStream(std::istream&); + bool fromYMDHMS(S32 year, S32 month = 1, S32 day = 0, S32 hour = 0, S32 min = 0, S32 sec = 0); /** * @brief Return the date in seconds since epoch. diff --git a/indra/llcommon/lldefs.h b/indra/llcommon/lldefs.h index f3b5ca361..10e6cb34b 100644 --- a/indra/llcommon/lldefs.h +++ b/indra/llcommon/lldefs.h @@ -242,5 +242,13 @@ inline LLDATATYPE llclampb(const LLDATATYPE& a) return llmin(llmax(a, (LLDATATYPE)0), (LLDATATYPE)255); } +template +inline void llswap(LLDATATYPE& lhs, LLDATATYPE& rhs) +{ + LLDATATYPE tmp = lhs; + lhs = rhs; + rhs = tmp; +} + #endif // LL_LLDEFS_H diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp index 4cdfe097d..33f150e9a 100644 --- a/indra/llcommon/llerror.cpp +++ b/indra/llcommon/llerror.cpp @@ -46,6 +46,7 @@ # include #endif // !LL_WINDOWS #include +#include #include "llapp.h" #include "llapr.h" @@ -162,7 +163,15 @@ namespace { break; } } +#ifdef CWDEBUG + // Include normal logging in libcwd's message processing. + // This takes care of prefixing with thread ID's, locking + // and allows us to (temporarily) turn off normal logging + // output. + Dout(dc::viewer, message); +#else fprintf(stderr, "%s\n", message.c_str()); +#endif #if LL_WINDOWS fflush(stderr); //Now using a buffer. flush is required. #endif @@ -1068,28 +1077,49 @@ namespace LLError switch (site.mLevel) { - case LEVEL_DEBUG: prefix << "DEBUG: "; break; - case LEVEL_INFO: prefix << "INFO: "; break; - case LEVEL_WARN: prefix << "WARNING: "; break; - case LEVEL_ERROR: prefix << "ERROR: "; break; - default: prefix << "XXX: "; break; + case LEVEL_DEBUG: prefix << "DEBUG"; break; + case LEVEL_INFO: prefix << "INFO"; break; + case LEVEL_WARN: prefix << "WARNING"; break; + case LEVEL_ERROR: prefix << "ERROR"; break; + default: prefix << "XXX"; break; }; - - if (settings_w->printLocation) + + bool need_function = true; + if (site.mBroadTag && *site.mBroadTag != '\0') { - prefix << abbreviateFile(site.mFile) - << "(" << site.mLine << ") : "; + prefix << "(\"" << site.mBroadTag << "\")"; +#if LL_DEBUG + // Suppress printing mFunction if mBroadTag is set, starts with + // "Plugin " and ends with "child": a debug message from a plugin. + size_t taglen = strlen(site.mBroadTag); + if (taglen >= 12 && strncmp(site.mBroadTag, "Plugin ", 7) == 0 && + strcmp(site.mBroadTag + taglen - 5, "child") == 0) + { + need_function = false; + } +#endif } + + prefix << ": "; - #if LL_WINDOWS - // DevStudio: __FUNCTION__ already includes the full class name - #else - if (site.mClassInfo != typeid(NoClassInfo)) + if (need_function) { - prefix << className(site.mClassInfo) << "::"; + if (settings_w->printLocation) + { + prefix << abbreviateFile(site.mFile) + << "(" << site.mLine << ") : "; + } + +#if LL_WINDOWS + // DevStudio: __FUNCTION__ already includes the full class name +#else + if (need_function && site.mClassInfo != typeid(NoClassInfo)) + { + prefix << className(site.mClassInfo) << "::"; + } +#endif + prefix << site.mFunction << ": "; } - #endif - prefix << site.mFunction << ": "; if (site.mPrintOnce) { @@ -1218,6 +1248,9 @@ namespace LLError #endif void crashAndLoop(const std::string& message) { +#ifdef CWDEBUG + DoutFatal(dc::core, message); +#else // Now, we go kaboom! int* make_me_crash = NULL; @@ -1230,6 +1263,7 @@ namespace LLError // this is an attempt to let Coverity and other semantic scanners know that this function won't be returning ever. exit(EXIT_FAILURE); +#endif } #if LL_WINDOWS #pragma optimize("", on) diff --git a/indra/llcommon/llerror.h b/indra/llcommon/llerror.h index 60f3bfad1..e04e59d53 100644 --- a/indra/llcommon/llerror.h +++ b/indra/llcommon/llerror.h @@ -179,7 +179,7 @@ namespace LLError { return s; } // used to indicate the end of a message - class NoClassInfo { }; + class LL_COMMON_API NoClassInfo { }; // used to indicate no class info known for logging //LLCallStacks keeps track of call stacks and output the call stacks to log file diff --git a/indra/llcommon/llerrorlegacy.h b/indra/llcommon/llerrorlegacy.h index fc563dc09..476d75380 100644 --- a/indra/llcommon/llerrorlegacy.h +++ b/indra/llcommon/llerrorlegacy.h @@ -34,7 +34,7 @@ #ifndef LL_LLERRORLEGACY_H #define LL_LLERRORLEGACY_H - +#include "llpreprocessor.h" /* LEGACY -- DO NOT USE THIS STUFF ANYMORE diff --git a/indra/llcommon/llerrorthread.cpp b/indra/llcommon/llerrorthread.cpp index e2b106aa2..293379910 100644 --- a/indra/llcommon/llerrorthread.cpp +++ b/indra/llcommon/llerrorthread.cpp @@ -32,7 +32,7 @@ #include "linden_common.h" #include "llerrorthread.h" #include "llapp.h" -#include "lltimer.h" +#include "lltimer.h" // ms_sleep() LLErrorThread::LLErrorThread() : LLThread("Error"), diff --git a/indra/llcommon/lleventtimer.cpp b/indra/llcommon/lleventtimer.cpp new file mode 100644 index 000000000..2720b93ab --- /dev/null +++ b/indra/llcommon/lleventtimer.cpp @@ -0,0 +1,115 @@ +/** + * @file lleventtimer.cpp + * @brief Cross-platform objects for doing timing + * + * $LicenseInfo:firstyear=2000&license=viewergpl$ + * + * Copyright (c) 2000-2010, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlife.com/developers/opensource/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlife.com/developers/opensource/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + * + */ + +#include "linden_common.h" + +#include "lleventtimer.h" + +#include "u64.h" + + +////////////////////////////////////////////////////////////////////////////// +// +// LLEventTimer Implementation +// +////////////////////////////////////////////////////////////////////////////// + +//std::list LLEventTimer::sActiveList; + +LLEventTimer::LLEventTimer(F32 period) +: mEventTimer() +{ + mPeriod = period; + //sActiveList.push_back(this); +} + +LLEventTimer::LLEventTimer(const LLDate& time) +: mEventTimer() +{ + mPeriod = (F32)(time.secondsSinceEpoch() - LLDate::now().secondsSinceEpoch()); + //sActiveList.push_back(this); +} + + +LLEventTimer::~LLEventTimer() +{ + //sActiveList.remove(this); +} + +//static +void LLEventTimer::updateClass() +{ + std::list completed_timers; + + /*{ + for (std::list::iterator iter = sActiveList.begin(); iter != sActiveList.end(); ) + { + LLEventTimer* timer = *iter++; + F32 et = timer->mEventTimer.getElapsedTimeF32(); + if (timer->mEventTimer.getStarted() && et > timer->mPeriod) { + timer->mEventTimer.reset(); + if ( timer->tick() ) + { + completed_timers.push_back( timer ); + } + } + } + }*/ + { + LLInstanceTrackerScopedGuard guard; + for (instance_iter iter = guard.beginInstances(); iter != guard.endInstances(); ) + { + LLEventTimer& timer = *iter++; + F32 et = timer.mEventTimer.getElapsedTimeF32(); + if (timer.mEventTimer.getStarted() && et > timer.mPeriod) { + timer.mEventTimer.reset(); + if ( timer.tick() ) + { + completed_timers.push_back( &timer ); + } + } + } + } + + if ( completed_timers.size() > 0 ) + { + for (std::list::iterator completed_iter = completed_timers.begin(); + completed_iter != completed_timers.end(); + completed_iter++ ) + { + delete *completed_iter; + } + } +} + + diff --git a/indra/llcommon/lleventtimer.h b/indra/llcommon/lleventtimer.h new file mode 100644 index 000000000..1521b507a --- /dev/null +++ b/indra/llcommon/lleventtimer.h @@ -0,0 +1,66 @@ +/** + * @file lleventtimer.h + * @brief Cross-platform objects for doing timing + * + * $LicenseInfo:firstyear=2000&license=viewergpl$ + * + * Copyright (c) 2000-2010, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlife.com/developers/opensource/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlife.com/developers/opensource/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + * + */ + +#ifndef LL_EVENTTIMER_H +#define LL_EVENTTIMER_H + +#include "stdtypes.h" +#include "lldate.h" +#include "llinstancetracker.h" +#include "lltimer.h" + +// class for scheduling a function to be called at a given frequency (approximate, inprecise) +class LL_COMMON_API LLEventTimer : public LLInstanceTracker +{ +public: + LLEventTimer(F32 period); // period is the amount of time between each call to tick() in seconds + LLEventTimer(const LLDate& time); + virtual ~LLEventTimer(); + + //function to be called at the supplied frequency + // Normally return FALSE; TRUE will delete the timer after the function returns. + virtual BOOL tick() = 0; + + static void updateClass(); + +protected: + LLTimer mEventTimer; + F32 mPeriod; + +//private: + //list of active timers +// static std::list sActiveList; // TODO should this be a vector +}; + + +#endif //LL_EVENTTIMER_H diff --git a/indra/llcommon/llfasttimer.cpp b/indra/llcommon/llfasttimer.cpp index b747b6ee1..d3783c582 100644 --- a/indra/llcommon/llfasttimer.cpp +++ b/indra/llcommon/llfasttimer.cpp @@ -33,13 +33,18 @@ #include "llfasttimer.h" +#include "llmemory.h" #include "llprocessor.h" #if LL_WINDOWS +#define WIN32_LEAN_AND_MEAN +#include +#include "lltimer.h" #elif LL_LINUX || LL_SOLARIS #include #include +#include "lltimer.h" #elif LL_DARWIN #include #include "lltimer.h" // get_clock_count() @@ -65,7 +70,7 @@ S32 LLFastTimer::sLastFrameIndex = -1; int LLFastTimer::sPauseHistory = 0; int LLFastTimer::sResetHistory = 0; -F64 LLFastTimer::sCPUClockFrequency = 0.0; +#define USE_RDTSC 0 #if LL_LINUX || LL_SOLARIS U64 LLFastTimer::sClockResolution = 1000000000; // 1e9, Nanosecond resolution @@ -73,81 +78,34 @@ U64 LLFastTimer::sClockResolution = 1000000000; // 1e9, Nanosecond resolution U64 LLFastTimer::sClockResolution = 1000000; // 1e6, Microsecond resolution #endif -////////////////////////////////////////////////////////////////////////////// - -// -// CPU clock/other clock frequency and count functions -// - -#if LL_WINDOWS - -U64 get_cpu_clock_count() -{ U32 hi,lo; - - __asm - { - _emit 0x0f - _emit 0x31 - mov lo,eax - mov hi,edx - } - - U64 ret = hi; - ret *= 4294967296L; - ret |= lo; - return ret; -}; - -#endif // LL_WINDOWS - -#if LL_LINUX || LL_SOLARIS -// Try to use the MONOTONIC clock if available, this is a constant time counter -// with nanosecond resolution (but not necessarily accuracy) and attempts are made -// to synchronize this value between cores at kernel start. It should not be affected -// by CPU frequency. If not available use the REALTIME clock, but this may be affected by -// NTP adjustments or other user activity affecting the system time. -U64 get_cpu_clock_count() -{ - struct timespec tp; - -#ifdef CLOCK_MONOTONIC - clock_gettime(CLOCK_MONOTONIC,&tp); -#else - clock_gettime(CLOCK_REALTIME,&tp); -#endif - return (tp.tv_sec*LLFastTimer::sClockResolution)+tp.tv_nsec; -} -#endif // (LL_LINUX || LL_SOLARIS)) - -#if LL_DARWIN -// -// Mac implementation of CPU clock -// -// Just use gettimeofday implementation for now - -U64 get_cpu_clock_count() -{ - return get_clock_count(); -} -#endif - -////////////////////////////////////////////////////////////////////////////// //static -#if LL_DARWIN || LL_LINUX || LL_SOLARIS -U64 LLFastTimer::countsPerSecond() +#if (LL_DARWIN || LL_LINUX || LL_SOLARIS) && !(defined(__i386__) || defined(__amd64__)) +U64 LLFastTimer::countsPerSecond() // counts per second for the *32-bit* timer { - return sClockResolution; + return sClockResolution >> 8; } -#else -U64 LLFastTimer::countsPerSecond() +#else // windows or x86-mac or x86-linux or x86-solaris +U64 LLFastTimer::countsPerSecond() // counts per second for the *32-bit* timer { - if (!sCPUClockFrequency) +#if USE_RDTSC || !LL_WINDOWS + //getCPUFrequency returns MHz and sCPUClockFrequency wants to be in Hz + static U64 sCPUClockFrequency = U64(LLProcessorInfo().getCPUFrequency()*1000000.0); + + // we drop the low-order byte in our timers, so report a lower frequency +#else + // If we're not using RDTSC, each fasttimer tick is just a performance counter tick. + // Not redefining the clock frequency itself (in llprocessor.cpp/calculate_cpu_frequency()) + // since that would change displayed MHz stats for CPUs + static bool firstcall = true; + static U64 sCPUClockFrequency; + if (firstcall) { - CProcessor proc; - sCPUClockFrequency = proc.GetCPUFrequency(50); + QueryPerformanceFrequency((LARGE_INTEGER*)&sCPUClockFrequency); + firstcall = false; } - return U64(sCPUClockFrequency); +#endif + return sCPUClockFrequency >> 8; } #endif @@ -200,3 +158,143 @@ void LLFastTimer::reset() } ////////////////////////////////////////////////////////////////////////////// +// +// Important note: These implementations must be FAST! +// + + +#if LL_WINDOWS +// +// Windows implementation of CPU clock +// + +// +// NOTE: put back in when we aren't using platform sdk anymore +// +// because MS has different signatures for these functions in winnt.h +// need to rename them to avoid conflicts +//#define _interlockedbittestandset _renamed_interlockedbittestandset +//#define _interlockedbittestandreset _renamed_interlockedbittestandreset +//#include +//#undef _interlockedbittestandset +//#undef _interlockedbittestandreset + +//inline U32 LLFastTimer::getCPUClockCount32() +//{ +// U64 time_stamp = __rdtsc(); +// return (U32)(time_stamp >> 8); +//} +// +//// return full timer value, *not* shifted by 8 bits +//inline U64 LLFastTimer::getCPUClockCount64() +//{ +// return __rdtsc(); +//} + +// shift off lower 8 bits for lower resolution but longer term timing +// on 1Ghz machine, a 32-bit word will hold ~1000 seconds of timing +#if USE_RDTSC +U32 LLFastTimer::getCPUClockCount32() +{ + U32 ret_val; + __asm + { + _emit 0x0f + _emit 0x31 + shr eax,8 + shl edx,24 + or eax, edx + mov dword ptr [ret_val], eax + } + return ret_val; +} + +// return full timer value, *not* shifted by 8 bits +U64 LLFastTimer::getCPUClockCount64() +{ + U64 ret_val; + __asm + { + _emit 0x0f + _emit 0x31 + mov eax,eax + mov edx,edx + mov dword ptr [ret_val+4], edx + mov dword ptr [ret_val], eax + } + return ret_val; +} + +std::string LLFastTimer::sClockType = "rdtsc"; + +#else +//LL_COMMON_API U64 get_clock_count(); // in lltimer.cpp +// These use QueryPerformanceCounter, which is arguably fine and also works on amd architectures. +U32 LLFastTimer::getCPUClockCount32() +{ + return (U32)(get_clock_count()>>8); +} + +U64 LLFastTimer::getCPUClockCount64() +{ + return get_clock_count(); +} + +std::string LLFastTimer::sClockType = "QueryPerformanceCounter"; +#endif + +#endif + + +#if (LL_LINUX || LL_SOLARIS) && !(defined(__i386__) || defined(__amd64__)) +// +// Linux and Solaris implementation of CPU clock - non-x86. +// This is accurate but SLOW! Only use out of desperation. +// +// Try to use the MONOTONIC clock if available, this is a constant time counter +// with nanosecond resolution (but not necessarily accuracy) and attempts are +// made to synchronize this value between cores at kernel start. It should not +// be affected by CPU frequency. If not available use the REALTIME clock, but +// this may be affected by NTP adjustments or other user activity affecting +// the system time. +U64 LLFastTimer::getCPUClockCount64() +{ + struct timespec tp; + +#ifdef CLOCK_MONOTONIC // MONOTONIC supported at build-time? + if (-1 == clock_gettime(CLOCK_MONOTONIC,&tp)) // if MONOTONIC isn't supported at runtime then ouch, try REALTIME +#endif + clock_gettime(CLOCK_REALTIME,&tp); + + return (tp.tv_sec*LLFastTimer::sClockResolution)+tp.tv_nsec; +} + +U32 LLFastTimer::getCPUClockCount32() +{ + return (U32)(LLFastTimer::getCPUClockCount64() >> 8); +} + +std::string LLFastTimer::sClockType = "clock_gettime"; + +#endif // (LL_LINUX || LL_SOLARIS) && !(defined(__i386__) || defined(__amd64__)) + + +#if (LL_LINUX || LL_SOLARIS || LL_DARWIN) && (defined(__i386__) || defined(__amd64__)) +// +// Mac+Linux+Solaris FAST x86 implementation of CPU clock +U32 LLFastTimer::getCPUClockCount32() +{ + U64 x; + __asm__ volatile (".byte 0x0f, 0x31": "=A"(x)); + return (U32)(x >> 8); +} + +U64 LLFastTimer::getCPUClockCount64() +{ + U64 x; + __asm__ volatile (".byte 0x0f, 0x31": "=A"(x)); + return x; +} + +std::string LLFastTimer::sClockType = "rdtsc"; +#endif \ No newline at end of file diff --git a/indra/llcommon/llfasttimer.h b/indra/llcommon/llfasttimer.h index 898ed496b..c1fea04b3 100644 --- a/indra/llcommon/llfasttimer.h +++ b/indra/llcommon/llfasttimer.h @@ -35,7 +35,6 @@ #define FAST_TIMER_ON 1 -LL_COMMON_API U64 get_cpu_clock_count(); class LL_COMMON_API LLFastTimer { @@ -51,6 +50,9 @@ public: FTM_IDLE, FTM_SLEEP, + // general timers + FT_STRING_FORMAT, + // common messaging components FTM_PUMP, FTM_CURL, @@ -104,7 +106,23 @@ public: FTM_RENDER_BLOOM, FTM_RENDER_BLOOM_FBO, FTM_RENDER_FONTS, - + + // deferred rendering + FTM_RENDER_DEFERRED, + FTM_BIND_DEFERRED, + FTM_SUN_SHADOW, + FTM_SOFTEN_SHADOW, + FTM_EDGE_DETECTION, + FTM_GI_TRACE, + FTM_GI_GATHER, + FTM_ATMOSPHERICS, + FTM_LOCAL_LIGHTS, + FTM_FULLSCREEN_LIGHTS, + FTM_PROJECTORS, + FTM_POST, + + FTM_VISIBLE_CLOUD, + // newview specific FTM_MESSAGES, FTM_MOUSEHANDLER, @@ -177,6 +195,7 @@ public: FTM_REFRESH, FTM_SORT, FTM_PICK, + FTM_STATEMACHINE, // Temp FTM_TEMP1, @@ -207,7 +226,7 @@ public: //gTimerBins[gCurTimerBin]++; //LLTimer::sNumTimerCalls++; - U64 cpu_clocks = get_cpu_clock_count(); + U64 cpu_clocks = getCPUClockCount64(); sStart[sCurDepth] = cpu_clocks; sCurDepth++; @@ -222,7 +241,7 @@ public: // These don't get counted, because they use CPU clockticks //gTimerBins[gCurTimerBin]++; //LLTimer::sNumTimerCalls++; - end = get_cpu_clock_count(); + end = getCPUClockCount64(); sCurDepth--; delta = end - sStart[sCurDepth]; @@ -237,6 +256,7 @@ public: static void reset(); static U64 countsPerSecond(); + static std::string sClockType; public: static int sCurDepth; static U64 sStart[FTM_MAX_DEPTH]; @@ -246,14 +266,17 @@ public: static U64 sCallAverage[FTM_NUM_TYPES]; static U64 sCountHistory[FTM_HISTORY_NUM][FTM_NUM_TYPES]; static U64 sCallHistory[FTM_HISTORY_NUM][FTM_NUM_TYPES]; - static S32 sCurFrameIndex; - static S32 sLastFrameIndex; + static int sPauseHistory; static int sResetHistory; - static F64 sCPUClockFrequency; - static U64 sClockResolution; -private: + static U32 getCPUClockCount32(); + static U64 getCPUClockCount64(); + + static U64 sClockResolution; + static S32 sCurFrameIndex; + static S32 sLastFrameIndex; + EFastTimerType mType; }; diff --git a/indra/llcommon/llfile.h b/indra/llcommon/llfile.h index 8b28d77bd..31d025bb0 100644 --- a/indra/llcommon/llfile.h +++ b/indra/llcommon/llfile.h @@ -233,7 +233,7 @@ public: * and should only be used for config files and the like -- not in a * loop. */ -std::streamsize llifstream_size(llifstream& fstr); -std::streamsize llofstream_size(llofstream& fstr); +std::streamsize LL_COMMON_API llifstream_size(llifstream& fstr); +std::streamsize LL_COMMON_API llofstream_size(llofstream& fstr); #endif // not LL_LLFILE_H diff --git a/indra/llcommon/llformat.cpp b/indra/llcommon/llformat.cpp index 7a500c9e5..f9f16006a 100644 --- a/indra/llcommon/llformat.cpp +++ b/indra/llcommon/llformat.cpp @@ -37,17 +37,41 @@ #include -std::string llformat(const char *fmt, ...) +// common used function with va_list argument +// wrapper for vsnprintf to be called from llformatXXX functions. +static void va_format(std::string& out, const char *fmt, va_list va) { char tstr[1024]; /* Flawfinder: ignore */ - va_list va; - va_start(va, fmt); #if LL_WINDOWS _vsnprintf(tstr, 1024, fmt, va); #else vsnprintf(tstr, 1024, fmt, va); /* Flawfinder: ignore */ #endif - va_end(va); - tstr[1023] = '\0'; - return std::string(tstr); + out.assign(tstr); } + +std::string llformat(const char *fmt, ...) +{ + std::string res; + va_list va; + va_start(va, fmt); + va_format(res, fmt, va); + va_end(va); + return res; +} + +std::string llformat_to_utf8(const char *fmt, ...) +{ + std::string res; + va_list va; + va_start(va, fmt); + va_format(res, fmt, va); + va_end(va); + +#if LL_WINDOWS + // made converting to utf8. See EXT-8318. + res = ll_convert_string_to_utf8_string(res); +#endif + return res; +} + diff --git a/indra/llcommon/llformat.h b/indra/llcommon/llformat.h index ad30d4fb1..1cf3bfcca 100644 --- a/indra/llcommon/llformat.h +++ b/indra/llcommon/llformat.h @@ -40,6 +40,9 @@ // *NOTE: buffer limited to 1024, (but vsnprintf prevents overrun) // should perhaps be replaced with boost::format. -LL_COMMON_API std::string llformat(const char *fmt, ...); +std::string LL_COMMON_API llformat(const char *fmt, ...); +// the same version as above but ensures that returned string is in utf8 on windows +// to enable correct converting utf8_to_wstring. +std::string LL_COMMON_API llformat_to_utf8(const char *fmt, ...); #endif // LL_LLFORMAT_H diff --git a/indra/llcommon/llindraconfigfile.h b/indra/llcommon/llindraconfigfile.h index 661f79bd6..17eda906e 100644 --- a/indra/llcommon/llindraconfigfile.h +++ b/indra/llcommon/llindraconfigfile.h @@ -33,8 +33,8 @@ #ifndef LL_LLINDRACONFIGFILE_H #define LL_LLINDRACONFIGFILE_H -#include #include "linden_common.h" +#include #include "lllivefile.h" #include "llsd.h" diff --git a/indra/media_plugins/webkit/dummy_volume_catcher.cpp b/indra/llcommon/llinstancetracker.cpp similarity index 62% rename from indra/media_plugins/webkit/dummy_volume_catcher.cpp rename to indra/llcommon/llinstancetracker.cpp index d54b31b2a..293a1388f 100644 --- a/indra/media_plugins/webkit/dummy_volume_catcher.cpp +++ b/indra/llcommon/llinstancetracker.cpp @@ -1,9 +1,7 @@ -/** - * @file dummy_volume_catcher.cpp - * @brief A null implementation of the "VolumeCatcher" class for platforms where it's not implemented yet. - * - * @cond - * $LicenseInfo:firstyear=2010&license=viewerlgpl$ +/** + * @file lllinstancetracker.cpp + * + * $LicenseInfo:firstyear=2009&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. * @@ -23,36 +21,27 @@ * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ - * @endcond */ -#include "volume_catcher.h" +// Precompiled header +#include "linden_common.h" +// associated header +#include "llinstancetracker.h" +// STL headers +// std headers +// external library headers +// other Linden headers - -class VolumeCatcherImpl +//static +void * & LLInstanceTrackerBase::getInstances(std::type_info const & info) { -}; + static std::map instances; -///////////////////////////////////////////////////// + std::string k = info.name(); + if(instances.find(k) == instances.end()) + { + instances[k] = NULL; + } -VolumeCatcher::VolumeCatcher() -{ - pimpl = NULL; + return instances[k]; } - -VolumeCatcher::~VolumeCatcher() -{ -} - -void VolumeCatcher::setVolume(F32 volume) -{ -} - -void VolumeCatcher::setPan(F32 pan) -{ -} - -void VolumeCatcher::pump() -{ -} - diff --git a/indra/llcommon/llinstancetracker.h b/indra/llcommon/llinstancetracker.h new file mode 100644 index 000000000..e4e535222 --- /dev/null +++ b/indra/llcommon/llinstancetracker.h @@ -0,0 +1,202 @@ +/** + * @file llinstancetracker.h + * @brief LLInstanceTracker is a mixin class that automatically tracks object + * instances with or without an associated key + * + * $LicenseInfo:firstyear=2000&license=viewergpl$ + * + * Copyright (c) 2000-2010, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlife.com/developers/opensource/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlife.com/developers/opensource/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + * + */ + +#ifndef LL_LLINSTANCETRACKER_H +#define LL_LLINSTANCETRACKER_H + +#include + +#include "string_table.h" +#include +#include +#include +#include +#include + +class LL_COMMON_API LLInstanceTrackerBase : public boost::noncopyable +{ + protected: + static void * & getInstances(std::type_info const & info); +}; +/// This mix-in class adds support for tracking all instances of the specified class parameter T +/// The (optional) key associates a value of type KEY with a given instance of T, for quick lookup +/// If KEY is not provided, then instances are stored in a simple set +/// @NOTE: see explicit specialization below for default KEY==T* case +template +class LLInstanceTracker : public LLInstanceTrackerBase +{ + typedef typename std::map InstanceMap; + typedef LLInstanceTracker MyT; + typedef boost::function KeyGetter; + typedef boost::function InstancePtrGetter; +public: + /// Dereferencing key_iter gives you a const KEY& + typedef boost::transform_iterator key_iter; + /// Dereferencing instance_iter gives you a T& + typedef boost::indirect_iterator< boost::transform_iterator > instance_iter; + + static T* getInstance(const KEY& k) + { + typename InstanceMap::const_iterator found = getMap_().find(k); + return (found == getMap_().end()) ? NULL : found->second; + } + + static key_iter beginKeys() + { + return boost::make_transform_iterator(getMap_().begin(), + boost::bind(&InstanceMap::value_type::first, _1)); + } + static key_iter endKeys() + { + return boost::make_transform_iterator(getMap_().end(), + boost::bind(&InstanceMap::value_type::first, _1)); + } + static instance_iter beginInstances() + { + return instance_iter(boost::make_transform_iterator(getMap_().begin(), + boost::bind(&InstanceMap::value_type::second, _1))); + } + static instance_iter endInstances() + { + return instance_iter(boost::make_transform_iterator(getMap_().end(), + boost::bind(&InstanceMap::value_type::second, _1))); + } + static S32 instanceCount() { return getMap_().size(); } +protected: + LLInstanceTracker(KEY key) { add_(key); } + virtual ~LLInstanceTracker() { remove_(); } + virtual void setKey(KEY key) { remove_(); add_(key); } + virtual const KEY& getKey() const { return mKey; } + +private: + void add_(KEY key) + { + mKey = key; + getMap_()[key] = static_cast(this); + } + void remove_() + { + getMap_().erase(mKey); + } + + static InstanceMap& getMap_() + { + void * & instances = getInstances(typeid(MyT)); + if (! instances) + { + instances = new InstanceMap; + } + return * static_cast(instances); + } + +private: + + KEY mKey; +}; + +/// explicit specialization for default case where KEY is T* +/// use a simple std::set +template +class LLInstanceTracker : public LLInstanceTrackerBase +{ + typedef typename std::set InstanceSet; + typedef LLInstanceTracker MyT; +public: + /// Dereferencing key_iter gives you a T* (since T* is the key) + typedef typename InstanceSet::iterator key_iter; + /// Dereferencing instance_iter gives you a T& + typedef boost::indirect_iterator instance_iter; + + /// for completeness of analogy with the generic implementation + static T* getInstance(T* k) { return k; } + static S32 instanceCount() { return getSet_().size(); } + + // Instantiate this to get access to iterators for this type. It's a 'guard' in the sense + // that it treats deletes of this type as errors as long as there is an instance of + // this class alive in scope somewhere (i.e. deleting while iterating is bad). + class LLInstanceTrackerScopedGuard + { + public: + LLInstanceTrackerScopedGuard() + { + ++sIterationNestDepth; + } + + ~LLInstanceTrackerScopedGuard() + { + --sIterationNestDepth; + } + + static instance_iter beginInstances() { return instance_iter(getSet_().begin()); } + static instance_iter endInstances() { return instance_iter(getSet_().end()); } + static key_iter beginKeys() { return getSet_().begin(); } + static key_iter endKeys() { return getSet_().end(); } + }; + +protected: + LLInstanceTracker() + { + // it's safe but unpredictable to create instances of this type while all instances are being iterated over. I hate unpredictable. This assert will probably be turned on early in the next development cycle. + //llassert(sIterationNestDepth == 0); + getSet_().insert(static_cast(this)); + } + virtual ~LLInstanceTracker() + { + // it's unsafe to delete instances of this type while all instances are being iterated over. + llassert(sIterationNestDepth == 0); + getSet_().erase(static_cast(this)); + } + + LLInstanceTracker(const LLInstanceTracker& other) + { + //llassert(sIterationNestDepth == 0); + getSet_().insert(static_cast(this)); + } + + static InstanceSet& getSet_() + { + void * & instances = getInstances(typeid(MyT)); + if (! instances) + { + instances = new InstanceSet; + } + return * static_cast(instances); + } + + static S32 sIterationNestDepth; +}; + +template S32 LLInstanceTracker::sIterationNestDepth = 0; + +#endif diff --git a/indra/llcommon/llliveappconfig.cpp b/indra/llcommon/llliveappconfig.cpp index d2744875d..75bdfee8b 100644 --- a/indra/llcommon/llliveappconfig.cpp +++ b/indra/llcommon/llliveappconfig.cpp @@ -38,9 +38,12 @@ #include "llsd.h" #include "llsdserialize.h" -LLLiveAppConfig::LLLiveAppConfig(LLApp* app, const std::string& filename, F32 refresh_period) -: LLLiveFile(filename, refresh_period), - mApp(app) +LLLiveAppConfig::LLLiveAppConfig( + const std::string& filename, + F32 refresh_period, + LLApp::OptionPriority priority) : + LLLiveFile(filename, refresh_period), + mPriority(priority) { } @@ -77,7 +80,7 @@ bool LLLiveAppConfig::loadFile() // to set the config to an empty config, and return that it // changed. - mApp->setOptionData( - LLApp::PRIORITY_SPECIFIC_CONFIGURATION, config); + LLApp* app = LLApp::instance(); + if(app) app->setOptionData(mPriority, config); return true; } diff --git a/indra/llcommon/llliveappconfig.h b/indra/llcommon/llliveappconfig.h index 465dde160..73b3a2335 100644 --- a/indra/llcommon/llliveappconfig.h +++ b/indra/llcommon/llliveappconfig.h @@ -33,25 +33,43 @@ #ifndef LLLIVEAPPCONFIG_H #define LLLIVEAPPCONFIG_H +#include "llapp.h" #include "lllivefile.h" -class LLApp; +/** + * @class LLLiveAppConfig + * @see LLLiveFile + * + * To use this, instantiate a LLLiveAppConfig object inside your main + * loop. The traditional name for it is live_config. Be sure to call + * live_config.checkAndReload() periodically. + */ class LL_COMMON_API LLLiveAppConfig : public LLLiveFile { public: - // To use this, instantiate a LLLiveAppConfig object inside your main loop. - // The traditional name for it is live_config. - // Be sure to call live_config.checkAndReload() periodically. - LLLiveAppConfig(LLApp* app, const std::string& filename, F32 refresh_period); - ~LLLiveAppConfig(); + /** + * @brief Constructor + * + * @param filename. The name of the file for periodically checking + * configuration. + * @param refresh_period How often the internal timer should + * bother checking the filesystem. + * @param The application priority level of that configuration file. + */ + LLLiveAppConfig( + const std::string& filename, + F32 refresh_period, + LLApp::OptionPriority priority); + + ~LLLiveAppConfig(); ///< Destructor protected: /*virtual*/ bool loadFile(); private: - LLApp* mApp; + LLApp::OptionPriority mPriority; }; #endif diff --git a/indra/llcommon/lllivefile.cpp b/indra/llcommon/lllivefile.cpp index 322f226d5..ce6ac4fac 100644 --- a/indra/llcommon/lllivefile.cpp +++ b/indra/llcommon/lllivefile.cpp @@ -33,7 +33,7 @@ #include "lllivefile.h" #include "llframetimer.h" -#include "lltimer.h" +#include "lleventtimer.h" const F32 DEFAULT_CONFIG_FILE_REFRESH = 5.0f; diff --git a/indra/llcommon/llmd5.cpp b/indra/llcommon/llmd5.cpp index 35067b3b3..1257af0e3 100644 --- a/indra/llcommon/llmd5.cpp +++ b/indra/llcommon/llmd5.cpp @@ -83,7 +83,7 @@ documentation and/or software. #include "llmd5.h" #include -#include +#include // cerr // how many bytes to grab at a time when checking files const int LLMD5::BLOCK_LEN = 4096; diff --git a/indra/llcommon/llmd5.h b/indra/llcommon/llmd5.h index 837dd3e5a..8bf715f14 100644 --- a/indra/llcommon/llmd5.h +++ b/indra/llcommon/llmd5.h @@ -108,9 +108,8 @@ public: // methods to acquire finalized result void raw_digest(unsigned char *array) const; // provide 16-byte array for binary data void hex_digest(char *string) const; // provide 33-byte array for ascii-hex string - friend std::ostream& operator<< (std::ostream&, LLMD5 context); - + friend LL_COMMON_API std::ostream& operator<< (std::ostream&, LLMD5 context); private: diff --git a/indra/llcommon/llmetrics.cpp b/indra/llcommon/llmetrics.cpp index 8db3284c4..30e5d435a 100644 --- a/indra/llcommon/llmetrics.cpp +++ b/indra/llcommon/llmetrics.cpp @@ -71,7 +71,7 @@ void LLMetricsImpl::recordEventDetails(const std::string& location, metrics["location"] = location; metrics["stats"] = stats; - llinfos << "LLMETRICS: " << LLSDNotationStreamer(metrics) << llendl; + llinfos << "LLMETRICS: " << (LLSDNotationStreamer(metrics)) << llendl; } // Store this: diff --git a/indra/llcommon/llprocesslauncher.cpp b/indra/llcommon/llprocesslauncher.cpp index e27aaa3c5..45bd98e20 100644 --- a/indra/llcommon/llprocesslauncher.cpp +++ b/indra/llcommon/llprocesslauncher.cpp @@ -32,7 +32,11 @@ #include "linden_common.h" +#include +#include +#include #include "llprocesslauncher.h" +#include "aiaprpool.h" #include #if LL_DARWIN || LL_LINUX @@ -64,6 +68,11 @@ void LLProcessLauncher::setWorkingDirectory(const std::string &dir) mWorkingDir = dir; } +const std::string& LLProcessLauncher::getExecutable() const +{ + return mExecutable; +} + void LLProcessLauncher::clearArguments() { mLaunchArguments.clear(); @@ -142,6 +151,7 @@ bool LLProcessLauncher::isRunning(void) return (mProcessHandle != 0); } + bool LLProcessLauncher::kill(void) { bool result = true; @@ -201,6 +211,79 @@ static bool reap_pid(pid_t pid) return result; } +#if LL_DEBUG +// Define this to create a temporary pipe(2) between parent and child process, so +// that the child process can report error messages that it encounters when +// trying to execve(2). Most notably failing to start due to missing libraries +// or undefined symbols. +#define DEBUG_PIPE_CHILD_ERROR_REPORTING 1 +#endif + +#ifdef DEBUG_PIPE_CHILD_ERROR_REPORTING + +// Called by child process. +static void write_pipe(apr_file_t* out, char const* message) +{ + apr_size_t const bytes_to_write = strlen(message) + 1; // +1 for the length byte. + assert(bytes_to_write < 256); + char buf[256]; + strncpy(buf + 1, message, sizeof(buf) - 1); + *reinterpret_cast(buf) = bytes_to_write - 1; + + apr_size_t bytes_written; + apr_status_t status = apr_file_write_full(out, buf, bytes_to_write, &bytes_written); + if (status != APR_SUCCESS) + { + std::cerr << "apr_file_write_full: " << apr_strerror(status, buf, sizeof(buf)) << std::endl; + } + else if (bytes_written != bytes_to_write) + { + std::cerr << "apr_file_write_full: bytes_written (" << bytes_written << ") != bytes_to_write (" << bytes_to_write << ")!" << std::endl; + } + status = apr_file_flush(out); + if (status != APR_SUCCESS) + { + std::cerr << "apr_file_flush: " << apr_strerror(status, buf, sizeof(buf)) << std::endl; + } + +#ifdef _DEBUG + std::cerr << "apr_file_write_full: Wrote " << bytes_written << " bytes to the pipe." << std::endl; +#endif +} + +// Called by parent process. +static std::string read_pipe(apr_file_t* in, bool timeout_ok = false) +{ + char buf[256]; + unsigned char bytes_to_read; + apr_size_t bytes_read; + apr_status_t status = apr_file_read_full(in, &bytes_to_read, 1, &bytes_read); + if (status != APR_SUCCESS) + { + if (APR_STATUS_IS_TIMEUP(status) && timeout_ok) + { + return "TIMEOUT"; + } + llwarns << "apr_file_read_full: " << apr_strerror(status, buf, sizeof(buf)) << llendl; + assert(APR_STATUS_IS_EOF(status)); + return "END OF FILE"; + } + assert(bytes_read == 1); + status = apr_file_read_full(in, buf, bytes_to_read, &bytes_read); + if (status != APR_SUCCESS) + { + llwarns << "apr_file_read_full: " << apr_strerror(status, buf, sizeof(buf)) << llendl; + assert(status == APR_SUCCESS); // Fail + } + assert(bytes_read == bytes_to_read); + + std::string received(buf, bytes_read); + llinfos << "Received: \"" << received << "\" (bytes read: " << bytes_read << ")" << llendl; + return received; +} + +#endif // DEBUG_PIPE_CHILD_ERROR_REPORTING + int LLProcessLauncher::launch(void) { // If there was already a process associated with this object, kill it. @@ -237,23 +320,96 @@ int LLProcessLauncher::launch(void) } } - // flush all buffers before the child inherits them - ::fflush(NULL); - - pid_t id = vfork(); - if(id == 0) + pid_t id; { - // child process - - ::execv(mExecutable.c_str(), (char * const *)fake_argv); - - // If we reach this point, the exec failed. - // Use _exit() instead of exit() per the vfork man page. - _exit(0); +#ifdef DEBUG_PIPE_CHILD_ERROR_REPORTING + // Set up a pipe to the child process for error reporting. + apr_file_t* in; + apr_file_t* out; + AIAPRPool pool; + pool.create(); + apr_status_t status = apr_file_pipe_create_ex(&in, &out, APR_FULL_BLOCK, pool()); + assert(status == APR_SUCCESS); + bool success = (status == APR_SUCCESS); + if (success) + { + apr_interval_time_t const timeout = 10000000; // 10 seconds. + status = apr_file_pipe_timeout_set(in, timeout); + assert(status == APR_SUCCESS); + success = (status == APR_SUCCESS); + } +#endif // DEBUG_PIPE_CHILD_ERROR_REPORTING + + // flush all buffers before the child inherits them + ::fflush(NULL); + + id = vfork(); + if (id == 0) + { + // child process + +#ifdef DEBUG_PIPE_CHILD_ERROR_REPORTING + // Tell parent process we're about to call execv. + write_pipe(out, "CALLING EXECV"); +#ifdef _DEBUG + char const* display = getenv("DISPLAY"); + std::cerr << "Calling ::execv(\"" << mExecutable << '"'; + for(int j = 0; j < i; ++j) + std::cerr << ", \"" << fake_argv[j] << '"'; + std::cerr << ") with DISPLAY=\"" << (display ? display : "NULL") << '"' << std::endl; +#endif +#endif // DEBUG_PIPE_CHILD_ERROR_REPORTING + + ::execv(mExecutable.c_str(), (char * const *)fake_argv); + +#ifdef DEBUG_PIPE_CHILD_ERROR_REPORTING + status = APR_FROM_OS_ERROR(apr_get_os_error()); + char message[256]; + char errbuf[128]; + apr_strerror(status, errbuf, sizeof(errbuf)); + snprintf(message, sizeof(message), "Child process: execv: %s: %s", mExecutable.c_str(), errbuf); + write_pipe(out, message); +#ifdef _DEBUG + std::cerr << "::execv() failed." << std::endl; +#endif +#endif // DEBUG_PIPE_CHILD_ERROR_REPORTING + + // If we reach this point, the exec failed. + // Use _exit() instead of exit() per the vfork man page. + _exit(0); + } + + // parent process + +#ifdef DEBUG_PIPE_CHILD_ERROR_REPORTING + // Close unused pipe end. + apr_file_close(out); + + if (success) + { + // Attempt to do error reporting. + std::string message = read_pipe(in); + success = (message == "CALLING EXECV"); + assert(success); + if (success) + { + status = apr_file_pipe_timeout_set(in, 2000000); // Only wait 2 seconds. + message = read_pipe(in, true); + if (message != "TIMEOUT" && message != "END OF FILE") + { + // Most likely execv failed. + llwarns << message << llendl; + assert(false); // Fail in debug mode. + } + } + } + + // Clean up. + apr_file_close(in); +#endif // DEBUG_PIPE_CHILD_ERROR_REPORTING + } - // parent process - if(current_wd >= 0) { // restore the previous working directory diff --git a/indra/llcommon/llprocesslauncher.h b/indra/llcommon/llprocesslauncher.h index 9f49a85bd..0b96f3f7b 100644 --- a/indra/llcommon/llprocesslauncher.h +++ b/indra/llcommon/llprocesslauncher.h @@ -53,6 +53,8 @@ public: void setExecutable(const std::string &executable); void setWorkingDirectory(const std::string &dir); + const std::string& getExecutable() const; + void clearArguments(); void addArgument(const std::string &arg); void addArgument(const char *arg); diff --git a/indra/llcommon/llprocessor.cpp b/indra/llcommon/llprocessor.cpp index 469e544b1..f255e5a8b 100644 --- a/indra/llcommon/llprocessor.cpp +++ b/indra/llcommon/llprocessor.cpp @@ -30,51 +30,351 @@ * $/LicenseInfo$ */ -// Filename: Processor.cpp -// ======================= -// Author: Benjamin Jurke -// File history: 27.02.2002 - File created. Support for Intel and AMD processors -// 05.03.2002 - Fixed the CPUID bug: On Pre-Pentium CPUs the CPUID -// command is not available -// - The CProcessor::WriteInfoTextFile function do not -// longer use Win32 file functions (-> os independend) -// - Optional include of the windows.h header which is -// still need for CProcessor::GetCPUFrequency. -// 06.03.2002 - My birthday (18th :-)) -// - Replaced the '\r\n' line endings in function -// CProcessor::CPUInfoToText by '\n' -// - Replaced unsigned __int64 by signed __int64 for -// solving some compiler conversion problems -// - Fixed a bug at family=6, model=6 (Celeron -> P2) -////////////////////////////////////////////////////////////////////////////////// - #include "linden_common.h" +#include "llprocessor.h" -#include "processor.h" +#include "llerror.h" -#include +//#include #if LL_WINDOWS # define WIN32_LEAN_AND_MEAN # include # include +# define _interlockedbittestandset _renamed_interlockedbittestandset +# define _interlockedbittestandreset _renamed_interlockedbittestandreset +# include +# undef _interlockedbittestandset +# undef _interlockedbittestandreset #endif -#if !LL_DARWIN && !LL_SOLARIS +#include "llsd.h" -#ifdef PROCESSOR_FREQUENCY_MEASURE_AVAILABLE -// We need the QueryPerformanceCounter and Sleep functions -#define FORCEINLINE __forceinline -#else -#define FORCEINLINE +#if LL_MSVC && _M_X64 +# define LL_X86_64 1 +# define LL_X86 1 +#elif LL_MSVC && _M_IX86 +# define LL_X86 1 +#elif LL_GNUC && ( defined(__amd64__) || defined(__x86_64__) ) +# define LL_X86_64 1 +# define LL_X86 1 +#elif LL_GNUC && ( defined(__i386__) ) +# define LL_X86 1 +#elif LL_GNUC && ( defined(__powerpc__) || defined(__ppc__) ) +# define LL_PPC 1 #endif +class LLProcessorInfoImpl; // foward declaration for the mImpl; -// Some macros we often need -//////////////////////////// -#define CheckBit(var, bit) ((var & (1 << bit)) ? true : false) +namespace +{ + enum cpu_info + { + eBrandName = 0, + eFrequency, + eVendor, + eStepping, + eFamily, + eExtendedFamily, + eModel, + eExtendedModel, + eType, + eBrandID, + eFamilyName + }; + + + const char* cpu_info_names[] = + { + "Processor Name", + "Frequency", + "Vendor", + "Stepping", + "Family", + "Extended Family", + "Model", + "Extended Model", + "Type", + "Brand ID", + "Family Name" + }; + + enum cpu_config + { + eMaxID, + eMaxExtID, + eCLFLUSHCacheLineSize, + eAPICPhysicalID, + eCacheLineSize, + eL2Associativity, + eCacheSizeK, + eFeatureBits, + eExtFeatureBits + }; + + const char* cpu_config_names[] = + { + "Max Supported CPUID level", + "Max Supported Ext. CPUID level", + "CLFLUSH cache line size", + "APIC Physical ID", + "Cache Line Size", + "L2 Associativity", + "Cache Size", + "Feature Bits", + "Ext. Feature Bits" + }; + + + + // *NOTE:Mani - this contains the elements we reference directly and extensions beyond the first 32. + // The rest of the names are referenced by bit maks returned from cpuid. + enum cpu_features + { + eSSE_Ext=25, + eSSE2_Ext=26, + + eSSE3_Features=32, + eMONTIOR_MWAIT=33, + eCPLDebugStore=34, + eThermalMonitor2=35, + eAltivec=36 + }; + + const char* cpu_feature_names[] = + { + "x87 FPU On Chip", + "Virtual-8086 Mode Enhancement", + "Debugging Extensions", + "Page Size Extensions", + "Time Stamp Counter", + "RDMSR and WRMSR Support", + "Physical Address Extensions", + "Machine Check Exception", + "CMPXCHG8B Instruction", + "APIC On Chip", + "Unknown1", + "SYSENTER and SYSEXIT", + "Memory Type Range Registers", + "PTE Global Bit", + "Machine Check Architecture", + "Conditional Move/Compare Instruction", + "Page Attribute Table", + "Page Size Extension", + "Processor Serial Number", + "CFLUSH Extension", + "Unknown2", + "Debug Store", + "Thermal Monitor and Clock Ctrl", + "MMX Technology", + "FXSAVE/FXRSTOR", + "SSE Extensions", + "SSE2 Extensions", + "Self Snoop", + "Hyper-threading Technology", + "Thermal Monitor", + "Unknown4", + "Pend. Brk. EN.", // 31 End of FeatureInfo bits + + "SSE3 New Instructions", // 32 + "MONITOR/MWAIT", + "CPL Qualified Debug Store", + "Thermal Monitor 2", + + "Altivec" + }; + + std::string intel_CPUFamilyName(int composed_family) + { + switch(composed_family) + { + case 3: return "Intel i386"; + case 4: return "Intel i486"; + case 5: return "Intel Pentium"; + case 6: return "Intel Pentium Pro/2/3, Core"; + case 7: return "Intel Itanium (IA-64)"; + case 0xF: return "Intel Pentium 4"; + case 0x10: return "Intel Itanium 2 (IA-64)"; + } + return "Unknown"; + } + + std::string amd_CPUFamilyName(int composed_family) + { + switch(composed_family) + { + case 4: return "AMD 80486/5x86"; + case 5: return "AMD K5/K6"; + case 6: return "AMD K7"; + case 0xF: return "AMD K8"; + case 0x10: return "AMD K8L"; + } + return "Unknown"; + } + + std::string compute_CPUFamilyName(const char* cpu_vendor, int composed_family) + { + const char* intel_string = "GenuineIntel"; + const char* amd_string = "AuthenticAMD"; + if(!strncmp(cpu_vendor, intel_string, strlen(intel_string))) + { + return intel_CPUFamilyName(composed_family); + } + else if(!strncmp(cpu_vendor, amd_string, strlen(amd_string))) + { + return amd_CPUFamilyName(composed_family); + } + return "Unknown"; + } + + std::string compute_CPUFamilyName(const char* cpu_vendor, int family, int ext_family) + { + const char* intel_string = "GenuineIntel"; + const char* amd_string = "AuthenticAMD"; + if(!strncmp(cpu_vendor, intel_string, strlen(intel_string))) + { + U32 composed_family = family + ext_family; + return intel_CPUFamilyName(composed_family); + } + else if(!strncmp(cpu_vendor, amd_string, strlen(amd_string))) + { + U32 composed_family = (family == 0xF) + ? family + ext_family + : family; + return amd_CPUFamilyName(composed_family); + } + return "Unknown"; + } + +} // end unnamed namespace + +// The base class for implementations. +// Each platform should override this class. +class LLProcessorInfoImpl +{ +public: + LLProcessorInfoImpl() + { + mProcessorInfo["info"] = LLSD::emptyMap(); + mProcessorInfo["config"] = LLSD::emptyMap(); + mProcessorInfo["extension"] = LLSD::emptyMap(); + } + virtual ~LLProcessorInfoImpl() {} + + F64 getCPUFrequency() const + { + return getInfo(eFrequency, 0).asReal(); + } + + bool hasSSE() const + { + return hasExtension(cpu_feature_names[eSSE_Ext]); + } + + bool hasSSE2() const + { + return hasExtension(cpu_feature_names[eSSE2_Ext]); + } + + bool hasAltivec() const + { + return hasExtension("Altivec"); + } + + std::string getCPUFamilyName() const { return getInfo(eFamilyName, "Unknown").asString(); } + std::string getCPUBrandName() const { return getInfo(eBrandName, "Unknown").asString(); } + + // This is virtual to support a different linux format. + // *NOTE:Mani - I didn't want to screw up server use of this data... + virtual std::string getCPUFeatureDescription() const + { + std::ostringstream out; + out << std::endl << std::endl; + out << "// CPU General Information" << std::endl; + out << "//////////////////////////" << std::endl; + out << "Processor Name: " << getCPUBrandName() << std::endl; + out << "Frequency: " << getCPUFrequency() << " MHz" << std::endl; + out << "Vendor: " << getInfo(eVendor, "Unknown").asString() << std::endl; + out << "Family: " << getCPUFamilyName() << " (" << getInfo(eFamily, 0) << ")" << std::endl; + out << "Extended family: " << getInfo(eExtendedFamily, 0) << std::endl; + out << "Model: " << getInfo(eModel, 0) << std::endl; + out << "Extended model: " << getInfo(eExtendedModel, 0) << std::endl; + out << "Type: " << getInfo(eType, 0) << std::endl; + out << "Brand ID: " << getInfo(eBrandID, 0) << std::endl; + out << std::endl; + out << "// CPU Configuration" << std::endl; + out << "//////////////////////////" << std::endl; + + // Iterate through the dictionary of configuration options. + LLSD configs = mProcessorInfo["config"]; + for(LLSD::map_const_iterator cfgItr = configs.beginMap(); cfgItr != configs.endMap(); ++cfgItr) + { + out << cfgItr->first << " = " << cfgItr->second << std::endl; + } + out << std::endl; + + out << "// CPU Extensions" << std::endl; + out << "//////////////////////////" << std::endl; + + for(LLSD::map_const_iterator itr = mProcessorInfo["extension"].beginMap(); itr != mProcessorInfo["extension"].endMap(); ++itr) + { + out << " " << itr->first << std::endl; + } + return out.str(); + } + +protected: + void setInfo(cpu_info info_type, const LLSD& value) + { + setInfo(cpu_info_names[info_type], value); + } + LLSD getInfo(cpu_info info_type, const LLSD& defaultVal) const + { + return getInfo(cpu_info_names[info_type], defaultVal); + } + + void setConfig(cpu_config config_type, const LLSD& value) + { + setConfig(cpu_config_names[config_type], value); + } + LLSD getConfig(cpu_config config_type, const LLSD& defaultVal) const + { + return getConfig(cpu_config_names[config_type], defaultVal); + } + + void setExtension(const std::string& name) { mProcessorInfo["extension"][name] = "true"; } + bool hasExtension(const std::string& name) const + { + return mProcessorInfo["extension"].has(name); + } + +private: + void setInfo(const std::string& name, const LLSD& value) { mProcessorInfo["info"][name]=value; } + LLSD getInfo(const std::string& name, const LLSD& defaultVal) const + { + if(mProcessorInfo["info"].has(name)) + { + return mProcessorInfo["info"][name]; + } + return defaultVal; + } + void setConfig(const std::string& name, const LLSD& value) { mProcessorInfo["config"][name]=value; } + LLSD getConfig(const std::string& name, const LLSD& defaultVal) const + { + LLSD r = mProcessorInfo["config"].get(name); + return r.isDefined() ? r : defaultVal; + } + +private: + + LLSD mProcessorInfo; +}; + + +#ifdef LL_MSVC +// LL_MSVC and not LLWINDOWS because some of the following code +// uses the MSVC compiler intrinsics __cpuid() and __rdtsc(). -#ifdef PROCESSOR_FREQUENCY_MEASURE_AVAILABLE // Delays for the specified amount of milliseconds static void _Delay(unsigned int ms) { @@ -97,63 +397,22 @@ static void _Delay(unsigned int ms) }while(c2.QuadPart-c1.QuadPart < x); // Loop while (second-first < x) } -#endif -// CProcessor::CProcessor -// ====================== -// Class constructor: -///////////////////////// -CProcessor::CProcessor() +static F64 calculate_cpu_frequency(U32 measure_msecs) { - uqwFrequency = 0; - strCPUName[0] = 0; - memset(&CPUInfo, 0, sizeof(CPUInfo)); -} - -// unsigned __int64 CProcessor::GetCPUFrequency(unsigned int uiMeasureMSecs) -// ========================================================================= -// Function to measure the current CPU frequency -//////////////////////////////////////////////////////////////////////////// -F64 CProcessor::GetCPUFrequency(unsigned int uiMeasureMSecs) -{ -#ifndef PROCESSOR_FREQUENCY_MEASURE_AVAILABLE - return 0; -#else - // If there are invalid measure time parameters, zero msecs for example, - // we've to exit the function - if (uiMeasureMSecs < 1) + if(measure_msecs == 0) { - // If theres already a measured frequency available, we return it - if (uqwFrequency > 0) - return uqwFrequency; - else - return 0; - } - - // Now we check if the CPUID command is available - if (!CheckCPUIDPresence()) return 0; - - // First we get the CPUID standard level 0x00000001 - unsigned long reg; - __asm - { - mov eax, 1 - cpuid - mov reg, edx } - // Then we check, if the RDTSC (Real Date Time Stamp Counter) is available. - // This function is necessary for our measure process. - if (!(reg & (1 << 4))) - return 0; - // After that we declare some vars and check the frequency of the high // resolution timer for the measure process. - // If there's no high-res timer, we exit. - __int64 starttime, endtime, timedif, freq, start, end, dif; + // If there"s no high-res timer, we exit. + unsigned __int64 starttime, endtime, timedif, freq, start, end, dif; if (!QueryPerformanceFrequency((LARGE_INTEGER *) &freq)) + { return 0; + } // Now we can init the measure process. We set the process and thread priority // to the highest available level (Realtime priority). Also we focus the @@ -169,35 +428,27 @@ F64 CProcessor::GetCPUFrequency(unsigned int uiMeasureMSecs) SetThreadPriority(hThread, THREAD_PRIORITY_TIME_CRITICAL); SetProcessAffinityMask(hProcess, dwNewMask); - // Now we call a CPUID to ensure, that all other prior called functions are - // completed now (serialization) - __asm cpuid + //// Now we call a CPUID to ensure, that all other prior called functions are + //// completed now (serialization) + //__asm cpuid + int cpu_info[4] = {-1}; + __cpuid(cpu_info, 0); // We ask the high-res timer for the start time QueryPerformanceCounter((LARGE_INTEGER *) &starttime); // Then we get the current cpu clock and store it - __asm - { - rdtsc - mov dword ptr [start+4], edx - mov dword ptr [start], eax - } + start = __rdtsc(); // Now we wart for some msecs - _Delay(uiMeasureMSecs); -// Sleep(uiMeasureMSecs); + _Delay(measure_msecs); + // Sleep(uiMeasureMSecs); // We ask for the end time QueryPerformanceCounter((LARGE_INTEGER *) &endtime); // And also for the end cpu clock - __asm - { - rdtsc - mov dword ptr [end+4], edx - mov dword ptr [end], eax - } + end = __rdtsc(); // Now we can restore the default process and thread priorities SetProcessAffinityMask(hProcess, dwProcessMask); @@ -210,2074 +461,433 @@ F64 CProcessor::GetCPUFrequency(unsigned int uiMeasureMSecs) // And finally the frequency is the clock difference divided by the time // difference. - uqwFrequency = (F64)dif / (((F64)timedif) / freq); + F64 frequency = (F64)dif / (((F64)timedif) / freq); // At last we just return the frequency that is also stored in the call - // member var uqwFrequency - return uqwFrequency; -#endif + // member var uqwFrequency - converted to MHz + return frequency / (F64)1000000; } -// bool CProcessor::AnalyzeIntelProcessor() -// ======================================== -// Private class function for analyzing an Intel processor -////////////////////////////////////////////////////////// -bool CProcessor::AnalyzeIntelProcessor() +// Windows implementation +class LLProcessorInfoWindowsImpl : public LLProcessorInfoImpl { -#if LL_WINDOWS - unsigned long eaxreg, ebxreg, edxreg; - - // First we check if the CPUID command is available - if (!CheckCPUIDPresence()) - return false; - - // Now we get the CPUID standard level 0x00000001 - __asm +public: + LLProcessorInfoWindowsImpl() { - mov eax, 1 - cpuid - mov eaxreg, eax - mov ebxreg, ebx - mov edxreg, edx + getCPUIDInfo(); + setInfo(eFrequency, calculate_cpu_frequency(50)); } - - // Then get the cpu model, family, type, stepping and brand id by masking - // the eax and ebx register - CPUInfo.uiStepping = eaxreg & 0xF; - CPUInfo.uiModel = (eaxreg >> 4) & 0xF; - CPUInfo.uiFamily = (eaxreg >> 8) & 0xF; - CPUInfo.uiType = (eaxreg >> 12) & 0x3; - CPUInfo.uiBrandID = ebxreg & 0xF; - static const char* INTEL_BRAND[] = +private: + void getCPUIDInfo() { - /* 0x00 */ "", - /* 0x01 */ "0.18 micron Intel Celeron", - /* 0x02 */ "0.18 micron Intel Pentium III", - /* 0x03 */ "0.13 micron Intel Celeron", - /* 0x04 */ "0.13 micron Intel Pentium III", - /* 0x05 */ "", - /* 0x06 */ "0.13 micron Intel Pentium III Mobile", - /* 0x07 */ "0.13 micron Intel Celeron Mobile", - /* 0x08 */ "0.18 micron Intel Pentium 4", - /* 0x09 */ "0.13 micron Intel Pentium 4", - /* 0x0A */ "0.13 micron Intel Celeron", - /* 0x0B */ "0.13 micron Intel Pentium 4 Xeon", - /* 0x0C */ "Intel Xeon MP", - /* 0x0D */ "", - /* 0x0E */ "0.18 micron Intel Pentium 4 Xeon", - /* 0x0F */ "Mobile Intel Celeron", - /* 0x10 */ "", - /* 0x11 */ "Mobile Genuine Intel", - /* 0x12 */ "Intel Celeron M", - /* 0x13 */ "Mobile Intel Celeron", - /* 0x14 */ "Intel Celeron", - /* 0x15 */ "Mobile Genuine Intel", - /* 0x16 */ "Intel Pentium M", - /* 0x17 */ "Mobile Intel Celeron", - }; + // http://msdn.microsoft.com/en-us/library/hskdteyh(VS.80).aspx - // Only override the brand if we have it in the lookup table. We should - // already have a string here from GetCPUInfo(). JC - if ( CPUInfo.uiBrandID < LL_ARRAY_SIZE(INTEL_BRAND) ) - { - strcpy(CPUInfo.strBrandID, INTEL_BRAND[CPUInfo.uiBrandID]); + // __cpuid with an InfoType argument of 0 returns the number of + // valid Ids in cpu_info[0] and the CPU identification string in + // the other three array elements. The CPU identification string is + // not in linear order. The code below arranges the information + // in a human readable form. + int cpu_info[4] = {-1}; + __cpuid(cpu_info, 0); + unsigned int ids = (unsigned int)cpu_info[0]; + setConfig(eMaxID, (S32)ids); - if (CPUInfo.uiBrandID == 3 && CPUInfo.uiModel == 6) + char cpu_vendor[0x20]; + memset(cpu_vendor, 0, sizeof(cpu_vendor)); + *((int*)cpu_vendor) = cpu_info[1]; + *((int*)(cpu_vendor+4)) = cpu_info[3]; + *((int*)(cpu_vendor+8)) = cpu_info[2]; + setInfo(eVendor, cpu_vendor); + + // Get the information associated with each valid Id + for(unsigned int i=0; i<=ids; ++i) { - strcpy(CPUInfo.strBrandID, "0.18 micron Intel Pentium III Xeon"); - } - } + __cpuid(cpu_info, i); - // Then we translate the cpu family - switch (CPUInfo.uiFamily) - { - case 3: // Family = 3: i386 (80386) processor family - strcpy(CPUInfo.strFamily, "Intel i386"); /* Flawfinder: ignore */ - break; - case 4: // Family = 4: i486 (80486) processor family - strcpy(CPUInfo.strFamily, "Intel i486"); /* Flawfinder: ignore */ - break; - case 5: // Family = 5: Pentium (80586) processor family - strcpy(CPUInfo.strFamily, "Intel Pentium"); /* Flawfinder: ignore */ - break; - case 6: // Family = 6: Pentium Pro (80686) processor family - strcpy(CPUInfo.strFamily, "Intel Pentium Pro/2/3, Core"); /* Flawfinder: ignore */ - break; - case 15: // Family = 15: Extended family specific - // Masking the extended family - CPUInfo.uiExtendedFamily = (eaxreg >> 20) & 0xFF; - switch (CPUInfo.uiExtendedFamily) + // Interpret CPU feature information. + if (i == 1) { - case 0: // Family = 15, Ext. Family = 0: Pentium 4 (80786 ??) processor family - strcpy(CPUInfo.strFamily, "Intel Pentium 4"); /* Flawfinder: ignore */ - break; - case 1: // Family = 15, Ext. Family = 1: McKinley (64-bit) processor family - strcpy(CPUInfo.strFamily, "Intel McKinley (IA-64)"); /* Flawfinder: ignore */ - break; - default: // Sure is sure - strcpy(CPUInfo.strFamily, "Unknown Intel Pentium 4+"); /* Flawfinder: ignore */ - break; - } - break; - default: // Failsave - strcpy(CPUInfo.strFamily, "Unknown"); /* Flawfinder: ignore */ - break; - } + setInfo(eStepping, cpu_info[0] & 0xf); + setInfo(eModel, (cpu_info[0] >> 4) & 0xf); + int family = (cpu_info[0] >> 8) & 0xf; + setInfo(eFamily, family); + setInfo(eType, (cpu_info[0] >> 12) & 0x3); + setInfo(eExtendedModel, (cpu_info[0] >> 16) & 0xf); + int ext_family = (cpu_info[0] >> 20) & 0xff; + setInfo(eExtendedFamily, ext_family); + setInfo(eBrandID, cpu_info[1] & 0xff); - // Now we come to the big deal, the exact model name - switch (CPUInfo.uiFamily) - { - case 3: // i386 (80386) processor family - strcpy(CPUInfo.strModel, "Unknown Intel i386"); /* Flawfinder: ignore */ - strncat(strCPUName, "Intel i386", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */ - break; - case 4: // i486 (80486) processor family - switch (CPUInfo.uiModel) - { - case 0: // Model = 0: i486 DX-25/33 processor model - strcpy(CPUInfo.strModel, "Intel i486 DX-25/33"); /* Flawfinder: ignore */ - strncat(strCPUName, "Intel i486 DX-25/33", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */ - break; - case 1: // Model = 1: i486 DX-50 processor model - strcpy(CPUInfo.strModel, "Intel i486 DX-50"); /* Flawfinder: ignore */ - strncat(strCPUName, "Intel i486 DX-50", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */ - break; - case 2: // Model = 2: i486 SX processor model - strcpy(CPUInfo.strModel, "Intel i486 SX"); /* Flawfinder: ignore */ - strncat(strCPUName, "Intel i486 SX", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */ - break; - case 3: // Model = 3: i486 DX2 (with i487 numeric coprocessor) processor model - strcpy(CPUInfo.strModel, "Intel i486 487/DX2"); /* Flawfinder: ignore */ - strncat(strCPUName, "Intel i486 DX2 with i487 numeric coprocessor", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */ - break; - case 4: // Model = 4: i486 SL processor model (never heard ?!?) - strcpy(CPUInfo.strModel, "Intel i486 SL"); /* Flawfinder: ignore */ - strncat(strCPUName, "Intel i486 SL", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */ - break; - case 5: // Model = 5: i486 SX2 processor model - strcpy(CPUInfo.strModel, "Intel i486 SX2"); /* Flawfinder: ignore */ - strncat(strCPUName, "Intel i486 SX2", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */ - break; - case 7: // Model = 7: i486 write-back enhanced DX2 processor model - strcpy(CPUInfo.strModel, "Intel i486 write-back enhanced DX2"); /* Flawfinder: ignore */ - strncat(strCPUName, "Intel i486 write-back enhanced DX2", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */ - break; - case 8: // Model = 8: i486 DX4 processor model - strcpy(CPUInfo.strModel, "Intel i486 DX4"); /* Flawfinder: ignore */ - strncat(strCPUName, "Intel i486 DX4", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */ - break; - case 9: // Model = 9: i486 write-back enhanced DX4 processor model - strcpy(CPUInfo.strModel, "Intel i486 write-back enhanced DX4"); /* Flawfinder: ignore */ - strncat(strCPUName, "Intel i486 DX4", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */ - break; - default: // ... - strcpy(CPUInfo.strModel, "Unknown Intel i486"); /* Flawfinder: ignore */ - strncat(strCPUName, "Intel i486 (Unknown model)", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */ - break; - } - break; - case 5: // Pentium (80586) processor family - switch (CPUInfo.uiModel) - { - case 0: // Model = 0: Pentium (P5 A-Step) processor model - strcpy(CPUInfo.strModel, "Intel Pentium (P5 A-Step)"); /* Flawfinder: ignore */ - strncat(strCPUName, "Intel Pentium (P5 A-Step core)", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */ - break; // Famous for the DIV bug, as far as I know - case 1: // Model = 1: Pentium 60/66 processor model - strcpy(CPUInfo.strModel, "Intel Pentium 60/66 (P5)"); /* Flawfinder: ignore */ - strncat(strCPUName, "Intel Pentium 60/66 (P5 core)", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */ - break; - case 2: // Model = 2: Pentium 75-200 (P54C) processor model - strcpy(CPUInfo.strModel, "Intel Pentium 75-200 (P54C)"); /* Flawfinder: ignore */ - strncat(strCPUName, "Intel Pentium 75-200 (P54C core)", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */ - break; - case 3: // Model = 3: Pentium overdrive for 486 systems processor model - strcpy(CPUInfo.strModel, "Intel Pentium for 486 system (P24T Overdrive)"); /* Flawfinder: ignore */ - strncat(strCPUName, "Intel Pentium for 486 (P24T overdrive core)", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ - break; - case 4: // Model = 4: Pentium MMX processor model - strcpy(CPUInfo.strModel, "Intel Pentium MMX (P55C)"); /*Flawfinder: ignore*/ - strncat(strCPUName, "Intel Pentium MMX (P55C core)", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ - break; - case 7: // Model = 7: Pentium processor model (don't know difference to Model=2) - strcpy(CPUInfo.strModel, "Intel Pentium (P54C)"); /*Flawfinder: ignore*/ - strncat(strCPUName, "Intel Pentium (P54C core)", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ - break; - case 8: // Model = 8: Pentium MMX (0.25 micron) processor model - strcpy(CPUInfo.strModel, "Intel Pentium MMX (P55C), 0.25 micron"); /*Flawfinder: ignore*/ - strncat(strCPUName, "Intel Pentium MMX (P55C core), 0.25 micron", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ - break; - default: // ... - strcpy(CPUInfo.strModel, "Unknown Intel Pentium"); /*Flawfinder: ignore*/ - strncat(strCPUName, "Intel Pentium (Unknown P5-model)", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ - break; - } - break; - case 6: // Pentium Pro (80686) processor family - switch (CPUInfo.uiModel) - { - case 0: // Model = 0: Pentium Pro (P6 A-Step) processor model - strcpy(CPUInfo.strModel, "Intel Pentium Pro (P6 A-Step)"); /*Flawfinder: ignore*/ - strncat(strCPUName, "Intel Pentium Pro (P6 A-Step core)", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ - break; - case 1: // Model = 1: Pentium Pro - strcpy(CPUInfo.strModel, "Intel Pentium Pro (P6)"); /*Flawfinder: ignore*/ - strncat(strCPUName, "Intel Pentium Pro (P6 core)", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ - break; - case 3: // Model = 3: Pentium II (66 MHz FSB, I think) processor model - strcpy(CPUInfo.strModel, "Intel Pentium II Model 3, 0.28 micron"); /*Flawfinder: ignore*/ - strncat(strCPUName, "Intel Pentium II (Model 3 core, 0.28 micron process)", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ - break; - case 5: // Model = 5: Pentium II/Xeon/Celeron (0.25 micron) processor model - strcpy(CPUInfo.strModel, "Intel Pentium II Model 5/Xeon/Celeron, 0.25 micron"); /*Flawfinder: ignore*/ - strncat(strCPUName, "Intel Pentium II/Xeon/Celeron (Model 5 core, 0.25 micron process)", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ - break; - case 6: // Model = 6: Pentium II with internal L2 cache - strcpy(CPUInfo.strModel, "Intel Pentium II - internal L2 cache"); /*Flawfinder: ignore*/ - strncat(strCPUName, "Intel Pentium II with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ - break; - case 7: // Model = 7: Pentium III/Xeon (extern L2 cache) processor model - strcpy(CPUInfo.strModel, "Intel Pentium III/Pentium III Xeon - external L2 cache, 0.25 micron"); /*Flawfinder: ignore*/ - strncat(strCPUName, "Intel Pentium III/Pentium III Xeon (0.25 micron process) with external L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ - break; - case 8: // Model = 8: Pentium III/Xeon/Celeron (256 KB on-die L2 cache) processor model - strcpy(CPUInfo.strModel, "Intel Pentium III/Celeron/Pentium III Xeon - internal L2 cache, 0.18 micron"); /*Flawfinder: ignore*/ - // We want to know it exactly: - switch (CPUInfo.uiBrandID) + setInfo(eFamilyName, compute_CPUFamilyName(cpu_vendor, family, ext_family)); + + setConfig(eCLFLUSHCacheLineSize, ((cpu_info[1] >> 8) & 0xff) * 8); + setConfig(eAPICPhysicalID, (cpu_info[1] >> 24) & 0xff); + + if(cpu_info[2] & 0x1) + { + setExtension(cpu_feature_names[eSSE3_Features]); + } + + if(cpu_info[2] & 0x8) + { + setExtension(cpu_feature_names[eMONTIOR_MWAIT]); + } + + if(cpu_info[2] & 0x10) + { + setExtension(cpu_feature_names[eCPLDebugStore]); + } + + if(cpu_info[2] & 0x100) + { + setExtension(cpu_feature_names[eThermalMonitor2]); + } + + unsigned int feature_info = (unsigned int) cpu_info[3]; + for(unsigned int index = 0, bit = 1; index < eSSE3_Features; ++index, bit <<= 1) + { + if(feature_info & bit) { - case 1: // Model = 8, Brand id = 1: Celeron (on-die L2 cache) processor model - strncat(strCPUName, "Intel Celeron (0.18 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ - break; - case 2: // Model = 8, Brand id = 2: Pentium III (on-die L2 cache) processor model (my current cpu :-)) - strncat(strCPUName, "Intel Pentium III (0.18 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ - break; - case 3: // Model = 8, Brand id = 3: Pentium III Xeon (on-die L2 cache) processor model - strncat(strCPUName, "Intel Pentium III Xeon (0.18 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ - break; - default: // ... - strncat(strCPUName, "Intel Pentium III core (unknown model, 0.18 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ - break; + setExtension(cpu_feature_names[index]); } - break; - case 9: // Model = 9: Intel Pentium M processor, Intel Celeron M processor, model 9 - strcpy(CPUInfo.strModel, "Intel Pentium M Series Processor"); /*Flawfinder: ignore*/ - strncat(strCPUName, "Intel Pentium M Series Processor", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ - break; - case 0xA: // Model = 0xA: Pentium III/Xeon/Celeron (1 or 2 MB on-die L2 cache) processor model - strcpy(CPUInfo.strModel, "Intel Pentium III/Celeron/Pentium III Xeon - internal L2 cache, 0.18 micron"); /*Flawfinder: ignore*/ - // Exact detection: - switch (CPUInfo.uiBrandID) - { - case 1: // Model = 0xA, Brand id = 1: Celeron (1 or 2 MB on-die L2 cache (does it exist??)) processor model - strncat(strCPUName, "Intel Celeron (0.18 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ - break; - case 2: // Model = 0xA, Brand id = 2: Pentium III (1 or 2 MB on-die L2 cache (never seen...)) processor model - strncat(strCPUName, "Intel Pentium III (0.18 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ - break; - case 3: // Model = 0xA, Brand id = 3: Pentium III Xeon (1 or 2 MB on-die L2 cache) processor model - strncat(strCPUName, "Intel Pentium III Xeon (0.18 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ - break; - default: // Getting bored of this............ - strncat(strCPUName, "Intel Pentium III core (unknown model, 0.18 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ - break; - } - break; - case 0xB: // Model = 0xB: Pentium III/Xeon/Celeron (Tualatin core, on-die cache) processor model - strcpy(CPUInfo.strModel, "Intel Pentium III/Celeron/Pentium III Xeon - internal L2 cache, 0.13 micron"); /*Flawfinder: ignore*/ - // Omniscient: ;-) - switch (CPUInfo.uiBrandID) - { - case 3: // Model = 0xB, Brand id = 3: Celeron (Tualatin core) processor model - strncat(strCPUName, "Intel Celeron (Tualatin core, 0.13 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ - break; - case 4: // Model = 0xB, Brand id = 4: Pentium III (Tualatin core) processor model - strncat(strCPUName, "Intel Pentium III (Tualatin core, 0.13 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ - break; - case 7: // Model = 0xB, Brand id = 7: Celeron mobile (Tualatin core) processor model - strncat(strCPUName, "Intel Celeron mobile (Tualatin core, 0.13 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ - break; - default: // *bored* - strncat(strCPUName, "Intel Pentium III Tualatin core (unknown model, 0.13 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ - break; - } - break; - case 0xD: // Model = 0xD: Intel Pentium M processor, Intel Celeron M processor, model D - strcpy(CPUInfo.strModel, "Intel Pentium M Series Processor"); /*Flawfinder: ignore*/ - strncat(strCPUName, "Intel Pentium M Series Processor", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ - break; - case 0xE: // Model = 0xE: Intel Core Duo processor, Intel Core Solo processor, model E - strcpy(CPUInfo.strModel, "Intel Core Series Processor"); /*Flawfinder: ignore*/ - strncat(strCPUName, "Intel Core Series Processor", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ - break; - case 0xF: // Model = 0xF: Intel Core 2 Duo processor, model F - strcpy(CPUInfo.strModel, "Intel Core 2 Series Processor"); /*Flawfinder: ignore*/ - strncat(strCPUName, "Intel Core 2 Series Processor", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ - break; - default: // *more bored* - strcpy(CPUInfo.strModel, "Unknown Intel Pentium Pro/2/3, Core"); /*Flawfinder: ignore*/ - strncat(strCPUName, "Intel Pentium Pro/2/3, Core (Unknown model)", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ - break; + } } - break; - case 15: // Extended processor family - // Masking the extended model - CPUInfo.uiExtendedModel = (eaxreg >> 16) & 0xFF; - switch (CPUInfo.uiModel) + } + + // Calling __cpuid with 0x80000000 as the InfoType argument + // gets the number of valid extended IDs. + __cpuid(cpu_info, 0x80000000); + unsigned int ext_ids = cpu_info[0]; + setConfig(eMaxExtID, 0); + + char cpu_brand_string[0x40]; + memset(cpu_brand_string, 0, sizeof(cpu_brand_string)); + + // Get the information associated with each extended ID. + for(unsigned int i=0x80000000; i<=ext_ids; ++i) + { + __cpuid(cpu_info, i); + + // Interpret CPU brand string and cache information. + if (i == 0x80000002) + memcpy(cpu_brand_string, cpu_info, sizeof(cpu_info)); + else if (i == 0x80000003) + memcpy(cpu_brand_string + 16, cpu_info, sizeof(cpu_info)); + else if (i == 0x80000004) { - case 0: // Model = 0: Pentium 4 Willamette (A-Step) core - if ((CPUInfo.uiBrandID) == 8) // Brand id = 8: P4 Willamette - { - strcpy(CPUInfo.strModel, "Intel Pentium 4 Willamette (A-Step)"); /*Flawfinder: ignore*/ - strncat(strCPUName, "Intel Pentium 4 Willamette (A-Step)", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ - } - else // else Xeon - { - strcpy(CPUInfo.strModel, "Intel Pentium 4 Willamette Xeon (A-Step)"); /* Flawfinder: ignore */ - strncat(strCPUName, "Intel Pentium 4 Willamette Xeon (A-Step)", sizeof(strCPUName) - strlen(strCPUName) - 1); /* Flawfinder: ignore */ - } - break; - case 1: // Model = 1: Pentium 4 Willamette core - if ((CPUInfo.uiBrandID) == 8) // Brand id = 8: P4 Willamette - { - strcpy(CPUInfo.strModel, "Intel Pentium 4 Willamette"); /* Flawfinder: ignore */ - strncat(strCPUName, "Intel Pentium 4 Willamette", sizeof(strCPUName) - strlen(strCPUName) - 1); /* Flawfinder: ignore */ - } - else // else Xeon - { - strcpy(CPUInfo.strModel, "Intel Pentium 4 Willamette Xeon"); /* Flawfinder: ignore */ - strncat(strCPUName, "Intel Pentium 4 Willamette Xeon", sizeof(strCPUName) - strlen(strCPUName) - 1); /* Flawfinder: ignore */ - } - break; - case 2: // Model = 2: Pentium 4 Northwood core - if (((CPUInfo.uiBrandID) == 9) || ((CPUInfo.uiBrandID) == 0xA)) // P4 Willamette - { - strcpy(CPUInfo.strModel, "Intel Pentium 4 Northwood"); /* Flawfinder: ignore */ - strncat(strCPUName, "Intel Pentium 4 Northwood", sizeof(strCPUName) - strlen(strCPUName) - 1); /* Flawfinder: ignore */ - } - else // Xeon - { - strcpy(CPUInfo.strModel, "Intel Pentium 4 Northwood Xeon"); /* Flawfinder: ignore */ - strncat(strCPUName, "Intel Pentium 4 Northwood Xeon", sizeof(strCPUName) - strlen(strCPUName) - 1); /* Flawfinder: ignore */ - } - break; - default: // Silly stupid never used failsave option - strcpy(CPUInfo.strModel, "Unknown Intel Pentium 4"); /* Flawfinder: ignore */ - strncat(strCPUName, "Intel Pentium 4 (Unknown model)", sizeof(strCPUName) - strlen(strCPUName) - 1); /* Flawfinder: ignore */ - break; + memcpy(cpu_brand_string + 32, cpu_info, sizeof(cpu_info)); + setInfo(eBrandName, cpu_brand_string); } - break; - default: // *grmpf* - strcpy(CPUInfo.strModel, "Unknown Intel model"); /* Flawfinder: ignore */ - strncat(strCPUName, "Intel (Unknown model)", sizeof(strCPUName) - strlen(strCPUName) - 1); /* Flawfinder: ignore */ - break; - } - - // After the long processor model block we now come to the processors serial - // number. - // First of all we check if the processor supports the serial number - if (CPUInfo.MaxSupportedLevel >= 3) - { - // If it supports the serial number CPUID level 0x00000003 we read the data - unsigned long sig1, sig2, sig3; - __asm - { - mov eax, 1 - cpuid - mov sig1, eax - mov eax, 3 - cpuid - mov sig2, ecx - mov sig3, edx - } - // Then we convert the data to a readable string - snprintf( /* Flawfinder: ignore */ - CPUInfo.strProcessorSerial, - sizeof(CPUInfo.strProcessorSerial), - "%04lX-%04lX-%04lX-%04lX-%04lX-%04lX", - sig1 >> 16, - sig1 & 0xFFFF, - sig3 >> 16, - sig3 & 0xFFFF, - sig2 >> 16, sig2 & 0xFFFF); - } - else - { - // If there's no serial number support we just put "No serial number" - snprintf( /* Flawfinder: ignore */ - CPUInfo.strProcessorSerial, - sizeof(CPUInfo.strProcessorSerial), - "No Processor Serial Number"); - } - - // Now we get the standard processor extensions - GetStandardProcessorExtensions(); - - // And finally the processor configuration (caches, TLBs, ...) and translate - // the data to readable strings - GetStandardProcessorConfiguration(); - TranslateProcessorConfiguration(); - - // At last... - return true; -#else - return FALSE; -#endif -} - -// bool CProcessor::AnalyzeAMDProcessor() -// ====================================== -// Private class function for analyzing an AMD processor -//////////////////////////////////////////////////////// -bool CProcessor::AnalyzeAMDProcessor() -{ -#if LL_WINDOWS - unsigned long eaxreg, ebxreg, ecxreg, edxreg; - - // First of all we check if the CPUID command is available - if (!CheckCPUIDPresence()) - return 0; - - // Now we get the CPUID standard level 0x00000001 - __asm - { - mov eax, 1 - cpuid - mov eaxreg, eax - mov ebxreg, ebx - mov edxreg, edx - } - - // Then we mask the model, family, stepping and type (AMD does not support brand id) - CPUInfo.uiStepping = eaxreg & 0xF; - CPUInfo.uiModel = (eaxreg >> 4) & 0xF; - CPUInfo.uiFamily = (eaxreg >> 8) & 0xF; - CPUInfo.uiType = (eaxreg >> 12) & 0x3; - - // Now we check if the processor supports the brand id string extended CPUID level - if (CPUInfo.MaxSupportedExtendedLevel >= 0x80000004) - { - // If it supports the extended CPUID level 0x80000004 we read the data - char tmp[52]; /* Flawfinder: ignore */ - memset(tmp, 0, sizeof(tmp)); - __asm - { - mov eax, 0x80000002 - cpuid - mov dword ptr [tmp], eax - mov dword ptr [tmp+4], ebx - mov dword ptr [tmp+8], ecx - mov dword ptr [tmp+12], edx - mov eax, 0x80000003 - cpuid - mov dword ptr [tmp+16], eax - mov dword ptr [tmp+20], ebx - mov dword ptr [tmp+24], ecx - mov dword ptr [tmp+28], edx - mov eax, 0x80000004 - cpuid - mov dword ptr [tmp+32], eax - mov dword ptr [tmp+36], ebx - mov dword ptr [tmp+40], ecx - mov dword ptr [tmp+44], edx - } - // And copy it to the brand id string - strncpy(CPUInfo.strBrandID, tmp,sizeof(CPUInfo.strBrandID)-1); - CPUInfo.strBrandID[sizeof(CPUInfo.strBrandID)-1]='\0'; - } - else - { - // Or just tell there is no brand id string support - strcpy(CPUInfo.strBrandID, ""); /* Flawfinder: ignore */ - } - - // After that we translate the processor family - switch(CPUInfo.uiFamily) - { - case 4: // Family = 4: 486 (80486) or 5x86 (80486) processor family - switch (CPUInfo.uiModel) + else if (i == 0x80000006) { - case 3: // Thanks to AMD for this nice form of family - case 7: // detection.... *grmpf* - case 8: - case 9: - strcpy(CPUInfo.strFamily, "AMD 80486"); /* Flawfinder: ignore */ - break; - case 0xE: - case 0xF: - strcpy(CPUInfo.strFamily, "AMD 5x86"); /* Flawfinder: ignore */ - break; - default: - strcpy(CPUInfo.strFamily, "Unknown family"); /* Flawfinder: ignore */ - break; - } - break; - case 5: // Family = 5: K5 or K6 processor family - switch (CPUInfo.uiModel) - { - case 0: - case 1: - case 2: - case 3: - strcpy(CPUInfo.strFamily, "AMD K5"); /* Flawfinder: ignore */ - break; - case 6: - case 7: - case 8: - case 9: - strcpy(CPUInfo.strFamily, "AMD K6"); /* Flawfinder: ignore */ - break; - default: - strcpy(CPUInfo.strFamily, "Unknown family"); /* Flawfinder: ignore */ - break; - } - break; - case 6: // Family = 6: K7 (Athlon, ...) processor family - strcpy(CPUInfo.strFamily, "AMD K7"); /* Flawfinder: ignore */ - break; - default: // For security - strcpy(CPUInfo.strFamily, "Unknown family"); /* Flawfinder: ignore */ - break; - } - - // After the family detection we come to the specific processor model - // detection - switch (CPUInfo.uiFamily) - { - case 4: // Family = 4: 486 (80486) or 5x85 (80486) processor family - switch (CPUInfo.uiModel) - { - case 3: // Model = 3: 80486 DX2 - strcpy(CPUInfo.strModel, "AMD 80486 DX2"); /* Flawfinder: ignore */ - strncat(strCPUName, "AMD 80486 DX2", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */ - break; - case 7: // Model = 7: 80486 write-back enhanced DX2 - strcpy(CPUInfo.strModel, "AMD 80486 write-back enhanced DX2"); /* Flawfinder: ignore */ - strncat(strCPUName, "AMD 80486 write-back enhanced DX2", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */ - break; - case 8: // Model = 8: 80486 DX4 - strcpy(CPUInfo.strModel, "AMD 80486 DX4"); /* Flawfinder: ignore */ - strncat(strCPUName, "AMD 80486 DX4", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */ - break; - case 9: // Model = 9: 80486 write-back enhanced DX4 - strcpy(CPUInfo.strModel, "AMD 80486 write-back enhanced DX4"); /* Flawfinder: ignore */ - strncat(strCPUName, "AMD 80486 write-back enhanced DX4", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */ - break; - case 0xE: // Model = 0xE: 5x86 - strcpy(CPUInfo.strModel, "AMD 5x86"); /* Flawfinder: ignore */ - strncat(strCPUName, "AMD 5x86", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */ - break; - case 0xF: // Model = 0xF: 5x86 write-back enhanced (oh my god.....) - strcpy(CPUInfo.strModel, "AMD 5x86 write-back enhanced"); /* Flawfinder: ignore */ - strncat(strCPUName, "AMD 5x86 write-back enhanced", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */ - break; - default: // ... - strcpy(CPUInfo.strModel, "Unknown AMD 80486 or 5x86 model"); /* Flawfinder: ignore */ - strncat(strCPUName, "AMD 80486 or 5x86 (Unknown model)", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */ - break; - } - break; - case 5: // Family = 5: K5 / K6 processor family - switch (CPUInfo.uiModel) - { - case 0: // Model = 0: K5 SSA 5 (Pentium Rating *ggg* 75, 90 and 100 Mhz) - strcpy(CPUInfo.strModel, "AMD K5 SSA5 (PR75, PR90, PR100)"); /* Flawfinder: ignore */ - strncat(strCPUName, "AMD K5 SSA5 (PR75, PR90, PR100)", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */ - break; - case 1: // Model = 1: K5 5k86 (PR 120 and 133 MHz) - strcpy(CPUInfo.strModel, "AMD K5 5k86 (PR120, PR133)"); /* Flawfinder: ignore */ - strncat(strCPUName, "AMD K5 5k86 (PR120, PR133)", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */ - break; - case 2: // Model = 2: K5 5k86 (PR 166 MHz) - strcpy(CPUInfo.strModel, "AMD K5 5k86 (PR166)"); /* Flawfinder: ignore */ - strncat(strCPUName, "AMD K5 5k86 (PR166)", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */ - break; - case 3: // Model = 3: K5 5k86 (PR 200 MHz) - strcpy(CPUInfo.strModel, "AMD K5 5k86 (PR200)"); /* Flawfinder: ignore */ - strncat(strCPUName, "AMD K5 5k86 (PR200)", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */ - break; - case 6: // Model = 6: K6 - strcpy(CPUInfo.strModel, "AMD K6 (0.30 micron)"); /* Flawfinder: ignore */ - strncat(strCPUName, "AMD K6 (0.30 micron)", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */ - break; - case 7: // Model = 7: K6 (0.25 micron) - strcpy(CPUInfo.strModel, "AMD K6 (0.25 micron)"); /* Flawfinder: ignore */ - strncat(strCPUName, "AMD K6 (0.25 micron)", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */ - break; - case 8: // Model = 8: K6-2 - strcpy(CPUInfo.strModel, "AMD K6-2"); /* Flawfinder: ignore */ - strncat(strCPUName, "AMD K6-2", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */ - break; - case 9: // Model = 9: K6-III - strcpy(CPUInfo.strModel, "AMD K6-III"); /* Flawfinder: ignore */ - strncat(strCPUName, "AMD K6-III", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */ - break; - case 0xD: // Model = 0xD: K6-2+ / K6-III+ - strcpy(CPUInfo.strModel, "AMD K6-2+ or K6-III+ (0.18 micron)"); /* Flawfinder: ignore */ - strncat(strCPUName, "AMD K6-2+ or K6-III+ (0.18 micron)", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */ - break; - default: // ... - strcpy(CPUInfo.strModel, "Unknown AMD K5 or K6 model"); /* Flawfinder: ignore */ - strncat(strCPUName, "AMD K5 or K6 (Unknown model)", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */ - break; - } - break; - case 6: // Family = 6: K7 processor family (AMDs first good processors) - switch (CPUInfo.uiModel) - { - case 1: // Athlon - strcpy(CPUInfo.strModel, "AMD Athlon (0.25 micron)"); /* Flawfinder: ignore */ - strncat(strCPUName, "AMD Athlon (0.25 micron)", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */ - break; - case 2: // Athlon (0.18 micron) - strcpy(CPUInfo.strModel, "AMD Athlon (0.18 micron)"); /* Flawfinder: ignore */ - strncat(strCPUName, "AMD Athlon (0.18 micron)", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */ - break; - case 3: // Duron (Spitfire core) - strcpy(CPUInfo.strModel, "AMD Duron (Spitfire)"); /* Flawfinder: ignore */ - strncat(strCPUName, "AMD Duron (Spitfire core)", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */ - break; - case 4: // Athlon (Thunderbird core) - strcpy(CPUInfo.strModel, "AMD Athlon (Thunderbird)"); /* Flawfinder: ignore */ - strncat(strCPUName, "AMD Athlon (Thunderbird core)", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */ - break; - case 6: // Athlon MP / Mobile Athlon (Palomino core) - strcpy(CPUInfo.strModel, "AMD Athlon MP/Mobile Athlon (Palomino)"); /* Flawfinder: ignore */ - strncat(strCPUName, "AMD Athlon MP/Mobile Athlon (Palomino core)", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */ - break; - case 7: // Mobile Duron (Morgan core) - strcpy(CPUInfo.strModel, "AMD Mobile Duron (Morgan)"); /* Flawfinder: ignore */ - strncat(strCPUName, "AMD Mobile Duron (Morgan core)", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */ - break; - default: // ... - strcpy(CPUInfo.strModel, "Unknown AMD K7 model"); /* Flawfinder: ignore */ - strncat(strCPUName, "AMD K7 (Unknown model)", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */ - break; - } - break; - default: // ... - strcpy(CPUInfo.strModel, "Unknown AMD model"); /* Flawfinder: ignore */ - strncat(strCPUName, "AMD (Unknown model)", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */ - break; - } - - // Now we read the standard processor extension that are stored in the same - // way the Intel standard extensions are - GetStandardProcessorExtensions(); - - // Then we check if theres an extended CPUID level support - if (CPUInfo.MaxSupportedExtendedLevel >= 0x80000001) - { - // If we can access the extended CPUID level 0x80000001 we get the - // edx register - __asm - { - mov eax, 0x80000001 - cpuid - mov edxreg, edx - } - - // Now we can mask some AMD specific cpu extensions - CPUInfo._Ext.EMMX_MultimediaExtensions = CheckBit(edxreg, 22); - CPUInfo._Ext.AA64_AMD64BitArchitecture = CheckBit(edxreg, 29); - CPUInfo._Ext._E3DNOW_InstructionExtensions = CheckBit(edxreg, 30); - CPUInfo._Ext._3DNOW_InstructionExtensions = CheckBit(edxreg, 31); - } - - // After that we check if the processor supports the ext. CPUID level - // 0x80000006 - if (CPUInfo.MaxSupportedExtendedLevel >= 0x80000006) - { - // If it's present, we read it out - __asm - { - mov eax, 0x80000005 - cpuid - mov eaxreg, eax - mov ebxreg, ebx - mov ecxreg, ecx - mov edxreg, edx - } - - // Then we mask the L1 Data TLB information - if ((ebxreg >> 16) && (eaxreg >> 16)) - { - CPUInfo._Data.bPresent = true; - strcpy(CPUInfo._Data.strPageSize, "4 KB / 2 MB / 4MB"); /*Flawfinder: ignore*/ - CPUInfo._Data.uiAssociativeWays = (eaxreg >> 24) & 0xFF; - CPUInfo._Data.uiEntries = (eaxreg >> 16) & 0xFF; - } - else if (eaxreg >> 16) - { - CPUInfo._Data.bPresent = true; - strcpy(CPUInfo._Data.strPageSize, "2 MB / 4MB"); /*Flawfinder: ignore*/ - CPUInfo._Data.uiAssociativeWays = (eaxreg >> 24) & 0xFF; - CPUInfo._Data.uiEntries = (eaxreg >> 16) & 0xFF; - } - else if (ebxreg >> 16) - { - CPUInfo._Data.bPresent = true; - strcpy(CPUInfo._Data.strPageSize, "4 KB"); /*Flawfinder: ignore*/ - CPUInfo._Data.uiAssociativeWays = (ebxreg >> 24) & 0xFF; - CPUInfo._Data.uiEntries = (ebxreg >> 16) & 0xFF; - } - if (CPUInfo._Data.uiAssociativeWays == 0xFF) - CPUInfo._Data.uiAssociativeWays = (unsigned int) -1; - - // Now the L1 Instruction/Code TLB information - if ((ebxreg & 0xFFFF) && (eaxreg & 0xFFFF)) - { - CPUInfo._Instruction.bPresent = true; - strcpy(CPUInfo._Instruction.strPageSize, "4 KB / 2 MB / 4MB"); /*Flawfinder: ignore*/ - CPUInfo._Instruction.uiAssociativeWays = (eaxreg >> 8) & 0xFF; - CPUInfo._Instruction.uiEntries = eaxreg & 0xFF; - } - else if (eaxreg & 0xFFFF) - { - CPUInfo._Instruction.bPresent = true; - strcpy(CPUInfo._Instruction.strPageSize, "2 MB / 4MB"); /*Flawfinder: ignore*/ - CPUInfo._Instruction.uiAssociativeWays = (eaxreg >> 8) & 0xFF; - CPUInfo._Instruction.uiEntries = eaxreg & 0xFF; - } - else if (ebxreg & 0xFFFF) - { - CPUInfo._Instruction.bPresent = true; - strcpy(CPUInfo._Instruction.strPageSize, "4 KB"); /*Flawfinder: ignore*/ - CPUInfo._Instruction.uiAssociativeWays = (ebxreg >> 8) & 0xFF; - CPUInfo._Instruction.uiEntries = ebxreg & 0xFF; - } - if (CPUInfo._Instruction.uiAssociativeWays == 0xFF) - CPUInfo._Instruction.uiAssociativeWays = (unsigned int) -1; - - // Then we read the L1 data cache information - if ((ecxreg >> 24) > 0) - { - CPUInfo._L1.Data.bPresent = true; - snprintf(CPUInfo._L1.Data.strSize, sizeof(CPUInfo._L1.Data.strSize), "%d KB", ecxreg >> 24); /* Flawfinder: ignore */ - CPUInfo._L1.Data.uiAssociativeWays = (ecxreg >> 15) & 0xFF; - CPUInfo._L1.Data.uiLineSize = ecxreg & 0xFF; - } - // After that we read the L2 instruction/code cache information - if ((edxreg >> 24) > 0) - { - CPUInfo._L1.Instruction.bPresent = true; - snprintf(CPUInfo._L1.Instruction.strSize, sizeof(CPUInfo._L1.Instruction.strSize), "%d KB", edxreg >> 24); /* Flawfinder: ignore */ - CPUInfo._L1.Instruction.uiAssociativeWays = (edxreg >> 15) & 0xFF; - CPUInfo._L1.Instruction.uiLineSize = edxreg & 0xFF; - } - - // Note: I'm not absolutely sure that the L1 page size code (the - // 'if/else if/else if' structs above) really detects the real page - // size for the TLB. Somebody should check it.... - - // Now we read the ext. CPUID level 0x80000006 - __asm - { - mov eax, 0x80000006 - cpuid - mov eaxreg, eax - mov ebxreg, ebx - mov ecxreg, ecx - } - - // We only mask the unified L2 cache masks (never heard of an - // L2 cache that is divided in data and code parts) - if (((ecxreg >> 12) & 0xF) > 0) - { - CPUInfo._L2.bPresent = true; - snprintf(CPUInfo._L2.strSize, sizeof(CPUInfo._L2.strSize), "%d KB", ecxreg >> 16); /* Flawfinder: ignore */ - switch ((ecxreg >> 12) & 0xF) - { - case 1: - CPUInfo._L2.uiAssociativeWays = 1; - break; - case 2: - CPUInfo._L2.uiAssociativeWays = 2; - break; - case 4: - CPUInfo._L2.uiAssociativeWays = 4; - break; - case 6: - CPUInfo._L2.uiAssociativeWays = 8; - break; - case 8: - CPUInfo._L2.uiAssociativeWays = 16; - break; - case 0xF: - CPUInfo._L2.uiAssociativeWays = (unsigned int) -1; - break; - default: - CPUInfo._L2.uiAssociativeWays = 0; - break; - } - CPUInfo._L2.uiLineSize = ecxreg & 0xFF; - } - } - else - { - // If we could not detect the ext. CPUID level 0x80000006 we - // try to read the standard processor configuration. - GetStandardProcessorConfiguration(); - } - // After reading we translate the configuration to strings - TranslateProcessorConfiguration(); - - // And finally exit - return true; -#else - return FALSE; -#endif -} - -// bool CProcessor::AnalyzeUnknownProcessor() -// ========================================== -// Private class function to analyze an unknown (No Intel or AMD) processor -/////////////////////////////////////////////////////////////////////////// -bool CProcessor::AnalyzeUnknownProcessor() -{ -#if LL_WINDOWS - unsigned long eaxreg, ebxreg; - - // We check if the CPUID command is available - if (!CheckCPUIDPresence()) - return false; - - // First of all we read the standard CPUID level 0x00000001 - // This level should be available on every x86-processor clone - __asm - { - mov eax, 1 - cpuid - mov eaxreg, eax - mov ebxreg, ebx - } - // Then we mask the processor model, family, type and stepping - CPUInfo.uiStepping = eaxreg & 0xF; - CPUInfo.uiModel = (eaxreg >> 4) & 0xF; - CPUInfo.uiFamily = (eaxreg >> 8) & 0xF; - CPUInfo.uiType = (eaxreg >> 12) & 0x3; - - // To have complete information we also mask the brand id - CPUInfo.uiBrandID = ebxreg & 0xF; - - // Then we get the standard processor extensions - GetStandardProcessorExtensions(); - - // Now we mark everything we do not know as unknown - strcpy(strCPUName, "Unknown"); /*Flawfinder: ignore*/ - - strcpy(CPUInfo._Data.strTLB, "Unknown"); /*Flawfinder: ignore*/ - strcpy(CPUInfo._Instruction.strTLB, "Unknown"); /*Flawfinder: ignore*/ - - strcpy(CPUInfo._Trace.strCache, "Unknown"); /*Flawfinder: ignore*/ - strcpy(CPUInfo._L1.Data.strCache, "Unknown"); /*Flawfinder: ignore*/ - strcpy(CPUInfo._L1.Instruction.strCache, "Unknown"); /*Flawfinder: ignore*/ - strcpy(CPUInfo._L2.strCache, "Unknown"); /*Flawfinder: ignore*/ - strcpy(CPUInfo._L3.strCache, "Unknown"); /*Flawfinder: ignore*/ - - strcpy(CPUInfo.strProcessorSerial, "Unknown / Not supported"); /*Flawfinder: ignore*/ - - // For the family, model and brand id we can only print the numeric value - snprintf(CPUInfo.strBrandID, sizeof(CPUInfo.strBrandID), "Brand-ID number %d", CPUInfo.uiBrandID); /* Flawfinder: ignore */ - snprintf(CPUInfo.strFamily, sizeof(CPUInfo.strFamily), "Family number %d", CPUInfo.uiFamily); /* Flawfinder: ignore */ - snprintf(CPUInfo.strModel, sizeof(CPUInfo.strModel), "Model number %d", CPUInfo.uiModel); /* Flawfinder: ignore */ - - // And thats it - return true; -#else - return FALSE; -#endif -} - -// bool CProcessor::CheckCPUIDPresence() -// ===================================== -// This function checks if the CPUID command is available on the current -// processor -//////////////////////////////////////////////////////////////////////// -bool CProcessor::CheckCPUIDPresence() -{ -#if LL_WINDOWS - unsigned long BitChanged; - - // We've to check if we can toggle the flag register bit 21 - // If we can't the processor does not support the CPUID command - __asm - { - pushfd - pop eax - mov ebx, eax - xor eax, 0x00200000 - push eax - popfd - pushfd - pop eax - xor eax,ebx - mov BitChanged, eax - } - - return ((BitChanged) ? true : false); -#else - return FALSE; -#endif -} - -// void CProcessor::DecodeProcessorConfiguration(unsigned int cfg) -// =============================================================== -// This function (or switch ?!) just translates a one-byte processor configuration -// byte to understandable values -////////////////////////////////////////////////////////////////////////////////// -void CProcessor::DecodeProcessorConfiguration(unsigned int cfg) -{ - // First we ensure that there's only one single byte - cfg &= 0xFF; - - // Then we do a big switch - switch(cfg) - { - case 0: // cfg = 0: Unused - break; - case 0x1: // cfg = 0x1: code TLB present, 4 KB pages, 4 ways, 32 entries - CPUInfo._Instruction.bPresent = true; - strcpy(CPUInfo._Instruction.strPageSize, "4 KB"); /*Flawfinder: ignore*/ - CPUInfo._Instruction.uiAssociativeWays = 4; - CPUInfo._Instruction.uiEntries = 32; - break; - case 0x2: // cfg = 0x2: code TLB present, 4 MB pages, fully associative, 2 entries - CPUInfo._Instruction.bPresent = true; - strcpy(CPUInfo._Instruction.strPageSize, "4 MB"); /*Flawfinder: ignore*/ - CPUInfo._Instruction.uiAssociativeWays = 4; - CPUInfo._Instruction.uiEntries = 2; - break; - case 0x3: // cfg = 0x3: data TLB present, 4 KB pages, 4 ways, 64 entries - CPUInfo._Data.bPresent = true; - strcpy(CPUInfo._Data.strPageSize, "4 KB"); /*Flawfinder: ignore*/ - CPUInfo._Data.uiAssociativeWays = 4; - CPUInfo._Data.uiEntries = 64; - break; - case 0x4: // cfg = 0x4: data TLB present, 4 MB pages, 4 ways, 8 entries - CPUInfo._Data.bPresent = true; - strcpy(CPUInfo._Data.strPageSize, "4 MB"); /*Flawfinder: ignore*/ - CPUInfo._Data.uiAssociativeWays = 4; - CPUInfo._Data.uiEntries = 8; - break; - case 0x6: // cfg = 0x6: code L1 cache present, 8 KB, 4 ways, 32 byte lines - CPUInfo._L1.Instruction.bPresent = true; - strcpy(CPUInfo._L1.Instruction.strSize, "8 KB"); /*Flawfinder: ignore*/ - CPUInfo._L1.Instruction.uiAssociativeWays = 4; - CPUInfo._L1.Instruction.uiLineSize = 32; - break; - case 0x8: // cfg = 0x8: code L1 cache present, 16 KB, 4 ways, 32 byte lines - CPUInfo._L1.Instruction.bPresent = true; - strcpy(CPUInfo._L1.Instruction.strSize, "16 KB"); /*Flawfinder: ignore*/ - CPUInfo._L1.Instruction.uiAssociativeWays = 4; - CPUInfo._L1.Instruction.uiLineSize = 32; - break; - case 0xA: // cfg = 0xA: data L1 cache present, 8 KB, 2 ways, 32 byte lines - CPUInfo._L1.Data.bPresent = true; - strcpy(CPUInfo._L1.Data.strSize, "8 KB"); /*Flawfinder: ignore*/ - CPUInfo._L1.Data.uiAssociativeWays = 2; - CPUInfo._L1.Data.uiLineSize = 32; - break; - case 0xC: // cfg = 0xC: data L1 cache present, 16 KB, 4 ways, 32 byte lines - CPUInfo._L1.Data.bPresent = true; - strcpy(CPUInfo._L1.Data.strSize, "16 KB"); /*Flawfinder: ignore*/ - CPUInfo._L1.Data.uiAssociativeWays = 4; - CPUInfo._L1.Data.uiLineSize = 32; - break; - case 0x22: // cfg = 0x22: code and data L3 cache present, 512 KB, 4 ways, 64 byte lines, sectored - CPUInfo._L3.bPresent = true; - strcpy(CPUInfo._L3.strSize, "512 KB"); /*Flawfinder: ignore*/ - CPUInfo._L3.uiAssociativeWays = 4; - CPUInfo._L3.uiLineSize = 64; - CPUInfo._L3.bSectored = true; - break; - case 0x23: // cfg = 0x23: code and data L3 cache present, 1024 KB, 8 ways, 64 byte lines, sectored - CPUInfo._L3.bPresent = true; - strcpy(CPUInfo._L3.strSize, "1024 KB"); /*Flawfinder: ignore*/ - CPUInfo._L3.uiAssociativeWays = 8; - CPUInfo._L3.uiLineSize = 64; - CPUInfo._L3.bSectored = true; - break; - case 0x25: // cfg = 0x25: code and data L3 cache present, 2048 KB, 8 ways, 64 byte lines, sectored - CPUInfo._L3.bPresent = true; - strcpy(CPUInfo._L3.strSize, "2048 KB"); /*Flawfinder: ignore*/ - CPUInfo._L3.uiAssociativeWays = 8; - CPUInfo._L3.uiLineSize = 64; - CPUInfo._L3.bSectored = true; - break; - case 0x29: // cfg = 0x29: code and data L3 cache present, 4096 KB, 8 ways, 64 byte lines, sectored - CPUInfo._L3.bPresent = true; - strcpy(CPUInfo._L3.strSize, "4096 KB"); /*Flawfinder: ignore*/ - CPUInfo._L3.uiAssociativeWays = 8; - CPUInfo._L3.uiLineSize = 64; - CPUInfo._L3.bSectored = true; - break; - case 0x40: // cfg = 0x40: no integrated L2 cache (P6 core) or L3 cache (P4 core) - break; - case 0x41: // cfg = 0x41: code and data L2 cache present, 128 KB, 4 ways, 32 byte lines - CPUInfo._L2.bPresent = true; - strcpy(CPUInfo._L2.strSize, "128 KB"); /*Flawfinder: ignore*/ - CPUInfo._L2.uiAssociativeWays = 4; - CPUInfo._L2.uiLineSize = 32; - break; - case 0x42: // cfg = 0x42: code and data L2 cache present, 256 KB, 4 ways, 32 byte lines - CPUInfo._L2.bPresent = true; - strcpy(CPUInfo._L2.strSize, "256 KB"); /*Flawfinder: ignore*/ - CPUInfo._L2.uiAssociativeWays = 4; - CPUInfo._L2.uiLineSize = 32; - break; - case 0x43: // cfg = 0x43: code and data L2 cache present, 512 KB, 4 ways, 32 byte lines - CPUInfo._L2.bPresent = true; - strcpy(CPUInfo._L2.strSize, "512 KB"); /* Flawfinder: ignore */ - CPUInfo._L2.uiAssociativeWays = 4; - CPUInfo._L2.uiLineSize = 32; - break; - case 0x44: // cfg = 0x44: code and data L2 cache present, 1024 KB, 4 ways, 32 byte lines - CPUInfo._L2.bPresent = true; - strcpy(CPUInfo._L2.strSize, "1 MB"); /* Flawfinder: ignore */ - CPUInfo._L2.uiAssociativeWays = 4; - CPUInfo._L2.uiLineSize = 32; - break; - case 0x45: // cfg = 0x45: code and data L2 cache present, 2048 KB, 4 ways, 32 byte lines - CPUInfo._L2.bPresent = true; - strcpy(CPUInfo._L2.strSize, "2 MB"); /* Flawfinder: ignore */ - CPUInfo._L2.uiAssociativeWays = 4; - CPUInfo._L2.uiLineSize = 32; - break; - case 0x50: // cfg = 0x50: code TLB present, 4 KB / 4 MB / 2 MB pages, fully associative, 64 entries - CPUInfo._Instruction.bPresent = true; - strcpy(CPUInfo._Instruction.strPageSize, "4 KB / 2 MB / 4 MB"); /* Flawfinder: ignore */ - CPUInfo._Instruction.uiAssociativeWays = (unsigned int) -1; - CPUInfo._Instruction.uiEntries = 64; - break; - case 0x51: // cfg = 0x51: code TLB present, 4 KB / 4 MB / 2 MB pages, fully associative, 128 entries - CPUInfo._Instruction.bPresent = true; - strcpy(CPUInfo._Instruction.strPageSize, "4 KB / 2 MB / 4 MB"); /* Flawfinder: ignore */ - CPUInfo._Instruction.uiAssociativeWays = (unsigned int) -1; - CPUInfo._Instruction.uiEntries = 128; - break; - case 0x52: // cfg = 0x52: code TLB present, 4 KB / 4 MB / 2 MB pages, fully associative, 256 entries - CPUInfo._Instruction.bPresent = true; - strcpy(CPUInfo._Instruction.strPageSize, "4 KB / 2 MB / 4 MB"); /* Flawfinder: ignore */ - CPUInfo._Instruction.uiAssociativeWays = (unsigned int) -1; - CPUInfo._Instruction.uiEntries = 256; - break; - case 0x5B: // cfg = 0x5B: data TLB present, 4 KB / 4 MB pages, fully associative, 64 entries - CPUInfo._Data.bPresent = true; - strcpy(CPUInfo._Data.strPageSize, "4 KB / 4 MB"); /* Flawfinder: ignore */ - CPUInfo._Data.uiAssociativeWays = (unsigned int) -1; - CPUInfo._Data.uiEntries = 64; - break; - case 0x5C: // cfg = 0x5C: data TLB present, 4 KB / 4 MB pages, fully associative, 128 entries - CPUInfo._Data.bPresent = true; - strcpy(CPUInfo._Data.strPageSize, "4 KB / 4 MB"); /* Flawfinder: ignore */ - CPUInfo._Data.uiAssociativeWays = (unsigned int) -1; - CPUInfo._Data.uiEntries = 128; - break; - case 0x5d: // cfg = 0x5D: data TLB present, 4 KB / 4 MB pages, fully associative, 256 entries - CPUInfo._Data.bPresent = true; - strcpy(CPUInfo._Data.strPageSize, "4 KB / 4 MB"); /* Flawfinder: ignore */ - CPUInfo._Data.uiAssociativeWays = (unsigned int) -1; - CPUInfo._Data.uiEntries = 256; - break; - case 0x66: // cfg = 0x66: data L1 cache present, 8 KB, 4 ways, 64 byte lines, sectored - CPUInfo._L1.Data.bPresent = true; - strcpy(CPUInfo._L1.Data.strSize, "8 KB"); /* Flawfinder: ignore */ - CPUInfo._L1.Data.uiAssociativeWays = 4; - CPUInfo._L1.Data.uiLineSize = 64; - break; - case 0x67: // cfg = 0x67: data L1 cache present, 16 KB, 4 ways, 64 byte lines, sectored - CPUInfo._L1.Data.bPresent = true; - strcpy(CPUInfo._L1.Data.strSize, "16 KB"); /* Flawfinder: ignore */ - CPUInfo._L1.Data.uiAssociativeWays = 4; - CPUInfo._L1.Data.uiLineSize = 64; - break; - case 0x68: // cfg = 0x68: data L1 cache present, 32 KB, 4 ways, 64 byte lines, sectored - CPUInfo._L1.Data.bPresent = true; - strcpy(CPUInfo._L1.Data.strSize, "32 KB"); /* Flawfinder: ignore */ - CPUInfo._L1.Data.uiAssociativeWays = 4; - CPUInfo._L1.Data.uiLineSize = 64; - break; - case 0x70: // cfg = 0x70: trace L1 cache present, 12 KuOPs, 4 ways - CPUInfo._Trace.bPresent = true; - strcpy(CPUInfo._Trace.strSize, "12 K-micro-ops"); /* Flawfinder: ignore */ - CPUInfo._Trace.uiAssociativeWays = 4; - break; - case 0x71: // cfg = 0x71: trace L1 cache present, 16 KuOPs, 4 ways - CPUInfo._Trace.bPresent = true; - strcpy(CPUInfo._Trace.strSize, "16 K-micro-ops"); /* Flawfinder: ignore */ - CPUInfo._Trace.uiAssociativeWays = 4; - break; - case 0x72: // cfg = 0x72: trace L1 cache present, 32 KuOPs, 4 ways - CPUInfo._Trace.bPresent = true; - strcpy(CPUInfo._Trace.strSize, "32 K-micro-ops"); /* Flawfinder: ignore */ - CPUInfo._Trace.uiAssociativeWays = 4; - break; - case 0x79: // cfg = 0x79: code and data L2 cache present, 128 KB, 8 ways, 64 byte lines, sectored - CPUInfo._L2.bPresent = true; - strcpy(CPUInfo._L2.strSize, "128 KB"); /* Flawfinder: ignore */ - CPUInfo._L2.uiAssociativeWays = 8; - CPUInfo._L2.uiLineSize = 64; - CPUInfo._L2.bSectored = true; - break; - case 0x7A: // cfg = 0x7A: code and data L2 cache present, 256 KB, 8 ways, 64 byte lines, sectored - CPUInfo._L2.bPresent = true; - strcpy(CPUInfo._L2.strSize, "256 KB"); /* Flawfinder: ignore */ - CPUInfo._L2.uiAssociativeWays = 8; - CPUInfo._L2.uiLineSize = 64; - CPUInfo._L2.bSectored = true; - break; - case 0x7B: // cfg = 0x7B: code and data L2 cache present, 512 KB, 8 ways, 64 byte lines, sectored - CPUInfo._L2.bPresent = true; - strcpy(CPUInfo._L2.strSize, "512 KB"); /* Flawfinder: ignore */ - CPUInfo._L2.uiAssociativeWays = 8; - CPUInfo._L2.uiLineSize = 64; - CPUInfo._L2.bSectored = true; - break; - case 0x7C: // cfg = 0x7C: code and data L2 cache present, 1024 KB, 8 ways, 64 byte lines, sectored - CPUInfo._L2.bPresent = true; - strcpy(CPUInfo._L2.strSize, "1 MB"); /* Flawfinder: ignore */ - CPUInfo._L2.uiAssociativeWays = 8; - CPUInfo._L2.uiLineSize = 64; - CPUInfo._L2.bSectored = true; - break; - case 0x81: // cfg = 0x81: code and data L2 cache present, 128 KB, 8 ways, 32 byte lines - CPUInfo._L2.bPresent = true; - strcpy(CPUInfo._L2.strSize, "128 KB"); /* Flawfinder: ignore */ - CPUInfo._L2.uiAssociativeWays = 8; - CPUInfo._L2.uiLineSize = 32; - break; - case 0x82: // cfg = 0x82: code and data L2 cache present, 256 KB, 8 ways, 32 byte lines - CPUInfo._L2.bPresent = true; - strcpy(CPUInfo._L2.strSize, "256 KB"); /* Flawfinder: ignore */ - CPUInfo._L2.uiAssociativeWays = 8; - CPUInfo._L2.uiLineSize = 32; - break; - case 0x83: // cfg = 0x83: code and data L2 cache present, 512 KB, 8 ways, 32 byte lines - CPUInfo._L2.bPresent = true; - strcpy(CPUInfo._L2.strSize, "512 KB"); /* Flawfinder: ignore */ - CPUInfo._L2.uiAssociativeWays = 8; - CPUInfo._L2.uiLineSize = 32; - break; - case 0x84: // cfg = 0x84: code and data L2 cache present, 1024 KB, 8 ways, 32 byte lines - CPUInfo._L2.bPresent = true; - strcpy(CPUInfo._L2.strSize, "1 MB"); /* Flawfinder: ignore */ - CPUInfo._L2.uiAssociativeWays = 8; - CPUInfo._L2.uiLineSize = 32; - break; - case 0x85: // cfg = 0x85: code and data L2 cache present, 2048 KB, 8 ways, 32 byte lines - CPUInfo._L2.bPresent = true; - strcpy(CPUInfo._L2.strSize, "2 MB"); /* Flawfinder: ignore */ - CPUInfo._L2.uiAssociativeWays = 8; - CPUInfo._L2.uiLineSize = 32; - break; - } -} - -FORCEINLINE static char *TranslateAssociativeWays(unsigned int uiWays, char *buf) -{ - // We define 0xFFFFFFFF (= -1) as fully associative - if (uiWays == ((unsigned int) -1)) - strcpy(buf, "fully associative"); /* Flawfinder: ignore */ - else - { - if (uiWays == 1) // A one way associative cache is just direct mapped - strcpy(buf, "direct mapped"); /* Flawfinder: ignore */ - else if (uiWays == 0) // This should not happen... - strcpy(buf, "unknown associative ways"); /* Flawfinder: ignore */ - else // The x-way associative cache - sprintf(buf, "%d ways associative", uiWays); /* Flawfinder: ignore */ - } - // To ease the function use we return the buffer - return buf; -} -FORCEINLINE static void TranslateTLB(ProcessorTLB *tlb) -{ - char buf[64]; /* Flawfinder: ignore */ - - // We just check if the TLB is present - if (tlb->bPresent) - snprintf(tlb->strTLB,sizeof(tlb->strTLB), "%s page size, %s, %d entries", tlb->strPageSize, TranslateAssociativeWays(tlb->uiAssociativeWays, buf), tlb->uiEntries); /* Flawfinder: ignore */ - else - strcpy(tlb->strTLB, "Not present"); /* Flawfinder: ignore */ -} -FORCEINLINE static void TranslateCache(ProcessorCache *cache) -{ - char buf[64]; /* Flawfinder: ignore */ - - // We just check if the cache is present - if (cache->bPresent) - { - // If present we construct the string - snprintf(cache->strCache, sizeof(cache->strCache), "%s cache size, %s, %d bytes line size", cache->strSize, TranslateAssociativeWays(cache->uiAssociativeWays, buf), cache->uiLineSize); /* Flawfinder: ignore */ - if (cache->bSectored) - strncat(cache->strCache, ", sectored", sizeof(cache->strCache)-strlen(cache->strCache)-1); /* Flawfinder: ignore */ - } - else - { - // Else we just say "Not present" - strcpy(cache->strCache, "Not present"); /* Flawfinder: ignore */ - } -} - -// void CProcessor::TranslateProcessorConfiguration() -// ================================================== -// Private class function to translate the processor configuration values -// to strings -///////////////////////////////////////////////////////////////////////// -void CProcessor::TranslateProcessorConfiguration() -{ - // We just call the small functions defined above - TranslateTLB(&CPUInfo._Data); - TranslateTLB(&CPUInfo._Instruction); - - TranslateCache(&CPUInfo._Trace); - - TranslateCache(&CPUInfo._L1.Instruction); - TranslateCache(&CPUInfo._L1.Data); - TranslateCache(&CPUInfo._L2); - TranslateCache(&CPUInfo._L3); -} - -// void CProcessor::GetStandardProcessorConfiguration() -// ==================================================== -// Private class function to read the standard processor configuration -////////////////////////////////////////////////////////////////////// -void CProcessor::GetStandardProcessorConfiguration() -{ -#if LL_WINDOWS - unsigned long eaxreg, ebxreg, ecxreg, edxreg; - - // We check if the CPUID function is available - if (!CheckCPUIDPresence()) - return; - - // First we check if the processor supports the standard - // CPUID level 0x00000002 - if (CPUInfo.MaxSupportedLevel >= 2) - { - // Now we go read the std. CPUID level 0x00000002 the first time - unsigned long count, num = 255; - for (count = 0; count < num; count++) - { - __asm - { - mov eax, 2 - cpuid - mov eaxreg, eax - mov ebxreg, ebx - mov ecxreg, ecx - mov edxreg, edx - } - // We have to repeat this reading for 'num' times - num = eaxreg & 0xFF; - - // Then we call the big decode switch function - DecodeProcessorConfiguration(eaxreg >> 8); - DecodeProcessorConfiguration(eaxreg >> 16); - DecodeProcessorConfiguration(eaxreg >> 24); - - // If ebx contains additional data we also decode it - if ((ebxreg & 0x80000000) == 0) - { - DecodeProcessorConfiguration(ebxreg); - DecodeProcessorConfiguration(ebxreg >> 8); - DecodeProcessorConfiguration(ebxreg >> 16); - DecodeProcessorConfiguration(ebxreg >> 24); - } - // And also the ecx register - if ((ecxreg & 0x80000000) == 0) - { - DecodeProcessorConfiguration(ecxreg); - DecodeProcessorConfiguration(ecxreg >> 8); - DecodeProcessorConfiguration(ecxreg >> 16); - DecodeProcessorConfiguration(ecxreg >> 24); - } - // At last the edx processor register - if ((edxreg & 0x80000000) == 0) - { - DecodeProcessorConfiguration(edxreg); - DecodeProcessorConfiguration(edxreg >> 8); - DecodeProcessorConfiguration(edxreg >> 16); - DecodeProcessorConfiguration(edxreg >> 24); + setConfig(eCacheLineSize, cpu_info[2] & 0xff); + setConfig(eL2Associativity, (cpu_info[2] >> 12) & 0xf); + setConfig(eCacheSizeK, (cpu_info[2] >> 16) & 0xffff); } } } -#endif -} +}; -// void CProcessor::GetStandardProcessorExtensions() -// ================================================= -// Private class function to read the standard processor extensions -/////////////////////////////////////////////////////////////////// -void CProcessor::GetStandardProcessorExtensions() -{ -#if LL_WINDOWS - unsigned long ebxreg, edxreg; - - // We check if the CPUID command is available - if (!CheckCPUIDPresence()) - return; - // We just get the standard CPUID level 0x00000001 which should be - // available on every x86 processor - __asm - { - mov eax, 1 - cpuid - mov ebxreg, ebx - mov edxreg, edx - } - - // Then we mask some bits - CPUInfo._Ext.FPU_FloatingPointUnit = CheckBit(edxreg, 0); - CPUInfo._Ext.VME_Virtual8086ModeEnhancements = CheckBit(edxreg, 1); - CPUInfo._Ext.DE_DebuggingExtensions = CheckBit(edxreg, 2); - CPUInfo._Ext.PSE_PageSizeExtensions = CheckBit(edxreg, 3); - CPUInfo._Ext.TSC_TimeStampCounter = CheckBit(edxreg, 4); - CPUInfo._Ext.MSR_ModelSpecificRegisters = CheckBit(edxreg, 5); - CPUInfo._Ext.PAE_PhysicalAddressExtension = CheckBit(edxreg, 6); - CPUInfo._Ext.MCE_MachineCheckException = CheckBit(edxreg, 7); - CPUInfo._Ext.CX8_COMPXCHG8B_Instruction = CheckBit(edxreg, 8); - CPUInfo._Ext.APIC_AdvancedProgrammableInterruptController = CheckBit(edxreg, 9); - CPUInfo._Ext.APIC_ID = (ebxreg >> 24) & 0xFF; - CPUInfo._Ext.SEP_FastSystemCall = CheckBit(edxreg, 11); - CPUInfo._Ext.MTRR_MemoryTypeRangeRegisters = CheckBit(edxreg, 12); - CPUInfo._Ext.PGE_PTE_GlobalFlag = CheckBit(edxreg, 13); - CPUInfo._Ext.MCA_MachineCheckArchitecture = CheckBit(edxreg, 14); - CPUInfo._Ext.CMOV_ConditionalMoveAndCompareInstructions = CheckBit(edxreg, 15); - CPUInfo._Ext.FGPAT_PageAttributeTable = CheckBit(edxreg, 16); - CPUInfo._Ext.PSE36_36bitPageSizeExtension = CheckBit(edxreg, 17); - CPUInfo._Ext.PN_ProcessorSerialNumber = CheckBit(edxreg, 18); - CPUInfo._Ext.CLFSH_CFLUSH_Instruction = CheckBit(edxreg, 19); - CPUInfo._Ext.CLFLUSH_InstructionCacheLineSize = (ebxreg >> 8) & 0xFF; - CPUInfo._Ext.DS_DebugStore = CheckBit(edxreg, 21); - CPUInfo._Ext.ACPI_ThermalMonitorAndClockControl = CheckBit(edxreg, 22); - CPUInfo._Ext.MMX_MultimediaExtensions = CheckBit(edxreg, 23); - CPUInfo._Ext.FXSR_FastStreamingSIMD_ExtensionsSaveRestore = CheckBit(edxreg, 24); - CPUInfo._Ext.SSE_StreamingSIMD_Extensions = CheckBit(edxreg, 25); - CPUInfo._Ext.SSE2_StreamingSIMD2_Extensions = CheckBit(edxreg, 26); - CPUInfo._Ext.Altivec_Extensions = false; - CPUInfo._Ext.SS_SelfSnoop = CheckBit(edxreg, 27); - CPUInfo._Ext.HT_HyperThreading = CheckBit(edxreg, 28); - CPUInfo._Ext.HT_HyterThreadingSiblings = (ebxreg >> 16) & 0xFF; - CPUInfo._Ext.TM_ThermalMonitor = CheckBit(edxreg, 29); - CPUInfo._Ext.IA64_Intel64BitArchitecture = CheckBit(edxreg, 30); -#endif -} - -// const ProcessorInfo *CProcessor::GetCPUInfo() -// ============================================= -// Calls all the other detection function to create an detailed -// processor information -/////////////////////////////////////////////////////////////// -const ProcessorInfo *CProcessor::GetCPUInfo() -{ -#if LL_WINDOWS - unsigned long eaxreg, ebxreg, ecxreg, edxreg; - - // First of all we check if the CPUID command is available - if (!CheckCPUIDPresence()) - return NULL; - - // We read the standard CPUID level 0x00000000 which should - // be available on every x86 processor - __asm - { - mov eax, 0 - cpuid - mov eaxreg, eax - mov ebxreg, ebx - mov edxreg, edx - mov ecxreg, ecx - } - // Then we connect the single register values to the vendor string - *((unsigned long *) CPUInfo.strVendor) = ebxreg; - *((unsigned long *) (CPUInfo.strVendor+4)) = edxreg; - *((unsigned long *) (CPUInfo.strVendor+8)) = ecxreg; - // Null terminate for string comparisons below. - CPUInfo.strVendor[12] = 0; - - // We can also read the max. supported standard CPUID level - CPUInfo.MaxSupportedLevel = eaxreg & 0xFFFF; - - // Then we read the ext. CPUID level 0x80000000 - __asm - { - mov eax, 0x80000000 - cpuid - mov eaxreg, eax - } - // ...to check the max. supportted extended CPUID level - CPUInfo.MaxSupportedExtendedLevel = eaxreg; - - // Then we switch to the specific processor vendors - // See http://www.sandpile.org/ia32/cpuid.htm - if (!strcmp(CPUInfo.strVendor, "GenuineIntel")) - { - AnalyzeIntelProcessor(); - } - else if (!strcmp(CPUInfo.strVendor, "AuthenticAMD")) - { - AnalyzeAMDProcessor(); - } - else if (!strcmp(CPUInfo.strVendor, "UMC UMC UMC")) - { - AnalyzeUnknownProcessor(); - } - else if (!strcmp(CPUInfo.strVendor, "CyrixInstead")) - { - AnalyzeUnknownProcessor(); - } - else if (!strcmp(CPUInfo.strVendor, "NexGenDriven")) - { - AnalyzeUnknownProcessor(); - } - else if (!strcmp(CPUInfo.strVendor, "CentaurHauls")) - { - AnalyzeUnknownProcessor(); - } - else if (!strcmp(CPUInfo.strVendor, "RiseRiseRise")) - { - AnalyzeUnknownProcessor(); - } - else if (!strcmp(CPUInfo.strVendor, "SiS SiS SiS")) - { - AnalyzeUnknownProcessor(); - } - else if (!strcmp(CPUInfo.strVendor, "GenuineTMx86")) - { - // Transmeta - AnalyzeUnknownProcessor(); - } - else if (!strcmp(CPUInfo.strVendor, "Geode by NSC")) - { - AnalyzeUnknownProcessor(); - } - else - { - AnalyzeUnknownProcessor(); - } -#endif - // After all we return the class CPUInfo member var - return (&CPUInfo); -} - -#elif LL_SOLARIS -#include - -#if defined(__i386) -#include -#endif - -// ====================== -// Class constructor: -///////////////////////// -CProcessor::CProcessor() -{ - uqwFrequency = 0; - strCPUName[0] = 0; - memset(&CPUInfo, 0, sizeof(CPUInfo)); -} - -// unsigned __int64 CProcessor::GetCPUFrequency(unsigned int uiMeasureMSecs) -// ========================================================================= -// Function to query the current CPU frequency -//////////////////////////////////////////////////////////////////////////// -F64 CProcessor::GetCPUFrequency(unsigned int /*uiMeasureMSecs*/) -{ - if(uqwFrequency == 0){ - GetCPUInfo(); - } - - return uqwFrequency; -} - -// const ProcessorInfo *CProcessor::GetCPUInfo() -// ============================================= -// Calls all the other detection function to create an detailed -// processor information -/////////////////////////////////////////////////////////////// -const ProcessorInfo *CProcessor::GetCPUInfo() -{ - // In Solaris the CPU info is in the kstats - // try "psrinfo" or "kstat cpu_info" to see all - // that's available - int ncpus=0, i; - kstat_ctl_t *kc; - kstat_t *ks; - kstat_named_t *ksinfo, *ksi; - kstat_t *CPU_stats_list; - - kc = kstat_open(); - - if((int)kc == -1){ - llwarns << "kstat_open(0 failed!" << llendl; - return (&CPUInfo); - } - - for (ks = kc->kc_chain; ks != NULL; ks = ks->ks_next) { - if (strncmp(ks->ks_module, "cpu_info", 8) == 0 && - strncmp(ks->ks_name, "cpu_info", 8) == 0) - ncpus++; - } - - if(ncpus < 1){ - llwarns << "No cpus found in kstats!" << llendl; - return (&CPUInfo); - } - - for (ks = kc->kc_chain; ks; ks = ks->ks_next) { - if (strncmp(ks->ks_module, "cpu_info", 8) == 0 - && strncmp(ks->ks_name, "cpu_info", 8) == 0 - && kstat_read(kc, ks, NULL) != -1){ - CPU_stats_list = ks; // only looking at the first CPU - - break; - } - } - - if(ncpus > 1) - snprintf(strCPUName, sizeof(strCPUName), "%d x ", ncpus); - - kstat_read(kc, CPU_stats_list, NULL); - ksinfo = (kstat_named_t *)CPU_stats_list->ks_data; - for(i=0; i < (int)(CPU_stats_list->ks_ndata); ++i){ // Walk the kstats for this cpu gathering what we need - ksi = ksinfo++; - if(!strcmp(ksi->name, "brand")){ - strncat(strCPUName, (char *)KSTAT_NAMED_STR_PTR(ksi), - sizeof(strCPUName)-strlen(strCPUName)-1); - strncat(CPUInfo.strFamily, (char *)KSTAT_NAMED_STR_PTR(ksi), - sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1); - strncpy(CPUInfo.strBrandID, strCPUName,sizeof(CPUInfo.strBrandID)-1); - CPUInfo.strBrandID[sizeof(CPUInfo.strBrandID)-1]='\0'; - // DEBUG llinfos << "CPU brand: " << strCPUName << llendl; - continue; - } - - if(!strcmp(ksi->name, "clock_MHz")){ -#if defined(__sparc) - llinfos << "Raw kstat clock rate is: " << ksi->value.l << llendl; - uqwFrequency = (F64)(ksi->value.l * 1000000); -#else - uqwFrequency = (F64)(ksi->value.i64 * 1000000); -#endif - //DEBUG llinfos << "CPU frequency: " << uqwFrequency << llendl; - continue; - } - -#if defined(__i386) - if(!strcmp(ksi->name, "vendor_id")){ - strncpy(CPUInfo.strVendor, (char *)KSTAT_NAMED_STR_PTR(ksi), sizeof(CPUInfo.strVendor)-1); - // DEBUG llinfos << "CPU vendor: " << CPUInfo.strVendor << llendl; - continue; - } -#endif - } - - kstat_close(kc); - -#if defined(__sparc) // SPARC does not define a vendor string in kstat - strncpy(CPUInfo.strVendor, "Sun Microsystems, Inc.", sizeof(CPUInfo.strVendor)-1); -#endif - - // DEBUG llinfo << "The system has " << ncpus << " CPUs with a clock rate of " << uqwFrequency << "MHz." << llendl; - -#if defined (__i386) // we really don't care about the CPU extensions on SPARC but on x86... - - // Now get cpu extensions - - uint_t ui; - - (void) getisax(&ui, 1); - - if(ui & AV_386_FPU) - CPUInfo._Ext.FPU_FloatingPointUnit = true; - if(ui & AV_386_CX8) - CPUInfo._Ext.CX8_COMPXCHG8B_Instruction = true; - if(ui & AV_386_MMX) - CPUInfo._Ext.MMX_MultimediaExtensions = true; - if(ui & AV_386_AMD_MMX) - CPUInfo._Ext.MMX_MultimediaExtensions = true; - if(ui & AV_386_FXSR) - CPUInfo._Ext.FXSR_FastStreamingSIMD_ExtensionsSaveRestore = true; - if(ui & AV_386_SSE) - CPUInfo._Ext.SSE_StreamingSIMD_Extensions = true; - if(ui & AV_386_SSE2) - CPUInfo._Ext.SSE2_StreamingSIMD2_Extensions = true; -/* Left these here since they may get used later - if(ui & AV_386_SSE3) - CPUInfo._Ext.... = true; - if(ui & AV_386_AMD_3DNow) - CPUInfo._Ext.... = true; - if(ui & AV_386_AMD_3DNowx) - CPUInfo._Ext.... = true; -*/ -#endif - return (&CPUInfo); -} - -#else -// LL_DARWIN +#elif LL_DARWIN #include #include -static char *TranslateAssociativeWays(unsigned int uiWays, char *buf) +class LLProcessorInfoDarwinImpl : public LLProcessorInfoImpl { - // We define 0xFFFFFFFF (= -1) as fully associative - if (uiWays == ((unsigned int) -1)) - strcpy(buf, "fully associative"); /* Flawfinder: ignore */ - else +public: + LLProcessorInfoDarwinImpl() { - if (uiWays == 1) // A one way associative cache is just direct mapped - strcpy(buf, "direct mapped"); /* Flawfinder: ignore */ - else if (uiWays == 0) // This should not happen... - strcpy(buf, "unknown associative ways"); /* Flawfinder: ignore */ - else // The x-way associative cache - sprintf(buf, "%d ways associative", uiWays); /* Flawfinder: ignore */ + getCPUIDInfo(); + uint64_t frequency = getSysctlInt64("hw.cpufrequency"); + setInfo(eFrequency, (F64)frequency / (F64)1000000); } - // To ease the function use we return the buffer - return buf; -} -static void TranslateTLB(ProcessorTLB *tlb) -{ - char buf[64]; /* Flawfinder: ignore */ - // We just check if the TLB is present - if (tlb->bPresent) - snprintf(tlb->strTLB, sizeof(tlb->strTLB), "%s page size, %s, %d entries", tlb->strPageSize, TranslateAssociativeWays(tlb->uiAssociativeWays, buf), tlb->uiEntries); /* Flawfinder: ignore */ - else - strcpy(tlb->strTLB, "Not present"); /* Flawfinder: ignore */ -} -static void TranslateCache(ProcessorCache *cache) -{ - char buf[64]; /* Flawfinder: ignore */ + virtual ~LLProcessorInfoDarwinImpl() {} - // We just check if the cache is present - if (cache->bPresent) +private: + int getSysctlInt(const char* name) + { + int result = 0; + size_t len = sizeof(int); + int error = sysctlbyname(name, (void*)&result, &len, NULL, 0); + return error == -1 ? 0 : result; + } + + uint64_t getSysctlInt64(const char* name) + { + uint64_t value = 0; + size_t size = sizeof(value); + int result = sysctlbyname(name, (void*)&value, &size, NULL, 0); + if ( result == 0 ) + { + if ( size == sizeof( uint64_t ) ) + ; + else if ( size == sizeof( uint32_t ) ) + value = (uint64_t)(( uint32_t *)&value); + else if ( size == sizeof( uint16_t ) ) + value = (uint64_t)(( uint16_t *)&value); + else if ( size == sizeof( uint8_t ) ) + value = (uint64_t)(( uint8_t *)&value); + else + { + LL_WARNS("Unknown type returned from sysctl!") << LL_ENDL; + } + } + + return result == -1 ? 0 : value; + } + + void getCPUIDInfo() { - // If present we construct the string - snprintf(cache->strCache,sizeof(cache->strCache), "%s cache size, %s, %d bytes line size", cache->strSize, TranslateAssociativeWays(cache->uiAssociativeWays, buf), cache->uiLineSize); /* Flawfinder: ignore */ - if (cache->bSectored) - strncat(cache->strCache, ", sectored", sizeof(cache->strCache)-strlen(cache->strCache)-1); /* Flawfinder: ignore */ + size_t len = 0; + + char cpu_brand_string[0x40]; + len = sizeof(cpu_brand_string); + memset(cpu_brand_string, 0, len); + sysctlbyname("machdep.cpu.brand_string", (void*)cpu_brand_string, &len, NULL, 0); + cpu_brand_string[0x3f] = 0; + setInfo(eBrandName, cpu_brand_string); + + char cpu_vendor[0x20]; + len = sizeof(cpu_vendor); + memset(cpu_vendor, 0, len); + sysctlbyname("machdep.cpu.vendor", (void*)cpu_vendor, &len, NULL, 0); + cpu_vendor[0x1f] = 0; + setInfo(eVendor, cpu_vendor); + + setInfo(eStepping, getSysctlInt("machdep.cpu.stepping")); + setInfo(eModel, getSysctlInt("machdep.cpu.model")); + int family = getSysctlInt("machdep.cpu.family"); + int ext_family = getSysctlInt("machdep.cpu.extfamily"); + setInfo(eFamily, family); + setInfo(eExtendedFamily, ext_family); + setInfo(eFamilyName, compute_CPUFamilyName(cpu_vendor, family, ext_family)); + setInfo(eExtendedModel, getSysctlInt("machdep.cpu.extmodel")); + setInfo(eBrandID, getSysctlInt("machdep.cpu.brand")); + setInfo(eType, 0); // ? where to find this? + + //setConfig(eCLFLUSHCacheLineSize, ((cpu_info[1] >> 8) & 0xff) * 8); + //setConfig(eAPICPhysicalID, (cpu_info[1] >> 24) & 0xff); + setConfig(eCacheLineSize, getSysctlInt("machdep.cpu.cache.linesize")); + setConfig(eL2Associativity, getSysctlInt("machdep.cpu.cache.L2_associativity")); + setConfig(eCacheSizeK, getSysctlInt("machdep.cpu.cache.size")); + + uint64_t feature_info = getSysctlInt64("machdep.cpu.feature_bits"); + S32 *feature_infos = (S32*)(&feature_info); + + setConfig(eFeatureBits, feature_infos[0]); + + for(unsigned int index = 0, bit = 1; index < eSSE3_Features; ++index, bit <<= 1) + { + if(feature_info & bit) + { + setExtension(cpu_feature_names[index]); + } + } + + // *NOTE:Mani - I didn't find any docs that assure me that machdep.cpu.feature_bits will always be + // The feature bits I think it is. Here's a test: +#ifndef LL_RELEASE_FOR_DOWNLOAD + #if defined(__i386__) && defined(__PIC__) + /* %ebx may be the PIC register. */ + #define __cpuid(level, a, b, c, d) \ + __asm__ ("xchgl\t%%ebx, %1\n\t" \ + "cpuid\n\t" \ + "xchgl\t%%ebx, %1\n\t" \ + : "=a" (a), "=r" (b), "=c" (c), "=d" (d) \ + : "0" (level)) + #else + #define __cpuid(level, a, b, c, d) \ + __asm__ ("cpuid\n\t" \ + : "=a" (a), "=b" (b), "=c" (c), "=d" (d) \ + : "0" (level)) + #endif + + unsigned int eax, ebx, ecx, edx; + __cpuid(0x1, eax, ebx, ecx, edx); + if(feature_infos[0] != (S32)edx) + { + llerrs << "machdep.cpu.feature_bits doesn't match expected cpuid result!" << llendl; + } +#endif // LL_RELEASE_FOR_DOWNLOAD + + + uint64_t ext_feature_info = getSysctlInt64("machdep.cpu.extfeature_bits"); + S32 *ext_feature_infos = (S32*)(&ext_feature_info); + setConfig(eExtFeatureBits, ext_feature_infos[0]); } - else +}; + +#elif LL_LINUX +const char CPUINFO_FILE[] = "/proc/cpuinfo"; + +class LLProcessorInfoLinuxImpl : public LLProcessorInfoImpl +{ +public: + LLProcessorInfoLinuxImpl() { - // Else we just say "Not present" - strcpy(cache->strCache, "Not present"); /* Flawfinder: ignore */ + get_proc_cpuinfo(); + } + + virtual ~LLProcessorInfoLinuxImpl() {} +private: + + void get_proc_cpuinfo() + { + std::map< std::string, std::string > cpuinfo; + LLFILE* cpuinfo_fp = LLFile::fopen(CPUINFO_FILE, "rb"); + if(cpuinfo_fp) + { + char line[MAX_STRING]; + memset(line, 0, MAX_STRING); + while(fgets(line, MAX_STRING, cpuinfo_fp)) + { + // /proc/cpuinfo on Linux looks like: + // name\t*: value\n + char* tabspot = strchr( line, '\t' ); + if (tabspot == NULL) + continue; + char* colspot = strchr( tabspot, ':' ); + if (colspot == NULL) + continue; + char* spacespot = strchr( colspot, ' ' ); + if (spacespot == NULL) + continue; + char* nlspot = strchr( line, '\n' ); + if (nlspot == NULL) + nlspot = line + strlen( line ); // Fallback to terminating NUL + std::string linename( line, tabspot ); + std::string llinename(linename); + LLStringUtil::toLower(llinename); + std::string lineval( spacespot + 1, nlspot ); + 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 mhz; + if (LLStringUtil::convertToF64(cpuinfo["cpu mhz"], mhz) + && 200.0 < mhz && mhz < 10000.0) + { + setInfo(eFrequency,(F64)(mhz)); + } + + LLPI_SET_INFO_STRING(eBrandName, "model name"); + LLPI_SET_INFO_STRING(eVendor, "vendor_id"); + + LLPI_SET_INFO_INT(eStepping, "stepping"); + LLPI_SET_INFO_INT(eModel, "model"); + + + S32 family; + if (!cpuinfo["cpu family"].empty() + && LLStringUtil::convertToS32(cpuinfo["cpu family"], family)) + { + setInfo(eFamily, family); + } + + setInfo(eFamilyName, compute_CPUFamilyName(cpuinfo["vendor_id"].c_str(), family)); + + // setInfo(eExtendedModel, getSysctlInt("machdep.cpu.extmodel")); + // setInfo(eBrandID, getSysctlInt("machdep.cpu.brand")); + // setInfo(eType, 0); // ? where to find this? + + //setConfig(eCLFLUSHCacheLineSize, ((cpu_info[1] >> 8) & 0xff) * 8); + //setConfig(eAPICPhysicalID, (cpu_info[1] >> 24) & 0xff); + //setConfig(eCacheLineSize, getSysctlInt("machdep.cpu.cache.linesize")); + //setConfig(eL2Associativity, getSysctlInt("machdep.cpu.cache.L2_associativity")); + //setConfig(eCacheSizeK, getSysctlInt("machdep.cpu.cache.size")); + + // Read extensions + std::string flags = " " + cpuinfo["flags"] + " "; + LLStringUtil::toLower(flags); + + if( flags.find( " sse " ) != std::string::npos ) + { + setExtension(cpu_feature_names[eSSE_Ext]); + } + + if( flags.find( " sse2 " ) != std::string::npos ) + { + setExtension(cpu_feature_names[eSSE2_Ext]); + } + +# endif // LL_X86 + } + + std::string getCPUFeatureDescription() const + { + std::ostringstream s; + + // *NOTE:Mani - This is for linux only. + LLFILE* cpuinfo = LLFile::fopen(CPUINFO_FILE, "rb"); + if(cpuinfo) + { + char line[MAX_STRING]; + memset(line, 0, MAX_STRING); + while(fgets(line, MAX_STRING, cpuinfo)) + { + line[strlen(line)-1] = ' '; + s << line; + s << std::endl; + } + fclose(cpuinfo); + s << std::endl; + } + else + { + s << "Unable to collect processor information" << std::endl; + } + return s.str(); + } + +}; + + +#endif // LL_MSVC elif LL_DARWIN elif LL_LINUX + +////////////////////////////////////////////////////// +// Interface definition +LLProcessorInfo::LLProcessorInfo() : mImpl(NULL) +{ + // *NOTE:Mani - not thread safe. + if(!mImpl) + { +#ifdef LL_MSVC + static LLProcessorInfoWindowsImpl the_impl; + mImpl = &the_impl; +#elif LL_DARWIN + static LLProcessorInfoDarwinImpl the_impl; + mImpl = &the_impl; +#else + static LLProcessorInfoLinuxImpl the_impl; + mImpl = &the_impl; +#endif // LL_MSVC } } -// void CProcessor::TranslateProcessorConfiguration() -// ================================================== -// Private class function to translate the processor configuration values -// to strings -///////////////////////////////////////////////////////////////////////// -void CProcessor::TranslateProcessorConfiguration() -{ - // We just call the small functions defined above - TranslateTLB(&CPUInfo._Data); - TranslateTLB(&CPUInfo._Instruction); - TranslateCache(&CPUInfo._Trace); +LLProcessorInfo::~LLProcessorInfo() {} +F64 LLProcessorInfo::getCPUFrequency() const { return mImpl->getCPUFrequency(); } +bool LLProcessorInfo::hasSSE() const { return mImpl->hasSSE(); } +bool LLProcessorInfo::hasSSE2() const { return mImpl->hasSSE2(); } +bool LLProcessorInfo::hasAltivec() const { return mImpl->hasAltivec(); } +std::string LLProcessorInfo::getCPUFamilyName() const { return mImpl->getCPUFamilyName(); } +std::string LLProcessorInfo::getCPUBrandName() const { return mImpl->getCPUBrandName(); } +std::string LLProcessorInfo::getCPUFeatureDescription() const { return mImpl->getCPUFeatureDescription(); } - TranslateCache(&CPUInfo._L1.Instruction); - TranslateCache(&CPUInfo._L1.Data); - TranslateCache(&CPUInfo._L2); - TranslateCache(&CPUInfo._L3); -} - -// CProcessor::CProcessor -// ====================== -// Class constructor: -///////////////////////// -CProcessor::CProcessor() -{ - uqwFrequency = 0; - strCPUName[0] = 0; - memset(&CPUInfo, 0, sizeof(CPUInfo)); -} - -// unsigned __int64 CProcessor::GetCPUFrequency(unsigned int uiMeasureMSecs) -// ========================================================================= -// Function to query the current CPU frequency -//////////////////////////////////////////////////////////////////////////// -F64 CProcessor::GetCPUFrequency(unsigned int /*uiMeasureMSecs*/) -{ - U64 frequency = 0; - size_t len = sizeof(frequency); - - if(sysctlbyname("hw.cpufrequency", &frequency, &len, NULL, 0) == 0) - { - uqwFrequency = (F64)frequency; - } - - return uqwFrequency; -} - -static bool hasFeature(const char *name) -{ - bool result = false; - int val = 0; - size_t len = sizeof(val); - - if(sysctlbyname(name, &val, &len, NULL, 0) == 0) - { - if(val != 0) - result = true; - } - - return result; -} - -// const ProcessorInfo *CProcessor::GetCPUInfo() -// ============================================= -// Calls all the other detection function to create an detailed -// processor information -/////////////////////////////////////////////////////////////// -const ProcessorInfo *CProcessor::GetCPUInfo() -{ - int pagesize = 0; - int cachelinesize = 0; - int l1icachesize = 0; - int l1dcachesize = 0; - int l2settings = 0; - int l2cachesize = 0; - int l3settings = 0; - int l3cachesize = 0; - int ncpu = 0; - int cpusubtype = 0; - - // sysctl knows all. - int mib[2]; - size_t len; - mib[0] = CTL_HW; - - mib[1] = HW_PAGESIZE; - len = sizeof(pagesize); - sysctl(mib, 2, &pagesize, &len, NULL, 0); - - mib[1] = HW_CACHELINE; - len = sizeof(cachelinesize); - sysctl(mib, 2, &cachelinesize, &len, NULL, 0); - - mib[1] = HW_L1ICACHESIZE; - len = sizeof(l1icachesize); - sysctl(mib, 2, &l1icachesize, &len, NULL, 0); - - mib[1] = HW_L1DCACHESIZE; - len = sizeof(l1dcachesize); - sysctl(mib, 2, &l1dcachesize, &len, NULL, 0); - - mib[1] = HW_L2SETTINGS; - len = sizeof(l2settings); - sysctl(mib, 2, &l2settings, &len, NULL, 0); - - mib[1] = HW_L2CACHESIZE; - len = sizeof(l2cachesize); - sysctl(mib, 2, &l2cachesize, &len, NULL, 0); - - mib[1] = HW_L3SETTINGS; - len = sizeof(l3settings); - sysctl(mib, 2, &l3settings, &len, NULL, 0); - - mib[1] = HW_L3CACHESIZE; - len = sizeof(l3cachesize); - sysctl(mib, 2, &l3cachesize, &len, NULL, 0); - - mib[1] = HW_NCPU; - len = sizeof(ncpu); - sysctl(mib, 2, &ncpu, &len, NULL, 0); - - sysctlbyname("hw.cpusubtype", &cpusubtype, &len, NULL, 0); - - strCPUName[0] = 0; - - if((ncpu == 0) || (ncpu == 1)) - { - // Uhhh... - } - else if(ncpu == 2) - { - strncat(strCPUName, "Dual ", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */ - } - else - { - snprintf(strCPUName, sizeof(strCPUName), "%d x ", ncpu); /* Flawfinder: ignore */ - } - -#if __ppc__ - switch(cpusubtype) - { - case CPU_SUBTYPE_POWERPC_601:// ((cpu_subtype_t) 1) - strncat(strCPUName, "PowerPC 601", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */ - strncat(CPUInfo.strFamily, "PowerPC", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1); /* Flawfinder: ignore */ - - break; - case CPU_SUBTYPE_POWERPC_602:// ((cpu_subtype_t) 2) - strncat(strCPUName, "PowerPC 602", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */ - strncat(CPUInfo.strFamily, "PowerPC", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1); /* Flawfinder: ignore */ - break; - case CPU_SUBTYPE_POWERPC_603:// ((cpu_subtype_t) 3) - strncat(strCPUName, "PowerPC 603", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */ - strncat(CPUInfo.strFamily, "PowerPC", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1); /* Flawfinder: ignore */ - break; - case CPU_SUBTYPE_POWERPC_603e:// ((cpu_subtype_t) 4) - strncat(strCPUName, "PowerPC 603e", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */ - strncat(CPUInfo.strFamily, "PowerPC", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1); /* Flawfinder: ignore */ - break; - case CPU_SUBTYPE_POWERPC_603ev:// ((cpu_subtype_t) 5) - strncat(strCPUName, "PowerPC 603ev", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */ - strncat(CPUInfo.strFamily, "PowerPC", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1); /* Flawfinder: ignore */ - break; - case CPU_SUBTYPE_POWERPC_604:// ((cpu_subtype_t) 6) - strncat(strCPUName, "PowerPC 604", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */ - strncat(CPUInfo.strFamily, "PowerPC", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1); /* Flawfinder: ignore */ - break; - case CPU_SUBTYPE_POWERPC_604e:// ((cpu_subtype_t) 7) - strncat(strCPUName, "PowerPC 604e", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */ - strncat(CPUInfo.strFamily, "PowerPC", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1); /* Flawfinder: ignore */ - break; - case CPU_SUBTYPE_POWERPC_620:// ((cpu_subtype_t) 8) - strncat(strCPUName, "PowerPC 620", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */ - strncat(CPUInfo.strFamily, "PowerPC", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1); /* Flawfinder: ignore */ - break; - case CPU_SUBTYPE_POWERPC_750:// ((cpu_subtype_t) 9) - strncat(strCPUName, "PowerPC 750", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */ - strncat(CPUInfo.strFamily, "PowerPC G3", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1); /* Flawfinder: ignore */ - break; - case CPU_SUBTYPE_POWERPC_7400:// ((cpu_subtype_t) 10) - strncat(strCPUName, "PowerPC 7400", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */ - strncat(CPUInfo.strFamily, "PowerPC G4", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1); /* Flawfinder: ignore */ - break; - case CPU_SUBTYPE_POWERPC_7450:// ((cpu_subtype_t) 11) - strncat(strCPUName, "PowerPC 7450", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */ - strncat(CPUInfo.strFamily, "PowerPC G4", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1); /* Flawfinder: ignore */ - break; - case CPU_SUBTYPE_POWERPC_970:// ((cpu_subtype_t) 100) - strncat(strCPUName, "PowerPC 970", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */ - strncat(CPUInfo.strFamily, "PowerPC G5", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1); /* Flawfinder: ignore */ - break; - - default: - strncat(strCPUName, "PowerPC (Unknown)", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */ - break; - } - - CPUInfo._Ext.EMMX_MultimediaExtensions = - CPUInfo._Ext.MMX_MultimediaExtensions = - CPUInfo._Ext.SSE_StreamingSIMD_Extensions = - CPUInfo._Ext.SSE2_StreamingSIMD2_Extensions = false; - - CPUInfo._Ext.Altivec_Extensions = hasFeature("hw.optional.altivec"); - -#endif - -#if __i386__ - // MBW -- XXX -- TODO -- make this call AnalyzeIntelProcessor()? - switch(cpusubtype) - { - default: - strncat(strCPUName, "i386 (Unknown)", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */ - break; - } - - CPUInfo._Ext.EMMX_MultimediaExtensions = hasFeature("hw.optional.mmx"); // MBW -- XXX -- this may be wrong... - CPUInfo._Ext.MMX_MultimediaExtensions = hasFeature("hw.optional.mmx"); - CPUInfo._Ext.SSE_StreamingSIMD_Extensions = hasFeature("hw.optional.sse"); - CPUInfo._Ext.SSE2_StreamingSIMD2_Extensions = hasFeature("hw.optional.sse2"); - CPUInfo._Ext.Altivec_Extensions = false; - CPUInfo._Ext.AA64_AMD64BitArchitecture = hasFeature("hw.optional.x86_64"); - -#endif - - // Terse CPU info uses this string... - strncpy(CPUInfo.strBrandID, strCPUName,sizeof(CPUInfo.strBrandID)-1); /* Flawfinder: ignore */ - CPUInfo.strBrandID[sizeof(CPUInfo.strBrandID)-1]='\0'; - - // Fun cache config stuff... - - if(l1dcachesize != 0) - { - CPUInfo._L1.Data.bPresent = true; - snprintf(CPUInfo._L1.Data.strSize, sizeof(CPUInfo._L1.Data.strSize), "%d KB", l1dcachesize / 1024); /* Flawfinder: ignore */ -// CPUInfo._L1.Data.uiAssociativeWays = ???; - CPUInfo._L1.Data.uiLineSize = cachelinesize; - } - - if(l1icachesize != 0) - { - CPUInfo._L1.Instruction.bPresent = true; - snprintf(CPUInfo._L1.Instruction.strSize, sizeof(CPUInfo._L1.Instruction.strSize), "%d KB", l1icachesize / 1024); /* Flawfinder: ignore */ -// CPUInfo._L1.Instruction.uiAssociativeWays = ???; - CPUInfo._L1.Instruction.uiLineSize = cachelinesize; - } - - if(l2cachesize != 0) - { - CPUInfo._L2.bPresent = true; - snprintf(CPUInfo._L2.strSize, sizeof(CPUInfo._L2.strSize), "%d KB", l2cachesize / 1024); /* Flawfinder: ignore */ -// CPUInfo._L2.uiAssociativeWays = ???; - CPUInfo._L2.uiLineSize = cachelinesize; - } - - if(l3cachesize != 0) - { - CPUInfo._L2.bPresent = true; - snprintf(CPUInfo._L2.strSize, sizeof(CPUInfo._L2.strSize), "%d KB", l3cachesize / 1024); /* Flawfinder: ignore */ -// CPUInfo._L2.uiAssociativeWays = ???; - CPUInfo._L2.uiLineSize = cachelinesize; - } - - CPUInfo._Ext.FPU_FloatingPointUnit = hasFeature("hw.optional.floatingpoint"); - -// printf("pagesize = 0x%x\n", pagesize); -// printf("cachelinesize = 0x%x\n", cachelinesize); -// printf("l1icachesize = 0x%x\n", l1icachesize); -// printf("l1dcachesize = 0x%x\n", l1dcachesize); -// printf("l2settings = 0x%x\n", l2settings); -// printf("l2cachesize = 0x%x\n", l2cachesize); -// printf("l3settings = 0x%x\n", l3settings); -// printf("l3cachesize = 0x%x\n", l3cachesize); - - // After reading we translate the configuration to strings - TranslateProcessorConfiguration(); - - // After all we return the class CPUInfo member var - return (&CPUInfo); -} - -#endif // LL_DARWIN - -// bool CProcessor::CPUInfoToText(char *strBuffer, unsigned int uiMaxLen) -// ====================================================================== -// Gets the frequency and processor information and writes it to a string -///////////////////////////////////////////////////////////////////////// -bool CProcessor::CPUInfoToText(char *strBuffer, unsigned int uiMaxLen) -{ -#define LENCHECK len = (unsigned int) strlen(buf); if (len >= uiMaxLen) return false; strcpy(strBuffer, buf); strBuffer += len; /*Flawfinder: ignore*/ -#define COPYADD(str) strcpy(buf, str); LENCHECK; /* Flawfinder: ignore */ -#define FORMATADD(format, var) sprintf(buf, format, var); LENCHECK; /* Flawfinder: ignore */ -#define BOOLADD(str, boolvar) COPYADD(str); if (boolvar) { COPYADD(" Yes\n"); } else { COPYADD(" No\n"); } - - char buf[1024]; /* Flawfinder: ignore */ - unsigned int len; - - // First we have to get the frequency - GetCPUFrequency(50); - - // Then we get the processor information - GetCPUInfo(); - - // Now we construct the string (see the macros at function beginning) - strBuffer[0] = 0; - - COPYADD("// CPU General Information\n//////////////////////////\n"); - FORMATADD("Processor name: %s\n", strCPUName); - FORMATADD("Frequency: %.2f MHz\n\n", (float) uqwFrequency / 1000000.0f); - FORMATADD("Vendor: %s\n", CPUInfo.strVendor); - FORMATADD("Family: %s\n", CPUInfo.strFamily); - FORMATADD("Extended family: %d\n", CPUInfo.uiExtendedFamily); - FORMATADD("Model: %s\n", CPUInfo.strModel); - FORMATADD("Extended model: %d\n", CPUInfo.uiExtendedModel); - FORMATADD("Type: %s\n", CPUInfo.strType); - FORMATADD("Brand ID: %s\n", CPUInfo.strBrandID); - if (CPUInfo._Ext.PN_ProcessorSerialNumber) - { - FORMATADD("Processor Serial: %s\n", CPUInfo.strProcessorSerial); - } - else - { - COPYADD("Processor Serial: Disabled\n"); - } -#if !LL_SOLARIS // NOTE: Why bother printing all this when it's irrelavent - - COPYADD("\n\n// CPU Configuration\n////////////////////\n"); - FORMATADD("L1 instruction cache: %s\n", CPUInfo._L1.Instruction.strCache); - FORMATADD("L1 data cache: %s\n", CPUInfo._L1.Data.strCache); - FORMATADD("L2 cache: %s\n", CPUInfo._L2.strCache); - FORMATADD("L3 cache: %s\n", CPUInfo._L3.strCache); - FORMATADD("Trace cache: %s\n", CPUInfo._Trace.strCache); - FORMATADD("Instruction TLB: %s\n", CPUInfo._Instruction.strTLB); - FORMATADD("Data TLB: %s\n", CPUInfo._Data.strTLB); - FORMATADD("Max Supported CPUID-Level: 0x%08lX\n", CPUInfo.MaxSupportedLevel); - FORMATADD("Max Supported Ext. CPUID-Level: 0x%08lX\n", CPUInfo.MaxSupportedExtendedLevel); - - COPYADD("\n\n// CPU Extensions\n/////////////////\n"); - BOOLADD("AA64 AMD 64-bit Architecture: ", CPUInfo._Ext.AA64_AMD64BitArchitecture); - BOOLADD("ACPI Thermal Monitor And Clock Control: ", CPUInfo._Ext.ACPI_ThermalMonitorAndClockControl); - BOOLADD("APIC Advanced Programmable Interrupt Controller: ", CPUInfo._Ext.APIC_AdvancedProgrammableInterruptController); - FORMATADD(" APIC-ID: %d\n", CPUInfo._Ext.APIC_ID); - BOOLADD("CLFSH CLFLUSH Instruction Presence: ", CPUInfo._Ext.CLFSH_CFLUSH_Instruction); - FORMATADD(" CLFLUSH Instruction Cache Line Size: %d\n", CPUInfo._Ext.CLFLUSH_InstructionCacheLineSize); - BOOLADD("CMOV Conditional Move And Compare Instructions: ", CPUInfo._Ext.CMOV_ConditionalMoveAndCompareInstructions); - BOOLADD("CX8 COMPXCHG8B Instruction: ", CPUInfo._Ext.CX8_COMPXCHG8B_Instruction); - BOOLADD("DE Debugging Extensions: ", CPUInfo._Ext.DE_DebuggingExtensions); - BOOLADD("DS Debug Store: ", CPUInfo._Ext.DS_DebugStore); - BOOLADD("FGPAT Page Attribute Table: ", CPUInfo._Ext.FGPAT_PageAttributeTable); - BOOLADD("FPU Floating Point Unit: ", CPUInfo._Ext.FPU_FloatingPointUnit); - BOOLADD("FXSR Fast Streaming SIMD Extensions Save/Restore:", CPUInfo._Ext.FXSR_FastStreamingSIMD_ExtensionsSaveRestore); - BOOLADD("HT Hyper Threading: ", CPUInfo._Ext.HT_HyperThreading); - BOOLADD("IA64 Intel 64-Bit Architecture: ", CPUInfo._Ext.IA64_Intel64BitArchitecture); - BOOLADD("MCA Machine Check Architecture: ", CPUInfo._Ext.MCA_MachineCheckArchitecture); - BOOLADD("MCE Machine Check Exception: ", CPUInfo._Ext.MCE_MachineCheckException); - BOOLADD("MMX Multimedia Extensions: ", CPUInfo._Ext.MMX_MultimediaExtensions); - BOOLADD("MMX+ Multimedia Extensions: ", CPUInfo._Ext.EMMX_MultimediaExtensions); - BOOLADD("MSR Model Specific Registers: ", CPUInfo._Ext.MSR_ModelSpecificRegisters); - BOOLADD("MTRR Memory Type Range Registers: ", CPUInfo._Ext.MTRR_MemoryTypeRangeRegisters); - BOOLADD("PAE Physical Address Extension: ", CPUInfo._Ext.PAE_PhysicalAddressExtension); - BOOLADD("PGE PTE Global Flag: ", CPUInfo._Ext.PGE_PTE_GlobalFlag); - if (CPUInfo._Ext.PN_ProcessorSerialNumber) - { - FORMATADD("PN Processor Serial Number: %s\n", CPUInfo.strProcessorSerial); - } - else - { - COPYADD("PN Processor Serial Number: Disabled\n"); - } - BOOLADD("PSE Page Size Extensions: ", CPUInfo._Ext.PSE_PageSizeExtensions); - BOOLADD("PSE36 36-bit Page Size Extension: ", CPUInfo._Ext.PSE36_36bitPageSizeExtension); - BOOLADD("SEP Fast System Call: ", CPUInfo._Ext.SEP_FastSystemCall); - BOOLADD("SS Self Snoop: ", CPUInfo._Ext.SS_SelfSnoop); - BOOLADD("SSE Streaming SIMD Extensions: ", CPUInfo._Ext.SSE_StreamingSIMD_Extensions); - BOOLADD("SSE2 Streaming SIMD 2 Extensions: ", CPUInfo._Ext.SSE2_StreamingSIMD2_Extensions); - BOOLADD("ALTVEC Altivec Extensions: ", CPUInfo._Ext.Altivec_Extensions); - BOOLADD("TM Thermal Monitor: ", CPUInfo._Ext.TM_ThermalMonitor); - BOOLADD("TSC Time Stamp Counter: ", CPUInfo._Ext.TSC_TimeStampCounter); - BOOLADD("VME Virtual 8086 Mode Enhancements: ", CPUInfo._Ext.VME_Virtual8086ModeEnhancements); - BOOLADD("3DNow! Instructions: ", CPUInfo._Ext._3DNOW_InstructionExtensions); - BOOLADD("Enhanced 3DNow! Instructions: ", CPUInfo._Ext._E3DNOW_InstructionExtensions); -#endif - // Yippie!!! - return true; -} - -// bool CProcessor::WriteInfoTextFile(const std::string& strFilename) -// =========================================================== -// Takes use of CProcessor::CPUInfoToText and saves the string to a -// file -/////////////////////////////////////////////////////////////////// -bool CProcessor::WriteInfoTextFile(const std::string& strFilename) -{ - char buf[16384]; /* Flawfinder: ignore */ - - // First we get the string - if (!CPUInfoToText(buf, 16383)) - return false; - - // Then we create a new file (CREATE_ALWAYS) - LLFILE *file = LLFile::fopen(strFilename, "w"); /* Flawfinder: ignore */ - if (!file) - return false; - - // After that we write the string to the file - unsigned long dwBytesToWrite, dwBytesWritten; - dwBytesToWrite = (unsigned long) strlen(buf); /*Flawfinder: ignore*/ - dwBytesWritten = (unsigned long) fwrite(buf, 1, dwBytesToWrite, file); - fclose(file); - if (dwBytesToWrite != dwBytesWritten) - return false; - - // Done - return true; -} diff --git a/indra/llcommon/llprocessor.h b/indra/llcommon/llprocessor.h index 746d007a7..00cd5a555 100644 --- a/indra/llcommon/llprocessor.h +++ b/indra/llcommon/llprocessor.h @@ -30,166 +30,26 @@ * $/LicenseInfo$ */ -// Author: Benjamin Jurke -// File history: 27.02.2002 File created. -/////////////////////////////////////////// - #ifndef LLPROCESSOR_H #define LLPROCESSOR_H +class LLProcessorInfoImpl; -// Options: -/////////// -#if LL_WINDOWS -#define PROCESSOR_FREQUENCY_MEASURE_AVAILABLE -#endif - -#if LL_MSVC && _M_X64 -# define LL_X86_64 1 -# define LL_X86 1 -#elif LL_MSVC && _M_IX86 -# define LL_X86 1 -#elif LL_GNUC && ( defined(__amd64__) || defined(__x86_64__) ) -# define LL_X86_64 1 -# define LL_X86 1 -#elif LL_GNUC && ( defined(__i386__) ) -# define LL_X86 1 -#elif LL_GNUC && ( defined(__powerpc__) || defined(__ppc__) ) -# define LL_PPC 1 -#endif - - -struct ProcessorExtensions +class LL_COMMON_API LLProcessorInfo { - bool FPU_FloatingPointUnit; - bool VME_Virtual8086ModeEnhancements; - bool DE_DebuggingExtensions; - bool PSE_PageSizeExtensions; - bool TSC_TimeStampCounter; - bool MSR_ModelSpecificRegisters; - bool PAE_PhysicalAddressExtension; - bool MCE_MachineCheckException; - bool CX8_COMPXCHG8B_Instruction; - bool APIC_AdvancedProgrammableInterruptController; - unsigned int APIC_ID; - bool SEP_FastSystemCall; - bool MTRR_MemoryTypeRangeRegisters; - bool PGE_PTE_GlobalFlag; - bool MCA_MachineCheckArchitecture; - bool CMOV_ConditionalMoveAndCompareInstructions; - bool FGPAT_PageAttributeTable; - bool PSE36_36bitPageSizeExtension; - bool PN_ProcessorSerialNumber; - bool CLFSH_CFLUSH_Instruction; - unsigned int CLFLUSH_InstructionCacheLineSize; - bool DS_DebugStore; - bool ACPI_ThermalMonitorAndClockControl; - bool EMMX_MultimediaExtensions; - bool MMX_MultimediaExtensions; - bool FXSR_FastStreamingSIMD_ExtensionsSaveRestore; - bool SSE_StreamingSIMD_Extensions; - bool SSE2_StreamingSIMD2_Extensions; - bool Altivec_Extensions; - bool SS_SelfSnoop; - bool HT_HyperThreading; - unsigned int HT_HyterThreadingSiblings; - bool TM_ThermalMonitor; - bool IA64_Intel64BitArchitecture; - bool _3DNOW_InstructionExtensions; - bool _E3DNOW_InstructionExtensions; - bool AA64_AMD64BitArchitecture; -}; - -struct ProcessorCache -{ - bool bPresent; - char strSize[32]; /* Flawfinder: ignore */ - unsigned int uiAssociativeWays; - unsigned int uiLineSize; - bool bSectored; - char strCache[128]; /* Flawfinder: ignore */ -}; - -struct ProcessorL1Cache -{ - ProcessorCache Instruction; - ProcessorCache Data; -}; - -struct ProcessorTLB -{ - bool bPresent; - char strPageSize[32]; /* Flawfinder: ignore */ - unsigned int uiAssociativeWays; - unsigned int uiEntries; - char strTLB[128]; /* Flawfinder: ignore */ -}; - -struct ProcessorInfo -{ - char strVendor[16]; /* Flawfinder: ignore */ - unsigned int uiFamily; - unsigned int uiExtendedFamily; - char strFamily[64]; /* Flawfinder: ignore */ - unsigned int uiModel; - unsigned int uiExtendedModel; - char strModel[128]; /* Flawfinder: ignore */ - unsigned int uiStepping; - unsigned int uiType; - char strType[64]; /* Flawfinder: ignore */ - unsigned int uiBrandID; - char strBrandID[64]; /* Flawfinder: ignore */ - char strProcessorSerial[64]; /* Flawfinder: ignore */ - unsigned long MaxSupportedLevel; - unsigned long MaxSupportedExtendedLevel; - ProcessorExtensions _Ext; - ProcessorL1Cache _L1; - ProcessorCache _L2; - ProcessorCache _L3; - ProcessorCache _Trace; - ProcessorTLB _Instruction; - ProcessorTLB _Data; -}; - - -// CProcessor -// ========== -// Class for detecting the processor name, type and available -// extensions as long as it's speed. -///////////////////////////////////////////////////////////// -class CProcessor -{ -// Constructor / Destructor: -//////////////////////////// public: - CProcessor(); + LLProcessorInfo(); + ~LLProcessorInfo(); -// Private vars: -//////////////// -public: - F64 uqwFrequency; - char strCPUName[128]; /* Flawfinder: ignore */ - ProcessorInfo CPUInfo; - -// Private functions: -///////////////////// + F64 getCPUFrequency() const; + bool hasSSE() const; + bool hasSSE2() const; + bool hasAltivec() const; + std::string getCPUFamilyName() const; + std::string getCPUBrandName() const; + std::string getCPUFeatureDescription() const; private: - bool AnalyzeIntelProcessor(); - bool AnalyzeAMDProcessor(); - bool AnalyzeUnknownProcessor(); - bool CheckCPUIDPresence(); - void DecodeProcessorConfiguration(unsigned int cfg); - void TranslateProcessorConfiguration(); - void GetStandardProcessorConfiguration(); - void GetStandardProcessorExtensions(); - -// Public functions: -//////////////////// -public: - F64 GetCPUFrequency(unsigned int uiMeasureMSecs); - const ProcessorInfo *GetCPUInfo(); - bool CPUInfoToText(char *strBuffer, unsigned int uiMaxLen); - bool WriteInfoTextFile(const std::string& strFilename); + LLProcessorInfoImpl* mImpl; }; diff --git a/indra/llcommon/llrand.h b/indra/llcommon/llrand.h index 73ea17956..30fec9b98 100644 --- a/indra/llcommon/llrand.h +++ b/indra/llcommon/llrand.h @@ -65,32 +65,32 @@ /** *@brief Generate a float from [0, RAND_MAX). */ -LL_COMMON_API S32 ll_rand(); +S32 LL_COMMON_API ll_rand(); /** *@brief Generate a float from [0, val) or (val, 0]. */ -LL_COMMON_API S32 ll_rand(S32 val); +S32 LL_COMMON_API ll_rand(S32 val); /** *@brief Generate a float from [0, 1.0). */ -LL_COMMON_API F32 ll_frand(); +F32 LL_COMMON_API ll_frand(); /** *@brief Generate a float from [0, val) or (val, 0]. */ -LL_COMMON_API F32 ll_frand(F32 val); +F32 LL_COMMON_API ll_frand(F32 val); /** *@brief Generate a double from [0, 1.0). */ -LL_COMMON_API F64 ll_drand(); +F64 LL_COMMON_API ll_drand(); /** *@brief Generate a double from [0, val) or (val, 0]. */ -LL_COMMON_API F64 ll_drand(F64 val); +F64 LL_COMMON_API ll_drand(F64 val); /** * @brief typedefs for good boost lagged fibonacci. diff --git a/indra/llcommon/llrun.h b/indra/llcommon/llrun.h index 0f8d51d81..1fc9925df 100644 --- a/indra/llcommon/llrun.h +++ b/indra/llcommon/llrun.h @@ -38,8 +38,6 @@ #include #include -#include "llpreprocessor.h" - class LLRunnable; /** diff --git a/indra/llcommon/llstacktrace.cpp b/indra/llcommon/llstacktrace.cpp new file mode 100644 index 000000000..e0446c5d0 --- /dev/null +++ b/indra/llcommon/llstacktrace.cpp @@ -0,0 +1,143 @@ +/** + * @file llstacktrace.cpp + * @brief stack tracing functionality + * + * $LicenseInfo:firstyear=2001&license=viewergpl$ + * + * Copyright (c) 2001-2010, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlife.com/developers/opensource/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlife.com/developers/opensource/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + * + */ + +#include "linden_common.h" +#include "llstacktrace.h" + +#ifdef LL_WINDOWS + +#include +#include + +#include "windows.h" +#include "Dbghelp.h" + +typedef USHORT NTAPI RtlCaptureStackBackTrace_Function( + IN ULONG frames_to_skip, + IN ULONG frames_to_capture, + OUT PVOID *backtrace, + OUT PULONG backtrace_hash); + +static RtlCaptureStackBackTrace_Function* const RtlCaptureStackBackTrace_fn = + (RtlCaptureStackBackTrace_Function*) + GetProcAddress(GetModuleHandleA("ntdll.dll"), "RtlCaptureStackBackTrace"); + +bool ll_get_stack_trace(std::vector& lines) +{ + const S32 MAX_STACK_DEPTH = 32; + const S32 STRING_NAME_LENGTH = 200; + const S32 FRAME_SKIP = 2; + static BOOL symbolsLoaded = false; + static BOOL firstCall = true; + + HANDLE hProc = GetCurrentProcess(); + + // load the symbols if they're not loaded + if(!symbolsLoaded && firstCall) + { + symbolsLoaded = SymInitialize(hProc, NULL, true); + firstCall = false; + } + + // if loaded, get the call stack + if(symbolsLoaded) + { + // create the frames to hold the addresses + void* frames[MAX_STACK_DEPTH]; + memset(frames, 0, sizeof(void*)*MAX_STACK_DEPTH); + S32 depth = 0; + + // get the addresses + depth = RtlCaptureStackBackTrace_fn(FRAME_SKIP, MAX_STACK_DEPTH, frames, NULL); + + IMAGEHLP_LINE64 line; + memset(&line, 0, sizeof(IMAGEHLP_LINE64)); + line.SizeOfStruct = sizeof(IMAGEHLP_LINE64); + + // create something to hold address info + PIMAGEHLP_SYMBOL64 pSym; + pSym = (PIMAGEHLP_SYMBOL64)malloc(sizeof(IMAGEHLP_SYMBOL64) + STRING_NAME_LENGTH); + memset(pSym, 0, sizeof(IMAGEHLP_SYMBOL64) + STRING_NAME_LENGTH); + pSym->MaxNameLength = STRING_NAME_LENGTH; + pSym->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64); + + // get address info for each address frame + // and store + for(S32 i=0; i < depth; i++) + { + std::stringstream stack_line; + BOOL ret; + + DWORD64 addr = (DWORD64)frames[i]; + ret = SymGetSymFromAddr64(hProc, addr, 0, pSym); + if(ret) + { + stack_line << pSym->Name << " "; + } + + DWORD dummy; + ret = SymGetLineFromAddr64(hProc, addr, &dummy, &line); + if(ret) + { + std::string file_name = line.FileName; + std::string::size_type index = file_name.rfind("\\"); + stack_line << file_name.substr(index + 1, file_name.size()) << ":" << line.LineNumber; + } + + lines.push_back(stack_line.str()); + } + + free(pSym); + + // TODO: figure out a way to cleanup symbol loading + // Not hugely necessary, however. + //SymCleanup(hProc); + return true; + } + else + { + lines.push_back("Stack Trace Failed. PDB symbol info not loaded"); + } + + return false; +} + +#else + +bool ll_get_stack_trace(std::vector& lines) +{ + return false; +} + +#endif + diff --git a/indra/llcommon/processor.h b/indra/llcommon/llstacktrace.h similarity index 68% rename from indra/llcommon/processor.h rename to indra/llcommon/llstacktrace.h index 5ba55402b..93883b8b3 100644 --- a/indra/llcommon/processor.h +++ b/indra/llcommon/llstacktrace.h @@ -1,10 +1,10 @@ /** - * @file processor.h - * @brief Legacy wrapper header. + * @file llstacktrace.h + * @brief stack trace functions * - * $LicenseInfo:firstyear=2000&license=viewergpl$ + * $LicenseInfo:firstyear=2001&license=viewergpl$ * - * Copyright (c) 2000-2009, Linden Research, Inc. + * Copyright (c) 2001-2010, Linden Research, Inc. * * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab @@ -12,13 +12,13 @@ * ("GPL"), unless you have obtained a separate licensing agreement * ("Other License"), formally executed by you and Linden Lab. Terms of * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * online at http://secondlife.com/developers/opensource/gplv2 * * There are special exceptions to the terms and conditions of the GPL as * it is applied to this Source Code. View the full text of the exception * in the file doc/FLOSS-exception.txt in this software distribution, or * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * http://secondlife.com/developers/opensource/flossexception * * By copying, modifying or distributing this software, you acknowledge * that you have read and understood your obligations described above, @@ -28,6 +28,18 @@ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, * COMPLETENESS OR PERFORMANCE. * $/LicenseInfo$ + * */ -#include "llprocessor.h" + +#ifndef LL_LLSTACKTRACE_H +#define LL_LLSTACKTRACE_H + +#include "stdtypes.h" +#include +#include + +LL_COMMON_API bool ll_get_stack_trace(std::vector& lines); + +#endif + diff --git a/indra/llcommon/llstl.h b/indra/llcommon/llstl.h index 788617953..18842f276 100644 --- a/indra/llcommon/llstl.h +++ b/indra/llcommon/llstl.h @@ -39,6 +39,7 @@ #include #include #include +#include "stdtypes.h" // llcommon/stdtypes.h, needed for S32 and U32. // Use to compare the first element only of a pair // e.g. typedef std::set, compare_pair > some_pair_set_t; diff --git a/indra/llcommon/llstreamtools.cpp b/indra/llcommon/llstreamtools.cpp index ee4f46318..b60220830 100644 --- a/indra/llcommon/llstreamtools.cpp +++ b/indra/llcommon/llstreamtools.cpp @@ -436,7 +436,7 @@ void get_keyword_and_value(std::string& keyword, while (line_index < line_size) { c = line[line_index]; - if (!isspace(c)) + if (!LLStringOps::isSpace(c)) { break; } @@ -448,7 +448,7 @@ void get_keyword_and_value(std::string& keyword, while (line_index < line_size) { c = line[line_index]; - if (isspace(c) || '\r' == c || '\n' == c) + if (LLStringOps::isSpace(c) || '\r' == c || '\n' == c) { break; } diff --git a/indra/llcommon/llstring.cpp b/indra/llcommon/llstring.cpp index f08b4c042..7423726cb 100644 --- a/indra/llcommon/llstring.cpp +++ b/indra/llcommon/llstring.cpp @@ -34,6 +34,7 @@ #include "llstring.h" #include "llerror.h" +#include "llfasttimer.h" #if LL_WINDOWS #define WIN32_LEAN_AND_MEAN @@ -71,6 +72,24 @@ U8 hex_as_nybble(char hex) return 0; // uh - oh, not hex any more... } +bool iswindividual(llwchar elem) +{ + U32 cur_char = (U32)elem; + bool result = false; + if (0x2E80<= cur_char && cur_char <= 0x9FFF) + { + result = true; + } + else if (0xAC00<= cur_char && cur_char <= 0xD7A0 ) + { + result = true; + } + else if (0xF900<= cur_char && cur_char <= 0xFA60 ) + { + result = true; + } + return result; +} bool _read_file_into_string(std::string& str, const std::string& filename) { @@ -630,14 +649,14 @@ namespace snprintf_hack } } -std::string ll_convert_wide_to_string(const wchar_t* in) +std::string ll_convert_wide_to_string(const wchar_t* in, unsigned int code_page) { std::string out; if(in) { int len_in = wcslen(in); int len_out = WideCharToMultiByte( - CP_ACP, + code_page, 0, in, len_in, @@ -652,7 +671,7 @@ std::string ll_convert_wide_to_string(const wchar_t* in) if(pout) { WideCharToMultiByte( - CP_ACP, + code_page, 0, in, len_in, @@ -666,8 +685,55 @@ std::string ll_convert_wide_to_string(const wchar_t* in) } return out; } + +wchar_t* ll_convert_string_to_wide(const std::string& in, unsigned int code_page) +{ + // From review: + // We can preallocate a wide char buffer that is the same length (in wchar_t elements) as the utf8 input, + // plus one for a null terminator, and be guaranteed to not overflow. + + // Normally, I'd call that sort of thing premature optimization, + // but we *are* seeing string operations taking a bunch of time, especially when constructing widgets. +// int output_str_len = MultiByteToWideChar(code_page, 0, in.c_str(), in.length(), NULL, 0); + + // reserve place to NULL terminator + int output_str_len = in.length(); + wchar_t* w_out = new wchar_t[output_str_len + 1]; + + memset(w_out, 0, output_str_len + 1); + int real_output_str_len = MultiByteToWideChar (code_page, 0, in.c_str(), in.length(), w_out, output_str_len); + + //looks like MultiByteToWideChar didn't add null terminator to converted string, see EXT-4858. + w_out[real_output_str_len] = 0; + + return w_out; +} + +std::string ll_convert_string_to_utf8_string(const std::string& in) +{ + wchar_t* w_mesg = ll_convert_string_to_wide(in, CP_ACP); + std::string out_utf8(ll_convert_wide_to_string(w_mesg, CP_UTF8)); + delete[] w_mesg; + + return out_utf8; +} #endif // LL_WINDOWS +long LLStringOps::sPacificTimeOffset = 0; +long LLStringOps::sLocalTimeOffset = 0; +bool LLStringOps::sPacificDaylightTime = 0; +std::map LLStringOps::datetimeToCodes; + +std::vector LLStringOps::sWeekDayList; +std::vector LLStringOps::sWeekDayShortList; +std::vector LLStringOps::sMonthList; +std::vector LLStringOps::sMonthShortList; + + +std::string LLStringOps::sDayFormat; +std::string LLStringOps::sAM; +std::string LLStringOps::sPM; + S32 LLStringOps::collate(const llwchar* a, const llwchar* b) { #if LL_WINDOWS @@ -679,6 +745,107 @@ S32 LLStringOps::collate(const llwchar* a, const llwchar* b) #endif } +void LLStringOps::setupDatetimeInfo (bool daylight) +{ + time_t nowT, localT, gmtT; + struct tm * tmpT; + + nowT = time (NULL); + + tmpT = gmtime (&nowT); + gmtT = mktime (tmpT); + + tmpT = localtime (&nowT); + localT = mktime (tmpT); + + sLocalTimeOffset = (long) (gmtT - localT); + if (tmpT->tm_isdst) + { + sLocalTimeOffset -= 60 * 60; // 1 hour + } + + sPacificDaylightTime = daylight; + sPacificTimeOffset = (sPacificDaylightTime? 7 : 8 ) * 60 * 60; + + datetimeToCodes["wkday"] = "%a"; // Thu + datetimeToCodes["weekday"] = "%A"; // Thursday + datetimeToCodes["year4"] = "%Y"; // 2009 + datetimeToCodes["year"] = "%Y"; // 2009 + datetimeToCodes["year2"] = "%y"; // 09 + datetimeToCodes["mth"] = "%b"; // Aug + datetimeToCodes["month"] = "%B"; // August + datetimeToCodes["mthnum"] = "%m"; // 08 + datetimeToCodes["day"] = "%d"; // 31 + datetimeToCodes["sday"] = "%-d"; // 9 + datetimeToCodes["hour24"] = "%H"; // 14 + datetimeToCodes["hour"] = "%H"; // 14 + datetimeToCodes["hour12"] = "%I"; // 02 + datetimeToCodes["min"] = "%M"; // 59 + datetimeToCodes["ampm"] = "%p"; // AM + datetimeToCodes["second"] = "%S"; // 59 + datetimeToCodes["timezone"] = "%Z"; // PST +} + +void tokenizeStringToArray(const std::string& data, std::vector& output) +{ + output.clear(); + size_t length = data.size(); + + // tokenize it and put it in the array + std::string cur_word; + for(size_t i = 0; i < length; ++i) + { + if(data[i] == ':') + { + output.push_back(cur_word); + cur_word.clear(); + } + else + { + cur_word.append(1, data[i]); + } + } + output.push_back(cur_word); +} + +void LLStringOps::setupWeekDaysNames(const std::string& data) +{ + tokenizeStringToArray(data,sWeekDayList); +} +void LLStringOps::setupWeekDaysShortNames(const std::string& data) +{ + tokenizeStringToArray(data,sWeekDayShortList); +} +void LLStringOps::setupMonthNames(const std::string& data) +{ + tokenizeStringToArray(data,sMonthList); +} +void LLStringOps::setupMonthShortNames(const std::string& data) +{ + tokenizeStringToArray(data,sMonthShortList); +} +void LLStringOps::setupDayFormat(const std::string& data) +{ + sDayFormat = data; +} + + +std::string LLStringOps::getDatetimeCode (std::string key) +{ + std::map::iterator iter; + + iter = datetimeToCodes.find (key); + if (iter != datetimeToCodes.end()) + { + return iter->second; + } + else + { + return std::string(""); + } +} + + namespace LLStringFn { // NOTE - this restricts output to ascii @@ -715,12 +882,12 @@ namespace LLStringFn // https://wiki.lindenlab.com/wiki/Unicode_Guidelines has details on // allowable code points for XML. Specifically, they are: // 0x09, 0x0a, 0x0d, and 0x20 on up. JC - std::string strip_invalid_xml(const std::string& input) + std::string strip_invalid_xml(const std::string& instr) { std::string output; - output.reserve( input.size() ); - std::string::const_iterator it = input.begin(); - while (it != input.end()) + output.reserve( instr.size() ); + std::string::const_iterator it = instr.begin(); + while (it != instr.end()) { // Must compare as unsigned for >= // Test most likely match first @@ -756,6 +923,412 @@ namespace LLStringFn } } +//////////////////////////////////////////////////////////// + +// Forward specialization of LLStringUtil::format before use in LLStringUtil::formatDatetime. +template<> +S32 LLStringUtil::format(std::string& s, const format_map_t& substitutions); + +//static +template<> +void LLStringUtil::getTokens(const std::string& instr, std::vector& tokens, const std::string& delims) +{ + std::string currToken; + std::string::size_type begIdx, endIdx; + + begIdx = instr.find_first_not_of (delims); + while (begIdx != std::string::npos) + { + endIdx = instr.find_first_of (delims, begIdx); + if (endIdx == std::string::npos) + { + endIdx = instr.length(); + } + + currToken = instr.substr(begIdx, endIdx - begIdx); + LLStringUtil::trim (currToken); + tokens.push_back(currToken); + begIdx = instr.find_first_not_of (delims, endIdx); + } +} + +template<> +LLStringUtil::size_type LLStringUtil::getSubstitution(const std::string& instr, size_type& start, std::vector& tokens) +{ + const std::string delims (","); + + // Find the first ] + size_type pos2 = instr.find(']', start); + if (pos2 == std::string::npos) + return std::string::npos; + + // Find the last [ before ] + size_type pos1 = instr.find_last_of('[', pos2-1); + if (pos1 == std::string::npos || pos1 < start) + return std::string::npos; + + getTokens(std::string(instr,pos1+1,pos2-pos1-1), tokens, delims); + start = pos2+1; + + return pos1; +} + +// static +template<> +bool LLStringUtil::simpleReplacement(std::string &replacement, std::string token, const format_map_t& substitutions) +{ + // see if we have a replacement for the bracketed string (without the brackets) + // test first using has() because if we just look up with operator[] we get back an + // empty string even if the value is missing. We want to distinguish between + // missing replacements and deliberately empty replacement strings. + format_map_t::const_iterator iter = substitutions.find(token); + if (iter != substitutions.end()) + { + replacement = iter->second; + return true; + } + // if not, see if there's one WITH brackets + iter = substitutions.find(std::string("[" + token + "]")); + if (iter != substitutions.end()) + { + replacement = iter->second; + return true; + } + + return false; +} + +// static +template<> +bool LLStringUtil::simpleReplacement(std::string &replacement, std::string token, const LLSD& substitutions) +{ + // see if we have a replacement for the bracketed string (without the brackets) + // test first using has() because if we just look up with operator[] we get back an + // empty string even if the value is missing. We want to distinguish between + // missing replacements and deliberately empty replacement strings. + if (substitutions.has(token)) + { + replacement = substitutions[token].asString(); + return true; + } + // if not, see if there's one WITH brackets + else if (substitutions.has(std::string("[" + token + "]"))) + { + replacement = substitutions[std::string("[" + token + "]")].asString(); + return true; + } + + return false; +} + +//static +template<> +void LLStringUtil::setLocale(std::string inLocale) +{ + sLocale = inLocale; +}; + +//static +template<> +std::string LLStringUtil::getLocale(void) +{ + return sLocale; +}; + +// static +template<> +void LLStringUtil::formatNumber(std::string& numStr, std::string decimals) +{ + std::stringstream strStream; + S32 intDecimals = 0; + + convertToS32 (decimals, intDecimals); + if (!sLocale.empty()) + { + // std::locale() throws if the locale is unknown! (EXT-7926) + try + { + strStream.imbue(std::locale(sLocale.c_str())); + } catch (const std::exception &) + { + LL_WARNS_ONCE("Locale") << "Cannot set locale to " << sLocale << LL_ENDL; + } + } + + if (!intDecimals) + { + S32 intStr; + + if (convertToS32(numStr, intStr)) + { + strStream << intStr; + numStr = strStream.str(); + } + } + else + { + F32 floatStr; + + if (convertToF32(numStr, floatStr)) + { + strStream << std::fixed << std::showpoint << std::setprecision(intDecimals) << floatStr; + numStr = strStream.str(); + } + } +} + +// static +template<> +bool LLStringUtil::formatDatetime(std::string& replacement, std::string token, + std::string param, S32 secFromEpoch) +{ + if (param == "local") // local + { + secFromEpoch -= LLStringOps::getLocalTimeOffset(); + } + else if (param != "utc") // slt + { + secFromEpoch -= LLStringOps::getPacificTimeOffset(); + } + + // if never fell into those two ifs above, param must be utc + if (secFromEpoch < 0) secFromEpoch = 0; + + LLDate datetime((F64)secFromEpoch); + std::string code = LLStringOps::getDatetimeCode (token); + + // special case to handle timezone + if (code == "%Z") { + if (param == "utc") + { + replacement = "GMT"; + } + else if (param == "local") + { + replacement = ""; // user knows their own timezone + } + else + { + // "slt" = Second Life Time, which is deprecated. + // If not utc or user local time, fallback to Pacific time + replacement = LLStringOps::getPacificDaylightTime() ? "PDT" : "PST"; + } + return true; + } + + //EXT-7013 + //few codes are not suppotred by strtime function (example - weekdays for Japanise) + //so use predefined ones + + //if sWeekDayList is not empty than current locale doesn't support + //weekday name. + time_t loc_seconds = (time_t) secFromEpoch; + if(LLStringOps::sWeekDayList.size() == 7 && code == "%A") + { + struct tm * gmt = gmtime (&loc_seconds); + replacement = LLStringOps::sWeekDayList[gmt->tm_wday]; + } + else if(LLStringOps::sWeekDayShortList.size() == 7 && code == "%a") + { + struct tm * gmt = gmtime (&loc_seconds); + replacement = LLStringOps::sWeekDayShortList[gmt->tm_wday]; + } + else if(LLStringOps::sMonthList.size() == 12 && code == "%B") + { + struct tm * gmt = gmtime (&loc_seconds); + replacement = LLStringOps::sMonthList[gmt->tm_mon]; + } + else if( !LLStringOps::sDayFormat.empty() && code == "%d" ) + { + struct tm * gmt = gmtime (&loc_seconds); + LLStringUtil::format_map_t args; + args["[MDAY]"] = llformat ("%d", gmt->tm_mday); + replacement = LLStringOps::sDayFormat; + LLStringUtil::format(replacement, args); + } + else if (code == "%-d") + { + struct tm * gmt = gmtime (&loc_seconds); + replacement = llformat ("%d", gmt->tm_mday); // day of the month without leading zero + } + else if( !LLStringOps::sAM.empty() && !LLStringOps::sPM.empty() && code == "%p" ) + { + struct tm * gmt = gmtime (&loc_seconds); + if(gmt->tm_hour<12) + { + replacement = LLStringOps::sAM; + } + else + { + replacement = LLStringOps::sPM; + } + } + else + { + replacement = datetime.toHTTPDateString(code); + } + + // *HACK: delete leading zero from hour string in case 'hour12' (code = %I) time format + // to show time without leading zero, e.g. 08:16 -> 8:16 (EXT-2738). + // We could have used '%l' format instead, but it's not supported by Windows. + if(code == "%I" && token == "hour12" && replacement.at(0) == '0') + { + replacement = replacement.at(1); + } + + return !code.empty(); +} + +// LLStringUtil::format recogizes the following patterns. +// All substitutions *must* be encased in []'s in the input string. +// The []'s are optional in the substitution map. +// [FOO_123] +// [FOO,number,precision] +// [FOO,datetime,format] + + +// static +template<> +S32 LLStringUtil::format(std::string& s, const format_map_t& substitutions) +{ + LLFastTimer ft(LLFastTimer::FT_STRING_FORMAT); + S32 res = 0; + + std::string output; + std::vector tokens; + + std::string::size_type start = 0; + std::string::size_type prev_start = 0; + std::string::size_type key_start = 0; + while ((key_start = getSubstitution(s, start, tokens)) != std::string::npos) + { + output += std::string(s, prev_start, key_start-prev_start); + prev_start = start; + + bool found_replacement = false; + std::string replacement; + + if (tokens.size() == 0) + { + found_replacement = false; + } + else if (tokens.size() == 1) + { + found_replacement = simpleReplacement (replacement, tokens[0], substitutions); + } + else if (tokens[1] == "number") + { + std::string param = "0"; + + if (tokens.size() > 2) param = tokens[2]; + found_replacement = simpleReplacement (replacement, tokens[0], substitutions); + if (found_replacement) formatNumber (replacement, param); + } + else if (tokens[1] == "datetime") + { + std::string param; + if (tokens.size() > 2) param = tokens[2]; + + format_map_t::const_iterator iter = substitutions.find("datetime"); + if (iter != substitutions.end()) + { + S32 secFromEpoch = 0; + BOOL r = LLStringUtil::convertToS32(iter->second, secFromEpoch); + if (r) + { + found_replacement = formatDatetime(replacement, tokens[0], param, secFromEpoch); + } + } + } + + if (found_replacement) + { + output += replacement; + res++; + } + else + { + // we had no replacement, use the string as is + // e.g. "hello [MISSING_REPLACEMENT]" or "-=[Stylized Name]=-" + output += std::string(s, key_start, start-key_start); + } + tokens.clear(); + } + // send the remainder of the string (with no further matches for bracketed names) + output += std::string(s, start); + s = output; + return res; +} + +//static +template<> +S32 LLStringUtil::format(std::string& s, const LLSD& substitutions) +{ + LLFastTimer ft(LLFastTimer::FT_STRING_FORMAT); + S32 res = 0; + + if (!substitutions.isMap()) + { + return res; + } + + std::string output; + std::vector tokens; + + std::string::size_type start = 0; + std::string::size_type prev_start = 0; + std::string::size_type key_start = 0; + while ((key_start = getSubstitution(s, start, tokens)) != std::string::npos) + { + output += std::string(s, prev_start, key_start-prev_start); + prev_start = start; + + bool found_replacement = false; + std::string replacement; + + if (tokens.size() == 0) + { + found_replacement = false; + } + else if (tokens.size() == 1) + { + found_replacement = simpleReplacement (replacement, tokens[0], substitutions); + } + else if (tokens[1] == "number") + { + std::string param = "0"; + + if (tokens.size() > 2) param = tokens[2]; + found_replacement = simpleReplacement (replacement, tokens[0], substitutions); + if (found_replacement) formatNumber (replacement, param); + } + else if (tokens[1] == "datetime") + { + std::string param; + if (tokens.size() > 2) param = tokens[2]; + + S32 secFromEpoch = (S32) substitutions["datetime"].asInteger(); + found_replacement = formatDatetime (replacement, tokens[0], param, secFromEpoch); + } + + if (found_replacement) + { + output += replacement; + res++; + } + else + { + // we had no replacement, use the string as is + // e.g. "hello [MISSING_REPLACEMENT]" or "-=[Stylized Name]=-" + output += std::string(s, key_start, start-key_start); + } + tokens.clear(); + } + // send the remainder of the string (with no further matches for bracketed names) + output += std::string(s, start); + s = output; + return res; +} //////////////////////////////////////////////////////////// // Testing diff --git a/indra/llcommon/llstring.h b/indra/llcommon/llstring.h index 171747921..bdbefe935 100644 --- a/indra/llcommon/llstring.h +++ b/indra/llcommon/llstring.h @@ -37,6 +37,9 @@ #include #include #include +#include +#include +#include "llsd.h" #if LL_LINUX || LL_SOLARIS #include @@ -148,7 +151,23 @@ struct char_traits class LL_COMMON_API LLStringOps { +private: + static long sPacificTimeOffset; + static long sLocalTimeOffset; + static bool sPacificDaylightTime; + + static std::map datetimeToCodes; + public: + static std::vector sWeekDayList; + static std::vector sWeekDayShortList; + static std::vector sMonthList; + static std::vector sMonthShortList; + static std::string sDayFormat; + + static std::string sAM; + static std::string sPM; + static char toUpper(char elem) { return toupper((unsigned char)elem); } static llwchar toUpper(llwchar elem) { return towupper(elem); } @@ -177,14 +196,31 @@ public: static S32 collate(const llwchar* a, const llwchar* b); static bool isHexString(const std::string& str); + + static void setupDatetimeInfo(bool pacific_daylight_time); + + static void setupWeekDaysNames(const std::string& data); + static void setupWeekDaysShortNames(const std::string& data); + static void setupMonthNames(const std::string& data); + static void setupMonthShortNames(const std::string& data); + static void setupDayFormat(const std::string& data); + + + static long getPacificTimeOffset(void) { return sPacificTimeOffset;} + static long getLocalTimeOffset(void) { return sLocalTimeOffset;} + // Is the Pacific time zone (aka server time zone) + // currently in daylight savings time? + static bool getPacificDaylightTime(void) { return sPacificDaylightTime;} + + static std::string getDatetimeCode (std::string key); }; /** * @brief Return a string constructed from in without crashing if the * pointer is NULL. */ -std::string LL_COMMON_API ll_safe_string(const char* in); -std::string LL_COMMON_API ll_safe_string(const char* in, S32 maxlen); +LL_COMMON_API std::string ll_safe_string(const char* in); +LL_COMMON_API std::string ll_safe_string(const char* in, S32 maxlen); // Allowing assignments from non-strings into format_map_t is apparently @@ -206,6 +242,9 @@ private: template class LLStringUtilBase { +private: + static std::string sLocale; + public: typedef typename std::basic_string::size_type size_type; @@ -213,10 +252,18 @@ public: ///////////////////////////////////////////////////////////////////////////////////////// // Static Utility functions that operate on std::strings - static std::basic_string const null; + static const std::basic_string null; typedef std::map format_map_t; - static S32 format(std::basic_string& s, const format_map_t& fmt_map); + LL_COMMON_API static void getTokens(const std::basic_string& instr, std::vector >& tokens, const std::basic_string& delims); + LL_COMMON_API static void formatNumber(std::basic_string& numStr, std::basic_string decimals); + LL_COMMON_API static bool formatDatetime(std::basic_string& replacement, std::basic_string token, std::basic_string param, S32 secFromEpoch); + LL_COMMON_API static S32 format(std::basic_string& s, const format_map_t& substitutions); + LL_COMMON_API static S32 format(std::basic_string& s, const LLSD& substitutions); + LL_COMMON_API static bool simpleReplacement(std::basic_string& replacement, std::basic_string token, const format_map_t& substitutions); + LL_COMMON_API static bool simpleReplacement(std::basic_string& replacement, std::basic_string token, const LLSD& substitutions); + LL_COMMON_API static void setLocale (std::string inLocale); + LL_COMMON_API static std::string getLocale (void); static bool isValidIndex(const std::basic_string& string, size_type i) { @@ -233,7 +280,25 @@ public: // True if this is the head of s. static BOOL isHead( const std::basic_string& string, const T* s ); - + + /** + * @brief Returns true if string starts with substr + * + * If etither string or substr are empty, this method returns false. + */ + static bool startsWith( + const std::basic_string& string, + const std::basic_string& substr); + + /** + * @brief Returns true if string ends in substr + * + * If etither string or substr are empty, this method returns false. + */ + static bool endsWith( + const std::basic_string& string, + const std::basic_string& substr); + static void addCRLF(std::basic_string& string); static void removeCRLF(std::basic_string& string); @@ -298,13 +363,19 @@ public: // Copies src into dst at a given offset. static void copyInto(std::basic_string& dst, const std::basic_string& src, size_type offset); + static bool isPartOfWord(T c) { return (c == (T)'_') || LLStringOps::isAlnum(c); } + + #ifdef _DEBUG - static void testHarness(); + LL_COMMON_API static void testHarness(); #endif +private: + LL_COMMON_API static size_type getSubstitution(const std::basic_string& instr, size_type& start, std::vector >& tokens); }; -template std::basic_string const LLStringUtilBase::null; +template const std::basic_string LLStringUtilBase::null; +template std::string LLStringUtilBase::sLocale; typedef LLStringUtilBase LLStringUtil; typedef LLStringUtilBase LLWStringUtil; @@ -366,6 +437,7 @@ LL_COMMON_API U8 hex_as_nybble(char hex); * @return Returns true on success. If false, str is unmodified. */ LL_COMMON_API bool _read_file_into_string(std::string& str, const std::string& filename); +LL_COMMON_API bool iswindividual(llwchar elem); /** * Unicode support @@ -495,7 +567,20 @@ using snprintf_hack::snprintf; * * This replaces the unsafe W2A macro from ATL. */ -LL_COMMON_API std::string ll_convert_wide_to_string(const wchar_t* in); +LL_COMMON_API std::string ll_convert_wide_to_string(const wchar_t* in, unsigned int code_page); + +/** + * Converts a string to wide string. + * + * It will allocate memory for result string with "new []". Don't forget to release it with "delete []". + */ +LL_COMMON_API wchar_t* ll_convert_string_to_wide(const std::string& in, unsigned int code_page); + +/** + * Converts incoming string into urf8 string + * + */ +LL_COMMON_API std::string ll_convert_string_to_utf8_string(const std::string& in); //@} #endif // LL_WINDOWS @@ -558,63 +643,12 @@ namespace LLStringFn } //////////////////////////////////////////////////////////// +// NOTE: LLStringUtil::format, getTokens, and support functions moved to llstring.cpp. +// There is no LLWStringUtil::format implementation currently. +// Calling thse for anything other than LLStringUtil will produce link errors. -// LLStringBase::format() -// -// This function takes a string 's' and a map 'fmt_map' of strings-to-strings. -// All occurances of strings in 's' from the left-hand side of 'fmt_map' are -// then replaced with the corresponding right-hand side of 'fmt_map', non- -// recursively. The function returns the number of substitutions made. +//////////////////////////////////////////////////////////// -// static -template -S32 LLStringUtilBase::format(std::basic_string& s, const format_map_t& fmt_map) -{ - typedef typename std::basic_string::size_type string_size_type_t; - string_size_type_t scanstart = 0; - S32 res = 0; - - // Look for the first match of any keyword, replace that keyword, - // repeat from the end of the replacement string. This avoids - // accidentally performing substitution on a substituted string. - while (1) - { - string_size_type_t first_match_pos = scanstart; - string_size_type_t first_match_str_length = 0; - std::basic_string first_match_str_replacement; - - for (format_map_t::const_iterator iter = fmt_map.begin(); - iter != fmt_map.end(); - ++iter) - { - string_size_type_t n = s.find(iter->first, scanstart); - if (n != std::basic_string::npos && - (n < first_match_pos || - 0 == first_match_str_length)) - { - first_match_pos = n; - first_match_str_length = iter->first.length(); - first_match_str_replacement = iter->second; - } - } - - if (0 == first_match_str_length) - { - // no more keys found to substitute from this point - // in the string forward. - break; - } - else - { - s.erase(first_match_pos, first_match_str_length); - s.insert(first_match_pos, first_match_str_replacement); - scanstart = first_match_pos + - first_match_str_replacement.length(); - ++res; - } - } - return res; -} // static template @@ -1003,14 +1037,15 @@ void LLStringUtilBase::stripNonprintable(std::basic_string& string) { return; } - char* c_string = new char[string.size() + 1]; + size_t src_size = string.size(); + char* c_string = new char[src_size + 1]; if(c_string == NULL) { return; } - strcpy(c_string, string.c_str()); /*Flawfinder: ignore*/ + copy(c_string, string.c_str(), src_size+1); char* write_head = &c_string[0]; - for (size_type i = 0; i < string.size(); i++) + for (size_type i = 0; i < src_size; i++) { char* read_head = &string[i]; write_head = &c_string[j]; @@ -1090,6 +1125,30 @@ BOOL LLStringUtilBase::isHead( const std::basic_string& string, const T* s } } +// static +template +bool LLStringUtilBase::startsWith( + const std::basic_string& string, + const std::basic_string& substr) +{ + if(string.empty() || (substr.empty())) return false; + if(0 == string.find(substr)) return true; + return false; +} + +// static +template +bool LLStringUtilBase::endsWith( + const std::basic_string& string, + const std::basic_string& substr) +{ + if(string.empty() || (substr.empty())) return false; + std::string::size_type idx = string.rfind(substr); + if(std::string::npos == idx) return false; + return (idx == (string.size() - substr.size())); +} + + template BOOL LLStringUtilBase::convertToBOOL(const std::basic_string& string, BOOL& value) { diff --git a/indra/llcommon/llstringtable.cpp b/indra/llcommon/llstringtable.cpp index 27f9036b8..2f3a994d8 100644 --- a/indra/llcommon/llstringtable.cpp +++ b/indra/llcommon/llstringtable.cpp @@ -38,6 +38,23 @@ LLStringTable gStringTable(32768); +LLStringTableEntry::LLStringTableEntry(const char *str) +: mString(NULL), mCount(1) +{ + // Copy string + U32 length = (U32)strlen(str) + 1; /*Flawfinder: ignore*/ + length = llmin(length, MAX_STRINGS_LENGTH); + mString = new char[length]; + strncpy(mString, str, length); /*Flawfinder: ignore*/ + mString[length - 1] = 0; +} + +LLStringTableEntry::~LLStringTableEntry() +{ + delete [] mString; + mCount = 0; +} + LLStringTable::LLStringTable(int tablesize) : mUniqueEntries(0) { diff --git a/indra/llcommon/llstringtable.h b/indra/llcommon/llstringtable.h index 238701dfd..d40c9d8df 100644 --- a/indra/llcommon/llstringtable.h +++ b/indra/llcommon/llstringtable.h @@ -49,11 +49,11 @@ #endif #if STRING_TABLE_HASH_MAP -#if LL_WINDOWS -#include -#else -#include -#endif +# if LL_WINDOWS +# include +# else +# include +# endif #endif const U32 MAX_STRINGS_LENGTH = 256; @@ -61,21 +61,9 @@ const U32 MAX_STRINGS_LENGTH = 256; class LL_COMMON_API LLStringTableEntry { public: - LLStringTableEntry(const char *str) - : mString(NULL), mCount(1) - { - // Copy string - U32 length = (U32)strlen(str) + 1; /*Flawfinder: ignore*/ - length = llmin(length, MAX_STRINGS_LENGTH); - mString = new char[length]; - strncpy(mString, str, length); /*Flawfinder: ignore*/ - mString[length - 1] = 0; - } - ~LLStringTableEntry() - { - delete [] mString; - mCount = 0; - } + LLStringTableEntry(const char *str); + ~LLStringTableEntry(); + void incCount() { mCount++; } BOOL decCount() { return --mCount; } diff --git a/indra/llcommon/llsys.cpp b/indra/llcommon/llsys.cpp index bde0cbd6e..82366453a 100644 --- a/indra/llcommon/llsys.cpp +++ b/indra/llcommon/llsys.cpp @@ -52,13 +52,13 @@ # include # include # include +//# include May be needed? #elif LL_LINUX # include # include # include # include const char MEMINFO_FILE[] = "/proc/meminfo"; -const char CPUINFO_FILE[] = "/proc/cpuinfo"; #elif LL_SOLARIS # include # include @@ -74,7 +74,7 @@ extern int errno; static const S32 CPUINFO_BUFFER_SIZE = 16383; -LL_COMMON_API LLCPUInfo gSysCPU; +LLCPUInfo gSysCPU; #if LL_WINDOWS #ifndef DLLVERSIONINFO @@ -325,7 +325,58 @@ LLOSInfo::LLOSInfo() : } mOSString += compatibility_mode; +#elif LL_DARWIN + + // Initialize mOSStringSimple to something like: + // "Mac OS X 10.6.7" + { + const char * DARWIN_PRODUCT_NAME = "Mac OS X"; + + SInt32 major_version, minor_version, bugfix_version; + OSErr r1 = Gestalt(gestaltSystemVersionMajor, &major_version); + OSErr r2 = Gestalt(gestaltSystemVersionMinor, &minor_version); + OSErr r3 = Gestalt(gestaltSystemVersionBugFix, &bugfix_version); + + if((r1 == noErr) && (r2 == noErr) && (r3 == noErr)) + { + mMajorVer = major_version; + mMinorVer = minor_version; + mBuild = bugfix_version; + + std::stringstream os_version_string; + os_version_string << DARWIN_PRODUCT_NAME << " " << mMajorVer << "." << mMinorVer << "." << mBuild; + + // Put it in the OS string we are compiling + mOSStringSimple.append(os_version_string.str()); + } + else + { + mOSStringSimple.append("Unable to collect OS info"); + } + } + + // Initialize mOSString to something like: + // "Mac OS X 10.6.7 Darwin Kernel Version 10.7.0: Sat Jan 29 15:17:16 PST 2011; root:xnu-1504.9.37~1/RELEASE_I386 i386" + struct utsname un; + if(uname(&un) != -1) + { + mOSString = mOSStringSimple; + mOSString.append(" "); + mOSString.append(un.sysname); + mOSString.append(" "); + mOSString.append(un.release); + mOSString.append(" "); + mOSString.append(un.version); + mOSString.append(" "); + mOSString.append(un.machine); + } + else + { + mOSString = mOSStringSimple; + } + #else + struct utsname un; if(uname(&un) != -1) { @@ -341,15 +392,7 @@ LLOSInfo::LLOSInfo() : // Simplify 'Simple' std::string ostype = mOSStringSimple.substr(0, mOSStringSimple.find_first_of(" ", 0)); - if (ostype == "Darwin") - { - // Only care about major Darwin versions, truncate at first '.' - S32 idx1 = mOSStringSimple.find_first_of(".", 0); - std::string simple = mOSStringSimple.substr(0, idx1); - if (simple.length() > 0) - mOSStringSimple = simple; - } - else if (ostype == "Linux") + if (ostype == "Linux") { // Only care about major and minor Linux versions, truncate at second '.' std::string::size_type idx1 = mOSStringSimple.find_first_of(".", 0); @@ -513,71 +556,21 @@ U32 LLOSInfo::getProcessResidentSizeKB() LLCPUInfo::LLCPUInfo() { std::ostringstream out; - CProcessor proc; - const ProcessorInfo* info = proc.GetCPUInfo(); + LLProcessorInfo proc; // proc.WriteInfoTextFile("procInfo.txt"); - mHasSSE = info->_Ext.SSE_StreamingSIMD_Extensions; - mHasSSE2 = info->_Ext.SSE2_StreamingSIMD2_Extensions; - mHasAltivec = info->_Ext.Altivec_Extensions; - mCPUMHz = (F64)(proc.GetCPUFrequency(50)/1000000.0); - mFamily.assign( info->strFamily ); + mHasSSE = proc.hasSSE(); + mHasSSE2 = proc.hasSSE2(); + mHasAltivec = proc.hasAltivec(); + mCPUMHz = (F64)proc.getCPUFrequency(); + mFamily = proc.getCPUFamilyName(); mCPUString = "Unknown"; -#if LL_WINDOWS || LL_DARWIN || LL_SOLARIS - out << proc.strCPUName; + out << proc.getCPUBrandName(); if (200 < mCPUMHz && mCPUMHz < 10000) // *NOTE: cpu speed is often way wrong, do a sanity check { out << " (" << mCPUMHz << " MHz)"; } mCPUString = out.str(); - -#elif LL_LINUX - std::map< std::string, std::string > cpuinfo; - LLFILE* cpuinfo_fp = LLFile::fopen(CPUINFO_FILE, "rb"); - if(cpuinfo_fp) - { - char line[MAX_STRING]; - memset(line, 0, MAX_STRING); - while(fgets(line, MAX_STRING, cpuinfo_fp)) - { - // /proc/cpuinfo on Linux looks like: - // name\t*: value\n - char* tabspot = strchr( line, '\t' ); - if (tabspot == NULL) - continue; - char* colspot = strchr( tabspot, ':' ); - if (colspot == NULL) - continue; - char* spacespot = strchr( colspot, ' ' ); - if (spacespot == NULL) - continue; - char* nlspot = strchr( line, '\n' ); - if (nlspot == NULL) - nlspot = line + strlen( line ); // Fallback to terminating NUL - std::string linename( line, tabspot ); - std::string llinename(linename); - LLStringUtil::toLower(llinename); - std::string lineval( spacespot + 1, nlspot ); - cpuinfo[ llinename ] = lineval; - } - fclose(cpuinfo_fp); - } -# if LL_X86 - std::string flags = " " + cpuinfo["flags"] + " "; - LLStringUtil::toLower(flags); - mHasSSE = ( flags.find( " sse " ) != std::string::npos ); - mHasSSE2 = ( flags.find( " sse2 " ) != std::string::npos ); - - F64 mhz; - if (LLStringUtil::convertToF64(cpuinfo["cpu mhz"], mhz) - && 200.0 < mhz && mhz < 10000.0) - { - mCPUMHz = (F64)llrint(mhz); - } - if (!cpuinfo["model name"].empty()) - mCPUString = cpuinfo["model name"]; -# endif // LL_X86 -#endif // LL_LINUX } bool LLCPUInfo::hasAltivec() const @@ -607,38 +600,9 @@ std::string LLCPUInfo::getCPUString() const void LLCPUInfo::stream(std::ostream& s) const { -#if LL_WINDOWS || LL_DARWIN || LL_SOLARIS // gather machine information. - char proc_buf[CPUINFO_BUFFER_SIZE]; /* Flawfinder: ignore */ - CProcessor proc; - if(proc.CPUInfoToText(proc_buf, CPUINFO_BUFFER_SIZE)) - { - s << proc_buf; - } - else - { - s << "Unable to collect processor information" << std::endl; - } -#else - // *NOTE: This works on linux. What will it do on other systems? - LLFILE* cpuinfo = LLFile::fopen(CPUINFO_FILE, "rb"); - if(cpuinfo) - { - char line[MAX_STRING]; - memset(line, 0, MAX_STRING); - while(fgets(line, MAX_STRING, cpuinfo)) - { - line[strlen(line)-1] = ' '; - s << line; - } - fclose(cpuinfo); - s << std::endl; - } - else - { - s << "Unable to collect processor information" << std::endl; - } -#endif + s << LLProcessorInfo().getCPUFeatureDescription(); + // These are interesting as they reflect our internal view of the // CPU's attributes regardless of platform s << "->mHasSSE: " << (U32)mHasSSE << std::endl; diff --git a/indra/llcommon/llsys.h b/indra/llcommon/llsys.h index e481c8838..10f963d50 100644 --- a/indra/llcommon/llsys.h +++ b/indra/llcommon/llsys.h @@ -131,10 +131,10 @@ LL_COMMON_API std::ostream& operator<<(std::ostream& s, const LLCPUInfo& info); LL_COMMON_API std::ostream& operator<<(std::ostream& s, const LLMemoryInfo& info); // gunzip srcfile into dstfile. Returns FALSE on error. -LL_COMMON_API BOOL gunzip_file(const std::string& srcfile, const std::string& dstfile); +BOOL LL_COMMON_API gunzip_file(const std::string& srcfile, const std::string& dstfile); // gzip srcfile into dstfile. Returns FALSE on error. -LL_COMMON_API BOOL gzip_file(const std::string& srcfile, const std::string& dstfile); +BOOL LL_COMMON_API gzip_file(const std::string& srcfile, const std::string& dstfile); -LL_COMMON_API extern LLCPUInfo gSysCPU; +extern LL_COMMON_API LLCPUInfo gSysCPU; #endif // LL_LLSYS_H diff --git a/indra/llcommon/llthread.cpp b/indra/llcommon/llthread.cpp index 7ced30939..8bd341457 100644 --- a/indra/llcommon/llthread.cpp +++ b/indra/llcommon/llthread.cpp @@ -67,6 +67,10 @@ // void *APR_THREAD_FUNC LLThread::staticRun(apr_thread_t *apr_threadp, void *datap) { +#ifdef CWDEBUG + debug::init_thread(); +#endif + LLThread *threadp = (LLThread *)datap; // Set thread state to running diff --git a/indra/llcommon/lltimer.cpp b/indra/llcommon/lltimer.cpp index c0d47890c..34e19f83f 100644 --- a/indra/llcommon/lltimer.cpp +++ b/indra/llcommon/lltimer.cpp @@ -33,7 +33,6 @@ #include "linden_common.h" #include "lltimer.h" -#include "timing.h" // totalTime prototype. #include "u64.h" @@ -52,6 +51,9 @@ // // Locally used constants // +const U32 SEC_PER_DAY = 86400; +const F64 SEC_TO_MICROSEC = 1000000.f; +const U64 SEC_TO_MICROSEC_U64 = 1000000; const F64 USEC_TO_SEC_F64 = 0.000001; @@ -571,59 +573,6 @@ void timeStructToFormattedString(struct tm * time, std::string format, std::stri } -////////////////////////////////////////////////////////////////////////////// -// -// LLEventTimer Implementation -// -////////////////////////////////////////////////////////////////////////////// - -std::list LLEventTimer::sActiveList; - -LLEventTimer::LLEventTimer(F32 period) -: mEventTimer() -{ - mPeriod = period; - sActiveList.push_back(this); -} - -LLEventTimer::LLEventTimer(const LLDate& time) -: mEventTimer() -{ - mPeriod = (F32)(time.secondsSinceEpoch() - LLDate::now().secondsSinceEpoch()); - sActiveList.push_back(this); -} -LLEventTimer::~LLEventTimer() -{ - sActiveList.remove(this); -} - -void LLEventTimer::updateClass() -{ - std::list completed_timers; - for (std::list::iterator iter = sActiveList.begin(); iter != sActiveList.end(); ) - { - LLEventTimer* timer = *iter++; - F32 et = timer->mEventTimer.getElapsedTimeF32(); - if (timer->mEventTimer.getStarted() && et > timer->mPeriod) { - timer->mEventTimer.reset(); - if ( timer->tick() ) - { - completed_timers.push_back( timer ); - } - } - } - - if ( completed_timers.size() > 0 ) - { - for (std::list::iterator completed_iter = completed_timers.begin(); - completed_iter != completed_timers.end(); - completed_iter++ ) - { - delete *completed_iter; - } - } -} - diff --git a/indra/llcommon/lltimer.h b/indra/llcommon/lltimer.h index 26734919c..68f06fdce 100644 --- a/indra/llcommon/lltimer.h +++ b/indra/llcommon/lltimer.h @@ -55,6 +55,8 @@ const U32 USEC_PER_HOUR = USEC_PER_MIN * MIN_PER_HOUR; const U32 SEC_PER_HOUR = SEC_PER_MIN * MIN_PER_HOUR; const F64 SEC_PER_USEC = 1.0 / (F64) USEC_PER_SEC; +LL_COMMON_API U64 totalTime(); // Returns current system time in microseconds + class LL_COMMON_API LLTimer { public: @@ -155,7 +157,7 @@ static inline time_t time_max() } // Correction factor used by time_corrected() above. -LL_COMMON_API extern S32 gUTCOffset; +extern LL_COMMON_API S32 gUTCOffset; // Is the current computer (in its current time zone) // observing daylight savings time? @@ -173,27 +175,4 @@ LL_COMMON_API void secondsToTimecodeString(F32 current_time, std::string& tcstri LL_COMMON_API void timeToFormattedString(time_t time, std::string format, std::string ×tr); LL_COMMON_API void timeStructToFormattedString(struct tm * time, std::string format, std::string ×tr); -// class for scheduling a function to be called at a given frequency (approximate, inprecise) -class LL_COMMON_API LLEventTimer -{ -public: - LLEventTimer(F32 period); // period is the amount of time between each call to tick() in seconds - LLEventTimer(const LLDate& time); - virtual ~LLEventTimer(); - - //function to be called at the supplied frequency - // Normally return FALSE; TRUE will delete the timer after the function returns. - virtual BOOL tick() = 0; - - static void updateClass(); - -protected: - LLTimer mEventTimer; - F32 mPeriod; - -private: - //list of active timers - static std::list sActiveList; // TODO should this be a vector -}; - #endif diff --git a/indra/llcommon/timing.h b/indra/llcommon/timing.h index cfc637eb6..140ce1fca 100644 --- a/indra/llcommon/timing.h +++ b/indra/llcommon/timing.h @@ -43,7 +43,6 @@ const F32 SEC_TO_MICROSEC = 1000000.f; const U64 SEC_TO_MICROSEC_U64 = 1000000; const U32 SEC_PER_DAY = 86400; -// This is just a stub, implementation in lltimer.cpp. This file will be deprecated in the future. -LL_COMMON_API U64 totalTime(); // Returns current system time in microseconds +// functionality has been moved lltimer.{cpp,h}. This file will be deprecated in the future. #endif diff --git a/indra/llcrashlogger/llcrashlogger.cpp b/indra/llcrashlogger/llcrashlogger.cpp index 3dc41e897..f955ccdfd 100644 --- a/indra/llcrashlogger/llcrashlogger.cpp +++ b/indra/llcrashlogger/llcrashlogger.cpp @@ -29,13 +29,15 @@ * COMPLETENESS OR PERFORMANCE. * $/LicenseInfo$ */ + +#include "linden_common.h" + #include #include #include #include #include "llcrashlogger.h" -#include "linden_common.h" #include "llstring.h" #include "indra_constants.h" // CRASH_BEHAVIOR_ASK, CRASH_SETTING_NAME #include "llerror.h" diff --git a/indra/llcrashlogger/llcrashlogger.h b/indra/llcrashlogger/llcrashlogger.h index f8abe2059..72c1f3fb8 100644 --- a/indra/llcrashlogger/llcrashlogger.h +++ b/indra/llcrashlogger/llcrashlogger.h @@ -32,10 +32,10 @@ #ifndef LLCRASHLOGGER_H #define LLCRASHLOGGER_H -#include - #include "linden_common.h" +#include + #include "llapp.h" #include "llsd.h" #include "llcontrol.h" diff --git a/indra/llimage/tests/llimageworker_test.cpp b/indra/llimage/tests/llimageworker_test.cpp index cc44696a4..2bca81434 100644 --- a/indra/llimage/tests/llimageworker_test.cpp +++ b/indra/llimage/tests/llimageworker_test.cpp @@ -32,6 +32,7 @@ */ // Precompiled header: almost always required for newview cpp files +#include "../llcommon/linden_common.h" #include #include #include diff --git a/indra/llinventory/llsaleinfo.cpp b/indra/llinventory/llsaleinfo.cpp index b7afb28ad..e51e35e6e 100644 --- a/indra/llinventory/llsaleinfo.cpp +++ b/indra/llinventory/llsaleinfo.cpp @@ -30,8 +30,8 @@ * $/LicenseInfo$ */ -#include #include "linden_common.h" +#include #include "llsaleinfo.h" diff --git a/indra/llmath/llcamera.cpp b/indra/llmath/llcamera.cpp index e6b6797c6..263803930 100644 --- a/indra/llmath/llcamera.cpp +++ b/indra/llmath/llcamera.cpp @@ -45,7 +45,8 @@ LLCamera::LLCamera() : mNearPlane(DEFAULT_NEAR_PLANE), mFarPlane(DEFAULT_FAR_PLANE), mFixedDistance(-1.f), - mPlaneCount(6) + mPlaneCount(6), + mFrustumCornerDist(0.f) { calculateFrustumPlanes(); } @@ -55,7 +56,8 @@ LLCamera::LLCamera(F32 vertical_fov_rads, F32 aspect_ratio, S32 view_height_in_p LLCoordFrame(), mViewHeightInPixels(view_height_in_pixels), mFixedDistance(-1.f), - mPlaneCount(6) + mPlaneCount(6), + mFrustumCornerDist(0.f) { mAspect = llclamp(aspect_ratio, MIN_ASPECT_RATIO, MAX_ASPECT_RATIO); mNearPlane = llclamp(near_plane, MIN_NEAR_PLANE, MAX_NEAR_PLANE); @@ -65,6 +67,10 @@ LLCamera::LLCamera(F32 vertical_fov_rads, F32 aspect_ratio, S32 view_height_in_p setView(vertical_fov_rads); } +LLCamera::~LLCamera() +{ + +} // ---------------- LLCamera::getFoo() member functions ---------------- @@ -86,11 +92,11 @@ F32 LLCamera::getMaxView() const // ---------------- LLCamera::setFoo() member functions ---------------- -void LLCamera::setUserClipPlane(LLPlane plane) +void LLCamera::setUserClipPlane(LLPlane const& plane) { mPlaneCount = 7; - mAgentPlanes[6].p = plane; - mAgentPlanes[6].mask = calcPlaneMask(plane); + mAgentPlanes[6] = plane; + mPlaneMask[6] = plane.calcPlaneMask(); } void LLCamera::disableUserClipPlane() @@ -178,7 +184,7 @@ S32 LLCamera::AABBInFrustum(const LLVector3 ¢er, const LLVector3& radius) U8 mask = 0; S32 result = 2; - if (radius.magVecSquared() > mFrustumCornerDist * mFrustumCornerDist) + /*if (radius.magVecSquared() > mFrustumCornerDist * mFrustumCornerDist) { //box is larger than frustum, check frustum quads against box planes static const LLVector3 dir[] = @@ -241,12 +247,16 @@ S32 LLCamera::AABBInFrustum(const LLVector3 ¢er, const LLVector3& radius) result = 1; } } - else + else*/ { for (U32 i = 0; i < mPlaneCount; i++) { - mask = mAgentPlanes[i].mask; - LLPlane p = mAgentPlanes[i].p; + mask = mPlaneMask[i]; + if (mask == 0xff) + { + continue; + } + LLPlane p = mAgentPlanes[i]; LLVector3 n = LLVector3(p); float d = p.mV[3]; LLVector3 rscale = radius.scaledVec(scaler[mask]); @@ -293,8 +303,12 @@ S32 LLCamera::AABBInFrustumNoFarClip(const LLVector3 ¢er, const LLVector3& r continue; } - mask = mAgentPlanes[i].mask; - LLPlane p = mAgentPlanes[i].p; + mask = mPlaneMask[i]; + if (mask == 0xff) + { + continue; + } + LLPlane p = mAgentPlanes[i]; LLVector3 n = LLVector3(p); float d = p.mV[3]; LLVector3 rscale = radius.scaledVec(scaler[mask]); @@ -434,23 +448,22 @@ int LLCamera::sphereInFrustumOld(const LLVector3 &sphere_center, const F32 radiu int LLCamera::sphereInFrustum(const LLVector3 &sphere_center, const F32 radius) const { // Returns 1 if sphere is in frustum, 0 if not. - int res = 2; + bool res = false; for (int i = 0; i < 6; i++) { - float d = mAgentPlanes[i].p.dist(sphere_center); - - if (d > radius) + if (mPlaneMask[i] != 0xff) { - return 0; - } + float d = mAgentPlanes[i].dist(sphere_center); - if (d > -radius) - { - res = 1; + if (d > radius) + { + return 0; + } + res = res || (d > -radius); } } - return res; + return res?1:2; } @@ -602,29 +615,20 @@ LLPlane planeFromPoints(LLVector3 p1, LLVector3 p2, LLVector3 p3) return LLPlane(p1, n); } -U8 LLCamera::calcPlaneMask(const LLPlane& plane) + +void LLCamera::ignoreAgentFrustumPlane(S32 idx) { - U8 mask = 0; - - if (plane.mV[0] >= 0) + if (idx < 0 || idx > (S32) mPlaneCount) { - mask |= 1; - } - if (plane.mV[1] >= 0) - { - mask |= 2; - } - if (plane.mV[2] >= 0) - { - mask |= 4; + return; } - return mask; + mPlaneMask[idx] = 0xff; + mAgentPlanes[idx].clear(); } void LLCamera::calcAgentFrustumPlanes(LLVector3* frust) { - for (int i = 0; i < 8; i++) { mAgentFrustum[i] = frust[i]; @@ -637,27 +641,27 @@ void LLCamera::calcAgentFrustumPlanes(LLVector3* frust) //order of planes is important, keep most likely to fail in the front of the list //near - frust[0], frust[1], frust[2] - mAgentPlanes[2].p = planeFromPoints(frust[0], frust[1], frust[2]); + mAgentPlanes[2] = planeFromPoints(frust[0], frust[1], frust[2]); //far - mAgentPlanes[5].p = planeFromPoints(frust[5], frust[4], frust[6]); + mAgentPlanes[5] = planeFromPoints(frust[5], frust[4], frust[6]); //left - mAgentPlanes[0].p = planeFromPoints(frust[4], frust[0], frust[7]); + mAgentPlanes[0] = planeFromPoints(frust[4], frust[0], frust[7]); //right - mAgentPlanes[1].p = planeFromPoints(frust[1], frust[5], frust[6]); + mAgentPlanes[1] = planeFromPoints(frust[1], frust[5], frust[6]); //top - mAgentPlanes[4].p = planeFromPoints(frust[3], frust[2], frust[6]); + mAgentPlanes[4] = planeFromPoints(frust[3], frust[2], frust[6]); //bottom - mAgentPlanes[3].p = planeFromPoints(frust[1], frust[0], frust[4]); + mAgentPlanes[3] = planeFromPoints(frust[1], frust[0], frust[4]); //cache plane octant facing mask for use in AABBInFrustum for (U32 i = 0; i < mPlaneCount; i++) { - mAgentPlanes[i].mask = calcPlaneMask(mAgentPlanes[i].p); + mPlaneMask[i] = mAgentPlanes[i].calcPlaneMask(); } } diff --git a/indra/llmath/llcamera.h b/indra/llmath/llcamera.h index 85b93dfc9..56afca025 100644 --- a/indra/llmath/llcamera.h +++ b/indra/llmath/llcamera.h @@ -70,6 +70,12 @@ class LLCamera : public LLCoordFrame { public: + + LLCamera(const LLCamera& rhs) + { + *this = rhs; + } + enum { PLANE_LEFT = 0, PLANE_RIGHT = 1, @@ -84,6 +90,17 @@ public: PLANE_TOP_MASK = (1< 0.f) ? 1.f : -1.f; + F32 new_foo = F32( S64(foo * bar + sign * 0.5f)); + new_foo /= bar; + + return new_foo; } inline F32 lerp(F32 a, F32 b, F32 u) @@ -522,4 +525,41 @@ inline F32 llgaussian(F32 x, F32 o) return 1.f/(F_SQRT_TWO_PI*o)*powf(F_E, -(x*x)/(2*o*o)); } +//helper function for removing outliers +template +inline void ll_remove_outliers(std::vector& data, F32 k) +{ + if (data.size() < 100) + { //not enough samples + return; + } + + VEC_TYPE Q1 = data[data.size()/4]; + VEC_TYPE Q3 = data[data.size()-data.size()/4-1]; + + VEC_TYPE min = (VEC_TYPE) ((F32) Q1-k * (F32) (Q3-Q1)); + VEC_TYPE max = (VEC_TYPE) ((F32) Q3+k * (F32) (Q3-Q1)); + + U32 i = 0; + while (i < data.size() && data[i] < min) + { + i++; + } + + S32 j = data.size()-1; + while (j > 0 && data[j] > max) + { + j--; + } + + if (j < data.size()-1) + { + data.erase(data.begin()+j, data.end()); + } + + if (i > 0) + { + data.erase(data.begin(), data.begin()+i); + } +} #endif diff --git a/indra/llmath/lloctree.h b/indra/llmath/lloctree.h index ced65d1d9..86589b87e 100644 --- a/indra/llmath/lloctree.h +++ b/indra/llmath/lloctree.h @@ -73,6 +73,13 @@ public: virtual void visit(const LLOctreeNode* branch) = 0; }; +template +class LLOctreeTravelerDepthFirst : public LLOctreeTraveler +{ +public: + virtual void traverse(const LLOctreeNode* node); +}; + template class LLOctreeNode : public LLTreeNode { @@ -124,11 +131,10 @@ public: inline void setParent(BaseType* parent) { mParent = (oct_node*) parent; } inline const LLVector3d& getCenter() const { return mCenter; } inline const LLVector3d& getSize() const { return mSize; } - inline void setCenter(LLVector3d center) { mCenter = center; } - inline void setSize(LLVector3d size) { mSize = size; } - inline oct_node* getNodeAt(T* data) { return getNodeAt(data->getPositionGroup(), data->getBinRadius()); } - inline U8 getOctant() const { return mOctant; } - inline void setOctant(U8 octant) { mOctant = octant; } + inline void setCenter(const LLVector3d center) { mCenter = center; } + inline void setSize(const LLVector3d size) { mSize = size; } + inline oct_node* getNodeAt(T* data) { return getNodeAt(data->getPositionGroup(), data->getBinRadius()); } + inline U8 getOctant() const { return mOctant; } inline const oct_node* getOctParent() const { return (const oct_node*) getParent(); } inline oct_node* getOctParent() { return (oct_node*) getParent(); } @@ -197,17 +203,17 @@ public: return contains(xform->getBinRadius()); } - bool contains(F64 radius) + bool contains(F32 radius) { if (mParent == NULL) { //root node contains nothing return false; } - F64 size = mSize.mdV[0]; - F64 p_size = size * 2.0; + F32 size = mSize[0]; + F32 p_size = size * 2.f; - return (radius <= 0.001 && size <= 0.001) || + return (radius <= 0.001f && size <= 0.001f) || (radius <= p_size && radius > size); } @@ -243,7 +249,30 @@ public: void accept(tree_traveler* visitor) const { visitor->visit(this); } void accept(oct_traveler* visitor) const { visitor->visit(this); } - oct_node* getNodeAt(const LLVector3d& pos, const F64& rad) + void validateChildMap() + { + for (U32 i = 0; i < 8; i++) + { + U8 idx = mChildMap[i]; + if (idx != 255) + { + LLOctreeNode* child = mChild[idx]; + + if (child->getOctant() != i) + { + llerrs << "Invalid child map, bad octant data." << llendl; + } + + if (getOctant(child->getCenter()) != child->getOctant()) + { + llerrs << "Invalid child octant compared to position data." << llendl; + } + } + } + } + + + oct_node* getNodeAt(const LLVector3d& pos, const F32& rad) { LLOctreeNode* node = this; @@ -251,24 +280,18 @@ public: { //do a quick search by octant U8 octant = node->getOctant(pos.mdV); - BOOL keep_going = TRUE; - + //traverse the tree until we find a node that has no node //at the appropriate octant or is smaller than the object. //by definition, that node is the smallest node that contains // the data - while (keep_going && node->getSize().mdV[0] >= rad) + U8 next_node = node->mChildMap[octant]; + + while (next_node != 255 && node->getSize()[0] >= rad) { - keep_going = FALSE; - for (U32 i = 0; i < node->getChildCount() && !keep_going; i++) - { - if (node->getChild(i)->getOctant() == octant) - { - node = node->getChild(i); - octant = node->getOctant(pos.mdV); - keep_going = TRUE; - } - } + node = node->getChild(next_node); + octant = node->getOctant(pos.mdV); + next_node = node->mChildMap[octant]; } } else if (!node->contains(rad) && node->getParent()) @@ -444,6 +467,9 @@ public: void clearChildren() { mChild.clear(); + + U32* foo = (U32*) mChildMap; + foo[0] = foo[1] = 0xFFFFFFFF; } void validate() @@ -477,6 +503,12 @@ public: void addChild(oct_node* child, BOOL silent = FALSE) { #if LL_OCTREE_PARANOIA_CHECK + + if (child->getSize() == getSize()) + { + OCT_ERRS << "Child size is same as parent size!" << llendl; + } + for (U32 i = 0; i < getChildCount(); i++) { if(mChild[i]->getSize() != child->getSize()) @@ -495,6 +527,8 @@ public: } #endif + mChildMap[child->getOctant()] = (U8) mChild.size(); + mChild.push_back(child); child->setParent(this); @@ -508,7 +542,7 @@ public: } } - void removeChild(U8 index, BOOL destroy = FALSE) + void removeChild(S32 index, BOOL destroy = FALSE) { for (U32 i = 0; i < this->getListenerCount(); i++) { @@ -516,6 +550,8 @@ public: listener->handleChildRemoval(this, getChild(index)); } + + if (destroy) { mChild[index]->destroy(); @@ -523,6 +559,15 @@ public: } mChild.erase(mChild.begin() + index); + //rebuild child map + U32* foo = (U32*) mChildMap; + foo[0] = foo[1] = 0xFFFFFFFF; + + for (U32 i = 0; i < mChild.size(); ++i) + { + mChildMap[mChild[i]->getOctant()] = i; + } + checkAlive(); } @@ -553,14 +598,27 @@ public: } protected: - child_list mChild; - element_list mData; - oct_node* mParent; + typedef enum + { + CENTER = 0, + SIZE = 1, + MAX = 2, + MIN = 3 + } eDName; + LLVector3d mCenter; LLVector3d mSize; LLVector3d mMax; LLVector3d mMin; + + oct_node* mParent; U8 mOctant; + + child_list mChild; + U8 mChildMap[8]; + + element_list mData; + }; //just like a regular node, except it might expand on insert and compress on balance @@ -571,8 +629,8 @@ public: typedef LLOctreeNode BaseType; typedef LLOctreeNode oct_node; - LLOctreeRoot( LLVector3d center, - LLVector3d size, + LLOctreeRoot( const LLVector3d ¢er, + const LLVector3d &size, BaseType* parent) : BaseType(center, size, parent) { @@ -604,6 +662,8 @@ public: //destroy child child->clearChildren(); delete child; + + return false; } return true; @@ -700,7 +760,6 @@ public: } }; - //======================== // LLOctreeTraveler //======================== @@ -714,4 +773,14 @@ void LLOctreeTraveler::traverse(const LLOctreeNode* node) } } +template +void LLOctreeTravelerDepthFirst::traverse(const LLOctreeNode* node) +{ + for (U32 i = 0; i < node->getChildCount(); i++) + { + traverse(node->getChild(i)); + } + node->accept(this); +} + #endif diff --git a/indra/llmath/llplane.h b/indra/llmath/llplane.h index 89c6a1460..8803d0774 100644 --- a/indra/llmath/llplane.h +++ b/indra/llmath/llplane.h @@ -48,13 +48,13 @@ public: LLPlane() {}; // no default constructor LLPlane(const LLVector3 &p0, F32 d) { setVec(p0, d); } LLPlane(const LLVector3 &p0, const LLVector3 &n) { setVec(p0, n); } - void setVec(const LLVector3 &p0, F32 d) { LLVector4::setVec(p0[0], p0[1], p0[2], d); } - void setVec(const LLVector3 &p0, const LLVector3 &n) + inline void setVec(const LLVector3 &p0, F32 d) { LLVector4::setVec(p0[0], p0[1], p0[2], d); } + inline void setVec(const LLVector3 &p0, const LLVector3 &n) { F32 d = -(p0 * n); setVec(n, d); } - void setVec(const LLVector3 &p0, const LLVector3 &p1, const LLVector3 &p2) + inline void setVec(const LLVector3 &p0, const LLVector3 &p1, const LLVector3 &p2) { LLVector3 u, v, w; u = p1 - p0; @@ -64,8 +64,39 @@ public: F32 d = -(w * p0); setVec(w, d); } - LLPlane& operator=(const LLVector4& v2) { LLVector4::setVec(v2[0],v2[1],v2[2],v2[3]); return *this;} + + inline LLPlane& operator=(const LLVector4& v2) { LLVector4::setVec(v2[0],v2[1],v2[2],v2[3]); return *this;} + + inline void set(const LLPlane& p2) { LLVector4::setVec(p2); } + + // F32 dist(const LLVector3 &v2) const { return mV[0]*v2[0] + mV[1]*v2[1] + mV[2]*v2[2] + mV[3]; } + + // reset the vector to 0, 0, 0, 1 + inline void clear() { LLVector4::setVec(0, 0, 0, 1); } + + inline void getVector3(LLVector3& vec) const { vec.set(mV[0], mV[1], mV[2]); } + + // Retrieve the mask indicating which of the x, y, or z axis are greater or equal to zero. + inline U8 calcPlaneMask() const + { + U8 mask = 0; + + if (mV[0] >= 0) + { + mask |= 1; + } + if (mV[1] >= 0) + { + mask |= 2; + } + if (mV[2] >= 0) + { + mask |= 4; + } + + return mask; + } }; diff --git a/indra/llmath/llquaternion.cpp b/indra/llmath/llquaternion.cpp index fdcc19d65..73c5f4505 100644 --- a/indra/llmath/llquaternion.cpp +++ b/indra/llmath/llquaternion.cpp @@ -32,9 +32,10 @@ #include "linden_common.h" +#include "llmath.h" // for F_PI + #include "llquaternion.h" -#include "llmath.h" // for F_PI //#include "vmath.h" #include "v3math.h" #include "v3dmath.h" diff --git a/indra/llmath/llquaternion.h b/indra/llmath/llquaternion.h index 0769f29f2..a7bb09fae 100644 --- a/indra/llmath/llquaternion.h +++ b/indra/llmath/llquaternion.h @@ -33,7 +33,11 @@ #ifndef LLQUATERNION_H #define LLQUATERNION_H -#include "llmath.h" +#include + +#ifndef LLMATH_H //enforce specific include order to avoid tangling inline dependencies +#error "Please include llmath.h first." +#endif class LLVector4; class LLVector3; diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index b3fdde257..8285a8175 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -103,27 +103,33 @@ BOOL check_same_clock_dir( const LLVector3& pt1, const LLVector3& pt2, const LLV BOOL LLLineSegmentBoxIntersect(const LLVector3& start, const LLVector3& end, const LLVector3& center, const LLVector3& size) { - float fAWdU[3]; - LLVector3 dir; - LLVector3 diff; + return LLLineSegmentBoxIntersect(start.mV, end.mV, center.mV, size.mV); +} + +BOOL LLLineSegmentBoxIntersect(const F32* start, const F32* end, const F32* center, const F32* size) +{ + F32 fAWdU[3]; + F32 dir[3]; + F32 diff[3]; for (U32 i = 0; i < 3; i++) { - dir.mV[i] = 0.5f * (end.mV[i] - start.mV[i]); - diff.mV[i] = (0.5f * (end.mV[i] + start.mV[i])) - center.mV[i]; - fAWdU[i] = fabsf(dir.mV[i]); - if(fabsf(diff.mV[i])>size.mV[i] + fAWdU[i]) return false; + dir[i] = 0.5f * (end[i] - start[i]); + diff[i] = (0.5f * (end[i] + start[i])) - center[i]; + fAWdU[i] = fabsf(dir[i]); + if(fabsf(diff[i])>size[i] + fAWdU[i]) return false; } float f; - f = dir.mV[1] * diff.mV[2] - dir.mV[2] * diff.mV[1]; if(fabsf(f)>size.mV[1]*fAWdU[2] + size.mV[2]*fAWdU[1]) return false; - f = dir.mV[2] * diff.mV[0] - dir.mV[0] * diff.mV[2]; if(fabsf(f)>size.mV[0]*fAWdU[2] + size.mV[2]*fAWdU[0]) return false; - f = dir.mV[0] * diff.mV[1] - dir.mV[1] * diff.mV[0]; if(fabsf(f)>size.mV[0]*fAWdU[1] + size.mV[1]*fAWdU[0]) return false; + f = dir[1] * diff[2] - dir[2] * diff[1]; if(fabsf(f)>size[1]*fAWdU[2] + size[2]*fAWdU[1]) return false; + f = dir[2] * diff[0] - dir[0] * diff[2]; if(fabsf(f)>size[0]*fAWdU[2] + size[2]*fAWdU[0]) return false; + f = dir[0] * diff[1] - dir[1] * diff[0]; if(fabsf(f)>size[0]*fAWdU[1] + size[1]*fAWdU[0]) return false; return true; } + // intersect test between triangle vert0, vert1, vert2 and a ray from orig in direction dir. // returns TRUE if intersecting and returns barycentric coordinates in intersection_a, intersection_b, // and returns the intersection point along dir in intersection_t. @@ -1688,7 +1694,8 @@ LLVolume::LLVolume(const LLVolumeParams ¶ms, const F32 detail, const BOOL ge mGenerateSingleFace = generate_single_face; generate(); - if (mParams.getSculptID().isNull() && params.getSculptType() == LL_SCULPT_TYPE_NONE) + + if (mParams.getSculptID().isNull() && mParams.getSculptType() == LL_SCULPT_TYPE_NONE) { createVolumeFaces(); } diff --git a/indra/llmath/llvolume.h b/indra/llmath/llvolume.h index ddfac18cd..7bae2749e 100644 --- a/indra/llmath/llvolume.h +++ b/indra/llmath/llvolume.h @@ -984,6 +984,7 @@ LLVector3 calc_binormal_from_triangle( const LLVector3& pos2, const LLVector2& tex2); +BOOL LLLineSegmentBoxIntersect(const F32* start, const F32* end, const F32* center, const F32* size); BOOL LLLineSegmentBoxIntersect(const LLVector3& start, const LLVector3& end, const LLVector3& center, const LLVector3& size); BOOL LLTriangleRayIntersect(const LLVector3& vert0, const LLVector3& vert1, const LLVector3& vert2, const LLVector3& orig, const LLVector3& dir, F32* intersection_a, F32* intersection_b, F32* intersection_t, BOOL two_sided); diff --git a/indra/llmath/m4math.cpp b/indra/llmath/m4math.cpp index d8e7b4aaf..74855bdc4 100644 --- a/indra/llmath/m4math.cpp +++ b/indra/llmath/m4math.cpp @@ -221,8 +221,33 @@ const LLMatrix4& LLMatrix4::transpose() F32 LLMatrix4::determinant() const { - llerrs << "Not implemented!" << llendl; - return 0.f; + F32 value = + mMatrix[0][3] * mMatrix[1][2] * mMatrix[2][1] * mMatrix[3][0] - + mMatrix[0][2] * mMatrix[1][3] * mMatrix[2][1] * mMatrix[3][0] - + mMatrix[0][3] * mMatrix[1][1] * mMatrix[2][2] * mMatrix[3][0] + + mMatrix[0][1] * mMatrix[1][3] * mMatrix[2][2] * mMatrix[3][0] + + mMatrix[0][2] * mMatrix[1][1] * mMatrix[2][3] * mMatrix[3][0] - + mMatrix[0][1] * mMatrix[1][2] * mMatrix[2][3] * mMatrix[3][0] - + mMatrix[0][3] * mMatrix[1][2] * mMatrix[2][0] * mMatrix[3][1] + + mMatrix[0][2] * mMatrix[1][3] * mMatrix[2][0] * mMatrix[3][1] + + mMatrix[0][3] * mMatrix[1][0] * mMatrix[2][2] * mMatrix[3][1] - + mMatrix[0][0] * mMatrix[1][3] * mMatrix[2][2] * mMatrix[3][1] - + mMatrix[0][2] * mMatrix[1][0] * mMatrix[2][3] * mMatrix[3][1] + + mMatrix[0][0] * mMatrix[1][2] * mMatrix[2][3] * mMatrix[3][1] + + mMatrix[0][3] * mMatrix[1][1] * mMatrix[2][0] * mMatrix[3][2] - + mMatrix[0][1] * mMatrix[1][3] * mMatrix[2][0] * mMatrix[3][2] - + mMatrix[0][3] * mMatrix[1][0] * mMatrix[2][1] * mMatrix[3][2] + + mMatrix[0][0] * mMatrix[1][3] * mMatrix[2][1] * mMatrix[3][2] + + mMatrix[0][1] * mMatrix[1][0] * mMatrix[2][3] * mMatrix[3][2] - + mMatrix[0][0] * mMatrix[1][1] * mMatrix[2][3] * mMatrix[3][2] - + mMatrix[0][2] * mMatrix[1][1] * mMatrix[2][0] * mMatrix[3][3] + + mMatrix[0][1] * mMatrix[1][2] * mMatrix[2][0] * mMatrix[3][3] + + mMatrix[0][2] * mMatrix[1][0] * mMatrix[2][1] * mMatrix[3][3] - + mMatrix[0][0] * mMatrix[1][2] * mMatrix[2][1] * mMatrix[3][3] - + mMatrix[0][1] * mMatrix[1][0] * mMatrix[2][2] * mMatrix[3][3] + + mMatrix[0][0] * mMatrix[1][1] * mMatrix[2][2] * mMatrix[3][3]; + + return value; } // Only works for pure orthonormal, homogeneous transform matrices. @@ -428,6 +453,17 @@ const LLMatrix4& LLMatrix4::initRotTrans(const LLQuaternion &q, const LLVector return (*this); } +const LLMatrix4& LLMatrix4::initScale(const LLVector3 &scale) +{ + setIdentity(); + + mMatrix[VX][VX] = scale.mV[VX]; + mMatrix[VY][VY] = scale.mV[VY]; + mMatrix[VZ][VZ] = scale.mV[VZ]; + + return (*this); +} + const LLMatrix4& LLMatrix4::initAll(const LLVector3 &scale, const LLQuaternion &q, const LLVector3 &pos) { F32 sx, sy, sz; @@ -774,6 +810,23 @@ bool operator!=(const LLMatrix4 &a, const LLMatrix4 &b) return FALSE; } +bool operator<(const LLMatrix4& a, const LLMatrix4 &b) +{ + U32 i, j; + for (i = 0; i < NUM_VALUES_IN_MAT4; i++) + { + for (j = 0; j < NUM_VALUES_IN_MAT4; j++) + { + if (a.mMatrix[i][j] != b.mMatrix[i][j]) + { + return a.mMatrix[i][j] < b.mMatrix[i][j]; + } + } + } + + return false; +} + const LLMatrix4& operator*=(LLMatrix4 &a, F32 k) { U32 i, j; @@ -813,4 +866,54 @@ std::ostream& operator<<(std::ostream& s, const LLMatrix4 &a) return s; } +LLSD LLMatrix4::getValue() const +{ + LLSD ret; + + ret[0] = mMatrix[0][0]; + ret[1] = mMatrix[0][1]; + ret[2] = mMatrix[0][2]; + ret[3] = mMatrix[0][3]; + + ret[4] = mMatrix[1][0]; + ret[5] = mMatrix[1][1]; + ret[6] = mMatrix[1][2]; + ret[7] = mMatrix[1][3]; + + ret[8] = mMatrix[2][0]; + ret[9] = mMatrix[2][1]; + ret[10] = mMatrix[2][2]; + ret[11] = mMatrix[2][3]; + + ret[12] = mMatrix[3][0]; + ret[13] = mMatrix[3][1]; + ret[14] = mMatrix[3][2]; + ret[15] = mMatrix[3][3]; + + return ret; +} + +void LLMatrix4::setValue(const LLSD& data) +{ + mMatrix[0][0] = data[0].asReal(); + mMatrix[0][1] = data[1].asReal(); + mMatrix[0][2] = data[2].asReal(); + mMatrix[0][3] = data[3].asReal(); + + mMatrix[1][0] = data[4].asReal(); + mMatrix[1][1] = data[5].asReal(); + mMatrix[1][2] = data[6].asReal(); + mMatrix[1][3] = data[7].asReal(); + + mMatrix[2][0] = data[8].asReal(); + mMatrix[2][1] = data[9].asReal(); + mMatrix[2][2] = data[10].asReal(); + mMatrix[2][3] = data[11].asReal(); + + mMatrix[3][0] = data[12].asReal(); + mMatrix[3][1] = data[13].asReal(); + mMatrix[3][2] = data[14].asReal(); + mMatrix[3][3] = data[15].asReal(); +} + diff --git a/indra/llmath/m4math.h b/indra/llmath/m4math.h index e74b7afe9..27e4be4b4 100644 --- a/indra/llmath/m4math.h +++ b/indra/llmath/m4math.h @@ -125,6 +125,8 @@ public: ~LLMatrix4(void); // Destructor + LLSD getValue() const; + void setValue(const LLSD&); ////////////////////////////// // @@ -138,6 +140,7 @@ public: // various useful matrix functions const LLMatrix4& setIdentity(); // Load identity matrix + bool isIdentity() const; const LLMatrix4& setZero(); // Clears matrix to all zeros. const LLMatrix4& initRotation(const F32 angle, const F32 x, const F32 y, const F32 z); // Calculate rotation matrix by rotating angle radians about (x, y, z) @@ -159,6 +162,7 @@ public: const LLMatrix4& initRotTrans(const F32 roll, const F32 pitch, const F32 yaw, const LLVector4 &pos); // Rotation from Euler + translation const LLMatrix4& initRotTrans(const LLQuaternion &q, const LLVector4 &pos); // Set with Quaternion and position + const LLMatrix4& initScale(const LLVector3 &scale); // Set all const LLMatrix4& initAll(const LLVector3 &scale, const LLQuaternion &q, const LLVector3 &pos); @@ -236,6 +240,7 @@ public: friend bool operator==(const LLMatrix4 &a, const LLMatrix4 &b); // Return a == b friend bool operator!=(const LLMatrix4 &a, const LLMatrix4 &b); // Return a != b + friend bool operator<(const LLMatrix4 &a, const LLMatrix4& b); // Return a < b friend const LLMatrix4& operator+=(LLMatrix4 &a, const LLMatrix4 &b); // Return a + b friend const LLMatrix4& operator-=(LLMatrix4 &a, const LLMatrix4 &b); // Return a - b @@ -269,6 +274,30 @@ inline const LLMatrix4& LLMatrix4::setIdentity() return (*this); } +inline bool LLMatrix4::isIdentity() const +{ + return + mMatrix[0][0] == 1.f && + mMatrix[0][1] == 0.f && + mMatrix[0][2] == 0.f && + mMatrix[0][3] == 0.f && + + mMatrix[1][0] == 0.f && + mMatrix[1][1] == 1.f && + mMatrix[1][2] == 0.f && + mMatrix[1][3] == 0.f && + + mMatrix[2][0] == 0.f && + mMatrix[2][1] == 0.f && + mMatrix[2][2] == 1.f && + mMatrix[2][3] == 0.f && + + mMatrix[3][0] == 0.f && + mMatrix[3][1] == 0.f && + mMatrix[3][2] == 0.f && + mMatrix[3][3] == 1.f; +} + /* inline LLMatrix4 operator*(const LLMatrix4 &a, const LLMatrix4 &b) diff --git a/indra/llmath/v2math.cpp b/indra/llmath/v2math.cpp index 555e1f92b..220336e0c 100644 --- a/indra/llmath/v2math.cpp +++ b/indra/llmath/v2math.cpp @@ -115,3 +115,18 @@ LLVector2 lerp(const LLVector2 &a, const LLVector2 &b, F32 u) a.mV[VX] + (b.mV[VX] - a.mV[VX]) * u, a.mV[VY] + (b.mV[VY] - a.mV[VY]) * u ); } + +LLSD LLVector2::getValue() const +{ + LLSD ret; + ret[0] = mV[0]; + ret[1] = mV[1]; + return ret; +} + +void LLVector2::setValue(LLSD& sd) +{ + mV[0] = (F32) sd[0].asReal(); + mV[1] = (F32) sd[1].asReal(); +} + diff --git a/indra/llmath/v2math.h b/indra/llmath/v2math.h index 65f371431..ae26c85ce 100644 --- a/indra/llmath/v2math.h +++ b/indra/llmath/v2math.h @@ -66,6 +66,9 @@ class LLVector2 void set(const LLVector2 &vec); // Sets LLVector2 to vec void set(const F32 *vec); // Sets LLVector2 to vec + LLSD getValue() const; + void setValue(LLSD& sd); + void setVec(F32 x, F32 y); // deprecated void setVec(const LLVector2 &vec); // deprecated void setVec(const F32 *vec); // deprecated diff --git a/indra/llmath/v3math.cpp b/indra/llmath/v3math.cpp index 63683ed49..daabbcc37 100644 --- a/indra/llmath/v3math.cpp +++ b/indra/llmath/v3math.cpp @@ -140,6 +140,21 @@ BOOL LLVector3::clampLength( F32 length_limit ) return changed; } +BOOL LLVector3::clamp(const LLVector3 &min_vec, const LLVector3 &max_vec) +{ + BOOL ret = FALSE; + + if (mV[0] < min_vec[0]) { mV[0] = min_vec[0]; ret = TRUE; } + if (mV[1] < min_vec[1]) { mV[1] = min_vec[1]; ret = TRUE; } + if (mV[2] < min_vec[2]) { mV[2] = min_vec[2]; ret = TRUE; } + + if (mV[0] > max_vec[0]) { mV[0] = max_vec[0]; ret = TRUE; } + if (mV[1] > max_vec[1]) { mV[1] = max_vec[1]; ret = TRUE; } + if (mV[2] > max_vec[2]) { mV[2] = max_vec[2]; ret = TRUE; } + + return ret; +} + // Sets all values to absolute value of their original values // Returns TRUE if data changed @@ -197,6 +212,28 @@ const LLVector3& LLVector3::rotVec(const LLQuaternion &q) return *this; } +const LLVector3& LLVector3::transVec(const LLMatrix4& mat) +{ + setVec( + mV[VX] * mat.mMatrix[VX][VX] + + mV[VY] * mat.mMatrix[VX][VY] + + mV[VZ] * mat.mMatrix[VX][VZ] + + mat.mMatrix[VX][VW], + + mV[VX] * mat.mMatrix[VY][VX] + + mV[VY] * mat.mMatrix[VY][VY] + + mV[VZ] * mat.mMatrix[VY][VZ] + + mat.mMatrix[VY][VW], + + mV[VX] * mat.mMatrix[VZ][VX] + + mV[VY] * mat.mMatrix[VZ][VY] + + mV[VZ] * mat.mMatrix[VZ][VZ] + + mat.mMatrix[VZ][VW]); + + return *this; +} + + const LLVector3& LLVector3::rotVec(F32 angle, const LLVector3 &vec) { if ( !vec.isExactlyZero() && angle ) diff --git a/indra/llmath/v3math.h b/indra/llmath/v3math.h index e1461f29d..1cfa1edaa 100644 --- a/indra/llmath/v3math.h +++ b/indra/llmath/v3math.h @@ -40,6 +40,7 @@ class LLVector2; class LLVector4; class LLMatrix3; +class LLMatrix4; class LLVector3d; class LLQuaternion; @@ -75,6 +76,7 @@ class LLVector3 inline BOOL isFinite() const; // checks to see if all values of LLVector3 are finite BOOL clamp(F32 min, F32 max); // Clamps all values to (min,max), returns TRUE if data changed + BOOL clamp(const LLVector3 &min_vec, const LLVector3 &max_vec); // Scales vector by another vector BOOL clampLength( F32 length_limit ); // Scales vector to limit length to a value void quantize16(F32 lowerxy, F32 upperxy, F32 lowerz, F32 upperz); // changes the vector to reflect quatization @@ -115,6 +117,7 @@ class LLVector3 const LLVector3& rotVec(F32 angle, F32 x, F32 y, F32 z); // Rotates about x,y,z by angle radians const LLVector3& rotVec(const LLMatrix3 &mat); // Rotates by LLMatrix4 mat const LLVector3& rotVec(const LLQuaternion &q); // Rotates by LLQuaternion q + const LLVector3& transVec(const LLMatrix4& mat); // Transforms by LLMatrix4 mat (mat * v) const LLVector3& scaleVec(const LLVector3& vec); // scales per component by vec LLVector3 scaledVec(const LLVector3& vec) const; // get a copy of this vector scaled by vec @@ -162,6 +165,8 @@ F32 dist_vec(const LLVector3 &a, const LLVector3 &b); // Returns distance betwe F32 dist_vec_squared(const LLVector3 &a, const LLVector3 &b);// Returns distance squared between a and b F32 dist_vec_squared2D(const LLVector3 &a, const LLVector3 &b);// Returns distance squared between a and b ignoring Z component LLVector3 projected_vec(const LLVector3 &a, const LLVector3 &b); // Returns vector a projected on vector b +LLVector3 parallel_component(const LLVector3 &a, const LLVector3 &b); // Returns vector a projected on vector b (same as projected_vec) +LLVector3 orthogonal_component(const LLVector3 &a, const LLVector3 &b); // Returns component of vector a not parallel to vector b (same as projected_vec) LLVector3 lerp(const LLVector3 &a, const LLVector3 &b, F32 u); // Returns a vector that is a linear interpolation between a and b inline LLVector3::LLVector3(void) @@ -496,6 +501,17 @@ inline LLVector3 projected_vec(const LLVector3 &a, const LLVector3 &b) return project_axis * (a * project_axis); } +inline LLVector3 parallel_component(const LLVector3 &a, const LLVector3 &b) +{ + return projected_vec(a, b); +} + +inline LLVector3 orthogonal_component(const LLVector3 &a, const LLVector3 &b) +{ + return a - projected_vec(a, b); +} + + inline LLVector3 lerp(const LLVector3 &a, const LLVector3 &b, F32 u) { return LLVector3( @@ -529,6 +545,21 @@ inline void update_min_max(LLVector3& min, LLVector3& max, const LLVector3& pos) } } +inline void update_min_max(LLVector3& min, LLVector3& max, const F32* pos) +{ + for (U32 i = 0; i < 3; i++) + { + if (min.mV[i] > pos[i]) + { + min.mV[i] = pos[i]; + } + if (max.mV[i] < pos[i]) + { + max.mV[i] = pos[i]; + } + } +} + inline F32 angle_between(const LLVector3& a, const LLVector3& b) { LLVector3 an = a; diff --git a/indra/llmath/v4color.h b/indra/llmath/v4color.h index 5d8e2ad9f..f5a9adcfc 100644 --- a/indra/llmath/v4color.h +++ b/indra/llmath/v4color.h @@ -114,6 +114,7 @@ class LLColor4 const LLColor4& operator=(const LLColor3 &a); // Assigns vec3 to vec4 and returns vec4 + bool operator<(const LLColor4& rhs) const; friend std::ostream& operator<<(std::ostream& s, const LLColor4 &a); // Print a friend LLColor4 operator+(const LLColor4 &a, const LLColor4 &b); // Return vector a + b friend LLColor4 operator-(const LLColor4 &a, const LLColor4 &b); // Return vector a minus b @@ -595,6 +596,23 @@ inline LLColor4 lerp(const LLColor4 &a, const LLColor4 &b, F32 u) a.mV[VW] + (b.mV[VW] - a.mV[VW]) * u); } +inline bool LLColor4::operator<(const LLColor4& rhs) const +{ + if (mV[0] != rhs.mV[0]) + { + return mV[0] < rhs.mV[0]; + } + if (mV[1] != rhs.mV[1]) + { + return mV[1] < rhs.mV[1]; + } + if (mV[2] != rhs.mV[2]) + { + return mV[2] < rhs.mV[2]; + } + + return mV[3] < rhs.mV[3]; +} void LLColor4::clamp() { diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp index 38b2bea1b..6b8e86b94 100644 --- a/indra/llmessage/llcurl.cpp +++ b/indra/llmessage/llcurl.cpp @@ -55,8 +55,8 @@ #include "llstl.h" #include "llsdserialize.h" #include "llthread.h" - #include "llsocks5.h" +#include "lltimer.h" ////////////////////////////////////////////////////////////////////////////// /* @@ -92,6 +92,26 @@ std::vector LLCurl::sSSLMutex; std::string LLCurl::sCAPath; std::string LLCurl::sCAFile; +void check_curl_code(CURLcode code) +{ + if (code != CURLE_OK) + { + // linux appears to throw a curl error once per session for a bad initialization + // at a pretty random time (when enabling cookies). + llinfos << "curl error detected: " << curl_easy_strerror(code) << llendl; + } +} + +void check_curl_multi_code(CURLMcode code) +{ + if (code != CURLM_OK) + { + // linux appears to throw a curl error once per session for a bad initialization + // at a pretty random time (when enabling cookies). + llinfos << "curl multi error detected: " << curl_multi_strerror(code) << llendl; + } +} + //static void LLCurl::setCAPath(const std::string& path) { @@ -241,7 +261,12 @@ public: void resetState(); + static CURL* allocEasyHandle(); + static void releaseEasyHandle(CURL* handle); + private: + friend class LLCurl; + CURL* mCurlEasyHandle; struct curl_slist* mHeaders; @@ -256,8 +281,62 @@ private: std::vector mStrings; ResponderPtr mResponder; + + static std::set sFreeHandles; + static std::set sActiveHandles; + static LLMutex* sHandleMutex; }; +std::set LLCurl::Easy::sFreeHandles; +std::set LLCurl::Easy::sActiveHandles; +LLMutex* LLCurl::Easy::sHandleMutex = NULL; + + +//static +CURL* LLCurl::Easy::allocEasyHandle() +{ + CURL* ret = NULL; + LLMutexLock lock(sHandleMutex); + if (sFreeHandles.empty()) + { + ret = curl_easy_init(); + } + else + { + ret = *(sFreeHandles.begin()); + sFreeHandles.erase(ret); + curl_easy_reset(ret); + } + + if (ret) + { + sActiveHandles.insert(ret); + } + + return ret; +} + +//static +void LLCurl::Easy::releaseEasyHandle(CURL* handle) +{ + if (!handle) + { + llerrs << "handle cannot be NULL!" << llendl; + } + + LLMutexLock lock(sHandleMutex); + + if (sActiveHandles.find(handle) != sActiveHandles.end()) + { + sActiveHandles.erase(handle); + sFreeHandles.insert(handle); + } + else + { + llerrs << "Invalid handle." << llendl; + } +} + LLCurl::Easy::Easy() : mHeaders(NULL), mCurlEasyHandle(NULL) @@ -268,18 +347,20 @@ LLCurl::Easy::Easy() LLCurl::Easy* LLCurl::Easy::getEasy() { Easy* easy = new Easy(); - easy->mCurlEasyHandle = curl_easy_init(); + easy->mCurlEasyHandle = allocEasyHandle(); + if (!easy->mCurlEasyHandle) { // this can happen if we have too many open files (fails in c-ares/ares_init.c) - llwarns << "curl_multi_init() returned NULL! Easy handles: " << gCurlEasyCount << " Multi handles: " << gCurlMultiCount << llendl; + llwarns << "allocEasyHandle() returned NULL! Easy handles: " << gCurlEasyCount << " Multi handles: " << gCurlMultiCount << llendl; delete easy; return NULL; } - // set no DMS caching as default for all easy handles. This prevents them adopting a + // set no DNS caching as default for all easy handles. This prevents them adopting a // multi handles cache if they are added to one. - curl_easy_setopt(easy->mCurlEasyHandle, CURLOPT_DNS_CACHE_TIMEOUT, 0); + CURLcode result = curl_easy_setopt(easy->mCurlEasyHandle, CURLOPT_DNS_CACHE_TIMEOUT, 0); + check_curl_code(result); if (LLSocks::getInstance()->isHttpProxyEnabled()) { @@ -305,7 +386,7 @@ LLCurl::Easy* LLCurl::Easy::getEasy() LLCurl::Easy::~Easy() { - curl_easy_cleanup(mCurlEasyHandle); + releaseEasyHandle(mCurlEasyHandle); --gCurlEasyCount; curl_slist_free_all(mHeaders); for_each(mStrings.begin(), mStrings.end(), DeletePointerArray()); @@ -364,9 +445,9 @@ void LLCurl::Easy::setHeaders() void LLCurl::Easy::getTransferInfo(LLCurl::TransferInfo* info) { - curl_easy_getinfo(mCurlEasyHandle, CURLINFO_SIZE_DOWNLOAD, &info->mSizeDownload); - curl_easy_getinfo(mCurlEasyHandle, CURLINFO_TOTAL_TIME, &info->mTotalTime); - curl_easy_getinfo(mCurlEasyHandle, CURLINFO_SPEED_DOWNLOAD, &info->mSpeedDownload); + check_curl_code(curl_easy_getinfo(mCurlEasyHandle, CURLINFO_SIZE_DOWNLOAD, &info->mSizeDownload)); + check_curl_code(curl_easy_getinfo(mCurlEasyHandle, CURLINFO_TOTAL_TIME, &info->mTotalTime)); + check_curl_code(curl_easy_getinfo(mCurlEasyHandle, CURLINFO_SPEED_DOWNLOAD, &info->mSpeedDownload)); } U32 LLCurl::Easy::report(CURLcode code) @@ -376,13 +457,14 @@ U32 LLCurl::Easy::report(CURLcode code) if (code == CURLE_OK) { - curl_easy_getinfo(mCurlEasyHandle, CURLINFO_RESPONSE_CODE, &responseCode); + check_curl_code(curl_easy_getinfo(mCurlEasyHandle, CURLINFO_RESPONSE_CODE, &responseCode)); //*TODO: get reason from first line of mHeaderOutput } else { responseCode = 499; responseReason = strerror(code) + " : " + mErrorBuffer; + setopt(CURLOPT_FRESH_CONNECT, TRUE); } if (mResponder) @@ -398,17 +480,20 @@ U32 LLCurl::Easy::report(CURLcode code) // Note: these all assume the caller tracks the value (i.e. keeps it persistant) void LLCurl::Easy::setopt(CURLoption option, S32 value) { - curl_easy_setopt(mCurlEasyHandle, option, value); + CURLcode result = curl_easy_setopt(mCurlEasyHandle, option, value); + check_curl_code(result); } void LLCurl::Easy::setopt(CURLoption option, void* value) { - curl_easy_setopt(mCurlEasyHandle, option, value); + CURLcode result = curl_easy_setopt(mCurlEasyHandle, option, value); + check_curl_code(result); } void LLCurl::Easy::setopt(CURLoption option, char* value) { - curl_easy_setopt(mCurlEasyHandle, option, value); + CURLcode result = curl_easy_setopt(mCurlEasyHandle, option, value); + check_curl_code(result); } // Note: this copies the string so that the caller does not have to keep it around @@ -417,7 +502,8 @@ void LLCurl::Easy::setoptString(CURLoption option, const std::string& value) char* tstring = new char[value.length()+1]; strcpy(tstring, value.c_str()); mStrings.push_back(tstring); - curl_easy_setopt(mCurlEasyHandle, option, tstring); + CURLcode result = curl_easy_setopt(mCurlEasyHandle, option, tstring); + check_curl_code(result); } void LLCurl::Easy::slist_append(const char* str) @@ -510,6 +596,9 @@ void LLCurl::Easy::prepRequest(const std::string& url, setCA(); setopt(CURLOPT_SSL_VERIFYPEER, true); + + //don't verify host name so urls with scrubbed host names will work (improves DNS performance) + setopt(CURLOPT_SSL_VERIFYHOST, 0); setopt(CURLOPT_TIMEOUT, CURL_REQUEST_TIMEOUT); setoptString(CURLOPT_URL, url); @@ -586,7 +675,7 @@ LLCurl::Multi::~Multi() iter != mEasyActiveList.end(); ++iter) { Easy* easy = *iter; - curl_multi_remove_handle(mCurlMultiHandle, easy->getCurlHandle()); + check_curl_multi_code(curl_multi_remove_handle(mCurlMultiHandle, easy->getCurlHandle())); delete easy; } mEasyActiveList.clear(); @@ -596,7 +685,7 @@ LLCurl::Multi::~Multi() for_each(mEasyFreeList.begin(), mEasyFreeList.end(), DeletePointer()); mEasyFreeList.clear(); - curl_multi_cleanup(mCurlMultiHandle); + check_curl_multi_code(curl_multi_cleanup(mCurlMultiHandle)); --gCurlMultiCount; } @@ -617,8 +706,10 @@ S32 LLCurl::Multi::perform() CURLMcode code = curl_multi_perform(mCurlMultiHandle, &q); if (CURLM_CALL_MULTI_PERFORM != code || q == 0) { + check_curl_multi_code(code); break; } + } mQueued = q; return q; @@ -685,11 +776,12 @@ LLCurl::Easy* LLCurl::Multi::allocEasy() bool LLCurl::Multi::addEasy(Easy* easy) { CURLMcode mcode = curl_multi_add_handle(mCurlMultiHandle, easy->getCurlHandle()); - if (mcode != CURLM_OK) - { - llwarns << "Curl Error: " << curl_multi_strerror(mcode) << llendl; - return false; - } + check_curl_multi_code(mcode); + //if (mcode != CURLM_OK) + //{ + // llwarns << "Curl Error: " << curl_multi_strerror(mcode) << llendl; + // return false; + //} return true; } @@ -710,22 +802,14 @@ void LLCurl::Multi::easyFree(Easy* easy) void LLCurl::Multi::removeEasy(Easy* easy) { - curl_multi_remove_handle(mCurlMultiHandle, easy->getCurlHandle()); + check_curl_multi_code(curl_multi_remove_handle(mCurlMultiHandle, easy->getCurlHandle())); easyFree(easy); } //static std::string LLCurl::strerror(CURLcode errorcode) { -#if LL_DARWIN - // curl_easy_strerror was added in libcurl 7.12.0. Unfortunately, the version in the Mac OS X 10.3.9 SDK is 7.10.2... - // There's a problem with the custom curl headers in our build that keeps me from #ifdefing this on the libcurl version number - // (the correct check would be #if LIBCURL_VERSION_NUM >= 0x070c00). We'll fix the header problem soon, but for now - // just punt and print the numeric error code on the Mac. - return llformat("%d", errorcode); -#else // LL_DARWIN return std::string(curl_easy_strerror(errorcode)); -#endif // LL_DARWIN } //////////////////////////////////////////////////////////////////////////// @@ -737,6 +821,7 @@ LLCurlRequest::LLCurlRequest() : mActiveRequestCount(0) { mThreadID = LLThread::currentID(); + mProcessing = FALSE; } LLCurlRequest::~LLCurlRequest() @@ -771,6 +856,11 @@ LLCurl::Easy* LLCurlRequest::allocEasy() bool LLCurlRequest::addEasy(LLCurl::Easy* easy) { llassert_always(mActiveMulti); + + if (mProcessing) + { + llerrs << "Posting to a LLCurlRequest instance from within a responder is not allowed (causes DNS timeouts)." << llendl; + } bool res = mActiveMulti->addEasy(easy); return res; } @@ -828,12 +918,41 @@ bool LLCurlRequest::post(const std::string& url, bool res = addEasy(easy); return res; } + +bool LLCurlRequest::post(const std::string& url, + const headers_t& headers, + const std::string& data, + LLCurl::ResponderPtr responder) +{ + LLCurl::Easy* easy = allocEasy(); + if (!easy) + { + return false; + } + easy->prepRequest(url, headers, responder); + + easy->getInput().write(data.data(), data.size()); + S32 bytes = easy->getInput().str().length(); + easy->setopt(CURLOPT_POST, 1); + easy->setopt(CURLOPT_POSTFIELDS, (void*)NULL); + easy->setopt(CURLOPT_POSTFIELDSIZE, bytes); + + easy->slist_append("Content-Type: application/octet-stream"); + easy->setHeaders(); + + lldebugs << "POSTING: " << bytes << " bytes." << llendl; + bool res = addEasy(easy); + return res; +} + // Note: call once per frame S32 LLCurlRequest::process() { llassert_always(mThreadID == LLThread::currentID()); S32 res = 0; + + mProcessing = TRUE; for (curlmulti_set_t::iterator iter = mMultiSet.begin(); iter != mMultiSet.end(); ) { @@ -847,6 +966,7 @@ S32 LLCurlRequest::process() delete multi; } } + mProcessing = FALSE; return res; } @@ -1076,8 +1196,12 @@ void LLCurl::initClass() // Do not change this "unless you are familiar with and mean to control // internal operations of libcurl" // - http://curl.haxx.se/libcurl/c/curl_global_init.html - curl_global_init(CURL_GLOBAL_ALL); + CURLcode code = curl_global_init(CURL_GLOBAL_ALL); + + check_curl_code(code); + Easy::sHandleMutex = new LLMutex; + #if SAFE_SSL S32 mutex_count = CRYPTO_num_locks(); for (S32 i=0; i::iterator iter = Easy::sFreeHandles.begin(); iter != Easy::sFreeHandles.end(); ++iter) + { + CURL* curl = *iter; + curl_easy_cleanup(curl); + } + + Easy::sFreeHandles.clear(); + + llassert(Easy::sActiveHandles.empty()); } const unsigned int LLCurl::MAX_REDIRECTS = 5; diff --git a/indra/llmessage/llcurl.h b/indra/llmessage/llcurl.h index 99ac1ffdd..084408c70 100644 --- a/indra/llmessage/llcurl.h +++ b/indra/llmessage/llcurl.h @@ -207,6 +207,8 @@ public: void get(const std::string& url, LLCurl::ResponderPtr responder); bool getByteRange(const std::string& url, const headers_t& headers, S32 offset, S32 length, LLCurl::ResponderPtr responder); bool post(const std::string& url, const headers_t& headers, const LLSD& data, LLCurl::ResponderPtr responder); + bool post(const std::string& url, const headers_t& headers, const std::string& data, LLCurl::ResponderPtr responder); + S32 process(); S32 getQueued(); @@ -220,6 +222,7 @@ private: curlmulti_set_t mMultiSet; LLCurl::Multi* mActiveMulti; S32 mActiveRequestCount; + BOOL mProcessing; U32 mThreadID; // debug }; diff --git a/indra/llmessage/llnetcanary.cpp b/indra/llmessage/llnetcanary.cpp index a714c60f2..57ee6d3a6 100644 --- a/indra/llmessage/llnetcanary.cpp +++ b/indra/llmessage/llnetcanary.cpp @@ -1,6 +1,6 @@ // -#include "llnetcanary.h" #include "linden_common.h" +#include "llnetcanary.h" #include "llerror.h" #ifdef _MSC_VER #include diff --git a/indra/llmessage/llsdmessagebuilder.cpp b/indra/llmessage/llsdmessagebuilder.cpp index 6e41b0389..2680dd0b7 100644 --- a/indra/llmessage/llsdmessagebuilder.cpp +++ b/indra/llmessage/llsdmessagebuilder.cpp @@ -35,6 +35,7 @@ #include "llsdmessagebuilder.h" #include "llmessagetemplate.h" +#include "llmath.h" #include "llquaternion.h" #include "llsdutil.h" #include "llsdutil_math.h" diff --git a/indra/llmessage/llservicebuilder.cpp b/indra/llmessage/llservicebuilder.cpp index 51404a35b..449848053 100644 --- a/indra/llmessage/llservicebuilder.cpp +++ b/indra/llmessage/llservicebuilder.cpp @@ -94,7 +94,7 @@ bool starts_with(const std::string& text, const char* prefix) // TODO: Build a real services.xml for windows development. // and remove the base_url logic below. -std::string LLServiceBuilder::buildServiceURI(const std::string& service_name) +std::string LLServiceBuilder::buildServiceURI(const std::string& service_name) const { std::ostringstream service_url; // Find the service builder @@ -132,7 +132,7 @@ std::string LLServiceBuilder::buildServiceURI(const std::string& service_name) std::string LLServiceBuilder::buildServiceURI( const std::string& service_name, - const LLSD& option_map) + const LLSD& option_map) const { return russ_format(buildServiceURI(service_name), option_map); } diff --git a/indra/llmessage/llservicebuilder.h b/indra/llmessage/llservicebuilder.h index 4670438bc..47476774a 100644 --- a/indra/llmessage/llservicebuilder.h +++ b/indra/llmessage/llservicebuilder.h @@ -76,7 +76,7 @@ public: * * @param service_name The name of the service you want to call. */ - std::string buildServiceURI(const std::string& service_name); + std::string buildServiceURI(const std::string& service_name) const; /** * @brief Build a service url if the url with construction parameters. @@ -88,7 +88,7 @@ public: */ std::string buildServiceURI( const std::string& service_name, - const LLSD& option_map); + const LLSD& option_map) const; public: /** diff --git a/indra/llmessage/llsocks5.cpp b/indra/llmessage/llsocks5.cpp index 7326e806b..d21412f86 100644 --- a/indra/llmessage/llsocks5.cpp +++ b/indra/llmessage/llsocks5.cpp @@ -30,13 +30,12 @@ * $/LicenseInfo$ */ -#include - #include "linden_common.h" #include "net.h" #include "llhost.h" #include "message.h" #include "llsocks5.h" +#include // Static class variable instances diff --git a/indra/llmessage/lltemplatemessagebuilder.cpp b/indra/llmessage/lltemplatemessagebuilder.cpp index fa02456d9..6f9707ed5 100644 --- a/indra/llmessage/lltemplatemessagebuilder.cpp +++ b/indra/llmessage/lltemplatemessagebuilder.cpp @@ -35,6 +35,7 @@ #include "lltemplatemessagebuilder.h" #include "llmessagetemplate.h" +#include "llmath.h" #include "llquaternion.h" #include "u64.h" #include "v3dmath.h" diff --git a/indra/llmessage/lltemplatemessagereader.cpp b/indra/llmessage/lltemplatemessagereader.cpp index c95132437..93de1b13d 100644 --- a/indra/llmessage/lltemplatemessagereader.cpp +++ b/indra/llmessage/lltemplatemessagereader.cpp @@ -36,6 +36,7 @@ #include "llfasttimer.h" #include "llmessagebuilder.h" #include "llmessagetemplate.h" +#include "llmath.h" #include "llquaternion.h" #include "message.h" #include "u64.h" diff --git a/indra/llmessage/message.cpp b/indra/llmessage/message.cpp index d0572fb4a..5a3d78452 100644 --- a/indra/llmessage/message.cpp +++ b/indra/llmessage/message.cpp @@ -2469,12 +2469,12 @@ void dump_prehash_files() " * Generated from message template version number %.3f\n" " */\n", gMessageSystem->mMessageFileVersionNumber); - fprintf(fp, "\n\nextern F32 gPrehashVersionNumber;\n\n"); + fprintf(fp, "\n\nextern F32 const gPrehashVersionNumber;\n\n"); for (i = 0; i < MESSAGE_NUMBER_OF_HASH_BUCKETS; i++) { if (!LLMessageStringTable::getInstance()->mEmpty[i] && LLMessageStringTable::getInstance()->mString[i][0] != '.') { - fprintf(fp, "extern char * _PREHASH_%s;\n", LLMessageStringTable::getInstance()->mString[i]); + fprintf(fp, "extern char const* const _PREHASH_%s;\n", LLMessageStringTable::getInstance()->mString[i]); } } fprintf(fp, "\n\n#endif\n"); @@ -2499,12 +2499,12 @@ void dump_prehash_files() gMessageSystem->mMessageFileVersionNumber); fprintf(fp, "#include \"linden_common.h\"\n"); fprintf(fp, "#include \"message.h\"\n\n"); - fprintf(fp, "\n\nF32 gPrehashVersionNumber = %.3ff;\n\n", gMessageSystem->mMessageFileVersionNumber); + fprintf(fp, "\n\nF32 const gPrehashVersionNumber = %.3ff;\n\n", gMessageSystem->mMessageFileVersionNumber); for (i = 0; i < MESSAGE_NUMBER_OF_HASH_BUCKETS; i++) { if (!LLMessageStringTable::getInstance()->mEmpty[i] && LLMessageStringTable::getInstance()->mString[i][0] != '.') { - fprintf(fp, "char * _PREHASH_%s = LLMessageStringTable::getInstance()->getString(\"%s\");\n", LLMessageStringTable::getInstance()->mString[i], LLMessageStringTable::getInstance()->mString[i]); + fprintf(fp, "char const* const _PREHASH_%s = LLMessageStringTable::getInstance()->getString(\"%s\");\n", LLMessageStringTable::getInstance()->mString[i], LLMessageStringTable::getInstance()->mString[i]); } } fclose(fp); diff --git a/indra/llmessage/sound_ids.cpp b/indra/llmessage/sound_ids.cpp index 028ef8fc1..9262a33b3 100644 --- a/indra/llmessage/sound_ids.cpp +++ b/indra/llmessage/sound_ids.cpp @@ -34,259 +34,281 @@ #include "lluuid.h" -LLUUID const SND_NULL = LLUUID::null; -LLUUID const SND_RIDE ("00000000-0000-0000-0000-000000000100"); -LLUUID const SND_SHOT ("00000000-0000-0000-0000-000000000101"); -LLUUID const SND_MORTAR ("00000000-0000-0000-0000-000000000102"); -LLUUID const SND_HIT ("00000000-0000-0000-0000-000000000103"); -LLUUID const SND_EXPLOSION ("00000000-0000-0000-0000-000000000104"); -LLUUID const SND_BOING ("00000000-0000-0000-0000-000000000105"); -LLUUID const SND_OBJECT_CREATE ("9f1bc096-3592-411e-9b0b-c447a9ff054c"); +const LLUUID SND_NULL = LLUUID::null; +const LLUUID SND_RIDE ("00000000-0000-0000-0000-000000000100"); +const LLUUID SND_SHOT ("00000000-0000-0000-0000-000000000101"); +const LLUUID SND_MORTAR ("00000000-0000-0000-0000-000000000102"); +const LLUUID SND_HIT ("00000000-0000-0000-0000-000000000103"); +const LLUUID SND_EXPLOSION ("00000000-0000-0000-0000-000000000104"); +const LLUUID SND_BOING ("00000000-0000-0000-0000-000000000105"); +const LLUUID SND_OBJECT_CREATE ("9f1bc096-3592-411e-9b0b-c447a9ff054c"); // // Different bird sounds for different states // -LLUUID const SND_CHIRP ("00000000-0000-0000-0000-000000000106"); // Flying random chirp -LLUUID const SND_CHIRP2 ("828a9526-175b-455d-8af0-0e3c0fb602b2"); // Spooked by user -LLUUID const SND_CHIRP3 ("f99772d6-1ce6-4a39-a28b-06d26c94c9e3"); // Spooked by object -LLUUID const SND_CHIRP4 ("54472ca4-7fc9-42cb-b7d5-99ad5b12bd50"); // Chasing other bird -LLUUID const SND_CHIRP5 ("2929964f-fac5-40d7-9179-2864a8fa9ace"); // Hopping random chirp -LLUUID const SND_CHIRPDEAD ("9abff1d3-863a-4e04-bd83-3834fd7fcff4"); // Hit by grenade - dead! +const LLUUID SND_CHIRP ("00000000-0000-0000-0000-000000000106"); // Flying random chirp +const LLUUID SND_CHIRP2 ("828a9526-175b-455d-8af0-0e3c0fb602b2"); // Spooked by user +const LLUUID SND_CHIRP3 ("f99772d6-1ce6-4a39-a28b-06d26c94c9e3"); // Spooked by object +const LLUUID SND_CHIRP4 ("54472ca4-7fc9-42cb-b7d5-99ad5b12bd50"); // Chasing other bird +const LLUUID SND_CHIRP5 ("2929964f-fac5-40d7-9179-2864a8fa9ace"); // Hopping random chirp +const LLUUID SND_CHIRPDEAD ("9abff1d3-863a-4e04-bd83-3834fd7fcff4"); // Hit by grenade - dead! -LLUUID const SND_MUNCH ("00000000-0000-0000-0000-000000000107"); -LLUUID const SND_PUNCH ("00000000-0000-0000-0000-000000000108"); -LLUUID const SND_SPLASH ("00000000-0000-0000-0000-000000000109"); -LLUUID const SND_CLICK ("00000000-0000-0000-0000-000000000110"); -LLUUID const SND_WHISTLE ("ab858f9a-1f44-4d39-9b33-351543d03ccb"); -LLUUID const SND_TYPING ("5e191c7b-8996-9ced-a177-b2ac32bfea06"); +const LLUUID SND_MUNCH ("00000000-0000-0000-0000-000000000107"); +const LLUUID SND_PUNCH ("00000000-0000-0000-0000-000000000108"); +const LLUUID SND_SPLASH ("00000000-0000-0000-0000-000000000109"); +const LLUUID SND_CLICK ("00000000-0000-0000-0000-000000000110"); +const LLUUID SND_WHISTLE ("ab858f9a-1f44-4d39-9b33-351543d03ccb"); +const LLUUID SND_TYPING ("5e191c7b-8996-9ced-a177-b2ac32bfea06"); -LLUUID const SND_ARROW_SHOT ("00000000-0000-0000-0000-000000000111"); -LLUUID const SND_ARROW_THUD ("00000000-0000-0000-0000-000000000112"); -LLUUID const SND_LASER_SHOT ("00000000-0000-0000-0000-000000000113"); -LLUUID const SND_JET_THRUST ("67f5e4f0-0534-4d97-bc01-f297648d20e0"); +const LLUUID SND_ARROW_SHOT ("00000000-0000-0000-0000-000000000111"); +const LLUUID SND_ARROW_THUD ("00000000-0000-0000-0000-000000000112"); +const LLUUID SND_LASER_SHOT ("00000000-0000-0000-0000-000000000113"); +const LLUUID SND_JET_THRUST ("67f5e4f0-0534-4d97-bc01-f297648d20e0"); -LLUUID const SND_SILENCE ("00000000-0000-0000-0000-000000000114"); -LLUUID const SND_BUBBLES ("00000000-0000-0000-0000-000000000115"); -LLUUID const SND_WELCOME ("00000000-0000-0000-0000-000000000116"); -LLUUID const SND_SQUISH ("00000000-0000-0000-0000-000000000117"); -LLUUID const SND_SUBPOD ("00000000-0000-0000-0000-000000000118"); -LLUUID const SND_FOOTSTEPS ("00000000-0000-0000-0000-000000000119"); -LLUUID const SND_STEP_LEFT ("00000000-0000-0000-0000-000000000124"); -LLUUID const SND_STEP_RIGHT ("00000000-0000-0000-0000-000000000125"); +const LLUUID SND_SILENCE ("00000000-0000-0000-0000-000000000114"); +const LLUUID SND_BUBBLES ("00000000-0000-0000-0000-000000000115"); +const LLUUID SND_WELCOME ("00000000-0000-0000-0000-000000000116"); +const LLUUID SND_SQUISH ("00000000-0000-0000-0000-000000000117"); +const LLUUID SND_SUBPOD ("00000000-0000-0000-0000-000000000118"); +const LLUUID SND_FOOTSTEPS ("00000000-0000-0000-0000-000000000119"); +const LLUUID SND_STEP_LEFT ("00000000-0000-0000-0000-000000000124"); +const LLUUID SND_STEP_RIGHT ("00000000-0000-0000-0000-000000000125"); -LLUUID const SND_BALL_COLLISION ("00000000-0000-0000-0000-000000000120"); +const LLUUID SND_BALL_COLLISION ("00000000-0000-0000-0000-000000000120"); -LLUUID const SND_OOOH_SCARE_ME ("00000000-0000-0000-0000-000000000121"); -LLUUID const SND_PAYBACK_TIME ("00000000-0000-0000-0000-000000000122"); -LLUUID const SND_READY_FOR_BATTLE ("00000000-0000-0000-0000-000000000123"); +const LLUUID SND_OOOH_SCARE_ME ("00000000-0000-0000-0000-000000000121"); +const LLUUID SND_PAYBACK_TIME ("00000000-0000-0000-0000-000000000122"); +const LLUUID SND_READY_FOR_BATTLE ("00000000-0000-0000-0000-000000000123"); -LLUUID const SND_FLESH_FLESH ("dce5fdd4-afe4-4ea1-822f-dd52cac46b08"); -LLUUID const SND_FLESH_PLASTIC ("51011582-fbca-4580-ae9e-1a5593f094ec"); -LLUUID const SND_FLESH_RUBBER ("68d62208-e257-4d0c-bbe2-20c9ea9760bb"); -LLUUID const SND_GLASS_FLESH ("75872e8c-bc39-451b-9b0b-042d7ba36cba"); -LLUUID const SND_GLASS_GLASS ("6a45ba0b-5775-4ea8-8513-26008a17f873"); -LLUUID const SND_GLASS_PLASTIC ("992a6d1b-8c77-40e0-9495-4098ce539694"); -LLUUID const SND_GLASS_RUBBER ("2de4da5a-faf8-46be-bac6-c4d74f1e5767"); -LLUUID const SND_GLASS_WOOD ("6e3fb0f7-6d9c-42ca-b86b-1122ff562d7d"); -LLUUID const SND_METAL_FLESH ("14209133-4961-4acc-9649-53fc38ee1667"); -LLUUID const SND_METAL_GLASS ("bc4a4348-cfcc-4e5e-908e-8a52a8915fe6"); -LLUUID const SND_METAL_METAL ("9e5c1297-6eed-40c0-825a-d9bcd86e3193"); -LLUUID const SND_METAL_PLASTIC ("e534761c-1894-4b61-b20c-658a6fb68157"); -LLUUID const SND_METAL_RUBBER ("8761f73f-6cf9-4186-8aaa-0948ed002db1"); -LLUUID const SND_METAL_WOOD ("874a26fd-142f-4173-8c5b-890cd846c74d"); -LLUUID const SND_PLASTIC_PLASTIC ("0e24a717-b97e-4b77-9c94-b59a5a88b2da"); -LLUUID const SND_RUBBER_PLASTIC ("75cf3ade-9a5b-4c4d-bb35-f9799bda7fb2"); -LLUUID const SND_RUBBER_RUBBER ("153c8bf7-fb89-4d89-b263-47e58b1b4774"); -LLUUID const SND_STONE_FLESH ("55c3e0ce-275a-46fa-82ff-e0465f5e8703"); -LLUUID const SND_STONE_GLASS ("24babf58-7156-4841-9a3f-761bdbb8e237"); -LLUUID const SND_STONE_METAL ("aca261d8-e145-4610-9e20-9eff990f2c12"); -LLUUID const SND_STONE_PLASTIC ("0642fba6-5dcf-4d62-8e7b-94dbb529d117"); -LLUUID const SND_STONE_RUBBER ("25a863e8-dc42-4e8a-a357-e76422ace9b5"); -LLUUID const SND_STONE_STONE ("9538f37c-456e-4047-81be-6435045608d4"); -LLUUID const SND_STONE_WOOD ("8c0f84c3-9afd-4396-b5f5-9bca2c911c20"); -LLUUID const SND_WOOD_FLESH ("be582e5d-b123-41a2-a150-454c39e961c8"); -LLUUID const SND_WOOD_PLASTIC ("c70141d4-ba06-41ea-bcbc-35ea81cb8335"); -LLUUID const SND_WOOD_RUBBER ("7d1826f4-24c4-4aac-8c2e-eff45df37783"); -LLUUID const SND_WOOD_WOOD ("063c97d3-033a-4e9b-98d8-05c8074922cb"); +const LLUUID SND_FLESH_FLESH ("dce5fdd4-afe4-4ea1-822f-dd52cac46b08"); +const LLUUID SND_FLESH_PLASTIC ("51011582-fbca-4580-ae9e-1a5593f094ec"); +const LLUUID SND_FLESH_RUBBER ("68d62208-e257-4d0c-bbe2-20c9ea9760bb"); +const LLUUID SND_GLASS_FLESH ("75872e8c-bc39-451b-9b0b-042d7ba36cba"); +const LLUUID SND_GLASS_GLASS ("6a45ba0b-5775-4ea8-8513-26008a17f873"); +const LLUUID SND_GLASS_PLASTIC ("992a6d1b-8c77-40e0-9495-4098ce539694"); +const LLUUID SND_GLASS_RUBBER ("2de4da5a-faf8-46be-bac6-c4d74f1e5767"); +const LLUUID SND_GLASS_WOOD ("6e3fb0f7-6d9c-42ca-b86b-1122ff562d7d"); +const LLUUID SND_METAL_FLESH ("14209133-4961-4acc-9649-53fc38ee1667"); +const LLUUID SND_METAL_GLASS ("bc4a4348-cfcc-4e5e-908e-8a52a8915fe6"); +const LLUUID SND_METAL_METAL ("9e5c1297-6eed-40c0-825a-d9bcd86e3193"); +const LLUUID SND_METAL_PLASTIC ("e534761c-1894-4b61-b20c-658a6fb68157"); +const LLUUID SND_METAL_RUBBER ("8761f73f-6cf9-4186-8aaa-0948ed002db1"); +const LLUUID SND_METAL_WOOD ("874a26fd-142f-4173-8c5b-890cd846c74d"); +const LLUUID SND_PLASTIC_PLASTIC ("0e24a717-b97e-4b77-9c94-b59a5a88b2da"); +const LLUUID SND_RUBBER_PLASTIC ("75cf3ade-9a5b-4c4d-bb35-f9799bda7fb2"); +const LLUUID SND_RUBBER_RUBBER ("153c8bf7-fb89-4d89-b263-47e58b1b4774"); +const LLUUID SND_STONE_FLESH ("55c3e0ce-275a-46fa-82ff-e0465f5e8703"); +const LLUUID SND_STONE_GLASS ("24babf58-7156-4841-9a3f-761bdbb8e237"); +const LLUUID SND_STONE_METAL ("aca261d8-e145-4610-9e20-9eff990f2c12"); +const LLUUID SND_STONE_PLASTIC ("0642fba6-5dcf-4d62-8e7b-94dbb529d117"); +const LLUUID SND_STONE_RUBBER ("25a863e8-dc42-4e8a-a357-e76422ace9b5"); +const LLUUID SND_STONE_STONE ("9538f37c-456e-4047-81be-6435045608d4"); +const LLUUID SND_STONE_WOOD ("8c0f84c3-9afd-4396-b5f5-9bca2c911c20"); +const LLUUID SND_WOOD_FLESH ("be582e5d-b123-41a2-a150-454c39e961c8"); +const LLUUID SND_WOOD_PLASTIC ("c70141d4-ba06-41ea-bcbc-35ea81cb8335"); +const LLUUID SND_WOOD_RUBBER ("7d1826f4-24c4-4aac-8c2e-eff45df37783"); +const LLUUID SND_WOOD_WOOD ("063c97d3-033a-4e9b-98d8-05c8074922cb"); -LLUUID const SND_SLIDE_FLESH_FLESH ("614eec22-f73d-4fdc-8691-a37dc5c58333"); -LLUUID const SND_SLIDE_FLESH_PLASTIC (SND_NULL); -LLUUID const SND_SLIDE_FLESH_RUBBER (SND_NULL); -LLUUID const SND_SLIDE_FLESH_FABRIC ("3678b9b9-2a0c-42b5-9c83-80b64ad6e898"); -LLUUID const SND_SLIDE_FLESH_GRAVEL ("02eaa42a-ce1a-4b6b-9c38-cd7ad0e8f4a6"); -LLUUID const SND_SLIDE_FLESH_GRAVEL_02 ("e7d3b501-79f8-4419-b842-ab6843e0f840"); -LLUUID const SND_SLIDE_FLESH_GRAVEL_03 ("4c3e8b52-6244-4e44-85a6-f4ab994418ed"); -LLUUID const SND_SLIDE_GLASS_GRAVEL ("ca491e77-5c47-4ea1-8021-b3ebbf636cab"); -LLUUID const SND_SLIDE_GLASS_GRAVEL_02 ("30794d49-91ce-48e3-a527-c06f67bd6cbe"); -LLUUID const SND_SLIDE_GLASS_GRAVEL_03 ("04c78e54-fd8d-46b6-8ab9-7678b5d6e5cb"); -LLUUID const SND_SLIDE_GLASS_FLESH (SND_NULL); -LLUUID const SND_SLIDE_GLASS_GLASS (SND_NULL); -LLUUID const SND_SLIDE_GLASS_PLASTIC (SND_NULL); -LLUUID const SND_SLIDE_GLASS_RUBBER (SND_NULL); -LLUUID const SND_SLIDE_GLASS_WOOD (SND_NULL); -LLUUID const SND_SLIDE_METAL_FABRIC ("18b66e81-2958-42d4-a373-7a5054919adc"); -LLUUID const SND_SLIDE_METAL_FLESH ("dde65837-633c-4841-af2f-62ec471bf61e"); -LLUUID const SND_SLIDE_METAL_FLESH_02 ("f3cc2cbe-1a1a-4db7-a8d2-e9c8f8fa1f4f"); -LLUUID const SND_SLIDE_METAL_GLASS ("4188be39-7b1f-4495-bf2b-83ddd82eea05"); -LLUUID const SND_SLIDE_METAL_GLASS_02 ("336faa2b-9d96-4e14-93ad-b63b60074379"); -LLUUID const SND_SLIDE_METAL_GLASS_03 ("34d912aa-cf73-4462-b7d0-dcba2c66caba"); -LLUUID const SND_SLIDE_METAL_GLASS_04 ("97ffc063-e872-4469-8e95-1450ac6bad2b"); -LLUUID const SND_SLIDE_METAL_GRAVEL ("2bbff37d-009a-4cfc-9a0d-817652c08fbe"); -LLUUID const SND_SLIDE_METAL_GRAVEL_02 ("a906a228-783b-49e7-9f0a-e20a41d0e39f"); -LLUUID const SND_SLIDE_METAL_METAL ("09461277-c691-45de-b2c5-89dfd3712f79"); -LLUUID const SND_SLIDE_METAL_METAL_02 ("e00a5d97-8fdc-46c1-bd53-7e312727466c"); -LLUUID const SND_SLIDE_METAL_METAL_03 ("8ebfa780-c440-4b52-ab65-5edf3bc15bf1"); -LLUUID const SND_SLIDE_METAL_METAL_04 ("d6d03cb2-5b16-4e31-b7d4-2a81d2a0909b"); -LLUUID const SND_SLIDE_METAL_METAL_05 ("3a46f447-916e-47de-a1e5-95d1af46bd0f"); -LLUUID const SND_SLIDE_METAL_METAL_06 ("cd423231-e70d-4fd2-ad26-f1c6cf5f0610"); -LLUUID const SND_SLIDE_METAL_PLASTIC (SND_NULL); -LLUUID const SND_SLIDE_METAL_RUBBER ("12d97bc0-3c15-4744-b6bd-77d1316eb4f0"); -LLUUID const SND_SLIDE_METAL_WOOD ("4afb6926-a73f-4cb7-85d5-0f9a40107434"); -LLUUID const SND_SLIDE_METAL_WOOD_02 ("349970bf-187d-4bcb-b2cf-e7bb6581590f"); -LLUUID const SND_SLIDE_METAL_WOOD_03 ("64bf6e87-73d4-4cb4-84f7-55cecfd97cd3"); -LLUUID const SND_SLIDE_METAL_WOOD_04 ("0dc670a9-dbe8-41bc-b8ee-4d96d99219d5"); -LLUUID const SND_SLIDE_METAL_WOOD_05 ("6e3cc57b-c9aa-4829-86a1-8e82aeaccb47"); -LLUUID const SND_SLIDE_METAL_WOOD_06 ("c1237f4c-8c88-4da1-bfbc-2af26a8d9e5a"); -LLUUID const SND_SLIDE_METAL_WOOD_07 ("0e1ec243-063b-4dcb-a903-52b8dffed3d2"); -LLUUID const SND_SLIDE_METAL_WOOD_08 ("66736d0f-533d-4007-a8ee-0f27c2034126"); -LLUUID const SND_SLIDE_PLASTIC_GRAVEL ("35092c21-5c48-4b4d-a818-3cf240af2348"); -LLUUID const SND_SLIDE_PLASTIC_GRAVEL_02("c37f5776-0020-47e8-89a0-c74cc6f5742d"); -LLUUID const SND_SLIDE_PLASTIC_GRAVEL_03("d2fc8db6-2e66-464a-8ccb-f99b61ee4987"); -LLUUID const SND_SLIDE_PLASTIC_GRAVEL_04("93cbdb10-6e82-4c0b-a547-7b3b79ac25f6"); -LLUUID const SND_SLIDE_PLASTIC_GRAVEL_05("2f6d0542-fcd1-4264-a17b-f57bf5ebf402"); -LLUUID const SND_SLIDE_PLASTIC_GRAVEL_06("5b8887d4-3be2-45a0-b25d-85af3b1e6392"); -LLUUID const SND_SLIDE_PLASTIC_PLASTIC (SND_NULL); -LLUUID const SND_SLIDE_PLASTIC_PLASTIC_02 (SND_NULL); -LLUUID const SND_SLIDE_PLASTIC_PLASTIC_03 (SND_NULL); -LLUUID const SND_SLIDE_PLASTIC_FABRIC ("7294d9ad-3e41-4373-992c-a9f21d5d66ad"); -LLUUID const SND_SLIDE_PLASTIC_FABRIC_02("58608ce1-f524-472f-b447-bbe6ce4a46e0"); -LLUUID const SND_SLIDE_PLASTIC_FABRIC_03("06ae285e-0b34-4ea6-84ab-9c6c31b414fc"); -LLUUID const SND_SLIDE_PLASTIC_FABRIC_04("211613db-0461-49bd-9554-5c14ad8b31f6"); -LLUUID const SND_SLIDE_RUBBER_PLASTIC ("a98ffa5a-e48e-4f9d-9242-b9a3210ad84a"); -LLUUID const SND_SLIDE_RUBBER_PLASTIC_02 ("d4136c40-eeaa-49c6-a982-8e5a16f5d93a"); -LLUUID const SND_SLIDE_RUBBER_PLASTIC_03 ("29ec0fb2-0b23-47b2-835b-c83cc7cf9fb0"); -LLUUID const SND_SLIDE_RUBBER_RUBBER (SND_NULL); -LLUUID const SND_SLIDE_STONE_FLESH (SND_NULL); -LLUUID const SND_SLIDE_STONE_GLASS (SND_NULL); -LLUUID const SND_SLIDE_STONE_METAL (SND_NULL); -LLUUID const SND_SLIDE_STONE_PLASTIC ("afd0bcc3-d41a-4572-9e7f-08a29eeb0b8a"); -LLUUID const SND_SLIDE_STONE_PLASTIC_02 ("881b720a-96cf-4128-bb98-5d87e03e93c7"); -LLUUID const SND_SLIDE_STONE_PLASTIC_03 ("293dac42-658a-4c5a-a7a2-6d4c5e5658b0"); -LLUUID const SND_SLIDE_STONE_RUBBER ("0724b946-6a3f-4eeb-bb50-0a3b33120974"); -LLUUID const SND_SLIDE_STONE_RUBBER_02 ("ada93d00-76e2-4bf1-9ad9-493727630717"); -LLUUID const SND_SLIDE_STONE_STONE ("ade766dc-2e75-4699-9b41-7c8e53d2b3f2"); -LLUUID const SND_SLIDE_STONE_STONE_02 ("66698375-6594-47b0-8046-c3973de1291d"); -LLUUID const SND_SLIDE_STONE_WOOD ("174ef324-ed50-4f65-9479-b4da580aeb3c"); -LLUUID const SND_SLIDE_STONE_WOOD_02 ("33d517fd-ff11-4d01-a7b5-0e3abf818dcf"); -LLUUID const SND_SLIDE_STONE_WOOD_03 ("1bac4b63-e6fd-4659-9761-991284cf4582"); -LLUUID const SND_SLIDE_STONE_WOOD_04 ("a7d28564-6821-4c01-a378-cde98fba7ba9"); -LLUUID const SND_SLIDE_WOOD_FABRIC ("22c58e74-22cd-4960-9ab7-5bf08ab824e5"); -LLUUID const SND_SLIDE_WOOD_FABRIC_02 ("0b0ed22e-4a0f-4617-a4cf-20d0f2b78ccc"); -LLUUID const SND_SLIDE_WOOD_FABRIC_03 ("42b80abb-9823-4b74-a210-326ccf23636a"); -LLUUID const SND_SLIDE_WOOD_FABRIC_04 ("8538298a-1e6b-4b69-a9ee-5e01e4a02b35"); -LLUUID const SND_SLIDE_WOOD_FLESH ("84b026f3-a11c-4366-aa7c-07edcd89b2bb"); -LLUUID const SND_SLIDE_WOOD_FLESH_02 ("2644191f-4848-47ba-8ba7-bddc0bfcb3da"); -LLUUID const SND_SLIDE_WOOD_FLESH_03 ("edb978e4-9be9-456f-b2fc-e8502bfe25be"); -LLUUID const SND_SLIDE_WOOD_FLESH_04 ("bf2b972e-f42a-46d7-b53e-5fca38f5bc61"); -LLUUID const SND_SLIDE_WOOD_GRAVEL ("d063bb4d-0eff-4403-a6cc-c6c6c073e624"); -LLUUID const SND_SLIDE_WOOD_GRAVEL_02 ("511eb679-6d93-47fa-9141-c3ef9261c919"); -LLUUID const SND_SLIDE_WOOD_GRAVEL_03 ("4ed1fd43-4707-4e5c-b7b7-21ec4e72c1ac"); -LLUUID const SND_SLIDE_WOOD_GRAVEL_04 ("99ea89b3-aa76-4b87-99c8-670365c6d8c3"); -LLUUID const SND_SLIDE_WOOD_PLASTIC ("505ca3c4-94a0-4e28-8fc1-ea72a428396b"); -LLUUID const SND_SLIDE_WOOD_PLASTIC_02 ("fc404011-df71-4ed0-8f22-b72bdd18f63c"); -LLUUID const SND_SLIDE_WOOD_PLASTIC_03 ("67dbe225-26df-4efa-8c8b-f1ef669fec45"); -LLUUID const SND_SLIDE_WOOD_RUBBER (SND_NULL); -LLUUID const SND_SLIDE_WOOD_WOOD ("3079d569-b3e8-4df4-9e09-f0d4611213ef"); -LLUUID const SND_SLIDE_WOOD_WOOD_02 ("276b093d-dbcb-4279-a89e-a54b0b416af6"); -LLUUID const SND_SLIDE_WOOD_WOOD_03 ("c3f3ca5e-2768-4081-847f-247139310fdb"); -LLUUID const SND_SLIDE_WOOD_WOOD_04 ("f08d44b8-ff87-4a98-9561-c72f1f2fec81"); -LLUUID const SND_SLIDE_WOOD_WOOD_05 ("2d8a58cf-f139-4238-8503-27d334d05c85"); -LLUUID const SND_SLIDE_WOOD_WOOD_06 ("e157ebbd-b12d-4225-aa7c-d47b026a7687"); -LLUUID const SND_SLIDE_WOOD_WOOD_07 ("35e17956-e7b4-478c-b274-e37db8a166b2"); -LLUUID const SND_SLIDE_WOOD_WOOD_08 ("e606fc65-0643-4964-9979-ff964fa6a62c"); +const LLUUID SND_SLIDE_FLESH_FLESH ("614eec22-f73d-4fdc-8691-a37dc5c58333"); +const LLUUID SND_SLIDE_FLESH_PLASTIC (SND_NULL); +const LLUUID SND_SLIDE_FLESH_RUBBER (SND_NULL); +const LLUUID SND_SLIDE_FLESH_FABRIC ("3678b9b9-2a0c-42b5-9c83-80b64ad6e898"); +const LLUUID SND_SLIDE_FLESH_GRAVEL ("02eaa42a-ce1a-4b6b-9c38-cd7ad0e8f4a6"); +const LLUUID SND_SLIDE_FLESH_GRAVEL_02 ("e7d3b501-79f8-4419-b842-ab6843e0f840"); +const LLUUID SND_SLIDE_FLESH_GRAVEL_03 ("4c3e8b52-6244-4e44-85a6-f4ab994418ed"); +const LLUUID SND_SLIDE_GLASS_GRAVEL ("ca491e77-5c47-4ea1-8021-b3ebbf636cab"); +const LLUUID SND_SLIDE_GLASS_GRAVEL_02 ("30794d49-91ce-48e3-a527-c06f67bd6cbe"); +const LLUUID SND_SLIDE_GLASS_GRAVEL_03 ("04c78e54-fd8d-46b6-8ab9-7678b5d6e5cb"); +const LLUUID SND_SLIDE_GLASS_FLESH (SND_NULL); +const LLUUID SND_SLIDE_GLASS_GLASS (SND_NULL); +const LLUUID SND_SLIDE_GLASS_PLASTIC (SND_NULL); +const LLUUID SND_SLIDE_GLASS_RUBBER (SND_NULL); +const LLUUID SND_SLIDE_GLASS_WOOD (SND_NULL); +const LLUUID SND_SLIDE_METAL_FABRIC ("18b66e81-2958-42d4-a373-7a5054919adc"); +const LLUUID SND_SLIDE_METAL_FLESH ("dde65837-633c-4841-af2f-62ec471bf61e"); +const LLUUID SND_SLIDE_METAL_FLESH_02 ("f3cc2cbe-1a1a-4db7-a8d2-e9c8f8fa1f4f"); +const LLUUID SND_SLIDE_METAL_GLASS ("4188be39-7b1f-4495-bf2b-83ddd82eea05"); +const LLUUID SND_SLIDE_METAL_GLASS_02 ("336faa2b-9d96-4e14-93ad-b63b60074379"); +const LLUUID SND_SLIDE_METAL_GLASS_03 ("34d912aa-cf73-4462-b7d0-dcba2c66caba"); +const LLUUID SND_SLIDE_METAL_GLASS_04 ("97ffc063-e872-4469-8e95-1450ac6bad2b"); +const LLUUID SND_SLIDE_METAL_GRAVEL ("2bbff37d-009a-4cfc-9a0d-817652c08fbe"); +const LLUUID SND_SLIDE_METAL_GRAVEL_02 ("a906a228-783b-49e7-9f0a-e20a41d0e39f"); +const LLUUID SND_SLIDE_METAL_METAL ("09461277-c691-45de-b2c5-89dfd3712f79"); +const LLUUID SND_SLIDE_METAL_METAL_02 ("e00a5d97-8fdc-46c1-bd53-7e312727466c"); +const LLUUID SND_SLIDE_METAL_METAL_03 ("8ebfa780-c440-4b52-ab65-5edf3bc15bf1"); +const LLUUID SND_SLIDE_METAL_METAL_04 ("d6d03cb2-5b16-4e31-b7d4-2a81d2a0909b"); +const LLUUID SND_SLIDE_METAL_METAL_05 ("3a46f447-916e-47de-a1e5-95d1af46bd0f"); +const LLUUID SND_SLIDE_METAL_METAL_06 ("cd423231-e70d-4fd2-ad26-f1c6cf5f0610"); +const LLUUID SND_SLIDE_METAL_PLASTIC (SND_NULL); +const LLUUID SND_SLIDE_METAL_RUBBER ("12d97bc0-3c15-4744-b6bd-77d1316eb4f0"); +const LLUUID SND_SLIDE_METAL_WOOD ("4afb6926-a73f-4cb7-85d5-0f9a40107434"); +const LLUUID SND_SLIDE_METAL_WOOD_02 ("349970bf-187d-4bcb-b2cf-e7bb6581590f"); +const LLUUID SND_SLIDE_METAL_WOOD_03 ("64bf6e87-73d4-4cb4-84f7-55cecfd97cd3"); +const LLUUID SND_SLIDE_METAL_WOOD_04 ("0dc670a9-dbe8-41bc-b8ee-4d96d99219d5"); +const LLUUID SND_SLIDE_METAL_WOOD_05 ("6e3cc57b-c9aa-4829-86a1-8e82aeaccb47"); +const LLUUID SND_SLIDE_METAL_WOOD_06 ("c1237f4c-8c88-4da1-bfbc-2af26a8d9e5a"); +const LLUUID SND_SLIDE_METAL_WOOD_07 ("0e1ec243-063b-4dcb-a903-52b8dffed3d2"); +const LLUUID SND_SLIDE_METAL_WOOD_08 ("66736d0f-533d-4007-a8ee-0f27c2034126"); +const LLUUID SND_SLIDE_PLASTIC_GRAVEL ("35092c21-5c48-4b4d-a818-3cf240af2348"); +const LLUUID SND_SLIDE_PLASTIC_GRAVEL_02("c37f5776-0020-47e8-89a0-c74cc6f5742d"); +const LLUUID SND_SLIDE_PLASTIC_GRAVEL_03("d2fc8db6-2e66-464a-8ccb-f99b61ee4987"); +const LLUUID SND_SLIDE_PLASTIC_GRAVEL_04("93cbdb10-6e82-4c0b-a547-7b3b79ac25f6"); +const LLUUID SND_SLIDE_PLASTIC_GRAVEL_05("2f6d0542-fcd1-4264-a17b-f57bf5ebf402"); +const LLUUID SND_SLIDE_PLASTIC_GRAVEL_06("5b8887d4-3be2-45a0-b25d-85af3b1e6392"); +const LLUUID SND_SLIDE_PLASTIC_PLASTIC (SND_NULL); +const LLUUID SND_SLIDE_PLASTIC_PLASTIC_02 (SND_NULL); +const LLUUID SND_SLIDE_PLASTIC_PLASTIC_03 (SND_NULL); +const LLUUID SND_SLIDE_PLASTIC_FABRIC ("7294d9ad-3e41-4373-992c-a9f21d5d66ad"); +const LLUUID SND_SLIDE_PLASTIC_FABRIC_02("58608ce1-f524-472f-b447-bbe6ce4a46e0"); +const LLUUID SND_SLIDE_PLASTIC_FABRIC_03("06ae285e-0b34-4ea6-84ab-9c6c31b414fc"); +const LLUUID SND_SLIDE_PLASTIC_FABRIC_04("211613db-0461-49bd-9554-5c14ad8b31f6"); +const LLUUID SND_SLIDE_RUBBER_PLASTIC ("a98ffa5a-e48e-4f9d-9242-b9a3210ad84a"); +const LLUUID SND_SLIDE_RUBBER_PLASTIC_02 ("d4136c40-eeaa-49c6-a982-8e5a16f5d93a"); +const LLUUID SND_SLIDE_RUBBER_PLASTIC_03 ("29ec0fb2-0b23-47b2-835b-c83cc7cf9fb0"); +const LLUUID SND_SLIDE_RUBBER_RUBBER (SND_NULL); +const LLUUID SND_SLIDE_STONE_FLESH (SND_NULL); +const LLUUID SND_SLIDE_STONE_GLASS (SND_NULL); +const LLUUID SND_SLIDE_STONE_METAL (SND_NULL); +const LLUUID SND_SLIDE_STONE_PLASTIC ("afd0bcc3-d41a-4572-9e7f-08a29eeb0b8a"); +const LLUUID SND_SLIDE_STONE_PLASTIC_02 ("881b720a-96cf-4128-bb98-5d87e03e93c7"); +const LLUUID SND_SLIDE_STONE_PLASTIC_03 ("293dac42-658a-4c5a-a7a2-6d4c5e5658b0"); +const LLUUID SND_SLIDE_STONE_RUBBER ("0724b946-6a3f-4eeb-bb50-0a3b33120974"); +const LLUUID SND_SLIDE_STONE_RUBBER_02 ("ada93d00-76e2-4bf1-9ad9-493727630717"); +const LLUUID SND_SLIDE_STONE_STONE ("ade766dc-2e75-4699-9b41-7c8e53d2b3f2"); +const LLUUID SND_SLIDE_STONE_STONE_02 ("66698375-6594-47b0-8046-c3973de1291d"); +const LLUUID SND_SLIDE_STONE_WOOD ("174ef324-ed50-4f65-9479-b4da580aeb3c"); +const LLUUID SND_SLIDE_STONE_WOOD_02 ("33d517fd-ff11-4d01-a7b5-0e3abf818dcf"); +const LLUUID SND_SLIDE_STONE_WOOD_03 ("1bac4b63-e6fd-4659-9761-991284cf4582"); +const LLUUID SND_SLIDE_STONE_WOOD_04 ("a7d28564-6821-4c01-a378-cde98fba7ba9"); +const LLUUID SND_SLIDE_WOOD_FABRIC ("22c58e74-22cd-4960-9ab7-5bf08ab824e5"); +const LLUUID SND_SLIDE_WOOD_FABRIC_02 ("0b0ed22e-4a0f-4617-a4cf-20d0f2b78ccc"); +const LLUUID SND_SLIDE_WOOD_FABRIC_03 ("42b80abb-9823-4b74-a210-326ccf23636a"); +const LLUUID SND_SLIDE_WOOD_FABRIC_04 ("8538298a-1e6b-4b69-a9ee-5e01e4a02b35"); +const LLUUID SND_SLIDE_WOOD_FLESH ("84b026f3-a11c-4366-aa7c-07edcd89b2bb"); +const LLUUID SND_SLIDE_WOOD_FLESH_02 ("2644191f-4848-47ba-8ba7-bddc0bfcb3da"); +const LLUUID SND_SLIDE_WOOD_FLESH_03 ("edb978e4-9be9-456f-b2fc-e8502bfe25be"); +const LLUUID SND_SLIDE_WOOD_FLESH_04 ("bf2b972e-f42a-46d7-b53e-5fca38f5bc61"); +const LLUUID SND_SLIDE_WOOD_GRAVEL ("d063bb4d-0eff-4403-a6cc-c6c6c073e624"); +const LLUUID SND_SLIDE_WOOD_GRAVEL_02 ("511eb679-6d93-47fa-9141-c3ef9261c919"); +const LLUUID SND_SLIDE_WOOD_GRAVEL_03 ("4ed1fd43-4707-4e5c-b7b7-21ec4e72c1ac"); +const LLUUID SND_SLIDE_WOOD_GRAVEL_04 ("99ea89b3-aa76-4b87-99c8-670365c6d8c3"); +const LLUUID SND_SLIDE_WOOD_PLASTIC ("505ca3c4-94a0-4e28-8fc1-ea72a428396b"); +const LLUUID SND_SLIDE_WOOD_PLASTIC_02 ("fc404011-df71-4ed0-8f22-b72bdd18f63c"); +const LLUUID SND_SLIDE_WOOD_PLASTIC_03 ("67dbe225-26df-4efa-8c8b-f1ef669fec45"); +const LLUUID SND_SLIDE_WOOD_RUBBER (SND_NULL); +const LLUUID SND_SLIDE_WOOD_WOOD ("3079d569-b3e8-4df4-9e09-f0d4611213ef"); +const LLUUID SND_SLIDE_WOOD_WOOD_02 ("276b093d-dbcb-4279-a89e-a54b0b416af6"); +const LLUUID SND_SLIDE_WOOD_WOOD_03 ("c3f3ca5e-2768-4081-847f-247139310fdb"); +const LLUUID SND_SLIDE_WOOD_WOOD_04 ("f08d44b8-ff87-4a98-9561-c72f1f2fec81"); +const LLUUID SND_SLIDE_WOOD_WOOD_05 ("2d8a58cf-f139-4238-8503-27d334d05c85"); +const LLUUID SND_SLIDE_WOOD_WOOD_06 ("e157ebbd-b12d-4225-aa7c-d47b026a7687"); +const LLUUID SND_SLIDE_WOOD_WOOD_07 ("35e17956-e7b4-478c-b274-e37db8a166b2"); +const LLUUID SND_SLIDE_WOOD_WOOD_08 ("e606fc65-0643-4964-9979-ff964fa6a62c"); -LLUUID const SND_ROLL_FLESH_FLESH (SND_NULL); -LLUUID const SND_ROLL_FLESH_PLASTIC ("89a0be4c-848d-4a6e-8886-298f56c2cff4"); -LLUUID const SND_ROLL_FLESH_PLASTIC_02 ("beb06343-1aa1-4af2-b320-5d2ec31c53b1"); -LLUUID const SND_ROLL_FLESH_RUBBER (SND_NULL); -LLUUID const SND_ROLL_GLASS_GRAVEL ("ba795c74-7e09-4572-b495-e09886a46b86"); -LLUUID const SND_ROLL_GLASS_GRAVEL_02 ("4c93c3b7-14cb-4d9b-a7df-628ad935f1f2"); -LLUUID const SND_ROLL_GLASS_FLESH (SND_NULL); -LLUUID const SND_ROLL_GLASS_GLASS (SND_NULL); -LLUUID const SND_ROLL_GLASS_PLASTIC (SND_NULL); -LLUUID const SND_ROLL_GLASS_RUBBER (SND_NULL); -LLUUID const SND_ROLL_GLASS_WOOD ("d40b1f48-a061-4f6e-b18f-4326a3dd5c29"); -LLUUID const SND_ROLL_GLASS_WOOD_02 ("78cd407a-bb36-4163-ba09-20f2e6d9d44b"); -LLUUID const SND_ROLL_GRAVEL_GRAVEL ("c7354cc3-6df5-4738-8dbb-b28a6ac46a05"); -LLUUID const SND_ROLL_GRAVEL_GRAVEL_02 ("01d194c4-72a6-47df-81a5-8db430faff87"); -LLUUID const SND_ROLL_METAL_FABRIC ("ce6e6564-20fd-48e4-81e2-cd3f81c00a3e"); -LLUUID const SND_ROLL_METAL_FABRIC_02 ("fc4d0065-32f6-4bb0-9f3f-f4737eb27163"); -LLUUID const SND_ROLL_METAL_FLESH (SND_NULL); -LLUUID const SND_ROLL_METAL_GLASS ("63d530bb-a41f-402b-aa1f-be6b11959809"); -LLUUID const SND_ROLL_METAL_GLASS_02 ("f62642c2-6db5-4faa-8b77-939067d837c3"); -LLUUID const SND_ROLL_METAL_GLASS_03 ("db5b5a15-2817-4cd7-9f0b-9ad49b5e52c8"); -LLUUID const SND_ROLL_METAL_GRAVEL ("447164e3-9646-4c1a-a16d-606892891466"); -LLUUID const SND_ROLL_METAL_METAL ("c3c22cf3-5d1f-4cc3-b4b5-708b9f65979c"); -LLUUID const SND_ROLL_METAL_METAL_02 ("d8386277-a1ea-460e-b6fd-bb285c323bf1"); -LLUUID const SND_ROLL_METAL_METAL_03 ("69ee1f02-f9cd-4c8b-aedd-39a2d6705680"); -LLUUID const SND_ROLL_METAL_METAL_04 ("5cc6b5fd-26ce-47ad-b21d-3a7c190dd375"); -LLUUID const SND_ROLL_METAL_PLASTIC ("c6a9bbf6-df15-4713-9f84-7237fce4051e"); -LLUUID const SND_ROLL_METAL_PLASTIC_01 ("0fedb59b-2dbb-4cec-b6cc-8559ec027749"); -LLUUID const SND_ROLL_METAL_RUBBER (SND_NULL); -LLUUID const SND_ROLL_METAL_WOOD ("1d76af57-01b1-4c73-9a1d-69523bfa50ea"); -LLUUID const SND_ROLL_METAL_WOOD_02 ("78aa4e71-8e7c-4b90-a561-3ebdc639f99b"); -LLUUID const SND_ROLL_METAL_WOOD_03 ("777d95bf-962f-48fa-93bf-8c1806557d72"); -LLUUID const SND_ROLL_METAL_WOOD_04 ("1833da76-45e2-4a8b-97da-d17413e056c9"); -LLUUID const SND_ROLL_METAL_WOOD_05 ("b13e1232-3d8d-42e9-92ec-b30f9f823962"); -LLUUID const SND_ROLL_PLASTIC_FABRIC ("616a1f03-209f-4c55-b264-83a000b6ef0a"); -LLUUID const SND_ROLL_PLASTIC_PLASTIC ("873f3d82-00b2-4082-9c69-7aef3461dba1"); -LLUUID const SND_ROLL_PLASTIC_PLASTIC_02 ("cc39879f-ebc8-4405-a4fc-8342f5bed31e"); -LLUUID const SND_ROLL_RUBBER_PLASTIC (SND_NULL); -LLUUID const SND_ROLL_RUBBER_RUBBER (SND_NULL); -LLUUID const SND_ROLL_STONE_FLESH (SND_NULL); -LLUUID const SND_ROLL_STONE_GLASS (SND_NULL); -LLUUID const SND_ROLL_STONE_METAL (SND_NULL); -LLUUID const SND_ROLL_STONE_PLASTIC ("155f65a8-cae7-476e-a58b-fd362be7fd0e"); -LLUUID const SND_ROLL_STONE_RUBBER (SND_NULL); -LLUUID const SND_ROLL_STONE_STONE ("67d56e3f-6ed5-4658-9418-14f020c38b11"); -LLUUID const SND_ROLL_STONE_STONE_02 ("43d99d10-d75b-4246-accf-4ceb2c909aa7"); -LLUUID const SND_ROLL_STONE_STONE_03 ("f04e83ff-eed7-4e99-8f45-eb97e4e1d3b7"); -LLUUID const SND_ROLL_STONE_STONE_04 ("10fcc5ad-fa89-48d6-b774-986b580c1efc"); -LLUUID const SND_ROLL_STONE_STONE_05 ("3d86f5a3-1a91-49d9-b99f-8521a7422497"); -LLUUID const SND_ROLL_STONE_WOOD ("53e46fb7-6c21-4fe1-bffe-0567475d48fa"); -LLUUID const SND_ROLL_STONE_WOOD_02 ("5eba8c9a-a014-4299-87f1-315c45ec795b"); -LLUUID const SND_ROLL_STONE_WOOD_03 ("ea6c05fc-6e9c-4526-8a20-bc47810bb549"); -LLUUID const SND_ROLL_STONE_WOOD_04 ("64618cbf-3f42-4728-8094-e77807545efb"); -LLUUID const SND_ROLL_WOOD_FLESH ("26ee185d-6fc3-49f8-89ba-51cab04cfc42"); -LLUUID const SND_ROLL_WOOD_FLESH_02 ("334faa25-1e80-4c99-b29f-4c9c2a3d079d"); -LLUUID const SND_ROLL_WOOD_FLESH_03 ("2f876626-4dce-4f71-a91e-a25302edfab7"); -LLUUID const SND_ROLL_WOOD_FLESH_04 ("d6877aac-07fc-4931-bcde-585f223802ad"); -LLUUID const SND_ROLL_WOOD_GRAVEL ("2a23ebb5-a4a2-4f1f-8d75-7384239354aa"); -LLUUID const SND_ROLL_WOOD_GRAVEL_02 ("208bf26d-f097-450c-95c4-9d26317c613c"); -LLUUID const SND_ROLL_WOOD_GRAVEL_03 ("a26ecaf4-92c6-4e32-9864-56b7c70cab8e"); -LLUUID const SND_ROLL_WOOD_PLASTIC ("71c1000a-9f16-4cc3-8ede-ec4aa3bf5723"); -LLUUID const SND_ROLL_WOOD_PLASTIC_02 ("7bc20ba6-1e6d-4eea-83ad-c5cc3ae0e409"); -LLUUID const SND_ROLL_WOOD_RUBBER (SND_NULL); -LLUUID const SND_ROLL_WOOD_WOOD ("2cc8eec4-bb4a-4ba8-b783-71526ec708e8"); -LLUUID const SND_ROLL_WOOD_WOOD_02 ("0a1f8070-a11a-4b4c-b260-5ffb6acb0a5d"); -LLUUID const SND_ROLL_WOOD_WOOD_03 ("160bef64-da9c-4be8-b07b-a5060b501700"); -LLUUID const SND_ROLL_WOOD_WOOD_04 ("1c62ea16-cc60-48ed-829a-68b8f4cf0c1c"); -LLUUID const SND_ROLL_WOOD_WOOD_05 ("be9cc8fe-b920-4bf5-8924-453088cbc03f"); -LLUUID const SND_ROLL_WOOD_WOOD_06 ("a76cfe60-56b0-43b1-8f31-93e56947d78b"); -LLUUID const SND_ROLL_WOOD_WOOD_07 ("0c6aa481-b5bc-4573-ae83-8e16ff27e750"); -LLUUID const SND_ROLL_WOOD_WOOD_08 ("214ab2c7-871a-451b-b0db-4c5677199011"); -LLUUID const SND_ROLL_WOOD_WOOD_09 ("0086e4db-3ac6-4545-b414-6f359bedd9a5"); +const LLUUID SND_ROLL_FLESH_FLESH (SND_NULL); +const LLUUID SND_ROLL_FLESH_PLASTIC ("89a0be4c-848d-4a6e-8886-298f56c2cff4"); +const LLUUID SND_ROLL_FLESH_PLASTIC_02 ("beb06343-1aa1-4af2-b320-5d2ec31c53b1"); +const LLUUID SND_ROLL_FLESH_RUBBER (SND_NULL); +const LLUUID SND_ROLL_GLASS_GRAVEL ("ba795c74-7e09-4572-b495-e09886a46b86"); +const LLUUID SND_ROLL_GLASS_GRAVEL_02 ("4c93c3b7-14cb-4d9b-a7df-628ad935f1f2"); +const LLUUID SND_ROLL_GLASS_FLESH (SND_NULL); +const LLUUID SND_ROLL_GLASS_GLASS (SND_NULL); +const LLUUID SND_ROLL_GLASS_PLASTIC (SND_NULL); +const LLUUID SND_ROLL_GLASS_RUBBER (SND_NULL); +const LLUUID SND_ROLL_GLASS_WOOD ("d40b1f48-a061-4f6e-b18f-4326a3dd5c29"); +const LLUUID SND_ROLL_GLASS_WOOD_02 ("78cd407a-bb36-4163-ba09-20f2e6d9d44b"); +const LLUUID SND_ROLL_GRAVEL_GRAVEL ("c7354cc3-6df5-4738-8dbb-b28a6ac46a05"); +const LLUUID SND_ROLL_GRAVEL_GRAVEL_02 ("01d194c4-72a6-47df-81a5-8db430faff87"); +const LLUUID SND_ROLL_METAL_FABRIC ("ce6e6564-20fd-48e4-81e2-cd3f81c00a3e"); +const LLUUID SND_ROLL_METAL_FABRIC_02 ("fc4d0065-32f6-4bb0-9f3f-f4737eb27163"); +const LLUUID SND_ROLL_METAL_FLESH (SND_NULL); +const LLUUID SND_ROLL_METAL_GLASS ("63d530bb-a41f-402b-aa1f-be6b11959809"); +const LLUUID SND_ROLL_METAL_GLASS_02 ("f62642c2-6db5-4faa-8b77-939067d837c3"); +const LLUUID SND_ROLL_METAL_GLASS_03 ("db5b5a15-2817-4cd7-9f0b-9ad49b5e52c8"); +const LLUUID SND_ROLL_METAL_GRAVEL ("447164e3-9646-4c1a-a16d-606892891466"); +const LLUUID SND_ROLL_METAL_METAL ("c3c22cf3-5d1f-4cc3-b4b5-708b9f65979c"); +const LLUUID SND_ROLL_METAL_METAL_02 ("d8386277-a1ea-460e-b6fd-bb285c323bf1"); +const LLUUID SND_ROLL_METAL_METAL_03 ("69ee1f02-f9cd-4c8b-aedd-39a2d6705680"); +const LLUUID SND_ROLL_METAL_METAL_04 ("5cc6b5fd-26ce-47ad-b21d-3a7c190dd375"); +const LLUUID SND_ROLL_METAL_PLASTIC ("c6a9bbf6-df15-4713-9f84-7237fce4051e"); +const LLUUID SND_ROLL_METAL_PLASTIC_01 ("0fedb59b-2dbb-4cec-b6cc-8559ec027749"); +const LLUUID SND_ROLL_METAL_RUBBER (SND_NULL); +const LLUUID SND_ROLL_METAL_WOOD ("1d76af57-01b1-4c73-9a1d-69523bfa50ea"); +const LLUUID SND_ROLL_METAL_WOOD_02 ("78aa4e71-8e7c-4b90-a561-3ebdc639f99b"); +const LLUUID SND_ROLL_METAL_WOOD_03 ("777d95bf-962f-48fa-93bf-8c1806557d72"); +const LLUUID SND_ROLL_METAL_WOOD_04 ("1833da76-45e2-4a8b-97da-d17413e056c9"); +const LLUUID SND_ROLL_METAL_WOOD_05 ("b13e1232-3d8d-42e9-92ec-b30f9f823962"); +const LLUUID SND_ROLL_PLASTIC_FABRIC ("616a1f03-209f-4c55-b264-83a000b6ef0a"); +const LLUUID SND_ROLL_PLASTIC_PLASTIC ("873f3d82-00b2-4082-9c69-7aef3461dba1"); +const LLUUID SND_ROLL_PLASTIC_PLASTIC_02 ("cc39879f-ebc8-4405-a4fc-8342f5bed31e"); +const LLUUID SND_ROLL_RUBBER_PLASTIC (SND_NULL); +const LLUUID SND_ROLL_RUBBER_RUBBER (SND_NULL); +const LLUUID SND_ROLL_STONE_FLESH (SND_NULL); +const LLUUID SND_ROLL_STONE_GLASS (SND_NULL); +const LLUUID SND_ROLL_STONE_METAL (SND_NULL); +const LLUUID SND_ROLL_STONE_PLASTIC ("155f65a8-cae7-476e-a58b-fd362be7fd0e"); +const LLUUID SND_ROLL_STONE_RUBBER (SND_NULL); +const LLUUID SND_ROLL_STONE_STONE ("67d56e3f-6ed5-4658-9418-14f020c38b11"); +const LLUUID SND_ROLL_STONE_STONE_02 ("43d99d10-d75b-4246-accf-4ceb2c909aa7"); +const LLUUID SND_ROLL_STONE_STONE_03 ("f04e83ff-eed7-4e99-8f45-eb97e4e1d3b7"); +const LLUUID SND_ROLL_STONE_STONE_04 ("10fcc5ad-fa89-48d6-b774-986b580c1efc"); +const LLUUID SND_ROLL_STONE_STONE_05 ("3d86f5a3-1a91-49d9-b99f-8521a7422497"); +const LLUUID SND_ROLL_STONE_WOOD ("53e46fb7-6c21-4fe1-bffe-0567475d48fa"); +const LLUUID SND_ROLL_STONE_WOOD_02 ("5eba8c9a-a014-4299-87f1-315c45ec795b"); +const LLUUID SND_ROLL_STONE_WOOD_03 ("ea6c05fc-6e9c-4526-8a20-bc47810bb549"); +const LLUUID SND_ROLL_STONE_WOOD_04 ("64618cbf-3f42-4728-8094-e77807545efb"); +const LLUUID SND_ROLL_WOOD_FLESH ("26ee185d-6fc3-49f8-89ba-51cab04cfc42"); +const LLUUID SND_ROLL_WOOD_FLESH_02 ("334faa25-1e80-4c99-b29f-4c9c2a3d079d"); +const LLUUID SND_ROLL_WOOD_FLESH_03 ("2f876626-4dce-4f71-a91e-a25302edfab7"); +const LLUUID SND_ROLL_WOOD_FLESH_04 ("d6877aac-07fc-4931-bcde-585f223802ad"); +const LLUUID SND_ROLL_WOOD_GRAVEL ("2a23ebb5-a4a2-4f1f-8d75-7384239354aa"); +const LLUUID SND_ROLL_WOOD_GRAVEL_02 ("208bf26d-f097-450c-95c4-9d26317c613c"); +const LLUUID SND_ROLL_WOOD_GRAVEL_03 ("a26ecaf4-92c6-4e32-9864-56b7c70cab8e"); +const LLUUID SND_ROLL_WOOD_PLASTIC ("71c1000a-9f16-4cc3-8ede-ec4aa3bf5723"); +const LLUUID SND_ROLL_WOOD_PLASTIC_02 ("7bc20ba6-1e6d-4eea-83ad-c5cc3ae0e409"); +const LLUUID SND_ROLL_WOOD_RUBBER (SND_NULL); +const LLUUID SND_ROLL_WOOD_WOOD ("2cc8eec4-bb4a-4ba8-b783-71526ec708e8"); +const LLUUID SND_ROLL_WOOD_WOOD_02 ("0a1f8070-a11a-4b4c-b260-5ffb6acb0a5d"); +const LLUUID SND_ROLL_WOOD_WOOD_03 ("160bef64-da9c-4be8-b07b-a5060b501700"); +const LLUUID SND_ROLL_WOOD_WOOD_04 ("1c62ea16-cc60-48ed-829a-68b8f4cf0c1c"); +const LLUUID SND_ROLL_WOOD_WOOD_05 ("be9cc8fe-b920-4bf5-8924-453088cbc03f"); +const LLUUID SND_ROLL_WOOD_WOOD_06 ("a76cfe60-56b0-43b1-8f31-93e56947d78b"); +const LLUUID SND_ROLL_WOOD_WOOD_07 ("0c6aa481-b5bc-4573-ae83-8e16ff27e750"); +const LLUUID SND_ROLL_WOOD_WOOD_08 ("214ab2c7-871a-451b-b0db-4c5677199011"); +const LLUUID SND_ROLL_WOOD_WOOD_09 ("0086e4db-3ac6-4545-b414-6f359bedd9a5"); -LLUUID const SND_SLIDE_STONE_STONE_01 ("2a7dcbd1-d3e6-4767-8432-8322648e7b9d"); +const LLUUID SND_SLIDE_STONE_STONE_01 ("2a7dcbd1-d3e6-4767-8432-8322648e7b9d"); -LLUUID const SND_STONE_DIRT_01 ("97727335-392c-4338-ac4b-23a7883279c2"); -LLUUID const SND_STONE_DIRT_02 ("cbe75eb2-3375-41d8-9e3f-2ae46b4164ed"); -LLUUID const SND_STONE_DIRT_03 ("31e236ee-001b-4c8e-ad6c-c2074cb64357"); -LLUUID const SND_STONE_DIRT_04 ("c8091652-e04b-4a11-84ba-15dba06e7a1b"); +const LLUUID SND_STONE_DIRT_01 ("97727335-392c-4338-ac4b-23a7883279c2"); +const LLUUID SND_STONE_DIRT_02 ("cbe75eb2-3375-41d8-9e3f-2ae46b4164ed"); +const LLUUID SND_STONE_DIRT_03 ("31e236ee-001b-4c8e-ad6c-c2074cb64357"); +const LLUUID SND_STONE_DIRT_04 ("c8091652-e04b-4a11-84ba-15dba06e7a1b"); -LLUUID const SND_STONE_STONE_02 ("ba4ef5ac-7435-4240-b826-c24ba8fa5a78"); -LLUUID const SND_STONE_STONE_04 ("ea296329-0f09-4993-af1b-e6784bab1dc9"); +const LLUUID SND_STONE_STONE_02 ("ba4ef5ac-7435-4240-b826-c24ba8fa5a78"); +const LLUUID SND_STONE_STONE_04 ("ea296329-0f09-4993-af1b-e6784bab1dc9"); + + + +// extra guids +#if 0 +const LLUUID SND_ ("a839b8ac-b0af-4ba9-9fde-188754744e02"); +const LLUUID SND_ ("20165fa8-836f-4993-85dc-1529172dcd14"); +const LLUUID SND_ ("fba8e17b-a4b3-4693-9fce-c14800f8a349"); +const LLUUID SND_ ("2d48db8b-7260-4b02-ad2a-b2c6bee60e94"); +const LLUUID SND_ ("956d344b-1808-4d8b-88b1-cbc82b7a96a1"); +const LLUUID SND_ ("b8303cc6-f0b4-4c6f-a199-81f87aba342e"); +const LLUUID SND_ ("fbf7cd0c-bc8f-4cba-9c19-11f4dd03a06b"); +const LLUUID SND_ ("85047f7d-933a-4ce5-a7b5-34670243e1ab"); +const LLUUID SND_ ("0f81acf7-6a2e-4490-957f-c7b0eda00559"); +const LLUUID SND_ ("5631a6a1-79b4-4de8-bccf-1880b6882da1"); +const LLUUID SND_ ("43c87a6b-ffb2-437b-89a0-9deba890a4fc"); +const LLUUID SND_ ("58878d1d-3156-4d01-ac3c-0c4fb99f4d53"); +const LLUUID SND_ ("9a83f321-44bf-40f6-b006-46c085515345"); +const LLUUID SND_ ("ff144533-33ab-40f2-bac8-39c34699ecc4"); +const LLUUID SND_ ("09018e87-d52c-4cd5-9805-015f413319e7"); +const LLUUID SND_ ("17d4c057-7edd-401e-9589-d5b9fe981bf2"); +#endif diff --git a/indra/llmessage/sound_ids.h b/indra/llmessage/sound_ids.h index aa50a2b88..f67fdd2aa 100644 --- a/indra/llmessage/sound_ids.h +++ b/indra/llmessage/sound_ids.h @@ -39,9 +39,9 @@ class LLUUID; extern const LLUUID SND_NULL; -extern LLUUID const SND_RIDE; -extern LLUUID const SND_SHOT; -extern LLUUID const SND_MORTAR; +extern const LLUUID SND_RIDE; +extern const LLUUID SND_SHOT; +extern const LLUUID SND_MORTAR; extern const LLUUID SND_HIT; extern const LLUUID SND_EXPLOSION; extern const LLUUID SND_BOING; @@ -58,237 +58,238 @@ extern const LLUUID SND_CHIRPDEAD; // Hit by grenade - dead! extern const LLUUID SND_MUNCH; extern const LLUUID SND_PUNCH; -extern LLUUID const SND_SPLASH; -extern LLUUID const SND_CLICK; -extern LLUUID const SND_WHISTLE; -extern LLUUID const SND_TYPING; +extern const LLUUID SND_SPLASH; +extern const LLUUID SND_CLICK; +extern const LLUUID SND_WHISTLE; +extern const LLUUID SND_TYPING; -extern LLUUID const SND_ARROW_SHOT; -extern LLUUID const SND_ARROW_THUD; -extern LLUUID const SND_LASER_SHOT; -extern LLUUID const SND_JET_THRUST; +extern const LLUUID SND_ARROW_SHOT; +extern const LLUUID SND_ARROW_THUD; +extern const LLUUID SND_LASER_SHOT; +extern const LLUUID SND_JET_THRUST; -extern LLUUID const SND_SILENCE; -extern LLUUID const SND_BUBBLES; -extern LLUUID const SND_WELCOME; -extern LLUUID const SND_SQUISH; -extern LLUUID const SND_SUBPOD; -extern LLUUID const SND_FOOTSTEPS; -extern LLUUID const SND_STEP_LEFT; -extern LLUUID const SND_STEP_RIGHT; +extern const LLUUID SND_SILENCE; +extern const LLUUID SND_BUBBLES; +extern const LLUUID SND_WELCOME; +extern const LLUUID SND_SQUISH; +extern const LLUUID SND_SUBPOD; +extern const LLUUID SND_FOOTSTEPS; +extern const LLUUID SND_STEP_LEFT; +extern const LLUUID SND_STEP_RIGHT; -extern LLUUID const SND_BALL_COLLISION; +extern const LLUUID SND_BALL_COLLISION; -extern LLUUID const SND_OOOH_SCARE_ME; -extern LLUUID const SND_PAYBACK_TIME; -extern LLUUID const SND_READY_FOR_BATTLE; +extern const LLUUID SND_OOOH_SCARE_ME; +extern const LLUUID SND_PAYBACK_TIME; +extern const LLUUID SND_READY_FOR_BATTLE; -extern LLUUID const SND_FLESH_FLESH; -extern LLUUID const SND_FLESH_PLASTIC; -extern LLUUID const SND_FLESH_RUBBER; -extern LLUUID const SND_GLASS_FLESH; -extern LLUUID const SND_GLASS_GLASS; -extern LLUUID const SND_GLASS_PLASTIC; -extern LLUUID const SND_GLASS_RUBBER; -extern LLUUID const SND_GLASS_WOOD; -extern LLUUID const SND_METAL_FLESH; -extern LLUUID const SND_METAL_GLASS; -extern LLUUID const SND_METAL_METAL; -extern LLUUID const SND_METAL_PLASTIC; -extern LLUUID const SND_METAL_RUBBER; -extern LLUUID const SND_METAL_WOOD; -extern LLUUID const SND_PLASTIC_PLASTIC; -extern LLUUID const SND_RUBBER_PLASTIC; -extern LLUUID const SND_RUBBER_RUBBER; -extern LLUUID const SND_STONE_FLESH; -extern LLUUID const SND_STONE_GLASS; -extern LLUUID const SND_STONE_METAL; -extern LLUUID const SND_STONE_PLASTIC; -extern LLUUID const SND_STONE_RUBBER; -extern LLUUID const SND_STONE_STONE; -extern LLUUID const SND_STONE_WOOD; -extern LLUUID const SND_WOOD_FLESH; -extern LLUUID const SND_WOOD_PLASTIC; -extern LLUUID const SND_WOOD_RUBBER; -extern LLUUID const SND_WOOD_WOOD; - -extern LLUUID const SND_SLIDE_FLESH_FLESH; -extern LLUUID const SND_SLIDE_FLESH_PLASTIC; -extern LLUUID const SND_SLIDE_FLESH_RUBBER; -extern LLUUID const SND_SLIDE_FLESH_FABRIC; -extern LLUUID const SND_SLIDE_FLESH_GRAVEL; -extern LLUUID const SND_SLIDE_FLESH_GRAVEL_02; -extern LLUUID const SND_SLIDE_FLESH_GRAVEL_03; -extern LLUUID const SND_SLIDE_GLASS_GRAVEL; -extern LLUUID const SND_SLIDE_GLASS_GRAVEL_02; -extern LLUUID const SND_SLIDE_GLASS_GRAVEL_03; -extern LLUUID const SND_SLIDE_GLASS_FLESH; -extern LLUUID const SND_SLIDE_GLASS_GLASS; -extern LLUUID const SND_SLIDE_GLASS_PLASTIC; -extern LLUUID const SND_SLIDE_GLASS_RUBBER; -extern LLUUID const SND_SLIDE_GLASS_WOOD; -extern LLUUID const SND_SLIDE_METAL_FABRIC; -extern LLUUID const SND_SLIDE_METAL_FLESH; -extern LLUUID const SND_SLIDE_METAL_FLESH_02; -extern LLUUID const SND_SLIDE_METAL_GLASS; -extern LLUUID const SND_SLIDE_METAL_GLASS_02; -extern LLUUID const SND_SLIDE_METAL_GLASS_03; -extern LLUUID const SND_SLIDE_METAL_GLASS_04; -extern LLUUID const SND_SLIDE_METAL_GRAVEL; -extern LLUUID const SND_SLIDE_METAL_GRAVEL_02; -extern LLUUID const SND_SLIDE_METAL_METAL; -extern LLUUID const SND_SLIDE_METAL_METAL_02; -extern LLUUID const SND_SLIDE_METAL_METAL_03; -extern LLUUID const SND_SLIDE_METAL_METAL_04; -extern LLUUID const SND_SLIDE_METAL_METAL_05; -extern LLUUID const SND_SLIDE_METAL_METAL_06; -extern LLUUID const SND_SLIDE_METAL_PLASTIC; -extern LLUUID const SND_SLIDE_METAL_RUBBER; -extern LLUUID const SND_SLIDE_METAL_WOOD; -extern LLUUID const SND_SLIDE_METAL_WOOD_02; -extern LLUUID const SND_SLIDE_METAL_WOOD_03; -extern LLUUID const SND_SLIDE_METAL_WOOD_04; -extern LLUUID const SND_SLIDE_METAL_WOOD_05; -extern LLUUID const SND_SLIDE_METAL_WOOD_06; -extern LLUUID const SND_SLIDE_METAL_WOOD_07; -extern LLUUID const SND_SLIDE_METAL_WOOD_08; -extern LLUUID const SND_SLIDE_PLASTIC_GRAVEL; -extern LLUUID const SND_SLIDE_PLASTIC_GRAVEL_02; -extern LLUUID const SND_SLIDE_PLASTIC_GRAVEL_03; -extern LLUUID const SND_SLIDE_PLASTIC_GRAVEL_04; -extern LLUUID const SND_SLIDE_PLASTIC_GRAVEL_05; -extern LLUUID const SND_SLIDE_PLASTIC_GRAVEL_06; -extern LLUUID const SND_SLIDE_PLASTIC_PLASTIC; -extern LLUUID const SND_SLIDE_PLASTIC_PLASTIC_02; -extern LLUUID const SND_SLIDE_PLASTIC_PLASTIC_03; -extern LLUUID const SND_SLIDE_PLASTIC_FABRIC; -extern LLUUID const SND_SLIDE_PLASTIC_FABRIC_02; -extern LLUUID const SND_SLIDE_PLASTIC_FABRIC_03; -extern LLUUID const SND_SLIDE_PLASTIC_FABRIC_04; -extern LLUUID const SND_SLIDE_RUBBER_PLASTIC; -extern LLUUID const SND_SLIDE_RUBBER_PLASTIC_02; -extern LLUUID const SND_SLIDE_RUBBER_PLASTIC_03; -extern LLUUID const SND_SLIDE_RUBBER_RUBBER; -extern LLUUID const SND_SLIDE_STONE_FLESH; -extern LLUUID const SND_SLIDE_STONE_GLASS; -extern LLUUID const SND_SLIDE_STONE_METAL; -extern LLUUID const SND_SLIDE_STONE_PLASTIC; -extern LLUUID const SND_SLIDE_STONE_PLASTIC_02; -extern LLUUID const SND_SLIDE_STONE_PLASTIC_03; -extern LLUUID const SND_SLIDE_STONE_RUBBER; -extern LLUUID const SND_SLIDE_STONE_RUBBER_02; -extern LLUUID const SND_SLIDE_STONE_STONE; -extern LLUUID const SND_SLIDE_STONE_STONE_02; -extern LLUUID const SND_SLIDE_STONE_WOOD; -extern LLUUID const SND_SLIDE_STONE_WOOD_02; -extern LLUUID const SND_SLIDE_STONE_WOOD_03; -extern LLUUID const SND_SLIDE_STONE_WOOD_04; -extern LLUUID const SND_SLIDE_WOOD_FABRIC; -extern LLUUID const SND_SLIDE_WOOD_FABRIC_02; -extern LLUUID const SND_SLIDE_WOOD_FABRIC_03; -extern LLUUID const SND_SLIDE_WOOD_FABRIC_04; -extern LLUUID const SND_SLIDE_WOOD_FLESH; -extern LLUUID const SND_SLIDE_WOOD_FLESH_02; -extern LLUUID const SND_SLIDE_WOOD_FLESH_03; -extern LLUUID const SND_SLIDE_WOOD_FLESH_04; -extern LLUUID const SND_SLIDE_WOOD_GRAVEL; -extern LLUUID const SND_SLIDE_WOOD_GRAVEL_02; -extern LLUUID const SND_SLIDE_WOOD_GRAVEL_03; -extern LLUUID const SND_SLIDE_WOOD_GRAVEL_04; -extern LLUUID const SND_SLIDE_WOOD_PLASTIC; -extern LLUUID const SND_SLIDE_WOOD_PLASTIC_02; -extern LLUUID const SND_SLIDE_WOOD_PLASTIC_03; -extern LLUUID const SND_SLIDE_WOOD_RUBBER; -extern LLUUID const SND_SLIDE_WOOD_WOOD; -extern LLUUID const SND_SLIDE_WOOD_WOOD_02; -extern LLUUID const SND_SLIDE_WOOD_WOOD_03; -extern LLUUID const SND_SLIDE_WOOD_WOOD_04; -extern LLUUID const SND_SLIDE_WOOD_WOOD_05; -extern LLUUID const SND_SLIDE_WOOD_WOOD_06; -extern LLUUID const SND_SLIDE_WOOD_WOOD_07; -extern LLUUID const SND_SLIDE_WOOD_WOOD_08; +extern const LLUUID SND_FLESH_FLESH; +extern const LLUUID SND_FLESH_PLASTIC; +extern const LLUUID SND_FLESH_RUBBER; +extern const LLUUID SND_GLASS_FLESH; +extern const LLUUID SND_GLASS_GLASS; +extern const LLUUID SND_GLASS_PLASTIC; +extern const LLUUID SND_GLASS_RUBBER; +extern const LLUUID SND_GLASS_WOOD; +extern const LLUUID SND_METAL_FLESH; +extern const LLUUID SND_METAL_GLASS; +extern const LLUUID SND_METAL_METAL; +extern const LLUUID SND_METAL_PLASTIC; +extern const LLUUID SND_METAL_RUBBER; +extern const LLUUID SND_METAL_WOOD; +extern const LLUUID SND_PLASTIC_PLASTIC; +extern const LLUUID SND_RUBBER_PLASTIC; +extern const LLUUID SND_RUBBER_RUBBER; +extern const LLUUID SND_STONE_FLESH; +extern const LLUUID SND_STONE_GLASS; +extern const LLUUID SND_STONE_METAL; +extern const LLUUID SND_STONE_PLASTIC; +extern const LLUUID SND_STONE_RUBBER; +extern const LLUUID SND_STONE_STONE; +extern const LLUUID SND_STONE_WOOD; +extern const LLUUID SND_WOOD_FLESH; +extern const LLUUID SND_WOOD_PLASTIC; +extern const LLUUID SND_WOOD_RUBBER; +extern const LLUUID SND_WOOD_WOOD; -extern LLUUID const SND_ROLL_FLESH_FLESH; -extern LLUUID const SND_ROLL_FLESH_PLASTIC; -extern LLUUID const SND_ROLL_FLESH_PLASTIC_02; -extern LLUUID const SND_ROLL_FLESH_RUBBER; -extern LLUUID const SND_ROLL_GLASS_GRAVEL; -extern LLUUID const SND_ROLL_GLASS_GRAVEL_02; -extern LLUUID const SND_ROLL_GLASS_FLESH; -extern LLUUID const SND_ROLL_GLASS_GLASS; -extern LLUUID const SND_ROLL_GLASS_PLASTIC; -extern LLUUID const SND_ROLL_GLASS_RUBBER; -extern LLUUID const SND_ROLL_GLASS_WOOD; -extern LLUUID const SND_ROLL_GLASS_WOOD_02; -extern LLUUID const SND_ROLL_GRAVEL_GRAVEL; -extern LLUUID const SND_ROLL_GRAVEL_GRAVEL_02; -extern LLUUID const SND_ROLL_METAL_FABRIC; -extern LLUUID const SND_ROLL_METAL_FABRIC_02; -extern LLUUID const SND_ROLL_METAL_FLESH; -extern LLUUID const SND_ROLL_METAL_GLASS; -extern LLUUID const SND_ROLL_METAL_GLASS_02; -extern LLUUID const SND_ROLL_METAL_GLASS_03; -extern LLUUID const SND_ROLL_METAL_GRAVEL; -extern LLUUID const SND_ROLL_METAL_METAL; -extern LLUUID const SND_ROLL_METAL_METAL_02; -extern LLUUID const SND_ROLL_METAL_METAL_03; -extern LLUUID const SND_ROLL_METAL_METAL_04; -extern LLUUID const SND_ROLL_METAL_PLASTIC; -extern LLUUID const SND_ROLL_METAL_PLASTIC_01; -extern LLUUID const SND_ROLL_METAL_RUBBER; -extern LLUUID const SND_ROLL_METAL_WOOD; -extern LLUUID const SND_ROLL_METAL_WOOD_02; -extern LLUUID const SND_ROLL_METAL_WOOD_03; -extern LLUUID const SND_ROLL_METAL_WOOD_04; -extern LLUUID const SND_ROLL_METAL_WOOD_05; -extern LLUUID const SND_ROLL_PLASTIC_FABRIC; -extern LLUUID const SND_ROLL_PLASTIC_PLASTIC; -extern LLUUID const SND_ROLL_PLASTIC_PLASTIC_02; -extern LLUUID const SND_ROLL_RUBBER_PLASTIC; -extern LLUUID const SND_ROLL_RUBBER_RUBBER; -extern LLUUID const SND_ROLL_STONE_FLESH; -extern LLUUID const SND_ROLL_STONE_GLASS; -extern LLUUID const SND_ROLL_STONE_METAL; -extern LLUUID const SND_ROLL_STONE_PLASTIC; -extern LLUUID const SND_ROLL_STONE_RUBBER; -extern LLUUID const SND_ROLL_STONE_STONE; -extern LLUUID const SND_ROLL_STONE_STONE_02; -extern LLUUID const SND_ROLL_STONE_STONE_03; -extern LLUUID const SND_ROLL_STONE_STONE_04; -extern LLUUID const SND_ROLL_STONE_STONE_05; -extern LLUUID const SND_ROLL_STONE_WOOD; -extern LLUUID const SND_ROLL_STONE_WOOD_02; -extern LLUUID const SND_ROLL_STONE_WOOD_03; -extern LLUUID const SND_ROLL_STONE_WOOD_04; -extern LLUUID const SND_ROLL_WOOD_FLESH; -extern LLUUID const SND_ROLL_WOOD_FLESH_02; -extern LLUUID const SND_ROLL_WOOD_FLESH_03; -extern LLUUID const SND_ROLL_WOOD_FLESH_04; -extern LLUUID const SND_ROLL_WOOD_GRAVEL; -extern LLUUID const SND_ROLL_WOOD_GRAVEL_02; -extern LLUUID const SND_ROLL_WOOD_GRAVEL_03; -extern LLUUID const SND_ROLL_WOOD_PLASTIC; -extern LLUUID const SND_ROLL_WOOD_PLASTIC_02; -extern LLUUID const SND_ROLL_WOOD_RUBBER; -extern LLUUID const SND_ROLL_WOOD_WOOD; -extern LLUUID const SND_ROLL_WOOD_WOOD_02; -extern LLUUID const SND_ROLL_WOOD_WOOD_03; -extern LLUUID const SND_ROLL_WOOD_WOOD_04; -extern LLUUID const SND_ROLL_WOOD_WOOD_05; -extern LLUUID const SND_ROLL_WOOD_WOOD_06; -extern LLUUID const SND_ROLL_WOOD_WOOD_07; -extern LLUUID const SND_ROLL_WOOD_WOOD_08; -extern LLUUID const SND_ROLL_WOOD_WOOD_09; +extern const LLUUID SND_SLIDE_FLESH_FLESH; +extern const LLUUID SND_SLIDE_FLESH_PLASTIC; +extern const LLUUID SND_SLIDE_FLESH_RUBBER; +extern const LLUUID SND_SLIDE_FLESH_FABRIC; +extern const LLUUID SND_SLIDE_FLESH_GRAVEL; +extern const LLUUID SND_SLIDE_FLESH_GRAVEL_02; +extern const LLUUID SND_SLIDE_FLESH_GRAVEL_03; +extern const LLUUID SND_SLIDE_GLASS_GRAVEL; +extern const LLUUID SND_SLIDE_GLASS_GRAVEL_02; +extern const LLUUID SND_SLIDE_GLASS_GRAVEL_03; +extern const LLUUID SND_SLIDE_GLASS_FLESH; +extern const LLUUID SND_SLIDE_GLASS_GLASS; +extern const LLUUID SND_SLIDE_GLASS_PLASTIC; +extern const LLUUID SND_SLIDE_GLASS_RUBBER; +extern const LLUUID SND_SLIDE_GLASS_WOOD; +extern const LLUUID SND_SLIDE_METAL_FABRIC; +extern const LLUUID SND_SLIDE_METAL_FLESH; +extern const LLUUID SND_SLIDE_METAL_FLESH_02; +extern const LLUUID SND_SLIDE_METAL_GLASS; +extern const LLUUID SND_SLIDE_METAL_GLASS_02; +extern const LLUUID SND_SLIDE_METAL_GLASS_03; +extern const LLUUID SND_SLIDE_METAL_GLASS_04; +extern const LLUUID SND_SLIDE_METAL_GRAVEL; +extern const LLUUID SND_SLIDE_METAL_GRAVEL_02; +extern const LLUUID SND_SLIDE_METAL_METAL; +extern const LLUUID SND_SLIDE_METAL_METAL_02; +extern const LLUUID SND_SLIDE_METAL_METAL_03; +extern const LLUUID SND_SLIDE_METAL_METAL_04; +extern const LLUUID SND_SLIDE_METAL_METAL_05; +extern const LLUUID SND_SLIDE_METAL_METAL_06; +extern const LLUUID SND_SLIDE_METAL_PLASTIC; +extern const LLUUID SND_SLIDE_METAL_RUBBER; +extern const LLUUID SND_SLIDE_METAL_WOOD; +extern const LLUUID SND_SLIDE_METAL_WOOD_02; +extern const LLUUID SND_SLIDE_METAL_WOOD_03; +extern const LLUUID SND_SLIDE_METAL_WOOD_04; +extern const LLUUID SND_SLIDE_METAL_WOOD_05; +extern const LLUUID SND_SLIDE_METAL_WOOD_06; +extern const LLUUID SND_SLIDE_METAL_WOOD_07; +extern const LLUUID SND_SLIDE_METAL_WOOD_08; +extern const LLUUID SND_SLIDE_PLASTIC_GRAVEL; +extern const LLUUID SND_SLIDE_PLASTIC_GRAVEL_02; +extern const LLUUID SND_SLIDE_PLASTIC_GRAVEL_03; +extern const LLUUID SND_SLIDE_PLASTIC_GRAVEL_04; +extern const LLUUID SND_SLIDE_PLASTIC_GRAVEL_05; +extern const LLUUID SND_SLIDE_PLASTIC_GRAVEL_06; +extern const LLUUID SND_SLIDE_PLASTIC_PLASTIC; +extern const LLUUID SND_SLIDE_PLASTIC_PLASTIC_02; +extern const LLUUID SND_SLIDE_PLASTIC_PLASTIC_03; +extern const LLUUID SND_SLIDE_PLASTIC_FABRIC; +extern const LLUUID SND_SLIDE_PLASTIC_FABRIC_02; +extern const LLUUID SND_SLIDE_PLASTIC_FABRIC_03; +extern const LLUUID SND_SLIDE_PLASTIC_FABRIC_04; +extern const LLUUID SND_SLIDE_RUBBER_PLASTIC; +extern const LLUUID SND_SLIDE_RUBBER_PLASTIC_02; +extern const LLUUID SND_SLIDE_RUBBER_PLASTIC_03; +extern const LLUUID SND_SLIDE_RUBBER_RUBBER; +extern const LLUUID SND_SLIDE_STONE_FLESH; +extern const LLUUID SND_SLIDE_STONE_GLASS; +extern const LLUUID SND_SLIDE_STONE_METAL; +extern const LLUUID SND_SLIDE_STONE_PLASTIC; +extern const LLUUID SND_SLIDE_STONE_PLASTIC_02; +extern const LLUUID SND_SLIDE_STONE_PLASTIC_03; +extern const LLUUID SND_SLIDE_STONE_RUBBER; +extern const LLUUID SND_SLIDE_STONE_RUBBER_02; +extern const LLUUID SND_SLIDE_STONE_STONE; +extern const LLUUID SND_SLIDE_STONE_STONE_02; +extern const LLUUID SND_SLIDE_STONE_WOOD; +extern const LLUUID SND_SLIDE_STONE_WOOD_02; +extern const LLUUID SND_SLIDE_STONE_WOOD_03; +extern const LLUUID SND_SLIDE_STONE_WOOD_04; +extern const LLUUID SND_SLIDE_WOOD_FABRIC; +extern const LLUUID SND_SLIDE_WOOD_FABRIC_02; +extern const LLUUID SND_SLIDE_WOOD_FABRIC_03; +extern const LLUUID SND_SLIDE_WOOD_FABRIC_04; +extern const LLUUID SND_SLIDE_WOOD_FLESH; +extern const LLUUID SND_SLIDE_WOOD_FLESH_02; +extern const LLUUID SND_SLIDE_WOOD_FLESH_03; +extern const LLUUID SND_SLIDE_WOOD_FLESH_04; +extern const LLUUID SND_SLIDE_WOOD_GRAVEL; +extern const LLUUID SND_SLIDE_WOOD_GRAVEL_02; +extern const LLUUID SND_SLIDE_WOOD_GRAVEL_03; +extern const LLUUID SND_SLIDE_WOOD_GRAVEL_04; +extern const LLUUID SND_SLIDE_WOOD_PLASTIC; +extern const LLUUID SND_SLIDE_WOOD_PLASTIC_02; +extern const LLUUID SND_SLIDE_WOOD_PLASTIC_03; +extern const LLUUID SND_SLIDE_WOOD_RUBBER; +extern const LLUUID SND_SLIDE_WOOD_WOOD; +extern const LLUUID SND_SLIDE_WOOD_WOOD_02; +extern const LLUUID SND_SLIDE_WOOD_WOOD_03; +extern const LLUUID SND_SLIDE_WOOD_WOOD_04; +extern const LLUUID SND_SLIDE_WOOD_WOOD_05; +extern const LLUUID SND_SLIDE_WOOD_WOOD_06; +extern const LLUUID SND_SLIDE_WOOD_WOOD_07; +extern const LLUUID SND_SLIDE_WOOD_WOOD_08; -extern LLUUID const SND_SLIDE_STONE_STONE_01; -extern LLUUID const SND_STONE_DIRT_01; -extern LLUUID const SND_STONE_DIRT_02; -extern LLUUID const SND_STONE_DIRT_03; -extern LLUUID const SND_STONE_DIRT_04; +extern const LLUUID SND_ROLL_FLESH_FLESH; +extern const LLUUID SND_ROLL_FLESH_PLASTIC; +extern const LLUUID SND_ROLL_FLESH_PLASTIC_02; +extern const LLUUID SND_ROLL_FLESH_RUBBER; +extern const LLUUID SND_ROLL_GLASS_GRAVEL; +extern const LLUUID SND_ROLL_GLASS_GRAVEL_02; +extern const LLUUID SND_ROLL_GLASS_FLESH; +extern const LLUUID SND_ROLL_GLASS_GLASS; +extern const LLUUID SND_ROLL_GLASS_PLASTIC; +extern const LLUUID SND_ROLL_GLASS_RUBBER; +extern const LLUUID SND_ROLL_GLASS_WOOD; +extern const LLUUID SND_ROLL_GLASS_WOOD_02; +extern const LLUUID SND_ROLL_GRAVEL_GRAVEL; +extern const LLUUID SND_ROLL_GRAVEL_GRAVEL_02; +extern const LLUUID SND_ROLL_METAL_FABRIC; +extern const LLUUID SND_ROLL_METAL_FABRIC_02; +extern const LLUUID SND_ROLL_METAL_FLESH; +extern const LLUUID SND_ROLL_METAL_GLASS; +extern const LLUUID SND_ROLL_METAL_GLASS_02; +extern const LLUUID SND_ROLL_METAL_GLASS_03; +extern const LLUUID SND_ROLL_METAL_GRAVEL; +extern const LLUUID SND_ROLL_METAL_METAL; +extern const LLUUID SND_ROLL_METAL_METAL_02; +extern const LLUUID SND_ROLL_METAL_METAL_03; +extern const LLUUID SND_ROLL_METAL_METAL_04; +extern const LLUUID SND_ROLL_METAL_PLASTIC; +extern const LLUUID SND_ROLL_METAL_PLASTIC_01; +extern const LLUUID SND_ROLL_METAL_RUBBER; +extern const LLUUID SND_ROLL_METAL_WOOD; +extern const LLUUID SND_ROLL_METAL_WOOD_02; +extern const LLUUID SND_ROLL_METAL_WOOD_03; +extern const LLUUID SND_ROLL_METAL_WOOD_04; +extern const LLUUID SND_ROLL_METAL_WOOD_05; +extern const LLUUID SND_ROLL_PLASTIC_FABRIC; +extern const LLUUID SND_ROLL_PLASTIC_PLASTIC; +extern const LLUUID SND_ROLL_PLASTIC_PLASTIC_02; +extern const LLUUID SND_ROLL_RUBBER_PLASTIC; +extern const LLUUID SND_ROLL_RUBBER_RUBBER; +extern const LLUUID SND_ROLL_STONE_FLESH; +extern const LLUUID SND_ROLL_STONE_GLASS; +extern const LLUUID SND_ROLL_STONE_METAL; +extern const LLUUID SND_ROLL_STONE_PLASTIC; +extern const LLUUID SND_ROLL_STONE_RUBBER; +extern const LLUUID SND_ROLL_STONE_STONE; +extern const LLUUID SND_ROLL_STONE_STONE_02; +extern const LLUUID SND_ROLL_STONE_STONE_03; +extern const LLUUID SND_ROLL_STONE_STONE_04; +extern const LLUUID SND_ROLL_STONE_STONE_05; +extern const LLUUID SND_ROLL_STONE_WOOD; +extern const LLUUID SND_ROLL_STONE_WOOD_02; +extern const LLUUID SND_ROLL_STONE_WOOD_03; +extern const LLUUID SND_ROLL_STONE_WOOD_04; +extern const LLUUID SND_ROLL_WOOD_FLESH; +extern const LLUUID SND_ROLL_WOOD_FLESH_02; +extern const LLUUID SND_ROLL_WOOD_FLESH_03; +extern const LLUUID SND_ROLL_WOOD_FLESH_04; +extern const LLUUID SND_ROLL_WOOD_GRAVEL; +extern const LLUUID SND_ROLL_WOOD_GRAVEL_02; +extern const LLUUID SND_ROLL_WOOD_GRAVEL_03; +extern const LLUUID SND_ROLL_WOOD_PLASTIC; +extern const LLUUID SND_ROLL_WOOD_PLASTIC_02; +extern const LLUUID SND_ROLL_WOOD_RUBBER; +extern const LLUUID SND_ROLL_WOOD_WOOD; +extern const LLUUID SND_ROLL_WOOD_WOOD_02; +extern const LLUUID SND_ROLL_WOOD_WOOD_03; +extern const LLUUID SND_ROLL_WOOD_WOOD_04; +extern const LLUUID SND_ROLL_WOOD_WOOD_05; +extern const LLUUID SND_ROLL_WOOD_WOOD_06; +extern const LLUUID SND_ROLL_WOOD_WOOD_07; +extern const LLUUID SND_ROLL_WOOD_WOOD_08; +extern const LLUUID SND_ROLL_WOOD_WOOD_09; -extern LLUUID const SND_STONE_STONE_02; -extern LLUUID const SND_STONE_STONE_04; +extern const LLUUID SND_SLIDE_STONE_STONE_01; + +extern const LLUUID SND_STONE_DIRT_01; +extern const LLUUID SND_STONE_DIRT_02; +extern const LLUUID SND_STONE_DIRT_03; +extern const LLUUID SND_STONE_DIRT_04; + +extern const LLUUID SND_STONE_STONE_02; +extern const LLUUID SND_STONE_STONE_04; #endif diff --git a/indra/llplugin/CMakeLists.txt b/indra/llplugin/CMakeLists.txt index 63a7ad75b..4b5420b6b 100644 --- a/indra/llplugin/CMakeLists.txt +++ b/indra/llplugin/CMakeLists.txt @@ -24,6 +24,7 @@ include_directories( ) set(llplugin_SOURCE_FILES + llpluginclassbasic.cpp llpluginclassmedia.cpp llplugincookiestore.cpp llplugininstance.cpp @@ -37,6 +38,7 @@ set(llplugin_SOURCE_FILES set(llplugin_HEADER_FILES CMakeLists.txt + llpluginclassbasic.h llpluginclassmedia.h llpluginclassmediaowner.h llplugincookiestore.h diff --git a/indra/llplugin/llpluginclassbasic.cpp b/indra/llplugin/llpluginclassbasic.cpp new file mode 100644 index 000000000..0567b157f --- /dev/null +++ b/indra/llplugin/llpluginclassbasic.cpp @@ -0,0 +1,189 @@ +/** + * @file llpluginclassbasic.cpp + * @brief LLPluginClassBasic handles a plugin which knows about the "basic" message class. + * + * @cond + * $LicenseInfo:firstyear=2010&license=viewergpl$ + * + * Copyright (c) 2010, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlife.com/developers/opensource/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlife.com/developers/opensource/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + * + * @endcond + */ + +#include "linden_common.h" +#include "indra_constants.h" + +#include "llpluginclassbasic.h" +#include "llpluginmessageclasses.h" + +LLPluginClassBasic::LLPluginClassBasic(void) : mPlugin(NULL), mDeleteOK(true) +{ + // Note that this only initializes the base class, the derived class doesn't exist yet! + // Derived classes must therefore call their own reset_impl() from their constructor. + reset(); +} + +LLPluginClassBasic::~LLPluginClassBasic() +{ + llassert_always(mDeleteOK); + delete mPlugin; +} + +bool LLPluginClassBasic::init(std::string const& launcher_filename, std::string const& plugin_filename, bool debug) +{ + LL_DEBUGS("Plugin") << "launcher: " << launcher_filename << LL_ENDL; + LL_DEBUGS("Plugin") << "plugin: " << plugin_filename << LL_ENDL; + + mPlugin = new LLPluginProcessParent(this); + mPlugin->setSleepTime(mSleepTime); + + mPlugin->init(launcher_filename, plugin_filename, debug); + + return init_impl(); +} + +void LLPluginClassBasic::reset() +{ + if (mPlugin != NULL) + { + delete mPlugin; + mPlugin = NULL; + } + mSleepTime = 1.0f / 50.0f; + mPriority = PRIORITY_NORMAL; + reset_impl(); +} + +void LLPluginClassBasic::idle(void) +{ + if(mPlugin) + { + mPlugin->idle(); + } + + idle_impl(); + + if(mPlugin && mPlugin->isRunning()) + { + // Send queued messages + while(!mSendQueue.empty()) + { + LLPluginMessage message = mSendQueue.front(); + mSendQueue.pop(); + mPlugin->sendMessage(message); + } + } +} + +char const* LLPluginClassBasic::priorityToString(EPriority priority) +{ + const char* result = "UNKNOWN"; + switch(priority) + { + case PRIORITY_SLEEP: result = "sleep"; break; + case PRIORITY_LOW: result = "low"; break; + case PRIORITY_NORMAL: result = "normal"; break; + case PRIORITY_HIGH: result = "high"; break; + } + + return result; +} + +void LLPluginClassBasic::setPriority(EPriority priority) +{ + if (mPriority != priority) + { + mPriority = priority; + + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_BASIC, "set_priority"); + + std::string priority_string = priorityToString(priority); + switch(priority) + { + case PRIORITY_SLEEP: + mSleepTime = 1.0f; + break; + case PRIORITY_LOW: + mSleepTime = 1.0f / 25.0f; + break; + case PRIORITY_NORMAL: + mSleepTime = 1.0f / 50.0f; + break; + case PRIORITY_HIGH: + mSleepTime = 1.0f / 100.0f; + break; + } + + message.setValue("priority", priority_string); + sendMessage(message); + + if(mPlugin) + { + mPlugin->setSleepTime(mSleepTime); + } + + LL_DEBUGS("PluginPriority") << this << ": setting priority to " << priority_string << LL_ENDL; + + priorityChanged(mPriority); + } +} + +/* virtual */ +void LLPluginClassBasic::receivePluginMessage(const LLPluginMessage &message) +{ + std::string message_class = message.getClass(); + + if (message_class == LLPLUGIN_MESSAGE_CLASS_BASIC) + { + std::string message_name = message.getName(); + + // This class hasn't defined any incoming messages yet. +// if (message_name == "message_name") +// { +// } +// else + { + LL_WARNS("Plugin") << "Unknown " << message_class << " class message: " << message_name << LL_ENDL; + } + } +} + +// This is the viewer process (the parent process) +// +// Call this function to send a message to a plugin. +// It calls LLPluginProcessParent::sendMessage. +void LLPluginClassBasic::sendMessage(LLPluginMessage const& message) +{ + if(mPlugin && mPlugin->isRunning()) + { + mPlugin->sendMessage(message); + } + else + { + // The plugin isn't set up yet -- queue this message to be sent after initialization. + mSendQueue.push(message); + } +} diff --git a/indra/llplugin/llpluginclassbasic.h b/indra/llplugin/llpluginclassbasic.h new file mode 100644 index 000000000..6c0602608 --- /dev/null +++ b/indra/llplugin/llpluginclassbasic.h @@ -0,0 +1,129 @@ +/** + * @file llpluginclassbasic.h + * @brief LLPluginClassBasic handles interaction with a plugin which knows about the "basic" message class. + * + * @cond + * $LicenseInfo:firstyear=2010&license=viewergpl$ + * + * Copyright (c) 2010, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlife.com/developers/opensource/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlife.com/developers/opensource/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + * + * @endcond + */ + +#ifndef LL_LLPLUGINCLASSBASIC_H +#define LL_LLPLUGINCLASSBASIC_H + +#include "llerror.h" // Needed for LOG_CLASS +#include "stdtypes.h" // Needed for F64 +#include "llpluginprocessparent.h" +#include "llpluginclassmediaowner.h" +#include "llpluginmessage.h" +#include +#include + +class LLPluginClassBasic : public LLPluginProcessParentOwner +{ + LOG_CLASS(LLPluginClassBasic); + +public: + LLPluginClassBasic(void); + virtual ~LLPluginClassBasic(); + + // Local initialization, called when creating a plugin process. Return true if successful. + bool init(std::string const& launcher_filename, std::string const& plugin_filename, bool debug); + + // Undoes everything init did. Called when destroying a plugin process. + void reset(void); + + void idle(void); + + // Send message to the plugin, either queueing or sending directly. + void sendMessage(LLPluginMessage const& message); + + // "Loading" means uninitialized or any state prior to fully running (processing commands). + bool isPluginLoading(void) const { return mPlugin ? mPlugin->isLoading() : false; } + + // "Running" means the steady state -- i.e. processing messages. + bool isPluginRunning(void) const { return mPlugin ? mPlugin->isRunning() : false; } + + // "Exited" means any regular or error state after "Running" (plugin may have crashed or exited normally). + bool isPluginExited(void) const { return mPlugin ? mPlugin->isDone() : false; } + + std::string getPluginVersion() const { return mPlugin ? mPlugin->getPluginVersion() : std::string(""); } + + bool getDisableTimeout() const { return mPlugin ? mPlugin->getDisableTimeout() : false; } + + void setDisableTimeout(bool disable) { if (mPlugin) mPlugin->setDisableTimeout(disable); } + + enum EPriority + { + PRIORITY_SLEEP, // Sleep 1 second every message. + PRIORITY_LOW, // Sleep 1/25 second. + PRIORITY_NORMAL, // Sleep 1/50 second. + PRIORITY_HIGH // Sleep 1/100 second. + }; + + static char const* priorityToString(EPriority priority); + void setPriority(EPriority priority); + +protected: + EPriority mPriority; + LLPluginProcessParent* mPlugin; + +private: + F64 mSleepTime; + std::queue mSendQueue; // Used to queue messages while the plugin initializes. + +protected: + // Called as last function when calling 'init()'. + virtual bool init_impl(void) { return true; } + + // Called as last function when calling 'reset()'. + virtual void reset_impl(void) { } + + // Called from idle() before flushing messages to the plugin. + virtual void idle_impl(void) { } + + // Called from setPriority. + virtual void priorityChanged(EPriority priority) { } + + // Inherited from LLPluginProcessParentOwner. + /*virtual*/ void receivePluginMessage(LLPluginMessage const&); + + // Inherited from LLPluginProcessParentOwner. + /*virtual*/ void receivedShutdown() { mPlugin->exitState(); } + + //-------------------------------------- + // Debug use only + // +private: + bool mDeleteOK; + +public: + void setDeleteOK(bool flag) { mDeleteOK = flag; } +}; + +#endif // LL_LLPLUGINCLASSBASIC_H diff --git a/indra/llplugin/llpluginclassmedia.cpp b/indra/llplugin/llpluginclassmedia.cpp index 85241bec1..c8b903e58 100644 --- a/indra/llplugin/llpluginclassmedia.cpp +++ b/indra/llplugin/llpluginclassmedia.cpp @@ -54,49 +54,24 @@ static int nextPowerOf2( int value ) return next_power_of_2; } -LLPluginClassMedia::LLPluginClassMedia(LLPluginClassMediaOwner *owner) +LLPluginClassMedia::LLPluginClassMedia(LLPluginClassMediaOwner *owner): mOwner(owner) { - mOwner = owner; - mPlugin = NULL; - reset(); - - //debug use - mDeleteOK = true ; + // Most initialization is done with reset_impl(), which we call here + // in order to avoid code duplication. + LLPluginClassMedia::reset_impl(); } - -LLPluginClassMedia::~LLPluginClassMedia() +bool LLPluginClassMedia::init_impl(void) { - llassert_always(mDeleteOK) ; - reset(); -} - -bool LLPluginClassMedia::init(const std::string &launcher_filename, const std::string &plugin_filename, bool debug) -{ - LL_DEBUGS("Plugin") << "launcher: " << launcher_filename << LL_ENDL; - LL_DEBUGS("Plugin") << "plugin: " << plugin_filename << LL_ENDL; - - mPlugin = new LLPluginProcessParent(this); - mPlugin->setSleepTime(mSleepTime); - // Queue up the media init message -- it will be sent after all the currently queued messages. LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "init"); sendMessage(message); - - mPlugin->init(launcher_filename, plugin_filename, debug); return true; } - -void LLPluginClassMedia::reset() +void LLPluginClassMedia::reset_impl(void) { - if(mPlugin != NULL) - { - delete mPlugin; - mPlugin = NULL; - } - mTextureParamsReceived = false; mRequestedTextureDepth = 0; mRequestedTextureInternalFormat = 0; @@ -125,14 +100,12 @@ void LLPluginClassMedia::reset() mDirtyRect = LLRect::null; mAutoScaleMedia = false; mRequestedVolume = 1.0f; - mPriority = PRIORITY_NORMAL; mLowPrioritySizeLimit = LOW_PRIORITY_TEXTURE_SIZE_DEFAULT; mAllowDownsample = false; mPadding = 0; mLastMouseX = 0; mLastMouseY = 0; mStatus = LLPluginClassMediaOwner::MEDIA_NONE; - mSleepTime = 1.0f / 100.0f; mCanCut = false; mCanCopy = false; mCanPaste = false; @@ -158,13 +131,8 @@ void LLPluginClassMedia::reset() mLoadedDuration = 0.0f; } -void LLPluginClassMedia::idle(void) +void LLPluginClassMedia::idle_impl(void) { - if(mPlugin) - { - mPlugin->idle(); - } - if((mMediaWidth == -1) || (!mTextureParamsReceived) || (mPlugin == NULL) || (mPlugin->isBlocked())) { // Can't process a size change at this time @@ -260,17 +228,6 @@ void LLPluginClassMedia::idle(void) LL_DEBUGS("Plugin") << "Sending size_change" << LL_ENDL; } } - - if(mPlugin && mPlugin->isRunning()) - { - // Send queued messages - while(!mSendQueue.empty()) - { - LLPluginMessage message = mSendQueue.front(); - mSendQueue.pop(); - mPlugin->sendMessage(message); - } - } } int LLPluginClassMedia::getTextureWidth() const @@ -295,18 +252,16 @@ unsigned char* LLPluginClassMedia::getBitsData() void LLPluginClassMedia::setSize(int width, int height) { - if((width > 0) && (height > 0)) + if (width <= 0 || height <= 0) + { + width = height = -1; + } + if (mSetMediaWidth != width || mSetMediaHeight != height) { mSetMediaWidth = width; mSetMediaHeight = height; + setSizeInternal(); } - else - { - mSetMediaWidth = -1; - mSetMediaHeight = -1; - } - - setSizeInternal(); } void LLPluginClassMedia::setSizeInternal(void) @@ -335,7 +290,7 @@ void LLPluginClassMedia::setSizeInternal(void) { switch(mPriority) { - case PRIORITY_SLIDESHOW: + case PRIORITY_SLEEP: case PRIORITY_LOW: // Reduce maximum texture dimension to (or below) mLowPrioritySizeLimit while((mRequestedMediaWidth > mLowPrioritySizeLimit) || (mRequestedMediaHeight > mLowPrioritySizeLimit)) @@ -584,71 +539,10 @@ void LLPluginClassMedia::loadURI(const std::string &uri) sendMessage(message); } -const char* LLPluginClassMedia::priorityToString(EPriority priority) +void LLPluginClassMedia::priorityChanged(EPriority priority) { - const char* result = "UNKNOWN"; - switch(priority) - { - case PRIORITY_UNLOADED: result = "unloaded"; break; - case PRIORITY_STOPPED: result = "stopped"; break; - case PRIORITY_HIDDEN: result = "hidden"; break; - case PRIORITY_SLIDESHOW: result = "slideshow"; break; - case PRIORITY_LOW: result = "low"; break; - case PRIORITY_NORMAL: result = "normal"; break; - case PRIORITY_HIGH: result = "high"; break; - } - - return result; -} - -void LLPluginClassMedia::setPriority(EPriority priority) -{ - if(mPriority != priority) - { - mPriority = priority; - - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "set_priority"); - - std::string priority_string = priorityToString(priority); - switch(priority) - { - case PRIORITY_UNLOADED: - mSleepTime = 1.0f; - break; - case PRIORITY_STOPPED: - mSleepTime = 1.0f; - break; - case PRIORITY_HIDDEN: - mSleepTime = 1.0f; - break; - case PRIORITY_SLIDESHOW: - mSleepTime = 1.0f; - break; - case PRIORITY_LOW: - mSleepTime = 1.0f / 25.0f; - break; - case PRIORITY_NORMAL: - mSleepTime = 1.0f / 50.0f; - break; - case PRIORITY_HIGH: - mSleepTime = 1.0f / 100.0f; - break; - } - - message.setValue("priority", priority_string); - - sendMessage(message); - - if(mPlugin) - { - mPlugin->setSleepTime(mSleepTime); - } - - LL_DEBUGS("PluginPriority") << this << ": setting priority to " << priority_string << LL_ENDL; - - // This may affect the calculated size, so recalculate it here. - setSizeInternal(); - } + // This may affect the calculated size, so recalculate it here. + setSizeInternal(); } void LLPluginClassMedia::setLowPrioritySizeLimit(int size) @@ -657,7 +551,6 @@ void LLPluginClassMedia::setLowPrioritySizeLimit(int size) if(mLowPrioritySizeLimit != power) { mLowPrioritySizeLimit = power; - // This may affect the calculated size, so recalculate it here. setSizeInternal(); } @@ -726,7 +619,11 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message) { std::string message_class = message.getClass(); - if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA) + if (message_class == LLPLUGIN_MESSAGE_CLASS_BASIC) + { + LLPluginClassBasic::receivePluginMessage(message); + } + else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA) { std::string message_name = message.getName(); if(message_name == "texture_params") @@ -777,7 +674,7 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message) mDirtyRect.unionWith(newDirtyRect); } - LL_DEBUGS("Plugin") << "adjusted incoming rect is: (" + LL_DEBUGS("PluginUpdated") << "adjusted incoming rect is: (" << newDirtyRect.mLeft << ", " << newDirtyRect.mTop << ", " << newDirtyRect.mRight << ", " @@ -1003,10 +900,9 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message) // } // else { - LL_WARNS("Plugin") << "Unknown " << message_name << " class message: " << message_name << LL_ENDL; + LL_WARNS("Plugin") << "Unknown " << message_class << " class message: " << message_name << LL_ENDL; } } - } /* virtual */ @@ -1029,19 +925,6 @@ void LLPluginClassMedia::mediaEvent(LLPluginClassMediaOwner::EMediaEvent event) } } -void LLPluginClassMedia::sendMessage(const LLPluginMessage &message) -{ - if(mPlugin && mPlugin->isRunning()) - { - mPlugin->sendMessage(message); - } - else - { - // The plugin isn't set up yet -- queue this message to be sent after initialization. - mSendQueue.push(message); - } -} - //////////////////////////////////////////////////////////// // MARK: media_browser class functions bool LLPluginClassMedia::pluginSupportsMediaBrowser(void) diff --git a/indra/llplugin/llpluginclassmedia.h b/indra/llplugin/llpluginclassmedia.h index 0004971c6..2882de180 100644 --- a/indra/llplugin/llpluginclassmedia.h +++ b/indra/llplugin/llpluginclassmedia.h @@ -36,29 +36,16 @@ #ifndef LL_LLPLUGINCLASSMEDIA_H #define LL_LLPLUGINCLASSMEDIA_H -#include "llgltypes.h" -#include "llpluginprocessparent.h" +#include "llpluginclassbasic.h" #include "llrect.h" -#include "llpluginclassmediaowner.h" -#include #include "v4color.h" -class LLPluginClassMedia : public LLPluginProcessParentOwner +class LLPluginClassMedia : public LLPluginClassBasic { LOG_CLASS(LLPluginClassMedia); + public: LLPluginClassMedia(LLPluginClassMediaOwner *owner); - virtual ~LLPluginClassMedia(); - - // local initialization, called by the media manager when creating a source - virtual bool init(const std::string &launcher_filename, - const std::string &plugin_filename, - bool debug); - - // undoes everything init() didm called by the media manager when destroying a source - virtual void reset(); - - void idle(void); // All of these may return 0 or an actual valid value. // Callers need to check the return for 0, and not use the values in that case. @@ -101,22 +88,22 @@ public: bool getDirty(LLRect *dirty_rect = NULL); void resetDirty(void); - typedef enum + enum EMouseEventType { MOUSE_EVENT_DOWN, MOUSE_EVENT_UP, MOUSE_EVENT_MOVE, MOUSE_EVENT_DOUBLE_CLICK - }EMouseEventType; + }; void mouseEvent(EMouseEventType type, int button, int x, int y, MASK modifiers); - typedef enum + enum EKeyEventType { KEY_EVENT_DOWN, KEY_EVENT_UP, KEY_EVENT_REPEAT - }EKeyEventType; + }; bool keyEvent(EKeyEventType type, int key_code, MASK modifiers, LLSD native_key_data); @@ -127,39 +114,13 @@ public: void loadURI(const std::string &uri); - // "Loading" means uninitialized or any state prior to fully running (processing commands) - bool isPluginLoading(void) { return mPlugin?mPlugin->isLoading():false; }; - - // "Running" means the steady state -- i.e. processing messages - bool isPluginRunning(void) { return mPlugin?mPlugin->isRunning():false; }; - - // "Exited" means any regular or error state after "Running" (plugin may have crashed or exited normally) - bool isPluginExited(void) { return mPlugin?mPlugin->isDone():false; }; - - std::string getPluginVersion() { return mPlugin?mPlugin->getPluginVersion():std::string(""); }; - - bool getDisableTimeout() { return mPlugin?mPlugin->getDisableTimeout():false; }; - void setDisableTimeout(bool disable) { if(mPlugin) mPlugin->setDisableTimeout(disable); }; - // Inherited from LLPluginProcessParentOwner /* virtual */ void receivePluginMessage(const LLPluginMessage &message); /* virtual */ void pluginLaunchFailed(); /* virtual */ void pluginDied(); + // Inherited from LLPluginClassBasic + /* virtual */ void priorityChanged(EPriority priority); - - typedef enum - { - PRIORITY_UNLOADED, // media plugin isn't even loaded. - PRIORITY_STOPPED, // media is not playing, shouldn't need to update at all. - PRIORITY_HIDDEN, // media is not being displayed or is out of view, don't need to do graphic updates, but may still update audio, playhead, etc. - PRIORITY_SLIDESHOW, // media is in the far distance, updates very infrequently - PRIORITY_LOW, // media is in the distance, may be rendered at reduced size - PRIORITY_NORMAL, // normal (default) priority - PRIORITY_HIGH // media has user focus and/or is taking up most of the screen - }EPriority; - - static const char* priorityToString(EPriority priority); - void setPriority(EPriority priority); void setLowPrioritySizeLimit(int size); F64 getCPUUsage(); @@ -256,22 +217,23 @@ public: void initializeUrlHistory(const LLSD& url_history); protected: - - LLPluginClassMediaOwner *mOwner; + virtual bool init_impl(void); + virtual void reset_impl(void); + virtual void idle_impl(void); // Notify this object's owner that an event has occurred. void mediaEvent(LLPluginClassMediaOwner::EMediaEvent event); - void sendMessage(const LLPluginMessage &message); // Send message internally, either queueing or sending directly. - std::queue mSendQueue; // Used to queue messages while the plugin initializes. - void setSizeInternal(void); +protected: + LLPluginClassMediaOwner *mOwner; + bool mTextureParamsReceived; // the mRequestedTexture* fields are only valid when this is true S32 mRequestedTextureDepth; - LLGLenum mRequestedTextureInternalFormat; - LLGLenum mRequestedTextureFormat; - LLGLenum mRequestedTextureType; + U32 mRequestedTextureInternalFormat; + U32 mRequestedTextureFormat; + U32 mRequestedTextureType; bool mRequestedTextureSwapBytes; bool mRequestedTextureCoordsOpenGL; @@ -313,16 +275,11 @@ protected: float mRequestedVolume; - // Priority of this media stream - EPriority mPriority; int mLowPrioritySizeLimit; bool mAllowDownsample; int mPadding; - - LLPluginProcessParent *mPlugin; - LLRect mDirtyRect; std::string translateModifiers(MASK modifiers); @@ -332,8 +289,6 @@ protected: int mLastMouseY; LLPluginClassMediaOwner::EMediaStatus mStatus; - - F64 mSleepTime; bool mCanCut; bool mCanCopy; @@ -363,15 +318,6 @@ protected: F64 mDuration; F64 mCurrentRate; F64 mLoadedDuration; - -//-------------------------------------- - //debug use only - // -private: - bool mDeleteOK ; -public: - void setDeleteOK(bool flag) { mDeleteOK = flag ;} -//-------------------------------------- }; #endif // LL_LLPLUGINCLASSMEDIA_H diff --git a/indra/llplugin/llplugininstance.cpp b/indra/llplugin/llplugininstance.cpp index 3a1395cd2..914eadcce 100644 --- a/indra/llplugin/llplugininstance.cpp +++ b/indra/llplugin/llplugininstance.cpp @@ -55,8 +55,8 @@ const char *LLPluginInstance::PLUGIN_INIT_FUNCTION_NAME = "LLPluginInitEntryPoin */ LLPluginInstance::LLPluginInstance(LLPluginInstanceMessageListener *owner) : mDSOHandle(NULL), - mPluginUserData(NULL), - mPluginSendMessageFunction(NULL) + mPluginObject(NULL), + mReceiveMessageFunction(NULL) { mOwner = owner; } @@ -109,9 +109,9 @@ int LLPluginInstance::load(std::string &plugin_file) if(result == APR_SUCCESS) { - result = init_function(staticReceiveMessage, (void*)this, &mPluginSendMessageFunction, &mPluginUserData); + result = init_function(&LLPluginInstance::staticReceiveMessage, this, &mReceiveMessageFunction, &mPluginObject); - if(result != APR_SUCCESS) + if(result != 0) { LL_WARNS("Plugin") << "call to init function failed with error " << result << LL_ENDL; } @@ -120,6 +120,14 @@ int LLPluginInstance::load(std::string &plugin_file) return (int)result; } +// This is the SLPlugin process (the child process). +// This is not part of a DSO. +// +// This function is called from LLPluginProcessChild::receiveMessageRaw +// for messages received from the viewer that are not internal. +// +// It sends the message to the DSO by calling the registered 'received' +// function (for example, FilepickerPlugin::receiveMessage). /** * Sends a message to the plugin. * @@ -127,10 +135,10 @@ int LLPluginInstance::load(std::string &plugin_file) */ void LLPluginInstance::sendMessage(const std::string &message) { - if(mPluginSendMessageFunction) + if(mReceiveMessageFunction) { LL_DEBUGS("Plugin") << "sending message to plugin: \"" << message << "\"" << LL_ENDL; - mPluginSendMessageFunction(message.c_str(), &mPluginUserData); + mReceiveMessageFunction(message.c_str(), &mPluginObject); } else { @@ -147,14 +155,19 @@ void LLPluginInstance::idle(void) } // static -void LLPluginInstance::staticReceiveMessage(const char *message_string, void **user_data) +void LLPluginInstance::staticReceiveMessage(char const* message_string, LLPluginInstance** self_ptr) { - // TODO: validate that the user_data argument is still a valid LLPluginInstance pointer + // TODO: validate that the self argument is still a valid LLPluginInstance pointer // we could also use a key that's looked up in a map (instead of a direct pointer) for safety, but that's probably overkill - LLPluginInstance *self = (LLPluginInstance*)*user_data; - self->receiveMessage(message_string); + (*self_ptr)->receiveMessage(message_string); } +// This is the SLPlugin process. +// This is not part of a DSO. +// +// This function is called by a loaded DSO (through a function pointer, it +// is called from BasicPluginBase::sendMessage) for messages it wants to +// send to the viewer. It calls LLPluginProcessChild::receivePluginMessage. /** * Plugin receives message from plugin loader shell. * diff --git a/indra/llplugin/llplugininstance.h b/indra/llplugin/llplugininstance.h index 9cf6075ff..b2b107bab 100644 --- a/indra/llplugin/llplugininstance.h +++ b/indra/llplugin/llplugininstance.h @@ -36,9 +36,8 @@ #define LL_LLPLUGININSTANCE_H #include "llstring.h" -#include "llapr.h" -#include "apr_dso.h" +struct apr_dso_handle_t; //Cannot include llapr, as it defines NOUSER for windows, which breaks including commdlg.h! /** * @brief LLPluginInstanceMessageListener receives messages sent from the plugin loader shell to the plugin. @@ -51,6 +50,8 @@ public: virtual void receivePluginMessage(const std::string &message) = 0; }; +class BasicPluginBase; + /** * @brief LLPluginInstance handles loading the dynamic library of a plugin and setting up its entry points for message passing. */ @@ -79,26 +80,28 @@ public: * @param[in] message_string Null-terminated C string * @param[in] user_data The opaque reference that the callee supplied during setup. */ - typedef void (*sendMessageFunction) (const char *message_string, void **user_data); + typedef void (*receiveMessageFunction)(char const* message_string, BasicPluginBase** plugin_object); + + typedef void (*sendMessageFunction)(char const* message_string, LLPluginInstance** plugin_instance); /** The signature of the plugin init function. TODO:DOC check direction (pluging loader shell to plugin?) * * @param[in] host_user_data Data from plugin loader shell. * @param[in] plugin_send_function Function for sending from the plugin loader shell to plugin. */ - typedef int (*pluginInitFunction) (sendMessageFunction host_send_func, void *host_user_data, sendMessageFunction *plugin_send_func, void **plugin_user_data); + typedef int (*pluginInitFunction)(sendMessageFunction send_message_function, LLPluginInstance* plugin_instance, receiveMessageFunction* receive_message_function, BasicPluginBase** plugin_object); /** Name of plugin init function */ static const char *PLUGIN_INIT_FUNCTION_NAME; private: - static void staticReceiveMessage(const char *message_string, void **user_data); + static void staticReceiveMessage(char const* message_string, LLPluginInstance** plugin_instance); void receiveMessage(const char *message_string); apr_dso_handle_t *mDSOHandle; - void *mPluginUserData; - sendMessageFunction mPluginSendMessageFunction; + BasicPluginBase* mPluginObject; + receiveMessageFunction mReceiveMessageFunction; LLPluginInstanceMessageListener *mOwner; }; diff --git a/indra/llplugin/llpluginmessage.h b/indra/llplugin/llpluginmessage.h index fe504c8b9..7bc4ea12d 100644 --- a/indra/llplugin/llpluginmessage.h +++ b/indra/llplugin/llpluginmessage.h @@ -99,8 +99,17 @@ public: // (this clears out all existing state before starting the parse) // Returns -1 on failure, otherwise returns the number of key/value pairs in the message. int parse(const std::string &message); - - + + enum LLPLUGIN_LOG_LEVEL { + LOG_LEVEL_DEBUG, + LOG_LEVEL_INFO, + LOG_LEVEL_WARN, + LOG_LEVEL_ERR, + }; + + // For debugging purposes. + friend std::ostream& operator<<(std::ostream& os, LLPluginMessage const& message) { return os << message.mMessage; } + private: LLSD mMessage; diff --git a/indra/llplugin/llpluginmessageclasses.h b/indra/llplugin/llpluginmessageclasses.h index 8812a1676..b61720ab4 100644 --- a/indra/llplugin/llpluginmessageclasses.h +++ b/indra/llplugin/llpluginmessageclasses.h @@ -48,6 +48,9 @@ #define LLPLUGIN_MESSAGE_CLASS_BASE "base" #define LLPLUGIN_MESSAGE_CLASS_BASE_VERSION "1.0" +#define LLPLUGIN_MESSAGE_CLASS_BASIC "basic" +#define LLPLUGIN_MESSAGE_CLASS_BASIC_VERSION "1.0" + #define LLPLUGIN_MESSAGE_CLASS_MEDIA "media" #define LLPLUGIN_MESSAGE_CLASS_MEDIA_VERSION "1.0" diff --git a/indra/llplugin/llpluginmessagepipe.cpp b/indra/llplugin/llpluginmessagepipe.cpp index ebac3c52b..8f19145a8 100644 --- a/indra/llplugin/llpluginmessagepipe.cpp +++ b/indra/llplugin/llpluginmessagepipe.cpp @@ -89,6 +89,16 @@ bool LLPluginMessagePipeOwner::writeMessageRaw(const std::string &message) return result; } +bool LLPluginMessagePipeOwner::flushMessages(void) +{ + bool result = true; + if (mMessagePipe != NULL) + { + result = mMessagePipe->flushMessages(); + } + return result; +} + void LLPluginMessagePipeOwner::killMessagePipe(void) { if(mMessagePipe != NULL) @@ -163,26 +173,32 @@ bool LLPluginMessagePipe::pump(F64 timeout) return result; } -bool LLPluginMessagePipe::pumpOutput() +static apr_interval_time_t const flush_max_block_time = 10000000; // Even when flushing, give up after 10 seconds. +static apr_interval_time_t const flush_min_timeout = 1000; // When flushing, initially timeout after 1 ms. +static apr_interval_time_t const flush_max_timeout = 50000; // Never wait longer than 50 ms. + +// DO NOT SET 'flush' TO TRUE WHEN CALLED ON THE VIEWER SIDE! +// flush is only intended for plugin-side. +bool LLPluginMessagePipe::pumpOutput(bool flush) { bool result = true; if(mSocket) { - apr_status_t status; - apr_size_t size; + apr_interval_time_t flush_time_left_usec = flush_max_block_time; + apr_interval_time_t timeout_usec = flush ? flush_min_timeout : 0; LLMutexLock lock(&mOutputMutex); - if(!mOutput.empty()) + while(result && !mOutput.empty()) { // write any outgoing messages - size = (apr_size_t)mOutput.size(); + apr_size_t size = (apr_size_t)mOutput.size(); - setSocketTimeout(0); + setSocketTimeout(timeout_usec); // LL_INFOS("Plugin") << "before apr_socket_send, size = " << size << LL_ENDL; - status = apr_socket_send( + apr_status_t status = apr_socket_send( mSocket->getSocket(), (const char*)mOutput.data(), &size); @@ -193,12 +209,29 @@ bool LLPluginMessagePipe::pumpOutput() { // success mOutput = mOutput.substr(size); + break; } - else if(APR_STATUS_IS_EAGAIN(status)) + else if(APR_STATUS_IS_EAGAIN(status) || APR_STATUS_IS_TIMEUP(status)) { // Socket buffer is full... // remove the written part from the buffer and try again later. mOutput = mOutput.substr(size); + if (!flush) + break; + flush_time_left_usec -= timeout_usec; + if (flush_time_left_usec <= 0) + { + result = false; + } + else if (size == 0) + { + // Nothing at all was written. Increment wait time. + timeout_usec = llmin(flush_max_timeout, 2 * timeout_usec); + } + else + { + timeout_usec = llmax(flush_min_timeout, timeout_usec / 2); + } } else if(APR_STATUS_IS_EOF(status)) { diff --git a/indra/llplugin/llpluginmessagepipe.h b/indra/llplugin/llpluginmessagepipe.h index 6eedca27f..1e71caf42 100644 --- a/indra/llplugin/llpluginmessagepipe.h +++ b/indra/llplugin/llpluginmessagepipe.h @@ -61,6 +61,8 @@ protected: bool canSendMessage(void); // call this to send a message over the pipe bool writeMessageRaw(const std::string &message); + // call this to attempt to flush all messages for 10 seconds long. + bool flushMessages(void); // call this to close the pipe void killMessagePipe(void); @@ -79,8 +81,10 @@ public: void clearOwner(void); bool pump(F64 timeout = 0.0f); - bool pumpOutput(); + bool pumpOutput(bool flush = false); bool pumpInput(F64 timeout = 0.0f); + + bool flushMessages(void) { return pumpOutput(true); } protected: void processInput(void); diff --git a/indra/llplugin/llpluginprocesschild.cpp b/indra/llplugin/llpluginprocesschild.cpp index d2238236f..fdcb4f6a8 100644 --- a/indra/llplugin/llpluginprocesschild.cpp +++ b/indra/llplugin/llpluginprocesschild.cpp @@ -227,6 +227,7 @@ void LLPluginProcessChild::idle(void) case STATE_DONE: // just sit here. + LL_WARNS("Plugin") << "Calling LLPluginProcessChild::idle while in STATE_DONE!" << LL_ENDL; break; } @@ -286,6 +287,11 @@ bool LLPluginProcessChild::isDone(void) return result; } +// This is the SLPlugin process. +// This is not part of a DSO. +// +// This function is called by SLPlugin to send a message (originating from +// SLPlugin itself) to the loaded DSO. It calls LLPluginInstance::sendMessage. void LLPluginProcessChild::sendMessageToPlugin(const LLPluginMessage &message) { if (mInstance) @@ -305,15 +311,26 @@ void LLPluginProcessChild::sendMessageToPlugin(const LLPluginMessage &message) } } +// This is the SLPlugin process (the child process). +// This is not part of a DSO. +// +// This function is called by SLPlugin to send 'message' to the viewer (the parent process). void LLPluginProcessChild::sendMessageToParent(const LLPluginMessage &message) { std::string buffer = message.generate(); LL_DEBUGS("Plugin") << "Sending to parent: " << buffer << LL_ENDL; + // Write the serialized message to the pipe. writeMessageRaw(buffer); } +// This is the SLPlugin process (the child process). +// This is not part of a DSO. +// +// This function is called when the serialized message 'message' was received from the viewer. +// It parses the message and handles LLPLUGIN_MESSAGE_CLASS_INTERNAL. +// Other message classes are passed on to LLPluginInstance::sendMessage. void LLPluginProcessChild::receiveMessageRaw(const std::string &message) { // Incoming message from the TCP Socket @@ -449,7 +466,17 @@ void LLPluginProcessChild::receiveMessageRaw(const std::string &message) } } -/* virtual */ +// This is the SLPlugin process. +// This is not part of a DSO. +// +// This function is called from LLPluginInstance::receiveMessage +// for messages from a loaded DSO that have to be passed to the +// viewer. +// +// It handles the base messages that are responses to messages sent by this +// class, and passes the rest on to LLPluginMessagePipeOwner::writeMessageRaw +// to be written to the pipe. +/* virtual */ void LLPluginProcessChild::receivePluginMessage(const std::string &message) { LL_DEBUGS("Plugin") << "Received from plugin: " << message << LL_ENDL; @@ -527,6 +554,26 @@ void LLPluginProcessChild::receivePluginMessage(const std::string &message) } } } + else if (message_class == LLPLUGIN_MESSAGE_CLASS_INTERNAL) + { + bool flush = false; + std::string message_name = parsed.getName(); + if(message_name == "shutdown") + { + // The plugin is finished. + setState(STATE_UNLOADING); + flush = true; + } + else if (message_name == "flush") + { + flush = true; + passMessage = false; + } + if (flush) + { + flushMessages(); + } + } } if(passMessage) diff --git a/indra/llplugin/llpluginprocesschild.h b/indra/llplugin/llpluginprocesschild.h index 5d643d792..66082db7c 100644 --- a/indra/llplugin/llpluginprocesschild.h +++ b/indra/llplugin/llpluginprocesschild.h @@ -88,7 +88,7 @@ private: STATE_PLUGIN_LOADED, // plugin library has been loaded STATE_PLUGIN_INITIALIZING, // plugin is processing init message STATE_RUNNING, // steady state (processing messages) - STATE_UNLOADING, // plugin has sent shutdown_response and needs to be unloaded + STATE_UNLOADING, // plugin has sent shutdown and needs to be unloaded STATE_UNLOADED, // plugin has been unloaded STATE_ERROR, // generic bailout state STATE_DONE // state machine will sit in this state after either error or normal termination. diff --git a/indra/llplugin/llpluginprocessparent.cpp b/indra/llplugin/llpluginprocessparent.cpp index 2cb6b2832..0d361324e 100644 --- a/indra/llplugin/llpluginprocessparent.cpp +++ b/indra/llplugin/llpluginprocessparent.cpp @@ -38,6 +38,9 @@ #include "llpluginprocessparent.h" #include "llpluginmessagepipe.h" #include "llpluginmessageclasses.h" +#if LL_LINUX +#include +#endif #include "llapr.h" @@ -101,6 +104,7 @@ LLPluginProcessParent::LLPluginProcessParent(LLPluginProcessParentOwner *owner) mDebug = false; mBlocked = false; mPolledInput = false; + mReceivedShutdown = false; mPollFD.client_data = NULL; mPollFDPool.create(); @@ -162,6 +166,8 @@ void LLPluginProcessParent::errorState(void) { if(mState < STATE_RUNNING) setState(STATE_LAUNCH_FAILURE); + else if (mReceivedShutdown) + setState(STATE_EXITING); else setState(STATE_ERROR); } @@ -373,14 +379,12 @@ void LLPluginProcessParent::idle(void) { if(mDebug) { - #if LL_DARWIN // If we're set to debug, start up a gdb instance in a new terminal window and have it attach to the plugin process and continue. - + std::stringstream cmd; + +#if LL_DARWIN // The command we're constructing would look like this on the command line: // osascript -e 'tell application "Terminal"' -e 'set win to do script "gdb -pid 12345"' -e 'do script "continue" in win' -e 'end tell' - - std::stringstream cmd; - mDebugger.setExecutable("/usr/bin/osascript"); mDebugger.addArgument("-e"); mDebugger.addArgument("tell application \"Terminal\""); @@ -392,19 +396,32 @@ void LLPluginProcessParent::idle(void) mDebugger.addArgument("-e"); mDebugger.addArgument("end tell"); mDebugger.launch(); - - #elif LL_LINUX - - std::stringstream cmd; - - mDebugger.setExecutable("/usr/bin/gnome-terminal"); - mDebugger.addArgument("--geometry=165x24-0+0"); - mDebugger.addArgument("-e"); - cmd << "/usr/bin/gdb -n /proc/" << mProcess.getProcessID() << "/exe " << mProcess.getProcessID(); - mDebugger.addArgument(cmd.str()); +#elif LL_LINUX + // The command we're constructing would look like this on the command line: + // /usr/bin/xterm -geometry 160x24-0+0 -e '/usr/bin/gdb -n /proc/12345/exe 12345' + // This can be changed by setting the following environment variables, for example: + // export LL_DEBUG_TERMINAL_COMMAND="/usr/bin/gnome-terminal --geometry=165x24-0+0 -e %s" + // export LL_DEBUG_GDB_PATH=/usr/bin/gdb + char const* env; + std::string const terminal_command = (env = getenv("LL_DEBUG_TERMINAL_COMMAND")) ? env : "/usr/bin/xterm -geometry 160x24+0+0 -e %s"; + char const* const gdb_path = (env = getenv("LL_DEBUG_GDB_PATH")) ? env : "/usr/bin/gdb"; + cmd << gdb_path << " -n /proc/" << mProcess.getProcessID() << "/exe " << mProcess.getProcessID(); + std::vector tokens = boost::program_options::split_unix(terminal_command, " "); + std::vector::iterator token = tokens.begin(); + mDebugger.setExecutable(*token); + while (++token != tokens.end()) + { + if (*token == "%s") + { + mDebugger.addArgument(cmd.str()); + } + else + { + mDebugger.addArgument(*token); + } + } mDebugger.launch(); - - #endif +#endif } // This will allow us to time out if the process never starts. @@ -565,6 +582,9 @@ void LLPluginProcessParent::setSleepTime(F64 sleep_time, bool force_send) } } +// This is the viewer process (the parent process) +// +// This function is called to send a message to the plugin. void LLPluginProcessParent::sendMessage(const LLPluginMessage &message) { if(message.hasValue("blocking_response")) @@ -574,9 +594,23 @@ void LLPluginProcessParent::sendMessage(const LLPluginMessage &message) // reset the heartbeat timer, since there will have been no heartbeats while the plugin was blocked. mHeartbeat.setTimerExpirySec(mPluginLockupTimeout); } + if (message.hasValue("gorgon")) + { + // After this message it is expected that the plugin will not send any more messages for a long time. + mBlocked = true; + } std::string buffer = message.generate(); - LL_DEBUGS("Plugin") << "Sending: " << buffer << LL_ENDL; +#if LL_DEBUG + if (message.getName() == "mouse_event") + { + LL_DEBUGS("PluginMouseEvent") << "Sending: " << buffer << LL_ENDL; + } + else + { + LL_DEBUGS("Plugin") << "Sending: " << buffer << LL_ENDL; + } +#endif writeMessageRaw(buffer); // Try to send message immediately. @@ -622,6 +656,16 @@ void LLPluginProcessParent::setMessagePipe(LLPluginMessagePipe *message_pipe) } } +apr_status_t LLPluginProcessParent::socketError(apr_status_t error) +{ + mSocketError = error; + if (APR_STATUS_IS_EPIPE(error)) + { + errorState(); + } + return error; +}; + //static void LLPluginProcessParent::dirtyPollSet() { @@ -838,9 +882,13 @@ void LLPluginProcessParent::servicePoll() } } +// This the viewer process (the parent process). +// +// This function is called when a message is received from a plugin. +// It parses the message and passes it on to LLPluginProcessParent::receiveMessage. void LLPluginProcessParent::receiveMessageRaw(const std::string &message) { - LL_DEBUGS("Plugin") << "Received: " << message << LL_ENDL; + LL_DEBUGS("PluginRaw") << "Received: " << message << LL_ENDL; LLPluginMessage parsed; if(parsed.parse(message) != -1) @@ -849,6 +897,13 @@ void LLPluginProcessParent::receiveMessageRaw(const std::string &message) { mBlocked = true; } + if(parsed.hasValue("perseus")) + { + mBlocked = false; + + // reset the heartbeat timer, since there will have been no heartbeats while the plugin was blocked. + mHeartbeat.setTimerExpirySec(mPluginLockupTimeout); + } if(mPolledInput) { @@ -891,6 +946,12 @@ void LLPluginProcessParent::receiveMessageEarly(const LLPluginMessage &message) } } +// This is the viewer process (the parent process). +// +// This function is called for messages that have to +// be written to the plugin. +// Note that LLPLUGIN_MESSAGE_CLASS_INTERNAL messages +// are not sent to the plugin, but are handled here. void LLPluginProcessParent::receiveMessage(const LLPluginMessage &message) { std::string message_class = message.getClass(); @@ -949,8 +1010,13 @@ void LLPluginProcessParent::receiveMessage(const LLPluginMessage &message) mCPUUsage = message.getValueReal("cpu_usage"); - LL_DEBUGS("Plugin") << "cpu usage reported as " << mCPUUsage << LL_ENDL; - + LL_DEBUGS("PluginHeartbeat") << "cpu usage reported as " << mCPUUsage << LL_ENDL; + } + else if(message_name == "shutdown") + { + LL_INFOS("Plugin") << "received shutdown message" << LL_ENDL; + mReceivedShutdown = true; + mOwner->receivedShutdown(); } else if(message_name == "shm_add_response") { @@ -970,6 +1036,30 @@ void LLPluginProcessParent::receiveMessage(const LLPluginMessage &message) mSharedMemoryRegions.erase(iter); } } + else if(message_name == "log_message") + { + std::string msg=message.getValue("message"); + S32 level=message.getValueS32("log_level"); + + switch(level) + { + case LLPluginMessage::LOG_LEVEL_DEBUG: + LL_DEBUGS("Plugin child")<mLightTexture != mLightTexture) ) + { + return false; + } + + if ( (param->mParams != mParams ) ) + { + return false; + } + + return true; +} + +void LLLightImageParams::copy(const LLNetworkData& data) +{ + const LLLightImageParams *param = (LLLightImageParams*)&data; + mLightTexture = param->mLightTexture; + mParams = param->mParams; +} + + + +LLSD LLLightImageParams::asLLSD() const +{ + LLSD sd; + + sd["texture"] = mLightTexture; + sd["params"] = mParams.getValue(); + + return sd; +} + +bool LLLightImageParams::fromLLSD(LLSD& sd) +{ + if (sd.has("texture")) + { + setLightTexture( sd["texture"] ); + setParams( LLVector3( sd["params"] ) ); + return true; + } + + return false; +} diff --git a/indra/llprimitive/llprimitive.h b/indra/llprimitive/llprimitive.h index 03769a87a..c9b035db3 100644 --- a/indra/llprimitive/llprimitive.h +++ b/indra/llprimitive/llprimitive.h @@ -107,7 +107,8 @@ public: { PARAMS_FLEXIBLE = 0x10, PARAMS_LIGHT = 0x20, - PARAMS_SCULPT = 0x30 + PARAMS_SCULPT = 0x30, + PARAMS_LIGHT_IMAGE = 0x40, }; public: @@ -267,6 +268,29 @@ public: U8 getSculptType() const { return mSculptType; } }; +class LLLightImageParams : public LLNetworkData +{ +protected: + LLUUID mLightTexture; + LLVector3 mParams; + +public: + LLLightImageParams(); + /*virtual*/ BOOL pack(LLDataPacker &dp) const; + /*virtual*/ BOOL unpack(LLDataPacker &dp); + /*virtual*/ bool operator==(const LLNetworkData& data) const; + /*virtual*/ void copy(const LLNetworkData& data); + LLSD asLLSD() const; + operator LLSD() const { return asLLSD(); } + bool fromLLSD(LLSD& sd); + + void setLightTexture(const LLUUID& id) { mLightTexture = id; } + LLUUID getLightTexture() const { return mLightTexture; } + bool isLightSpotlight() const { return mLightTexture.notNull(); } + void setParams(const LLVector3& params) { mParams = params; } + LLVector3 getParams() const { return mParams; } + +}; class LLPrimitive : public LLXform @@ -340,8 +364,8 @@ public: S32 unpackTEField(U8 *cur_ptr, U8 *buffer_end, U8 *data_ptr, U8 data_size, U8 face_count, EMsgVariableType type); BOOL packTEMessage(LLMessageSystem *mesgsys, int shield = 0, std::string client_str = "") const; BOOL packTEMessage(LLDataPacker &dp) const; - S32 unpackTEMessage(LLMessageSystem *mesgsys, char *block_name); - S32 unpackTEMessage(LLMessageSystem *mesgsys, char *block_name, const S32 block_num); // Variable num of blocks + S32 unpackTEMessage(LLMessageSystem* mesgsys, char const* block_name); + S32 unpackTEMessage(LLMessageSystem* mesgsys, char const* block_name, const S32 block_num); // Variable num of blocks BOOL unpackTEMessage(LLDataPacker &dp); #ifdef CHECK_FOR_FINITE diff --git a/indra/llprimitive/llvolumemessage.cpp b/indra/llprimitive/llvolumemessage.cpp index dcfecb140..273ed1b7e 100644 --- a/indra/llprimitive/llvolumemessage.cpp +++ b/indra/llprimitive/llvolumemessage.cpp @@ -100,7 +100,7 @@ bool LLVolumeMessage::packProfileParams( bool LLVolumeMessage::unpackProfileParams( LLProfileParams* params, LLMessageSystem* mesgsys, - char* block_name, + char const* block_name, S32 block_num) { bool ok = true; @@ -328,7 +328,7 @@ bool LLVolumeMessage::packPathParams( bool LLVolumeMessage::unpackPathParams( LLPathParams* params, LLMessageSystem* mesgsys, - char* block_name, + char const* block_name, S32 block_num) { U8 curve; @@ -528,7 +528,7 @@ bool LLVolumeMessage::packVolumeParams(const LLVolumeParams* params, LLDataPacke bool LLVolumeMessage::unpackVolumeParams( LLVolumeParams* params, LLMessageSystem* mesgsys, - char* block_name, + char const* block_name, S32 block_num) { bool ok = true; diff --git a/indra/llprimitive/llvolumemessage.h b/indra/llprimitive/llvolumemessage.h index 514c7007a..aa88577ac 100644 --- a/indra/llprimitive/llvolumemessage.h +++ b/indra/llprimitive/llvolumemessage.h @@ -55,7 +55,7 @@ protected: static bool unpackProfileParams( LLProfileParams* params, LLMessageSystem* mesgsys, - char* block_name, + char const* block_name, S32 block_num = 0); static bool unpackProfileParams(LLProfileParams* params, LLDataPacker& dp); @@ -66,7 +66,7 @@ protected: static bool unpackPathParams( LLPathParams* params, LLMessageSystem* mesgsys, - char* block_name, + char const* block_name, S32 block_num = 0); static bool unpackPathParams(LLPathParams* params, LLDataPacker& dp); @@ -89,7 +89,7 @@ public: static bool unpackVolumeParams( LLVolumeParams* params, LLMessageSystem* mesgsys, - char* block_name, + char const* block_name, S32 block_num = 0); static bool unpackVolumeParams(LLVolumeParams* params, LLDataPacker &dp); }; diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp index d708398b2..673bc4b9e 100644 --- a/indra/llrender/llgl.cpp +++ b/indra/llrender/llgl.cpp @@ -45,10 +45,12 @@ #include "llrender.h" #include "llerror.h" +#include "llerrorcontrol.h" #include "llquaternion.h" #include "llmath.h" #include "m4math.h" #include "llstring.h" +#include "llstacktrace.h" #include "llglheaders.h" @@ -56,15 +58,53 @@ //#define GL_STATE_VERIFY #endif + +BOOL gDebugSession = FALSE; BOOL gDebugGL = FALSE; BOOL gClothRipple = FALSE; BOOL gNoRender = FALSE; BOOL gGLActive = FALSE; + +std::ofstream gFailLog; + +void ll_init_fail_log(std::string filename) +{ + gFailLog.open(filename.c_str()); +} + + +void ll_fail(std::string msg) +{ + + if (gDebugSession) + { + std::vector lines; + + gFailLog << LLError::utcTime() << " " << msg << std::endl; + + gFailLog << "Stack Trace:" << std::endl; + + ll_get_stack_trace(lines); + + for(size_t i = 0; i < lines.size(); ++i) + { + gFailLog << lines[i] << std::endl; + } + + gFailLog << "End of Stack Trace." << std::endl << std::endl; + + gFailLog.flush(); + } +}; + +void ll_close_fail_log() +{ + gFailLog.close(); +} LLMatrix4 gGLObliqueProjectionInverse; #define LL_GL_NAME_POOLING 0 -LLGLNamePool::pool_list_t LLGLNamePool::sInstances; std::list LLGLUpdate::sGLQ; #if (LL_WINDOWS || LL_LINUX || LL_SOLARIS) && !LL_MESA_HEADLESS @@ -134,12 +174,9 @@ PFNGLFRAMEBUFFERTEXTURE3DEXTPROC glFramebufferTexture3DEXT = NULL; PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC glFramebufferRenderbufferEXT = NULL; PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC glGetFramebufferAttachmentParameterivEXT = NULL; PFNGLGENERATEMIPMAPEXTPROC glGenerateMipmapEXT = NULL; - -// GL_EXT_framebuffer_multisample -PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC glRenderbufferStorageMultisampleEXT = NULL; - -// GL_EXT_framebuffer_blit PFNGLBLITFRAMEBUFFEREXTPROC glBlitFramebufferEXT = NULL; +PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC glRenderbufferStorageMultisampleEXT = NULL; +PFNGLFRAMEBUFFERTEXTURELAYEREXTPROC glFramebufferTextureLayerEXT = NULL; // GL_EXT_blend_func_separate PFNGLBLENDFUNCSEPARATEEXTPROC glBlendFuncSeparateEXT = NULL; @@ -278,6 +315,8 @@ LLGLManager::LLGLManager() : mIsDisabled(FALSE), mHasMultitexture(FALSE), + mHasATIMemInfo(FALSE), + mHasNVXMemInfo(FALSE), mNumTextureUnits(1), mHasMipMapGeneration(FALSE), mHasCompressedTextures(FALSE), @@ -290,7 +329,9 @@ LLGLManager::LLGLManager() : mHasShaderObjects(FALSE), mHasVertexShader(FALSE), mHasFragmentShader(FALSE), + mNumTextureImageUnits(0), mHasOcclusionQuery(FALSE), + mHasOcclusionQuery2(FALSE), mHasPointParameters(FALSE), mHasDrawBuffers(FALSE), mHasTextureRectangle(FALSE), @@ -460,6 +501,20 @@ bool LLGLManager::initGL() // This is called here because it depends on the setting of mIsGF2or4MX, and sets up mHasMultitexture. initExtensions(); + if (mHasATIMemInfo) + { //ask the gl how much vram is free at startup and attempt to use no more than half of that + S32 meminfo[4]; + glGetIntegerv(GL_TEXTURE_FREE_MEMORY_ATI, meminfo); + + mVRAM = meminfo[0]/1024; + } + else if (mHasNVXMemInfo) + { + S32 dedicated_memory; + glGetIntegerv(GL_GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX, &dedicated_memory); + mVRAM = dedicated_memory/1024; + } + if (mHasMultitexture) { GLint num_tex_units; @@ -479,6 +534,12 @@ bool LLGLManager::initGL() return false; } + if (mHasFragmentShader) + { + GLint num_tex_image_units; + glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &num_tex_image_units); + mNumTextureImageUnits = num_tex_image_units; + } initGLStates(); return true; @@ -504,14 +565,13 @@ void LLGLManager::getGLInfo(LLSD& info) std::string LLGLManager::getGLInfoString() { std::string info_str; - std::string all_exts, line; info_str += std::string("GL_VENDOR ") + ll_safe_string((const char *)glGetString(GL_VENDOR)) + std::string("\n"); info_str += std::string("GL_RENDERER ") + ll_safe_string((const char *)glGetString(GL_RENDERER)) + std::string("\n"); info_str += std::string("GL_VERSION ") + ll_safe_string((const char *)glGetString(GL_VERSION)) + std::string("\n"); #if !LL_MESA_HEADLESS - all_exts = (const char *)gGLHExts.mSysExts; + std::string all_exts= ll_safe_string(((const char *)gGLHExts.mSysExts)); LLStringUtil::replaceChar(all_exts, ' ', '\n'); info_str += std::string("GL_EXTENSIONS:\n") + all_exts + std::string("\n"); #endif @@ -522,14 +582,13 @@ std::string LLGLManager::getGLInfoString() void LLGLManager::printGLInfoString() { std::string info_str; - std::string all_exts, line; LL_INFOS("RenderInit") << "GL_VENDOR: " << ((const char *)glGetString(GL_VENDOR)) << LL_ENDL; LL_INFOS("RenderInit") << "GL_RENDERER: " << ((const char *)glGetString(GL_RENDERER)) << LL_ENDL; LL_INFOS("RenderInit") << "GL_VERSION: " << ((const char *)glGetString(GL_VERSION)) << LL_ENDL; #if !LL_MESA_HEADLESS - all_exts = std::string(gGLHExts.mSysExts); + std::string all_exts= ll_safe_string(((const char *)gGLHExts.mSysExts)); LLStringUtil::replaceChar(all_exts, ' ', '\n'); LL_DEBUGS("RenderInit") << "GL_EXTENSIONS:\n" << all_exts << LL_ENDL; #endif @@ -615,6 +674,8 @@ void LLGLManager::initExtensions() mHasTextureRectangle = FALSE; #else // LL_MESA_HEADLESS mHasMultitexture = glh_init_extensions("GL_ARB_multitexture"); + mHasATIMemInfo = ExtensionExists("GL_ATI_meminfo", gGLHExts.mSysExts); + mHasNVXMemInfo = ExtensionExists("GL_NVX_gpu_memory_info", gGLHExts.mSysExts); mHasMipMapGeneration = glh_init_extensions("GL_SGIS_generate_mipmap"); mHasSeparateSpecularColor = glh_init_extensions("GL_EXT_separate_specular_color"); mHasAnisotropic = glh_init_extensions("GL_EXT_texture_filter_anisotropic"); @@ -623,11 +684,18 @@ void LLGLManager::initExtensions() mHasARBEnvCombine = ExtensionExists("GL_ARB_texture_env_combine", gGLHExts.mSysExts); mHasCompressedTextures = glh_init_extensions("GL_ARB_texture_compression"); mHasOcclusionQuery = ExtensionExists("GL_ARB_occlusion_query", gGLHExts.mSysExts); + mHasOcclusionQuery2 = ExtensionExists("GL_ARB_occlusion_query2", gGLHExts.mSysExts); mHasVertexBufferObject = ExtensionExists("GL_ARB_vertex_buffer_object", gGLHExts.mSysExts); mHasDepthClamp = ExtensionExists("GL_ARB_depth_clamp", gGLHExts.mSysExts) || ExtensionExists("GL_NV_depth_clamp", gGLHExts.mSysExts); - // mask out FBO support when packed_depth_stencil isn't there 'cause we need it for LLRenderTarget -Brad - mHasFramebufferObject = ExtensionExists("GL_EXT_framebuffer_object", gGLHExts.mSysExts) - && ExtensionExists("GL_EXT_packed_depth_stencil", gGLHExts.mSysExts); + // mask out FBO support when packed_depth_stencil isn't there 'cause we need it for LLRenderTarget -Brad +#ifdef GL_ARB_framebuffer_object + mHasFramebufferObject = ExtensionExists("GL_ARB_framebuffer_object", gGLHExts.mSysExts); +#else + mHasFramebufferObject = ExtensionExists("GL_EXT_framebuffer_object", gGLHExts.mSysExts) && + ExtensionExists("GL_EXT_framebuffer_blit", gGLHExts.mSysExts) && + ExtensionExists("GL_EXT_framebuffer_multisample", gGLHExts.mSysExts) && + ExtensionExists("GL_EXT_packed_depth_stencil", gGLHExts.mSysExts); +#endif mHasFramebufferMultisample = mHasFramebufferObject && ExtensionExists("GL_EXT_framebuffer_multisample", gGLHExts.mSysExts); mHasDrawBuffers = ExtensionExists("GL_ARB_draw_buffers", gGLHExts.mSysExts); mHasBlendFuncSeparate = ExtensionExists("GL_EXT_blend_func_separate", gGLHExts.mSysExts); @@ -741,6 +809,10 @@ void LLGLManager::initExtensions() { LL_INFOS("RenderInit") << "Couldn't initialize GL_ARB_occlusion_query" << LL_ENDL; } + if (!mHasOcclusionQuery2) + { + LL_INFOS("RenderInit") << "Couldn't initialize GL_ARB_occlusion_query2" << LL_ENDL; + } if (!mHasPointParameters) { LL_INFOS("RenderInit") << "Couldn't initialize GL_ARB_point_parameters" << LL_ENDL; @@ -827,11 +899,9 @@ void LLGLManager::initExtensions() glFramebufferRenderbufferEXT = (PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC) GLH_EXT_GET_PROC_ADDRESS("glFramebufferRenderbufferEXT"); glGetFramebufferAttachmentParameterivEXT = (PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC) GLH_EXT_GET_PROC_ADDRESS("glGetFramebufferAttachmentParameterivEXT"); glGenerateMipmapEXT = (PFNGLGENERATEMIPMAPEXTPROC) GLH_EXT_GET_PROC_ADDRESS("glGenerateMipmapEXT"); - } - if (mHasFramebufferMultisample) - { - glRenderbufferStorageMultisampleEXT = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC) GLH_EXT_GET_PROC_ADDRESS("glRenderbufferStorageMultisampleEXT"); glBlitFramebufferEXT = (PFNGLBLITFRAMEBUFFEREXTPROC) GLH_EXT_GET_PROC_ADDRESS("glBlitFramebufferEXT"); + glRenderbufferStorageMultisampleEXT = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC) GLH_EXT_GET_PROC_ADDRESS("glRenderbufferStorageMultisampleEXT"); + glFramebufferTextureLayerEXT = (PFNGLFRAMEBUFFERTEXTURELAYEREXTPROC) GLH_EXT_GET_PROC_ADDRESS("glFramebufferTextureLayerEXT"); } if (mHasDrawBuffers) { @@ -1003,12 +1073,35 @@ void flush_glerror() glGetError(); } -void assert_glerror() +//this function outputs gl error to the log file, does not crash the code. +void log_glerror() { - if (gNoRender || !gDebugGL) + if (LL_UNLIKELY(!gGLManager.mInited)) { - return; + return ; } + // Create or update texture to be used with this data + GLenum error; + error = glGetError(); + while (LL_UNLIKELY(error)) + { + GLubyte const * gl_error_msg = gluErrorString(error); + if (NULL != gl_error_msg) + { + llwarns << "GL Error: " << error << " GL Error String: " << gl_error_msg << llendl ; + } + else + { + // gluErrorString returns NULL for some extensions' error codes. + // you'll probably have to grep for the number in glext.h. + llwarns << "GL Error: UNKNOWN 0x" << std::hex << error << std::dec << llendl; + } + error = glGetError(); + } +} + +void do_assert_glerror() +{ if (LL_UNLIKELY(!gGLManager.mInited)) { LL_ERRS("RenderInit") << "GL not initialized" << LL_ENDL; @@ -1020,29 +1113,65 @@ void assert_glerror() while (LL_UNLIKELY(error)) { quit = TRUE; -#ifndef LL_LINUX // *FIX: ! This should be an error for linux as well. GLubyte const * gl_error_msg = gluErrorString(error); if (NULL != gl_error_msg) { LL_WARNS("RenderState") << "GL Error:" << error<< LL_ENDL; LL_WARNS("RenderState") << "GL Error String:" << gl_error_msg << LL_ENDL; + + if (gDebugSession) + { + gFailLog << "GL Error:" << gl_error_msg << std::endl; + } } else { // gluErrorString returns NULL for some extensions' error codes. // you'll probably have to grep for the number in glext.h. LL_WARNS("RenderState") << "GL Error: UNKNOWN 0x" << std::hex << error << std::dec << LL_ENDL; + + if (gDebugSession) + { + gFailLog << "GL Error: UNKNOWN 0x" << std::hex << error << std::dec << std::endl; + } } error = glGetError(); -#endif } if (quit) { - llerrs << "One or more unhandled GL errors." << llendl; + if (gDebugSession) + { + ll_fail("assert_glerror failed"); + } + else + { + llerrs << "One or more unhandled GL errors." << llendl; + } } } +void assert_glerror() +{ + if (gNoRender) + return; + if (!gGLActive) + { + //llwarns << "GL used while not active!" << llendl; + + if (gDebugSession) + { + //ll_fail("GL used while not active"); + } + } + + if (gDebugGL) + { + do_assert_glerror(); + } +} + + void clear_glerror() { // Create or update texture to be used with this data @@ -1125,9 +1254,19 @@ void LLGLState::checkStates(const std::string& msg) glGetIntegerv(GL_BLEND_SRC, &src); glGetIntegerv(GL_BLEND_DST, &dst); + BOOL error = FALSE; + if (src != GL_SRC_ALPHA || dst != GL_ONE_MINUS_SRC_ALPHA) { - LL_GL_ERRS << "Blend function corrupted: " << std::hex << src << " " << std::hex << dst << " " << msg << std::dec << LL_ENDL; + if (gDebugSession) + { + gFailLog << "Blend function corrupted: " << std::hex << src << " " << std::hex << dst << " " << msg << std::dec << std::endl; + error = TRUE; + } + else + { + LL_GL_ERRS << "Blend function corrupted: " << std::hex << src << " " << std::hex << dst << " " << msg << std::dec << LL_ENDL; + } } for (boost::unordered_map::iterator iter = sStateMap.begin(); @@ -1139,10 +1278,22 @@ void LLGLState::checkStates(const std::string& msg) if(cur_state != gl_state) { dumpStates(); - LL_GL_ERRS << llformat("LLGLState error. State: 0x%04x",state) << LL_ENDL; + if (gDebugSession) + { + gFailLog << llformat("LLGLState error. State: 0x%04x",state) << std::endl; + error = TRUE; + } + else + { + LL_GL_ERRS << llformat("LLGLState error. State: 0x%04x",state) << LL_ENDL; + } } } + if (error) + { + ll_fail("LLGLState::checkStates failed."); + } stop_glerror(); } @@ -1153,9 +1304,12 @@ void LLGLState::checkTextureChannels(const std::string& msg) return; } + stop_glerror(); + GLint activeTexture; glGetIntegerv(GL_ACTIVE_TEXTURE_ARB, &activeTexture); - + stop_glerror(); + BOOL error = FALSE; if (activeTexture == GL_TEXTURE0_ARB) @@ -1163,15 +1317,22 @@ void LLGLState::checkTextureChannels(const std::string& msg) GLint tex_env_mode = 0; glGetTexEnviv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &tex_env_mode); + stop_glerror(); + if (tex_env_mode != GL_MODULATE) { error = TRUE; LL_WARNS("RenderState") << "GL_TEXTURE_ENV_MODE invalid: " << std::hex << tex_env_mode << std::dec << LL_ENDL; + if (gDebugSession) + { + gFailLog << "GL_TEXTURE_ENV_MODE invalid: " << std::hex << tex_env_mode << std::dec << std::endl; + } } } GLint maxTextureUnits = 0; glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &maxTextureUnits); + stop_glerror(); static const char* label[] = { @@ -1200,35 +1361,44 @@ void LLGLState::checkTextureChannels(const std::string& msg) }; GLint stackDepth = 0; + glh::matrix4f mat; glh::matrix4f identity; identity.identity(); -// LLMatrix4 identity; -// LLMatrix4 matrix; for (GLint i = 1; i < maxTextureUnits; i++) { gGL.getTexUnit(i)->activate(); glClientActiveTextureARB(GL_TEXTURE0_ARB+i); - + stop_glerror(); glGetIntegerv(GL_TEXTURE_STACK_DEPTH, &stackDepth); + stop_glerror(); if (stackDepth != 1) { error = TRUE; LL_WARNS("RenderState") << "Texture matrix stack corrupted." << LL_ENDL; + + if (gDebugSession) + { + gFailLog << "Texture matrix stack corrupted." << std::endl; + } } - //glGetFloatv(GL_TEXTURE_MATRIX, (GLfloat*) matrix.mMatrix); glGetFloatv(GL_TEXTURE_MATRIX, (GLfloat*) mat.m); + stop_glerror(); - //if (matrix != identity) if (mat != identity) { error = TRUE; LL_WARNS("RenderState") << "Texture matrix in channel " << i << " corrupt." << LL_ENDL; + if (gDebugSession) + { + gFailLog << "Texture matrix in channel " << i << " corrupt." << std::endl; + } } + for (S32 j = (i == 0 ? 1 : 0); j < (gGLManager.mHasTextureRectangle ? 9 : 8); j++) { @@ -1236,24 +1406,42 @@ void LLGLState::checkTextureChannels(const std::string& msg) { error = TRUE; LL_WARNS("RenderState") << "Texture channel " << i << " still has " << label[j] << " enabled." << LL_ENDL; + if (gDebugSession) + { + gFailLog << "Texture channel " << i << " still has " << label[j] << " enabled." << std::endl; + } } + stop_glerror(); } glGetFloatv(GL_TEXTURE_MATRIX, mat.m); + stop_glerror(); if (mat != identity) { error = TRUE; LL_WARNS("RenderState") << "Texture matrix " << i << " is not identity." << LL_ENDL; + if (gDebugSession) + { + gFailLog << "Texture matrix " << i << " is not identity." << std::endl; + } } } gGL.getTexUnit(0)->activate(); glClientActiveTextureARB(GL_TEXTURE0_ARB); + stop_glerror(); if (error) { - LL_GL_ERRS << "GL texture state corruption detected. " << msg << LL_ENDL; + if (gDebugSession) + { + ll_fail("LLGLState::checkTextureChannels failed."); + } + else + { + LL_GL_ERRS << "GL texture state corruption detected. " << msg << LL_ENDL; + } } } @@ -1273,6 +1461,10 @@ void LLGLState::checkClientArrays(const std::string& msg, U32 data_mask) if (active_texture != GL_TEXTURE0_ARB) { llwarns << "Client active texture corrupted: " << active_texture << llendl; + if (gDebugSession) + { + gFailLog << "Client active texture corrupted: " << active_texture << std::endl; + } error = TRUE; } @@ -1280,6 +1472,10 @@ void LLGLState::checkClientArrays(const std::string& msg, U32 data_mask) if (active_texture != GL_TEXTURE0_ARB) { llwarns << "Active texture corrupted: " << active_texture << llendl; + if (gDebugSession) + { + gFailLog << "Active texture corrupted: " << active_texture << std::endl; + } error = TRUE; } @@ -1316,6 +1512,10 @@ void LLGLState::checkClientArrays(const std::string& msg, U32 data_mask) { error = TRUE; LL_WARNS("RenderState") << "GL still has " << label[j] << " enabled." << LL_ENDL; + if (gDebugSession) + { + gFailLog << "GL still has " << label[j] << " enabled." << std::endl; + } } } else @@ -1324,6 +1524,10 @@ void LLGLState::checkClientArrays(const std::string& msg, U32 data_mask) { error = TRUE; LL_WARNS("RenderState") << "GL does not have " << label[j] << " enabled." << LL_ENDL; + if (gDebugSession) + { + gFailLog << "GL does not have " << label[j] << " enabled." << std::endl; + } } } } @@ -1336,6 +1540,10 @@ void LLGLState::checkClientArrays(const std::string& msg, U32 data_mask) { error = TRUE; LL_WARNS("RenderState") << "GL still has GL_TEXTURE_COORD_ARRAY enabled on channel 1." << LL_ENDL; + if (gDebugSession) + { + gFailLog << "GL still has GL_TEXTURE_COORD_ARRAY enabled on channel 1." << std::endl; + } } } else @@ -1344,6 +1552,10 @@ void LLGLState::checkClientArrays(const std::string& msg, U32 data_mask) { error = TRUE; LL_WARNS("RenderState") << "GL does not have GL_TEXTURE_COORD_ARRAY enabled on channel 1." << LL_ENDL; + if (gDebugSession) + { + gFailLog << "GL does not have GL_TEXTURE_COORD_ARRAY enabled on channel 1." << std::endl; + } } } @@ -1353,6 +1565,10 @@ void LLGLState::checkClientArrays(const std::string& msg, U32 data_mask) { error = TRUE; LL_WARNS("RenderState") << "GL still has GL_TEXTURE_2D enabled on channel 1." << LL_ENDL; + if (gDebugSession) + { + gFailLog << "GL still has GL_TEXTURE_2D enabled on channel 1." << std::endl; + } } } else @@ -1361,6 +1577,10 @@ void LLGLState::checkClientArrays(const std::string& msg, U32 data_mask) { error = TRUE; LL_WARNS("RenderState") << "GL does not have GL_TEXTURE_2D enabled on channel 1." << LL_ENDL; + if (gDebugSession) + { + gFailLog << "GL does not have GL_TEXTURE_2D enabled on channel 1." << std::endl; + } } } @@ -1379,13 +1599,24 @@ void LLGLState::checkClientArrays(const std::string& msg, U32 data_mask) { error = TRUE; LL_WARNS("RenderState") << "GL still has vertex attrib array " << i << " enabled." << LL_ENDL; + if (gDebugSession) + { + gFailLog << "GL still has vertex attrib array " << i << " enabled." << std::endl; + } } } } if (error) { + if (gDebugSession) + { + ll_fail("LLGLState::checkClientArrays failed."); + } + else + { LL_GL_ERRS << "GL client array corruption detected. " << msg << LL_ENDL; + } } } @@ -1436,7 +1667,17 @@ LLGLState::~LLGLState() { if (gDebugGL) { + if (!gDebugSession) + { llassert_always(sStateMap[mState] == glIsEnabled(mState)); + } + else + { + if (sStateMap[mState] != glIsEnabled(mState)) + { + ll_fail("GL enabled state does not match expected"); + } + } } if (mIsEnabled != mWasEnabled) @@ -1620,12 +1861,17 @@ void parse_gl_version( S32* major, S32* minor, S32* release, std::string* vendor } } -LLGLUserClipPlane::LLGLUserClipPlane(const LLPlane& p, const glh::matrix4f& modelview, const glh::matrix4f& projection) +LLGLUserClipPlane::LLGLUserClipPlane(const LLPlane& p, const glh::matrix4f& modelview, const glh::matrix4f& projection, bool apply) { - mModelview = modelview; - mProjection = projection; + mApply = apply; - setPlane(p.mV[0], p.mV[1], p.mV[2], p.mV[3]); + if (mApply) + { + mModelview = modelview; + mProjection = projection; + + setPlane(p[0], p[1], p[2], p[3]); + } } void LLGLUserClipPlane::setPlane(F32 a, F32 b, F32 c, F32 d) @@ -1656,31 +1902,20 @@ void LLGLUserClipPlane::setPlane(F32 a, F32 b, F32 c, F32 d) LLGLUserClipPlane::~LLGLUserClipPlane() { - glMatrixMode(GL_PROJECTION); - glPopMatrix(); - glMatrixMode(GL_MODELVIEW); + if (mApply) + { + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + } } LLGLNamePool::LLGLNamePool() { } -void LLGLNamePool::registerPool(LLGLNamePool* pool) -{ - pool_list_t::iterator iter = std::find(sInstances.begin(), sInstances.end(), pool); - if (iter == sInstances.end()) - { - sInstances.push_back(pool); - } -} - LLGLNamePool::~LLGLNamePool() { - pool_list_t::iterator iter = std::find(sInstances.begin(), sInstances.end(), this); - if (iter != sInstances.end()) - { - sInstances.erase(iter); - } } void LLGLNamePool::upkeep() @@ -1748,20 +1983,22 @@ void LLGLNamePool::release(GLuint name) //static void LLGLNamePool::upkeepPools() { - for (pool_list_t::iterator iter = sInstances.begin(); iter != sInstances.end(); ++iter) + tracker_t::LLInstanceTrackerScopedGuard guard; + for (tracker_t::instance_iter iter = guard.beginInstances(); iter != guard.endInstances(); ++iter) { - LLGLNamePool* pool = *iter; - pool->upkeep(); + LLGLNamePool & pool = *iter; + pool.upkeep(); } } //static void LLGLNamePool::cleanupPools() { - for (pool_list_t::iterator iter = sInstances.begin(); iter != sInstances.end(); ++iter) + tracker_t::LLInstanceTrackerScopedGuard guard; + for (tracker_t::instance_iter iter = guard.beginInstances(); iter != guard.endInstances(); ++iter) { - LLGLNamePool* pool = *iter; - pool->cleanup(); + LLGLNamePool & pool = *iter; + pool.cleanup(); } } @@ -1838,17 +2075,26 @@ void LLGLDepthTest::checkState() sWriteEnabled != mask || sDepthFunc != func) { + if (gDebugSession) + { + gFailLog << "Unexpected depth testing state." << std::endl; + } + else { LL_GL_ERRS << "Unexpected depth testing state." << LL_ENDL; } } } } -LLGLSquashToFarClip::LLGLSquashToFarClip(glh::matrix4f P) + +LLGLSquashToFarClip::LLGLSquashToFarClip(glh::matrix4f P, U32 layer) { + + F32 depth = 0.99999f - 0.0001f * layer; + for (U32 i = 0; i < 4; i++) { - P.element(2, i) = P.element(3, i) * 0.99999f; + P.element(2, i) = P.element(3, i) * depth; } glMatrixMode(GL_PROJECTION); diff --git a/indra/llrender/llgl.h b/indra/llrender/llgl.h index da4bde75f..2e0ca22e5 100644 --- a/indra/llrender/llgl.h +++ b/indra/llrender/llgl.h @@ -37,7 +37,7 @@ #include #include -#include +#include #include "llerror.h" #include "v4color.h" @@ -46,14 +46,23 @@ #include "v4math.h" #include "llplane.h" #include "llgltypes.h" +#include "llinstancetracker.h" #include "llglheaders.h" #include "glh/glh_linear.h" extern BOOL gDebugGL; +extern BOOL gDebugSession; +extern std::ofstream gFailLog; #define LL_GL_ERRS LL_ERRS("RenderState") +void ll_init_fail_log(std::string filename); + +void ll_fail(std::string msg); + +void ll_close_fail_log(); + class LLSD; // Manage GL extensions... @@ -74,6 +83,8 @@ public: // Extensions used by everyone BOOL mHasMultitexture; + BOOL mHasATIMemInfo; + BOOL mHasNVXMemInfo; S32 mNumTextureUnits; BOOL mHasMipMapGeneration; BOOL mHasCompressedTextures; @@ -87,7 +98,9 @@ public: BOOL mHasShaderObjects; BOOL mHasVertexShader; BOOL mHasFragmentShader; + S32 mNumTextureImageUnits; BOOL mHasOcclusionQuery; + BOOL mHasOcclusionQuery2; BOOL mHasPointParameters; BOOL mHasDrawBuffers; BOOL mHasDepthClamp; @@ -152,6 +165,7 @@ void rotate_quat(LLQuaternion& rotation); void flush_glerror(); // Flush GL errors when we know we're handling them correctly. +void log_glerror(); void assert_glerror(); void clear_glerror(); @@ -292,12 +306,14 @@ class LLGLUserClipPlane { public: - LLGLUserClipPlane(const LLPlane& plane, const glh::matrix4f& modelview, const glh::matrix4f& projection); + LLGLUserClipPlane(const LLPlane& plane, const glh::matrix4f& modelview, const glh::matrix4f& projection, bool apply = true); ~LLGLUserClipPlane(); void setPlane(F32 a, F32 b, F32 c, F32 d); private: + bool mApply; + glh::matrix4f mProjection; glh::matrix4f mModelview; }; @@ -313,7 +329,7 @@ private: class LLGLSquashToFarClip { public: - LLGLSquashToFarClip(glh::matrix4f projection); + LLGLSquashToFarClip(glh::matrix4f projection, U32 layer = 0); ~LLGLSquashToFarClip(); }; @@ -321,9 +337,11 @@ public: Generic pooling scheme for things which use GL names (used for occlusion queries and vertex buffer objects). Prevents thrashing of GL name caches by avoiding calls to glGenFoo and glDeleteFoo. */ -class LLGLNamePool +class LLGLNamePool : public LLInstanceTracker { public: + typedef LLInstanceTracker tracker_t; + struct NameEntry { GLuint name; @@ -350,13 +368,11 @@ public: GLuint allocate(); void release(GLuint name); - static void registerPool(LLGLNamePool* pool); static void upkeepPools(); static void cleanupPools(); protected: typedef std::vector pool_list_t; - static pool_list_t sInstances; virtual GLuint allocateName() = 0; virtual void releaseName(GLuint name) = 0; @@ -411,4 +427,66 @@ extern BOOL gClothRipple; extern BOOL gNoRender; extern BOOL gGLActive; +// Deal with changing glext.h definitions for newer SDK versions, specifically +// with MAC OSX 10.5 -> 10.6 + + +#ifndef GL_DEPTH_ATTACHMENT +#define GL_DEPTH_ATTACHMENT GL_DEPTH_ATTACHMENT_EXT +#endif + +#ifndef GL_STENCIL_ATTACHMENT +#define GL_STENCIL_ATTACHMENT GL_STENCIL_ATTACHMENT_EXT +#endif + +#ifndef GL_FRAMEBUFFER +#define GL_FRAMEBUFFER GL_FRAMEBUFFER_EXT +#define GL_DRAW_FRAMEBUFFER GL_DRAW_FRAMEBUFFER_EXT +#define GL_READ_FRAMEBUFFER GL_READ_FRAMEBUFFER_EXT +#define GL_FRAMEBUFFER_COMPLETE GL_FRAMEBUFFER_COMPLETE_EXT +#define GL_FRAMEBUFFER_UNSUPPORTED GL_FRAMEBUFFER_UNSUPPORTED_EXT +#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT +#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT +#define glGenFramebuffers glGenFramebuffersEXT +#define glBindFramebuffer glBindFramebufferEXT +#define glCheckFramebufferStatus glCheckFramebufferStatusEXT +#define glBlitFramebuffer glBlitFramebufferEXT +#define glDeleteFramebuffers glDeleteFramebuffersEXT +#define glFramebufferRenderbuffer glFramebufferRenderbufferEXT +#define glFramebufferTexture2D glFramebufferTexture2DEXT +#endif + +#ifndef GL_RENDERBUFFER +#define GL_RENDERBUFFER GL_RENDERBUFFER_EXT +#define glGenRenderbuffers glGenRenderbuffersEXT +#define glBindRenderbuffer glBindRenderbufferEXT +#define glRenderbufferStorage glRenderbufferStorageEXT +#define glRenderbufferStorageMultisample glRenderbufferStorageMultisampleEXT +#define glDeleteRenderbuffers glDeleteRenderbuffersEXT +#endif + +#ifndef GL_COLOR_ATTACHMENT +#define GL_COLOR_ATTACHMENT GL_COLOR_ATTACHMENT_EXT +#endif + +#ifndef GL_COLOR_ATTACHMENT0 +#define GL_COLOR_ATTACHMENT0 GL_COLOR_ATTACHMENT0_EXT +#endif + +#ifndef GL_COLOR_ATTACHMENT1 +#define GL_COLOR_ATTACHMENT1 GL_COLOR_ATTACHMENT1_EXT +#endif + +#ifndef GL_COLOR_ATTACHMENT2 +#define GL_COLOR_ATTACHMENT2 GL_COLOR_ATTACHMENT2_EXT +#endif + +#ifndef GL_COLOR_ATTACHMENT3 +#define GL_COLOR_ATTACHMENT3 GL_COLOR_ATTACHMENT3_EXT +#endif + + +#ifndef GL_DEPTH24_STENCIL8 +#define GL_DEPTH24_STENCIL8 GL_DEPTH24_STENCIL8_EXT +#endif #endif // LL_LLGL_H diff --git a/indra/llrender/llglheaders.h b/indra/llrender/llglheaders.h index 81ae3d40e..9efe16432 100644 --- a/indra/llrender/llglheaders.h +++ b/indra/llrender/llglheaders.h @@ -473,17 +473,17 @@ extern PFNGLFRAMEBUFFERTEXTURE3DEXTPROC glFramebufferTexture3DEXT; extern PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC glFramebufferRenderbufferEXT; extern PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC glGetFramebufferAttachmentParameterivEXT; extern PFNGLGENERATEMIPMAPEXTPROC glGenerateMipmapEXT; - -// GL_EXT_framebuffer_multisample -extern PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC glRenderbufferStorageMultisampleEXT; - -// GL_EXT_framebuffer_blit extern PFNGLBLITFRAMEBUFFEREXTPROC glBlitFramebufferEXT; +extern PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC glRenderbufferStorageMultisampleEXT; +extern PFNGLFRAMEBUFFERTEXTURELAYEREXTPROC glFramebufferTextureLayerEXT; //GL_ARB_draw_buffers extern PFNGLDRAWBUFFERSARBPROC glDrawBuffersARB; + #elif LL_WINDOWS +//---------------------------------------------------------------------------- +// LL_WINDOWS // windows gl headers depend on things like APIENTRY, so include windows. #define WIN32_LEAN_AND_MEAN @@ -672,12 +672,9 @@ extern PFNGLFRAMEBUFFERTEXTURE3DEXTPROC glFramebufferTexture3DEXT; extern PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC glFramebufferRenderbufferEXT; extern PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC glGetFramebufferAttachmentParameterivEXT; extern PFNGLGENERATEMIPMAPEXTPROC glGenerateMipmapEXT; - -// GL_EXT_framebuffer_multisample -extern PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC glRenderbufferStorageMultisampleEXT; - -// GL_EXT_framebuffer_blit extern PFNGLBLITFRAMEBUFFEREXTPROC glBlitFramebufferEXT; +extern PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC glRenderbufferStorageMultisampleEXT; +extern PFNGLFRAMEBUFFERTEXTURELAYEREXTPROC glFramebufferTextureLayerEXT; //GL_ARB_draw_buffers extern PFNGLDRAWBUFFERSARBPROC glDrawBuffersARB; @@ -720,6 +717,9 @@ extern void glFramebufferRenderbufferEXT(GLenum target, GLenum attachment, GLenu extern void glGetFramebufferAttachmentParameterivEXT(GLenum target, GLenum attachment, GLenum pname, GLint *params) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER; extern void glGenerateMipmapEXT(GLenum target) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER; +#ifndef GL_ARB_framebuffer_object +#define glGenerateMipmap glGenerateMipmapEXT +#endif // GL_ARB_draw_buffers extern void glDrawBuffersARB(GLsizei n, const GLenum* bufs) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER; @@ -842,4 +842,21 @@ extern void glGetBufferPointervARB (GLenum, GLenum, GLvoid* *); #define GL_DEPTH_CLAMP 0x864F #endif +//GL_NVX_gpu_memory_info constants +#ifndef GL_NVX_gpu_memory_info +#define GL_NVX_gpu_memory_info +#define GL_GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX 0x9047 +#define GL_GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX 0x9048 +#define GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX 0x9049 +#define GL_GPU_MEMORY_INFO_EVICTION_COUNT_NVX 0x904A +#define GL_GPU_MEMORY_INFO_EVICTED_MEMORY_NVX 0x904B +#endif + +//GL_ATI_meminfo constants +#ifndef GL_ATI_meminfo +#define GL_ATI_meminfo +#define GL_VBO_FREE_MEMORY_ATI 0x87FB +#define GL_TEXTURE_FREE_MEMORY_ATI 0x87FC +#define GL_RENDERBUFFER_FREE_MEMORY_ATI 0x87FD +#endif #endif // LL_LLGLHEADERS_H diff --git a/indra/llrender/llglimmediate.cpp b/indra/llrender/llglimmediate.cpp deleted file mode 100644 index 17c2182df..000000000 --- a/indra/llrender/llglimmediate.cpp +++ /dev/null @@ -1 +0,0 @@ -#error This file has been renamed llrender.cpp diff --git a/indra/llrender/llglimmediate.h b/indra/llrender/llglimmediate.h deleted file mode 100644 index 4a7a0ebec..000000000 --- a/indra/llrender/llglimmediate.h +++ /dev/null @@ -1 +0,0 @@ -#error This file has been renamed llrender.h diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp index 057b025d9..5eb5ffd10 100644 --- a/indra/llrender/llglslshader.cpp +++ b/indra/llrender/llglslshader.cpp @@ -420,7 +420,15 @@ S32 LLGLSLShader::disableTexture(S32 uniform, LLTexUnit::eTextureType mode) { if (gDebugGL && gGL.getTexUnit(index)->getCurrType() != mode) { - llerrs << "Texture channel " << index << " texture type corrupted." << llendl; + if (gDebugSession) + { + gFailLog << "Texture channel " << index << " texture type corrupted." << std::endl; + ll_fail("LLGLSLShader::disableTexture failed"); + } + else + { + llerrs << "Texture channel " << index << " texture type corrupted." << llendl; + } } gGL.getTexUnit(index)->disable(); } @@ -708,17 +716,46 @@ void LLGLSLShader::uniformMatrix4fv(U32 index, U32 count, GLboolean transpose, c GLint LLGLSLShader::getUniformLocation(const string& uniform) { + GLint ret = -1; if (mProgramObject > 0) { std::map::iterator iter = mUniformMap.find(uniform); if (iter != mUniformMap.end()) { - llassert(iter->second == glGetUniformLocationARB(mProgramObject, uniform.c_str())); - return iter->second; + if (gDebugGL) + { + stop_glerror(); + if (iter->second != glGetUniformLocationARB(mProgramObject, uniform.c_str())) + { + llerrs << "Uniform does not match." << llendl; + } + stop_glerror(); + } + ret = iter->second; } } - return -1; + /*if (gDebugGL) + { + if (ret == -1 && ret != glGetUniformLocationARB(mProgramObject, uniform.c_str())) + { + llerrs << "Uniform map invalid." << llendl; + } + }*/ + + return ret; +} + +GLint LLGLSLShader::getAttribLocation(U32 attrib) +{ + if (attrib < mAttribute.size()) + { + return mAttribute[attrib]; + } + else + { + return -1; + } } void LLGLSLShader::uniform1i(const string& uniform, GLint v) @@ -892,7 +929,9 @@ void LLGLSLShader::uniformMatrix4fv(const string& uniform, U32 count, GLboolean if (location >= 0) { + stop_glerror(); glUniformMatrix4fvARB(location, count, transpose, v); + stop_glerror(); } } diff --git a/indra/llrender/llglslshader.h b/indra/llrender/llglslshader.h index 1f46a7b4f..3c47e7504 100644 --- a/indra/llrender/llglslshader.h +++ b/indra/llrender/llglslshader.h @@ -109,7 +109,7 @@ public: void vertexAttrib4fv(U32 index, GLfloat* v); GLint getUniformLocation(const std::string& uniform); - + GLint getAttribLocation(U32 attrib); GLint mapUniformTextureChannel(GLint location, GLenum type); diff --git a/indra/llrender/llglstates.h b/indra/llrender/llglstates.h index 9ade49e4e..e26aead67 100644 --- a/indra/llrender/llglstates.h +++ b/indra/llrender/llglstates.h @@ -262,25 +262,4 @@ public: //---------------------------------------------------------------------------- - -class LLGLSBlendFunc : public LLGLSPipeline { -protected: - GLint mSavedSrc, mSavedDst; - LLGLEnable mBlend; - -public: - LLGLSBlendFunc(GLenum srcFunc, GLenum dstFunc) : - mBlend(GL_BLEND) - { - glGetIntegerv(GL_BLEND_SRC, &mSavedSrc); - glGetIntegerv(GL_BLEND_DST, &mSavedDst); - glBlendFunc(srcFunc, dstFunc); - } - - ~LLGLSBlendFunc(void) { - glBlendFunc(mSavedSrc, mSavedDst); - } -}; - - #endif diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index f20e0d6ad..763b9a772 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -110,24 +110,58 @@ void LLImageGL::checkTexSize(bool forced) const { if ((forced || gDebugGL) && mTarget == GL_TEXTURE_2D) { + { + //check viewport + GLint vp[4] ; + glGetIntegerv(GL_VIEWPORT, vp) ; + llcallstacks << "viewport: " << vp[0] << " : " << vp[1] << " : " << vp[2] << " : " << vp[3] << llcallstacksendl ; + } GLint texname; glGetIntegerv(GL_TEXTURE_BINDING_2D, &texname); + BOOL error = FALSE; if (texname != mTexName) { - llerrs << "Invalid texture bound!" << llendl; + llinfos << "Bound: " << texname << " Should bind: " << mTexName << " Default: " << LLImageGL::sDefaultGLTexture->getTexName() << llendl; + + error = TRUE; + if (gDebugSession) + { + gFailLog << "Invalid texture bound!" << std::endl; + } + else + { + llerrs << "Invalid texture bound!" << llendl; + } } stop_glerror() ; LLGLint x = 0, y = 0 ; glGetTexLevelParameteriv(mTarget, 0, GL_TEXTURE_WIDTH, (GLint*)&x); glGetTexLevelParameteriv(mTarget, 0, GL_TEXTURE_HEIGHT, (GLint*)&y) ; stop_glerror() ; + llcallstacks << "w: " << x << " h: " << y << llcallstacksendl ; + if(!x || !y) { return ; } if(x != (mWidth >> mCurrentDiscardLevel) || y != (mHeight >> mCurrentDiscardLevel)) { - llerrs << "wrong texture size and discard level!" << llendl ; + error = TRUE; + if (gDebugSession) + { + gFailLog << "wrong texture size and discard level!" << + mWidth << " Height: " << mHeight << " Current Level: " << (S32)mCurrentDiscardLevel << std::endl; + } + else + { + llerrs << "wrong texture size and discard level: width: " << + mWidth << " Height: " << mHeight << " Current Level: " << (S32)mCurrentDiscardLevel << llendl ; + } + } + + if (error) + { + ll_fail("LLImageGL::checkTexSize failed."); } } } @@ -649,7 +683,7 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips) } // LLFastTimer t2(LLFastTimer::FTM_TEMP2); - gGL.getTexUnit(0)->bind(this); + llverify(gGL.getTexUnit(0)->bind(this)); if (mUseMipMaps) { @@ -864,12 +898,14 @@ BOOL LLImageGL::setSubImage(const U8* datap, S32 data_width, S32 data_height, S3 } if (mTexName == 0) { - llwarns << "Setting subimage on image without GL texture" << llendl; + // *TODO: Re-enable warning? Ran into thread locking issues? DK 2011-02-18 + //llwarns << "Setting subimage on image without GL texture" << llendl; return FALSE; } if (datap == NULL) { - llwarns << "Setting subimage on image with NULL datap" << llendl; + // *TODO: Re-enable warning? Ran into thread locking issues? DK 2011-02-18 + //llwarns << "Setting subimage on image with NULL datap" << llendl; return FALSE; } @@ -991,6 +1027,7 @@ void LLImageGL::deleteTextures(S32 numTextures, U32 *textures) void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 width, S32 height, U32 pixformat, U32 pixtype, const void *pixels) { glTexImage2D(target, miplevel, intformat, width, height, 0, pixformat, pixtype, pixels); + stop_glerror(); } //create an empty GL texture: just create a texture name @@ -1143,6 +1180,13 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_ if (mUseMipMaps) { mAutoGenMips = gGLManager.mHasMipMapGeneration; +#if LL_DARWIN + // On the Mac GF2 and GF4MX drivers, auto mipmap generation doesn't work right with alpha-only textures. + if(gGLManager.mIsGF2or4MX && (mFormatInternal == GL_ALPHA8) && (mFormatPrimary == GL_ALPHA)) + { + mAutoGenMips = FALSE; + } +#endif } mCurrentDiscardLevel = discard_level; diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index 5bc77f437..b10c77c1a 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -45,10 +45,12 @@ LLRender gGL; // Handy copies of last good GL matrices F64 gGLModelView[16]; F64 gGLLastModelView[16]; +F64 gGLLastProjection[16]; F64 gGLProjection[16]; S32 gGLViewport[4]; static const U32 LL_NUM_TEXTURE_LAYERS = 8; +static const U32 LL_NUM_LIGHT_UNITS = 8; static GLenum sGLTextureType[] = { @@ -118,14 +120,29 @@ void LLTexUnit::refreshState(void) // and we reset the cached tex unit state glActiveTextureARB(GL_TEXTURE0_ARB + mIndex); + + // + // Per apple spec, don't call glEnable/glDisable when index exceeds max texture units + // http://www.mailinglistarchive.com/html/mac-opengl@lists.apple.com/2008-07/msg00653.html + // + bool enableDisable = (mIndex < gGLManager.mNumTextureUnits); + if (mCurrTexType != TT_NONE) { - glEnable(sGLTextureType[mCurrTexType]); + if (enableDisable) + { + glEnable(sGLTextureType[mCurrTexType]); + } + glBindTexture(sGLTextureType[mCurrTexType], mCurrTexture); } else { - glDisable(GL_TEXTURE_2D); + if (enableDisable) + { + glDisable(GL_TEXTURE_2D); + } + glBindTexture(GL_TEXTURE_2D, 0); } @@ -144,7 +161,7 @@ void LLTexUnit::activate(void) { if (mIndex < 0) return; - if (gGL.mCurrTextureUnitIndex != mIndex || gGL.mDirty) + if ((S32)gGL.mCurrTextureUnitIndex != mIndex || gGL.mDirty) { glActiveTextureARB(GL_TEXTURE0_ARB + mIndex); gGL.mCurrTextureUnitIndex = mIndex; @@ -163,7 +180,10 @@ void LLTexUnit::enable(eTextureType type) disable(); // Force a disable of a previous texture type if it's enabled. } mCurrTexType = type; - glEnable(sGLTextureType[type]); + if (mIndex < gGLManager.mNumTextureUnits) + { + glEnable(sGLTextureType[type]); + } } } @@ -175,7 +195,11 @@ void LLTexUnit::disable(void) { activate(); unbind(mCurrTexType); - glDisable(sGLTextureType[mCurrTexType]); + if (mIndex < gGLManager.mNumTextureUnits) + { + glDisable(sGLTextureType[mCurrTexType]); + } + mCurrTexType = TT_NONE; } } @@ -729,6 +753,130 @@ void LLTexUnit::debugTextureUnit(void) } } +LLLightState::LLLightState(S32 index) +: mIndex(index), + mEnabled(false), + mConstantAtten(1.f), + mLinearAtten(0.f), + mQuadraticAtten(0.f), + mSpotExponent(0.f), + mSpotCutoff(180.f) +{ + if (mIndex == 0) + { + mDiffuse.set(1,1,1,1); + mSpecular.set(1,1,1,1); + } + + mAmbient.set(0,0,0,1); + mPosition.set(0,0,1,0); + mSpotDirection.set(0,0,-1); + +} + +void LLLightState::enable() +{ + if (!mEnabled) + { + glEnable(GL_LIGHT0+mIndex); + mEnabled = true; + } +} + +void LLLightState::disable() +{ + if (mEnabled) + { + glDisable(GL_LIGHT0+mIndex); + mEnabled = false; + } +} + +void LLLightState::setDiffuse(const LLColor4& diffuse) +{ + if (mDiffuse != diffuse) + { + mDiffuse = diffuse; + glLightfv(GL_LIGHT0+mIndex, GL_DIFFUSE, mDiffuse.mV); + } +} + +void LLLightState::setAmbient(const LLColor4& ambient) +{ + if (mAmbient != ambient) + { + mAmbient = ambient; + glLightfv(GL_LIGHT0+mIndex, GL_AMBIENT, mAmbient.mV); + } +} + +void LLLightState::setSpecular(const LLColor4& specular) +{ + if (mSpecular != specular) + { + mSpecular = specular; + glLightfv(GL_LIGHT0+mIndex, GL_SPECULAR, mSpecular.mV); + } +} + +void LLLightState::setPosition(const LLVector4& position) +{ + //always set position because modelview matrix may have changed + mPosition = position; + glLightfv(GL_LIGHT0+mIndex, GL_POSITION, mPosition.mV); +} + +void LLLightState::setConstantAttenuation(const F32& atten) +{ + if (mConstantAtten != atten) + { + mConstantAtten = atten; + glLightf(GL_LIGHT0+mIndex, GL_CONSTANT_ATTENUATION, atten); + } +} + +void LLLightState::setLinearAttenuation(const F32& atten) +{ + if (mLinearAtten != atten) + { + mLinearAtten = atten; + glLightf(GL_LIGHT0+mIndex, GL_LINEAR_ATTENUATION, atten); + } +} + +void LLLightState::setQuadraticAttenuation(const F32& atten) +{ + if (mQuadraticAtten != atten) + { + mQuadraticAtten = atten; + glLightf(GL_LIGHT0+mIndex, GL_QUADRATIC_ATTENUATION, atten); + } +} + +void LLLightState::setSpotExponent(const F32& exponent) +{ + if (mSpotExponent != exponent) + { + mSpotExponent = exponent; + glLightf(GL_LIGHT0+mIndex, GL_SPOT_EXPONENT, exponent); + } +} + +void LLLightState::setSpotCutoff(const F32& cutoff) +{ + if (mSpotCutoff != cutoff) + { + mSpotCutoff = cutoff; + glLightf(GL_LIGHT0+mIndex, GL_SPOT_CUTOFF, cutoff); + } +} + +void LLLightState::setSpotDirection(const LLVector3& direction) +{ + //always set direction because modelview matrix may have changed + mSpotDirection = direction; + glLightfv(GL_LIGHT0+mIndex, GL_SPOT_DIRECTION, direction.mV); +} LLRender::LLRender() : mDirty(false), @@ -750,6 +898,11 @@ LLRender::LLRender() } mDummyTexUnit = new LLTexUnit(-1); + for (U32 i = 0; i < LL_NUM_LIGHT_UNITS; ++i) + { + mLightState.push_back(new LLLightState(i)); + } + for (U32 i = 0; i < 4; i++) { mCurrColorMask[i] = true; @@ -777,6 +930,12 @@ void LLRender::shutdown() mTexUnits.clear(); delete mDummyTexUnit; mDummyTexUnit = NULL; + + for (U32 i = 0; i < mLightState.size(); ++i) + { + delete mLightState[i]; + } + mLightState.clear(); } void LLRender::refreshState(void) @@ -941,6 +1100,7 @@ void LLRender::blendFunc(eBlendFactor color_sfactor, eBlendFactor color_dfactor, sGLBlendFactor[alpha_sfactor], sGLBlendFactor[alpha_dfactor]); } } + LLTexUnit* LLRender::getTexUnit(U32 index) { if ((index >= 0) && (index < mTexUnits.size())) @@ -954,6 +1114,16 @@ LLTexUnit* LLRender::getTexUnit(U32 index) } } +LLLightState* LLRender::getLight(U32 index) +{ + if (index < mLightState.size()) + { + return mLightState[index]; + } + + return NULL; +} + bool LLRender::verifyTexUnitActive(U32 unitToVerify) { if (mCurrTextureUnitIndex == unitToVerify) @@ -1058,6 +1228,34 @@ void LLRender::flush() } #endif + + if (gDebugGL) + { + if (mMode == LLRender::QUADS) + { + if (mCount%4 != 0) + { + llerrs << "Incomplete quad rendered." << llendl; + } + } + + if (mMode == LLRender::TRIANGLES) + { + if (mCount%3 != 0) + { + llerrs << "Incomplete triangle rendered." << llendl; + } + } + + if (mMode == LLRender::LINES) + { + if (mCount%2 != 0) + { + llerrs << "Incomplete line rendered." << llendl; + } + } + } + mBuffer->setBuffer(immediate_mask); mBuffer->drawArrays(mMode, 0, mCount); diff --git a/indra/llrender/llrender.h b/indra/llrender/llrender.h index ab0935bbe..6dd4db9e5 100644 --- a/indra/llrender/llrender.h +++ b/indra/llrender/llrender.h @@ -43,6 +43,7 @@ #include "v2math.h" #include "v3math.h" #include "v4coloru.h" +#include "v4math.h" #include "llstrider.h" #include "llmemory.h" #include "llglheaders.h" @@ -218,6 +219,40 @@ protected: void setTextureCombiner(eTextureBlendOp op, eTextureBlendSrc src1, eTextureBlendSrc src2, bool isAlpha = false); }; +class LLLightState +{ +public: + LLLightState(S32 index); + + void enable(); + void disable(); + void setDiffuse(const LLColor4& diffuse); + void setAmbient(const LLColor4& ambient); + void setSpecular(const LLColor4& specular); + void setPosition(const LLVector4& position); + void setConstantAttenuation(const F32& atten); + void setLinearAttenuation(const F32& atten); + void setQuadraticAttenuation(const F32& atten); + void setSpotExponent(const F32& exponent); + void setSpotCutoff(const F32& cutoff); + void setSpotDirection(const LLVector3& direction); + +protected: + S32 mIndex; + bool mEnabled; + LLColor4 mDiffuse; + LLColor4 mAmbient; + LLColor4 mSpecular; + LLVector4 mPosition; + LLVector3 mSpotDirection; + + F32 mConstantAtten; + F32 mLinearAtten; + F32 mQuadraticAtten; + + F32 mSpotExponent; + F32 mSpotCutoff; +}; class LLRender { friend class LLTexUnit; @@ -324,6 +359,8 @@ public: void blendFunc(eBlendFactor color_sfactor, eBlendFactor color_dfactor, eBlendFactor alpha_sfactor, eBlendFactor alpha_dfactor); + LLLightState* getLight(U32 index); + LLTexUnit* getTexUnit(U32 index); U32 getCurrentTexUnitIndex(void) const { return mCurrTextureUnitIndex; } @@ -358,6 +395,7 @@ private: LLStrider mColorsp; std::vector mTexUnits; LLTexUnit* mDummyTexUnit; + std::vector mLightState; eBlendFactor mCurrBlendColorSFactor; eBlendFactor mCurrBlendColorDFactor; @@ -369,6 +407,7 @@ private: extern F64 gGLModelView[16]; extern F64 gGLLastModelView[16]; +extern F64 gGLLastProjection[16]; extern F64 gGLProjection[16]; extern S32 gGLViewport[4]; diff --git a/indra/llrender/llrendersphere.cpp b/indra/llrender/llrendersphere.cpp index e22b75392..212963f27 100644 --- a/indra/llrender/llrendersphere.cpp +++ b/indra/llrender/llrendersphere.cpp @@ -68,45 +68,6 @@ void drawSolidSphere(GLdouble radius, GLint slices, GLint stacks) } -// lat = 0 is Z-axis -// lon = 0, lat = 90 at X-axis -void lat2xyz(LLVector3 * result, F32 lat, F32 lon) -{ - // Convert a latitude and longitude to x,y,z on a normal sphere and return it in result - F32 r; - result->mV[VX] = (F32) (cos(lon * DEG_TO_RAD) * sin(lat * DEG_TO_RAD)); - result->mV[VY] = (F32) (sin(lon * DEG_TO_RAD) * sin(lat * DEG_TO_RAD)); - r = (F32) pow(result->mV[VX] * result->mV[VX] + result->mV[VY] * result->mV[VY], 0.5f); - if (r == 1.0f) - { - result->mV[VZ] = 0.0f; - } - else - { - result->mV[VZ] = (F32) pow(1 - r*r, 0.5f); - if (lat > 90.01) - { - result->mV[VZ] *= -1.0; - } - } -} - -void lat2xyz_rad(LLVector3 * result, F32 lat, F32 lon) -{ - // Convert a latitude and longitude to x,y,z on a normal sphere and return it in result - F32 r; - result->mV[VX] = (F32) (cos(lon) * sin(lat)); - result->mV[VY] = (F32) (sin(lon) * sin(lat)); - r = (F32) pow(result->mV[VX] * result->mV[VX] + result->mV[VY] * result->mV[VY], 0.5f); - if (r == 1.0f) - result->mV[VZ] = 0.0f; - else - { - result->mV[VZ] = (F32) pow(1 - r*r, 0.5f); - if (lat > F_PI_BY_TWO) result->mV[VZ] *= -1.0; - } -} - // A couple thoughts on sphere drawing: // 1) You need more slices than stacks, but little less than 2:1 // 2) At low LOD, setting stacks to an odd number avoids a "band" around the equator, making things look smoother @@ -181,3 +142,50 @@ void LLRenderSphere::render() { glCallList(mDList[0]); } + +inline LLVector3 polar_to_cart(F32 latitude, F32 longitude) +{ + return LLVector3(sin(F_TWO_PI * latitude) * cos(F_TWO_PI * longitude), + sin(F_TWO_PI * latitude) * sin(F_TWO_PI * longitude), + cos(F_TWO_PI * latitude)); +} + + +void LLRenderSphere::renderGGL() +{ + S32 const LATITUDE_SLICES = 20; + S32 const LONGITUDE_SLICES = 30; + + if (mSpherePoints.empty()) + { + mSpherePoints.resize(LATITUDE_SLICES + 1); + for (S32 lat_i = 0; lat_i < LATITUDE_SLICES + 1; lat_i++) + { + mSpherePoints[lat_i].resize(LONGITUDE_SLICES + 1); + for (S32 lon_i = 0; lon_i < LONGITUDE_SLICES + 1; lon_i++) + { + F32 lat = (F32)lat_i / LATITUDE_SLICES; + F32 lon = (F32)lon_i / LONGITUDE_SLICES; + + mSpherePoints[lat_i][lon_i] = polar_to_cart(lat, lon); + } + } + } + + gGL.begin(LLRender::TRIANGLES); + + for (S32 lat_i = 0; lat_i < LATITUDE_SLICES; lat_i++) + { + for (S32 lon_i = 0; lon_i < LONGITUDE_SLICES; lon_i++) + { + gGL.vertex3fv(mSpherePoints[lat_i][lon_i].mV); + gGL.vertex3fv(mSpherePoints[lat_i][lon_i+1].mV); + gGL.vertex3fv(mSpherePoints[lat_i+1][lon_i].mV); + + gGL.vertex3fv(mSpherePoints[lat_i+1][lon_i].mV); + gGL.vertex3fv(mSpherePoints[lat_i][lon_i+1].mV); + gGL.vertex3fv(mSpherePoints[lat_i+1][lon_i+1].mV); + } + } + gGL.end(); +} diff --git a/indra/llrender/llrendersphere.h b/indra/llrender/llrendersphere.h index 617ee3e12..ebc71b614 100644 --- a/indra/llrender/llrendersphere.h +++ b/indra/llrender/llrendersphere.h @@ -52,6 +52,10 @@ public: void cleanupGL(); void render(F32 pixel_area); // of a box of size 1.0 at that position void render(); // render at highest LOD + void renderGGL(); // render using LLRender + +private: + std::vector< std::vector > mSpherePoints; }; extern LLRenderSphere gSphere; diff --git a/indra/llrender/llrendertarget.cpp b/indra/llrender/llrendertarget.cpp index 106b93a21..3eefbe571 100644 --- a/indra/llrender/llrendertarget.cpp +++ b/indra/llrender/llrendertarget.cpp @@ -36,6 +36,9 @@ #include "llrender.h" #include "llgl.h" +LLRenderTarget* LLRenderTarget::sBoundTarget = NULL; + + void check_framebuffer_status() { @@ -46,16 +49,14 @@ void check_framebuffer_status() { case GL_FRAMEBUFFER_COMPLETE_EXT: break; - case GL_FRAMEBUFFER_UNSUPPORTED_EXT: - llerrs << "WTF?" << llendl; - break; default: - llerrs << "WTF?" << llendl; + llerrs <<"check_framebuffer_status failed" << llendl; + break; } } } -BOOL LLRenderTarget::sUseFBO = FALSE; +bool LLRenderTarget::sUseFBO = false; LLRenderTarget::LLRenderTarget() : mResX(0), @@ -64,8 +65,8 @@ LLRenderTarget::LLRenderTarget() : mFBO(0), mDepth(0), mStencil(0), - mUseDepth(FALSE), - mRenderDepth(FALSE), + mUseDepth(false), + mRenderDepth(false), mUsage(LLTexUnit::TT_TEXTURE), mSamples(0), mSampleBuffer(NULL) @@ -83,7 +84,7 @@ void LLRenderTarget::setSampleBuffer(LLMultisampleBuffer* buffer) mSampleBuffer = buffer; } -void LLRenderTarget::allocate(U32 resx, U32 resy, U32 color_fmt, BOOL depth, BOOL stencil, LLTexUnit::eTextureType usage, BOOL use_fbo) +void LLRenderTarget::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil, LLTexUnit::eTextureType usage, bool use_fbo) { stop_glerror(); mResX = resx; @@ -214,6 +215,16 @@ void LLRenderTarget::shareDepthBuffer(LLRenderTarget& target) llerrs << "Cannot share depth buffer between non FBO render targets." << llendl; } + if (target.mDepth) + { + llerrs << "Attempting to override existing depth buffer. Detach existing buffer first." << llendl; + } + + if (target.mUseDepth) + { + llerrs << "Attempting to override existing shared depth buffer. Detach existing buffer first." << llendl; + } + if (mDepth) { stop_glerror(); @@ -226,16 +237,12 @@ void LLRenderTarget::shareDepthBuffer(LLRenderTarget& target) stop_glerror(); glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, mDepth); stop_glerror(); + target.mStencil = true; } else { glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, LLTexUnit::getInternalType(mUsage), mDepth, 0); stop_glerror(); - if (mStencil) - { - glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, LLTexUnit::getInternalType(mUsage), mDepth, 0); - stop_glerror(); - } } glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); @@ -245,18 +252,6 @@ void LLRenderTarget::shareDepthBuffer(LLRenderTarget& target) void LLRenderTarget::release() { - if (mFBO) - { - glDeleteFramebuffersEXT(1, (GLuint *) &mFBO); - mFBO = 0; - } - - if (mTex.size() > 0) - { - LLImageGL::deleteTextures(mTex.size(), &mTex[0]); - mTex.clear(); - } - if (mDepth) { if (mStencil) @@ -271,8 +266,36 @@ void LLRenderTarget::release() } mDepth = 0; } + else if (mUseDepth && mFBO) + { //detach shared depth buffer + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFBO); + if (mStencil) + { //attached as a renderbuffer + glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, 0); + glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, 0); + mStencil = false; + } + else + { //attached as a texture + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, LLTexUnit::getInternalType(mUsage), 0, 0); + } + mUseDepth = false; + } + + if (mFBO) + { + glDeleteFramebuffersEXT(1, (GLuint *) &mFBO); + mFBO = 0; + } + + if (mTex.size() > 0) + { + LLImageGL::deleteTextures(mTex.size(), &mTex[0]); + mTex.clear(); + } mSampleBuffer = NULL; + sBoundTarget = NULL; } void LLRenderTarget::bindTarget() @@ -311,6 +334,7 @@ void LLRenderTarget::bindTarget() } glViewport(0, 0, mResX, mResY); + sBoundTarget = this; } // static @@ -320,6 +344,7 @@ void LLRenderTarget::unbindTarget() { glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); } + sBoundTarget = NULL; } void LLRenderTarget::clear(U32 mask_in) @@ -351,19 +376,19 @@ U32 LLRenderTarget::getTexture(U32 attachment) const { llerrs << "Invalid attachment index." << llendl; } + if (mTex.empty()) + { + return 0; + } return mTex[attachment]; } void LLRenderTarget::bindTexture(U32 index, S32 channel) { - if (index > mTex.size()-1) - { - llerrs << "Invalid attachment index." << llendl; - } - gGL.getTexUnit(channel)->bindManual(mUsage, mTex[index]); + gGL.getTexUnit(channel)->bindManual(mUsage, getTexture(index)); } -void LLRenderTarget::flush(BOOL fetch_depth) +void LLRenderTarget::flush(bool fetch_depth) { gGL.flush(); if (!mFBO) @@ -386,7 +411,11 @@ void LLRenderTarget::flush(BOOL fetch_depth) } else { + stop_glerror(); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + + stop_glerror(); if (mSampleBuffer) { @@ -439,6 +468,10 @@ void LLRenderTarget::flush(BOOL fetch_depth) void LLRenderTarget::copyContents(LLRenderTarget& source, S32 srcX0, S32 srcY0, S32 srcX1, S32 srcY1, S32 dstX0, S32 dstY0, S32 dstX1, S32 dstY1, U32 mask, U32 filter) { + GLboolean write_depth = mask & GL_DEPTH_BUFFER_BIT ? TRUE : FALSE; + + LLGLDepthTest depth(write_depth, write_depth); + gGL.flush(); if (!source.mFBO || !mFBO) { @@ -494,6 +527,10 @@ void LLRenderTarget::copyContentsToFramebuffer(LLRenderTarget& source, S32 srcX0 llerrs << "Cannot copy framebuffer contents for non FBO render targets." << llendl; } { + GLboolean write_depth = mask & GL_DEPTH_BUFFER_BIT ? TRUE : FALSE; + + LLGLDepthTest depth(write_depth, write_depth); + glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, source.mSampleBuffer ? source.mSampleBuffer->mFBO : source.mFBO); stop_glerror(); glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, 0); @@ -513,9 +550,9 @@ void LLRenderTarget::copyContentsToFramebuffer(LLRenderTarget& source, S32 srcX0 } } -BOOL LLRenderTarget::isComplete() const +bool LLRenderTarget::isComplete() const { - return (!mTex.empty() || mDepth) ? TRUE : FALSE; + return (!mTex.empty() || mDepth) ? true : false; } void LLRenderTarget::getViewport(S32* viewport) @@ -536,10 +573,10 @@ LLMultisampleBuffer::LLMultisampleBuffer() LLMultisampleBuffer::~LLMultisampleBuffer() { - releaseSampleBuffer(); + release(); } -void LLMultisampleBuffer::releaseSampleBuffer() +void LLMultisampleBuffer::release() { if (mFBO) { @@ -586,14 +623,15 @@ void LLMultisampleBuffer::bindTarget(LLRenderTarget* ref) glViewport(0, 0, mResX, mResY); + sBoundTarget = this; } -void LLMultisampleBuffer::allocate(U32 resx, U32 resy, U32 color_fmt, BOOL depth, BOOL stencil, LLTexUnit::eTextureType usage, BOOL use_fbo ) +void LLMultisampleBuffer::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil, LLTexUnit::eTextureType usage, bool use_fbo ) { allocate(resx,resy,color_fmt,depth,stencil,usage,use_fbo,2); } -void LLMultisampleBuffer::allocate(U32 resx, U32 resy, U32 color_fmt, BOOL depth, BOOL stencil, LLTexUnit::eTextureType usage, BOOL use_fbo, U32 samples ) +void LLMultisampleBuffer::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil, LLTexUnit::eTextureType usage, bool use_fbo, U32 samples ) { stop_glerror(); mResX = resx; @@ -603,7 +641,7 @@ void LLMultisampleBuffer::allocate(U32 resx, U32 resy, U32 color_fmt, BOOL depth mUseDepth = depth; mStencil = stencil; - releaseSampleBuffer(); + release(); if (!gGLManager.mHasFramebufferMultisample) { @@ -640,11 +678,9 @@ void LLMultisampleBuffer::allocate(U32 resx, U32 resy, U32 color_fmt, BOOL depth { glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, mDepth); } - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); } stop_glerror(); - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); stop_glerror(); } @@ -683,11 +719,9 @@ void LLMultisampleBuffer::addColorAttachment(U32 color_fmt) { case GL_FRAMEBUFFER_COMPLETE_EXT: break; - case GL_FRAMEBUFFER_UNSUPPORTED_EXT: - llerrs << "WTF?" << llendl; - break; default: - llerrs << "WTF?" << llendl; + llerrs << "WTF? " << std::hex << status << llendl; + break; } glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); diff --git a/indra/llrender/llrendertarget.h b/indra/llrender/llrendertarget.h index 9ad4ec3a4..fe5cf9072 100644 --- a/indra/llrender/llrendertarget.h +++ b/indra/llrender/llrendertarget.h @@ -69,7 +69,7 @@ class LLRenderTarget { public: //whether or not to use FBO implementation - static BOOL sUseFBO; + static bool sUseFBO; LLRenderTarget(); virtual ~LLRenderTarget(); @@ -77,7 +77,7 @@ public: //allocate resources for rendering //must be called before use //multiple calls will release previously allocated resources - void allocate(U32 resx, U32 resy, U32 color_fmt, BOOL depth, BOOL stencil, LLTexUnit::eTextureType usage = LLTexUnit::TT_TEXTURE, BOOL use_fbo = FALSE); + void allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil, LLTexUnit::eTextureType usage = LLTexUnit::TT_TEXTURE, bool use_fbo = FALSE); //provide this render target with a multisample resource. void setSampleBuffer(LLMultisampleBuffer* buffer); @@ -94,7 +94,7 @@ public: //free any allocated resources //safe to call redundantly - void release(); + virtual void release(); //bind target for rendering //applies appropriate viewport @@ -121,7 +121,7 @@ public: U32 getTexture(U32 attachment = 0) const; U32 getDepth(void) const { return mDepth; } - BOOL hasStencil() const { return mStencil; } + bool hasStencil() const { return mStencil; } void bindTexture(U32 index, S32 channel); @@ -131,7 +131,7 @@ public: // call bindTarget once, do all your rendering, call flush once // if fetch_depth is TRUE, every effort will be made to copy the depth buffer into // the current depth texture. A depth texture will be allocated if needed. - void flush(BOOL fetch_depth = FALSE); + void flush(bool fetch_depth = FALSE); void copyContents(LLRenderTarget& source, S32 srcX0, S32 srcY0, S32 srcX1, S32 srcY1, S32 dstX0, S32 dstY0, S32 dstX1, S32 dstY1, U32 mask, U32 filter); @@ -142,7 +142,9 @@ public: //Returns TRUE if target is ready to be rendered into. //That is, if the target has been allocated with at least //one renderable attachment (i.e. color buffer, depth buffer). - BOOL isComplete() const; + bool isComplete() const; + + static LLRenderTarget* getCurrentBoundTarget() { return sBoundTarget; } protected: friend class LLMultisampleBuffer; @@ -151,12 +153,14 @@ protected: std::vector mTex; U32 mFBO; U32 mDepth; - BOOL mStencil; - BOOL mUseDepth; - BOOL mRenderDepth; + bool mStencil; + bool mUseDepth; + bool mRenderDepth; LLTexUnit::eTextureType mUsage; U32 mSamples; LLMultisampleBuffer* mSampleBuffer; + + static LLRenderTarget* sBoundTarget; }; @@ -166,12 +170,12 @@ public: LLMultisampleBuffer(); virtual ~LLMultisampleBuffer(); - void releaseSampleBuffer(); + virtual void release(); virtual void bindTarget(); void bindTarget(LLRenderTarget* ref); - virtual void allocate(U32 resx, U32 resy, U32 color_fmt, BOOL depth, BOOL stencil, LLTexUnit::eTextureType usage, BOOL use_fbo); - void allocate(U32 resx, U32 resy, U32 color_fmt, BOOL depth, BOOL stencil, LLTexUnit::eTextureType usage, BOOL use_fbo, U32 samples); + virtual void allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil, LLTexUnit::eTextureType usage, bool use_fbo); + void allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil, LLTexUnit::eTextureType usage, bool use_fbo, U32 samples); virtual void addColorAttachment(U32 color_fmt); virtual void allocateDepth(); }; diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp index 810d9fa2c..2dc3dae91 100644 --- a/indra/llrender/llshadermgr.cpp +++ b/indra/llrender/llshadermgr.cpp @@ -226,7 +226,14 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader) else if (features->isFullbright) { - if (features->hasWaterFog) + if (features->isShiny && features->hasWaterFog) + { + if (!shader->attachObject("lighting/lightFullbrightShinyWaterF.glsl")) + { + return FALSE; + } + } + else if (features->hasWaterFog) { if (!shader->attachObject("lighting/lightFullbrightWaterF.glsl")) { @@ -306,7 +313,7 @@ void LLShaderMgr::dumpObjectLog(GLhandleARB ret, BOOL warns) } else { - LL_DEBUGS("ShaderLoading") << log << LL_ENDL; + LL_INFOS("ShaderLoading") << log << LL_ENDL; } } } diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index 8108eeee8..d697b95dd 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -31,13 +31,13 @@ */ #include "linden_common.h" +#include "llmemory.h" #include - +#include "llsys.h" #include "llvertexbuffer.h" // #include "llrender.h" #include "llglheaders.h" -#include "llmemory.h" #include "llmemtype.h" #include "llrender.h" @@ -67,6 +67,8 @@ U32 LLVertexBuffer::sAllocatedBytes = 0; BOOL LLVertexBuffer::sMapped = FALSE; BOOL LLVertexBuffer::sUseStreamDraw = TRUE; BOOL LLVertexBuffer::sOmitBlank = FALSE; +BOOL LLVertexBuffer::sPreferStreamDraw = FALSE; +S32 LLVertexBuffer::sWeight4Loc = -1; std::vector LLVertexBuffer::sDeleteList; @@ -88,15 +90,16 @@ void LLVBOPool::releaseName(GLuint name) S32 LLVertexBuffer::sTypeOffsets[LLVertexBuffer::TYPE_MAX] = { - sizeof(LLVector3), // TYPE_VERTEX, - sizeof(LLVector3), // TYPE_NORMAL, + sizeof(LLVector4), // TYPE_VERTEX, + sizeof(LLVector4), // TYPE_NORMAL, sizeof(LLVector2), // TYPE_TEXCOORD0, sizeof(LLVector2), // TYPE_TEXCOORD1, sizeof(LLVector2), // TYPE_TEXCOORD2, sizeof(LLVector2), // TYPE_TEXCOORD3, sizeof(LLColor4U), // TYPE_COLOR, - sizeof(LLVector3), // TYPE_BINORMAL, + sizeof(LLVector4), // TYPE_BINORMAL, sizeof(F32), // TYPE_WEIGHT, + sizeof(LLVector4), // TYPE_WEIGHT4, sizeof(LLVector4), // TYPE_CLOTHWEIGHT, }; @@ -138,6 +141,7 @@ void LLVertexBuffer::setupClientArrays(U32 data_mask) GL_COLOR_ARRAY, }; + BOOL error = FALSE; for (U32 i = 0; i < 4; ++i) { if (sLastMask & mask[i]) @@ -150,23 +154,44 @@ void LLVertexBuffer::setupClientArrays(U32 data_mask) { //needs to be enabled, make sure it was (DEBUG TEMPORARY) if (i > 0 && !glIsEnabled(array[i])) { - llerrs << "Bad client state! " << array[i] << " disabled." << llendl; + if (gDebugSession) + { + error = TRUE; + gFailLog << "Bad client state! " << array[i] << " disabled." << std::endl; + } + else + { + llerrs << "Bad client state! " << array[i] << " disabled." << llendl; + } } } } else { //was disabled - if (data_mask & mask[i]) + if (data_mask & mask[i] && i > 0) { //needs to be enabled glEnableClientState(array[i]); } - else if (gDebugGL && glIsEnabled(array[i])) + else if (gDebugGL && i > 0 && glIsEnabled(array[i])) { //needs to be disabled, make sure it was (DEBUG TEMPORARY) - llerrs << "Bad client state! " << array[i] << " enabled." << llendl; + if (gDebugSession) + { + error = TRUE; + gFailLog << "Bad client state! " << array[i] << " enabled." << std::endl; + } + else + { + llerrs << "Bad client state! " << array[i] << " enabled." << llendl; + } } } } + if (error) + { + ll_fail("LLVertexBuffer::setupClientArrays failed"); + } + U32 map_tc[] = { MAP_TEXCOORD1, @@ -209,23 +234,81 @@ void LLVertexBuffer::setupClientArrays(U32 data_mask) glClientActiveTextureARB(GL_TEXTURE0_ARB); } + if (sLastMask & MAP_WEIGHT4) + { + if (sWeight4Loc < 0) + { + llerrs << "Weighting disabled but vertex buffer still bound!" << llendl; + } + + if (!(data_mask & MAP_WEIGHT4)) + { //disable 4-component skin weight + glDisableVertexAttribArrayARB(sWeight4Loc); + } + } + else if (data_mask & MAP_WEIGHT4) + { + if (sWeight4Loc >= 0) + { //enable 4-component skin weight + glEnableVertexAttribArrayARB(sWeight4Loc); + } + } + + sLastMask = data_mask; } } +//static +void LLVertexBuffer::drawArrays(U32 mode, const std::vector& pos, const std::vector& norm) +{ + U32 count = pos.size(); + llassert(norm.size() >= pos.size()); + + unbind(); + + setupClientArrays(MAP_VERTEX | MAP_NORMAL); + + glVertexPointer(3, GL_FLOAT, 0, pos[0].mV); + glNormalPointer(GL_FLOAT, 0, norm[0].mV); + + glDrawArrays(sGLMode[mode], 0, count); +} + +void LLVertexBuffer::validateRange(U32 start, U32 end, U32 count, U32 indices_offset) const +{ + if (start >= (U32) mRequestedNumVerts || + end >= (U32) mRequestedNumVerts) + { + llerrs << "Bad vertex buffer draw range: [" << start << ", " << end << "] vs " << mRequestedNumVerts << llendl; + } + + llassert(mRequestedNumIndices >= 0); + + if (indices_offset >= (U32) mRequestedNumIndices || + indices_offset + count > (U32) mRequestedNumIndices) + { + llerrs << "Bad index buffer draw range: [" << indices_offset << ", " << indices_offset+count << "]" << llendl; + } + + if (gDebugGL && !useVBOs()) + { + U16* idx = ((U16*) getIndicesPointer())+indices_offset; + for (U32 i = 0; i < count; ++i) + { + if (idx[i] < start || idx[i] > end) + { + llerrs << "Index out of range: " << idx[i] << " not in [" << start << ", " << end << "]" << llendl; + } + } + } +} + void LLVertexBuffer::drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indices_offset) const { - if (start >= (U32) mRequestedNumVerts || - end >= (U32) mRequestedNumVerts) - { - llerrs << "Bad vertex buffer draw range: [" << start << ", " << end << "]" << llendl; - } + validateRange(start, end, count, indices_offset); - if (indices_offset >= (U32) mRequestedNumIndices || - indices_offset + count > (U32) mRequestedNumIndices) - { - llerrs << "Bad index buffer draw range: [" << indices_offset << ", " << indices_offset+count << "]" << llendl; - } + llassert(mRequestedNumVerts >= 0); if (mGLIndices != sGLRenderIndices) { @@ -243,16 +326,19 @@ void LLVertexBuffer::drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indi return; } + U16* idx = ((U16*) getIndicesPointer())+indices_offset; + stop_glerror(); glDrawRangeElements(sGLMode[mode], start, end, count, GL_UNSIGNED_SHORT, - ((U16*) getIndicesPointer()) + indices_offset); + idx); stop_glerror(); } void LLVertexBuffer::draw(U32 mode, U32 count, U32 indices_offset) const { + llassert(mRequestedNumIndices >= 0); if (indices_offset >= (U32) mRequestedNumIndices || - indices_offset + count > (U32) mRequestedNumIndices) + indices_offset + count > (U32) mRequestedNumIndices) { llerrs << "Bad index buffer draw range: [" << indices_offset << ", " << indices_offset+count << "]" << llendl; } @@ -281,6 +367,7 @@ void LLVertexBuffer::draw(U32 mode, U32 count, U32 indices_offset) const void LLVertexBuffer::drawArrays(U32 mode, U32 first, U32 count) const { + llassert(mRequestedNumVerts >= 0); if (first >= (U32) mRequestedNumVerts || first + count > (U32) mRequestedNumVerts) { @@ -317,12 +404,8 @@ void LLVertexBuffer::initClass(bool use_vbo, bool no_vbo_mapping) { llinfos << "VBO is disabled." << llendl ; } - + sDisableVBOMapping = sEnableVBOs && no_vbo_mapping ; - LLGLNamePool::registerPool(&sDynamicVBOPool); - LLGLNamePool::registerPool(&sDynamicIBOPool); - LLGLNamePool::registerPool(&sStreamVBOPool); - LLGLNamePool::registerPool(&sStreamIBOPool); } //static @@ -395,6 +478,11 @@ LLVertexBuffer::LLVertexBuffer(U32 typemask, S32 usage) : { mUsage = 0; } + + if (mUsage == GL_DYNAMIC_DRAW_ARB && sPreferStreamDraw) + { + mUsage = GL_STREAM_DRAW_ARB; + } S32 stride = calcStride(typemask, mOffsets); @@ -431,6 +519,8 @@ LLVertexBuffer::~LLVertexBuffer() destroyGLBuffer(); destroyGLIndices(); sCount--; + + llassert_always(!mMappedData && !mMappedIndexData) ; }; //---------------------------------------------------------------------------- @@ -629,6 +719,8 @@ void LLVertexBuffer::updateNumVerts(S32 nverts) { LLMemType mt(LLMemType::MTYPE_VERTEX_DATA); + llassert(nverts >= 0); + if (nverts >= 65535) { llwarns << "Vertex buffer overflow!" << llendl; @@ -657,6 +749,9 @@ void LLVertexBuffer::updateNumVerts(S32 nverts) void LLVertexBuffer::updateNumIndices(S32 nindices) { LLMemType mt(LLMemType::MTYPE_VERTEX_DATA); + + llassert(nindices >= 0); + mRequestedNumIndices = nindices; if (!mDynamicSize) { @@ -679,6 +774,11 @@ void LLVertexBuffer::allocateBuffer(S32 nverts, S32 nindices, bool create) { LLMemType mt(LLMemType::MTYPE_VERTEX_DATA); + if (nverts < 0 || nindices < 0 || + nverts > 65536) + { + llerrs << "Bad vertex buffer allocation: " << nverts << " : " << nindices << llendl; + } updateNumVerts(nverts); updateNumIndices(nindices); @@ -697,6 +797,9 @@ void LLVertexBuffer::allocateBuffer(S32 nverts, S32 nindices, bool create) void LLVertexBuffer::resizeBuffer(S32 newnverts, S32 newnindices) { + llassert(newnverts >= 0); + llassert(newnindices >= 0); + mRequestedNumVerts = newnverts; mRequestedNumIndices = newnindices; @@ -881,8 +984,16 @@ volatile U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 access) if (!mMappedData) { + log_glerror(); + + //check the availability of memory + U32 avail_phy_mem, avail_vir_mem; + LLMemoryInfo::getAvailableMemoryKB(avail_phy_mem, avail_vir_mem) ; + llinfos << "Available physical mwmory(KB): " << avail_phy_mem << llendl ; + llinfos << "Available virtual memory(KB): " << avail_vir_mem << llendl; + if(!sDisableVBOMapping) - { + { //-------------------- //print out more debug info before crash llinfos << "vertex buffer size: (num verts : num indices) = " << getNumVerts() << " : " << getNumIndices() << llendl ; @@ -939,12 +1050,13 @@ volatile U8* LLVertexBuffer::mapIndexBuffer(S32 access) else { mMappedIndexData = (U8*) glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB); + stop_glerror(); } - stop_glerror(); } if (!mMappedIndexData) { + log_glerror(); if(!sDisableVBOMapping) { @@ -1030,7 +1142,6 @@ void LLVertexBuffer::unmapBuffer(S32 type) //throw out client data (we won't be using it again) mEmpty = TRUE; mFinal = TRUE; - if(sDisableVBOMapping) { freeClientBuffer() ; @@ -1129,6 +1240,12 @@ bool LLVertexBuffer::getWeightStrider(LLStrider& strider, S32 index) { return VertexBufferStrider::get(*this, strider, index); } + +bool LLVertexBuffer::getWeight4Strider(LLStrider& strider, S32 index) +{ + return VertexBufferStrider::get(*this, strider, index); +} + bool LLVertexBuffer::getClothWeightStrider(LLStrider& strider, S32 index) { return VertexBufferStrider::get(*this, strider, index); @@ -1197,7 +1314,15 @@ void LLVertexBuffer::setBuffer(U32 data_mask, S32 type) glGetIntegerv(GL_ARRAY_BUFFER_BINDING_ARB, &buff); if ((GLuint)buff != mGLBuffer) { - llerrs << "Invalid GL vertex buffer bound: " << buff << llendl; + if (gDebugSession) + { + error = TRUE; + gFailLog << "Invalid GL vertex buffer bound: " << buff << std::endl; + } + else + { + llerrs << "Invalid GL vertex buffer bound: " << buff << llendl; + } } if (mGLIndices) @@ -1205,7 +1330,15 @@ void LLVertexBuffer::setBuffer(U32 data_mask, S32 type) glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB, &buff); if ((GLuint)buff != mGLIndices) { - llerrs << "Invalid GL index buffer bound: " << buff << llendl; + if (gDebugSession) + { + error = TRUE; + gFailLog << "Invalid GL index buffer bound: " << buff << std::endl; + } + else + { + llerrs << "Invalid GL index buffer bound: " << buff << llendl; + } } } } @@ -1218,7 +1351,15 @@ void LLVertexBuffer::setBuffer(U32 data_mask, S32 type) glGetIntegerv(GL_ARRAY_BUFFER_BINDING_ARB, &buff); if ((GLuint)buff != mGLBuffer) { - llerrs << "Invalid GL vertex buffer bound: " << buff << llendl; + if (gDebugSession) + { + error = TRUE; + gFailLog << "Invalid GL vertex buffer bound: " << std::endl; + } + else + { + llerrs << "Invalid GL vertex buffer bound: " << buff << llendl; + } } if (mGLIndices != 0) @@ -1226,7 +1367,15 @@ void LLVertexBuffer::setBuffer(U32 data_mask, S32 type) glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB, &buff); if ((GLuint)buff != mGLIndices) { - llerrs << "Invalid GL index buffer bound: " << buff << llendl; + if (gDebugSession) + { + error = TRUE; + gFailLog << "Invalid GL index buffer bound: "<< std::endl; + } + else + { + llerrs << "Invalid GL index buffer bound: " << buff << llendl; + } } } } @@ -1249,13 +1398,21 @@ void LLVertexBuffer::setBuffer(U32 data_mask, S32 type) if (data_mask != 0) { - llerrs << "Buffer set for rendering before being filled after resize." << llendl; + if (gDebugSession) + { + error = TRUE; + gFailLog << "Buffer set for rendering before being filled after resize." << std::endl; + } + else + { + llerrs << "Buffer set for rendering before being filled after resize." << llendl; + } } } if (error) { - llerrs << "LLVertexBuffer::mapBuffer failed" << llendl; + ll_fail("LLVertexBuffer::mapBuffer failed"); } unmapBuffer(type); } @@ -1316,7 +1473,7 @@ void LLVertexBuffer::setupVertexBuffer(U32 data_mask) const { llerrs << "LLVertexBuffer::setupVertexBuffer missing required components for supplied data mask. Missing: "; - static const char* mask_names[] = {"VERTEX","NORMAL","TEXCOORD0","TEXCOORD1","TEXCOORD2","TEXCOORD3","COLOR","BINORMAL","WEIGHT","CLOTH_WEIGHT"}; + static const char* mask_names[] = {"VERTEX","NORMAL","TEXCOORD0","TEXCOORD1","TEXCOORD2","TEXCOORD3","COLOR","BINORMAL","WEIGHT","WEIGHT4","CLOTH_WEIGHT"}; for(int i = 0; i < 32; ++i) { if((data_mask & (1<& pos, const std::vector& norm); static void clientCopy(F64 max_time = 0.005); //copy data from client to GL static void unbind(); //unbind any bound vertex buffer @@ -101,6 +116,7 @@ public: // These use VertexAttribPointer and should possibly be made generic TYPE_BINORMAL, TYPE_WEIGHT, + TYPE_WEIGHT4, TYPE_CLOTHWEIGHT, TYPE_MAX, TYPE_INDEX, @@ -116,6 +132,7 @@ public: // These use VertexAttribPointer and should possibly be made generic MAP_BINORMAL = (1<& strider, S32 index=0); bool getColorStrider(LLStrider& strider, S32 index=0); bool getWeightStrider(LLStrider& strider, S32 index=0); + bool getWeight4Strider(LLStrider& strider, S32 index=0); bool getClothWeightStrider(LLStrider& strider, S32 index=0); BOOL isEmpty() const { return mEmpty; } @@ -199,6 +217,11 @@ public: void drawArrays(U32 mode, U32 offset, U32 count) const; void drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indices_offset) const; + //for debugging, validate data in given range is valid + void validateRange(U32 start, U32 end, U32 count, U32 offset) const; + + + protected: S32 mNumVerts; // Number of vertices allocated S32 mNumIndices; // Number of indices allocated @@ -246,12 +269,12 @@ public: static BOOL sDisableVBOMapping; //disable glMapBufferARB static BOOL sEnableVBOs; - static BOOL sVBOActive; - static BOOL sIBOActive; static S32 sTypeOffsets[TYPE_MAX]; static U32 sGLMode[LLRender::NUM_MODES]; static U32 sGLRenderBuffer; static U32 sGLRenderIndices; + static BOOL sVBOActive; + static BOOL sIBOActive; static U32 sLastMask; static U32 sAllocatedBytes; static U32 sBindCount; diff --git a/indra/llui/lldelayeduidelete.h b/indra/llui/lldelayeduidelete.h index 2f08ee8fa..043e6972e 100644 --- a/indra/llui/lldelayeduidelete.h +++ b/indra/llui/lldelayeduidelete.h @@ -1,7 +1,7 @@ // #ifndef LL_LLDELAYEDUIDELETE_H #define LL_LLDELAYEDUIDELETE_H -#include "lltimer.h" +#include "lleventtimer.h" #include "llview.h" class LLDeleteJob { diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index 2d72026a2..0ab07c5e4 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -1356,14 +1356,20 @@ LLFloater* LLFloater::getClosableFloaterFromFocus() // The focused floater may not be closable, // Find and close a parental floater that is closeable, if any. + LLFloater* previous_floater = NULL; // Guard against endless loop, because getParentFloater(x) can return x! for(LLFloater* floater_to_close = focused_floater; NULL != floater_to_close; floater_to_close = gFloaterView->getParentFloater(floater_to_close)) { + if(floater_to_close == previous_floater) + { + break; + } if(floater_to_close->isCloseable()) { return floater_to_close; } + previous_floater = floater_to_close; } return NULL; diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp index cfa10734e..807d7bf2a 100644 --- a/indra/llui/llmenugl.cpp +++ b/indra/llui/llmenugl.cpp @@ -2324,6 +2324,8 @@ void LLMenuGL::arrange( void ) (*item_iter)->buildDrawLabel(); } } + + cleanupSpilloverBranch(); } if (mKeepFixedSize) { @@ -2540,6 +2542,11 @@ BOOL LLMenuGL::append( LLMenuItemGL* item ) // Its added as a fix to a viewer 1.23 bug that has already been address by skinning work. BOOL LLMenuGL::appendNoArrange( LLMenuItemGL* item ) { + if (mSpilloverMenu) + { + return mSpilloverMenu->append(item); + } + mItems.push_back( item ); addChild( item ); return TRUE; @@ -4411,6 +4418,9 @@ BOOL LLMenuHolderGL::hideMenus() { return FALSE; } + + sItemActivationTimer.stop(); + BOOL menu_visible = hasVisibleMenu(); if (menu_visible) { diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp index 6bd4e4f22..13ca40cf9 100644 --- a/indra/llui/llnotifications.cpp +++ b/indra/llui/llnotifications.cpp @@ -908,8 +908,7 @@ mParent(parent) else { LLNotificationChannelPtr p = LLNotifications::instance().getChannel(parent); - LLStandardSignal::slot_type f = boost::bind(&LLNotificationChannelBase::updateItem, this, _1); - p->connectChanged(f); + p->connectChanged(boost::bind(&LLNotificationChannelBase::updateItem, this, _1)); } } @@ -1010,16 +1009,18 @@ bool LLNotifications::uniqueFilter(LLNotificationPtr pNotif) bool LLNotifications::uniqueHandler(const LLSD& payload) { + std::string cmd = payload["sigtype"]; + LLNotificationPtr pNotif = LLNotifications::instance().find(payload["id"].asUUID()); if (pNotif && pNotif->hasUniquenessConstraints()) { - if (payload["sigtype"].asString() == "add") + if (cmd == "add") { // not a duplicate according to uniqueness criteria, so we keep it // and store it for future uniqueness checks mUniqueNotifications.insert(std::make_pair(pNotif->getName(), pNotif)); } - else if (payload["sigtype"].asString() == "delete") + else if (cmd == "delete") { mUniqueNotifications.erase(pNotif->getName()); } @@ -1425,6 +1426,8 @@ LLNotificationPtr LLNotifications::add(const LLNotification::Params& p) void LLNotifications::add(const LLNotificationPtr pNotif) { + if (pNotif == NULL) return; + // first see if we already have it -- if so, that's a problem LLNotificationSet::iterator it=mItems.find(pNotif); if (it != mItems.end()) @@ -1437,6 +1440,8 @@ void LLNotifications::add(const LLNotificationPtr pNotif) void LLNotifications::cancel(LLNotificationPtr pNotif) { + if (pNotif == NULL || pNotif->isCancelled()) return; + LLNotificationSet::iterator it=mItems.find(pNotif); if (it == mItems.end()) { diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h index bb379121c..4b325f54d 100644 --- a/indra/llui/llnotifications.h +++ b/indra/llui/llnotifications.h @@ -96,6 +96,7 @@ // we want to minimize external dependencies, but this one is important #include "llsd.h" +#include "llinstancetracker.h" // and we need this to manage the notification callbacks #include "llfunctorregistry.h" diff --git a/indra/llui/llui.h b/indra/llui/llui.h index c7b7446a0..abc9a298b 100644 --- a/indra/llui/llui.h +++ b/indra/llui/llui.h @@ -602,62 +602,6 @@ public: virtual void cleanUp() = 0; }; -// This mix-in class adds support for tracking all instances of the specificed class parameter T -// The (optional) key associates a value of type KEY with a given instance of T, for quick lookup -// If KEY is not provided, then instances are stored in a simple list -template -class LLInstanceTracker : boost::noncopyable -{ -public: - typedef typename std::map::iterator instance_iter; - typedef typename std::map::const_iterator instance_const_iter; - - static T* getInstance(KEY k) { instance_iter found = sInstances.find(k); return (found == sInstances.end()) ? NULL : found->second; } - - static instance_iter beginInstances() { return sInstances.begin(); } - static instance_iter endInstances() { return sInstances.end(); } - static S32 instanceCount() { return sInstances.size(); } -protected: - LLInstanceTracker(KEY key) { add(key); } - virtual ~LLInstanceTracker() { remove(); } - virtual void setKey(KEY key) { remove(); add(key); } - virtual const KEY& getKey() const { return mKey; } - -private: - void add(KEY key) - { - mKey = key; - sInstances[key] = static_cast(this); - } - void remove() { sInstances.erase(mKey); } - -private: - - KEY mKey; - static std::map sInstances; -}; - -template -class LLInstanceTracker : boost::noncopyable -{ -public: - typedef typename std::set::iterator instance_iter; - typedef typename std::set::const_iterator instance_const_iter; - - static instance_iter instancesBegin() { return sInstances.begin(); } - static instance_iter instancesEnd() { return sInstances.end(); } - static S32 instanceCount() { return sInstances.size(); } - -protected: - LLInstanceTracker() { sInstances.insert(static_cast(this)); } - virtual ~LLInstanceTracker() { sInstances.erase(static_cast(this)); } - - static std::set sInstances; -}; - -template std::map LLInstanceTracker::sInstances; -template std::set LLInstanceTracker::sInstances; - class LLCallbackRegistry { public: diff --git a/indra/llvfs/lldir.cpp b/indra/llvfs/lldir.cpp index 29b50d7bc..28fcd7751 100644 --- a/indra/llvfs/lldir.cpp +++ b/indra/llvfs/lldir.cpp @@ -524,7 +524,11 @@ std::string LLDir::getTempFilename() const std::string LLDir::getScrubbedFileName(const std::string uncleanFileName) { std::string name(uncleanFileName); - const std::string illegalChars(getForbiddenFileChars()); + std::string illegalChars(getForbiddenFileChars()); +#if LL_LINUX || LL_SOLARIS + // Spaces in filenames are REALLY annoying on UNIX. + illegalChars += ' '; +#endif // replace any illegal file chars with and underscore '_' for( unsigned int i = 0; i < illegalChars.length(); i++ ) { diff --git a/indra/media_plugins/CMakeLists.txt b/indra/media_plugins/CMakeLists.txt deleted file mode 100644 index 9858d093e..000000000 --- a/indra/media_plugins/CMakeLists.txt +++ /dev/null @@ -1,15 +0,0 @@ -# -*- cmake -*- - -add_subdirectory(base) - -add_subdirectory(webkit) - -if (LINUX) - add_subdirectory(gstreamer010) -endif (LINUX) - -if (DARWIN OR WINDOWS) - add_subdirectory(quicktime) -endif (DARWIN OR WINDOWS) - -add_subdirectory(example) diff --git a/indra/media_plugins/example/media_plugin_example.cpp b/indra/media_plugins/example/media_plugin_example.cpp deleted file mode 100644 index da7de0179..000000000 --- a/indra/media_plugins/example/media_plugin_example.cpp +++ /dev/null @@ -1,412 +0,0 @@ -/** - * @file media_plugin_example.cpp - * @brief Example plugin for LLMedia API plugin system - * - * @cond - * $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$ - * @endcond - */ - -#include "linden_common.h" - -#include "llgl.h" -#include "llplugininstance.h" -#include "llpluginmessage.h" -#include "llpluginmessageclasses.h" -#include "media_plugin_base.h" - -#include - -//////////////////////////////////////////////////////////////////////////////// -// -class MediaPluginExample : - public MediaPluginBase -{ - public: - MediaPluginExample( LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data ); - ~MediaPluginExample(); - - /*virtual*/ void receiveMessage( const char* message_string ); - - private: - bool init(); - void update( F64 milliseconds ); - void write_pixel( int x, int y, unsigned char r, unsigned char g, unsigned char b ); - bool mFirstTime; - - time_t mLastUpdateTime; - enum Constants { ENumObjects = 10 }; - unsigned char* mBackgroundPixels; - int mColorR[ ENumObjects ]; - int mColorG[ ENumObjects ]; - int mColorB[ ENumObjects ]; - int mXpos[ ENumObjects ]; - int mYpos[ ENumObjects ]; - int mXInc[ ENumObjects ]; - int mYInc[ ENumObjects ]; - int mBlockSize[ ENumObjects ]; - bool mMouseButtonDown; - bool mStopAction; -}; - -//////////////////////////////////////////////////////////////////////////////// -// -MediaPluginExample::MediaPluginExample( LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data ) : - MediaPluginBase( host_send_func, host_user_data ) -{ - mFirstTime = true; - mWidth = 0; - mHeight = 0; - mDepth = 4; - mPixels = 0; - mMouseButtonDown = false; - mStopAction = false; - mLastUpdateTime = 0; -} - -//////////////////////////////////////////////////////////////////////////////// -// -MediaPluginExample::~MediaPluginExample() -{ -} - -//////////////////////////////////////////////////////////////////////////////// -// -void MediaPluginExample::receiveMessage( const char* message_string ) -{ -// std::cerr << "MediaPluginWebKit::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_BROWSER] = LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER_VERSION; - message.setValueLLSD("versions", versions); - - std::string plugin_version = "Example plugin 1.0..0"; - message.setValue("plugin_version", plugin_version); - sendMessage(message); - } - else if(message_name == "idle") - { - // no response is necessary here. - F64 time = message_in.getValueReal("time"); - - // Convert time to milliseconds for update() - update((int)(time * 1000.0f)); - } - else if(message_name == "cleanup") - { - } - else if(message_name == "shm_added") - { - SharedSegmentInfo info; - info.mAddress = message_in.getValuePointer("address"); - info.mSize = (size_t)message_in.getValueS32("size"); - std::string name = message_in.getValue("name"); - - mSharedSegments.insert(SharedSegmentMap::value_type(name, info)); - - } - else if(message_name == "shm_remove") - { - std::string name = message_in.getValue("name"); - - SharedSegmentMap::iterator iter = mSharedSegments.find(name); - if(iter != mSharedSegments.end()) - { - if(mPixels == iter->second.mAddress) - { - // This is the currently active pixel buffer. Make sure we stop drawing to it. - mPixels = NULL; - mTextureSegmentName.clear(); - } - mSharedSegments.erase(iter); - } - else - { -// std::cerr << "MediaPluginWebKit::receiveMessage: unknown shared memory region!" << std::endl; - } - - // Send the response so it can be cleaned up. - LLPluginMessage message("base", "shm_remove_response"); - message.setValue("name", name); - sendMessage(message); - } - else - { -// std::cerr << "MediaPluginWebKit::receiveMessage: unknown base message: " << message_name << std::endl; - } - } - else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA) - { - if(message_name == "init") - { - // Plugin gets to decide the texture parameters to use. - mDepth = 4; - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "texture_params"); - message.setValueS32("default_width", 1024); - message.setValueS32("default_height", 1024); - message.setValueS32("depth", mDepth); - message.setValueU32("internalformat", GL_RGBA); - message.setValueU32("format", GL_RGBA); - message.setValueU32("type", GL_UNSIGNED_BYTE); - message.setValueBoolean("coords_opengl", true); - 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"); - - 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; - mWidth = width; - mHeight = height; - - mTextureWidth = texture_width; - mTextureHeight = 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); - - } - else if(message_name == "load_uri") - { - } - else if(message_name == "mouse_event") - { - std::string event = message_in.getValue("event"); - if(event == "down") - { - - } - else if(event == "up") - { - } - else if(event == "double_click") - { - } - } - } - else - { -// std::cerr << "MediaPluginWebKit::receiveMessage: unknown message class: " << message_class << std::endl; - }; - } -} - -//////////////////////////////////////////////////////////////////////////////// -// -void MediaPluginExample::write_pixel( int x, int y, unsigned char r, unsigned char g, unsigned char b ) -{ - // make sure we don't write outside the buffer - if ( ( x < 0 ) || ( x >= mWidth ) || ( y < 0 ) || ( y >= mHeight ) ) - return; - - if ( mBackgroundPixels != NULL ) - { - unsigned char *pixel = mBackgroundPixels; - pixel += y * mWidth * mDepth; - pixel += ( x * mDepth ); - pixel[ 0 ] = b; - pixel[ 1 ] = g; - pixel[ 2 ] = r; - - setDirty( x, y, x + 1, y + 1 ); - }; -} - -//////////////////////////////////////////////////////////////////////////////// -// -void MediaPluginExample::update( F64 milliseconds ) -{ - if ( mWidth < 1 || mWidth > 2048 || mHeight < 1 || mHeight > 2048 ) - return; - - if ( mPixels == 0 ) - return; - - if ( mFirstTime ) - { - for( int n = 0; n < ENumObjects; ++n ) - { - mXpos[ n ] = ( mWidth / 2 ) + rand() % ( mWidth / 16 ) - ( mWidth / 32 ); - mYpos[ n ] = ( mHeight / 2 ) + rand() % ( mHeight / 16 ) - ( mHeight / 32 ); - - mColorR[ n ] = rand() % 0x60 + 0x60; - mColorG[ n ] = rand() % 0x60 + 0x60; - mColorB[ n ] = rand() % 0x60 + 0x60; - - mXInc[ n ] = 0; - while ( mXInc[ n ] == 0 ) - mXInc[ n ] = rand() % 7 - 3; - - mYInc[ n ] = 0; - while ( mYInc[ n ] == 0 ) - mYInc[ n ] = rand() % 9 - 4; - - mBlockSize[ n ] = rand() % 0x30 + 0x10; - }; - - delete [] mBackgroundPixels; - - mBackgroundPixels = new unsigned char[ mWidth * mHeight * mDepth ]; - - mFirstTime = false; - }; - - if ( mStopAction ) - return; - - if ( time( NULL ) > mLastUpdateTime + 3 ) - { - const int num_squares = rand() % 20 + 4; - int sqr1_r = rand() % 0x80 + 0x20; - int sqr1_g = rand() % 0x80 + 0x20; - int sqr1_b = rand() % 0x80 + 0x20; - int sqr2_r = rand() % 0x80 + 0x20; - int sqr2_g = rand() % 0x80 + 0x20; - int sqr2_b = rand() % 0x80 + 0x20; - - for ( int y1 = 0; y1 < num_squares; ++y1 ) - { - for ( int x1 = 0; x1 < num_squares; ++x1 ) - { - int px_start = mWidth * x1 / num_squares; - int px_end = ( mWidth * ( x1 + 1 ) ) / num_squares; - int py_start = mHeight * y1 / num_squares; - int py_end = ( mHeight * ( y1 + 1 ) ) / num_squares; - - for( int y2 = py_start; y2 < py_end; ++y2 ) - { - for( int x2 = px_start; x2 < px_end; ++x2 ) - { - int rowspan = mWidth * mDepth; - - if ( ( y1 % 2 ) ^ ( x1 % 2 ) ) - { - mBackgroundPixels[ y2 * rowspan + x2 * mDepth + 0 ] = sqr1_r; - mBackgroundPixels[ y2 * rowspan + x2 * mDepth + 1 ] = sqr1_g; - mBackgroundPixels[ y2 * rowspan + x2 * mDepth + 2 ] = sqr1_b; - } - else - { - mBackgroundPixels[ y2 * rowspan + x2 * mDepth + 0 ] = sqr2_r; - mBackgroundPixels[ y2 * rowspan + x2 * mDepth + 1 ] = sqr2_g; - mBackgroundPixels[ y2 * rowspan + x2 * mDepth + 2 ] = sqr2_b; - }; - }; - }; - }; - }; - - time( &mLastUpdateTime ); - }; - - memcpy( mPixels, mBackgroundPixels, mWidth * mHeight * mDepth ); - - for( int n = 0; n < ENumObjects; ++n ) - { - if ( rand() % 50 == 0 ) - { - mXInc[ n ] = 0; - while ( mXInc[ n ] == 0 ) - mXInc[ n ] = rand() % 7 - 3; - - mYInc[ n ] = 0; - while ( mYInc[ n ] == 0 ) - mYInc[ n ] = rand() % 9 - 4; - }; - - if ( mXpos[ n ] + mXInc[ n ] < 0 || mXpos[ n ] + mXInc[ n ] >= mWidth - mBlockSize[ n ] ) - mXInc[ n ] =- mXInc[ n ]; - - if ( mYpos[ n ] + mYInc[ n ] < 0 || mYpos[ n ] + mYInc[ n ] >= mHeight - mBlockSize[ n ] ) - mYInc[ n ] =- mYInc[ n ]; - - mXpos[ n ] += mXInc[ n ]; - mYpos[ n ] += mYInc[ n ]; - - for( int y = 0; y < mBlockSize[ n ]; ++y ) - { - for( int x = 0; x < mBlockSize[ n ]; ++x ) - { - mPixels[ ( mXpos[ n ] + x ) * mDepth + ( mYpos[ n ] + y ) * mDepth * mWidth + 0 ] = mColorR[ n ]; - mPixels[ ( mXpos[ n ] + x ) * mDepth + ( mYpos[ n ] + y ) * mDepth * mWidth + 1 ] = mColorG[ n ]; - mPixels[ ( mXpos[ n ] + x ) * mDepth + ( mYpos[ n ] + y ) * mDepth * mWidth + 2 ] = mColorB[ n ]; - }; - }; - }; - - setDirty( 0, 0, mWidth, mHeight ); -}; - -//////////////////////////////////////////////////////////////////////////////// -// -bool MediaPluginExample::init() -{ - LLPluginMessage message( LLPLUGIN_MESSAGE_CLASS_MEDIA, "name_text" ); - message.setValue( "name", "Example Plugin" ); - sendMessage( message ); - - return true; -}; - -//////////////////////////////////////////////////////////////////////////////// -// -int init_media_plugin( LLPluginInstance::sendMessageFunction host_send_func, - void* host_user_data, - LLPluginInstance::sendMessageFunction *plugin_send_func, - void **plugin_user_data ) -{ - MediaPluginExample* self = new MediaPluginExample( host_send_func, host_user_data ); - *plugin_send_func = MediaPluginExample::staticReceiveMessage; - *plugin_user_data = ( void* )self; - - return 0; -} - diff --git a/indra/media_plugins/gstreamer010/llmediaimplgstreamer.h b/indra/media_plugins/gstreamer010/llmediaimplgstreamer.h deleted file mode 100644 index 6bc272c00..000000000 --- a/indra/media_plugins/gstreamer010/llmediaimplgstreamer.h +++ /dev/null @@ -1,53 +0,0 @@ -/** - * @file llmediaimplgstreamer.h - * @author Tofu Linden - * @brief implementation that supports media playback via GStreamer. - * - * @cond - * $LicenseInfo:firstyear=2007&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - * @endcond - */ - -// header guard -#ifndef llmediaimplgstreamer_h -#define llmediaimplgstreamer_h - -#if LL_GSTREAMER010_ENABLED - -extern "C" { -#include -#include - -#include "apr_pools.h" -#include "apr_dso.h" -} - - -extern "C" { -gboolean llmediaimplgstreamer_bus_callback (GstBus *bus, - GstMessage *message, - gpointer data); -} - -#endif // LL_GSTREAMER010_ENABLED - -#endif // llmediaimplgstreamer_h diff --git a/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms.cpp b/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms.cpp deleted file mode 100644 index 2e4baaa9e..000000000 --- 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 - -extern "C" { -#include - -#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 d1559089c..000000000 --- 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 -} - -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 b33e59363..000000000 --- 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 14fbcb48b..000000000 --- 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 e7b31bec9..000000000 --- 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 - -extern "C" { -#include -#include -} - -///////////////////////////////////////////////////////////////////////// -// 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/webkit/volume_catcher.h b/indra/media_plugins/webkit/volume_catcher.h deleted file mode 100644 index 337f2913d..000000000 --- a/indra/media_plugins/webkit/volume_catcher.h +++ /dev/null @@ -1,54 +0,0 @@ -/** - * @file volume_catcher.h - * @brief Interface to a class with platform-specific implementations that allows control of the audio volume of all sources in the current process. - * - * @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_H -#define VOLUME_CATCHER_H - -#include "linden_common.h" - -class VolumeCatcherImpl; - -class VolumeCatcher -{ - 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 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 - - private: - VolumeCatcherImpl *pimpl; -}; - -#endif // VOLUME_CATCHER_H diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 0692c6137..1275906a2 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -22,6 +22,7 @@ include(LLInventory) include(LLMath) include(LLMessage) include(LLPlugin) +include(AIStateMachine) include(LLPrimitive) include(LLRender) include(LLUI) @@ -43,6 +44,7 @@ if (WINDOWS) endif (WINDOWS) include_directories( + ${CMAKE_SOURCE_DIR}/newview ${DBUSGLIB_INCLUDE_DIRS} ${HUNSPELL_INCLUDE_DIR} ${ELFIO_INCLUDE_DIR} @@ -134,7 +136,6 @@ set(viewer_SOURCE_FILES lldebugmessagebox.cpp lldebugview.cpp lldelayedgestureerror.cpp - lldirpicker.cpp lldrawable.cpp lldrawpoolalpha.cpp lldrawpoolavatar.cpp @@ -156,7 +157,6 @@ set(viewer_SOURCE_FILES llface.cpp llfasttimerview.cpp llfeaturemanager.cpp - llfilepicker.cpp llfirstuse.cpp llflexibleobject.cpp llfloaterabout.cpp @@ -185,7 +185,6 @@ set(viewer_SOURCE_FILES llfloatercolorpicker.cpp llfloatercustomize.cpp llfloaterdaycycle.cpp - llfloaterdickdongs.cpp llfloaterdirectory.cpp llfloatereditui.cpp llfloaterenvsettings.cpp @@ -236,7 +235,6 @@ set(viewer_SOURCE_FILES llfloatersnapshot.cpp llfloaterstats.cpp llfloatertelehub.cpp - llfloaterteleport.cpp llfloaterteleporthistory.cpp llfloatertest.cpp llfloatertools.cpp @@ -444,6 +442,8 @@ set(viewer_SOURCE_FILES llviewerkeyboard.cpp llviewerlayer.cpp llviewermedia.cpp + llviewermediaeventemitter.cpp + llviewermediaobserver.cpp llviewermediafocus.cpp llviewermedia_streamingaudio.cpp llviewermenu.cpp @@ -458,6 +458,7 @@ set(viewer_SOURCE_FILES llviewerparceloverlay.cpp llviewerpartsim.cpp llviewerpartsource.cpp + llviewerpluginmanager.cpp llviewerregion.cpp llviewershadermgr.cpp llviewerstats.cpp @@ -610,7 +611,6 @@ set(viewer_HEADER_FILES lldebugmessagebox.h lldebugview.h lldelayedgestureerror.h - lldirpicker.h lldrawable.h lldrawpool.h lldrawpoolalpha.h @@ -633,7 +633,6 @@ set(viewer_HEADER_FILES llface.h llfasttimerview.h llfeaturemanager.h - llfilepicker.h llfirstuse.h llflexibleobject.h llfloaterabout.h @@ -662,7 +661,6 @@ set(viewer_HEADER_FILES llfloatercolorpicker.h llfloatercustomize.h llfloaterdaycycle.h - llfloaterdickdongs.h llfloaterdirectory.h llfloatereditui.h llfloaterenvsettings.h @@ -713,7 +711,6 @@ set(viewer_HEADER_FILES llfloatersnapshot.h llfloaterstats.h llfloatertelehub.h - llfloaterteleport.h llfloaterteleporthistory.h llfloatertest.h llfloatertools.h @@ -922,6 +919,7 @@ set(viewer_HEADER_FILES llviewerkeyboard.h llviewerlayer.h llviewermedia.h + llviewermediaeventemitter.h llviewermediaobserver.h llviewermediafocus.h llviewermenu.h @@ -936,6 +934,7 @@ set(viewer_HEADER_FILES llviewerparceloverlay.h llviewerpartsim.h llviewerpartsource.h + llviewerpluginmanager.h llviewerprecompiledheaders.h llviewerregion.h llviewershadermgr.h @@ -1412,7 +1411,7 @@ if (WINDOWS) DEPENDS ${VIEWER_BINARY_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py ) - add_dependencies(${VIEWER_BINARY_NAME} SLPlugin media_plugin_quicktime media_plugin_webkit) + add_dependencies(${VIEWER_BINARY_NAME} SLPlugin media_plugin_quicktime media_plugin_webkit basic_plugin_filepicker) if (PACKAGE) add_custom_target(package ALL DEPENDS ${CMAKE_CFG_INTDIR}/touched.bat) @@ -1429,6 +1428,7 @@ target_link_libraries(${VIEWER_BINARY_NAME} ${LLINVENTORY_LIBRARIES} ${LLMESSAGE_LIBRARIES} ${LLPLUGIN_LIBRARIES} + ${AISTATEMACHINE_LIBRARIES} ${LLPRIMITIVE_LIBRARIES} ${LLRENDER_LIBRARIES} ${FREETYPE_LIBRARIES} @@ -1491,7 +1491,7 @@ if (LINUX) DEPENDS secondlife-stripped ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py ) - add_dependencies(${VIEWER_BINARY_NAME} SLPlugin media_plugin_gstreamer010 media_plugin_webkit) + add_dependencies(${VIEWER_BINARY_NAME} SLPlugin media_plugin_gstreamer010 media_plugin_webkit basic_plugin_filepicker) if (PACKAGE) add_custom_target(package ALL DEPENDS ${product}.tar.bz2) @@ -1532,7 +1532,7 @@ if (DARWIN) DEPENDS ${VIEWER_BINARY_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py ) - add_dependencies(${VIEWER_BINARY_NAME} SLPlugin media_plugin_quicktime media_plugin_webkit) + add_dependencies(${VIEWER_BINARY_NAME} SLPlugin media_plugin_quicktime media_plugin_webkit basic_plugin_filepicker) if (PACKAGE) add_custom_target(package ALL DEPENDS ${VIEWER_BINARY_NAME}) @@ -1648,6 +1648,18 @@ if (WINDOWS) COMMENT "Copying Quicktime Plugin to the runtime folder." ) + get_target_property(BUILT_FILEPICKER_PLUGIN basic_plugin_filepicker LOCATION) + add_custom_command( + TARGET ${VIEWER_BINARY_NAME} POST_BUILD + COMMAND ${CMAKE_COMMAND} + ARGS + -E + copy_if_different + ${BUILT_FILEPICKER_PLUGIN} + ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/llplugin + COMMENT "Copying filepicker Plugin to the runtime folder." + ) + # Copying the mime_types.xml file to app_settings set(mime_types_source "${CMAKE_SOURCE_DIR}/newview/skins/default/xui/en-us") set(mime_types_dest "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/app_settings") diff --git a/indra/newview/app_settings/cmd_line.xml b/indra/newview/app_settings/cmd_line.xml index 354d40279..6bed5a829 100644 --- a/indra/newview/app_settings/cmd_line.xml +++ b/indra/newview/app_settings/cmd_line.xml @@ -106,6 +106,14 @@ QuitAfterSeconds + + debugsession + + desc + Run as if RenderDebugGL is TRUE, but log errors until end of session. + map-to + DebugSession + rotate map-to @@ -238,7 +246,7 @@ multiple desc - Allow multple viewers. + Allow multiple viewers. map-to AllowMultipleViewers diff --git a/indra/newview/app_settings/high_graphics.xml b/indra/newview/app_settings/high_graphics.xml index 6368f7099..2e939f47e 100644 --- a/indra/newview/app_settings/high_graphics.xml +++ b/indra/newview/app_settings/high_graphics.xml @@ -13,7 +13,7 @@ - + diff --git a/indra/newview/app_settings/logcontrol.xml b/indra/newview/app_settings/logcontrol.xml index 6bf7613f7..cbfda6de4 100644 --- a/indra/newview/app_settings/logcontrol.xml +++ b/indra/newview/app_settings/logcontrol.xml @@ -42,6 +42,15 @@ ShaderLoading Openjpeg + + Plugin + Plugin child + + PluginRaw child + + + + diff --git a/indra/newview/app_settings/low_graphics.xml b/indra/newview/app_settings/low_graphics.xml index 3f67a70d7..79b25003f 100644 --- a/indra/newview/app_settings/low_graphics.xml +++ b/indra/newview/app_settings/low_graphics.xml @@ -13,7 +13,7 @@ - + diff --git a/indra/newview/app_settings/mid_graphics.xml b/indra/newview/app_settings/mid_graphics.xml index 12da77da4..4660d0cd4 100644 --- a/indra/newview/app_settings/mid_graphics.xml +++ b/indra/newview/app_settings/mid_graphics.xml @@ -13,7 +13,7 @@ - + diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 24d9c80f8..d0f5ac23e 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -1894,10 +1894,10 @@ 0 - BeaconAlwaysOn + ShowBeaconsFloater Comment - Beacons / highlighting always on + Show beacons floater Persist 1 Type @@ -1905,6 +1905,28 @@ Value 0 + BeaconsKeepVisible + + Comment + Don't turn off BeaconsVisible when beacons floater is closed + Persist + 1 + Type + Boolean + Value + 0 + + BeaconsVisible + + Comment + Show beacons / highlighting + Persist + 0 + Type + Boolean + Value + 0 + BrowserHomePage Comment @@ -1952,7 +1974,7 @@ PluginAttachDebuggerToPlugins Comment - TODO: understand what this actually does -.-sg + Opens a terminal window with a debugger and attach it, every time a new SLPlugin process is started. Persist 1 Type @@ -2654,6 +2676,65 @@ Value 1.0 + CameraFocusTransitionTime + + Comment + How many seconds it takes the camera to transition between focal distances + Persist + 1 + Type + F32 + Value + 0.5 + + + CameraFNumber + + Comment + Camera f-number value for DoF effect + Persist + 1 + Type + F32 + Value + 9.0 + + + CameraFocalLength + + Comment + Camera focal length for DoF effect (in millimeters) + Persist + 1 + Type + F32 + Value + 50 + + + CameraFieldOfView + + Comment + Vertical camera field of view for DoF effect (in degrees) + Persist + 1 + Type + F32 + Value + 60.0 + + + CameraAspectRatio + + Comment + Camera aspect ratio for DoF effect + Persist + 1 + Type + F32 + Value + 1.5 + ChatBarStealsFocus Comment @@ -8925,7 +9006,7 @@ Type S32 Value - 35 + 12 RenderAvatarPhysicsLODFactor @@ -8960,24 +9041,22 @@ Value 1 - RenderShadowGaussian - - Comment - Gaussian coefficients for the two shadow/SSAO blurring passes (z component unused). - Persist - 1 - Type - Vector3 - Value - - 2.0 - 2.0 - 0.0 - - - RenderShadowNearDist - - Comment + + RenderLocalLights + + Comment + Whether or not to render local lights. + Persist + 1 + Type + Boolean + Value + 1 + + + RenderShadowNearDist + + Comment Near clip plane of shadow camera (affects precision of depth shadows). Persist 1 @@ -9000,11 +9079,74 @@ Vector3 Value - 4.0 - 8.0 - 24.0 + 1.0 + 12.0 + 32.0 - + + RenderShadowSplitExponent + + Comment + Near clip plane split distances for shadow map frusta (x=perspective, y=ortho, z=transition rate). + Persist + 1 + Type + Vector3 + Value + + 3.0 + 3.0 + 2.0 + + + RenderShadowOrthoClipPlanes + + Comment + Near clip plane split distances for orthographic shadow map frusta. + Persist + 1 + Type + Vector3 + Value + + 4.0 + 8.0 + 24.0 + + + RenderShadowProjOffset + + Comment + Amount to scale distance to virtual origin of shadow perspective projection. + Persist + 1 + Type + F32 + Value + 2.0 + + RenderShadowSlopeThreshold + + Comment + Cutoff slope value for points to affect perspective shadow generation + Persist + 1 + Type + F32 + Value + 0.0 + + RenderShadowProjExponent + + Comment + Exponent applied to transition between ortho and perspective shadow projections based on viewing angle and light vector. + Persist + 1 + Type + F32 + Value + 0.5 + RenderSSAOScale Comment @@ -9025,7 +9167,7 @@ Type U32 Value - 60 + 200 RenderSSAOFactor @@ -9048,7 +9190,7 @@ Vector3 Value - 0.40 + 0.80 1.00 0.00 @@ -9073,7 +9215,7 @@ Type F32 Value - 128 + 64 RenderCubeMap @@ -9163,7 +9305,175 @@ Value 0 - RenderDeferredAlphaSoften + + RenderGIRange + + Comment + Distance to cut off GI effect. + Persist + 1 + Type + F32 + Value + 96 + + + RenderGILuminance + + Comment + Luminance factor of global illumination contribution. + Persist + 1 + Type + F32 + Value + 0.075 + + + RenderGIBrightness + + Comment + Brightness factor of global illumination contribution. + Persist + 1 + Type + F32 + Value + 0.3 + + + RenderGINoise + + Comment + Noise of position sampling for GI photon mapping. + Persist + 1 + Type + F32 + Value + 0.7 + + + RenderGIAttenuation + + Comment + Distance attenuation factor for indirect lighting. + Persist + 1 + Type + F32 + Value + 0.1 + + + RenderGIBlurBrightness + + Comment + Brightness factor of global illumination blur effect. + Persist + 1 + Type + F32 + Value + 1.025 + + + RenderGIBlurEdgeWeight + + Comment + Edge weight for GI soften filter (sharpness). + Persist + 1 + Type + F32 + Value + 0.8 + + + RenderGIBlurIncrement + + Comment + Increment of scale for each pass of global illumination blur effect. + Persist + 1 + Type + F32 + Value + 0.8 + + + RenderLuminanceScale + + Comment + Luminance value scalar for darkening effect. + Persist + 1 + Type + F32 + Value + 1.0 + + + RenderSunLuminanceScale + + Comment + Sun Luminance value scalar for darkening effect. + Persist + 1 + Type + F32 + Value + 1.0 + + + RenderSunLuminanceOffset + + Comment + Sun Luminance value offset for darkening effect. + Persist + 1 + Type + F32 + Value + 0 + + + RenderLuminanceDetail + + Comment + Mipmap level to use for luminance + Persist + 1 + Type + F32 + Value + 16.0 + + + RenderEdgeDepthCutoff + + Comment + Cutoff for depth difference that amounts to an edge. + Persist + 1 + Type + F32 + Value + 0.01 + + RenderEdgeNormCutoff + + Comment + Cutoff for normal difference that amounts to an edge. + Persist + 1 + Type + F32 + Value + 0.25 + + + RenderDeferredAlphaSoften Comment Scalar for softening alpha surfaces (for soft particles). @@ -9185,9 +9495,249 @@ Value 4 - RenderDeferred - - Comment + RenderDeferredSpotShadowBias + + Comment + Bias value for spot shadows (prevent shadow acne). + Persist + 1 + Type + F32 + Value + -64.0 + + RenderDeferredSpotShadowOffset + + Comment + Offset value for spot shadows (prevent shadow acne). + Persist + 1 + Type + F32 + Value + 0.8 + + + RenderShadowBias + + Comment + Bias value for shadows (prevent shadow acne). + Persist + 1 + Type + F32 + Value + -0.008 + + RenderShadowOffset + + Comment + Offset value for shadows (prevent shadow acne). + Persist + 1 + Type + F32 + Value + 0.01 + + + RenderShadowBiasError + + Comment + Error scale for shadow bias (based on altitude). + Persist + 1 + Type + F32 + Value + 0 + + RenderShadowOffsetError + + Comment + Error scale for shadow offset (based on altitude). + Persist + 1 + Type + F32 + Value + 0 + + + RenderSpotLightsInNondeferred + + Comment + Whether to support projectors as spotlights when Lighting and Shadows is disabled + Persist + 1 + Type + Boolean + Value + 0 + + + RenderSpotShadowBias + + Comment + Bias value for shadows (prevent shadow acne). + Persist + 1 + Type + F32 + Value + 0.0 + + RenderSpotShadowOffset + + Comment + Offset value for shadows (prevent shadow acne). + Persist + 1 + Type + F32 + Value + 0.04 + + + RenderShadowResolutionScale + + Comment + Scale of shadow map resolution vs. screen resolution + Persist + 1 + Type + F32 + Value + 1.0 + + + RenderDeferredTreeShadowBias + + Comment + Bias value for tree shadows (prevent shadow acne). + Persist + 1 + Type + F32 + Value + 1.0 + + RenderDeferredTreeShadowOffset + + Comment + Offset value for tree shadows (prevent shadow acne). + Persist + 1 + Type + F32 + Value + 1.0 + + + RenderHoverGlowEnable + + Comment + Show glow effect when hovering on interactive objects. + Persist + 1 + Type + Boolean + Value + 0 + + + RenderHighlightFadeTime + + Comment + Transition time for mouseover highlights. + Persist + 1 + Type + F32 + Value + 0.1 + + + RenderHighlightBrightness + + Comment + Brightness of mouseover highlights. + Persist + 1 + Type + F32 + Value + 4.0 + + + RenderHighlightThickness + + Comment + Thickness of mouseover highlights. + Persist + 1 + Type + F32 + Value + 0.6 + + + RenderHighlightColor + + Comment + Brightness of mouseover highlights. + Persist + 1 + Type + Color4 + Value + + 0.4 + 0.98 + 0.93 + 1.0 + + + + RenderSpecularResX + + Comment + Spec map resolution. + Persist + 1 + Type + U32 + Value + 128 + + + RenderSpecularResY + + Comment + Spec map resolution. + Persist + 1 + Type + U32 + Value + 128 + + + RenderSpecularExponent + + Comment + Specular exponent for generating spec map + Persist + 1 + Type + F32 + Value + 8 + + + RenderDeferred + + Comment Use deferred rendering pipeline. Persist 1 @@ -9196,19 +9746,93 @@ Value 0 - RenderDeferredSunShadow - - Comment - Generate shadows from the sun. - Persist - 1 - Type - Boolean - Value - 1 - - RenderDeferredSunWash - + + RenderDeferredGI + + Comment + Enable GI in deferred renderer. + Persist + 1 + Type + Boolean + Value + 0 + + + RenderDeferredSun + + Comment + Execute sunlight shader in deferred renderer. + Persist + 1 + Type + Boolean + Value + 1 + + + RenderDeferredAtmospheric + + Comment + Execute atmospheric shader in deferred renderer. + Persist + 1 + Type + Boolean + Value + 1 + + + RenderDeferredSSAO + + Comment + Execute screen space ambient occlusion shader in deferred renderer. + Persist + 1 + Type + Boolean + Value + 1 + + + RenderDeferredBlurLight + + Comment + Execute shadow softening shader in deferred renderer. + Persist + 1 + Type + Boolean + Value + 1 + + + RenderDeferredLocalLights + + Comment + Execute local lighting shader in deferred renderer. + Persist + 1 + Type + Boolean + Value + 1 + + + RenderDeferredFullscreenLights + + Comment + Execute local lighting shader in deferred renderer. + Persist + 1 + Type + Boolean + Value + 1 + + + RenderDeferredSunWash + Comment Amount local lights are washed out by sun. Persist @@ -9228,20 +9852,59 @@ F32 Value -0.0001 - - RenderShadowBlurSize - - Comment - Scale of shadow softening kernel. - Persist - 1 - Type - F32 - Value - 0.7 - - RenderShadowBlurSamples - + + RenderShadowErrorCutoff + + Comment + Cutoff error value to use ortho instead of perspective projection. + Persist + 1 + Type + F32 + Value + 5.0 + + RenderShadowFOVCutoff + + Comment + Cutoff FOV to use ortho instead of perspective projection. + Persist + 1 + Type + F32 + Value + 1.1 + + + RenderShadowGaussian + + Comment + Gaussian coefficients for the two shadow/SSAO blurring passes (z component unused). + Persist + 1 + Type + Vector3 + Value + + 3.0 + 2.0 + 0.0 + + + + RenderShadowBlurSize + + Comment + Scale of shadow softening kernel. + Persist + 1 + Type + F32 + Value + 1.4 + + RenderShadowBlurSamples + Comment Number of samples to take for each pass of shadow blur (value range 1-16). Actual number of samples is value * 2 - 1. Persist @@ -9251,6 +9914,104 @@ Value 5 + RenderShadowBlurDistFactor + + Comment + Distance scaler for shadow blur. + Persist + 1 + Type + F32 + Value + 0.1 + + + RenderGIAmbiance + + Comment + Ambiance factor of global illumination contribution. + Persist + 1 + Type + F32 + Value + 0.5 + + + RenderGIMinRenderSize + + Comment + Minimum size of objects to put into GI source map. + Persist + 1 + Type + F32 + Value + 0.5 + + + RenderGIBlurColorCurve + + Comment + Color curve for GI softening kernel + Persist + 1 + Type + Vector3 + Value + + 1.0 + 0.6 + 0.02 + + + + RenderGIBlurPasses + + Comment + Scale of GI softening kernel. + Persist + 1 + Type + U32 + Value + 4 + + + RenderGIBlurSize + + Comment + Scale of GI softening kernel. + Persist + 1 + Type + F32 + Value + 4.0 + + RenderGIBlurSamples + + Comment + Number of samples to take for each pass of GI blur (value range 1-16). Actual number of samples is value * 2 - 1. + Persist + 1 + Type + U32 + Value + 16 + + RenderGIBlurDistFactor + + Comment + Distance scaler for GI blur. + Persist + 1 + Type + F32 + Value + 0.0 + + RenderDynamicLOD Comment @@ -9320,7 +10081,7 @@ RenderFastAlpha Comment - Use lossy alpha rendering optimization (opaque/nonexistent small alpha faces). + Use alpha masks where appropriate. Persist 1 Type @@ -9600,17 +10361,6 @@ Value 0 - RenderLightingDetail - - Comment - Amount of detail for lighting objects/avatars/terrain (0=sun/moon only, 1=enable local lights) - Persist - 1 - Type - S32 - Value - 1 - RenderMaxPartCount Comment @@ -9787,6 +10537,18 @@ Value 2 + RenderShadowDetail + + Comment + Detail of shadows. + Persist + 1 + Type + S32 + Value + 0 + + RenderReflectionRes Comment @@ -9897,6 +10659,17 @@ Value 1.0 + RenderTransparentWater + + Comment + Render water as transparent. Setting to false renders water as opaque with a simple texture applied. + Persist + 1 + Type + Boolean + Value + 1 + RenderTreeLODFactor Comment @@ -10007,6 +10780,17 @@ Value 1 + RenderPreferStreamDraw + + Comment + Use GL_STREAM_DRAW in place of GL_DYNAMIC_DRAW + Persist + 1 + Type + Boolean + Value + 0 + RenderVolumeLODFactor Comment @@ -10051,28 +10835,6 @@ Value 512 - RenderWaterReflections - - Comment - Reflect the environment in the water. - Persist - 1 - Type - Boolean - Value - 0 - - RenderWaterVoidCulling - - Comment - Cull void water objects when off-screen. - Persist - 1 - Type - Boolean - Value - 1 - RotateRight Comment @@ -11399,6 +12161,17 @@ Value 0 + StateMachineMaxTime + + Comment + Maximum time per frame spent executing AIStateMachine objects, in miliseconds + Persist + 1 + Type + U32 + Value + 20 + StatsAutoRun Comment @@ -14032,6 +14805,17 @@ Value 0 + keepbeacons + + Comment + Keep beacons when closing floater + Persist + 1 + Type + Boolean + Value + 0 + LogTextureDownloadsToViewerLog Comment diff --git a/indra/newview/app_settings/shaders/class1/avatar/avatarF.glsl b/indra/newview/app_settings/shaders/class1/avatar/avatarF.glsl index b6cc7f771..431c7f8e1 100644 --- a/indra/newview/app_settings/shaders/class1/avatar/avatarF.glsl +++ b/indra/newview/app_settings/shaders/class1/avatar/avatarF.glsl @@ -4,6 +4,8 @@ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 void default_lighting(); diff --git a/indra/newview/app_settings/shaders/class1/avatar/avatarSkinV.glsl b/indra/newview/app_settings/shaders/class1/avatar/avatarSkinV.glsl index 292dbfdab..9057560e6 100644 --- a/indra/newview/app_settings/shaders/class1/avatar/avatarSkinV.glsl +++ b/indra/newview/app_settings/shaders/class1/avatar/avatarSkinV.glsl @@ -4,6 +4,8 @@ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 attribute vec4 weight; //1 diff --git a/indra/newview/app_settings/shaders/class1/avatar/avatarV.glsl b/indra/newview/app_settings/shaders/class1/avatar/avatarV.glsl index ee3410d73..7b36d03c3 100644 --- a/indra/newview/app_settings/shaders/class1/avatar/avatarV.glsl +++ b/indra/newview/app_settings/shaders/class1/avatar/avatarV.glsl @@ -4,6 +4,8 @@ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol); mat4 getSkinnedTransform(); diff --git a/indra/newview/app_settings/shaders/class1/avatar/eyeballF.glsl b/indra/newview/app_settings/shaders/class1/avatar/eyeballF.glsl index 4d93c1944..cc49fe9f7 100644 --- a/indra/newview/app_settings/shaders/class1/avatar/eyeballF.glsl +++ b/indra/newview/app_settings/shaders/class1/avatar/eyeballF.glsl @@ -4,6 +4,8 @@ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 void default_lighting(); diff --git a/indra/newview/app_settings/shaders/class1/avatar/eyeballV.glsl b/indra/newview/app_settings/shaders/class1/avatar/eyeballV.glsl index b3c988a92..af9c28a6e 100644 --- a/indra/newview/app_settings/shaders/class1/avatar/eyeballV.glsl +++ b/indra/newview/app_settings/shaders/class1/avatar/eyeballV.glsl @@ -4,6 +4,8 @@ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 vec4 calcLightingSpecular(vec3 pos, vec3 norm, vec4 color, inout vec4 specularColor, vec4 baseCol); void calcAtmospherics(vec3 inPositionEye); diff --git a/indra/newview/app_settings/shaders/class1/avatar/pickAvatarF.glsl b/indra/newview/app_settings/shaders/class1/avatar/pickAvatarF.glsl index 201930041..0b9943479 100644 --- a/indra/newview/app_settings/shaders/class1/avatar/pickAvatarF.glsl +++ b/indra/newview/app_settings/shaders/class1/avatar/pickAvatarF.glsl @@ -4,6 +4,8 @@ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 uniform sampler2D diffuseMap; diff --git a/indra/newview/app_settings/shaders/class1/avatar/pickAvatarV.glsl b/indra/newview/app_settings/shaders/class1/avatar/pickAvatarV.glsl index 12d8f9d2f..801a8e06d 100644 --- a/indra/newview/app_settings/shaders/class1/avatar/pickAvatarV.glsl +++ b/indra/newview/app_settings/shaders/class1/avatar/pickAvatarV.glsl @@ -4,6 +4,8 @@ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 mat4 getSkinnedTransform(); diff --git a/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl b/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl index 7c8d238d2..22cae7a34 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl @@ -4,18 +4,15 @@ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 #extension GL_ARB_texture_rectangle : enable uniform sampler2D diffuseMap; -uniform sampler2DShadow shadowMap0; -uniform sampler2DShadow shadowMap1; -uniform sampler2DShadow shadowMap2; -uniform sampler2DShadow shadowMap3; -uniform sampler2D noiseMap; -uniform sampler2DRect positionMap; +uniform sampler2DRect depthMap; -uniform mat4 shadow_matrix[4]; +uniform mat4 shadow_matrix[6]; uniform vec4 shadow_clip; uniform vec2 screen_res; @@ -26,63 +23,45 @@ varying vec3 vary_ambient; varying vec3 vary_directional; varying vec3 vary_fragcoord; varying vec3 vary_position; +varying vec3 vary_pointlight_col; -uniform float alpha_soften; +uniform mat4 inv_proj; + +vec4 getPosition(vec2 pos_screen) +{ + float depth = texture2DRect(depthMap, pos_screen.xy).a; + vec2 sc = pos_screen.xy*2.0; + sc /= screen_res; + sc -= vec2(1.0,1.0); + vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); + vec4 pos = inv_proj * ndc; + pos /= pos.w; + pos.w = 1.0; + return pos; +} void main() { vec2 frag = vary_fragcoord.xy/vary_fragcoord.z*0.5+0.5; frag *= screen_res; - vec3 samp_pos = texture2DRect(positionMap, frag).xyz; - - float shadow = 1.0; vec4 pos = vec4(vary_position, 1.0); - if (pos.z > -shadow_clip.w) - { - if (pos.z < -shadow_clip.z) - { - vec4 lpos = shadow_matrix[3]*pos; - shadow = shadow2DProj(shadowMap3, lpos).x; - shadow += max((pos.z+shadow_clip.z)/(shadow_clip.z-shadow_clip.w)*2.0-1.0, 0.0); - } - else if (pos.z < -shadow_clip.y) - { - vec4 lpos = shadow_matrix[2]*pos; - shadow = shadow2DProj(shadowMap2, lpos).x; - } - else if (pos.z < -shadow_clip.x) - { - vec4 lpos = shadow_matrix[1]*pos; - shadow = shadow2DProj(shadowMap1, lpos).x; - } - else - { - vec4 lpos = shadow_matrix[0]*pos; - shadow = shadow2DProj(shadowMap0, lpos).x; - } - } + vec4 diff= texture2D(diffuseMap, gl_TexCoord[0].xy); - vec4 col = vec4(vary_ambient + vary_directional.rgb*shadow, gl_Color.a); - vec4 color = texture2D(diffuseMap, gl_TexCoord[0].xy) * col; + vec4 col = vec4(vary_ambient + vary_directional.rgb, gl_Color.a); + vec4 color = diff * col; color.rgb = atmosLighting(color.rgb); color.rgb = scaleSoftClip(color.rgb); - /*if (samp_pos.z != 0.0) - { - float dist_factor = alpha_soften; - float a = gl_Color.a; - a *= a; - dist_factor *= 1.0/(1.0-a); - color.a *= min((pos.z-samp_pos.z)*dist_factor, 1.0); - }*/ - + color.rgb += diff.rgb * vary_pointlight_col.rgb; + //gl_FragColor = gl_Color; gl_FragColor = color; //gl_FragColor = vec4(1,0,1,1); + //gl_FragColor = vec4(1,0,1,1)*shadow; } diff --git a/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl b/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl index 9f130ee42..d1c678f30 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl @@ -5,11 +5,12 @@ * $License$ */ +#version 120 + vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol); void calcAtmospherics(vec3 inPositionEye); float calcDirectionalLight(vec3 n, vec3 l); -float calcPointLight(vec3 v, vec3 n, vec4 lp, float la); vec3 atmosAmbient(vec3 light); vec3 atmosAffectDirectionalLight(float lightIntensity); @@ -20,8 +21,37 @@ varying vec3 vary_ambient; varying vec3 vary_directional; varying vec3 vary_fragcoord; varying vec3 vary_position; +varying vec3 vary_light; +varying vec3 vary_pointlight_col; uniform float near_clip; +uniform float shadow_offset; +uniform float shadow_bias; + +float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float fa, float is_pointlight) +{ + //get light vector + vec3 lv = lp.xyz-v; + + //get distance + float d = length(lv); + + //normalize light vector + lv *= 1.0/d; + + //distance attenuation + float dist2 = d*d/(la*la); + float da = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0); + + // spotlight coefficient. + float spot = max(dot(-ln, lv), is_pointlight); + da *= spot*spot; // GL_SPOT_EXPONENT=2 + + //angular attenuation + da *= calcDirectionalLight(n, lv); + + return da; +} void main() { @@ -32,32 +62,37 @@ void main() vec4 pos = (gl_ModelViewMatrix * gl_Vertex); vec3 norm = normalize(gl_NormalMatrix * gl_Normal); - vary_position = pos.xyz; + + float dp_directional_light = max(0.0, dot(norm, gl_LightSource[0].position.xyz)); + vary_position = pos.xyz + gl_LightSource[0].position.xyz * (1.0-dp_directional_light)*shadow_offset; calcAtmospherics(pos.xyz); //vec4 color = calcLighting(pos.xyz, norm, gl_Color, vec4(0.)); - + vec4 col = vec4(0.0, 0.0, 0.0, gl_Color.a); + + // Collect normal lights + col.rgb += gl_LightSource[2].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[2].position, gl_LightSource[2].spotDirection.xyz, gl_LightSource[2].linearAttenuation, gl_LightSource[2].quadraticAttenuation, gl_LightSource[2].specular.a); + col.rgb += gl_LightSource[3].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[3].position, gl_LightSource[3].spotDirection.xyz, gl_LightSource[3].linearAttenuation, gl_LightSource[3].quadraticAttenuation, gl_LightSource[3].specular.a); + col.rgb += gl_LightSource[4].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[4].position, gl_LightSource[4].spotDirection.xyz, gl_LightSource[4].linearAttenuation, gl_LightSource[4].quadraticAttenuation, gl_LightSource[4].specular.a); + col.rgb += gl_LightSource[5].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[5].position, gl_LightSource[5].spotDirection.xyz, gl_LightSource[5].linearAttenuation, gl_LightSource[5].quadraticAttenuation, gl_LightSource[5].specular.a); + col.rgb += gl_LightSource[6].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[6].position, gl_LightSource[6].spotDirection.xyz, gl_LightSource[6].linearAttenuation, gl_LightSource[6].quadraticAttenuation, gl_LightSource[6].specular.a); + col.rgb += gl_LightSource[7].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[7].position, gl_LightSource[7].spotDirection.xyz, gl_LightSource[7].linearAttenuation, gl_LightSource[7].quadraticAttenuation, gl_LightSource[7].specular.a); + + vary_pointlight_col = col.rgb*gl_Color.rgb; + + col.rgb = vec3(0,0,0); // Add windlight lights col.rgb = atmosAmbient(vec3(0.)); - col.rgb = scaleUpLight(col.rgb); - - // Collect normal lights (need to be divided by two, as we later multiply by 2) - col.rgb += gl_LightSource[2].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[2].position, gl_LightSource[2].linearAttenuation); - col.rgb += gl_LightSource[3].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[3].position, gl_LightSource[3].linearAttenuation); - col.rgb += gl_LightSource[4].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[4].position, gl_LightSource[4].linearAttenuation); - col.rgb += gl_LightSource[5].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[5].position, gl_LightSource[5].linearAttenuation); - col.rgb += gl_LightSource[6].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[6].position, gl_LightSource[6].linearAttenuation); - col.rgb += gl_LightSource[7].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[7].position, gl_LightSource[7].linearAttenuation); - col.rgb += gl_LightSource[1].diffuse.rgb*calcDirectionalLight(norm, gl_LightSource[1].position.xyz); - col.rgb = scaleDownLight(col.rgb); + + vary_light = gl_LightSource[0].position.xyz; vary_ambient = col.rgb*gl_Color.rgb; vary_directional.rgb = gl_Color.rgb*atmosAffectDirectionalLight(max(calcDirectionalLight(norm, gl_LightSource[0].position.xyz), (1.0-gl_Color.a)*(1.0-gl_Color.a))); - col.rgb = min(col.rgb*gl_Color.rgb, 1.0); + col.rgb = col.rgb*gl_Color.rgb; gl_FrontColor = col; diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaF.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaF.glsl deleted file mode 100644 index 6c94f5c5a..000000000 --- a/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaF.glsl +++ /dev/null @@ -1,68 +0,0 @@ -/** - * @file avatarAlphaF.glsl - * - * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. - * $License$ - */ - -uniform sampler2D diffuseMap; -uniform sampler2DShadow shadowMap0; -uniform sampler2DShadow shadowMap1; -uniform sampler2DShadow shadowMap2; -uniform sampler2DShadow shadowMap3; -uniform sampler2D noiseMap; - -uniform mat4 shadow_matrix[4]; -uniform vec4 shadow_clip; - -vec3 atmosLighting(vec3 light); -vec3 scaleSoftClip(vec3 light); - -varying vec3 vary_ambient; -varying vec3 vary_directional; -varying vec4 vary_position; -varying vec3 vary_normal; - -void main() -{ - float shadow = 1.0; - vec4 pos = vary_position; - vec3 norm = normalize(vary_normal); - - vec3 nz = texture2D(noiseMap, gl_FragCoord.xy/128.0).xyz; - - if (pos.z > -shadow_clip.w) - { - - if (pos.z < -shadow_clip.z) - { - vec4 lpos = shadow_matrix[3]*pos; - shadow = shadow2DProj(shadowMap3, lpos).x; - } - else if (pos.z < -shadow_clip.y) - { - vec4 lpos = shadow_matrix[2]*pos; - shadow = shadow2DProj(shadowMap2, lpos).x; - } - else if (pos.z < -shadow_clip.x) - { - vec4 lpos = shadow_matrix[1]*pos; - shadow = shadow2DProj(shadowMap1, lpos).x; - } - else - { - vec4 lpos = shadow_matrix[0]*pos; - shadow = shadow2DProj(shadowMap0, lpos).x; - } - } - - - vec4 col = vec4(vary_ambient + vary_directional*shadow, gl_Color.a); - vec4 color = texture2D(diffuseMap, gl_TexCoord[0].xy) * col; - - color.rgb = atmosLighting(color.rgb); - - color.rgb = scaleSoftClip(color.rgb); - - gl_FragColor = color; -} diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaV.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaV.glsl index c1988d3c7..616990560 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaV.glsl @@ -4,23 +4,53 @@ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol); mat4 getSkinnedTransform(); void calcAtmospherics(vec3 inPositionEye); float calcDirectionalLight(vec3 n, vec3 l); -float calcPointLight(vec3 v, vec3 n, vec4 lp, float la); +float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float is_pointlight); vec3 atmosAmbient(vec3 light); vec3 atmosAffectDirectionalLight(float lightIntensity); vec3 scaleDownLight(vec3 light); vec3 scaleUpLight(vec3 light); -varying vec4 vary_position; +varying vec3 vary_position; varying vec3 vary_ambient; varying vec3 vary_directional; -varying vec3 vary_normal; +varying vec3 vary_fragcoord; +varying vec3 vary_pointlight_col; + +uniform float near_clip; + +float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float fa, float is_pointlight) +{ + //get light vector + vec3 lv = lp.xyz-v; + + //get distance + float d = length(lv); + + //normalize light vector + lv *= 1.0/d; + + //distance attenuation + float dist2 = d*d/(la*la); + float da = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0); + + // spotlight coefficient. + float spot = max(dot(-ln, lv), is_pointlight); + da *= spot*spot; // GL_SPOT_EXPONENT=2 + + //angular attenuation + da *= calcDirectionalLight(n, lv); + + return da; +} void main() { @@ -40,29 +70,31 @@ void main() norm.z = dot(trans[2].xyz, gl_Normal); norm = normalize(norm); - gl_Position = gl_ProjectionMatrix * pos; - vary_position = pos; - vary_normal = norm; + vec4 frag_pos = gl_ProjectionMatrix * pos; + gl_Position = frag_pos; + + vary_position = pos.xyz; calcAtmospherics(pos.xyz); //vec4 color = calcLighting(pos.xyz, norm, gl_Color, vec4(0.)); - vec4 col; - col.a = gl_Color.a; + + vec4 col = vec4(0.0, 0.0, 0.0, gl_Color.a); + + // Collect normal lights + col.rgb += gl_LightSource[2].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[2].position, gl_LightSource[2].spotDirection.xyz, gl_LightSource[2].linearAttenuation, gl_LightSource[2].quadraticAttenuation, gl_LightSource[2].specular.a); + col.rgb += gl_LightSource[3].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[3].position, gl_LightSource[3].spotDirection.xyz, gl_LightSource[3].linearAttenuation, gl_LightSource[3].quadraticAttenuation ,gl_LightSource[3].specular.a); + col.rgb += gl_LightSource[4].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[4].position, gl_LightSource[4].spotDirection.xyz, gl_LightSource[4].linearAttenuation, gl_LightSource[4].quadraticAttenuation, gl_LightSource[4].specular.a); + col.rgb += gl_LightSource[5].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[5].position, gl_LightSource[5].spotDirection.xyz, gl_LightSource[5].linearAttenuation, gl_LightSource[5].quadraticAttenuation, gl_LightSource[5].specular.a); + col.rgb += gl_LightSource[6].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[6].position, gl_LightSource[6].spotDirection.xyz, gl_LightSource[6].linearAttenuation, gl_LightSource[6].quadraticAttenuation, gl_LightSource[6].specular.a); + col.rgb += gl_LightSource[7].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[7].position, gl_LightSource[7].spotDirection.xyz, gl_LightSource[7].linearAttenuation, gl_LightSource[7].quadraticAttenuation, gl_LightSource[7].specular.a); + vary_pointlight_col = col.rgb*gl_Color.rgb; + + col.rgb = vec3(0,0,0); + // Add windlight lights col.rgb = atmosAmbient(vec3(0.)); - col.rgb = scaleUpLight(col.rgb); - - // Collect normal lights (need to be divided by two, as we later multiply by 2) - col.rgb += gl_LightSource[2].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[2].position, gl_LightSource[2].linearAttenuation); - col.rgb += gl_LightSource[3].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[3].position, gl_LightSource[3].linearAttenuation); - col.rgb += gl_LightSource[4].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[4].position, gl_LightSource[4].linearAttenuation); - col.rgb += gl_LightSource[5].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[5].position, gl_LightSource[5].linearAttenuation); - col.rgb += gl_LightSource[6].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[6].position, gl_LightSource[6].linearAttenuation); - col.rgb += gl_LightSource[7].diffuse.rgb*calcPointLight(pos.xyz, norm, gl_LightSource[7].position, gl_LightSource[7].linearAttenuation); - col.rgb += gl_LightSource[1].diffuse.rgb*calcDirectionalLight(norm, gl_LightSource[1].position.xyz); - col.rgb = scaleDownLight(col.rgb); vary_ambient = col.rgb*gl_Color.rgb; vary_directional = gl_Color.rgb*atmosAffectDirectionalLight(max(calcDirectionalLight(norm, gl_LightSource[0].position.xyz), (1.0-gl_Color.a)*(1.0-gl_Color.a))); @@ -72,7 +104,8 @@ void main() gl_FrontColor = col; gl_FogFragCoord = pos.z; - + + vary_fragcoord.xyz = frag_pos.xyz + vec3(0,0,near_clip); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl index b5daef03e..e2a36719c 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl @@ -4,11 +4,12 @@ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 uniform sampler2D diffuseMap; varying vec3 vary_normal; -varying vec4 vary_position; void main() { @@ -21,7 +22,7 @@ void main() gl_FragData[0] = vec4(diff.rgb, 0.0); gl_FragData[1] = vec4(0,0,0,0); - gl_FragData[2] = vec4(normalize(vary_normal), 0.0); - gl_FragData[3] = vary_position; + vec3 nvn = normalize(vary_normal); + gl_FragData[2] = vec4(nvn.xy * 0.5 + 0.5, nvn.z, 0.0); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarShadowF.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarShadowF.glsl index 3f60d4a71..61574d0be 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/avatarShadowF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/avatarShadowF.glsl @@ -4,13 +4,15 @@ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 uniform sampler2D diffuseMap; void main() { - //gl_FragColor = vec4(1,1,1,gl_Color.a * texture2D(diffuseMap, gl_TexCoord[0].xy)); //This should not compile! - gl_FragColor = vec4(1,1,1,texture2D(diffuseMap, gl_TexCoord[0].xy).a * gl_Color.a); + //gl_FragColor = vec4(1,1,1,gl_Color.a * texture2D(diffuseMap, gl_TexCoord[0].xy).a); + gl_FragColor = vec4(1,1,1,1); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarShadowV.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarShadowV.glsl index 14da6b1ad..49ddd2b19 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/avatarShadowV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/avatarShadowV.glsl @@ -4,6 +4,8 @@ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 mat4 getSkinnedTransform(); @@ -28,8 +30,7 @@ void main() norm = normalize(norm); pos = gl_ProjectionMatrix * pos; - //smash geometry against near clip plane - pos.z = max(pos.z, -1.0); + pos.z = max(pos.z, -pos.w+0.01); gl_Position = pos; gl_FrontColor = gl_Color; diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarV.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarV.glsl index 12a7ff7f2..3465cef2b 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/avatarV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/avatarV.glsl @@ -4,13 +4,14 @@ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 mat4 getSkinnedTransform(); attribute vec4 weight; varying vec3 vary_normal; -varying vec4 vary_position; void main() { @@ -30,7 +31,6 @@ void main() norm.z = dot(trans[2].xyz, gl_Normal); norm = normalize(norm); - vary_position = pos; vary_normal = norm; gl_Position = gl_ProjectionMatrix * pos; diff --git a/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl index 3c6700a87..d04bfb3ad 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl @@ -4,45 +4,86 @@ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 #extension GL_ARB_texture_rectangle : enable -uniform sampler2DRect positionMap; +uniform sampler2DRect depthMap; uniform sampler2DRect normalMap; uniform sampler2DRect lightMap; +uniform float dist_factor; uniform float blur_size; uniform vec2 delta; -uniform vec3 kern[32]; -uniform int kern_length; +uniform vec3 kern[4]; uniform float kern_scale; varying vec2 vary_fragcoord; +uniform mat4 inv_proj; +uniform vec2 screen_res; + +vec4 getPosition(vec2 pos_screen) +{ + float depth = texture2DRect(depthMap, pos_screen.xy).a; + vec2 sc = pos_screen.xy*2.0; + sc /= screen_res; + sc -= vec2(1.0,1.0); + vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); + vec4 pos = inv_proj * ndc; + pos /= pos.w; + pos.w = 1.0; + return pos; +} + void main() { - vec3 norm = texture2DRect(normalMap, vary_fragcoord.xy).xyz; - vec3 pos = texture2DRect(positionMap, vary_fragcoord.xy).xyz; - vec2 ccol = texture2DRect(lightMap, vary_fragcoord.xy).rg; + vec2 tc = vary_fragcoord.xy; + vec3 norm = texture2DRect(normalMap, tc).xyz; + norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm + vec3 pos = getPosition(tc).xyz; + vec4 ccol = texture2DRect(lightMap, tc).rgba; vec2 dlt = kern_scale * delta / (1.0+norm.xy*norm.xy); + dlt /= max(-pos.z*dist_factor, 1.0); vec2 defined_weight = kern[0].xy; // special case the first (centre) sample's weight in the blur; we have to sample it anyway so we get it for 'free' - vec2 col = defined_weight * ccol; - - for (int i = 1; i < kern_length; i++) + vec4 col = defined_weight.xyxx * ccol; + + // relax tolerance according to distance to avoid speckling artifacts, as angles and distances are a lot more abrupt within a small screen area at larger distances + float pointplanedist_tolerance_pow2 = pos.z*pos.z*0.00005; + + // perturb sampling origin slightly in screen-space to hide edge-ghosting artifacts where smoothing radius is quite large + //This causes some pretty nasty artifacting, so disabling for now. + //tc += ( (mod(tc.x+tc.y,2) - 0.5) * kern[1].z * dlt * 0.5 ); + + for (int i = 1; i < 4; i++) { - vec2 tc = vary_fragcoord.xy + kern[i].z*dlt; - vec3 samppos = texture2DRect(positionMap, tc).xyz; + vec2 samptc = tc + kern[i].z*dlt; + vec3 samppos = getPosition(samptc).xyz; float d = dot(norm.xyz, samppos.xyz-pos.xyz);// dist from plane - if (d*d <= 0.003) + if (d*d <= pointplanedist_tolerance_pow2) { - col += texture2DRect(lightMap, tc).rg*kern[i].xy; + col += texture2DRect(lightMap, samptc)*kern[i].xyxx; + defined_weight += kern[i].xy; + } + } + for (int i = 1; i < 4; i++) + { + vec2 samptc = tc - kern[i].z*dlt; + vec3 samppos = getPosition(samptc).xyz; + float d = dot(norm.xyz, samppos.xyz-pos.xyz);// dist from plane + if (d*d <= pointplanedist_tolerance_pow2) + { + col += texture2DRect(lightMap, samptc)*kern[i].xyxx; defined_weight += kern[i].xy; } } - col /= defined_weight; - - gl_FragColor = vec4(col.r, col.g, 0.0, 1.0); + col /= defined_weight.xyxx; + col.y *= col.y; + + gl_FragColor = col; } + diff --git a/indra/newview/app_settings/shaders/class1/deferred/blurLightV.glsl b/indra/newview/app_settings/shaders/class1/deferred/blurLightV.glsl index b7f07e570..3f2d7d7b1 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/blurLightV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/blurLightV.glsl @@ -4,6 +4,8 @@ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 varying vec2 vary_fragcoord; uniform vec2 screen_res; diff --git a/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl b/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl index a8712bc8c..7a423f394 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl @@ -4,6 +4,8 @@ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 uniform sampler2D diffuseMap; uniform sampler2D bumpMap; @@ -11,19 +13,19 @@ uniform sampler2D bumpMap; varying vec3 vary_mat0; varying vec3 vary_mat1; varying vec3 vary_mat2; -varying vec4 vary_position; void main() { - vec3 col = texture2D(diffuseMap, gl_TexCoord[0].xy).rgb; + vec3 col = gl_Color.rgb * texture2D(diffuseMap, gl_TexCoord[0].xy).rgb; vec3 norm = texture2D(bumpMap, gl_TexCoord[0].xy).rgb * 2.0 - 1.0; vec3 tnorm = vec3(dot(norm,vary_mat0), - dot(norm,vary_mat1), - dot(norm,vary_mat2)); + dot(norm,vary_mat1), + dot(norm,vary_mat2)); - gl_FragData[0].rgb = gl_Color.rgb*col; - gl_FragData[1] = vec4(col*(gl_Color.a*1.5), gl_Color.a); - gl_FragData[2] = vec4(normalize(tnorm), 0.0); - gl_FragData[3] = vary_position; + gl_FragData[0] = vec4(col, 0.0); + gl_FragData[1] = gl_Color.aaaa; // spec + //gl_FragData[1] = vec4(vec3(gl_Color.a), gl_Color.a+(1.0-gl_Color.a)*gl_Color.a); // spec - from former class3 - maybe better, but not so well tested + vec3 nvn = normalize(tnorm); + gl_FragData[2] = vec4(nvn.xy * 0.5 + 0.5, nvn.z, 0.0); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/bumpV.glsl b/indra/newview/app_settings/shaders/class1/deferred/bumpV.glsl index ba180922c..c83f781e2 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/bumpV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/bumpV.glsl @@ -4,11 +4,12 @@ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 varying vec3 vary_mat0; varying vec3 vary_mat1; varying vec3 vary_mat2; -varying vec4 vary_position; void main() { @@ -16,8 +17,6 @@ void main() gl_Position = ftransform(); gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; - vary_position = gl_ModelViewMatrix * gl_Vertex; - vec3 n = normalize(gl_NormalMatrix * gl_Normal); vec3 b = normalize(gl_NormalMatrix * gl_MultiTexCoord2.xyz); vec3 t = cross(b, n); diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl index f2ba2df69..451195f97 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl @@ -4,17 +4,19 @@ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 uniform sampler2D diffuseMap; varying vec3 vary_normal; -varying vec4 vary_position; void main() { - vec3 col = texture2D(diffuseMap, gl_TexCoord[0].xy).rgb; - gl_FragData[0] = vec4(gl_Color.rgb*col, 1.0); - gl_FragData[1] = vec4(col*(gl_Color.a*1.5), gl_Color.a); - gl_FragData[2] = vec4(normalize(vary_normal), 0.0); - gl_FragData[3] = vary_position; + vec3 col = gl_Color.rgb * texture2D(diffuseMap, gl_TexCoord[0].xy).rgb; + gl_FragData[0] = vec4(col, 0.0); + gl_FragData[1] = gl_Color.aaaa; // spec + //gl_FragData[1] = vec4(vec3(gl_Color.a), gl_Color.a+(1.0-gl_Color.a)*gl_Color.a); // spec - from former class3 - maybe better, but not so well tested + vec3 nvn = normalize(vary_normal); + gl_FragData[2] = vec4(nvn.xy * 0.5 + 0.5, nvn.z, 0.0); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl index 3413a7f9d..af0314a75 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl @@ -2,20 +2,19 @@ * @file diffuseV.glsl * * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. - * $License$ + * $/LicenseInfo$ */ + +#version 120 varying vec3 vary_normal; -varying vec4 vary_position; void main() { //transform vertex - gl_Position = ftransform(); + gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; - vary_position = gl_ModelViewMatrix * gl_Vertex; - vary_normal = normalize(gl_NormalMatrix * gl_Normal); gl_FrontColor = gl_Color; diff --git a/indra/newview/app_settings/shaders/class1/deferred/fullbrightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/fullbrightF.glsl index 2a811c589..342987739 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/fullbrightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/fullbrightF.glsl @@ -1,21 +1,18 @@ /** * @file fullbrightF.glsl * - * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. - * $License$ + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $/LicenseInfo$ */ + +#version 120 #extension GL_ARB_texture_rectangle : enable uniform sampler2D diffuseMap; -uniform sampler2DShadow shadowMap0; -uniform sampler2DShadow shadowMap1; -uniform sampler2DShadow shadowMap2; -uniform sampler2DShadow shadowMap3; +uniform sampler2DRect depthMap; uniform sampler2D noiseMap; -uniform sampler2DRect positionMap; -uniform mat4 shadow_matrix[4]; uniform vec4 shadow_clip; uniform vec2 screen_res; @@ -28,14 +25,27 @@ varying vec4 vary_position; varying vec3 vary_normal; varying vec3 vary_fragcoord; -uniform float alpha_soften; +uniform mat4 inv_proj; + +vec4 getPosition(vec2 pos_screen) +{ + float depth = texture2DRect(depthMap, pos_screen.xy).a; + vec2 sc = pos_screen.xy*2.0; + sc /= screen_res; + sc -= vec2(1.0,1.0); + vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); + vec4 pos = inv_proj * ndc; + pos /= pos.w; + pos.w = 1.0; + return pos; +} void main() { vec2 frag = vary_fragcoord.xy/vary_fragcoord.z*0.5+0.5; frag *= screen_res; - vec3 samp_pos = texture2DRect(positionMap, frag).xyz; + vec3 samp_pos = getPosition(frag).xyz; float shadow = 1.0; vec4 pos = vary_position; @@ -46,15 +56,6 @@ void main() color.rgb = fullbrightScaleSoftClip(color.rgb); - if (samp_pos.z != 0.0) - { - float dist_factor = alpha_soften; - float a = gl_Color.a; - a *= a; - dist_factor *= 1.0/(1.0-a); - color.a *= min((pos.z-samp_pos.z)*dist_factor, 1.0); - } - //gl_FragColor = gl_Color; gl_FragColor = color; //gl_FragColor = vec4(1,0,1,1); diff --git a/indra/newview/app_settings/shaders/class1/deferred/fullbrightV.glsl b/indra/newview/app_settings/shaders/class1/deferred/fullbrightV.glsl index 6381a1ced..94f653541 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/fullbrightV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/fullbrightV.glsl @@ -4,6 +4,8 @@ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 void calcAtmospherics(vec3 inPositionEye); @@ -12,12 +14,12 @@ vec3 atmosAffectDirectionalLight(float lightIntensity); vec3 scaleDownLight(vec3 light); vec3 scaleUpLight(vec3 light); -varying vec4 vary_position; varying vec3 vary_ambient; varying vec3 vary_directional; varying vec3 vary_normal; varying vec3 vary_fragcoord; uniform float near_clip; +varying vec4 vary_position; void main() { diff --git a/indra/newview/app_settings/shaders/class1/deferred/giF.glsl b/indra/newview/app_settings/shaders/class1/deferred/giF.glsl new file mode 100644 index 000000000..75b555e8a --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/giF.glsl @@ -0,0 +1,168 @@ +/** + * @file giF.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $/LicenseInfo$ + */ + +#version 120 + +#extension GL_ARB_texture_rectangle : enable + +uniform sampler2DRect depthMap; +uniform sampler2DRect normalMap; +uniform sampler2D noiseMap; + +uniform sampler2D diffuseGIMap; +uniform sampler2D normalGIMap; +uniform sampler2D depthGIMap; + +uniform sampler2D lightFunc; + +// Inputs +varying vec2 vary_fragcoord; + +uniform vec2 screen_res; + +uniform mat4 inv_proj; +uniform mat4 gi_mat; //gPipeline.mGIMatrix - eye space to sun space +uniform mat4 gi_mat_proj; //gPipeline.mGIMatrixProj - eye space to projected sun space +uniform mat4 gi_norm_mat; //gPipeline.mGINormalMatrix - eye space normal to sun space normal matrix +uniform mat4 gi_inv_proj; //gPipeline.mGIInvProj - projected sun space to sun space +uniform float gi_radius; +uniform float gi_intensity; +uniform int gi_samples; +uniform vec2 gi_kern[25]; +uniform vec2 gi_scale; +uniform vec3 gi_quad; +uniform vec3 gi_spec; +uniform float gi_direction_weight; +uniform float gi_light_offset; + +vec4 getPosition(vec2 pos_screen) +{ + float depth = texture2DRect(depthMap, pos_screen.xy).a; + vec2 sc = pos_screen.xy*2.0; + sc /= screen_res; + sc -= vec2(1.0,1.0); + vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); + vec4 pos = inv_proj * ndc; + pos /= pos.w; + pos.w = 1.0; + return pos; +} + +vec4 getGIPosition(vec2 gi_tc) +{ + float depth = texture2D(depthGIMap, gi_tc).a; + vec2 sc = gi_tc*2.0; + sc -= vec2(1.0, 1.0); + vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); + vec4 pos = gi_inv_proj*ndc; + pos.xyz /= pos.w; + pos.w = 1.0; + return pos; +} + +vec3 giAmbient(vec3 pos, vec3 norm) +{ + vec4 gi_c = gi_mat_proj * vec4(pos, 1.0); + gi_c.xyz /= gi_c.w; + + vec4 gi_pos = gi_mat*vec4(pos,1.0); + vec3 gi_norm = (gi_norm_mat*vec4(norm,1.0)).xyz; + gi_norm = normalize(gi_norm); + + vec2 tcx = gi_norm.xy; + vec2 tcy = gi_norm.yx; + + vec4 eye_pos = gi_mat*vec4(0,0,0,1.0); + + vec3 eye_dir = normalize(gi_pos.xyz-eye_pos.xyz/eye_pos.w); + + //vec3 eye_dir = vec3(0,0,-1); + //eye_dir = (gi_norm_mat*vec4(eye_dir, 1.0)).xyz; + //eye_dir = normalize(eye_dir); + + //float round_x = gi_scale.x; + //float round_y = gi_scale.y; + + vec3 debug = texture2D(normalGIMap, gi_c.xy).rgb*0.5+0.5; + debug.xz = vec2(0.0,0.0); + //debug = fract(debug); + + float round_x = 1.0/64.0; + float round_y = 1.0/64.0; + + //gi_c.x = floor(gi_c.x/round_x+0.5)*round_x; + //gi_c.y = floor(gi_c.y/round_y+0.5)*round_y; + + float fda = 0.0; + vec3 fdiff = vec3(0,0,0); + + vec3 rcol = vec3(0,0,0); + + float fsa = 0.0; + + for (int i = -1; i < 2; i+=2 ) + { + for (int j = -1; j < 2; j+=2) + { + vec2 tc = vec2(i, j)*0.75; + vec3 nz = texture2D(noiseMap, vary_fragcoord.xy/128.0+tc*0.5).xyz; + //tc += gi_norm.xy*nz.z; + tc += nz.xy*2.0; + tc /= gi_samples; + tc += gi_c.xy; + + vec3 lnorm = -normalize(texture2D(normalGIMap, tc.xy).xyz*2.0-1.0); + vec3 lpos = getGIPosition(tc.xy).xyz; + + vec3 at = lpos-gi_pos.xyz; + float dist = dot(at,at); + float da = clamp(1.0/(gi_spec.x*dist), 0.0, 1.0); + + if (da > 0.0) + { + //add angular attenuation + vec3 ldir = at; + float ang_atten = clamp(dot(ldir, gi_norm), 0.0, 1.0); + + float ld = -dot(ldir, lnorm); + + if (ang_atten > 0.0 && ld < 0.0) + { + vec3 diff = texture2D(diffuseGIMap, tc.xy).xyz; + da = da*ang_atten; + fda += da; + fdiff += diff*da; + } + } + } + } + + fdiff /= max(gi_spec.y*fda, gi_quad.z); + fdiff = clamp(fdiff, vec3(0), vec3(1)); + + vec3 ret = fda*fdiff; + //ret = ret*ret*gi_quad.x+ret*gi_quad.y+gi_quad.z; + + //fda *= nz.z; + + //rcol.rgb *= gi_intensity; + //return rcol.rgb+vary_AmblitColor.rgb*0.25; + //return vec4(debug, 0.0); + //return vec4(fda*fdiff, 0.0); + return clamp(ret,vec3(0.0), vec3(1.0)); + //return debug.xyz; +} + +void main() +{ + vec2 pos_screen = vary_fragcoord.xy; + vec4 pos = getPosition(pos_screen); + vec3 norm = texture2DRect(normalMap, pos_screen).xyz; + norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm + + gl_FragData[0].xyz = giAmbient(pos, norm); +} diff --git a/indra/newview/app_settings/shaders/class1/deferred/giV.glsl b/indra/newview/app_settings/shaders/class1/deferred/giV.glsl new file mode 100644 index 000000000..8dc1410ea --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/giV.glsl @@ -0,0 +1,24 @@ +/** + * @file giV.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $/LicenseInfo$ + */ + +#version 120 + +varying vec2 vary_fragcoord; + +uniform vec2 screen_res; + +void main() +{ + //transform vertex + gl_Position = ftransform(); + vec4 pos = gl_ModelViewProjectionMatrix * gl_Vertex; + vary_fragcoord = (pos.xy * 0.5 + 0.5)*screen_res; + vec4 tex = gl_MultiTexCoord0; + tex.w = 1.0; + + gl_FrontColor = gl_Color; +} diff --git a/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl b/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl index 4e3e635f1..6b3bfcf2a 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl @@ -4,18 +4,17 @@ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 uniform sampler2D diffuseMap; uniform sampler2D normalMap; uniform sampler2D specularMap; -varying vec4 vary_position; - void main() { vec4 col = texture2D(diffuseMap, gl_TexCoord[0].xy); - gl_FragData[0] = vec4(col.rgb, col.a <= 0.5 ? 0.0 : 0.005); + gl_FragData[0] = vec4(col.rgb, col.a * 0.005); gl_FragData[1] = texture2D(specularMap, gl_TexCoord[0].xy); - gl_FragData[2] = vec4(texture2D(normalMap, gl_TexCoord[0].xy).xyz, vary_position.z); - gl_FragData[3] = vary_position; + gl_FragData[2] = vec4(texture2D(normalMap, gl_TexCoord[0].xy).xyz, 0.0); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/impostorV.glsl b/indra/newview/app_settings/shaders/class1/deferred/impostorV.glsl index 9c5ae3154..d90c4478c 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/impostorV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/impostorV.glsl @@ -4,8 +4,8 @@ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. * $License$ */ - -varying vec4 vary_position; + +#version 120 void main() { @@ -13,7 +13,5 @@ void main() gl_Position = ftransform(); gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; - vary_position = gl_ModelViewMatrix * gl_Vertex; - gl_FrontColor = gl_Color; } diff --git a/indra/newview/app_settings/shaders/class1/deferred/luminanceF.glsl b/indra/newview/app_settings/shaders/class1/deferred/luminanceF.glsl new file mode 100644 index 000000000..78df54d5d --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/luminanceF.glsl @@ -0,0 +1,17 @@ +/** + * @file luminanceF.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $/LicenseInfo$ + */ + +#version 120 + +uniform sampler2DRect diffuseMap; + +varying vec2 vary_fragcoord; + +void main() +{ + gl_FragColor = texture2DRect(diffuseMap, vary_fragcoord.xy); +} diff --git a/indra/newview/app_settings/shaders/class1/deferred/luminanceV.glsl b/indra/newview/app_settings/shaders/class1/deferred/luminanceV.glsl new file mode 100644 index 000000000..0c820bfc6 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/luminanceV.glsl @@ -0,0 +1,23 @@ +/** + * @file giV.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $/LicenseInfo$ + */ + +#version 120 + + +varying vec2 vary_fragcoord; + +uniform vec2 screen_res; + +void main() +{ + //transform vertex + gl_Position = ftransform(); + vec4 pos = gl_ModelViewProjectionMatrix * gl_Vertex; + vary_fragcoord = (pos.xy * 0.5 + 0.5)*screen_res; + + gl_FrontColor = gl_Color; +} diff --git a/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl index c8248b294..42f5f3dba 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl @@ -5,15 +5,18 @@ * $License$ */ +#version 120 + #extension GL_ARB_texture_rectangle : enable +uniform sampler2DRect depthMap; uniform sampler2DRect diffuseRect; uniform sampler2DRect specularRect; -uniform sampler2DRect positionMap; uniform sampler2DRect normalMap; uniform samplerCube environmentMap; -uniform sampler2DRect lightMap; uniform sampler2D noiseMap; +uniform sampler2D lightFunc; + uniform vec3 env_mat[3]; uniform float sun_wash; @@ -23,24 +26,50 @@ uniform int light_count; uniform vec4 light[16]; uniform vec4 light_col[16]; -varying vec3 vary_fragcoord; +varying vec4 vary_fragcoord; uniform vec2 screen_res; +uniform float far_z; + +uniform mat4 inv_proj; + +vec4 getPosition(vec2 pos_screen) +{ + float depth = texture2DRect(depthMap, pos_screen.xy).a; + vec2 sc = pos_screen.xy*2.0; + sc /= screen_res; + sc -= vec2(1.0,1.0); + vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); + vec4 pos = inv_proj * ndc; + pos /= pos.w; + pos.w = 1.0; + return pos; +} + void main() { vec2 frag = (vary_fragcoord.xy*0.5+0.5)*screen_res; - vec3 pos = texture2DRect(positionMap, frag.xy).xyz; - vec3 norm = normalize(texture2DRect(normalMap, frag.xy).xyz); + vec3 pos = getPosition(frag.xy).xyz; + if (pos.z < far_z) + { + discard; + } + + vec3 norm = texture2DRect(normalMap, frag.xy).xyz; + norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm + norm = normalize(norm); vec4 spec = texture2DRect(specularRect, frag.xy); vec3 diff = texture2DRect(diffuseRect, frag.xy).rgb; float noise = texture2D(noiseMap, frag.xy/128.0).b; vec3 out_col = vec3(0,0,0); + vec3 npos = normalize(-pos); for (int i = 0; i < light_count; ++i) { vec3 lv = light[i].xyz-pos; float dist2 = dot(lv,lv); - if (dist2 > light[i].w) + dist2 /= light[i].w; + if (dist2 > 1.0) { continue; } @@ -55,30 +84,31 @@ void main() da = dot(norm, lv); float fa = light_col[i].a+1.0; - float dist_atten = clamp(1.0-(dist2-light[i].w*(1.0-fa))/(light[i].w*fa), 0.0, 1.0); + float dist_atten = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0); dist_atten *= noise; float lit = da * dist_atten; vec3 col = light_col[i].rgb*lit*diff; + //vec3 col = vec3(dist2, light_col[i].a, lit); if (spec.a > 0.0) { - vec3 ref = reflect(normalize(pos), norm); - float sa = dot(ref,lv); - sa = max(sa, 0.0); - sa = pow(sa, 128.0 * spec.a*spec.a/dist_atten)*min(dist_atten*4.0, 1.0); - sa *= noise; - col += da*sa*light_col[i].rgb*spec.rgb; + //vec3 ref = dot(pos+lv, norm); + + float sa = dot(normalize(lv+npos),norm); + + if (sa > 0.0) + { + sa = texture2D(lightFunc,vec2(sa, spec.a)).a * min(dist_atten*4.0, 1.0); + sa *= noise; + col += da*sa*light_col[i].rgb*spec.rgb; + } } out_col += col; } - //attenuate point light contribution by SSAO component - out_col *= texture2DRect(lightMap, frag.xy).g; - - if (dot(out_col, out_col) <= 0.0) { discard; diff --git a/indra/newview/app_settings/shaders/class1/deferred/multiPointLightV.glsl b/indra/newview/app_settings/shaders/class1/deferred/multiPointLightV.glsl new file mode 100644 index 000000000..2e3e84dd1 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/multiPointLightV.glsl @@ -0,0 +1,20 @@ +/** + * @file multiPointLightV.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $/LicenseInfo$ + */ + +#version 120 + +varying vec4 vary_fragcoord; + +void main() +{ + //transform vertex + vec4 pos = gl_ModelViewProjectionMatrix * gl_Vertex; + vary_fragcoord = pos; + + gl_Position = pos; + gl_FrontColor = gl_Color; +} diff --git a/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl new file mode 100644 index 000000000..a9f03f761 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl @@ -0,0 +1,225 @@ +/** + * @file multiSpotLightF.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $/LicenseInfo$ + */ + +#version 120 + +//class 1 -- no shadows + +#extension GL_ARB_texture_rectangle : enable + +uniform sampler2DRect diffuseRect; +uniform sampler2DRect specularRect; +uniform sampler2DRect depthMap; +uniform sampler2DRect normalMap; +uniform samplerCube environmentMap; +uniform sampler2D noiseMap; +uniform sampler2D lightFunc; +uniform sampler2D projectionMap; + +uniform mat4 proj_mat; //screen space to light space +uniform float proj_near; //near clip for projection +uniform vec3 proj_p; //plane projection is emitting from (in screen space) +uniform vec3 proj_n; +uniform float proj_focus; //distance from plane to begin blurring +uniform float proj_lod; //(number of mips in proj map) +uniform float proj_range; //range between near clip and far clip plane of projection +uniform float proj_ambient_lod; +uniform float proj_ambiance; +uniform float near_clip; +uniform float far_clip; + +uniform vec3 proj_origin; //origin of projection to be used for angular attenuation +uniform float sun_wash; +uniform int proj_shadow_idx; +uniform float shadow_fade; + +varying vec4 vary_light; + +varying vec4 vary_fragcoord; +uniform vec2 screen_res; + +uniform mat4 inv_proj; + +vec4 texture2DLodSpecular(sampler2D projectionMap, vec2 tc, float lod) +{ + vec4 ret = texture2DLod(projectionMap, tc, lod); + + vec2 dist = tc-vec2(0.5); + + float det = max(1.0-lod/(proj_lod*0.5), 0.0); + + float d = dot(dist,dist); + + ret *= min(clamp((0.25-d)/0.25, 0.0, 1.0)+det, 1.0); + + return ret; +} + +vec4 texture2DLodDiffuse(sampler2D projectionMap, vec2 tc, float lod) +{ + vec4 ret = texture2DLod(projectionMap, tc, 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); + + float edge = 0.25*det; + + ret *= clamp(d/edge, 0.0, 1.0); + + return ret; +} + +vec4 texture2DLodAmbient(sampler2D projectionMap, vec2 tc, float lod) +{ + vec4 ret = texture2DLod(projectionMap, tc, lod); + + vec2 dist = tc-vec2(0.5); + + float d = dot(dist,dist); + + ret *= min(clamp((0.25-d)/0.25, 0.0, 1.0), 1.0); + + return ret; +} + + +vec4 getPosition(vec2 pos_screen) +{ + float depth = texture2DRect(depthMap, pos_screen.xy).a; + vec2 sc = pos_screen.xy*2.0; + sc /= screen_res; + sc -= vec2(1.0,1.0); + vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); + vec4 pos = inv_proj * ndc; + pos /= pos.w; + pos.w = 1.0; + return pos; +} + +void main() +{ + vec4 frag = vary_fragcoord; + frag.xyz /= frag.w; + frag.xyz = frag.xyz*0.5+0.5; + frag.xy *= screen_res; + + vec3 pos = getPosition(frag.xy).xyz; + vec3 lv = vary_light.xyz-pos.xyz; + float dist2 = dot(lv,lv); + dist2 /= vary_light.w; + if (dist2 > 1.0) + { + discard; + } + + vec3 norm = texture2DRect(normalMap, frag.xy).xyz*2.0-1.0; + + norm = normalize(norm); + float l_dist = -dot(lv, proj_n); + + vec4 proj_tc = (proj_mat * vec4(pos.xyz, 1.0)); + if (proj_tc.z < 0.0) + { + discard; + } + + proj_tc.xyz /= proj_tc.w; + + float fa = gl_Color.a+1.0; + float dist_atten = min(1.0-(dist2-1.0*(1.0-fa))/fa, 1.0); + if (dist_atten <= 0.0) + { + discard; + } + + lv = proj_origin-pos.xyz; + lv = normalize(lv); + float da = dot(norm, lv); + + vec3 col = vec3(0,0,0); + + vec3 diff_tex = texture2DRect(diffuseRect, frag.xy).rgb; + + float noise = texture2D(noiseMap, frag.xy/128.0).b; + if (proj_tc.z > 0.0 && + proj_tc.x < 1.0 && + proj_tc.y < 1.0 && + proj_tc.x > 0.0 && + proj_tc.y > 0.0) + { + float lit = 0.0; + float amb_da = proj_ambiance; + + if (da > 0.0) + { + float diff = clamp((l_dist-proj_focus)/proj_range, 0.0, 1.0); + float lod = diff * proj_lod; + + vec4 plcol = texture2DLodDiffuse(projectionMap, proj_tc.xy, lod); + + vec3 lcol = gl_Color.rgb * plcol.rgb * plcol.a; + + lit = da * dist_atten * noise; + + col = lcol*lit*diff_tex; + amb_da += (da*0.5)*proj_ambiance; + } + + //float diff = clamp((proj_range-proj_focus)/proj_range, 0.0, 1.0); + vec4 amb_plcol = texture2DLodAmbient(projectionMap, proj_tc.xy, proj_lod); + + amb_da += (da*da*0.5+0.5)*proj_ambiance; + + amb_da *= dist_atten * noise; + + amb_da = min(amb_da, 1.0-lit); + + col += amb_da*gl_Color.rgb*diff_tex.rgb*amb_plcol.rgb*amb_plcol.a; + } + + + vec4 spec = texture2DRect(specularRect, frag.xy); + if (spec.a > 0.0) + { + vec3 ref = reflect(normalize(pos), norm); + + //project from point pos in direction ref to plane proj_p, proj_n + vec3 pdelta = proj_p-pos; + float ds = dot(ref, proj_n); + + if (ds < 0.0) + { + vec3 pfinal = pos + ref * dot(pdelta, proj_n)/ds; + + vec4 stc = (proj_mat * vec4(pfinal.xyz, 1.0)); + + if (stc.z > 0.0) + { + stc.xy /= stc.w; + + float fatten = clamp(spec.a*spec.a+spec.a*0.5, 0.25, 1.0); + + stc.xy = (stc.xy - vec2(0.5)) * fatten + vec2(0.5); + + if (stc.x < 1.0 && + stc.y < 1.0 && + stc.x > 0.0 && + stc.y > 0.0) + { + vec4 scol = texture2DLodSpecular(projectionMap, stc.xy, proj_lod-spec.a*proj_lod); + col += dist_atten*scol.rgb*gl_Color.rgb*scol.a*spec.rgb; + } + } + } + } + + gl_FragColor.rgb = col; + gl_FragColor.a = 0.0; +} diff --git a/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl index 68f376d69..22ed9dcd4 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl @@ -1,41 +1,64 @@ /** * @file pointLightF.glsl * - * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. - * $License$ + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $/LicenseInfo$ */ + + #version 120 #extension GL_ARB_texture_rectangle : enable uniform sampler2DRect diffuseRect; uniform sampler2DRect specularRect; -uniform sampler2DRect positionMap; uniform sampler2DRect normalMap; uniform samplerCube environmentMap; -uniform sampler2DRect lightMap; uniform sampler2D noiseMap; +uniform sampler2D lightFunc; +uniform sampler2DRect depthMap; uniform vec3 env_mat[3]; uniform float sun_wash; varying vec4 vary_light; -varying vec3 vary_fragcoord; +varying vec4 vary_fragcoord; uniform vec2 screen_res; +uniform mat4 inv_proj; +uniform vec4 viewport; + +vec4 getPosition(vec2 pos_screen) +{ + float depth = texture2DRect(depthMap, pos_screen.xy).a; + vec2 sc = (pos_screen.xy-viewport.xy)*2.0; + sc /= viewport.zw; + sc -= vec2(1.0,1.0); + vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); + vec4 pos = inv_proj * ndc; + pos /= pos.w; + pos.w = 1.0; + return pos; +} + void main() { - vec2 frag = vary_fragcoord.xy/vary_fragcoord.z*0.5+0.5; - frag *= screen_res; - vec3 pos = texture2DRect(positionMap, frag).xyz; + vec4 frag = vary_fragcoord; + frag.xyz /= frag.w; + frag.xyz = frag.xyz*0.5+0.5; + frag.xy *= screen_res; + + vec3 pos = getPosition(frag.xy).xyz; vec3 lv = vary_light.xyz-pos; float dist2 = dot(lv,lv); - if (dist2 > vary_light.w) + dist2 /= vary_light.w; + if (dist2 > 1.0) { discard; } - vec3 norm = texture2DRect(normalMap, frag).xyz; + vec3 norm = texture2DRect(normalMap, frag.xy).xyz; + norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm float da = dot(norm, lv); if (da < 0.0) { @@ -46,35 +69,32 @@ void main() lv = normalize(lv); da = dot(norm, lv); - float noise = texture2D(noiseMap, frag/128.0).b; + float noise = texture2D(noiseMap, frag.xy/128.0).b; - vec3 col = texture2DRect(diffuseRect, frag).rgb; + vec3 col = texture2DRect(diffuseRect, frag.xy).rgb; float fa = gl_Color.a+1.0; - float dist_atten = clamp(1.0-(dist2-vary_light.w*(1.0-fa))/(vary_light.w*fa), 0.0, 1.0); + float dist_atten = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0); float lit = da * dist_atten * noise; col = gl_Color.rgb*lit*col; - vec4 spec = texture2DRect(specularRect, frag); + vec4 spec = texture2DRect(specularRect, frag.xy); if (spec.a > 0.0) { - vec3 ref = reflect(normalize(pos), norm); - float sa = dot(ref,lv); - sa = max(sa, 0.0); - sa = pow(sa, 128.0 * spec.a*spec.a/dist_atten)*min(dist_atten*4.0, 1.0); - sa *= noise; - col += da*sa*gl_Color.rgb*spec.rgb; + float sa = dot(normalize(lv-normalize(pos)),norm); + if (sa > 0.0) + { + sa = texture2D(lightFunc, vec2(sa, spec.a)).a * min(dist_atten*4.0, 1.0); + sa *= noise; + col += da*sa*gl_Color.rgb*spec.rgb; + } } - //attenuate point light contribution by SSAO component - col *= texture2DRect(lightMap, frag.xy).g; - if (dot(col, col) <= 0.0) { discard; } - gl_FragColor.rgb = col; gl_FragColor.a = 0.0; } diff --git a/indra/newview/app_settings/shaders/class1/deferred/pointLightV.glsl b/indra/newview/app_settings/shaders/class1/deferred/pointLightV.glsl index a4edb8825..1a426dddf 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pointLightV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pointLightV.glsl @@ -5,8 +5,10 @@ * $License$ */ +#version 120 + varying vec4 vary_light; -varying vec3 vary_fragcoord; +varying vec4 vary_fragcoord; uniform vec2 screen_res; uniform float near_clip; @@ -14,10 +16,10 @@ uniform float near_clip; void main() { //transform vertex - gl_Position = ftransform(); + gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; vec4 pos = gl_ModelViewProjectionMatrix * gl_Vertex; - vary_fragcoord.xyz = pos.xyz + vec3(0,0,near_clip); + vary_fragcoord = pos; vec4 tex = gl_MultiTexCoord0; tex.w = 1.0; diff --git a/indra/newview/app_settings/shaders/class1/deferred/postDeferredF.glsl b/indra/newview/app_settings/shaders/class1/deferred/postDeferredF.glsl new file mode 100644 index 000000000..77f1b2224 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/postDeferredF.glsl @@ -0,0 +1,137 @@ +/** + * @file postDeferredF.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $/LicenseInfo$ + */ + +#version 120 + +#extension GL_ARB_texture_rectangle : enable + +uniform sampler2DRect diffuseRect; +uniform sampler2DRect edgeMap; +uniform sampler2DRect depthMap; +uniform sampler2DRect normalMap; +uniform sampler2D bloomMap; + +uniform float depth_cutoff; +uniform float norm_cutoff; +uniform float focal_distance; +uniform float blur_constant; +uniform float tan_pixel_angle; +uniform float magnification; + +uniform mat4 inv_proj; +uniform vec2 screen_res; + +varying vec2 vary_fragcoord; + +float getDepth(vec2 pos_screen) +{ + float z = texture2DRect(depthMap, pos_screen.xy).a; + z = z*2.0-1.0; + vec4 ndc = vec4(0.0, 0.0, z, 1.0); + vec4 p = inv_proj*ndc; + return p.z/p.w; +} + +float calc_cof(float depth) +{ + float sc = abs(depth-focal_distance)/-depth*blur_constant; + + sc /= magnification; + + // tan_pixel_angle = pixel_length/-depth; + float pixel_length = tan_pixel_angle*-focal_distance; + + sc = sc/pixel_length; + sc *= 1.414; + + return sc; +} + +void dofSampleNear(inout vec4 diff, inout float w, float cur_sc, vec2 tc) +{ + float d = getDepth(tc); + + float sc = calc_cof(d); + + float wg = 0.25; + + vec4 s = texture2DRect(diffuseRect, tc); + // de-weight dull areas to make highlights 'pop' + wg += s.r+s.g+s.b; + + diff += wg*s; + + w += wg; +} + +void dofSample(inout vec4 diff, inout float w, float min_sc, float cur_depth, vec2 tc) +{ + float d = getDepth(tc); + + float sc = calc_cof(d); + + if (sc > min_sc //sampled pixel is more "out of focus" than current sample radius + || d < cur_depth) //sampled pixel is further away than current pixel + { + float wg = 0.25; + + vec4 s = texture2DRect(diffuseRect, tc); + // de-weight dull areas to make highlights 'pop' + wg += s.r+s.g+s.b; + + diff += wg*s; + + w += wg; + } +} + + +void main() +{ + vec3 norm = texture2DRect(normalMap, vary_fragcoord.xy).xyz; + norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm + + vec2 tc = vary_fragcoord.xy; + + float depth = getDepth(tc); + + vec4 diff = texture2DRect(diffuseRect, vary_fragcoord.xy); + + { + float w = 1.0; + + float sc = calc_cof(depth); + sc = min(abs(sc), 10.0); + + float fd = depth*0.5f; + + float PI = 3.14159265358979323846264; + + // sample quite uniformly spaced points within a circle, for a circular 'bokeh' + //if (depth < focal_distance) + { + while (sc > 0.5) + { + int its = int(max(1.0,(sc*3.7))); + for (int i=0; i 0.8) + { + vec3 samppos = getPosition(tc.xy).xyz; + samppos -= pos; + if (dot(samppos,samppos) < -0.05*pos.z) + { + col += texture2DRect(giLightMap, tc).rgb*kern[i].x; + defined_weight += kern[i].x; + } + } + } + + col /= defined_weight; + + //col = ccol; + + col = col*col*blur_quad.x + col*blur_quad.y + blur_quad.z; + + gl_FragData[0].xyz = col; + + //gl_FragColor = ccol; +} diff --git a/indra/newview/app_settings/shaders/class1/deferred/postgiV.glsl b/indra/newview/app_settings/shaders/class1/deferred/postgiV.glsl new file mode 100644 index 000000000..ae57227fe --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/postgiV.glsl @@ -0,0 +1,19 @@ +/** + * @file postgiV.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $/LicenseInfo$ + */ + +#version 120 + +varying vec2 vary_fragcoord; +uniform vec2 screen_res; + +void main() +{ + //transform vertex + gl_Position = ftransform(); + vec4 pos = gl_ModelViewProjectionMatrix * gl_Vertex; + vary_fragcoord = (pos.xy*0.5+0.5)*screen_res; +} diff --git a/indra/newview/app_settings/shaders/class1/deferred/shadowF.glsl b/indra/newview/app_settings/shaders/class1/deferred/shadowF.glsl index b3758c363..4d85bbf62 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/shadowF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/shadowF.glsl @@ -4,11 +4,16 @@ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 uniform sampler2D diffuseMap; +varying vec4 post_pos; void main() { gl_FragColor = vec4(1,1,1,texture2D(diffuseMap, gl_TexCoord[0].xy).a * gl_Color.a); + + gl_FragDepth = max(post_pos.z/post_pos.w*0.5+0.5, 0.0); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/shadowV.glsl b/indra/newview/app_settings/shaders/class1/deferred/shadowV.glsl index aae1beeae..9baa39814 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/shadowV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/shadowV.glsl @@ -4,14 +4,20 @@ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 + +varying vec4 post_pos; void main() { //transform vertex vec4 pos = gl_ModelViewProjectionMatrix*gl_Vertex; - //smash geometry against the near clip plane (great for ortho projections) - pos.z = max(pos.z, -1.0); - gl_Position = pos; + + post_pos = pos; + + gl_Position = vec4(pos.x, pos.y, pos.w*0.5, pos.w); + gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; gl_FrontColor = gl_Color; } diff --git a/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl index d5671a6ce..cffab338d 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl @@ -4,17 +4,17 @@ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 #extension GL_ARB_texture_rectangle : enable uniform sampler2DRect diffuseRect; uniform sampler2DRect specularRect; -uniform sampler2DRect positionMap; uniform sampler2DRect normalMap; -uniform sampler2DRect depthMap; uniform sampler2DRect lightMap; -uniform sampler2D noiseMap; -uniform samplerCube environmentMap; +uniform sampler2DRect depthMap; +uniform sampler2D lightFunc; uniform float blur_size; uniform float blur_fidelity; @@ -38,8 +38,8 @@ uniform vec4 max_y; uniform vec4 glow; uniform float scene_light_strength; uniform vec3 env_mat[3]; -uniform mat4 shadow_matrix[3]; -uniform vec4 shadow_clip; +//uniform mat4 shadow_matrix[3]; +//uniform vec4 shadow_clip; uniform mat3 ssao_effect_mat; varying vec4 vary_light; @@ -52,6 +52,27 @@ vec3 vary_AmblitColor; vec3 vary_AdditiveColor; vec3 vary_AtmosAttenuation; +uniform mat4 inv_proj; +uniform vec2 screen_res; + +vec4 getPosition_d(vec2 pos_screen, float depth) +{ + vec2 sc = pos_screen.xy*2.0; + sc /= screen_res; + sc -= vec2(1.0,1.0); + vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); + vec4 pos = inv_proj * ndc; + pos /= pos.w; + pos.w = 1.0; + return pos; +} + +vec4 getPosition(vec2 pos_screen) +{ //get position in screen space (world units) given window coordinate and depth map + float depth = texture2DRect(depthMap, pos_screen.xy).a; + return getPosition_d(pos_screen, depth); +} + vec3 getPositionEye() { return vary_PositionEye; @@ -235,45 +256,85 @@ vec3 scaleSoftClip(vec3 light) void main() { vec2 tc = vary_fragcoord.xy; - vec3 pos = texture2DRect(positionMap, tc).xyz; + float depth = texture2DRect(depthMap, tc.xy).a; + vec3 pos = getPosition_d(tc, depth).xyz; vec3 norm = texture2DRect(normalMap, tc).xyz; - vec3 nz = texture2D(noiseMap, vary_fragcoord.xy/128.0).xyz; + norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm + //vec3 nz = texture2D(noiseMap, vary_fragcoord.xy/128.0).xyz; float da = max(dot(norm.xyz, vary_light.xyz), 0.0); - vec4 diffuse = vec4(texture2DRect(diffuseRect, tc).rgb, 1.0); + vec4 diffuse = texture2DRect(diffuseRect, tc); vec4 spec = texture2DRect(specularRect, vary_fragcoord.xy); vec2 scol_ambocc = texture2DRect(lightMap, vary_fragcoord.xy).rg; - float scol = scol_ambocc.r; + float scol = max(scol_ambocc.r, diffuse.a); float ambocc = scol_ambocc.g; calcAtmospherics(pos.xyz, ambocc); vec3 col = atmosAmbient(vec3(0)); - col += atmosAffectDirectionalLight(min(da, scol)); - + col += atmosAffectDirectionalLight(max(min(da, scol), diffuse.a)); col *= diffuse.rgb; - if (spec.a > 0.2) + if (spec.a > 0.0) // specular reflection { - vec3 ref = reflect(pos.xyz, norm.xyz); - vec3 rc; - rc.x = dot(ref, env_mat[0]); - rc.y = dot(ref, env_mat[1]); - rc.z = dot(ref, env_mat[2]); - - vec3 refcol = textureCube(environmentMap, rc).rgb; - col.rgb += refcol * spec.rgb; + // the old infinite-sky shiny reflection + // + vec3 refnormpersp = normalize(reflect(pos.xyz, norm.xyz)); + float sa = dot(refnormpersp, vary_light.xyz); + vec3 dumbshiny = vary_SunlitColor*scol_ambocc.r*texture2D(lightFunc, vec2(sa, spec.a)).a; + /* + // screen-space cheap fakey reflection map + // + vec3 refnorm = normalize(reflect(vec3(0,0,-1), norm.xyz)); + depth -= 0.5; // unbias depth + // first figure out where we'll make our 2D guess from + vec2 ref2d = (0.25 * screen_res.y) * (refnorm.xy) * abs(refnorm.z) / depth; + // Offset the guess source a little according to a trivial + // checkerboard dither function and spec.a. + // This is meant to be similar to sampling a blurred version + // of the diffuse map. LOD would be better in that regard. + // The goal of the blur is to soften reflections in surfaces + // with low shinyness, and also to disguise our lameness. + float checkerboard = floor(mod(tc.x+tc.y, 2.0)); // 0.0, 1.0 + float checkoffset = (3.0 + (7.0*(1.0-spec.a)))*(checkerboard-0.5); + ref2d += vec2(checkoffset, checkoffset); + ref2d += tc.xy; // use as offset from destination + // Get attributes from the 2D guess point. + // We average two samples of diffuse (not of anything else) per + // pixel to try to reduce aliasing some more. + vec3 refcol = 0.5 * (texture2DRect(diffuseRect, ref2d + vec2(0.0, -checkoffset)).rgb + + texture2DRect(diffuseRect, ref2d + vec2(-checkoffset, 0.0)).rgb); + float refdepth = texture2DRect(depthMap, ref2d).a; + vec3 refpos = getPosition_d(ref2d, refdepth).xyz; + vec3 refn = texture2DRect(normalMap, ref2d).rgb; + refn = normalize(vec3((refn.xy-0.5)*2.0,refn.z)); // unpack norm + // figure out how appropriate our guess actually was + float refapprop = max(0.0, dot(-refnorm, normalize(pos - refpos))); + // darken reflections from points which face away from the reflected ray - our guess was a back-face + //refapprop *= step(dot(refnorm, refn), 0.0); + refapprop = min(refapprop, max(0.0, -dot(refnorm, refn))); // more conservative variant + // get appropriate light strength for guess-point. + // reflect light direction to increase the illusion that + // these are reflections. + vec3 reflight = reflect(lightnorm.xyz, norm.xyz); + float reflit = max(dot(refn, reflight.xyz), 0.0); + // apply sun color to guess-point, dampen according to inappropriateness of guess + float refmod = min(refapprop, reflit); + vec3 refprod = vary_SunlitColor * refcol.rgb * refmod; + vec3 ssshiny = (refprod * spec.a); + ssshiny *= 0.3; // dampen it even more + */ + vec3 ssshiny = vec3(0,0,0); + + // add the two types of shiny together + col += (ssshiny + dumbshiny) * spec.rgb; } col = atmosLighting(col); col = scaleSoftClip(col); - + gl_FragColor.rgb = col; gl_FragColor.a = 0.0; - //gl_FragColor.rg = scol_ambocc.rg; - //gl_FragColor.rgb = norm.rgb*0.5+0.5; - //gl_FragColor.rgb = vec3(ambocc); - //gl_FragColor.rgb = vec3(scol); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/softenLightNoSSAOF.glsl b/indra/newview/app_settings/shaders/class1/deferred/softenLightNoSSAOF.glsl new file mode 100644 index 000000000..bca692cab --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/softenLightNoSSAOF.glsl @@ -0,0 +1,337 @@ +/** + * @file softenLightF.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +#version 120 + +#extension GL_ARB_texture_rectangle : enable + +uniform sampler2DRect diffuseRect; +uniform sampler2DRect specularRect; +uniform sampler2DRect normalMap; +uniform sampler2DRect depthMap; +uniform sampler2D lightFunc; + +uniform float blur_size; +uniform float blur_fidelity; + +// Inputs +uniform vec4 morphFactor; +uniform vec3 camPosLocal; +//uniform vec4 camPosWorld; +uniform vec4 gamma; +uniform vec4 lightnorm; +uniform vec4 sunlight_color; +uniform vec4 ambient; +uniform vec4 blue_horizon; +uniform vec4 blue_density; +uniform vec4 haze_horizon; +uniform vec4 haze_density; +uniform vec4 cloud_shadow; +uniform vec4 density_multiplier; +uniform vec4 distance_multiplier; +uniform vec4 max_y; +uniform vec4 glow; +uniform float scene_light_strength; +uniform vec3 env_mat[3]; +//uniform mat4 shadow_matrix[3]; +//uniform vec4 shadow_clip; +uniform mat3 ssao_effect_mat; + +varying vec4 vary_light; +varying vec2 vary_fragcoord; + +vec3 vary_PositionEye; + +vec3 vary_SunlitColor; +vec3 vary_AmblitColor; +vec3 vary_AdditiveColor; +vec3 vary_AtmosAttenuation; + +uniform mat4 inv_proj; +uniform vec2 screen_res; + +vec4 getPosition_d(vec2 pos_screen, float depth) +{ + vec2 sc = pos_screen.xy*2.0; + sc /= screen_res; + sc -= vec2(1.0,1.0); + vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); + vec4 pos = inv_proj * ndc; + pos /= pos.w; + pos.w = 1.0; + return pos; +} + +vec4 getPosition(vec2 pos_screen) +{ //get position in screen space (world units) given window coordinate and depth map + float depth = texture2DRect(depthMap, pos_screen.xy).a; + return getPosition_d(pos_screen, depth); +} + +vec3 getPositionEye() +{ + return vary_PositionEye; +} +vec3 getSunlitColor() +{ + return vary_SunlitColor; +} +vec3 getAmblitColor() +{ + return vary_AmblitColor; +} +vec3 getAdditiveColor() +{ + return vary_AdditiveColor; +} +vec3 getAtmosAttenuation() +{ + return vary_AtmosAttenuation; +} + + +void setPositionEye(vec3 v) +{ + vary_PositionEye = v; +} + +void setSunlitColor(vec3 v) +{ + vary_SunlitColor = v; +} + +void setAmblitColor(vec3 v) +{ + vary_AmblitColor = v; +} + +void setAdditiveColor(vec3 v) +{ + vary_AdditiveColor = v; +} + +void setAtmosAttenuation(vec3 v) +{ + vary_AtmosAttenuation = v; +} + +void calcAtmospherics(vec3 inPositionEye, float ambFactor) { + + vec3 P = inPositionEye; + setPositionEye(P); + + //(TERRAIN) limit altitude + if (P.y > max_y.x) P *= (max_y.x / P.y); + if (P.y < -max_y.x) P *= (-max_y.x / P.y); + + vec3 tmpLightnorm = lightnorm.xyz; + + vec3 Pn = normalize(P); + float Plen = length(P); + + vec4 temp1 = vec4(0); + vec3 temp2 = vec3(0); + vec4 blue_weight; + vec4 haze_weight; + vec4 sunlight = sunlight_color; + vec4 light_atten; + + //sunlight attenuation effect (hue and brightness) due to atmosphere + //this is used later for sunlight modulation at various altitudes + light_atten = (blue_density * 1.0 + vec4(haze_density.r) * 0.25) * (density_multiplier.x * max_y.x); + //I had thought blue_density and haze_density should have equal weighting, + //but attenuation due to haze_density tends to seem too strong + + temp1 = blue_density + vec4(haze_density.r); + blue_weight = blue_density / temp1; + haze_weight = vec4(haze_density.r) / temp1; + + //(TERRAIN) compute sunlight from lightnorm only (for short rays like terrain) + temp2.y = max(0.0, tmpLightnorm.y); + temp2.y = 1. / temp2.y; + sunlight *= exp( - light_atten * temp2.y); + + // main atmospheric scattering line integral + temp2.z = Plen * density_multiplier.x; + + // Transparency (-> temp1) + // ATI Bugfix -- can't store temp1*temp2.z*distance_multiplier.x in a variable because the ati + // compiler gets confused. + temp1 = exp(-temp1 * temp2.z * distance_multiplier.x); + + //final atmosphere attenuation factor + setAtmosAttenuation(temp1.rgb); + + //compute haze glow + //(can use temp2.x as temp because we haven't used it yet) + temp2.x = dot(Pn, tmpLightnorm.xyz); + temp2.x = 1. - temp2.x; + //temp2.x is 0 at the sun and increases away from sun + temp2.x = max(temp2.x, .03); //was glow.y + //set a minimum "angle" (smaller glow.y allows tighter, brighter hotspot) + temp2.x *= glow.x; + //higher glow.x gives dimmer glow (because next step is 1 / "angle") + temp2.x = pow(temp2.x, glow.z); + //glow.z should be negative, so we're doing a sort of (1 / "angle") function + + //add "minimum anti-solar illumination" + temp2.x += .25; + + //increase ambient when there are more clouds + vec4 tmpAmbient = ambient + (vec4(1.) - ambient) * cloud_shadow.x * 0.5; + + /* decrease value and saturation (that in HSV, not HSL) for occluded areas + * // for HSV color/geometry used here, see http://gimp-savvy.com/BOOK/index.html?node52.html + * // The following line of code performs the equivalent of: + * float ambAlpha = tmpAmbient.a; + * float ambValue = dot(vec3(tmpAmbient), vec3(0.577)); // projection onto <1/rt(3), 1/rt(3), 1/rt(3)>, the neutral white-black axis + * vec3 ambHueSat = vec3(tmpAmbient) - vec3(ambValue); + * tmpAmbient = vec4(RenderSSAOEffect.valueFactor * vec3(ambValue) + RenderSSAOEffect.saturationFactor *(1.0 - ambFactor) * ambHueSat, ambAlpha); + */ + tmpAmbient = vec4(mix(ssao_effect_mat * tmpAmbient.rgb, tmpAmbient.rgb, ambFactor), tmpAmbient.a); + + //haze color + setAdditiveColor( + vec3(blue_horizon * blue_weight * (sunlight*(1.-cloud_shadow.x) + tmpAmbient) + + (haze_horizon.r * haze_weight) * (sunlight*(1.-cloud_shadow.x) * temp2.x + + tmpAmbient))); + + //brightness of surface both sunlight and ambient + setSunlitColor(vec3(sunlight * .5)); + setAmblitColor(vec3(tmpAmbient * .25)); + setAdditiveColor(getAdditiveColor() * vec3(1.0 - temp1)); +} + +vec3 atmosLighting(vec3 light) +{ + light *= getAtmosAttenuation().r; + light += getAdditiveColor(); + return (2.0 * light); +} + +vec3 atmosTransport(vec3 light) { + light *= getAtmosAttenuation().r; + light += getAdditiveColor() * 2.0; + return light; +} +vec3 atmosGetDiffuseSunlightColor() +{ + return getSunlitColor(); +} + +vec3 scaleDownLight(vec3 light) +{ + return (light / scene_light_strength ); +} + +vec3 scaleUpLight(vec3 light) +{ + return (light * scene_light_strength); +} + +vec3 atmosAmbient(vec3 light) +{ + return getAmblitColor() + light / 2.0; +} + +vec3 atmosAffectDirectionalLight(float lightIntensity) +{ + return getSunlitColor() * lightIntensity; +} + +vec3 scaleSoftClip(vec3 light) +{ + //soft clip effect: + light = 1. - clamp(light, vec3(0.), vec3(1.)); + light = 1. - pow(light, gamma.xxx); + + return light; +} + +void main() +{ + vec2 tc = vary_fragcoord.xy; + float depth = texture2DRect(depthMap, tc.xy).a; + vec3 pos = getPosition_d(tc, depth).xyz; + vec3 norm = texture2DRect(normalMap, tc).xyz; + norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm + //vec3 nz = texture2D(noiseMap, vary_fragcoord.xy/128.0).xyz; + + float da = max(dot(norm.xyz, vary_light.xyz), 0.0); + + vec4 diffuse = texture2DRect(diffuseRect, tc); + vec4 spec = texture2DRect(specularRect, vary_fragcoord.xy); + + calcAtmospherics(pos.xyz, 1.0); + + vec3 col = atmosAmbient(vec3(0)); + col += atmosAffectDirectionalLight(max(min(da, 1.0), diffuse.a)); + + col *= diffuse.rgb; + + if (spec.a > 0.0) // specular reflection + { + // the old infinite-sky shiny reflection + // + vec3 refnormpersp = normalize(reflect(pos.xyz, norm.xyz)); + float sa = dot(refnormpersp, vary_light.xyz); + vec3 dumbshiny = vary_SunlitColor*texture2D(lightFunc, vec2(sa, spec.a)).a; + + /* + // screen-space cheap fakey reflection map + // + vec3 refnorm = normalize(reflect(vec3(0,0,-1), norm.xyz)); + depth -= 0.5; // unbias depth + // first figure out where we'll make our 2D guess from + vec2 ref2d = (0.25 * screen_res.y) * (refnorm.xy) * abs(refnorm.z) / depth; + // Offset the guess source a little according to a trivial + // checkerboard dither function and spec.a. + // This is meant to be similar to sampling a blurred version + // of the diffuse map. LOD would be better in that regard. + // The goal of the blur is to soften reflections in surfaces + // with low shinyness, and also to disguise our lameness. + float checkerboard = floor(mod(tc.x+tc.y, 2.0)); // 0.0, 1.0 + float checkoffset = (3.0 + (7.0*(1.0-spec.a)))*(checkerboard-0.5); + ref2d += vec2(checkoffset, checkoffset); + ref2d += tc.xy; // use as offset from destination + // Get attributes from the 2D guess point. + // We average two samples of diffuse (not of anything else) per + // pixel to try to reduce aliasing some more. + vec3 refcol = 0.5 * (texture2DRect(diffuseRect, ref2d + vec2(0.0, -checkoffset)).rgb + + texture2DRect(diffuseRect, ref2d + vec2(-checkoffset, 0.0)).rgb); + float refdepth = texture2DRect(depthMap, ref2d).a; + vec3 refpos = getPosition_d(ref2d, refdepth).xyz; + vec3 refn = texture2DRect(normalMap, ref2d).rgb; + refn = normalize(vec3((refn.xy-0.5)*2.0,refn.z)); // unpack norm + // figure out how appropriate our guess actually was + float refapprop = max(0.0, dot(-refnorm, normalize(pos - refpos))); + // darken reflections from points which face away from the reflected ray - our guess was a back-face + //refapprop *= step(dot(refnorm, refn), 0.0); + refapprop = min(refapprop, max(0.0, -dot(refnorm, refn))); // more conservative variant + // get appropriate light strength for guess-point. + // reflect light direction to increase the illusion that + // these are reflections. + vec3 reflight = reflect(lightnorm.xyz, norm.xyz); + float reflit = max(dot(refn, reflight.xyz), 0.0); + // apply sun color to guess-point, dampen according to inappropriateness of guess + float refmod = min(refapprop, reflit); + vec3 refprod = vary_SunlitColor * refcol.rgb * refmod; + vec3 ssshiny = (refprod * spec.a); + ssshiny *= 0.3; // dampen it even more + */ + vec3 ssshiny = vec3(0,0,0); + + // add the two types of shiny together + col += (ssshiny + dumbshiny) * spec.rgb; + } + + col = atmosLighting(col); + col = scaleSoftClip(col); + + gl_FragColor.rgb = col; + gl_FragColor.a = 0.0; +} diff --git a/indra/newview/app_settings/shaders/class1/deferred/softenLightV.glsl b/indra/newview/app_settings/shaders/class1/deferred/softenLightV.glsl index ad8af4780..3bc94e70d 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/softenLightV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/softenLightV.glsl @@ -4,6 +4,8 @@ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 uniform vec2 screen_res; diff --git a/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl new file mode 100644 index 000000000..29fac46bf --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl @@ -0,0 +1,167 @@ +/** + * @file spotLightF.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $/LicenseInfo$ + */ + +#version 120 + +#extension GL_ARB_texture_rectangle : enable + +uniform sampler2DRect diffuseRect; +uniform sampler2DRect specularRect; +uniform sampler2DRect depthMap; +uniform sampler2DRect normalMap; +uniform samplerCube environmentMap; +uniform sampler2D noiseMap; +uniform sampler2D lightFunc; +uniform sampler2D projectionMap; + +uniform mat4 proj_mat; //screen space to light space +uniform float proj_near; //near clip for projection +uniform vec3 proj_p; //plane projection is emitting from (in screen space) +uniform vec3 proj_n; +uniform float proj_focus; //distance from plane to begin blurring +uniform float proj_lod; //(number of mips in proj map) +uniform float proj_range; //range between near clip and far clip plane of projection +uniform float proj_ambiance; +uniform float near_clip; +uniform float far_clip; + +uniform vec3 proj_origin; //origin of projection to be used for angular attenuation +uniform float sun_wash; + +varying vec4 vary_light; + +varying vec4 vary_fragcoord; +uniform vec2 screen_res; + +uniform mat4 inv_proj; + +vec4 getPosition(vec2 pos_screen) +{ + float depth = texture2DRect(depthMap, pos_screen.xy).a; + vec2 sc = pos_screen.xy*2.0; + sc /= screen_res; + sc -= vec2(1.0,1.0); + vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); + vec4 pos = inv_proj * ndc; + pos /= pos.w; + pos.w = 1.0; + return pos; +} + +void main() +{ + vec4 frag = vary_fragcoord; + frag.xyz /= frag.w; + frag.xyz = frag.xyz*0.5+0.5; + frag.xy *= screen_res; + + vec3 pos = getPosition(frag.xy).xyz; + vec3 lv = vary_light.xyz-pos.xyz; + float dist2 = dot(lv,lv); + dist2 /= vary_light.w; + if (dist2 > 1.0) + { + discard; + } + + vec3 norm = texture2DRect(normalMap, frag.xy).xyz; + norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm + + norm = normalize(norm); + float l_dist = -dot(lv, proj_n); + + vec4 proj_tc = (proj_mat * vec4(pos.xyz, 1.0)); + if (proj_tc.z < 0.0) + { + discard; + } + + proj_tc.xyz /= proj_tc.w; + + float fa = gl_Color.a+1.0; + float dist_atten = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0); + + lv = proj_origin-pos.xyz; + lv = normalize(lv); + float da = dot(norm, lv); + + vec3 col = vec3(0,0,0); + + vec3 diff_tex = texture2DRect(diffuseRect, frag.xy).rgb; + + float noise = texture2D(noiseMap, frag.xy/128.0).b; + if (proj_tc.z > 0.0 && + proj_tc.x < 1.0 && + proj_tc.y < 1.0 && + proj_tc.x > 0.0 && + proj_tc.y > 0.0) + { + float lit = 0.0; + if (da > 0.0) + { + float diff = clamp((l_dist-proj_focus)/proj_range, 0.0, 1.0); + float lod = diff * proj_lod; + + vec4 plcol = texture2DLod(projectionMap, proj_tc.xy, lod); + + vec3 lcol = gl_Color.rgb * plcol.rgb * plcol.a; + + lit = da * dist_atten * noise; + + col = lcol*lit*diff_tex; + } + + float diff = clamp((proj_range-proj_focus)/proj_range, 0.0, 1.0); + float lod = diff * proj_lod; + vec4 amb_plcol = texture2DLod(projectionMap, proj_tc.xy, lod); + //float amb_da = mix(proj_ambiance, proj_ambiance*max(-da, 0.0), max(da, 0.0)); + float amb_da = proj_ambiance; + + amb_da += (da*da*0.5+0.5)*proj_ambiance; + + amb_da *= dist_atten * noise; + + amb_da = min(amb_da, 1.0-lit); + + col += amb_da*gl_Color.rgb*diff_tex.rgb*amb_plcol.rgb*amb_plcol.a; + } + + + vec4 spec = texture2DRect(specularRect, frag.xy); + if (spec.a > 0.0) + { + vec3 ref = reflect(normalize(pos), norm); + + //project from point pos in direction ref to plane proj_p, proj_n + vec3 pdelta = proj_p-pos; + float ds = dot(ref, proj_n); + + if (ds < 0.0) + { + vec3 pfinal = pos + ref * dot(pdelta, proj_n)/ds; + + vec3 stc = (proj_mat * vec4(pfinal.xyz, 1.0)).xyz; + + if (stc.z > 0.0) + { + stc.xy /= stc.z+proj_near; + + if (stc.x < 1.0 && + stc.y < 1.0 && + stc.x > 0.0 && + stc.y > 0.0) + { + vec4 scol = texture2DLod(projectionMap, stc.xy, proj_lod-spec.a*proj_lod); + col += dist_atten*scol.rgb*gl_Color.rgb*scol.a*spec.rgb; + } + } + } + } + + gl_FragColor.rgb = col; + gl_FragColor.a = 0.0; +} diff --git a/indra/newview/app_settings/shaders/class1/deferred/sunLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/sunLightF.glsl index d43fe6ca9..5db627ab1 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/sunLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/sunLightF.glsl @@ -4,136 +4,14 @@ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 + +//class 1, no shadow, no SSAO, should never be called #extension GL_ARB_texture_rectangle : enable -uniform sampler2DRect positionMap; -uniform sampler2DRect normalMap; -uniform sampler2DRect depthMap; -uniform sampler2DShadow shadowMap0; -uniform sampler2DShadow shadowMap1; -uniform sampler2DShadow shadowMap2; -uniform sampler2DShadow shadowMap3; -uniform sampler2D noiseMap; - -// Inputs -uniform mat4 shadow_matrix[4]; -uniform vec4 shadow_clip; -uniform float ssao_radius; -uniform float ssao_max_radius; -uniform float ssao_factor; -uniform float ssao_factor_inv; - -varying vec2 vary_fragcoord; -varying vec4 vary_light; - -//calculate decreases in ambient lighting when crowded out (SSAO) -float calcAmbientOcclusion(vec4 pos, vec3 norm) -{ - vec2 kern[8]; - // exponentially (^2) distant occlusion samples spread around origin - kern[0] = vec2(-1.0, 0.0) * 0.125*0.125; - kern[1] = vec2(1.0, 0.0) * 0.250*0.250; - kern[2] = vec2(0.0, 1.0) * 0.375*0.375; - kern[3] = vec2(0.0, -1.0) * 0.500*0.500; - kern[4] = vec2(0.7071, 0.7071) * 0.625*0.625; - kern[5] = vec2(-0.7071, -0.7071) * 0.750*0.750; - kern[6] = vec2(-0.7071, 0.7071) * 0.875*0.875; - kern[7] = vec2(0.7071, -0.7071) * 1.000*1.000; - - vec2 pos_screen = vary_fragcoord.xy; - vec3 pos_world = pos.xyz; - vec2 noise_reflect = texture2D(noiseMap, vary_fragcoord.xy/128.0).xy; - - float angle_hidden = 0.0; - int points = 0; - - float scale = min(ssao_radius / -pos_world.z, ssao_max_radius); - - // it was found that keeping # of samples a constant was the fastest, probably due to compiler optimizations (unrolling?) - for (int i = 0; i < 8; i++) - { - vec2 samppos_screen = pos_screen + scale * reflect(kern[i], noise_reflect); - vec3 samppos_world = texture2DRect(positionMap, samppos_screen).xyz; - - vec3 diff = pos_world - samppos_world; - float dist2 = dot(diff, diff); - - // assume each sample corresponds to an occluding sphere with constant radius, constant x-sectional area - // --> solid angle shrinking by the square of distance - //radius is somewhat arbitrary, can approx with just some constant k * 1 / dist^2 - //(k should vary inversely with # of samples, but this is taken care of later) - - //if (dot((samppos_world - 0.05*norm - pos_world), norm) > 0.0) // -0.05*norm to shift sample point back slightly for flat surfaces - // angle_hidden += min(1.0/dist2, ssao_factor_inv); // dist != 0 follows from conditional. max of 1.0 (= ssao_factor_inv * ssao_factor) - angle_hidden = angle_hidden + float(dot((samppos_world - 0.05*norm - pos_world), norm) > 0.0) * min(1.0/dist2, ssao_factor_inv); - - // 'blocked' samples (significantly closer to camera relative to pos_world) are "no data", not "no occlusion" - points = points + int(diff.z > -1.0); - } - - angle_hidden = min(ssao_factor*angle_hidden/float(points), 1.0); - - return 1.0 - (float(points != 0) * angle_hidden); -} - void main() { - vec2 pos_screen = vary_fragcoord.xy; - vec4 pos = vec4(texture2DRect(positionMap, pos_screen).xyz, 1.0); - vec3 norm = texture2DRect(normalMap, pos_screen).xyz; - - /*if (pos.z == 0.0) // do nothing for sky *FIX: REMOVE THIS IF/WHEN THE POSITION MAP IS BEING USED AS A STENCIL - { - gl_FragColor = vec4(0.0); // doesn't matter - return; - }*/ - - float shadow = 1.0; - float dp_directional_light = max(0.0, dot(norm, vary_light.xyz)); - - if (dp_directional_light == 0.0) - { - // if we know this point is facing away from the sun then we know it's in shadow without having to do a squirrelly shadow-map lookup - shadow = 0.0; - } - else if (pos.z > -shadow_clip.w) - { - if (pos.z < -shadow_clip.z) - { - vec4 lpos = shadow_matrix[3]*pos; - shadow = shadow2DProj(shadowMap3, lpos).x; - shadow += max((pos.z+shadow_clip.z)/(shadow_clip.z-shadow_clip.w)*2.0-1.0, 0.0); - } - else if (pos.z < -shadow_clip.y) - { - vec4 lpos = shadow_matrix[2]*pos; - shadow = shadow2DProj(shadowMap2, lpos).x; - } - else if (pos.z < -shadow_clip.x) - { - vec4 lpos = shadow_matrix[1]*pos; - shadow = shadow2DProj(shadowMap1, lpos).x; - } - else - { - vec4 lpos = shadow_matrix[0]*pos; - shadow = shadow2DProj(shadowMap0, lpos).x; - } - - // take the most-shadowed value out of these two: - // * the blurred sun shadow in the light (shadow) map - // * an unblurred dot product between the sun and this norm - // the goal is to err on the side of most-shadow to fill-in shadow holes and reduce artifacting - shadow = min(shadow, dp_directional_light); - } - else - { - // more distant than the shadow map covers - just use directional shading as shadow - shadow = dp_directional_light; - } - - gl_FragColor[0] = shadow; - gl_FragColor[1] = calcAmbientOcclusion(pos, norm); - //gl_FragColor[2] is unused as of August 2008, may be used for debugging + gl_FragColor = vec4(0,0,0,0); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/sunLightSSAOF.glsl b/indra/newview/app_settings/shaders/class1/deferred/sunLightSSAOF.glsl new file mode 100644 index 000000000..cd91351ad --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/sunLightSSAOF.glsl @@ -0,0 +1,116 @@ +/** + * @file sunLightSSAOF.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +#version 120 + +#extension GL_ARB_texture_rectangle : enable + +//class 1 -- no shadow, SSAO only + +uniform sampler2DRect depthMap; +uniform sampler2DRect normalMap; +uniform sampler2D noiseMap; + + +// Inputs +uniform mat4 shadow_matrix[6]; +uniform vec4 shadow_clip; +uniform float ssao_radius; +uniform float ssao_max_radius; +uniform float ssao_factor; +uniform float ssao_factor_inv; + +varying vec2 vary_fragcoord; +varying vec4 vary_light; + +uniform mat4 inv_proj; +uniform vec2 screen_res; + +uniform float shadow_bias; +uniform float shadow_offset; + +vec4 getPosition(vec2 pos_screen) +{ + float depth = texture2DRect(depthMap, pos_screen.xy).a; + vec2 sc = pos_screen.xy*2.0; + sc /= screen_res; + sc -= vec2(1.0,1.0); + vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); + vec4 pos = inv_proj * ndc; + pos /= pos.w; + pos.w = 1.0; + return pos; +} + +//calculate decreases in ambient lighting when crowded out (SSAO) +float calcAmbientOcclusion(vec4 pos, vec3 norm) +{ + float ret = 1.0; + + vec2 kern[8]; + // exponentially (^2) distant occlusion samples spread around origin + kern[0] = vec2(-1.0, 0.0) * 0.125*0.125; + kern[1] = vec2(1.0, 0.0) * 0.250*0.250; + kern[2] = vec2(0.0, 1.0) * 0.375*0.375; + kern[3] = vec2(0.0, -1.0) * 0.500*0.500; + kern[4] = vec2(0.7071, 0.7071) * 0.625*0.625; + kern[5] = vec2(-0.7071, -0.7071) * 0.750*0.750; + kern[6] = vec2(-0.7071, 0.7071) * 0.875*0.875; + kern[7] = vec2(0.7071, -0.7071) * 1.000*1.000; + + vec2 pos_screen = vary_fragcoord.xy; + vec3 pos_world = pos.xyz; + vec2 noise_reflect = texture2D(noiseMap, vary_fragcoord.xy/128.0).xy; + + float angle_hidden = 0.0; + int points = 0; + + float scale = min(ssao_radius / -pos_world.z, ssao_max_radius); + + // it was found that keeping # of samples a constant was the fastest, probably due to compiler optimizations unrolling?) + for (int i = 0; i < 8; i++) + { + vec2 samppos_screen = pos_screen + scale * reflect(kern[i], noise_reflect); + vec3 samppos_world = getPosition(samppos_screen).xyz; + + vec3 diff = pos_world - samppos_world; + float dist2 = dot(diff, diff); + + // assume each sample corresponds to an occluding sphere with constant radius, constant x-sectional area + // --> solid angle shrinking by the square of distance + //radius is somewhat arbitrary, can approx with just some constant k * 1 / dist^2 + //(k should vary inversely with # of samples, but this is taken care of later) + + angle_hidden = angle_hidden + float(dot((samppos_world - 0.05*norm - pos_world), norm) > 0.0) * min(1.0/dist2, ssao_factor_inv); + + // 'blocked' samples (significantly closer to camera relative to pos_world) are "no data", not "no occlusion" + points = points + int(diff.z > -1.0); + } + + angle_hidden = min(ssao_factor*angle_hidden/float(points), 1.0); + + ret = (1.0 - (float(points != 0) * angle_hidden)); + + return min(ret, 1.0); +} + +void main() +{ + vec2 pos_screen = vary_fragcoord.xy; + + //try doing an unproject here + + vec4 pos = getPosition(pos_screen); + + vec3 norm = texture2DRect(normalMap, pos_screen).xyz; + norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm + + gl_FragColor[0] = 1.0; + gl_FragColor[1] = calcAmbientOcclusion(pos, norm); + gl_FragColor[2] = 1.0; + gl_FragColor[3] = 1.0; +} diff --git a/indra/newview/app_settings/shaders/class1/deferred/sunLightV.glsl b/indra/newview/app_settings/shaders/class1/deferred/sunLightV.glsl index 5081485c4..9aef0a6bb 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/sunLightV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/sunLightV.glsl @@ -4,6 +4,8 @@ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 varying vec4 vary_light; varying vec2 vary_fragcoord; diff --git a/indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl b/indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl index 211b2e039..0a3fae592 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl @@ -4,6 +4,8 @@ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 uniform sampler2D detail_0; uniform sampler2D detail_1; @@ -12,7 +14,6 @@ uniform sampler2D detail_3; uniform sampler2D alpha_ramp; varying vec3 vary_normal; -varying vec4 vary_position; void main() { @@ -28,9 +29,9 @@ void main() float alphaFinal = texture2D(alpha_ramp, gl_TexCoord[1].zw).a; vec4 outColor = mix( mix(color3, color2, alpha2), mix(color1, color0, alpha1), alphaFinal ); - gl_FragData[0] = vec4(outColor.rgb, 1.0); + gl_FragData[0] = vec4(outColor.rgb, 0.0); gl_FragData[1] = vec4(outColor.rgb*0.2, 0.2); - gl_FragData[2] = vec4(normalize(vary_normal), 0.0); - gl_FragData[3] = vary_position; + vec3 nvn = normalize(vary_normal); + gl_FragData[2] = vec4(nvn.xy * 0.5 + 0.5, nvn.z, 0.0); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/terrainV.glsl b/indra/newview/app_settings/shaders/class1/deferred/terrainV.glsl index e9d6dcabf..06507f456 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/terrainV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/terrainV.glsl @@ -4,9 +4,10 @@ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 varying vec3 vary_normal; -varying vec4 vary_position; vec4 texgen_object(vec4 vpos, vec4 tc, mat4 mat, vec4 tp0, vec4 tp1) { @@ -27,7 +28,6 @@ void main() //transform vertex gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; - vary_position = gl_ModelViewMatrix * gl_Vertex; vary_normal = normalize(gl_NormalMatrix * gl_Normal); // Transform and pass tex coords diff --git a/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl b/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl index ea70eabf5..123520190 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl @@ -4,17 +4,18 @@ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 uniform sampler2D diffuseMap; varying vec3 vary_normal; -varying vec4 vary_position; void main() { vec4 col = texture2D(diffuseMap, gl_TexCoord[0].xy); gl_FragData[0] = vec4(gl_Color.rgb*col.rgb, col.a <= 0.5 ? 0.0 : 0.005); gl_FragData[1] = vec4(0,0,0,0); - gl_FragData[2] = vec4(normalize(vary_normal), 0.0); - gl_FragData[3] = vary_position; + vec3 nvn = normalize(vary_normal); + gl_FragData[2] = vec4(nvn.xy * 0.5 + 0.5, nvn.z, 0.0); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/treeV.glsl b/indra/newview/app_settings/shaders/class1/deferred/treeV.glsl index 9131d7c2b..d1500393b 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/treeV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/treeV.glsl @@ -4,9 +4,10 @@ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 varying vec3 vary_normal; -varying vec4 vary_position; void main() { @@ -14,8 +15,6 @@ void main() gl_Position = ftransform(); gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; - vary_position = gl_ModelViewMatrix * gl_Vertex; - vary_normal = normalize(gl_NormalMatrix * gl_Normal); gl_FrontColor = gl_Color; diff --git a/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl b/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl index 83959101e..606e44eae 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl @@ -4,21 +4,24 @@ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 #extension GL_ARB_texture_rectangle : enable + vec3 scaleSoftClip(vec3 inColor); vec3 atmosTransport(vec3 inColor); uniform sampler2D bumpMap; uniform sampler2D screenTex; uniform sampler2D refTex; -uniform sampler2DShadow shadowMap0; -uniform sampler2DShadow shadowMap1; -uniform sampler2DShadow shadowMap2; -uniform sampler2DShadow shadowMap3; +uniform sampler2DRectShadow shadowMap0; +uniform sampler2DRectShadow shadowMap1; +uniform sampler2DRectShadow shadowMap2; +uniform sampler2DRectShadow shadowMap3; uniform sampler2D noiseMap; -uniform mat4 shadow_matrix[4]; +uniform mat4 shadow_matrix[6]; uniform vec4 shadow_clip; uniform float sunAngle; @@ -33,9 +36,9 @@ uniform vec3 normScale; uniform float fresnelScale; uniform float fresnelOffset; uniform float blurMultiplier; +uniform vec2 screen_res; uniform mat4 norm_mat; //region space to screen space - //bigWave is (refCoord.w, view.w); varying vec4 refCoord; varying vec4 littleWave; @@ -114,51 +117,27 @@ void main() vec4 fb = texture2D(screenTex, distort2); //mix with reflection - // Note we actually want to use just df1, but multiplying by 0.999999 gets around and nvidia compiler bug + // Note we actually want to use just df1, but multiplying by 0.999999 gets around an nvidia compiler bug color.rgb = mix(fb.rgb, refcol.rgb, df1 * 0.99999); float shadow = 1.0; vec4 pos = vary_position; //vec3 nz = texture2D(noiseMap, gl_FragCoord.xy/128.0).xyz; - -// if (pos.z > -shadow_clip.w) -// { - vec4 spos = pos; - -/* if (pos.z < -shadow_clip.z) - { - vec4 lpos = (shadow_matrix[3]*spos); - shadow = shadow2DProj(shadowMap3, lpos).x; - } - else if (pos.z < -shadow_clip.y) - { - vec4 lpos = (shadow_matrix[2]*spos); - shadow = shadow2DProj(shadowMap2, lpos).x; - } - else if (pos.z < -shadow_clip.x) - { - vec4 lpos = (shadow_matrix[1]*spos); - shadow = shadow2DProj(shadowMap1, lpos).x; - } - else - { - vec4 lpos = (shadow_matrix[0]*spos); - shadow = shadow2DProj(shadowMap0, lpos).x; - } - }*/ + vec4 spos = pos; + + //spec *= shadow; + //color.rgb += spec * specular; -// spec *= shadow; -// color.rgb += spec * specular; - -// color.rgb = atmosTransport(color.rgb); -// color.rgb = scaleSoftClip(color.rgb); -// color.a = spec * sunAngle2; + //color.rgb = atmosTransport(color.rgb); + //color.rgb = scaleSoftClip(color.rgb); + //color.a = spec * sunAngle2; -// gl_FragColor = color; + //wavef.z *= 0.1f; + //wavef = normalize(wavef); vec3 screenspacewavef = (norm_mat*vec4(wavef, 1.0)).xyz; gl_FragData[0] = vec4(color.rgb, 0.5); // diffuse gl_FragData[1] = vec4(0.5,0.5,0.5, 0.95); // speccolor*spec, spec - gl_FragData[2] = vec4(screenspacewavef, 0.0); // normalxyz, displace + gl_FragData[2] = vec4(screenspacewavef.xy*0.5+0.5, screenspacewavef.z, screenspacewavef.z*0.5); // normalxyz, displace } diff --git a/indra/newview/app_settings/shaders/class1/deferred/waterV.glsl b/indra/newview/app_settings/shaders/class1/deferred/waterV.glsl index b45e5c530..2be8d4286 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/waterV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/waterV.glsl @@ -4,6 +4,8 @@ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 void calcAtmospherics(vec3 inPositionEye); diff --git a/indra/newview/app_settings/shaders/class1/effects/glowExtractF.glsl b/indra/newview/app_settings/shaders/class1/effects/glowExtractF.glsl index 5d7af2c13..61e5ba0d9 100644 --- a/indra/newview/app_settings/shaders/class1/effects/glowExtractF.glsl +++ b/indra/newview/app_settings/shaders/class1/effects/glowExtractF.glsl @@ -4,6 +4,8 @@ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 #extension GL_ARB_texture_rectangle : enable diff --git a/indra/newview/app_settings/shaders/class1/effects/glowExtractV.glsl b/indra/newview/app_settings/shaders/class1/effects/glowExtractV.glsl index 61dfd2f12..fd5300a1f 100644 --- a/indra/newview/app_settings/shaders/class1/effects/glowExtractV.glsl +++ b/indra/newview/app_settings/shaders/class1/effects/glowExtractV.glsl @@ -5,6 +5,7 @@ * $License$ */ +#version 120 void main() { diff --git a/indra/newview/app_settings/shaders/class1/effects/glowV.glsl b/indra/newview/app_settings/shaders/class1/effects/glowV.glsl index 13ce7c785..744eff196 100644 --- a/indra/newview/app_settings/shaders/class1/effects/glowV.glsl +++ b/indra/newview/app_settings/shaders/class1/effects/glowV.glsl @@ -4,6 +4,8 @@ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 uniform vec2 glowDelta; diff --git a/indra/newview/app_settings/shaders/class1/environment/terrainF.glsl b/indra/newview/app_settings/shaders/class1/environment/terrainF.glsl index 2278c6916..51b3cdd99 100644 --- a/indra/newview/app_settings/shaders/class1/environment/terrainF.glsl +++ b/indra/newview/app_settings/shaders/class1/environment/terrainF.glsl @@ -4,6 +4,8 @@ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 uniform sampler2D detail0; uniform sampler2D detail1; diff --git a/indra/newview/app_settings/shaders/class1/environment/terrainV.glsl b/indra/newview/app_settings/shaders/class1/environment/terrainV.glsl index 112d66981..fc4cb14c4 100644 --- a/indra/newview/app_settings/shaders/class1/environment/terrainV.glsl +++ b/indra/newview/app_settings/shaders/class1/environment/terrainV.glsl @@ -4,6 +4,8 @@ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol); diff --git a/indra/newview/app_settings/shaders/class1/environment/terrainWaterF.glsl b/indra/newview/app_settings/shaders/class1/environment/terrainWaterF.glsl index e2f68e882..7db3133f6 100644 --- a/indra/newview/app_settings/shaders/class1/environment/terrainWaterF.glsl +++ b/indra/newview/app_settings/shaders/class1/environment/terrainWaterF.glsl @@ -4,6 +4,8 @@ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 // this class1 shader is just a copy of terrainF diff --git a/indra/newview/app_settings/shaders/class1/environment/underWaterF.glsl b/indra/newview/app_settings/shaders/class1/environment/underWaterF.glsl index f1740a4dc..6f65b0179 100644 --- a/indra/newview/app_settings/shaders/class1/environment/underWaterF.glsl +++ b/indra/newview/app_settings/shaders/class1/environment/underWaterF.glsl @@ -4,6 +4,8 @@ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 uniform sampler2D diffuseMap; uniform sampler2D bumpMap; diff --git a/indra/newview/app_settings/shaders/class1/environment/waterF.glsl b/indra/newview/app_settings/shaders/class1/environment/waterF.glsl index 7e1788678..89217484f 100644 --- a/indra/newview/app_settings/shaders/class1/environment/waterF.glsl +++ b/indra/newview/app_settings/shaders/class1/environment/waterF.glsl @@ -4,6 +4,8 @@ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 vec3 scaleSoftClip(vec3 inColor); vec3 atmosTransport(vec3 inColor); diff --git a/indra/newview/app_settings/shaders/class1/environment/waterFogF.glsl b/indra/newview/app_settings/shaders/class1/environment/waterFogF.glsl index 7ee41998e..94296e0ba 100644 --- a/indra/newview/app_settings/shaders/class1/environment/waterFogF.glsl +++ b/indra/newview/app_settings/shaders/class1/environment/waterFogF.glsl @@ -4,6 +4,8 @@ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 vec4 applyWaterFog(vec4 color) { diff --git a/indra/newview/app_settings/shaders/class1/environment/waterV.glsl b/indra/newview/app_settings/shaders/class1/environment/waterV.glsl index 48ac87ef0..4dae985a7 100644 --- a/indra/newview/app_settings/shaders/class1/environment/waterV.glsl +++ b/indra/newview/app_settings/shaders/class1/environment/waterV.glsl @@ -4,6 +4,8 @@ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 void calcAtmospherics(vec3 inPositionEye); diff --git a/indra/newview/app_settings/shaders/class1/interface/highlightF.glsl b/indra/newview/app_settings/shaders/class1/interface/highlightF.glsl index 328c41652..5e4c123a8 100644 --- a/indra/newview/app_settings/shaders/class1/interface/highlightF.glsl +++ b/indra/newview/app_settings/shaders/class1/interface/highlightF.glsl @@ -4,6 +4,8 @@ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 uniform sampler2D diffuseMap; diff --git a/indra/newview/app_settings/shaders/class1/interface/highlightV.glsl b/indra/newview/app_settings/shaders/class1/interface/highlightV.glsl index a9ea6e856..4c052a35a 100644 --- a/indra/newview/app_settings/shaders/class1/interface/highlightV.glsl +++ b/indra/newview/app_settings/shaders/class1/interface/highlightV.glsl @@ -4,6 +4,8 @@ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 void main() { diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightF.glsl index 071489bca..65a87b5f6 100644 --- a/indra/newview/app_settings/shaders/class1/lighting/lightF.glsl +++ b/indra/newview/app_settings/shaders/class1/lighting/lightF.glsl @@ -4,6 +4,8 @@ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 uniform sampler2D diffuseMap; diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightF.glsl index b12cca912..7bfea160e 100644 --- a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightF.glsl +++ b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightF.glsl @@ -4,6 +4,8 @@ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 uniform sampler2D diffuseMap; diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightShinyF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightShinyF.glsl index bc795a751..32f52fbe8 100644 --- a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightShinyF.glsl +++ b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightShinyF.glsl @@ -4,6 +4,8 @@ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 uniform sampler2D diffuseMap; diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightShinyWaterF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightShinyWaterF.glsl new file mode 100644 index 000000000..1bdaccf9b --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightShinyWaterF.glsl @@ -0,0 +1,17 @@ +/** + * @file lightFullbrightShinyWaterF.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + + +#version 120 + +uniform sampler2D diffuseMap; +uniform samplerCube environmentMap; + +void fullbright_shiny_lighting_water() +{ + gl_FragColor = texture2D(diffuseMap, gl_TexCoord[0].xy); +} diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightWaterF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightWaterF.glsl index b13088fb1..89afa0ab2 100644 --- a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightWaterF.glsl +++ b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightWaterF.glsl @@ -5,6 +5,8 @@ * $License$ */ + +#version 120 uniform sampler2D diffuseMap; diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightFuncSpecularV.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightFuncSpecularV.glsl index bbbd9f3df..4ce4bc0cb 100644 --- a/indra/newview/app_settings/shaders/class1/lighting/lightFuncSpecularV.glsl +++ b/indra/newview/app_settings/shaders/class1/lighting/lightFuncSpecularV.glsl @@ -4,6 +4,8 @@ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 float calcDirectionalLight(vec3 n, vec3 l) { diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightFuncV.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightFuncV.glsl index 3e8fdfb3e..a437d075a 100644 --- a/indra/newview/app_settings/shaders/class1/lighting/lightFuncV.glsl +++ b/indra/newview/app_settings/shaders/class1/lighting/lightFuncV.glsl @@ -4,6 +4,8 @@ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 float calcDirectionalLight(vec3 n, vec3 l) @@ -12,7 +14,8 @@ float calcDirectionalLight(vec3 n, vec3 l) return a; } -float calcPointLight(vec3 v, vec3 n, vec4 lp, float la) + +float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float is_pointlight) { //get light vector vec3 lv = lp.xyz-v; @@ -26,6 +29,10 @@ float calcPointLight(vec3 v, vec3 n, vec4 lp, float la) //distance attenuation float da = clamp(1.0/(la * d), 0.0, 1.0); + // spotlight coefficient. + float spot = max(dot(-ln, lv), is_pointlight); + da *= spot*spot; // GL_SPOT_EXPONENT=2 + //angular attenuation da *= calcDirectionalLight(n, lv); diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightShinyF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightShinyF.glsl index 89785c45c..28dabb494 100644 --- a/indra/newview/app_settings/shaders/class1/lighting/lightShinyF.glsl +++ b/indra/newview/app_settings/shaders/class1/lighting/lightShinyF.glsl @@ -4,6 +4,8 @@ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 uniform sampler2D diffuseMap; diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightShinyWaterF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightShinyWaterF.glsl index 7ac3c359b..7985c17e0 100644 --- a/indra/newview/app_settings/shaders/class1/lighting/lightShinyWaterF.glsl +++ b/indra/newview/app_settings/shaders/class1/lighting/lightShinyWaterF.glsl @@ -4,6 +4,8 @@ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 uniform sampler2D diffuseMap; diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightSpecularV.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightSpecularV.glsl index 853212923..fddba5cff 100644 --- a/indra/newview/app_settings/shaders/class1/lighting/lightSpecularV.glsl +++ b/indra/newview/app_settings/shaders/class1/lighting/lightSpecularV.glsl @@ -4,6 +4,8 @@ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 float calcDirectionalLight(vec3 n, vec3 l); diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightV.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightV.glsl index 8c2813a85..8c01f3dd5 100644 --- a/indra/newview/app_settings/shaders/class1/lighting/lightV.glsl +++ b/indra/newview/app_settings/shaders/class1/lighting/lightV.glsl @@ -4,6 +4,8 @@ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 float calcDirectionalLight(vec3 n, vec3 l); diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightWaterF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightWaterF.glsl index 81dff1ef3..97506312a 100644 --- a/indra/newview/app_settings/shaders/class1/lighting/lightWaterF.glsl +++ b/indra/newview/app_settings/shaders/class1/lighting/lightWaterF.glsl @@ -4,6 +4,8 @@ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 uniform sampler2D diffuseMap; diff --git a/indra/newview/app_settings/shaders/class1/lighting/sumLightsSpecularV.glsl b/indra/newview/app_settings/shaders/class1/lighting/sumLightsSpecularV.glsl index 218585fb8..4146b8121 100644 --- a/indra/newview/app_settings/shaders/class1/lighting/sumLightsSpecularV.glsl +++ b/indra/newview/app_settings/shaders/class1/lighting/sumLightsSpecularV.glsl @@ -4,6 +4,9 @@ * Copyright (c) 2005-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 + float calcDirectionalLightSpecular(inout vec4 specular, vec3 view, vec3 n, vec3 l, vec3 lightCol, float da); vec3 atmosAmbient(vec3 light); vec3 atmosAffectDirectionalLight(float lightIntensity); diff --git a/indra/newview/app_settings/shaders/class1/lighting/sumLightsV.glsl b/indra/newview/app_settings/shaders/class1/lighting/sumLightsV.glsl index e5361033e..df198eafc 100644 --- a/indra/newview/app_settings/shaders/class1/lighting/sumLightsV.glsl +++ b/indra/newview/app_settings/shaders/class1/lighting/sumLightsV.glsl @@ -4,6 +4,8 @@ * Copyright (c) 2005-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 float calcDirectionalLight(vec3 n, vec3 l); diff --git a/indra/newview/app_settings/shaders/class1/objects/fullbrightF.glsl b/indra/newview/app_settings/shaders/class1/objects/fullbrightF.glsl index 1b0ffb911..028b51cbb 100755 --- a/indra/newview/app_settings/shaders/class1/objects/fullbrightF.glsl +++ b/indra/newview/app_settings/shaders/class1/objects/fullbrightF.glsl @@ -4,6 +4,8 @@ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 void fullbright_lighting(); diff --git a/indra/newview/app_settings/shaders/class1/objects/fullbrightShinyF.glsl b/indra/newview/app_settings/shaders/class1/objects/fullbrightShinyF.glsl index 936c228b4..b474ac55d 100644 --- a/indra/newview/app_settings/shaders/class1/objects/fullbrightShinyF.glsl +++ b/indra/newview/app_settings/shaders/class1/objects/fullbrightShinyF.glsl @@ -4,6 +4,8 @@ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 void fullbright_shiny_lighting(); diff --git a/indra/newview/app_settings/shaders/class1/objects/fullbrightShinyV.glsl b/indra/newview/app_settings/shaders/class1/objects/fullbrightShinyV.glsl index ba2aa024d..75b841a5f 100755 --- a/indra/newview/app_settings/shaders/class1/objects/fullbrightShinyV.glsl +++ b/indra/newview/app_settings/shaders/class1/objects/fullbrightShinyV.glsl @@ -4,6 +4,8 @@ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 void calcAtmospherics(vec3 inPositionEye); diff --git a/indra/newview/app_settings/shaders/class1/objects/fullbrightShinyWaterF.glsl b/indra/newview/app_settings/shaders/class1/objects/fullbrightShinyWaterF.glsl new file mode 100644 index 000000000..5daf66fb3 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/objects/fullbrightShinyWaterF.glsl @@ -0,0 +1,15 @@ +/** + * @file fullbrightShinyWaterF.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +#version 120 + +void fullbright_shiny_lighting_water(); + +void main() +{ + fullbright_shiny_lighting_water(); +} diff --git a/indra/newview/app_settings/shaders/class1/objects/fullbrightV.glsl b/indra/newview/app_settings/shaders/class1/objects/fullbrightV.glsl index e64ccb844..690a5d996 100755 --- a/indra/newview/app_settings/shaders/class1/objects/fullbrightV.glsl +++ b/indra/newview/app_settings/shaders/class1/objects/fullbrightV.glsl @@ -4,6 +4,8 @@ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 void calcAtmospherics(vec3 inPositionEye); diff --git a/indra/newview/app_settings/shaders/class1/objects/fullbrightWaterF.glsl b/indra/newview/app_settings/shaders/class1/objects/fullbrightWaterF.glsl index fd855aa91..8645dc3a8 100755 --- a/indra/newview/app_settings/shaders/class1/objects/fullbrightWaterF.glsl +++ b/indra/newview/app_settings/shaders/class1/objects/fullbrightWaterF.glsl @@ -4,6 +4,8 @@ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 void fullbright_lighting_water(); diff --git a/indra/newview/app_settings/shaders/class1/objects/shinyF.glsl b/indra/newview/app_settings/shaders/class1/objects/shinyF.glsl index bdb0b05f9..1d83116b1 100644 --- a/indra/newview/app_settings/shaders/class1/objects/shinyF.glsl +++ b/indra/newview/app_settings/shaders/class1/objects/shinyF.glsl @@ -4,6 +4,8 @@ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 void shiny_lighting(); diff --git a/indra/newview/app_settings/shaders/class1/objects/shinyV.glsl b/indra/newview/app_settings/shaders/class1/objects/shinyV.glsl index c2e1ddf73..3fb9a298c 100644 --- a/indra/newview/app_settings/shaders/class1/objects/shinyV.glsl +++ b/indra/newview/app_settings/shaders/class1/objects/shinyV.glsl @@ -4,6 +4,8 @@ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 void calcAtmospherics(vec3 inPositionEye); diff --git a/indra/newview/app_settings/shaders/class1/objects/shinyWaterF.glsl b/indra/newview/app_settings/shaders/class1/objects/shinyWaterF.glsl index 0a2a5f624..1fc497e49 100755 --- a/indra/newview/app_settings/shaders/class1/objects/shinyWaterF.glsl +++ b/indra/newview/app_settings/shaders/class1/objects/shinyWaterF.glsl @@ -4,6 +4,8 @@ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 void shiny_lighting_water(); diff --git a/indra/newview/app_settings/shaders/class1/objects/simpleF.glsl b/indra/newview/app_settings/shaders/class1/objects/simpleF.glsl index 7dacca4fe..97f5741b3 100644 --- a/indra/newview/app_settings/shaders/class1/objects/simpleF.glsl +++ b/indra/newview/app_settings/shaders/class1/objects/simpleF.glsl @@ -4,6 +4,8 @@ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 void default_lighting(); diff --git a/indra/newview/app_settings/shaders/class1/objects/simpleV.glsl b/indra/newview/app_settings/shaders/class1/objects/simpleV.glsl index 78b96b302..03167cfc6 100644 --- a/indra/newview/app_settings/shaders/class1/objects/simpleV.glsl +++ b/indra/newview/app_settings/shaders/class1/objects/simpleV.glsl @@ -4,6 +4,8 @@ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol); void calcAtmospherics(vec3 inPositionEye); diff --git a/indra/newview/app_settings/shaders/class1/objects/simpleWaterF.glsl b/indra/newview/app_settings/shaders/class1/objects/simpleWaterF.glsl index e066b3d02..e133dcf41 100755 --- a/indra/newview/app_settings/shaders/class1/objects/simpleWaterF.glsl +++ b/indra/newview/app_settings/shaders/class1/objects/simpleWaterF.glsl @@ -4,6 +4,8 @@ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 void default_lighting_water(); diff --git a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsF.glsl b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsF.glsl index 248c32201..4c20ad758 100644 --- a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsF.glsl +++ b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsF.glsl @@ -4,6 +4,8 @@ * Copyright (c) 2005-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 vec3 atmosLighting(vec3 light) { diff --git a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsHelpersV.glsl b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsHelpersV.glsl index c2c39e2e1..e83180714 100644 --- a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsHelpersV.glsl +++ b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsHelpersV.glsl @@ -4,6 +4,8 @@ * Copyright (c) 2005-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 vec3 atmosAmbient(vec3 light) { diff --git a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsV.glsl b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsV.glsl index 551b64340..c5adb50e4 100644 --- a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsV.glsl +++ b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsV.glsl @@ -4,6 +4,8 @@ * Copyright (c) 2005-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 void setPositionEye(vec3 v); diff --git a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsVarsF.glsl b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsVarsF.glsl index c001a4070..f8405b4d5 100644 --- a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsVarsF.glsl +++ b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsVarsF.glsl @@ -4,6 +4,8 @@ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 varying vec3 vary_PositionEye; diff --git a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsVarsV.glsl b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsVarsV.glsl index 1b263b085..658767427 100644 --- a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsVarsV.glsl +++ b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsVarsV.glsl @@ -4,6 +4,8 @@ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 varying vec3 vary_PositionEye; diff --git a/indra/newview/app_settings/shaders/class1/windlight/gammaF.glsl b/indra/newview/app_settings/shaders/class1/windlight/gammaF.glsl index c1ffda159..76a072000 100644 --- a/indra/newview/app_settings/shaders/class1/windlight/gammaF.glsl +++ b/indra/newview/app_settings/shaders/class1/windlight/gammaF.glsl @@ -4,6 +4,8 @@ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 uniform vec4 gamma; diff --git a/indra/newview/app_settings/shaders/class1/windlight/transportF.glsl b/indra/newview/app_settings/shaders/class1/windlight/transportF.glsl index 7097906fd..77ed3ea2b 100644 --- a/indra/newview/app_settings/shaders/class1/windlight/transportF.glsl +++ b/indra/newview/app_settings/shaders/class1/windlight/transportF.glsl @@ -4,6 +4,8 @@ * Copyright (c) 2005-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 vec3 atmosTransport(vec3 light) { diff --git a/indra/newview/app_settings/shaders/class2/avatar/eyeballV.glsl b/indra/newview/app_settings/shaders/class2/avatar/eyeballV.glsl index 3dd62d2d1..4af024f17 100644 --- a/indra/newview/app_settings/shaders/class2/avatar/eyeballV.glsl +++ b/indra/newview/app_settings/shaders/class2/avatar/eyeballV.glsl @@ -4,6 +4,8 @@ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 vec4 calcLightingSpecular(vec3 pos, vec3 norm, vec4 color, inout vec4 specularColor, vec4 baseCol); void calcAtmospherics(vec3 inPositionEye); diff --git a/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl b/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl new file mode 100644 index 000000000..f234f57d4 --- /dev/null +++ b/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl @@ -0,0 +1,125 @@ +/** + * @file alphaF.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $/LicenseInfo$ + */ + +#version 120 + +#extension GL_ARB_texture_rectangle : enable + +uniform sampler2D diffuseMap; +uniform sampler2DRectShadow shadowMap0; +uniform sampler2DRectShadow shadowMap1; +uniform sampler2DRectShadow shadowMap2; +uniform sampler2DRectShadow shadowMap3; +uniform sampler2DRect depthMap; + +uniform mat4 shadow_matrix[6]; +uniform vec4 shadow_clip; +uniform vec2 screen_res; +uniform vec2 shadow_res; + +vec3 atmosLighting(vec3 light); +vec3 scaleSoftClip(vec3 light); + +varying vec3 vary_ambient; +varying vec3 vary_directional; +varying vec3 vary_fragcoord; +varying vec3 vary_position; +varying vec3 vary_pointlight_col; + +uniform float shadow_bias; + +uniform mat4 inv_proj; + +vec4 getPosition(vec2 pos_screen) +{ + float depth = texture2DRect(depthMap, pos_screen.xy).a; + vec2 sc = pos_screen.xy*2.0; + sc /= screen_res; + sc -= vec2(1.0,1.0); + vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); + vec4 pos = inv_proj * ndc; + pos.xyz /= pos.w; + pos.w = 1.0; + return pos; +} + +float pcfShadow(sampler2DRectShadow shadowMap, vec4 stc, float scl) +{ + stc.xyz /= stc.w; + stc.z += shadow_bias; + + float cs = shadow2DRect(shadowMap, stc.xyz).x; + float shadow = cs; + + shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(scl, scl, 0.0)).x, cs); + shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(scl, -scl, 0.0)).x, cs); + shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(-scl, scl, 0.0)).x, cs); + shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(-scl, -scl, 0.0)).x, cs); + + return shadow/5.0; +} + + +void main() +{ + vec2 frag = vary_fragcoord.xy/vary_fragcoord.z*0.5+0.5; + frag *= screen_res; + + float shadow = 1.0; + vec4 pos = vec4(vary_position, 1.0); + + vec4 spos = pos; + + if (spos.z > -shadow_clip.w) + { + vec4 lpos; + + if (spos.z < -shadow_clip.z) + { + lpos = shadow_matrix[3]*spos; + lpos.xy *= shadow_res; + shadow = pcfShadow(shadowMap3, lpos, 1.5); + shadow += max((pos.z+shadow_clip.z)/(shadow_clip.z-shadow_clip.w)*2.0-1.0, 0.0); + } + else if (spos.z < -shadow_clip.y) + { + lpos = shadow_matrix[2]*spos; + lpos.xy *= shadow_res; + shadow = pcfShadow(shadowMap2, lpos, 1.5); + } + else if (spos.z < -shadow_clip.x) + { + lpos = shadow_matrix[1]*spos; + lpos.xy *= shadow_res; + shadow = pcfShadow(shadowMap1, lpos, 1.5); + } + else + { + lpos = shadow_matrix[0]*spos; + lpos.xy *= shadow_res; + shadow = pcfShadow(shadowMap0, lpos, 1.5); + } + } + + vec4 diff= texture2D(diffuseMap, gl_TexCoord[0].xy); + + vec4 col = vec4(vary_ambient + vary_directional.rgb*shadow, gl_Color.a); + vec4 color = diff * col; + + color.rgb = atmosLighting(color.rgb); + + color.rgb = scaleSoftClip(color.rgb); + + color.rgb += diff.rgb * vary_pointlight_col.rgb; + + //gl_FragColor = gl_Color; + gl_FragColor = color; + //gl_FragColor.r = 0.0; + //gl_FragColor = vec4(1,0,1,1)*shadow; + +} + diff --git a/indra/newview/app_settings/shaders/class2/deferred/alphaV.glsl b/indra/newview/app_settings/shaders/class2/deferred/alphaV.glsl new file mode 100644 index 000000000..7024025f7 --- /dev/null +++ b/indra/newview/app_settings/shaders/class2/deferred/alphaV.glsl @@ -0,0 +1,100 @@ +/** + * @file alphaV.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $/LicenseInfo$ + */ + +#version 120 + +vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol); +void calcAtmospherics(vec3 inPositionEye); + +float calcDirectionalLight(vec3 n, vec3 l); + +vec3 atmosAmbient(vec3 light); +vec3 atmosAffectDirectionalLight(float lightIntensity); +vec3 scaleDownLight(vec3 light); +vec3 scaleUpLight(vec3 light); + +varying vec3 vary_ambient; +varying vec3 vary_directional; +varying vec3 vary_fragcoord; +varying vec3 vary_position; +varying vec3 vary_pointlight_col; + +uniform float near_clip; +uniform float shadow_offset; +uniform float shadow_bias; + +float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float fa, float is_pointlight) +{ + //get light vector + vec3 lv = lp.xyz-v; + + //get distance + float d = length(lv); + + //normalize light vector + lv *= 1.0/d; + + //distance attenuation + float dist2 = d*d/(la*la); + float da = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0); + + // spotlight coefficient. + float spot = max(dot(-ln, lv), is_pointlight); + da *= spot*spot; // GL_SPOT_EXPONENT=2 + + //angular attenuation + da *= calcDirectionalLight(n, lv); + + return da; +} + +void main() +{ + //transform vertex + gl_Position = ftransform(); + + gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; + + vec4 pos = (gl_ModelViewMatrix * gl_Vertex); + vec3 norm = normalize(gl_NormalMatrix * gl_Normal); + + float dp_directional_light = max(0.0, dot(norm, gl_LightSource[0].position.xyz)); + vary_position = pos.xyz + gl_LightSource[0].position.xyz * (1.0-dp_directional_light)*shadow_offset; + + calcAtmospherics(pos.xyz); + + //vec4 color = calcLighting(pos.xyz, norm, gl_Color, vec4(0.)); + vec4 col = vec4(0.0, 0.0, 0.0, gl_Color.a); + + // Collect normal lights + col.rgb += gl_LightSource[2].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[2].position, gl_LightSource[2].spotDirection.xyz, gl_LightSource[2].linearAttenuation, gl_LightSource[2].quadraticAttenuation, gl_LightSource[2].specular.a); + col.rgb += gl_LightSource[3].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[3].position, gl_LightSource[3].spotDirection.xyz, gl_LightSource[3].linearAttenuation, gl_LightSource[3].quadraticAttenuation ,gl_LightSource[3].specular.a); + col.rgb += gl_LightSource[4].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[4].position, gl_LightSource[4].spotDirection.xyz, gl_LightSource[4].linearAttenuation, gl_LightSource[4].quadraticAttenuation, gl_LightSource[4].specular.a); + col.rgb += gl_LightSource[5].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[5].position, gl_LightSource[5].spotDirection.xyz, gl_LightSource[5].linearAttenuation, gl_LightSource[5].quadraticAttenuation, gl_LightSource[5].specular.a); + col.rgb += gl_LightSource[6].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[6].position, gl_LightSource[6].spotDirection.xyz, gl_LightSource[6].linearAttenuation, gl_LightSource[6].quadraticAttenuation, gl_LightSource[6].specular.a); + col.rgb += gl_LightSource[7].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[7].position, gl_LightSource[7].spotDirection.xyz, gl_LightSource[7].linearAttenuation, gl_LightSource[7].quadraticAttenuation, gl_LightSource[7].specular.a); + + vary_pointlight_col = col.rgb*gl_Color.rgb; + + col.rgb = vec3(0,0,0); + + // Add windlight lights + col.rgb = atmosAmbient(vec3(0.)); + + vary_ambient = col.rgb*gl_Color.rgb; + vary_directional.rgb = gl_Color.rgb*atmosAffectDirectionalLight(max(calcDirectionalLight(norm, gl_LightSource[0].position.xyz), (1.0-gl_Color.a)*(1.0-gl_Color.a))); + + col.rgb = col.rgb*gl_Color.rgb; + + gl_FrontColor = col; + + gl_FogFragCoord = pos.z; + + pos = gl_ModelViewProjectionMatrix * gl_Vertex; + vary_fragcoord.xyz = pos.xyz + vec3(0,0,near_clip); + +} diff --git a/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaV.glsl b/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaV.glsl new file mode 100644 index 000000000..495e86c8d --- /dev/null +++ b/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaV.glsl @@ -0,0 +1,112 @@ +/** + * @file avatarAlphaV.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $/LicenseInfo$ + */ + +#version 120 + +vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol); +mat4 getSkinnedTransform(); +void calcAtmospherics(vec3 inPositionEye); + +float calcDirectionalLight(vec3 n, vec3 l); +float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float is_pointlight); + +vec3 atmosAmbient(vec3 light); +vec3 atmosAffectDirectionalLight(float lightIntensity); +vec3 scaleDownLight(vec3 light); +vec3 scaleUpLight(vec3 light); + +varying vec3 vary_position; +varying vec3 vary_ambient; +varying vec3 vary_directional; +varying vec3 vary_fragcoord; +varying vec3 vary_pointlight_col; + +uniform float near_clip; +uniform float shadow_offset; +uniform float shadow_bias; + +float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float fa, float is_pointlight) +{ + //get light vector + vec3 lv = lp.xyz-v; + + //get distance + float d = length(lv); + + //normalize light vector + lv *= 1.0/d; + + //distance attenuation + float dist2 = d*d/(la*la); + float da = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0); + + // spotlight coefficient. + float spot = max(dot(-ln, lv), is_pointlight); + da *= spot*spot; // GL_SPOT_EXPONENT=2 + + //angular attenuation + da *= calcDirectionalLight(n, lv); + + return da; +} + +void main() +{ + gl_TexCoord[0] = gl_MultiTexCoord0; + + vec4 pos; + vec3 norm; + + mat4 trans = getSkinnedTransform(); + pos.x = dot(trans[0], gl_Vertex); + pos.y = dot(trans[1], gl_Vertex); + pos.z = dot(trans[2], gl_Vertex); + pos.w = 1.0; + + norm.x = dot(trans[0].xyz, gl_Normal); + norm.y = dot(trans[1].xyz, gl_Normal); + norm.z = dot(trans[2].xyz, gl_Normal); + norm = normalize(norm); + + gl_Position = gl_ProjectionMatrix * pos; + + float dp_directional_light = max(0.0, dot(norm, gl_LightSource[0].position.xyz)); + vary_position = pos.xyz + gl_LightSource[0].position.xyz * (1.0-dp_directional_light)*shadow_offset; + + calcAtmospherics(pos.xyz); + + //vec4 color = calcLighting(pos.xyz, norm, gl_Color, vec4(0.)); + + vec4 col = vec4(0.0, 0.0, 0.0, gl_Color.a); + + // Collect normal lights + col.rgb += gl_LightSource[2].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[2].position, gl_LightSource[2].spotDirection.xyz, gl_LightSource[2].linearAttenuation, gl_LightSource[2].quadraticAttenuation, gl_LightSource[2].specular.a); + col.rgb += gl_LightSource[3].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[3].position, gl_LightSource[3].spotDirection.xyz, gl_LightSource[3].linearAttenuation, gl_LightSource[3].quadraticAttenuation ,gl_LightSource[3].specular.a); + col.rgb += gl_LightSource[4].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[4].position, gl_LightSource[4].spotDirection.xyz, gl_LightSource[4].linearAttenuation, gl_LightSource[4].quadraticAttenuation, gl_LightSource[4].specular.a); + col.rgb += gl_LightSource[5].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[5].position, gl_LightSource[5].spotDirection.xyz, gl_LightSource[5].linearAttenuation, gl_LightSource[5].quadraticAttenuation, gl_LightSource[5].specular.a); + col.rgb += gl_LightSource[6].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[6].position, gl_LightSource[6].spotDirection.xyz, gl_LightSource[6].linearAttenuation, gl_LightSource[6].quadraticAttenuation, gl_LightSource[6].specular.a); + col.rgb += gl_LightSource[7].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[7].position, gl_LightSource[7].spotDirection.xyz, gl_LightSource[7].linearAttenuation, gl_LightSource[7].quadraticAttenuation, gl_LightSource[7].specular.a); + + vary_pointlight_col = col.rgb*gl_Color.rgb; + + col.rgb = vec3(0,0,0); + + // Add windlight lights + col.rgb = atmosAmbient(vec3(0.)); + + vary_ambient = col.rgb*gl_Color.rgb; + vary_directional = gl_Color.rgb*atmosAffectDirectionalLight(max(calcDirectionalLight(norm, gl_LightSource[0].position.xyz), (1.0-gl_Color.a)*(1.0-gl_Color.a))); + + col.rgb = min(col.rgb*gl_Color.rgb, 1.0); + + gl_FrontColor = col; + + gl_FogFragCoord = pos.z; + vary_fragcoord.xyz = pos.xyz + vec3(0,0,near_clip); +} + + diff --git a/indra/newview/app_settings/shaders/class2/deferred/edgeF.glsl b/indra/newview/app_settings/shaders/class2/deferred/edgeF.glsl new file mode 100644 index 000000000..3155f3f92 --- /dev/null +++ b/indra/newview/app_settings/shaders/class2/deferred/edgeF.glsl @@ -0,0 +1,63 @@ +/** + * @file edgeF.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $/LicenseInfo$ + */ + +#version 120 + +#extension GL_ARB_texture_rectangle : enable + +uniform sampler2DRect depthMap; +uniform sampler2DRect normalMap; + +varying vec2 vary_fragcoord; + +uniform float depth_cutoff; +uniform float norm_cutoff; + +uniform mat4 inv_proj; +uniform vec2 screen_res; + +float getDepth(vec2 pos_screen) +{ + float z = texture2DRect(depthMap, pos_screen.xy).a; + z = z*2.0-1.0; + vec4 ndc = vec4(0.0, 0.0, z, 1.0); + vec4 p = inv_proj*ndc; + return p.z/p.w; +} + +void main() +{ + vec3 norm = texture2DRect(normalMap, vary_fragcoord.xy).xyz; + norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm + float depth = getDepth(vary_fragcoord.xy); + + vec2 tc = vary_fragcoord.xy; + + float sc = 0.75; + + vec2 de; + de.x = (depth-getDepth(tc+vec2(sc, sc))) + (depth-getDepth(tc+vec2(-sc, -sc))); + de.y = (depth-getDepth(tc+vec2(-sc, sc))) + (depth-getDepth(tc+vec2(sc, -sc))); + de /= depth; + de *= de; + de = step(depth_cutoff, de); + + vec2 ne; + vec3 nexnorm = texture2DRect(normalMap, tc+vec2(-sc,-sc)).rgb; + nexnorm = vec3((nexnorm.xy-0.5)*2.0,nexnorm.z); // unpack norm + ne.x = dot(nexnorm, norm); + vec3 neynorm = texture2DRect(normalMap, tc+vec2(sc,sc)).rgb; + neynorm = vec3((neynorm.xy-0.5)*2.0,neynorm.z); // unpack norm + ne.y = dot(neynorm, norm); + + ne = 1.0-ne; + + ne = step(norm_cutoff, ne); + + gl_FragColor.a = dot(de,de)+dot(ne,ne); + //gl_FragColor.a = dot(de,de); +} diff --git a/indra/newview/app_settings/shaders/class2/deferred/edgeV.glsl b/indra/newview/app_settings/shaders/class2/deferred/edgeV.glsl new file mode 100644 index 000000000..b3413c301 --- /dev/null +++ b/indra/newview/app_settings/shaders/class2/deferred/edgeV.glsl @@ -0,0 +1,19 @@ +/** + * @file edgeV.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $/LicenseInfo$ + */ + +#version 120 + +varying vec2 vary_fragcoord; +uniform vec2 screen_res; + +void main() +{ + //transform vertex + gl_Position = ftransform(); + vec4 pos = gl_ModelViewProjectionMatrix * gl_Vertex; + vary_fragcoord = (pos.xy*0.5+0.5)*screen_res; +} diff --git a/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl new file mode 100644 index 000000000..d6cd984eb --- /dev/null +++ b/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl @@ -0,0 +1,236 @@ +/** + * @file multiSpotLightF.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $/LicenseInfo$ + */ + +#version 120 + +#extension GL_ARB_texture_rectangle : enable + +uniform sampler2DRect diffuseRect; +uniform sampler2DRect specularRect; +uniform sampler2DRect depthMap; +uniform sampler2DRect normalMap; +uniform samplerCube environmentMap; +uniform sampler2DRect lightMap; +uniform sampler2D noiseMap; +uniform sampler2D lightFunc; +uniform sampler2D projectionMap; + +uniform mat4 proj_mat; //screen space to light space +uniform float proj_near; //near clip for projection +uniform vec3 proj_p; //plane projection is emitting from (in screen space) +uniform vec3 proj_n; +uniform float proj_focus; //distance from plane to begin blurring +uniform float proj_lod; //(number of mips in proj map) +uniform float proj_range; //range between near clip and far clip plane of projection +uniform float proj_ambient_lod; +uniform float proj_ambiance; +uniform float near_clip; +uniform float far_clip; + +uniform vec3 proj_origin; //origin of projection to be used for angular attenuation +uniform float sun_wash; +uniform int proj_shadow_idx; +uniform float shadow_fade; + +varying vec4 vary_light; + +varying vec4 vary_fragcoord; +uniform vec2 screen_res; + +uniform mat4 inv_proj; + +vec4 texture2DLodSpecular(sampler2D projectionMap, vec2 tc, float lod) +{ + vec4 ret = texture2DLod(projectionMap, tc, lod); + + vec2 dist = tc-vec2(0.5); + + float det = max(1.0-lod/(proj_lod*0.5), 0.0); + + float d = dot(dist,dist); + + ret *= min(clamp((0.25-d)/0.25, 0.0, 1.0)+det, 1.0); + + return ret; +} + +vec4 texture2DLodDiffuse(sampler2D projectionMap, vec2 tc, float lod) +{ + vec4 ret = texture2DLod(projectionMap, tc, 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); + + float edge = 0.25*det; + + ret *= clamp(d/edge, 0.0, 1.0); + + return ret; +} + +vec4 texture2DLodAmbient(sampler2D projectionMap, vec2 tc, float lod) +{ + vec4 ret = texture2DLod(projectionMap, tc, lod); + + vec2 dist = tc-vec2(0.5); + + float d = dot(dist,dist); + + ret *= min(clamp((0.25-d)/0.25, 0.0, 1.0), 1.0); + + return ret; +} + + +vec4 getPosition(vec2 pos_screen) +{ + float depth = texture2DRect(depthMap, pos_screen.xy).a; + vec2 sc = pos_screen.xy*2.0; + sc /= screen_res; + sc -= vec2(1.0,1.0); + vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); + vec4 pos = inv_proj * ndc; + pos /= pos.w; + pos.w = 1.0; + return pos; +} + +void main() +{ + vec4 frag = vary_fragcoord; + frag.xyz /= frag.w; + frag.xyz = frag.xyz*0.5+0.5; + frag.xy *= screen_res; + + vec3 pos = getPosition(frag.xy).xyz; + vec3 lv = vary_light.xyz-pos.xyz; + float dist2 = dot(lv,lv); + dist2 /= vary_light.w; + if (dist2 > 1.0) + { + discard; + } + + float shadow = 1.0; + + if (proj_shadow_idx >= 0) + { + vec4 shd = texture2DRect(lightMap, frag.xy); + float sh[2]; + sh[0] = shd.b; + sh[1] = shd.a; + shadow = min(sh[proj_shadow_idx]+shadow_fade, 1.0); + } + + vec3 norm = texture2DRect(normalMap, frag.xy).xyz; + norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm + + norm = normalize(norm); + float l_dist = -dot(lv, proj_n); + + vec4 proj_tc = (proj_mat * vec4(pos.xyz, 1.0)); + if (proj_tc.z < 0.0) + { + discard; + } + + proj_tc.xyz /= proj_tc.w; + + float fa = gl_Color.a+1.0; + float dist_atten = min(1.0-(dist2-1.0*(1.0-fa))/fa, 1.0); + if (dist_atten <= 0.0) + { + discard; + } + + lv = proj_origin-pos.xyz; + lv = normalize(lv); + float da = dot(norm, lv); + + vec3 col = vec3(0,0,0); + + vec3 diff_tex = texture2DRect(diffuseRect, frag.xy).rgb; + + float noise = texture2D(noiseMap, frag.xy/128.0).b; + if (proj_tc.z > 0.0 && + proj_tc.x < 1.0 && + proj_tc.y < 1.0 && + proj_tc.x > 0.0 && + proj_tc.y > 0.0) + { + float lit = 0.0; + float amb_da = proj_ambiance; + + if (da > 0.0) + { + float diff = clamp((l_dist-proj_focus)/proj_range, 0.0, 1.0); + float lod = diff * proj_lod; + + vec4 plcol = texture2DLodDiffuse(projectionMap, proj_tc.xy, lod); + + vec3 lcol = gl_Color.rgb * plcol.rgb * plcol.a; + + lit = da * dist_atten * noise; + + col = lcol*lit*diff_tex*shadow; + amb_da += (da*0.5)*(1.0-shadow)*proj_ambiance; + } + + //float diff = clamp((proj_range-proj_focus)/proj_range, 0.0, 1.0); + vec4 amb_plcol = texture2DLodAmbient(projectionMap, proj_tc.xy, proj_lod); + + amb_da += (da*da*0.5+0.5)*proj_ambiance; + + amb_da *= dist_atten * noise; + + amb_da = min(amb_da, 1.0-lit); + + col += amb_da*gl_Color.rgb*diff_tex.rgb*amb_plcol.rgb*amb_plcol.a; + } + + + vec4 spec = texture2DRect(specularRect, frag.xy); + if (spec.a > 0.0) + { + vec3 ref = reflect(normalize(pos), norm); + + //project from point pos in direction ref to plane proj_p, proj_n + vec3 pdelta = proj_p-pos; + float ds = dot(ref, proj_n); + + if (ds < 0.0) + { + vec3 pfinal = pos + ref * dot(pdelta, proj_n)/ds; + + vec4 stc = (proj_mat * vec4(pfinal.xyz, 1.0)); + + if (stc.z > 0.0) + { + stc.xy /= stc.w; + + float fatten = clamp(spec.a*spec.a+spec.a*0.5, 0.25, 1.0); + + stc.xy = (stc.xy - vec2(0.5)) * fatten + vec2(0.5); + + if (stc.x < 1.0 && + stc.y < 1.0 && + stc.x > 0.0 && + stc.y > 0.0) + { + vec4 scol = texture2DLodSpecular(projectionMap, stc.xy, proj_lod-spec.a*proj_lod); + col += dist_atten*scol.rgb*gl_Color.rgb*scol.a*spec.rgb*shadow; + } + } + } + } + + gl_FragColor.rgb = col; + gl_FragColor.a = 0.0; +} diff --git a/indra/newview/app_settings/shaders/class2/deferred/softenLightV.glsl b/indra/newview/app_settings/shaders/class2/deferred/softenLightV.glsl new file mode 100644 index 000000000..8f0bcca76 --- /dev/null +++ b/indra/newview/app_settings/shaders/class2/deferred/softenLightV.glsl @@ -0,0 +1,26 @@ +/** + * @file softenLightF.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $/LicenseInfo$ + */ + +#version 120 + +uniform vec2 screen_res; + +varying vec4 vary_light; +varying vec2 vary_fragcoord; +void main() +{ + //transform vertex + gl_Position = ftransform(); + + vec4 pos = gl_ModelViewProjectionMatrix * gl_Vertex; + vary_fragcoord = (pos.xy*0.5+0.5)*screen_res; + + vec4 tex = gl_MultiTexCoord0; + tex.w = 1.0; + + vary_light = gl_MultiTexCoord0; +} diff --git a/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl new file mode 100644 index 000000000..d0e242c2d --- /dev/null +++ b/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl @@ -0,0 +1,185 @@ +/** + * @file spotLightF.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $/LicenseInfo$ + */ + +#version 120 + +#extension GL_ARB_texture_rectangle : enable + +uniform sampler2DRect diffuseRect; +uniform sampler2DRect specularRect; +uniform sampler2DRect depthMap; +uniform sampler2DRect normalMap; +uniform samplerCube environmentMap; +uniform sampler2DRect lightMap; +uniform sampler2D noiseMap; +uniform sampler2D lightFunc; +uniform sampler2D projectionMap; + +uniform mat4 proj_mat; //screen space to light space +uniform float proj_near; //near clip for projection +uniform vec3 proj_p; //plane projection is emitting from (in screen space) +uniform vec3 proj_n; +uniform float proj_focus; //distance from plane to begin blurring +uniform float proj_lod; //(number of mips in proj map) +uniform float proj_range; //range between near clip and far clip plane of projection +uniform float proj_ambiance; +uniform float near_clip; +uniform float far_clip; + +uniform vec3 proj_origin; //origin of projection to be used for angular attenuation +uniform float sun_wash; +uniform int proj_shadow_idx; +uniform float shadow_fade; + +varying vec4 vary_light; + +varying vec4 vary_fragcoord; +uniform vec2 screen_res; + +uniform mat4 inv_proj; + +vec4 getPosition(vec2 pos_screen) +{ + float depth = texture2DRect(depthMap, pos_screen.xy).a; + vec2 sc = pos_screen.xy*2.0; + sc /= screen_res; + sc -= vec2(1.0,1.0); + vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); + vec4 pos = inv_proj * ndc; + pos /= pos.w; + pos.w = 1.0; + return pos; +} + +void main() +{ + vec4 frag = vary_fragcoord; + frag.xyz /= frag.w; + frag.xyz = frag.xyz*0.5+0.5; + frag.xy *= screen_res; + + float shadow = 1.0; + + if (proj_shadow_idx >= 0) + { + vec4 shd = texture2DRect(lightMap, frag.xy); + float sh[2]; + sh[0] = shd.b; + sh[1] = shd.a; + shadow = min(sh[proj_shadow_idx]+shadow_fade, 1.0); + } + + vec3 pos = getPosition(frag.xy).xyz; + vec3 lv = vary_light.xyz-pos.xyz; + float dist2 = dot(lv,lv); + dist2 /= vary_light.w; + if (dist2 > 1.0) + { + discard; + } + + vec3 norm = texture2DRect(normalMap, frag.xy).xyz; + norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm + + norm = normalize(norm); + float l_dist = -dot(lv, proj_n); + + vec4 proj_tc = (proj_mat * vec4(pos.xyz, 1.0)); + if (proj_tc.z < 0.0) + { + discard; + } + + proj_tc.xyz /= proj_tc.w; + + float fa = gl_Color.a+1.0; + float dist_atten = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0); + + lv = proj_origin-pos.xyz; + lv = normalize(lv); + float da = dot(norm, lv); + + vec3 col = vec3(0,0,0); + + vec3 diff_tex = texture2DRect(diffuseRect, frag.xy).rgb; + + float noise = texture2D(noiseMap, frag.xy/128.0).b; + if (proj_tc.z > 0.0 && + proj_tc.x < 1.0 && + proj_tc.y < 1.0 && + proj_tc.x > 0.0 && + proj_tc.y > 0.0) + { + float lit = 0.0; + if (da > 0.0) + { + float diff = clamp((l_dist-proj_focus)/proj_range, 0.0, 1.0); + float lod = diff * proj_lod; + + vec4 plcol = texture2DLod(projectionMap, proj_tc.xy, lod); + + vec3 lcol = gl_Color.rgb * plcol.rgb * plcol.a; + + lit = da * dist_atten * noise; + + col = lcol*lit*diff_tex*shadow; + } + + float diff = clamp((proj_range-proj_focus)/proj_range, 0.0, 1.0); + float lod = diff * proj_lod; + vec4 amb_plcol = texture2DLod(projectionMap, proj_tc.xy, lod); + //float amb_da = mix(proj_ambiance, proj_ambiance*max(-da, 0.0), max(da, 0.0)); + float amb_da = proj_ambiance; + if (da > 0.0) + { + amb_da += (da*0.5)*(1.0-shadow)*proj_ambiance; + } + + amb_da += (da*da*0.5+0.5)*proj_ambiance; + + amb_da *= dist_atten * noise; + + amb_da = min(amb_da, 1.0-lit); + + col += amb_da*gl_Color.rgb*diff_tex.rgb*amb_plcol.rgb*amb_plcol.a; + } + + + vec4 spec = texture2DRect(specularRect, frag.xy); + if (spec.a > 0.0) + { + vec3 ref = reflect(normalize(pos), norm); + + //project from point pos in direction ref to plane proj_p, proj_n + vec3 pdelta = proj_p-pos; + float ds = dot(ref, proj_n); + + if (ds < 0.0) + { + vec3 pfinal = pos + ref * dot(pdelta, proj_n)/ds; + + vec3 stc = (proj_mat * vec4(pfinal.xyz, 1.0)).xyz; + + if (stc.z > 0.0) + { + stc.xy /= stc.z+proj_near; + + if (stc.x < 1.0 && + stc.y < 1.0 && + stc.x > 0.0 && + stc.y > 0.0) + { + vec4 scol = texture2DLod(projectionMap, stc.xy, proj_lod-spec.a*proj_lod); + col += dist_atten*scol.rgb*gl_Color.rgb*scol.a*spec.rgb*shadow; + } + } + } + } + + gl_FragColor.rgb = col; + gl_FragColor.a = 0.0; +} diff --git a/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl new file mode 100644 index 000000000..4369b3b34 --- /dev/null +++ b/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl @@ -0,0 +1,196 @@ +/** + * @file sunLightF.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $/LicenseInfo$ + */ + +#version 120 + +#extension GL_ARB_texture_rectangle : enable + +//class 2, shadows, no SSAO + +uniform sampler2DRect depthMap; +uniform sampler2DRect normalMap; +uniform sampler2DRectShadow shadowMap0; +uniform sampler2DRectShadow shadowMap1; +uniform sampler2DRectShadow shadowMap2; +uniform sampler2DRectShadow shadowMap3; +uniform sampler2DShadow shadowMap4; +uniform sampler2DShadow shadowMap5; + + +// Inputs +uniform mat4 shadow_matrix[6]; +uniform vec4 shadow_clip; +uniform float ssao_radius; +uniform float ssao_max_radius; +uniform float ssao_factor; +uniform float ssao_factor_inv; + +varying vec2 vary_fragcoord; +varying vec4 vary_light; + +uniform mat4 inv_proj; +uniform vec2 screen_res; +uniform vec2 shadow_res; +uniform vec2 proj_shadow_res; + +uniform float shadow_bias; +uniform float shadow_offset; + +uniform float spot_shadow_bias; +uniform float spot_shadow_offset; + +vec4 getPosition(vec2 pos_screen) +{ + float depth = texture2DRect(depthMap, pos_screen.xy).a; + vec2 sc = pos_screen.xy*2.0; + sc /= screen_res; + sc -= vec2(1.0,1.0); + vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); + vec4 pos = inv_proj * ndc; + pos /= pos.w; + pos.w = 1.0; + return pos; +} + +float pcfShadow(sampler2DRectShadow shadowMap, vec4 stc, float scl) +{ + stc.xyz /= stc.w; + stc.z += shadow_bias*scl; + + float cs = shadow2DRect(shadowMap, stc.xyz).x; + float shadow = cs; + + shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(1.5, 1.5, 0.0)).x, cs); + shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(1.5, -1.5, 0.0)).x, cs); + shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(-1.5, 1.5, 0.0)).x, cs); + shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(-1.5, -1.5, 0.0)).x, cs); + + return shadow/5.0; + + //return shadow; +} + +float pcfShadow(sampler2DShadow shadowMap, vec4 stc, float scl) +{ + stc.xyz /= stc.w; + stc.z += spot_shadow_bias*scl; + + float cs = shadow2D(shadowMap, stc.xyz).x; + float shadow = cs; + + vec2 off = 1.5/proj_shadow_res; + + shadow += max(shadow2D(shadowMap, stc.xyz+vec3(off.x, off.y, 0.0)).x, cs); + shadow += max(shadow2D(shadowMap, stc.xyz+vec3(off.x, -off.y, 0.0)).x, cs); + shadow += max(shadow2D(shadowMap, stc.xyz+vec3(-off.x, off.y, 0.0)).x, cs); + shadow += max(shadow2D(shadowMap, stc.xyz+vec3(-off.x, -off.y, 0.0)).x, cs); + + return shadow/5.0; + + //return shadow; +} + +void main() +{ + vec2 pos_screen = vary_fragcoord.xy; + + //try doing an unproject here + + vec4 pos = getPosition(pos_screen); + + vec4 nmap4 = texture2DRect(normalMap, pos_screen); + nmap4 = vec4((nmap4.xy-0.5)*2.0,nmap4.z,nmap4.w); // unpack norm + float displace = nmap4.w; + vec3 norm = nmap4.xyz; + + /*if (pos.z == 0.0) // do nothing for sky *FIX: REMOVE THIS IF/WHEN THE POSITION MAP IS BEING USED AS A STENCIL + { + gl_FragColor = vec4(0.0); // doesn't matter + return; + }*/ + + float shadow = 1.0; + float dp_directional_light = max(0.0, dot(norm, vary_light.xyz)); + + vec3 shadow_pos = pos.xyz + displace*norm; + vec3 offset = vary_light.xyz * (1.0-dp_directional_light); + + vec4 spos = vec4(shadow_pos+offset*shadow_offset, 1.0); + + if (spos.z > -shadow_clip.w) + { + if (dp_directional_light == 0.0) + { + // if we know this point is facing away from the sun then we know it's in shadow without having to do a squirrelly shadow-map lookup + shadow = 0.0; + } + else + { + vec4 lpos; + + if (spos.z < -shadow_clip.z) + { + lpos = shadow_matrix[3]*spos; + lpos.xy *= shadow_res; + shadow = pcfShadow(shadowMap3, lpos, 0.25); + shadow += max((pos.z+shadow_clip.z)/(shadow_clip.z-shadow_clip.w)*2.0-1.0, 0.0); + } + else if (spos.z < -shadow_clip.y) + { + lpos = shadow_matrix[2]*spos; + lpos.xy *= shadow_res; + shadow = pcfShadow(shadowMap2, lpos, 0.5); + } + else if (spos.z < -shadow_clip.x) + { + lpos = shadow_matrix[1]*spos; + lpos.xy *= shadow_res; + shadow = pcfShadow(shadowMap1, lpos, 0.75); + } + else + { + lpos = shadow_matrix[0]*spos; + lpos.xy *= shadow_res; + shadow = pcfShadow(shadowMap0, lpos, 1.0); + } + + // take the most-shadowed value out of these two: + // * the blurred sun shadow in the light (shadow) map + // * an unblurred dot product between the sun and this norm + // the goal is to err on the side of most-shadow to fill-in shadow holes and reduce artifacting + shadow = min(shadow, dp_directional_light); + + //lpos.xy /= lpos.w*32.0; + //if (fract(lpos.x) < 0.1 || fract(lpos.y) < 0.1) + //{ + // shadow = 0.0; + //} + + } + } + else + { + // more distant than the shadow map covers + shadow = 1.0; + } + + gl_FragColor[0] = shadow; + gl_FragColor[1] = 1.0; + + spos = vec4(shadow_pos+norm*spot_shadow_offset, 1.0); + + //spotlight shadow 1 + vec4 lpos = shadow_matrix[4]*spos; + gl_FragColor[2] = pcfShadow(shadowMap4, lpos, 0.8); + + //spotlight shadow 2 + lpos = shadow_matrix[5]*spos; + gl_FragColor[3] = pcfShadow(shadowMap5, lpos, 0.8); + + //gl_FragColor.rgb = pos.xyz; + //gl_FragColor.b = shadow; +} diff --git a/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl b/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl new file mode 100644 index 000000000..fcea7aaf1 --- /dev/null +++ b/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl @@ -0,0 +1,252 @@ +/** + * @file sunLightSSAOF.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +#version 120 + +#extension GL_ARB_texture_rectangle : enable + +//class 2 -- shadows and SSAO + +uniform sampler2DRect depthMap; +uniform sampler2DRect normalMap; +uniform sampler2DRectShadow shadowMap0; +uniform sampler2DRectShadow shadowMap1; +uniform sampler2DRectShadow shadowMap2; +uniform sampler2DRectShadow shadowMap3; +uniform sampler2DShadow shadowMap4; +uniform sampler2DShadow shadowMap5; +uniform sampler2D noiseMap; + +// Inputs +uniform mat4 shadow_matrix[6]; +uniform vec4 shadow_clip; +uniform float ssao_radius; +uniform float ssao_max_radius; +uniform float ssao_factor; +uniform float ssao_factor_inv; + +varying vec2 vary_fragcoord; +varying vec4 vary_light; + +uniform mat4 inv_proj; +uniform vec2 screen_res; +uniform vec2 shadow_res; +uniform vec2 proj_shadow_res; + +uniform float shadow_bias; +uniform float shadow_offset; + +uniform float spot_shadow_bias; +uniform float spot_shadow_offset; + +vec4 getPosition(vec2 pos_screen) +{ + float depth = texture2DRect(depthMap, pos_screen.xy).a; + vec2 sc = pos_screen.xy*2.0; + sc /= screen_res; + sc -= vec2(1.0,1.0); + vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); + vec4 pos = inv_proj * ndc; + pos /= pos.w; + pos.w = 1.0; + return pos; +} + +//calculate decreases in ambient lighting when crowded out (SSAO) +float calcAmbientOcclusion(vec4 pos, vec3 norm) +{ + float ret = 1.0; + + float dist = dot(pos.xyz,pos.xyz); + + vec2 kern[8]; + // exponentially (^2) distant occlusion samples spread around origin + kern[0] = vec2(-1.0, 0.0) * 0.125*0.125; + kern[1] = vec2(1.0, 0.0) * 0.250*0.250; + kern[2] = vec2(0.0, 1.0) * 0.375*0.375; + kern[3] = vec2(0.0, -1.0) * 0.500*0.500; + kern[4] = vec2(0.7071, 0.7071) * 0.625*0.625; + kern[5] = vec2(-0.7071, -0.7071) * 0.750*0.750; + kern[6] = vec2(-0.7071, 0.7071) * 0.875*0.875; + kern[7] = vec2(0.7071, -0.7071) * 1.000*1.000; + + vec2 pos_screen = vary_fragcoord.xy; + vec3 pos_world = pos.xyz; + vec2 noise_reflect = texture2D(noiseMap, vary_fragcoord.xy/128.0).xy; + + float angle_hidden = 0.0; + int points = 0; + + float scale = min(ssao_radius / -pos_world.z, ssao_max_radius); + + // it was found that keeping # of samples a constant was the fastest, probably due to compiler optimizations (unrolling?) + for (int i = 0; i < 8; i++) + { + vec2 samppos_screen = pos_screen + scale * reflect(kern[i], noise_reflect); + vec3 samppos_world = getPosition(samppos_screen).xyz; + + vec3 diff = pos_world - samppos_world; + float dist2 = dot(diff, diff); + + // assume each sample corresponds to an occluding sphere with constant radius, constant x-sectional area + // --> solid angle shrinking by the square of distance + //radius is somewhat arbitrary, can approx with just some constant k * 1 / dist^2 + //(k should vary inversely with # of samples, but this is taken care of later) + + angle_hidden = angle_hidden + float(dot((samppos_world - 0.05*norm - pos_world), norm) > 0.0) * min(1.0/dist2, ssao_factor_inv); + + // 'blocked' samples (significantly closer to camera relative to pos_world) are "no data", not "no occlusion" + points = points + int(diff.z > -1.0); + } + + angle_hidden = min(ssao_factor*angle_hidden/float(points), 1.0); + + ret = (1.0 - (float(points != 0) * angle_hidden)); + ret += max((dist-32.0*32.0)/(32.0*32.0), 0.0); + + return min(ret, 1.0); +} + +float pcfShadow(sampler2DRectShadow shadowMap, vec4 stc, float scl) +{ + stc.xyz /= stc.w; + stc.z += shadow_bias*scl; + + float cs = shadow2DRect(shadowMap, stc.xyz).x; + float shadow = cs; + + shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(1.5, 1.5, 0.0)).x, cs); + shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(1.5, -1.5, 0.0)).x, cs); + shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(-1.5, 1.5, 0.0)).x, cs); + shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(-1.5, -1.5, 0.0)).x, cs); + + return shadow/5.0; + + //return shadow; +} + +float pcfShadow(sampler2DShadow shadowMap, vec4 stc, float scl) +{ + stc.xyz /= stc.w; + stc.z += spot_shadow_bias*scl; + + float cs = shadow2D(shadowMap, stc.xyz).x; + float shadow = cs; + + vec2 off = 1.5/proj_shadow_res; + + shadow += max(shadow2D(shadowMap, stc.xyz+vec3(off.x, off.y, 0.0)).x, cs); + shadow += max(shadow2D(shadowMap, stc.xyz+vec3(off.x, -off.y, 0.0)).x, cs); + shadow += max(shadow2D(shadowMap, stc.xyz+vec3(-off.x, off.y, 0.0)).x, cs); + shadow += max(shadow2D(shadowMap, stc.xyz+vec3(-off.x, -off.y, 0.0)).x, cs); + + + return shadow/5.0; + + //return shadow; +} + +void main() +{ + vec2 pos_screen = vary_fragcoord.xy; + + //try doing an unproject here + + vec4 pos = getPosition(pos_screen); + + vec4 nmap4 = texture2DRect(normalMap, pos_screen); + nmap4 = vec4((nmap4.xy-0.5)*2.0,nmap4.z,nmap4.w); // unpack norm + float displace = nmap4.w; + vec3 norm = nmap4.xyz; + + /*if (pos.z == 0.0) // do nothing for sky *FIX: REMOVE THIS IF/WHEN THE POSITION MAP IS BEING USED AS A STENCIL + { + gl_FragColor = vec4(0.0); // doesn't matter + return; + }*/ + + float shadow = 1.0; + float dp_directional_light = max(0.0, dot(norm, vary_light.xyz)); + + vec3 shadow_pos = pos.xyz + displace*norm; + vec3 offset = vary_light.xyz * (1.0-dp_directional_light); + + vec4 spos = vec4(shadow_pos+offset*shadow_offset, 1.0); + + if (spos.z > -shadow_clip.w) + { + if (dp_directional_light == 0.0) + { + // if we know this point is facing away from the sun then we know it's in shadow without having to do a squirrelly shadow-map lookup + shadow = 0.0; + } + else + { + vec4 lpos; + + if (spos.z < -shadow_clip.z) + { + lpos = shadow_matrix[3]*spos; + lpos.xy *= shadow_res; + shadow = pcfShadow(shadowMap3, lpos, 0.25); + shadow += max((pos.z+shadow_clip.z)/(shadow_clip.z-shadow_clip.w)*2.0-1.0, 0.0); + } + else if (spos.z < -shadow_clip.y) + { + lpos = shadow_matrix[2]*spos; + lpos.xy *= shadow_res; + shadow = pcfShadow(shadowMap2, lpos, 0.5); + } + else if (spos.z < -shadow_clip.x) + { + lpos = shadow_matrix[1]*spos; + lpos.xy *= shadow_res; + shadow = pcfShadow(shadowMap1, lpos, 0.75); + } + else + { + lpos = shadow_matrix[0]*spos; + lpos.xy *= shadow_res; + shadow = pcfShadow(shadowMap0, lpos, 1.0); + } + + // take the most-shadowed value out of these two: + // * the blurred sun shadow in the light (shadow) map + // * an unblurred dot product between the sun and this norm + // the goal is to err on the side of most-shadow to fill-in shadow holes and reduce artifacting + shadow = min(shadow, dp_directional_light); + + //lpos.xy /= lpos.w*32.0; + //if (fract(lpos.x) < 0.1 || fract(lpos.y) < 0.1) + //{ + // shadow = 0.0; + //} + + } + } + else + { + // more distant than the shadow map covers + shadow = 1.0; + } + + gl_FragColor[0] = shadow; + gl_FragColor[1] = calcAmbientOcclusion(pos, norm); + + spos.xyz = shadow_pos+offset*spot_shadow_offset; + + //spotlight shadow 1 + vec4 lpos = shadow_matrix[4]*spos; + gl_FragColor[2] = pcfShadow(shadowMap4, lpos, 0.8); + + //spotlight shadow 2 + lpos = shadow_matrix[5]*spos; + gl_FragColor[3] = pcfShadow(shadowMap5, lpos, 0.8); + + //gl_FragColor.rgb = pos.xyz; + //gl_FragColor.b = shadow; +} diff --git a/indra/newview/app_settings/shaders/class2/deferred/sunLightV.glsl b/indra/newview/app_settings/shaders/class2/deferred/sunLightV.glsl new file mode 100644 index 000000000..9beb513ad --- /dev/null +++ b/indra/newview/app_settings/shaders/class2/deferred/sunLightV.glsl @@ -0,0 +1,27 @@ +/** + * @file sunLightF.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $/LicenseInfo$ + */ + +#version 120 + +varying vec4 vary_light; +varying vec2 vary_fragcoord; + +uniform vec2 screen_res; + +void main() +{ + //transform vertex + gl_Position = ftransform(); + vec4 pos = gl_ModelViewProjectionMatrix * gl_Vertex; + vary_fragcoord = (pos.xy * 0.5 + 0.5)*screen_res; + vec4 tex = gl_MultiTexCoord0; + tex.w = 1.0; + + vary_light = gl_MultiTexCoord0; + + gl_FrontColor = gl_Color; +} diff --git a/indra/newview/app_settings/shaders/class2/effects/blurF.glsl b/indra/newview/app_settings/shaders/class2/effects/blurF.glsl index 7edfebab2..43f37a80a 100644 --- a/indra/newview/app_settings/shaders/class2/effects/blurF.glsl +++ b/indra/newview/app_settings/shaders/class2/effects/blurF.glsl @@ -5,6 +5,7 @@ * $License$ */ +#version 120 #extension GL_ARB_texture_rectangle : enable uniform sampler2DRect RenderTexture; diff --git a/indra/newview/app_settings/shaders/class2/effects/blurV.glsl b/indra/newview/app_settings/shaders/class2/effects/blurV.glsl index ba65b16cc..cf4218bf7 100644 --- a/indra/newview/app_settings/shaders/class2/effects/blurV.glsl +++ b/indra/newview/app_settings/shaders/class2/effects/blurV.glsl @@ -4,6 +4,8 @@ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 uniform vec2 texelSize; uniform vec2 blurDirection; diff --git a/indra/newview/app_settings/shaders/class2/effects/colorFilterF.glsl b/indra/newview/app_settings/shaders/class2/effects/colorFilterF.glsl index 729949a17..f57633950 100644 --- a/indra/newview/app_settings/shaders/class2/effects/colorFilterF.glsl +++ b/indra/newview/app_settings/shaders/class2/effects/colorFilterF.glsl @@ -5,6 +5,7 @@ * $License$ */ +#version 120 #extension GL_ARB_texture_rectangle : enable uniform sampler2DRect RenderTexture; diff --git a/indra/newview/app_settings/shaders/class2/effects/drawQuadV.glsl b/indra/newview/app_settings/shaders/class2/effects/drawQuadV.glsl index 29c2a0948..229ede470 100644 --- a/indra/newview/app_settings/shaders/class2/effects/drawQuadV.glsl +++ b/indra/newview/app_settings/shaders/class2/effects/drawQuadV.glsl @@ -4,6 +4,8 @@ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 void main(void) { diff --git a/indra/newview/app_settings/shaders/class2/effects/extractF.glsl b/indra/newview/app_settings/shaders/class2/effects/extractF.glsl index f9eee5b89..fdf547264 100644 --- a/indra/newview/app_settings/shaders/class2/effects/extractF.glsl +++ b/indra/newview/app_settings/shaders/class2/effects/extractF.glsl @@ -5,6 +5,7 @@ * $License$ */ +#version 120 #extension GL_ARB_texture_rectangle : enable uniform sampler2DRect RenderTexture; diff --git a/indra/newview/app_settings/shaders/class2/effects/nightVisionF.glsl b/indra/newview/app_settings/shaders/class2/effects/nightVisionF.glsl index 833ef7d30..f6dfa52a9 100644 --- a/indra/newview/app_settings/shaders/class2/effects/nightVisionF.glsl +++ b/indra/newview/app_settings/shaders/class2/effects/nightVisionF.glsl @@ -5,6 +5,7 @@ * $License$ */ +#version 120 #extension GL_ARB_texture_rectangle : enable uniform sampler2DRect RenderTexture; diff --git a/indra/newview/app_settings/shaders/class2/effects/simpleF.glsl b/indra/newview/app_settings/shaders/class2/effects/simpleF.glsl index 3a236846c..3dbed8e01 100644 --- a/indra/newview/app_settings/shaders/class2/effects/simpleF.glsl +++ b/indra/newview/app_settings/shaders/class2/effects/simpleF.glsl @@ -5,6 +5,7 @@ * $License$ */ +#version 120 #extension GL_ARB_texture_rectangle : enable uniform sampler2DRect RenderTexture; diff --git a/indra/newview/app_settings/shaders/class2/environment/terrainF.glsl b/indra/newview/app_settings/shaders/class2/environment/terrainF.glsl index 4253bc21c..9ccc776ad 100644 --- a/indra/newview/app_settings/shaders/class2/environment/terrainF.glsl +++ b/indra/newview/app_settings/shaders/class2/environment/terrainF.glsl @@ -4,6 +4,8 @@ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 uniform sampler2D detail_0; uniform sampler2D detail_1; diff --git a/indra/newview/app_settings/shaders/class2/environment/terrainV.glsl b/indra/newview/app_settings/shaders/class2/environment/terrainV.glsl index 119d55a2c..19211b8e6 100644 --- a/indra/newview/app_settings/shaders/class2/environment/terrainV.glsl +++ b/indra/newview/app_settings/shaders/class2/environment/terrainV.glsl @@ -4,6 +4,8 @@ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 void calcAtmospherics(vec3 inPositionEye); diff --git a/indra/newview/app_settings/shaders/class2/environment/terrainWaterF.glsl b/indra/newview/app_settings/shaders/class2/environment/terrainWaterF.glsl index 3a98970f8..6f2f560a9 100755 --- a/indra/newview/app_settings/shaders/class2/environment/terrainWaterF.glsl +++ b/indra/newview/app_settings/shaders/class2/environment/terrainWaterF.glsl @@ -4,6 +4,8 @@ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 uniform sampler2D detail_0; uniform sampler2D detail_1; diff --git a/indra/newview/app_settings/shaders/class2/environment/underWaterF.glsl b/indra/newview/app_settings/shaders/class2/environment/underWaterF.glsl index 1998fea22..246b55440 100644 --- a/indra/newview/app_settings/shaders/class2/environment/underWaterF.glsl +++ b/indra/newview/app_settings/shaders/class2/environment/underWaterF.glsl @@ -4,6 +4,8 @@ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 uniform sampler2D diffuseMap; uniform sampler2D bumpMap; diff --git a/indra/newview/app_settings/shaders/class2/environment/waterF.glsl b/indra/newview/app_settings/shaders/class2/environment/waterF.glsl index 6ec3dc478..246377382 100644 --- a/indra/newview/app_settings/shaders/class2/environment/waterF.glsl +++ b/indra/newview/app_settings/shaders/class2/environment/waterF.glsl @@ -4,6 +4,8 @@ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 vec3 scaleSoftClip(vec3 inColor); vec3 atmosTransport(vec3 inColor); diff --git a/indra/newview/app_settings/shaders/class2/environment/waterFogF.glsl b/indra/newview/app_settings/shaders/class2/environment/waterFogF.glsl index 522c990cf..25d65b571 100644 --- a/indra/newview/app_settings/shaders/class2/environment/waterFogF.glsl +++ b/indra/newview/app_settings/shaders/class2/environment/waterFogF.glsl @@ -4,6 +4,8 @@ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 uniform vec4 lightnorm; uniform vec4 waterPlane; diff --git a/indra/newview/app_settings/shaders/class2/lighting/lightF.glsl b/indra/newview/app_settings/shaders/class2/lighting/lightF.glsl index b372d6629..e7779d357 100644 --- a/indra/newview/app_settings/shaders/class2/lighting/lightF.glsl +++ b/indra/newview/app_settings/shaders/class2/lighting/lightF.glsl @@ -4,6 +4,8 @@ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 uniform sampler2D diffuseMap; diff --git a/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightF.glsl b/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightF.glsl index e6b6d8580..509ac80b2 100644 --- a/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightF.glsl +++ b/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightF.glsl @@ -4,6 +4,8 @@ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 uniform sampler2D diffuseMap; diff --git a/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightShinyF.glsl b/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightShinyF.glsl index 8f408c043..17a4cb03f 100644 --- a/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightShinyF.glsl +++ b/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightShinyF.glsl @@ -4,6 +4,8 @@ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 uniform sampler2D diffuseMap; uniform samplerCube environmentMap; diff --git a/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightShinyWaterF.glsl b/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightShinyWaterF.glsl new file mode 100644 index 000000000..9b4b58436 --- /dev/null +++ b/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightShinyWaterF.glsl @@ -0,0 +1,31 @@ +/** + * @file lightFullbrightShinyWaterF.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + +#version 120 + +uniform sampler2D diffuseMap; +uniform samplerCube environmentMap; + +vec3 fullbrightShinyAtmosTransport(vec3 light); +vec3 fullbrightScaleSoftClip(vec3 light); +vec4 applyWaterFog(vec4 color); + +void fullbright_shiny_lighting_water() +{ + vec4 color = texture2D(diffuseMap, gl_TexCoord[0].xy); + color.rgb *= gl_Color.rgb; + + vec3 envColor = textureCube(environmentMap, gl_TexCoord[1].xyz).rgb; + color.rgb = mix(color.rgb, envColor.rgb, gl_Color.a); + + color.rgb = fullbrightShinyAtmosTransport(color.rgb); + color.rgb = fullbrightScaleSoftClip(color.rgb); + color.a = max(color.a, gl_Color.a); + + gl_FragColor = applyWaterFog(color); +} + diff --git a/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightWaterF.glsl b/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightWaterF.glsl index 060ad9cb6..548d1c9ee 100644 --- a/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightWaterF.glsl +++ b/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightWaterF.glsl @@ -4,6 +4,8 @@ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 uniform sampler2D diffuseMap; diff --git a/indra/newview/app_settings/shaders/class2/lighting/lightShinyF.glsl b/indra/newview/app_settings/shaders/class2/lighting/lightShinyF.glsl index b3927c77a..675fd4adf 100644 --- a/indra/newview/app_settings/shaders/class2/lighting/lightShinyF.glsl +++ b/indra/newview/app_settings/shaders/class2/lighting/lightShinyF.glsl @@ -4,6 +4,8 @@ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 uniform sampler2D diffuseMap; uniform samplerCube environmentMap; diff --git a/indra/newview/app_settings/shaders/class2/lighting/lightShinyWaterF.glsl b/indra/newview/app_settings/shaders/class2/lighting/lightShinyWaterF.glsl index f090306be..4e8a0d189 100644 --- a/indra/newview/app_settings/shaders/class2/lighting/lightShinyWaterF.glsl +++ b/indra/newview/app_settings/shaders/class2/lighting/lightShinyWaterF.glsl @@ -4,6 +4,8 @@ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 uniform sampler2D diffuseMap; diff --git a/indra/newview/app_settings/shaders/class2/lighting/lightSpecularV.glsl b/indra/newview/app_settings/shaders/class2/lighting/lightSpecularV.glsl index c3384ffc5..4e9fa16a1 100644 --- a/indra/newview/app_settings/shaders/class2/lighting/lightSpecularV.glsl +++ b/indra/newview/app_settings/shaders/class2/lighting/lightSpecularV.glsl @@ -4,6 +4,8 @@ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 // All lights, no specular highlights diff --git a/indra/newview/app_settings/shaders/class2/lighting/lightV.glsl b/indra/newview/app_settings/shaders/class2/lighting/lightV.glsl index ff3bcb5cd..75c0d7414 100644 --- a/indra/newview/app_settings/shaders/class2/lighting/lightV.glsl +++ b/indra/newview/app_settings/shaders/class2/lighting/lightV.glsl @@ -4,6 +4,8 @@ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 // All lights, no specular highlights diff --git a/indra/newview/app_settings/shaders/class2/lighting/lightWaterF.glsl b/indra/newview/app_settings/shaders/class2/lighting/lightWaterF.glsl index 086954cd4..64df7f0f9 100644 --- a/indra/newview/app_settings/shaders/class2/lighting/lightWaterF.glsl +++ b/indra/newview/app_settings/shaders/class2/lighting/lightWaterF.glsl @@ -4,6 +4,8 @@ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 uniform sampler2D diffuseMap; diff --git a/indra/newview/app_settings/shaders/class2/lighting/sumLightsSpecularV.glsl b/indra/newview/app_settings/shaders/class2/lighting/sumLightsSpecularV.glsl index edd1a8a94..2408e11d9 100644 --- a/indra/newview/app_settings/shaders/class2/lighting/sumLightsSpecularV.glsl +++ b/indra/newview/app_settings/shaders/class2/lighting/sumLightsSpecularV.glsl @@ -4,6 +4,8 @@ * Copyright (c) 2005-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 float calcDirectionalLightSpecular(inout vec4 specular, vec3 view, vec3 n, vec3 l, vec3 lightCol, float da); vec3 calcPointLightSpecular(inout vec4 specular, vec3 view, vec3 v, vec3 n, vec3 l, float r, float pw, vec3 lightCol); diff --git a/indra/newview/app_settings/shaders/class2/lighting/sumLightsV.glsl b/indra/newview/app_settings/shaders/class2/lighting/sumLightsV.glsl index f4c59734a..5f5b426da 100644 --- a/indra/newview/app_settings/shaders/class2/lighting/sumLightsV.glsl +++ b/indra/newview/app_settings/shaders/class2/lighting/sumLightsV.glsl @@ -4,9 +4,11 @@ * Copyright (c) 2005-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 float calcDirectionalLight(vec3 n, vec3 l); -float calcPointLight(vec3 v, vec3 n, vec4 lp, float la); +float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float is_pointlight); vec3 atmosAmbient(vec3 light); vec3 atmosAffectDirectionalLight(float lightIntensity); @@ -18,9 +20,10 @@ vec4 sumLights(vec3 pos, vec3 norm, vec4 color, vec4 baseLight) // Collect normal lights (need to be divided by two, as we later multiply by 2) col.rgb += gl_LightSource[1].diffuse.rgb * calcDirectionalLight(norm, gl_LightSource[1].position.xyz); - col.rgb += gl_LightSource[2].diffuse.rgb * calcPointLight(pos, norm, gl_LightSource[2].position, gl_LightSource[2].linearAttenuation); - col.rgb += gl_LightSource[3].diffuse.rgb * calcPointLight(pos, norm, gl_LightSource[3].position, gl_LightSource[3].linearAttenuation); - //col.rgb += gl_LightSource[4].diffuse.rgb * calcPointLight(pos, norm, gl_LightSource[4].position, gl_LightSource[4].linearAttenuation); + + col.rgb += gl_LightSource[2].diffuse.rgb * calcPointLightOrSpotLight(pos, norm, gl_LightSource[2].position, gl_LightSource[2].spotDirection.xyz, gl_LightSource[2].linearAttenuation, gl_LightSource[2].specular.a); + col.rgb += gl_LightSource[3].diffuse.rgb * calcPointLightOrSpotLight(pos, norm, gl_LightSource[3].position, gl_LightSource[3].spotDirection.xyz, gl_LightSource[3].linearAttenuation, gl_LightSource[3].specular.a); + //col.rgb += gl_LightSource[4].diffuse.rgb * calcPointLightOrSpotLight(pos, norm, gl_LightSource[4].position, gl_LightSource[4].spotDirection.xyz, gl_LightSource[4].linearAttenuation, gl_LightSource[4].specular.a); col.rgb = scaleDownLight(col.rgb); // Add windlight lights diff --git a/indra/newview/app_settings/shaders/class2/objects/shinyV.glsl b/indra/newview/app_settings/shaders/class2/objects/shinyV.glsl index 0d52f32a2..76e96cb27 100755 --- a/indra/newview/app_settings/shaders/class2/objects/shinyV.glsl +++ b/indra/newview/app_settings/shaders/class2/objects/shinyV.glsl @@ -4,6 +4,8 @@ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol); diff --git a/indra/newview/app_settings/shaders/class2/windlight/atmosphericsF.glsl b/indra/newview/app_settings/shaders/class2/windlight/atmosphericsF.glsl index 92c0664a5..80da3ee23 100644 --- a/indra/newview/app_settings/shaders/class2/windlight/atmosphericsF.glsl +++ b/indra/newview/app_settings/shaders/class2/windlight/atmosphericsF.glsl @@ -4,6 +4,8 @@ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 ////////////////////////////////////////////////////////// // The fragment shader for the terrain atmospherics diff --git a/indra/newview/app_settings/shaders/class2/windlight/atmosphericsHelpersV.glsl b/indra/newview/app_settings/shaders/class2/windlight/atmosphericsHelpersV.glsl index 32d5ed5db..c806655dc 100644 --- a/indra/newview/app_settings/shaders/class2/windlight/atmosphericsHelpersV.glsl +++ b/indra/newview/app_settings/shaders/class2/windlight/atmosphericsHelpersV.glsl @@ -4,6 +4,8 @@ * Copyright (c) 2005-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 // Output variables vec3 getSunlitColor(); diff --git a/indra/newview/app_settings/shaders/class2/windlight/atmosphericsV.glsl b/indra/newview/app_settings/shaders/class2/windlight/atmosphericsV.glsl index e40372e81..8b73c07ac 100644 --- a/indra/newview/app_settings/shaders/class2/windlight/atmosphericsV.glsl +++ b/indra/newview/app_settings/shaders/class2/windlight/atmosphericsV.glsl @@ -4,6 +4,8 @@ * Copyright (c) 2005-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 // varying param funcs void setSunlitColor(vec3 v); diff --git a/indra/newview/app_settings/shaders/class2/windlight/atmosphericsVarsF.glsl b/indra/newview/app_settings/shaders/class2/windlight/atmosphericsVarsF.glsl index 0dbf2d35e..3a5eeb853 100644 --- a/indra/newview/app_settings/shaders/class2/windlight/atmosphericsVarsF.glsl +++ b/indra/newview/app_settings/shaders/class2/windlight/atmosphericsVarsF.glsl @@ -4,6 +4,8 @@ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 varying vec3 vary_PositionEye; diff --git a/indra/newview/app_settings/shaders/class2/windlight/atmosphericsVarsV.glsl b/indra/newview/app_settings/shaders/class2/windlight/atmosphericsVarsV.glsl index b528837a5..aef449775 100644 --- a/indra/newview/app_settings/shaders/class2/windlight/atmosphericsVarsV.glsl +++ b/indra/newview/app_settings/shaders/class2/windlight/atmosphericsVarsV.glsl @@ -4,6 +4,8 @@ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 varying vec3 vary_PositionEye; diff --git a/indra/newview/app_settings/shaders/class2/windlight/cloudsF.glsl b/indra/newview/app_settings/shaders/class2/windlight/cloudsF.glsl index b7d7e5a2c..69262ec7d 100644 --- a/indra/newview/app_settings/shaders/class2/windlight/cloudsF.glsl +++ b/indra/newview/app_settings/shaders/class2/windlight/cloudsF.glsl @@ -4,6 +4,8 @@ * Copyright (c) 2005-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 ///////////////////////////////////////////////////////////////////////// // The fragment shader for the sky diff --git a/indra/newview/app_settings/shaders/class2/windlight/cloudsV.glsl b/indra/newview/app_settings/shaders/class2/windlight/cloudsV.glsl index e149d5861..881bb90b8 100644 --- a/indra/newview/app_settings/shaders/class2/windlight/cloudsV.glsl +++ b/indra/newview/app_settings/shaders/class2/windlight/cloudsV.glsl @@ -4,6 +4,8 @@ * Copyright (c) 2005-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 ////////////////////////////////////////////////////////////////////////// // The vertex shader for creating the atmospheric sky diff --git a/indra/newview/app_settings/shaders/class2/windlight/gammaF.glsl b/indra/newview/app_settings/shaders/class2/windlight/gammaF.glsl index 5410889ed..3ca7a962d 100644 --- a/indra/newview/app_settings/shaders/class2/windlight/gammaF.glsl +++ b/indra/newview/app_settings/shaders/class2/windlight/gammaF.glsl @@ -4,6 +4,8 @@ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 uniform vec4 gamma; diff --git a/indra/newview/app_settings/shaders/class2/windlight/skyF.glsl b/indra/newview/app_settings/shaders/class2/windlight/skyF.glsl index bc6d6d33f..6737d2617 100644 --- a/indra/newview/app_settings/shaders/class2/windlight/skyF.glsl +++ b/indra/newview/app_settings/shaders/class2/windlight/skyF.glsl @@ -4,6 +4,8 @@ * Copyright (c) 2005-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 ///////////////////////////////////////////////////////////////////////// // The fragment shader for the sky diff --git a/indra/newview/app_settings/shaders/class2/windlight/skyV.glsl b/indra/newview/app_settings/shaders/class2/windlight/skyV.glsl index e396aea6c..e1a6844d2 100644 --- a/indra/newview/app_settings/shaders/class2/windlight/skyV.glsl +++ b/indra/newview/app_settings/shaders/class2/windlight/skyV.glsl @@ -4,6 +4,8 @@ * Copyright (c) 2005-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 // SKY //////////////////////////////////////////////////////////////////////// // The vertex shader for creating the atmospheric sky diff --git a/indra/newview/app_settings/shaders/class2/windlight/transportF.glsl b/indra/newview/app_settings/shaders/class2/windlight/transportF.glsl index b7678cac6..e1e385496 100644 --- a/indra/newview/app_settings/shaders/class2/windlight/transportF.glsl +++ b/indra/newview/app_settings/shaders/class2/windlight/transportF.glsl @@ -4,6 +4,8 @@ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 ////////////////////////////////////////////////////////// // The fragment shader for the terrain atmospherics diff --git a/indra/newview/app_settings/shaders/class3/avatar/avatarV.glsl b/indra/newview/app_settings/shaders/class3/avatar/avatarV.glsl index 04c10536e..1b6e843c0 100644 --- a/indra/newview/app_settings/shaders/class3/avatar/avatarV.glsl +++ b/indra/newview/app_settings/shaders/class3/avatar/avatarV.glsl @@ -4,6 +4,8 @@ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol); mat4 getSkinnedTransform(); diff --git a/indra/newview/app_settings/shaders/class3/deferred/giDownsampleF.glsl b/indra/newview/app_settings/shaders/class3/deferred/giDownsampleF.glsl new file mode 100644 index 000000000..fc370ef36 --- /dev/null +++ b/indra/newview/app_settings/shaders/class3/deferred/giDownsampleF.glsl @@ -0,0 +1,88 @@ +/** + * @file giDownsampleF.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $/LicenseInfo$ + */ + +#version 120 + +uniform sampler2DRect giLightMap; + +uniform vec2 kern[32]; +uniform float dist_factor; +uniform float blur_size; +uniform vec2 delta; +uniform int kern_length; +uniform float kern_scale; +uniform vec3 blur_quad; + +varying vec2 vary_fragcoord; + +uniform mat4 inv_proj; +uniform vec2 screen_res; + +vec4 getPosition(vec2 pos_screen) +{ + float depth = texture2DRect(depthMap, pos_screen.xy).a; + vec2 sc = pos_screen.xy*2.0; + sc /= screen_res; + sc -= vec2(1.0,1.0); + vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); + vec4 pos = inv_proj * ndc; + pos /= pos.w; + pos.w = 1.0; + return pos; +} + +float getDepth(vec2 pos_screen) +{ + float z = texture2DRect(depthMap, pos_screen.xy).a; + z = z*2.0-1.0; + vec4 ndc = vec4(0.0, 0.0, z, 1.0); + vec4 p = inv_proj*ndc; + return p.z/p.w; +} + +void main() +{ + vec3 norm = texture2DRect(normalMap, vary_fragcoord.xy).xyz; + norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm + float depth = getDepth(vary_fragcoord.xy); + + vec3 ccol = texture2DRect(giLightMap, vary_fragcoord.xy).rgb; + vec2 dlt = kern_scale * delta/(vec2(1.0,1.0)+norm.xy*norm.xy); + dlt /= clamp(-depth*blur_quad.x, 1.0, 3.0); + float defined_weight = kern[0].x; + vec3 col = ccol*kern[0].x; + + for (int i = 0; i < kern_length; i++) + { + vec2 tc = vary_fragcoord.xy + kern[i].y*dlt; + vec3 sampNorm = texture2DRect(normalMap, tc.xy).xyz; + sampNorm = vec3((sampNorm.xy-0.5)*2.0,sampNorm.z); // unpack norm + + float d = dot(norm.xyz, sampNorm); + + if (d > 0.5) + { + float sampdepth = getDepth(tc.xy); + sampdepth -= depth; + if (sampdepth*sampdepth < blur_quad.z) + { + col += texture2DRect(giLightMap, tc).rgb*kern[i].x; + defined_weight += kern[i].x; + } + } + } + + col /= defined_weight; + + //col = ccol; + + col = col*blur_quad.y; + + gl_FragData[0].xyz = col; + + //gl_FragColor = ccol; +} diff --git a/indra/newview/app_settings/shaders/class3/deferred/giDownsampleV.glsl b/indra/newview/app_settings/shaders/class3/deferred/giDownsampleV.glsl new file mode 100644 index 000000000..ae57227fe --- /dev/null +++ b/indra/newview/app_settings/shaders/class3/deferred/giDownsampleV.glsl @@ -0,0 +1,19 @@ +/** + * @file postgiV.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $/LicenseInfo$ + */ + +#version 120 + +varying vec2 vary_fragcoord; +uniform vec2 screen_res; + +void main() +{ + //transform vertex + gl_Position = ftransform(); + vec4 pos = gl_ModelViewProjectionMatrix * gl_Vertex; + vary_fragcoord = (pos.xy*0.5+0.5)*screen_res; +} diff --git a/indra/newview/app_settings/shaders/class3/deferred/giF.glsl b/indra/newview/app_settings/shaders/class3/deferred/giF.glsl new file mode 100644 index 000000000..951e3e97a --- /dev/null +++ b/indra/newview/app_settings/shaders/class3/deferred/giF.glsl @@ -0,0 +1,193 @@ +/** + * @file giF.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $/LicenseInfo$ + */ + +#version 120 + +#extension GL_ARB_texture_rectangle : enable + +uniform sampler2DRect depthMap; +uniform sampler2DRect normalMap; +uniform sampler2DRect lightMap; +uniform sampler2DRect specularRect; + +uniform sampler2D noiseMap; + +uniform sampler2D diffuseGIMap; +uniform sampler2D specularGIMap; +uniform sampler2D normalGIMap; +uniform sampler2D depthGIMap; + +uniform sampler2D lightFunc; + +// Inputs +varying vec2 vary_fragcoord; + +uniform vec2 screen_res; + +uniform vec4 sunlight_color; + +uniform mat4 inv_proj; +uniform mat4 gi_mat; //gPipeline.mGIMatrix - eye space to sun space +uniform mat4 gi_mat_proj; //gPipeline.mGIMatrixProj - eye space to projected sun space +uniform mat4 gi_norm_mat; //gPipeline.mGINormalMatrix - eye space normal to sun space normal matrix +uniform mat4 gi_inv_proj; //gPipeline.mGIInvProj - projected sun space to sun space +uniform float gi_sample_width; +uniform float gi_noise; +uniform float gi_attenuation; +uniform float gi_range; + +vec4 getPosition(vec2 pos_screen) +{ + float depth = texture2DRect(depthMap, pos_screen.xy).a; + vec2 sc = pos_screen.xy*2.0; + sc /= screen_res; + sc -= vec2(1.0,1.0); + vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); + vec4 pos = inv_proj * ndc; + pos /= pos.w; + pos.w = 1.0; + return pos; +} + +vec4 getGIPosition(vec2 gi_tc) +{ + float depth = texture2D(depthGIMap, gi_tc).a; + vec2 sc = gi_tc*2.0; + sc -= vec2(1.0, 1.0); + vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); + vec4 pos = gi_inv_proj*ndc; + pos.xyz /= pos.w; + pos.w = 1.0; + return pos; +} + +vec3 giAmbient(vec3 pos, vec3 norm) +{ + vec4 gi_c = gi_mat_proj * vec4(pos, 1.0); + gi_c.xyz /= gi_c.w; + + vec4 gi_pos = gi_mat*vec4(pos,1.0); + vec3 gi_norm = (gi_norm_mat*vec4(norm,1.0)).xyz; + gi_norm = normalize(gi_norm); + + vec4 c_spec = texture2DRect(specularRect, vary_fragcoord.xy); + vec3 nz = texture2D(noiseMap, vary_fragcoord.xy/128.0).rgb; + gi_pos.xyz += nz.x*gi_noise*gi_norm.xyz; + vec2 tcx = gi_norm.xy; + vec2 tcy = gi_norm.yx; + + vec4 eye_pos = gi_mat*vec4(0,0,0,1.0); + + vec3 eye_dir = normalize(gi_pos.xyz-eye_pos.xyz); + vec3 eye_ref = reflect(eye_dir, gi_norm); + + float da = 0.0; //texture2DRect(lightMap, vary_fragcoord.xy).r*0.5; + vec3 fdiff = vec3(da); + float fda = da; + + vec3 rcol = vec3(0,0,0); + + float fsa = 0.0; + + + for (int i = -1; i <= 1; i += 2 ) + { + for (int j = -1; j <= 1; j+= 2) + { + vec2 tc = vec2(i, j)*0.75+gi_norm.xy*nz.z; + tc += nz.xy*2.0; + tc *= gi_sample_width*0.25; + tc += gi_c.xy; + + vec3 lnorm = -(texture2D(normalGIMap, tc.xy).xyz*2.0-1.0); + vec3 lpos = getGIPosition(tc.xy).xyz; + + vec3 at = lpos-gi_pos.xyz; + float dist = length(at); + float dist_atten = clamp(1.0/(gi_attenuation*dist), 0.0, 1.0); + + + if (dist_atten > 0.01) + { //possible contribution of indirect light to this surface + vec3 ldir = at; + + float ld = -dot(ldir, lnorm); + + if (ld < 0.0) + { + float ang_atten = dot(ldir, gi_norm); + + if (ang_atten > 0.0) + { + vec4 spec = texture2D(specularGIMap, tc.xy); + at = normalize(at); + vec3 diff; + + float da = 0.0; + + //contribution from indirect source to visible pixel + vec3 ha = at; + ha.z -= 1.0; + ha = normalize(ha); + if (spec.a > 0.0) + { + float sa = dot(ha,lnorm); + da = texture2D(lightFunc, vec2(sa, spec.a)).a; + } + else + { + da = -lnorm.z; + } + + diff = texture2D(diffuseGIMap, tc.xy).rgb+spec.rgb*spec.a*2.0; + + if (da > 0.0) + { //contribution from visible pixel to eye + vec3 ha = normalize(at-eye_dir); + if (c_spec.a > 0.0) + { + float sa = dot(ha, gi_norm); + da = dist_atten*texture2D(lightFunc, vec2(sa, c_spec.a)).a; + } + else + { + da = dist_atten*dot(gi_norm, normalize(ldir)); + } + fda += da; + fdiff += da*(c_spec.rgb*c_spec.a*2.0+vec3(1,1,1))*diff.rgb; + } + } + } + } + } + } + + fdiff *= sunlight_color.rgb; + + vec3 ret = fda*fdiff; + + return clamp(ret,vec3(0.0), vec3(1.0)); +} + +void main() +{ + vec2 pos_screen = vary_fragcoord.xy; + vec4 pos = getPosition(pos_screen); + + float rad = gi_range*0.5; + + vec3 norm = texture2DRect(normalMap, pos_screen).xyz; + norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm + float dist = max(length(pos.xyz)-rad, 0.0); + + float da = clamp(1.0-dist/rad, 0.0, 1.0); + + vec3 ambient = da > 0.0 ? giAmbient(pos.xyz, norm) : vec3(0); + + + gl_FragData[0].xyz = mix(vec3(0), ambient, da); +} diff --git a/indra/newview/app_settings/shaders/class3/deferred/giFinalF.glsl b/indra/newview/app_settings/shaders/class3/deferred/giFinalF.glsl new file mode 100644 index 000000000..b2f8b2c63 --- /dev/null +++ b/indra/newview/app_settings/shaders/class3/deferred/giFinalF.glsl @@ -0,0 +1,27 @@ +/** + * @file giFinalF.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $/LicenseInfo$ + */ + +#version 120 + +#extension GL_ARB_texture_rectangle : enable + +uniform sampler2DRect diffuseRect; +uniform sampler2D bloomMap; +uniform sampler2DRect edgeMap; + +uniform vec2 screen_res; +varying vec2 vary_fragcoord; + + +void main() +{ + vec4 bloom = texture2D(bloomMap, vary_fragcoord.xy/screen_res); + vec4 diff = texture2DRect(diffuseRect, vary_fragcoord.xy); + + gl_FragColor = bloom + diff; + //gl_FragColor.rgb = vec3(texture2DRect(edgeMap, vary_fragcoord.xy).a); +} \ No newline at end of file diff --git a/indra/newview/app_settings/shaders/class3/deferred/giFinalV.glsl b/indra/newview/app_settings/shaders/class3/deferred/giFinalV.glsl new file mode 100644 index 000000000..19c4e07b8 --- /dev/null +++ b/indra/newview/app_settings/shaders/class3/deferred/giFinalV.glsl @@ -0,0 +1,19 @@ +/** + * @file giFinalV.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $/LicenseInfo$ + */ + +#version 120 + +varying vec2 vary_fragcoord; +uniform vec2 screen_res; + +void main() +{ + //transform vertex + gl_Position = ftransform(); + vec4 pos = gl_ModelViewProjectionMatrix * gl_Vertex; + vary_fragcoord = (pos.xy*0.5+0.5)*screen_res; +} diff --git a/indra/newview/app_settings/shaders/class3/deferred/giV.glsl b/indra/newview/app_settings/shaders/class3/deferred/giV.glsl new file mode 100644 index 000000000..8dc1410ea --- /dev/null +++ b/indra/newview/app_settings/shaders/class3/deferred/giV.glsl @@ -0,0 +1,24 @@ +/** + * @file giV.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $/LicenseInfo$ + */ + +#version 120 + +varying vec2 vary_fragcoord; + +uniform vec2 screen_res; + +void main() +{ + //transform vertex + gl_Position = ftransform(); + vec4 pos = gl_ModelViewProjectionMatrix * gl_Vertex; + vary_fragcoord = (pos.xy * 0.5 + 0.5)*screen_res; + vec4 tex = gl_MultiTexCoord0; + tex.w = 1.0; + + gl_FrontColor = gl_Color; +} diff --git a/indra/newview/app_settings/shaders/class3/deferred/luminanceF.glsl b/indra/newview/app_settings/shaders/class3/deferred/luminanceF.glsl new file mode 100644 index 000000000..5f3bf68b2 --- /dev/null +++ b/indra/newview/app_settings/shaders/class3/deferred/luminanceF.glsl @@ -0,0 +1,21 @@ +/** + * @file luminanceF.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $/LicenseInfo$ + */ + +#version 120 + +#extension GL_ARB_texture_rectangle : enable + +uniform sampler2DRect lightMap; +uniform sampler2DRect diffuseRect; + +varying vec2 vary_fragcoord; +void main() +{ + float i = texture2DRect(lightMap, vary_fragcoord.xy).r; + gl_FragColor.rgb = vec3(i); + gl_FragColor.a = 1.0; +} diff --git a/indra/newview/app_settings/shaders/class3/deferred/luminanceV.glsl b/indra/newview/app_settings/shaders/class3/deferred/luminanceV.glsl new file mode 100644 index 000000000..a24eda35d --- /dev/null +++ b/indra/newview/app_settings/shaders/class3/deferred/luminanceV.glsl @@ -0,0 +1,22 @@ +/** + * @file giV.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $/LicenseInfo$ + */ + +#version 120 + +varying vec2 vary_fragcoord; + +uniform vec2 screen_res; + +void main() +{ + //transform vertex + gl_Position = ftransform(); + vec4 pos = gl_ModelViewProjectionMatrix * gl_Vertex; + vary_fragcoord = (pos.xy * 0.5 + 0.5)*screen_res; + + gl_FrontColor = gl_Color; +} diff --git a/indra/newview/app_settings/shaders/class3/deferred/postDeferredF.glsl b/indra/newview/app_settings/shaders/class3/deferred/postDeferredF.glsl new file mode 100644 index 000000000..ab99a8897 --- /dev/null +++ b/indra/newview/app_settings/shaders/class3/deferred/postDeferredF.glsl @@ -0,0 +1,82 @@ +/** + * @file postDeferredF.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $/LicenseInfo$ + */ + +#version 120 + +#extension GL_ARB_texture_rectangle : enable + +uniform sampler2DRect diffuseRect; +uniform sampler2DRect specularRect; + +uniform sampler2DRect localLightMap; +uniform sampler2DRect sunLightMap; +uniform sampler2DRect giLightMap; +uniform sampler2DRect edgeMap; + +uniform sampler2D luminanceMap; + +uniform sampler2DRect lightMap; + +uniform sampler2D lightFunc; +uniform sampler2D noiseMap; + +uniform float sun_lum_scale; +uniform float sun_lum_offset; +uniform float lum_scale; +uniform float lum_lod; +uniform vec4 ambient; +uniform float gi_brightness; +uniform float gi_luminance; + +uniform vec4 sunlight_color; + +uniform vec2 screen_res; +varying vec2 vary_fragcoord; + +void main() +{ + vec2 tc = vary_fragcoord.xy; + vec4 lcol = texture2DLod(luminanceMap, vec2(0.5, 0.5), lum_lod); + + vec3 gi_col = texture2DRect(giLightMap, vary_fragcoord.xy).rgb; + vec4 sun_col = texture2DRect(sunLightMap, vary_fragcoord.xy); + vec3 local_col = texture2DRect(localLightMap, vary_fragcoord.xy).rgb; + + float scol = texture2DRect(lightMap, vary_fragcoord.xy).r; + + vec3 diff = texture2DRect(diffuseRect, vary_fragcoord.xy).rgb; + vec4 spec = texture2DRect(specularRect, vary_fragcoord.xy); + + gi_col = gi_col*(diff.rgb+spec.rgb*spec.a); + + float lum = 1.0-clamp(pow(lcol.r, gi_brightness)+sun_lum_offset, 0.0, 1.0); + + lum *= sun_lum_scale; + + sun_col *= 1.0+(lum*lum_scale*scol); + + vec4 col; + col.rgb = gi_col+sun_col.rgb+local_col; + + col.a = sun_col.a; + + vec3 bcol = vec3(0,0,0); + float tweight = 0.0; + for (int i = 0; i < 16; i++) + { + float weight = (float(i)+1.0)/2.0; + bcol += texture2DLod(luminanceMap, vary_fragcoord.xy/screen_res, weight).rgb*weight*weight*weight; + tweight += weight*weight; + } + + bcol /= tweight; + bcol *= gi_luminance; + col.rgb += bcol*lum; + + gl_FragColor = col; + //gl_FragColor.rgb = texture2DRect(giLightMap, vary_fragcoord.xy).rgb; +} diff --git a/indra/newview/app_settings/shaders/class3/deferred/postDeferredV.glsl b/indra/newview/app_settings/shaders/class3/deferred/postDeferredV.glsl new file mode 100644 index 000000000..12983baa9 --- /dev/null +++ b/indra/newview/app_settings/shaders/class3/deferred/postDeferredV.glsl @@ -0,0 +1,19 @@ +/** + * @file postDeferredV.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $/LicenseInfo$ + */ + +#version 120 + +varying vec2 vary_fragcoord; +uniform vec2 screen_res; + +void main() +{ + //transform vertex + gl_Position = ftransform(); + vec4 pos = gl_ModelViewProjectionMatrix * gl_Vertex; + vary_fragcoord = (pos.xy*0.5+0.5)*screen_res; +} diff --git a/indra/newview/app_settings/shaders/class3/deferred/postgiF.glsl b/indra/newview/app_settings/shaders/class3/deferred/postgiF.glsl new file mode 100644 index 000000000..f03775470 --- /dev/null +++ b/indra/newview/app_settings/shaders/class3/deferred/postgiF.glsl @@ -0,0 +1,71 @@ +/** + * @file postgiF.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $/LicenseInfo$ + */ + +#version 120 + +#extension GL_ARB_texture_rectangle : enable + +uniform sampler2DRect depthMap; +uniform sampler2DRect normalMap; +uniform sampler2DRect giLightMap; +uniform sampler2D noiseMap; +uniform sampler2D giMip; +uniform sampler2DRect edgeMap; + + +uniform vec2 delta; +uniform float kern_scale; +uniform float gi_edge_weight; +uniform float gi_blur_brightness; + +varying vec2 vary_fragcoord; + +void main() +{ + vec2 dlt = kern_scale*delta; + float defined_weight = 0.0; + vec3 col = vec3(0.0); + + float e = 1.0; + + for (int i = 1; i < 8; i++) + { + vec2 tc = vary_fragcoord.xy + float(i) * dlt; + + e = max(e, 0.0); + float wght = e; + + col += texture2DRect(giLightMap, tc).rgb*wght; + defined_weight += wght; + + e *= e; + e -=(texture2DRect(edgeMap, tc.xy-dlt*0.25).a+ + texture2DRect(edgeMap, tc.xy+dlt*0.25).a)*gi_edge_weight; + } + + e = 1.0; + + for (int i = 1; i < 8; i++) + { + vec2 tc = vary_fragcoord.xy - float(i) * dlt; + + e = max(e,0.0); + float wght = e; + + col += texture2DRect(giLightMap, tc).rgb*wght; + defined_weight += wght; + + e *= e; + e -= (texture2DRect(edgeMap, tc.xy-dlt*0.25).a+ + texture2DRect(edgeMap, tc.xy+dlt*0.25).a)*gi_edge_weight; + + } + + col /= max(defined_weight, 0.01); + + gl_FragColor.rgb = col * gi_blur_brightness; +} diff --git a/indra/newview/app_settings/shaders/class3/deferred/postgiV.glsl b/indra/newview/app_settings/shaders/class3/deferred/postgiV.glsl new file mode 100644 index 000000000..ae57227fe --- /dev/null +++ b/indra/newview/app_settings/shaders/class3/deferred/postgiV.glsl @@ -0,0 +1,19 @@ +/** + * @file postgiV.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $/LicenseInfo$ + */ + +#version 120 + +varying vec2 vary_fragcoord; +uniform vec2 screen_res; + +void main() +{ + //transform vertex + gl_Position = ftransform(); + vec4 pos = gl_ModelViewProjectionMatrix * gl_Vertex; + vary_fragcoord = (pos.xy*0.5+0.5)*screen_res; +} diff --git a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl new file mode 100644 index 000000000..56f3f9697 --- /dev/null +++ b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl @@ -0,0 +1,356 @@ +/** + * @file softenLightF.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $/LicenseInfo$ + */ + +#version 120 + +#extension GL_ARB_texture_rectangle : enable + +uniform sampler2DRect diffuseRect; +uniform sampler2DRect specularRect; +uniform sampler2DRect normalMap; +uniform sampler2DRect lightMap; +uniform sampler2DRect depthMap; +uniform sampler2D lightFunc; +uniform vec3 gi_quad; + +uniform float blur_size; +uniform float blur_fidelity; + +// Inputs +uniform vec4 morphFactor; +uniform vec3 camPosLocal; +//uniform vec4 camPosWorld; +uniform vec4 gamma; +uniform vec4 lightnorm; +uniform vec4 sunlight_color; +uniform vec4 ambient; +uniform vec4 blue_horizon; +uniform vec4 blue_density; +uniform vec4 haze_horizon; +uniform vec4 haze_density; +uniform vec4 cloud_shadow; +uniform vec4 density_multiplier; +uniform vec4 distance_multiplier; +uniform vec4 max_y; +uniform vec4 glow; +uniform float scene_light_strength; +uniform vec3 env_mat[3]; +uniform vec4 shadow_clip; +uniform mat3 ssao_effect_mat; + +uniform mat4 inv_proj; +uniform vec2 screen_res; + +varying vec4 vary_light; +varying vec2 vary_fragcoord; + +vec3 vary_PositionEye; + +vec3 vary_SunlitColor; +vec3 vary_AmblitColor; +vec3 vary_AdditiveColor; +vec3 vary_AtmosAttenuation; +uniform float gi_ambiance; + +vec4 getPosition_d(vec2 pos_screen, float depth) +{ + vec2 sc = pos_screen.xy*2.0; + sc /= screen_res; + sc -= vec2(1.0,1.0); + vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); + vec4 pos = inv_proj * ndc; + pos /= pos.w; + pos.w = 1.0; + return pos; +} + +vec4 getPosition(vec2 pos_screen) +{ //get position in screen space (world units) given window coordinate and depth map + float depth = texture2DRect(depthMap, pos_screen.xy).a; + return getPosition_d(pos_screen, depth); +} + +vec3 getPositionEye() +{ + return vary_PositionEye; +} +vec3 getSunlitColor() +{ + return vary_SunlitColor; +} +vec3 getAmblitColor() +{ + return vary_AmblitColor; +} +vec3 getAdditiveColor() +{ + return vary_AdditiveColor; +} +vec3 getAtmosAttenuation() +{ + return vary_AtmosAttenuation; +} + + +void setPositionEye(vec3 v) +{ + vary_PositionEye = v; +} + +void setSunlitColor(vec3 v) +{ + vary_SunlitColor = v; +} + +void setAmblitColor(vec3 v) +{ + vary_AmblitColor = v; +} + +void setAdditiveColor(vec3 v) +{ + vary_AdditiveColor = v; +} + +void setAtmosAttenuation(vec3 v) +{ + vary_AtmosAttenuation = v; +} + +void calcAtmospherics(vec3 inPositionEye, float ambFactor) { + + vec3 P = inPositionEye; + setPositionEye(P); + + //(TERRAIN) limit altitude + if (P.y > max_y.x) P *= (max_y.x / P.y); + if (P.y < -max_y.x) P *= (-max_y.x / P.y); + + vec3 tmpLightnorm = lightnorm.xyz; + + vec3 Pn = normalize(P); + float Plen = length(P); + + vec4 temp1 = vec4(0); + vec3 temp2 = vec3(0); + vec4 blue_weight; + vec4 haze_weight; + vec4 sunlight = sunlight_color; + vec4 light_atten; + + //sunlight attenuation effect (hue and brightness) due to atmosphere + //this is used later for sunlight modulation at various altitudes + light_atten = (blue_density * 1.0 + vec4(haze_density.r) * 0.25) * (density_multiplier.x * max_y.x); + //I had thought blue_density and haze_density should have equal weighting, + //but attenuation due to haze_density tends to seem too strong + + temp1 = blue_density + vec4(haze_density.r); + blue_weight = blue_density / temp1; + haze_weight = vec4(haze_density.r) / temp1; + + //(TERRAIN) compute sunlight from lightnorm only (for short rays like terrain) + temp2.y = max(0.0, tmpLightnorm.y); + temp2.y = 1. / temp2.y; + sunlight *= exp( - light_atten * temp2.y); + + // main atmospheric scattering line integral + temp2.z = Plen * density_multiplier.x; + + // Transparency (-> temp1) + // ATI Bugfix -- can't store temp1*temp2.z*distance_multiplier.x in a variable because the ati + // compiler gets confused. + temp1 = exp(-temp1 * temp2.z * distance_multiplier.x); + + //final atmosphere attenuation factor + setAtmosAttenuation(temp1.rgb); + + //compute haze glow + //(can use temp2.x as temp because we haven't used it yet) + temp2.x = dot(Pn, tmpLightnorm.xyz); + temp2.x = 1. - temp2.x; + //temp2.x is 0 at the sun and increases away from sun + temp2.x = max(temp2.x, .03); //was glow.y + //set a minimum "angle" (smaller glow.y allows tighter, brighter hotspot) + temp2.x *= glow.x; + //higher glow.x gives dimmer glow (because next step is 1 / "angle") + temp2.x = pow(temp2.x, glow.z); + //glow.z should be negative, so we're doing a sort of (1 / "angle") function + + //add "minimum anti-solar illumination" + temp2.x += .25; + + //increase ambient when there are more clouds + vec4 tmpAmbient = ambient*gi_ambiance + (vec4(1.) - ambient*gi_ambiance) * cloud_shadow.x * 0.5; + + /* decrease value and saturation (that in HSV, not HSL) for occluded areas + * // for HSV color/geometry used here, see http://gimp-savvy.com/BOOK/index.html?node52.html + * // The following line of code performs the equivalent of: + * float ambAlpha = tmpAmbient.a; + * float ambValue = dot(vec3(tmpAmbient), vec3(0.577)); // projection onto <1/rt(3), 1/rt(3), 1/rt(3)>, the neutral white-black axis + * vec3 ambHueSat = vec3(tmpAmbient) - vec3(ambValue); + * tmpAmbient = vec4(RenderSSAOEffect.valueFactor * vec3(ambValue) + RenderSSAOEffect.saturationFactor *(1.0 - ambFactor) * ambHueSat, ambAlpha); + */ + tmpAmbient = vec4(mix(ssao_effect_mat * tmpAmbient.rgb, tmpAmbient.rgb, ambFactor), tmpAmbient.a); + + //haze color + setAdditiveColor( + vec3(blue_horizon * blue_weight * (sunlight*(1.-cloud_shadow.x) + tmpAmbient) + + (haze_horizon.r * haze_weight) * (sunlight*(1.-cloud_shadow.x) * temp2.x + + tmpAmbient))); + + //brightness of surface both sunlight and ambient + setSunlitColor(vec3(sunlight * .5)); + setAmblitColor(vec3(tmpAmbient * .25)); + setAdditiveColor(getAdditiveColor() * vec3(1.0 - temp1)); +} + +vec3 atmosLighting(vec3 light) +{ + light *= getAtmosAttenuation().r; + light += getAdditiveColor(); + return (2.0 * light); +} + +vec3 atmosTransport(vec3 light) { + light *= getAtmosAttenuation().r; + light += getAdditiveColor() * 2.0; + return light; +} +vec3 atmosGetDiffuseSunlightColor() +{ + return getSunlitColor(); +} + +vec3 scaleDownLight(vec3 light) +{ + return (light / scene_light_strength ); +} + +vec3 scaleUpLight(vec3 light) +{ + return (light * scene_light_strength); +} + +vec3 atmosAmbient(vec3 light) +{ + return getAmblitColor() + light / 2.0; +} + +vec3 atmosAffectDirectionalLight(float lightIntensity) +{ + return getSunlitColor() * lightIntensity; +} + +vec3 scaleSoftClip(vec3 light) +{ + //soft clip effect: + light = 1. - clamp(light, vec3(0.), vec3(1.)); + light = 1. - pow(light, gamma.xxx); + + return light; +} + +void main() +{ + vec2 tc = vary_fragcoord.xy; + float depth = texture2DRect(depthMap, tc.xy).a; + vec3 pos = getPosition_d(tc, depth).xyz; + vec3 norm = texture2DRect(normalMap, tc).xyz; + norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm + //vec3 nz = texture2D(noiseMap, vary_fragcoord.xy/128.0).xyz; + + float da = max(dot(norm.xyz, vary_light.xyz), 0.0); + + vec4 diffuse = texture2DRect(diffuseRect, tc); + vec4 spec = texture2DRect(specularRect, vary_fragcoord.xy); + + da = texture2D(lightFunc, vec2(da, 0.0)).a; + + vec2 scol_ambocc = texture2DRect(lightMap, vary_fragcoord.xy).rg; + float scol = max(scol_ambocc.r, diffuse.a); + float ambocc = scol_ambocc.g; + + calcAtmospherics(pos.xyz, ambocc); + + vec3 col = atmosAmbient(vec3(0)); + col += atmosAffectDirectionalLight(max(min(da, scol), diffuse.a)); + + col *= diffuse.rgb; + + if (spec.a > 0.0) // specular reflection + { + // the old infinite-sky shiny reflection + // + vec3 refnormpersp = normalize(reflect(pos.xyz, norm.xyz)); + float sa = dot(refnormpersp, vary_light.xyz); + vec3 dumbshiny = vary_SunlitColor*scol*texture2D(lightFunc, vec2(sa, spec.a)).a; + + /* + // screen-space cheap fakey reflection map + // + vec3 refnorm = normalize(reflect(vec3(0,0,-1), norm.xyz)); + depth -= 0.5; // unbias depth + // first figure out where we'll make our 2D guess from + vec2 ref2d = (0.25 * screen_res.y) * (refnorm.xy) * abs(refnorm.z) / depth; + // Offset the guess source a little according to a trivial + // checkerboard dither function and spec.a. + // This is meant to be similar to sampling a blurred version + // of the diffuse map. LOD would be better in that regard. + // The goal of the blur is to soften reflections in surfaces + // with low shinyness, and also to disguise our lameness. + float checkerboard = floor(mod(tc.x+tc.y, 2.0)); // 0.0, 1.0 + float checkoffset = (3.0 + (7.0*(1.0-spec.a)))*(checkerboard-0.5); + + ref2d += vec2(checkoffset, checkoffset); + ref2d += tc.xy; // use as offset from destination + // Get attributes from the 2D guess point. + // We average two samples of diffuse (not of anything else) per + // pixel to try to reduce aliasing some more. + vec3 refcol = 0.5 * (texture2DRect(diffuseRect, ref2d + vec2(0.0, -checkoffset)).rgb + + texture2DRect(diffuseRect, ref2d + vec2(-checkoffset, 0.0)).rgb); + float refdepth = texture2DRect(depthMap, ref2d).a; + vec3 refpos = getPosition_d(ref2d, refdepth).xyz; + float refshad = texture2DRect(lightMap, ref2d).r; + vec3 refn = texture2DRect(normalMap, ref2d).rgb; + refn = vec3((refn.xy-0.5)*2.0,refn.z); // unpack norm + refn = normalize(refn); + // figure out how appropriate our guess actually was + float refapprop = max(0.0, dot(-refnorm, normalize(pos - refpos))); + // darken reflections from points which face away from the reflected ray - our guess was a back-face + //refapprop *= step(dot(refnorm, refn), 0.0); + refapprop = min(refapprop, max(0.0, -dot(refnorm, refn))); // more conservative variant + // get appropriate light strength for guess-point. + // reflect light direction to increase the illusion that + // these are reflections. + vec3 reflight = reflect(lightnorm.xyz, norm.xyz); + float reflit = min(max(dot(refn, reflight.xyz), 0.0), refshad); + // apply sun color to guess-point, dampen according to inappropriateness of guess + float refmod = min(refapprop, reflit); + vec3 refprod = vary_SunlitColor * refcol.rgb * refmod; + vec3 ssshiny = (refprod * spec.a); + ssshiny *= 0.3; // dampen it even more + */ + vec3 ssshiny = vec3(0,0,0); + + // add the two types of shiny together + col += (ssshiny + dumbshiny) * spec.rgb; + } + + col = atmosLighting(col); + col = scaleSoftClip(col); + + gl_FragColor.rgb = col; + + //gl_FragColor.rgb = gi_col.rgb; + gl_FragColor.a = 0.0; + + //gl_FragColor.rg = scol_ambocc.rg; + //gl_FragColor.rgb = texture2DRect(lightMap, vary_fragcoord.xy).rgb; + //gl_FragColor.rgb = norm.rgb*0.5+0.5; + //gl_FragColor.rgb = vec3(ambocc); + //gl_FragColor.rgb = vec3(scol); +} diff --git a/indra/newview/app_settings/shaders/class3/deferred/softenLightV.glsl b/indra/newview/app_settings/shaders/class3/deferred/softenLightV.glsl new file mode 100644 index 000000000..8f0bcca76 --- /dev/null +++ b/indra/newview/app_settings/shaders/class3/deferred/softenLightV.glsl @@ -0,0 +1,26 @@ +/** + * @file softenLightF.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $/LicenseInfo$ + */ + +#version 120 + +uniform vec2 screen_res; + +varying vec4 vary_light; +varying vec2 vary_fragcoord; +void main() +{ + //transform vertex + gl_Position = ftransform(); + + vec4 pos = gl_ModelViewProjectionMatrix * gl_Vertex; + vary_fragcoord = (pos.xy*0.5+0.5)*screen_res; + + vec4 tex = gl_MultiTexCoord0; + tex.w = 1.0; + + vary_light = gl_MultiTexCoord0; +} diff --git a/indra/newview/app_settings/shaders/class3/deferred/treeF.glsl b/indra/newview/app_settings/shaders/class3/deferred/treeF.glsl new file mode 100644 index 000000000..c54d9a1e3 --- /dev/null +++ b/indra/newview/app_settings/shaders/class3/deferred/treeF.glsl @@ -0,0 +1,21 @@ +/** + * @file treeF.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $/LicenseInfo$ + */ + +#version 120 + +uniform sampler2D diffuseMap; + +varying vec3 vary_normal; + +void main() +{ + vec4 col = texture2D(diffuseMap, gl_TexCoord[0].xy); + gl_FragData[0] = vec4(gl_Color.rgb*col.rgb, col.a <= 0.5 ? 0.0 : 0.005); + gl_FragData[1] = vec4(0,0,0,0); + vec3 nvn = normalize(vary_normal); + gl_FragData[2] = vec4(nvn.xy * 0.5 + 0.5, nvn.z, 0.0); +} diff --git a/indra/newview/app_settings/shaders/class3/lighting/sumLightsSpecularV.glsl b/indra/newview/app_settings/shaders/class3/lighting/sumLightsSpecularV.glsl index bf5c78f3e..ee61162c0 100644 --- a/indra/newview/app_settings/shaders/class3/lighting/sumLightsSpecularV.glsl +++ b/indra/newview/app_settings/shaders/class3/lighting/sumLightsSpecularV.glsl @@ -4,6 +4,8 @@ * Copyright (c) 2005-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 float calcDirectionalLightSpecular(inout vec4 specular, vec3 view, vec3 n, vec3 l, vec3 lightCol, float da); vec3 calcPointLightSpecular(inout vec4 specular, vec3 view, vec3 v, vec3 n, vec3 l, float r, float pw, vec3 lightCol); diff --git a/indra/newview/app_settings/shaders/class3/lighting/sumLightsV.glsl b/indra/newview/app_settings/shaders/class3/lighting/sumLightsV.glsl index 1c5234c45..ae84fcb9c 100644 --- a/indra/newview/app_settings/shaders/class3/lighting/sumLightsV.glsl +++ b/indra/newview/app_settings/shaders/class3/lighting/sumLightsV.glsl @@ -4,9 +4,11 @@ * Copyright (c) 2005-$CurrentYear$, Linden Research, Inc. * $License$ */ + +#version 120 float calcDirectionalLight(vec3 n, vec3 l); -float calcPointLight(vec3 v, vec3 n, vec4 lp, float la); +float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float is_pointlight); vec3 atmosAmbient(vec3 light); vec3 atmosAffectDirectionalLight(float lightIntensity); @@ -15,24 +17,21 @@ vec3 scaleUpLight(vec3 light); vec4 sumLights(vec3 pos, vec3 norm, vec4 color, vec4 baseLight) { - vec4 col; - col.a = color.a; + vec4 col = vec4(0.0, 0.0, 0.0, color.a); - // Add windlight lights - col.rgb = atmosAffectDirectionalLight(calcDirectionalLight(norm, gl_LightSource[0].position.xyz)); - col.rgb += atmosAmbient(baseLight.rgb); - col.rgb = scaleUpLight(col.rgb); - // Collect normal lights (need to be divided by two, as we later multiply by 2) - col.rgb += gl_LightSource[2].diffuse.rgb*calcPointLight(pos, norm, gl_LightSource[2].position, gl_LightSource[2].linearAttenuation); - col.rgb += gl_LightSource[3].diffuse.rgb*calcPointLight(pos, norm, gl_LightSource[3].position, gl_LightSource[3].linearAttenuation); - col.rgb += gl_LightSource[4].diffuse.rgb*calcPointLight(pos, norm, gl_LightSource[4].position, gl_LightSource[4].linearAttenuation); - col.rgb += gl_LightSource[5].diffuse.rgb*calcPointLight(pos, norm, gl_LightSource[5].position, gl_LightSource[5].linearAttenuation); - col.rgb += gl_LightSource[6].diffuse.rgb*calcPointLight(pos, norm, gl_LightSource[6].position, gl_LightSource[6].linearAttenuation); - col.rgb += gl_LightSource[7].diffuse.rgb*calcPointLight(pos, norm, gl_LightSource[7].position, gl_LightSource[7].linearAttenuation); + col.rgb += gl_LightSource[2].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[2].position, gl_LightSource[2].spotDirection.xyz, gl_LightSource[2].linearAttenuation, gl_LightSource[2].specular.a); + col.rgb += gl_LightSource[3].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[3].position, gl_LightSource[3].spotDirection.xyz, gl_LightSource[3].linearAttenuation, gl_LightSource[3].specular.a); + col.rgb += gl_LightSource[4].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[4].position, gl_LightSource[4].spotDirection.xyz, gl_LightSource[4].linearAttenuation, gl_LightSource[4].specular.a); + col.rgb += gl_LightSource[5].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[5].position, gl_LightSource[5].spotDirection.xyz, gl_LightSource[5].linearAttenuation, gl_LightSource[5].specular.a); + col.rgb += gl_LightSource[6].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[6].position, gl_LightSource[6].spotDirection.xyz, gl_LightSource[6].linearAttenuation, gl_LightSource[6].specular.a); + col.rgb += gl_LightSource[7].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[7].position, gl_LightSource[7].spotDirection.xyz, gl_LightSource[7].linearAttenuation, gl_LightSource[7].specular.a); col.rgb += gl_LightSource[1].diffuse.rgb*calcDirectionalLight(norm, gl_LightSource[1].position.xyz); col.rgb = scaleDownLight(col.rgb); - + + // Add windlight lights + col.rgb += atmosAffectDirectionalLight(calcDirectionalLight(norm, gl_LightSource[0].position.xyz)); + col.rgb += atmosAmbient(baseLight.rgb); col.rgb = min(col.rgb*color.rgb, 1.0); diff --git a/indra/newview/app_settings/ultra_graphics.xml b/indra/newview/app_settings/ultra_graphics.xml index f16ec6c30..78213ff87 100644 --- a/indra/newview/app_settings/ultra_graphics.xml +++ b/indra/newview/app_settings/ultra_graphics.xml @@ -13,7 +13,7 @@ - + diff --git a/indra/newview/ascentkeyword.cpp b/indra/newview/ascentkeyword.cpp index bcbc8a28e..65efe3958 100644 --- a/indra/newview/ascentkeyword.cpp +++ b/indra/newview/ascentkeyword.cpp @@ -33,6 +33,7 @@ #include "ascentkeyword.h" #include "llviewercontrol.h" +#include "llui.h" #include diff --git a/indra/newview/chatbar_as_cmdline.cpp b/indra/newview/chatbar_as_cmdline.cpp index 818df6279..e43a185c6 100644 --- a/indra/newview/chatbar_as_cmdline.cpp +++ b/indra/newview/chatbar_as_cmdline.cpp @@ -41,6 +41,7 @@ #include "llviewerregion.h" #include "llworld.h" #include "lluuid.h" +#include "lleventtimer.h" #include "llviewercontrol.h" #include "material_codes.h" diff --git a/indra/newview/featuretable.txt b/indra/newview/featuretable.txt index a587d10ac..e3a8ca0de 100644 --- a/indra/newview/featuretable.txt +++ b/indra/newview/featuretable.txt @@ -34,18 +34,16 @@ RenderFogRatio 1 4.0 RenderGamma 1 0 RenderGlowResolutionPow 1 9 RenderGround 1 1 -RenderLightingDetail 1 1 +RenderLocalLights 1 1 RenderMaxPartCount 1 8192 -RenderNightBrightness 1 1.0 RenderObjectBump 1 1 -RenderReflectionDetail 1 3 +RenderReflectionDetail 1 4 RenderTerrainDetail 1 1 RenderTerrainLODFactor 1 2.0 RenderTreeLODFactor 1 1.0 RenderUseImpostors 1 1 RenderVBOEnable 1 1 RenderVolumeLODFactor 1 2.0 -RenderWaterReflections 1 1 UseStartScreen 1 1 UseOcclusion 1 1 VertexShaderEnable 1 1 @@ -55,9 +53,12 @@ Disregard128DefaultDrawDistance 1 1 Disregard96DefaultDrawDistance 1 1 RenderShaderLightingMaxLevel 1 3 RenderTextureMemoryMultiple 1 1.0 -RenderUseFBO 1 1 -RenderDeferred 1 1 -RenderFastAlpha 1 1 +RenderUseFBO 1 1 +RenderFastAlpha 1 1 +RenderDeferred 1 1 +RenderDeferredGI 1 1 +RenderShadowDetail 1 2 +RenderAvatarPhysicsLODFactor 1 1.0 // // Low Graphics Settings @@ -70,7 +71,7 @@ RenderAvatarVP 1 0 RenderFarClip 1 64 RenderFlexTimeFactor 1 0.1 RenderGlowResolutionPow 1 8 -RenderLightingDetail 1 0 +RenderLocalLights 1 0 RenderMaxPartCount 1 1024 RenderObjectBump 1 0 RenderReflectionDetail 1 0 @@ -79,13 +80,15 @@ RenderTerrainLODFactor 1 1 RenderTreeLODFactor 1 0.25 RenderUseImpostors 1 1 RenderVolumeLODFactor 1 0.5 -RenderWaterReflections 1 0 VertexShaderEnable 1 0 WindLightUseAtmosShaders 1 0 WLSkyDetail 1 48 -RenderUseFBO 0 0 -RenderDeferred 0 0 -RenderFastAlpha 0 0 +RenderUseFBO 0 0 +RenderFastAlpha 1 1 +RenderDeferred 0 0 +RenderDeferredGI 0 0 +RenderShadowDetail 0 0 +RenderAvatarPhysicsLODFactor 1 0.0 // // Mid Graphics Settings @@ -98,7 +101,7 @@ RenderAvatarVP 1 1 RenderFarClip 1 96 RenderFlexTimeFactor 1 0.5 RenderGlowResolutionPow 1 8 -RenderLightingDetail 1 1 +RenderLocalLights 1 1 RenderMaxPartCount 1 2048 RenderObjectBump 1 1 RenderReflectionDetail 1 0 @@ -107,13 +110,15 @@ RenderTerrainLODFactor 1 1.0 RenderTreeLODFactor 1 0.5 RenderUseImpostors 1 1 RenderVolumeLODFactor 1 1.125 -RenderWaterReflections 1 0 VertexShaderEnable 1 1 WindLightUseAtmosShaders 1 0 WLSkyDetail 1 48 -RenderUseFBO 1 0 -RenderDeferred 1 0 -RenderFastAlpha 1 0 +RenderUseFBO 1 0 +RenderFastAlpha 1 0 +RenderDeferred 1 0 +RenderDeferredGI 1 0 +RenderShadowDetail 1 0 +RenderAvatarPhysicsLODFactor 1 0.5 // @@ -127,7 +132,7 @@ RenderAvatarVP 1 1 RenderFarClip 1 128 RenderFlexTimeFactor 1 1.0 RenderGlowResolutionPow 1 9 -RenderLightingDetail 1 1 +RenderLocalLights 1 1 RenderMaxPartCount 1 4096 RenderObjectBump 1 1 RenderReflectionDetail 1 2 @@ -136,13 +141,15 @@ RenderTerrainLODFactor 1 2.0 RenderTreeLODFactor 1 0.5 RenderUseImpostors 1 1 RenderVolumeLODFactor 1 1.125 -RenderWaterReflections 1 0 VertexShaderEnable 1 1 WindLightUseAtmosShaders 1 1 WLSkyDetail 1 48 -RenderUseFBO 1 0 -RenderDeferred 1 0 -RenderFastAlpha 1 0 +RenderUseFBO 1 0 +RenderFastAlpha 1 0 +RenderDeferred 1 0 +RenderDeferredGI 1 0 +RenderShadowDetail 1 0 +RenderAvatarPhysicsLODFactor 1 0.75 // @@ -156,22 +163,24 @@ RenderAvatarVP 1 1 RenderFarClip 1 256 RenderFlexTimeFactor 1 1.0 RenderGlowResolutionPow 1 9 -RenderLightingDetail 1 1 +RenderLocalLights 1 1 RenderMaxPartCount 1 8192 RenderObjectBump 1 1 -RenderReflectionDetail 1 3 +RenderReflectionDetail 1 4 RenderTerrainDetail 1 1 RenderTerrainLODFactor 1 2.0 RenderTreeLODFactor 1 1.0 RenderUseImpostors 1 1 RenderVolumeLODFactor 1 2.0 -RenderWaterReflections 1 1 VertexShaderEnable 1 1 WindLightUseAtmosShaders 1 1 WLSkyDetail 1 128 -RenderUseFBO 1 1 -RenderDeferred 1 1 -RenderFastAlpha 1 1 +RenderUseFBO 1 1 +RenderFastAlpha 1 0 +RenderDeferred 1 1 +RenderDeferredGI 1 0 +RenderShadowDetail 1 0 +RenderAvatarPhysicsLODFactor 1 1.0 // // Class Unknown Hardware (unknown) @@ -209,9 +218,10 @@ RenderVBOEnable 1 1 list NoPixelShaders RenderAvatarVP 0 0 RenderAvatarCloth 0 0 -RenderWaterReflections 0 0 +RenderReflectionDetail 0 0 VertexShaderEnable 0 0 WindLightUseAtmosShaders 0 0 +RenderDeferred 0 0 // // No Vertex Shaders available @@ -219,9 +229,10 @@ WindLightUseAtmosShaders 0 0 list NoVertexShaders RenderAvatarVP 0 0 RenderAvatarCloth 0 0 -RenderWaterReflections 0 0 +RenderReflectionDetail 0 0 VertexShaderEnable 0 0 WindLightUseAtmosShaders 0 0 +RenderDeferred 0 0 // "Default" setups for safe, low, medium, high // @@ -229,14 +240,16 @@ list safe RenderAnisotropic 1 0 RenderAvatarCloth 0 0 RenderAvatarVP 0 0 -RenderLightingDetail 1 0 +RenderLocalLights 1 0 RenderObjectBump 0 0 RenderMaxPartCount 1 1024 RenderTerrainDetail 1 0 RenderUseImpostors 0 0 RenderVBOEnable 1 0 -RenderWaterReflections 0 0 +RenderReflectionDetail 0 0 WindLightUseAtmosShaders 0 0 +RenderUseFBO 1 0 +RenderDeferred 1 0 // // CPU based feature masks @@ -260,12 +273,13 @@ RenderVBOEnable 1 0 list Intel RenderAnisotropic 1 0 -RenderLightingDetail 1 0 +RenderLocalLights 1 0 RenderUseImpostors 0 0 +RenderDeferred 1 0 list GeForce2 RenderAnisotropic 1 0 -RenderLightingDetail 1 0 +RenderLocalLights 1 0 RenderMaxPartCount 1 2048 RenderTerrainDetail 1 0 RenderVBOEnable 1 1 diff --git a/indra/newview/featuretable_linux.txt b/indra/newview/featuretable_linux.txt index c8245ae93..e64bfa3e3 100644 --- a/indra/newview/featuretable_linux.txt +++ b/indra/newview/featuretable_linux.txt @@ -34,18 +34,16 @@ RenderFogRatio 1 4.0 RenderGamma 1 0 RenderGlowResolutionPow 1 9 RenderGround 1 1 -RenderLightingDetail 1 1 +RenderLocalLights 1 1 RenderMaxPartCount 1 8192 -RenderNightBrightness 1 1.0 RenderObjectBump 1 1 -RenderReflectionDetail 1 3 +RenderReflectionDetail 1 4 RenderTerrainDetail 1 1 RenderTerrainLODFactor 1 2.0 RenderTreeLODFactor 1 1.0 RenderUseImpostors 1 1 RenderVBOEnable 1 1 RenderVolumeLODFactor 1 2.0 -RenderWaterReflections 1 1 UseStartScreen 1 1 UseOcclusion 1 1 VertexShaderEnable 1 1 @@ -55,9 +53,12 @@ Disregard128DefaultDrawDistance 1 1 Disregard96DefaultDrawDistance 1 1 RenderShaderLightingMaxLevel 1 3 RenderTextureMemoryMultiple 1 1.0 -RenderUseFBO 1 1 -RenderDeferred 1 1 -RenderFastAlpha 1 1 +RenderUseFBO 1 1 +RenderFastAlpha 1 1 +RenderDeferred 1 1 +RenderDeferredGI 1 1 +RenderShadowDetail 1 2 +RenderAvatarPhysicsLODFactor 1 1.0 // // Low Graphics Settings @@ -70,7 +71,7 @@ RenderAvatarVP 1 0 RenderFarClip 1 64 RenderFlexTimeFactor 1 0.1 RenderGlowResolutionPow 1 8 -RenderLightingDetail 1 0 +RenderLocalLights 1 0 RenderMaxPartCount 1 1024 RenderObjectBump 1 0 RenderReflectionDetail 1 0 @@ -79,13 +80,15 @@ RenderTerrainLODFactor 1 1 RenderTreeLODFactor 1 0.25 RenderUseImpostors 1 1 RenderVolumeLODFactor 1 0.5 -RenderWaterReflections 1 0 VertexShaderEnable 1 0 WindLightUseAtmosShaders 1 0 WLSkyDetail 1 48 -RenderUseFBO 0 0 -RenderDeferred 0 0 -RenderFastAlpha 0 0 +RenderUseFBO 0 0 +RenderFastAlpha 1 1 +RenderDeferred 0 0 +RenderDeferredGI 0 0 +RenderShadowDetail 0 0 +RenderAvatarPhysicsLODFactor 1 0.0 // // Mid Graphics Settings @@ -98,7 +101,7 @@ RenderAvatarVP 1 1 RenderFarClip 1 96 RenderFlexTimeFactor 1 0.5 RenderGlowResolutionPow 1 8 -RenderLightingDetail 1 1 +RenderLocalLights 1 1 RenderMaxPartCount 1 2048 RenderObjectBump 1 1 RenderReflectionDetail 1 0 @@ -107,13 +110,15 @@ RenderTerrainLODFactor 1 1.0 RenderTreeLODFactor 1 0.5 RenderUseImpostors 1 1 RenderVolumeLODFactor 1 1.125 -RenderWaterReflections 1 0 VertexShaderEnable 1 1 WindLightUseAtmosShaders 1 0 WLSkyDetail 1 48 -RenderUseFBO 1 0 -RenderDeferred 1 0 -RenderFastAlpha 1 0 +RenderUseFBO 1 0 +RenderFastAlpha 1 0 +RenderDeferred 1 0 +RenderDeferredGI 1 0 +RenderShadowDetail 1 0 +RenderAvatarPhysicsLODFactor 1 0.5 // @@ -127,7 +132,7 @@ RenderAvatarVP 1 1 RenderFarClip 1 128 RenderFlexTimeFactor 1 1.0 RenderGlowResolutionPow 1 9 -RenderLightingDetail 1 1 +RenderLocalLights 1 1 RenderMaxPartCount 1 4096 RenderObjectBump 1 1 RenderReflectionDetail 1 2 @@ -136,13 +141,15 @@ RenderTerrainLODFactor 1 2.0 RenderTreeLODFactor 1 0.5 RenderUseImpostors 1 1 RenderVolumeLODFactor 1 1.125 -RenderWaterReflections 1 0 VertexShaderEnable 1 1 WindLightUseAtmosShaders 1 1 WLSkyDetail 1 48 -RenderUseFBO 1 0 -RenderDeferred 1 0 -RenderFastAlpha 1 0 +RenderUseFBO 1 0 +RenderFastAlpha 1 0 +RenderDeferred 1 0 +RenderDeferredGI 1 0 +RenderShadowDetail 1 0 +RenderAvatarPhysicsLODFactor 1 0.75 // @@ -156,22 +163,24 @@ RenderAvatarVP 1 1 RenderFarClip 1 256 RenderFlexTimeFactor 1 1.0 RenderGlowResolutionPow 1 9 -RenderLightingDetail 1 1 +RenderLocalLights 1 1 RenderMaxPartCount 1 8192 RenderObjectBump 1 1 -RenderReflectionDetail 1 3 +RenderReflectionDetail 1 4 RenderTerrainDetail 1 1 RenderTerrainLODFactor 1 2.0 RenderTreeLODFactor 1 1.0 RenderUseImpostors 1 1 RenderVolumeLODFactor 1 2.0 -RenderWaterReflections 1 1 VertexShaderEnable 1 1 WindLightUseAtmosShaders 1 1 WLSkyDetail 1 128 -RenderUseFBO 1 1 -RenderDeferred 1 1 -RenderFastAlpha 1 1 +RenderUseFBO 1 1 +RenderFastAlpha 1 0 +RenderDeferred 1 1 +RenderDeferredGI 1 0 +RenderShadowDetail 1 0 +RenderAvatarPhysicsLODFactor 1 1.0 // @@ -210,9 +219,10 @@ RenderVBOEnable 1 1 list NoPixelShaders RenderAvatarVP 0 0 RenderAvatarCloth 0 0 -RenderWaterReflections 0 0 +RenderReflectionDetail 0 0 VertexShaderEnable 0 0 WindLightUseAtmosShaders 0 0 +RenderDeferred 0 0 // // No Vertex Shaders available @@ -220,9 +230,10 @@ WindLightUseAtmosShaders 0 0 list NoVertexShaders RenderAvatarVP 0 0 RenderAvatarCloth 0 0 -RenderWaterReflections 0 0 +RenderReflectionDetail 0 0 VertexShaderEnable 0 0 WindLightUseAtmosShaders 0 0 +RenderDeferred 0 0 // "Default" setups for safe, low, medium, high // @@ -230,16 +241,16 @@ list safe RenderAnisotropic 1 0 RenderAvatarCloth 0 0 RenderAvatarVP 0 0 -RenderLightingDetail 1 0 +RenderLocalLights 1 0 RenderObjectBump 0 0 RenderMaxPartCount 1 1024 RenderTerrainDetail 1 0 RenderUseImpostors 0 0 RenderVBOEnable 1 0 -RenderWaterReflections 0 0 +RenderReflectionDetail 0 0 WindLightUseAtmosShaders 0 0 -RenderUseFBO 1 0 -RenderDeferred 1 0 +RenderUseFBO 1 0 +RenderDeferred 1 0 // @@ -264,13 +275,14 @@ RenderVBOEnable 1 0 list Intel RenderAnisotropic 1 0 -RenderLightingDetail 1 0 +RenderLocalLights 1 0 // Avoid some Intel crashes on Linux RenderCubeMap 0 0 +RenderDeferred 1 0 list GeForce2 RenderAnisotropic 1 0 -RenderLightingDetail 1 0 +RenderLocalLights 1 0 RenderMaxPartCount 1 2048 RenderTerrainDetail 1 0 RenderVBOEnable 1 1 diff --git a/indra/newview/featuretable_mac.txt b/indra/newview/featuretable_mac.txt index 86df881f9..16156fe42 100644 --- a/indra/newview/featuretable_mac.txt +++ b/indra/newview/featuretable_mac.txt @@ -34,18 +34,16 @@ RenderFogRatio 1 4.0 RenderGamma 1 0 RenderGlowResolutionPow 1 9 RenderGround 1 1 -RenderLightingDetail 1 1 +RenderLocalLights 1 1 RenderMaxPartCount 1 8192 -RenderNightBrightness 1 1.0 RenderObjectBump 1 1 -RenderReflectionDetail 1 3 +RenderReflectionDetail 1 4 RenderTerrainDetail 1 1 RenderTerrainLODFactor 1 2.0 RenderTreeLODFactor 1 1.0 RenderUseImpostors 1 1 RenderVBOEnable 1 1 RenderVolumeLODFactor 1 2.0 -RenderWaterReflections 1 1 UseStartScreen 1 1 UseOcclusion 1 1 VertexShaderEnable 1 1 @@ -55,9 +53,12 @@ Disregard128DefaultDrawDistance 1 1 Disregard96DefaultDrawDistance 1 1 RenderShaderLightingMaxLevel 1 3 RenderTextureMemoryMultiple 1 1.0 -RenderUseFBO 1 1 -RenderDeferred 1 1 -RenderFastAlpha 1 1 +RenderUseFBO 1 1 +RenderFastAlpha 1 1 +RenderDeferred 1 1 +RenderDeferredGI 1 1 +RenderShadowDetail 1 2 +RenderAvatarPhysicsLODFactor 1 1.0 // // Low Graphics Settings @@ -70,7 +71,7 @@ RenderAvatarVP 1 0 RenderFarClip 1 64 RenderFlexTimeFactor 1 0.1 RenderGlowResolutionPow 1 8 -RenderLightingDetail 1 0 +RenderLocalLights 1 0 RenderMaxPartCount 1 1024 RenderObjectBump 1 0 RenderReflectionDetail 1 0 @@ -79,13 +80,15 @@ RenderTerrainLODFactor 1 1 RenderTreeLODFactor 1 0.25 RenderUseImpostors 1 1 RenderVolumeLODFactor 1 0.5 -RenderWaterReflections 1 0 VertexShaderEnable 1 0 WindLightUseAtmosShaders 1 0 WLSkyDetail 1 48 -RenderUseFBO 0 0 -RenderDeferred 0 0 -RenderFastAlpha 0 0 +RenderUseFBO 0 0 +RenderFastAlpha 1 1 +RenderDeferred 0 0 +RenderDeferredGI 0 0 +RenderShadowDetail 0 0 +RenderAvatarPhysicsLODFactor 1 0.0 // // Mid Graphics Settings @@ -98,7 +101,7 @@ RenderAvatarVP 1 1 RenderFarClip 1 96 RenderFlexTimeFactor 1 0.5 RenderGlowResolutionPow 1 8 -RenderLightingDetail 1 1 +RenderLocalLights 1 1 RenderMaxPartCount 1 2048 RenderObjectBump 1 1 RenderReflectionDetail 1 0 @@ -107,13 +110,15 @@ RenderTerrainLODFactor 1 1.0 RenderTreeLODFactor 1 0.5 RenderUseImpostors 1 1 RenderVolumeLODFactor 1 1.125 -RenderWaterReflections 1 0 VertexShaderEnable 1 1 WindLightUseAtmosShaders 1 0 WLSkyDetail 1 48 -RenderUseFBO 1 0 -RenderDeferred 1 0 -RenderFastAlpha 1 0 +RenderUseFBO 1 0 +RenderFastAlpha 1 0 +RenderDeferred 1 0 +RenderDeferredGI 1 0 +RenderShadowDetail 1 0 +RenderAvatarPhysicsLODFactor 1 0.5 // @@ -127,7 +132,7 @@ RenderAvatarVP 1 1 RenderFarClip 1 128 RenderFlexTimeFactor 1 1.0 RenderGlowResolutionPow 1 9 -RenderLightingDetail 1 1 +RenderLocalLights 1 1 RenderMaxPartCount 1 4096 RenderObjectBump 1 1 RenderReflectionDetail 1 2 @@ -136,13 +141,15 @@ RenderTerrainLODFactor 1 2.0 RenderTreeLODFactor 1 0.5 RenderUseImpostors 1 1 RenderVolumeLODFactor 1 1.125 -RenderWaterReflections 1 0 VertexShaderEnable 1 1 WindLightUseAtmosShaders 1 1 WLSkyDetail 1 48 -RenderUseFBO 1 0 -RenderDeferred 1 0 -RenderFastAlpha 1 0 +RenderUseFBO 1 0 +RenderFastAlpha 1 0 +RenderDeferred 1 0 +RenderDeferredGI 1 0 +RenderShadowDetail 1 0 +RenderAvatarPhysicsLODFactor 1 0.75 // @@ -156,22 +163,24 @@ RenderAvatarVP 1 1 RenderFarClip 1 256 RenderFlexTimeFactor 1 1.0 RenderGlowResolutionPow 1 9 -RenderLightingDetail 1 1 +RenderLocalLights 1 1 RenderMaxPartCount 1 8192 RenderObjectBump 1 1 -RenderReflectionDetail 1 3 +RenderReflectionDetail 1 4 RenderTerrainDetail 1 1 RenderTerrainLODFactor 1 2.0 RenderTreeLODFactor 1 1.0 RenderUseImpostors 1 1 RenderVolumeLODFactor 1 2.0 -RenderWaterReflections 1 1 VertexShaderEnable 1 1 WindLightUseAtmosShaders 1 1 WLSkyDetail 1 128 -RenderUseFBO 1 1 -RenderDeferred 1 1 -RenderFastAlpha 1 1 +RenderUseFBO 1 1 +RenderFastAlpha 1 0 +RenderDeferred 1 1 +RenderDeferredGI 1 0 +RenderShadowDetail 1 0 +RenderAvatarPhysicsLODFactor 1 1.0 // // Class Unknown Hardware (unknown) @@ -209,9 +218,10 @@ RenderVBOEnable 1 1 list NoPixelShaders RenderAvatarVP 0 0 RenderAvatarCloth 0 0 -RenderWaterReflections 0 0 +RenderReflectionDetail 0 0 VertexShaderEnable 0 0 WindLightUseAtmosShaders 0 0 +RenderDeferred 0 0 // // No Vertex Shaders available @@ -219,9 +229,10 @@ WindLightUseAtmosShaders 0 0 list NoVertexShaders RenderAvatarVP 0 0 RenderAvatarCloth 0 0 -RenderWaterReflections 0 0 +RenderReflectionDetail 0 0 VertexShaderEnable 0 0 WindLightUseAtmosShaders 0 0 +RenderDeferred 0 0 // "Default" setups for safe, low, medium, high // @@ -229,14 +240,16 @@ list safe RenderAnisotropic 1 0 RenderAvatarCloth 0 0 RenderAvatarVP 0 0 -RenderLightingDetail 1 0 +RenderLocalLights 1 0 RenderObjectBump 0 0 RenderMaxPartCount 1 1024 RenderTerrainDetail 1 0 RenderUseImpostors 0 0 RenderVBOEnable 1 0 -RenderWaterReflections 0 0 +RenderReflectionDetail 0 0 WindLightUseAtmosShaders 0 0 +RenderUseFBO 1 0 +RenderDeferred 1 0 // // CPU based feature masks @@ -260,11 +273,12 @@ RenderVBOEnable 1 0 list Intel RenderAnisotropic 1 0 -RenderLightingDetail 1 0 +RenderLocalLights 1 0 +RenderDeferred 1 0 list GeForce2 RenderAnisotropic 1 0 -RenderLightingDetail 1 0 +RenderLocalLights 1 0 RenderMaxPartCount 1 2048 RenderTerrainDetail 1 0 RenderVBOEnable 1 1 diff --git a/indra/newview/floaterao.cpp b/indra/newview/floaterao.cpp index 489a838eb..c0a2bd3ac 100644 --- a/indra/newview/floaterao.cpp +++ b/indra/newview/floaterao.cpp @@ -419,7 +419,7 @@ void LLFloaterAO::onComboBoxCommit(LLUICtrl* ctrl, void* userdata) { int state = STATE_AGENT_IDLE; std::string stranim = box->getValue().asString(); -// llinfos << "state " << (gAgent.getAvatarObject()->mIsSitting) << " - " << getAnimationState() << llendl; +// llinfos << "state " << (gAgent.getAvatarObject()->isSitting()) << " - " << getAnimationState() << llendl; if (box->getName() == "walks") { gAgent.sendAnimationRequest(GetAnimID(ANIM_AGENT_WALK), ANIM_REQUEST_STOP); @@ -442,7 +442,7 @@ void LLFloaterAO::onComboBoxCommit(LLUICtrl* ctrl, void* userdata) { if (gAgent.getAvatarObject() && (gSavedSettings.getBOOL("AOEnabled")) && (gSavedSettings.getBOOL("AOSitsEnabled"))) { - if ((gAgent.getAvatarObject()->mIsSitting) && (getAnimationState() == STATE_AGENT_SIT)) + if ((gAgent.getAvatarObject()->isSitting()) && (getAnimationState() == STATE_AGENT_SIT)) { // llinfos << "sitting " << GetAnimID(ANIM_AGENT_SIT) << " " << getAssetIDByName(stranim) << llendl; gAgent.sendAnimationRequest(GetAnimID(ANIM_AGENT_SIT), ANIM_REQUEST_STOP); @@ -457,7 +457,7 @@ void LLFloaterAO::onComboBoxCommit(LLUICtrl* ctrl, void* userdata) // llinfos << "gsitting " << GetAnimID(ANIM_AGENT_SIT_GROUND) << " " << getAssetIDByName(stranim) << llendl; if (gAgent.getAvatarObject()) { - if ((gAgent.getAvatarObject()->mIsSitting) && (getAnimationState() == STATE_AGENT_GROUNDSIT)) + if ((gAgent.getAvatarObject()->isSitting()) && (getAnimationState() == STATE_AGENT_GROUNDSIT)) { // llinfos << "gsitting " << GetAnimID(ANIM_AGENT_SIT_GROUND) << " " << getAssetIDByName(stranim) << llendl; gAgent.sendAnimationRequest(GetAnimID(ANIM_AGENT_SIT_GROUND), ANIM_REQUEST_STOP); @@ -768,7 +768,7 @@ int LLFloaterAO::getAnimationState() { if (gAgent.getAvatarObject()) { - if (gAgent.getAvatarObject()->mIsSitting) setAnimationState(STATE_AGENT_SIT); + if (gAgent.getAvatarObject()->isSitting()) setAnimationState(STATE_AGENT_SIT); else if (gAgent.getFlying()) setAnimationState(STATE_AGENT_HOVER); } return mAnimationState; @@ -859,7 +859,7 @@ BOOL LLFloaterAO::ChangeStand() { if (gSavedSettings.getBOOL("AONoStandsInMouselook") && gAgent.cameraMouselook()) return FALSE; - if (gAgent.getAvatarObject()->mIsSitting) + if (gAgent.getAvatarObject()->isSitting()) { // stopMotion(getCurrentStandId(), FALSE, TRUE); //stop stand first then set state // if (getAnimationState() != STATE_AGENT_GROUNDSIT) setAnimationState(STATE_AGENT_SIT); @@ -912,7 +912,7 @@ BOOL LLFloaterAO::startMotion(const LLUUID& id, F32 time_offset, BOOL stand) BOOL sitting = FALSE; if (gAgent.getAvatarObject()) { - sitting = gAgent.getAvatarObject()->mIsSitting; + sitting = gAgent.getAvatarObject()->isSitting(); } if (sitting) return FALSE; gAgent.sendAnimationRequest(id, ANIM_REQUEST_START); diff --git a/indra/newview/floaterao.h b/indra/newview/floaterao.h index cf8ee2252..55cc7c052 100644 --- a/indra/newview/floaterao.h +++ b/indra/newview/floaterao.h @@ -5,6 +5,7 @@ #include "llfloater.h" #include "llviewercontrol.h" #include "llagent.h" +#include "lleventtimer.h" class AONoteCardDropTarget; diff --git a/indra/newview/floaterlocalassetbrowse.cpp b/indra/newview/floaterlocalassetbrowse.cpp index 76fa162b1..90458e09f 100644 --- a/indra/newview/floaterlocalassetbrowse.cpp +++ b/indra/newview/floaterlocalassetbrowse.cpp @@ -55,7 +55,7 @@ this feature is still a work in progress. #include #include "llviewertexturelist.h" #include "llviewerobjectlist.h" -#include "llfilepicker.h" +#include "statemachine/aifilepicker.h" #include "llviewermenufile.h" #include "llfloaterimagepreview.h" #include "llfile.h" @@ -376,6 +376,12 @@ std::vector LocalBitmap::getUsingObjects(bool seek_by_type, boo iter != gObjectList.mObjects.end(); iter++ ) { LLViewerObject* obj = *iter; + + if (obj->isDead()) + { + continue; + } + affected_object shell; shell.object = obj; shell.local_sculptmap = false; @@ -453,23 +459,27 @@ LocalAssetBrowser::~LocalAssetBrowser() void LocalAssetBrowser::AddBitmap() { - LLFilePicker& picker = LLFilePicker::instance(); - if ( !picker.getMultipleOpenFiles(LLFilePicker::FFLOAD_IMAGE) ) - { return; } + AIFilePicker* filepicker = AIFilePicker::create(); + filepicker->open(FFLOAD_IMAGE, "", "image", true); + filepicker->run(boost::bind(&LocalAssetBrowser::AddBitmap_continued, filepicker)); +} + +void LocalAssetBrowser::AddBitmap_continued(AIFilePicker* filepicker) +{ + if (!filepicker->hasFilename()) + return; bool change_happened = false; - std::string filename = picker.getFirstFile(); - while( !filename.empty() ) + std::vector const& filenames(filepicker->getFilenames()); + for(std::vector::const_iterator filename = filenames.begin(); filename != filenames.end(); ++filename) { - LocalBitmap* unit = new LocalBitmap( filename ); + LocalBitmap* unit = new LocalBitmap(*filename); if ( unit->getIfValidBool() ) { loaded_bitmaps.push_back( unit ); change_happened = true; } - - filename = picker.getNextFile(); } if ( change_happened ) diff --git a/indra/newview/floaterlocalassetbrowse.h b/indra/newview/floaterlocalassetbrowse.h index 6ee1c75a3..fb26cdccc 100644 --- a/indra/newview/floaterlocalassetbrowse.h +++ b/indra/newview/floaterlocalassetbrowse.h @@ -42,6 +42,7 @@ tag: vaa emerald local_asset_browser #include "llscrolllistctrl.h" #include "lltexturectrl.h" #include "lldrawable.h" +#include "lleventtimer.h" /*=======================================*/ @@ -169,6 +170,7 @@ class LocalBitmap */ +class AIFilePicker; class LocalAssetBrowser { @@ -181,6 +183,7 @@ class LocalAssetBrowser static void setLayerUpdated(bool toggle) { mLayerUpdated = toggle; } static void setSculptUpdated(bool toggle) { mSculptUpdated = toggle; } static void AddBitmap(void); + static void AddBitmap_continued(AIFilePicker* filepicker); static void DelBitmap( std::vector, S32 column = BITMAPLIST_COL_ID ); /* UpdateTextureCtrlList was made public cause texturectrl requests it once on spawn diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index 49dee2357..8e3c01011 100644 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -425,8 +425,6 @@ LLAgent::LLAgent() : mAutoPilotRotationThreshold(0.f), mAutoPilotFinishedCallback(NULL), mAutoPilotCallbackData(NULL), - - mCapabilities(), mEffectColor(0.f, 1.f, 1.f, 1.f), @@ -864,7 +862,7 @@ void LLAgent::setFlying(BOOL fly) } // don't allow taking off while sitting - if (fly && mAvatarObject->mIsSitting) + if (fly && mAvatarObject->isSitting()) { return; } @@ -1363,7 +1361,7 @@ F32 LLAgent::clampPitchToLimits(F32 angle) F32 angle_from_skyward = acos( mFrameAgent.getAtAxis() * skyward ); - if (isAgentAvatarValid() && mAvatarObject->mIsSitting) + if (isAgentAvatarValid() && mAvatarObject->isSitting()) { look_down_limit = 130.f * DEG_TO_RAD; } @@ -2716,7 +2714,7 @@ void LLAgent::updateLookAt(const S32 mouse_x, const S32 mouse_y) else { // *FIX: rotate mframeagent by sit object's rotation? - LLQuaternion look_rotation = mAvatarObject->mIsSitting ? mAvatarObject->getRenderRotation() : mFrameAgent.getQuaternion(); // use camera's current rotation + LLQuaternion look_rotation = mAvatarObject->isSitting() ? mAvatarObject->getRenderRotation() : mFrameAgent.getQuaternion(); // use camera's current rotation LLVector3 look_offset = LLVector3(2.f, 0.f, 0.f) * look_rotation * av_inv_rot; setLookAt(LOOKAT_TARGET_IDLE, mAvatarObject, look_offset); } @@ -3158,7 +3156,7 @@ void LLAgent::updateCamera() validateFocusObject(); if (isAgentAvatarValid() && - mAvatarObject->mIsSitting && + mAvatarObject->isSitting() && camera_mode == CAMERA_MODE_MOUSELOOK) { //Ventrella @@ -3279,7 +3277,7 @@ void LLAgent::updateCamera() // (2) focus, and (3) upvector. They can then be queried elsewhere in llAgent. //-------------------------------------------------------------------------------- // *TODO: use combined rotation of frameagent and sit object - LLQuaternion avatarRotationForFollowCam = mAvatarObject->mIsSitting ? mAvatarObject->getRenderRotation() : mFrameAgent.getQuaternion(); + LLQuaternion avatarRotationForFollowCam = mAvatarObject->isSitting() ? mAvatarObject->getRenderRotation() : mFrameAgent.getQuaternion(); LLFollowCamParams* current_cam = LLFollowCamMgr::getActiveFollowCamParams(); if (current_cam) @@ -3460,7 +3458,7 @@ void LLAgent::updateCamera() } mLastPositionGlobal = global_pos; - if (LLVOAvatar::sVisibleInFirstPerson && mAvatarObject.notNull() && !mAvatarObject->mIsSitting && cameraMouselook()) + if (LLVOAvatar::sVisibleInFirstPerson && mAvatarObject.notNull() && !mAvatarObject->isSitting() && cameraMouselook()) { LLVector3 head_pos = mAvatarObject->mHeadp->getWorldPosition() + LLVector3(0.08f, 0.f, 0.05f) * mAvatarObject->mHeadp->getWorldRotation() + @@ -3650,7 +3648,7 @@ LLVector3d LLAgent::calcFocusPositionTargetGlobal() } return mFocusTargetGlobal; } - else if (mSitCameraEnabled && mAvatarObject.notNull() && mAvatarObject->mIsSitting && mSitCameraReferenceObject.notNull()) + else if (mSitCameraEnabled && mAvatarObject.notNull() && mAvatarObject->isSitting() && mSitCameraReferenceObject.notNull()) { // sit camera LLVector3 object_pos = mSitCameraReferenceObject->getRenderPosition(); @@ -3775,7 +3773,7 @@ LLVector3d LLAgent::calcCameraPositionTargetGlobal(BOOL *hit_limit) return LLVector3d::zero; } head_offset.clearVec(); - if (mAvatarObject->mIsSitting && mAvatarObject->getParent()) + if (mAvatarObject->isSitting() && mAvatarObject->getParent()) { mAvatarObject->updateHeadOffset(); head_offset.mdV[VX] = mAvatarObject->mHeadOffset.mV[VX]; @@ -3789,7 +3787,7 @@ LLVector3d LLAgent::calcCameraPositionTargetGlobal(BOOL *hit_limit) else { head_offset.mdV[VZ] = mAvatarObject->mHeadOffset.mV[VZ]; - if (mAvatarObject->mIsSitting) + if (mAvatarObject->isSitting()) { head_offset.mdV[VZ] += 0.1; } @@ -3805,7 +3803,7 @@ LLVector3d LLAgent::calcCameraPositionTargetGlobal(BOOL *hit_limit) if (mSitCameraEnabled && isAgentAvatarValid() - && mAvatarObject->mIsSitting + && mAvatarObject->isSitting() && mSitCameraReferenceObject.notNull()) { // sit camera @@ -3837,7 +3835,7 @@ LLVector3d LLAgent::calcCameraPositionTargetGlobal(BOOL *hit_limit) local_camera_offset = mFrameAgent.rotateToAbsolute( local_camera_offset ); } - if (!mCameraCollidePlane.isExactlyZero() && (!isAgentAvatarValid() || !mAvatarObject->mIsSitting)) + if (!mCameraCollidePlane.isExactlyZero() && (!isAgentAvatarValid() || !mAvatarObject->isSitting())) { LLVector3 plane_normal; plane_normal.setVec(mCameraCollidePlane.mV); @@ -4215,7 +4213,7 @@ void LLAgent::changeCameraToThirdPerson(BOOL animate) // [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) +SG if ( (!gRlvHandler.hasBehaviour(RLV_BHVR_UNSIT)) && (mAvatarObject.notNull()) - && (mAvatarObject->mIsSitting) + && (mAvatarObject->isSitting()) && gSavedSettings.getBOOL("SianaUnsitOnCamReset")) { setControlFlags(AGENT_CONTROL_STAND_UP); // force stand up @@ -4228,7 +4226,7 @@ void LLAgent::changeCameraToThirdPerson(BOOL animate) if (isAgentAvatarValid()) { - if (!mAvatarObject->mIsSitting) + if (!mAvatarObject->isSitting()) { mAvatarObject->mPelvisp->setPosition(LLVector3::zero); } @@ -6308,7 +6306,7 @@ void LLAgent::teleportViaLandmark(const LLUUID& landmark_asset_id) // [RLVa:KB] - Checked: 2009-07-07 (RLVa-1.0.0d) if ( (rlv_handler_t::isEnabled()) && ( (gRlvHandler.hasBehaviour(RLV_BHVR_TPLM)) || - ((gRlvHandler.hasBehaviour(RLV_BHVR_UNSIT)) && (mAvatarObject.notNull()) && (mAvatarObject->mIsSitting)) )) + ((gRlvHandler.hasBehaviour(RLV_BHVR_UNSIT)) && (mAvatarObject.notNull()) && (mAvatarObject->isSitting())) )) { RlvNotifications::notifyBlockedTeleport(); return; @@ -6384,7 +6382,7 @@ void LLAgent::teleportViaLocation(const LLVector3d& pos_global) { // If we're getting teleported due to @tpto we should disregard any @tploc=n or @unsit=n restrictions from the same object if ( (gRlvHandler.hasBehaviourExcept(RLV_BHVR_TPLOC, gRlvHandler.getCurrentObject())) || - ( (mAvatarObject.notNull()) && (mAvatarObject->mIsSitting) && + ( (mAvatarObject.notNull()) && (mAvatarObject->isSitting()) && (gRlvHandler.hasBehaviourExcept(RLV_BHVR_UNSIT, gRlvHandler.getCurrentObject()))) ) { RlvNotifications::notifyBlockedTeleport(); @@ -7093,16 +7091,6 @@ void LLAgent::processAgentInitialWearablesUpdate( LLMessageSystem* mesgsys, void // before we had wearables, or that the database has gotten messed up. return; } - //else - //{ - // // OGPX HACK: OGP authentication does not pass back login-flags, - // // thus doesn't check for "gendered" flag - // // so this isn't an ideal place for this because the check in idle_startup in STATE_WEARABLES_WAIT - // // is happening *before* this call. That causes the welcomechoosesex dialog to be displayed - // // but I'm torn on removing this commented out code because I'm unsure how the initial wearables - // // code will work out. - // gAgent.setGenderChosen(TRUE); - //} //lldebugs << "processAgentInitialWearablesUpdate()" << llendl; // Add wearables @@ -8544,43 +8532,6 @@ void LLAgent::userAttachMultipleAttachments(LLInventoryModel::item_array_t& obj_ } } -// OGPX - This code will change when capabilities get refactored. -// Right now this is used for capabilities that we get from OGP agent domain -void LLAgent::setCapability(const std::string& name, const std::string& url) -{ -#if 0 // OGPX : I think (hope?) we don't need this - // but I'm leaving it here commented out because I'm not quite - // sure why the region capabilities code had it wedged in setCap call - // Maybe the agent domain capabilities will need something like this as well - - if (name == "EventQueueGet") - { - delete mEventPoll; - mEventPoll = NULL; - mEventPoll = new LLEventPoll(url, getHost()); - } - else if (name == "UntrustedSimulatorMessage") - { - LLHTTPSender::setSender(mHost, new LLCapHTTPSender(url)); - } - else -#endif - { - mCapabilities[name] = url; - } -} - -//OGPX : Agent Domain capabilities... this needs to be refactored -std::string LLAgent::getCapability(const std::string& name) const -{ - CapabilityMap::const_iterator iter = mCapabilities.find(name); - if (iter == mCapabilities.end()) - { - return ""; - } - return iter->second; -} - void LLAgent::showLureDestination(const std::string fromname, const int global_x, const int global_y, const int x, const int y, const int z, const std::string maturity) { const LLVector3d posglobal = LLVector3d(F64(global_x), F64(global_y), F64(0)); diff --git a/indra/newview/llagent.h b/indra/newview/llagent.h index 8fafdd7b9..f697e4778 100644 --- a/indra/newview/llagent.h +++ b/indra/newview/llagent.h @@ -376,15 +376,6 @@ public: const LLColor4 &getEffectColor(); void setEffectColor(const LLColor4 &color); - // OGPX : Moving capabilities off region to agent service means they end up in LLAgent - // but, long term, this needs to be refactored into generalized Capabilities class - // since we want more flexibility in gathering up where services come from. - // Segmenting into region and agent domain caps might not make sense. Some implementations - // might want to provide caps that are not on the region or the agent domain. This is - // unsettled enough for now that we'll leave it as is. - void setCapability(const std::string& name, const std::string& url); - std::string getCapability(const std::string& name) const ; - // // UTILITIES // @@ -538,11 +529,6 @@ public: const LLVector3 &getTargetVelocity() const; const std::string getTeleportSourceSLURL() const { return mTeleportSourceSLURL; } - // OGPX : setTeleportSourceURL() is only used in agent domain case, - // so also made function name go from SLURL->URL for OGPX. - // This is what gets chatted into text chat when a teleport successfully completes. - void setTeleportSourceURL(const std::string agentdTeleportURL){ mTeleportSourceSLURL = agentdTeleportURL;}; - // Setting the ability for this avatar to proxy for another avatar. //static void processAddModifyAbility(LLMessageSystem* msg, void**); @@ -629,7 +615,6 @@ public: TELEPORT_START_ARRIVAL = 4, // Transition to ARRIVING. Viewer has received avatar update, etc., from destination simulator TELEPORT_ARRIVING = 5, // Make the user wait while content "pre-caches" TELEPORT_LOCAL = 6, // Teleporting in-sim without showing the progress screen - TELEPORT_PLACE_AVATAR = 7 // OGPX : Separate agent domain TP using place_avatar from legacy }; ETeleportState getTeleportState() const { return mTeleportState; } @@ -750,11 +735,12 @@ public: // whether look-at reset after teleport bool getTeleportKeepsLookAt() { return mbTeleportKeepsLookAt; } +protected: // stuff to do for any sort of teleport. Returns true if the // teleport can proceed. - bool teleportCore(bool is_local = false); //OGPX : now public method so agent domain TP can call + bool teleportCore(bool is_local = false); + -protected: // helper function to prematurely age chat when agent is moving void ageChat(); @@ -954,11 +940,6 @@ private: std::set mProxyForAgents; - - // - typedef std::map CapabilityMap; //OGPX TODO: refactor Caps to their own class - CapabilityMap mCapabilities; // for caps that we have on the agent domain. - LLColor4 mEffectColor; BOOL mHaveHomePosition; diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 62f8260e3..29ce3c494 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -44,6 +44,7 @@ #include "lltexteditor.h" #include "llalertdialog.h" #include "llerrorcontrol.h" +#include "lleventtimer.h" #include "llviewertexturelist.h" #include "llgroupmgr.h" #include "llagent.h" @@ -72,6 +73,7 @@ #include "llmutelist.h" #include "llurldispatcher.h" #include "llurlhistory.h" +#include "statemachine/aifilepicker.h" #include "llfirstuse.h" #include "llrender.h" #include "llfont.h" @@ -303,10 +305,6 @@ BOOL gCrashOnStartup = FALSE; BOOL gLLErrorActivated = FALSE; BOOL gLogoutInProgress = FALSE; -static std::string gPlaceAvatarCap; //OGPX TODO: should belong elsewhere, as part of the llagent caps? - - - //////////////////////////////////////////////////////////// // Internal globals... that should be removed. static std::string gArgs; @@ -436,7 +434,6 @@ static void settings_to_globals() LLFolderView::sAutoOpenTime = llmax(0.25f, gSavedSettings.getF32("FolderAutoOpenDelay")); LLToolBar::sInventoryAutoOpenTime = gSavedSettings.getF32("InventoryAutoOpenDelay"); LLSelectMgr::sRectSelectInclusive = gSavedSettings.getBOOL("RectangleSelectInclusive"); - LLSelectMgr::sRenderSelectionHighlights = gSavedSettings.getBOOL("RenderHighlightSelections"); LLSelectMgr::sRenderHiddenSelections = gSavedSettings.getBOOL("RenderHiddenSelections"); LLSelectMgr::sRenderLightRadius = gSavedSettings.getBOOL("RenderLightRadius"); @@ -587,6 +584,7 @@ bool LLAppViewer::init() LLCurl::initClass(); initThreads(); + LL_INFOS("InitInfo") << "Threads initialized." << LL_ENDL ; ; writeSystemInfo(); @@ -733,12 +731,14 @@ bool LLAppViewer::init() OSMB_OK); return 1; } + LL_INFOS("InitInfo") << "Cache initialization is done." << LL_ENDL ; // // Initialize the window // gGLActive = TRUE; initWindow(); + LL_INFOS("InitInfo") << "Window is initialized." << LL_ENDL ; // initWindow also initializes the Feature List, so now we can initialize this global. LLCubeMap::sUseCubeMaps = LLFeatureManager::getInstance()->isFeatureAvailable("RenderCubeMap"); @@ -781,6 +781,32 @@ bool LLAppViewer::init() return 0; } +#if (_M_IX86_FP > 1 || defined(__SSE2__)) + // Without SSE2 support we will crash almost immediately, warn here. + if (!gSysCPU.hasSSE2()) + { + // can't use an alert here since we're exiting and + // all hell breaks lose. + OSMessageBox( + LLNotifications::instance().getGlobalString("UnsupportedCPUSSE2"), + LLStringUtil::null, + OSMB_OK); + return 0; + } +#elif (_M_IX86_FP == 1 || defined(__SSE__)) + // Without SSE support we will crash almost immediately, warn here. + if (!gSysCPU.hasSSE()) + { + // can't use an alert here since we're exiting and + // all hell breaks lose. + OSMessageBox( + LLNotifications::instance().getGlobalString("UnsupportedCPUSSE"), + LLStringUtil::null, + OSMB_OK); + return 0; + } +#endif + // alert the user if they are using unsupported hardware if(!gSavedSettings.getBOOL("AlertedUnsupportedHardware")) { @@ -871,13 +897,33 @@ bool LLAppViewer::mainLoop() LLMemType mt1(LLMemType::MTYPE_MAIN); LLTimer frameTimer,idleTimer; LLTimer debugTime; + LLFrameTimer memCheckTimer; LLViewerJoystick* joystick(LLViewerJoystick::getInstance()); joystick->setNeedsReset(true); + + const F32 memory_check_interval = 1.0f ; //second + // Handle messages while (!LLApp::isExiting()) { LLFastTimer::reset(); // Should be outside of any timer instances + + //clear call stack records + llclearcallstacks; + + //check memory availability information + { + if(memory_check_interval < memCheckTimer.getElapsedTimeF32()) + { + memCheckTimer.reset() ; + + //update the availability of memory + LLMemoryInfo::getAvailableMemoryKB(mAvailPhysicalMemInKB, mAvailVirtualMemInKB) ; + } + llcallstacks << "Available physical mem(KB): " << mAvailPhysicalMemInKB << llcallstacksendl ; + llcallstacks << "Available virtual mem(KB): " << mAvailVirtualMemInKB << llcallstacksendl ; + } try { LLFastTimer t(LLFastTimer::FTM_FRAME); @@ -911,9 +957,11 @@ bool LLAppViewer::mainLoop() #endif //memory leaking simulation - if(LLFloaterMemLeak::getInstance()) + LLFloaterMemLeak* mem_leak_instance = + LLFloaterMemLeak::getInstance(); + if(mem_leak_instance) { - LLFloaterMemLeak::getInstance()->idle() ; + mem_leak_instance->idle() ; } if (!LLApp::isExiting()) @@ -1076,10 +1124,22 @@ bool LLAppViewer::mainLoop() } catch(std::bad_alloc) { - //stop memory leaking simulation - if(LLFloaterMemLeak::getInstance()) { - LLFloaterMemLeak::getInstance()->stop() ; + llinfos << "Availabe physical memory(KB) at the beginning of the frame: " << mAvailPhysicalMemInKB << llendl ; + llinfos << "Availabe virtual memory(KB) at the beginning of the frame: " << mAvailVirtualMemInKB << llendl ; + + LLMemoryInfo::getAvailableMemoryKB(mAvailPhysicalMemInKB, mAvailVirtualMemInKB) ; + + llinfos << "Current availabe physical memory(KB): " << mAvailPhysicalMemInKB << llendl ; + llinfos << "Current availabe virtual memory(KB): " << mAvailVirtualMemInKB << llendl ; + } + + //stop memory leaking simulation + LLFloaterMemLeak* mem_leak_instance = + LLFloaterMemLeak::getInstance(); + if(mem_leak_instance) + { + mem_leak_instance->stop() ; llwarns << "Bad memory allocation in LLAppViewer::mainLoop()!" << llendl ; } else @@ -1104,9 +1164,11 @@ bool LLAppViewer::mainLoop() llwarns << "Bad memory allocation when saveFinalSnapshot() is called!" << llendl ; //stop memory leaking simulation - if(LLFloaterMemLeak::getInstance()) + LLFloaterMemLeak* mem_leak_instance = + LLFloaterMemLeak::getInstance(); + if(mem_leak_instance) { - LLFloaterMemLeak::getInstance()->stop() ; + mem_leak_instance->stop() ; } } } @@ -1120,8 +1182,27 @@ bool LLAppViewer::mainLoop() return true; } +void LLAppViewer::flushVFSIO() +{ + while (1) + { + S32 pending = LLVFSThread::updateClass(0); + pending += LLLFSThread::updateClass(0); + if (!pending) + { + break; + } + llinfos << "Waiting for pending IO to finish: " << pending << llendflush; + ms_sleep(100); + } +} + +extern void cleanup_pose_stand(void); + bool LLAppViewer::cleanup() { + cleanup_pose_stand(); + //flag all elements as needing to be destroyed immediately // to ensure shutdown order LLMortician::setZealous(TRUE); @@ -1228,36 +1309,31 @@ bool LLAppViewer::cleanup() removeCacheFiles("*.dsf"); removeCacheFiles("*.bodypart"); removeCacheFiles("*.clothing"); + // + llinfos << "Cache files removed" << llendflush; */ // - llinfos << "Cache files removed" << llendflush; - cleanup_menus(); // Wait for any pending VFS IO - while (1) - { - S32 pending = LLVFSThread::updateClass(0); - pending += LLLFSThread::updateClass(0); - if (!pending) - { - break; - } - llinfos << "Waiting for pending IO to finish: " << pending << llendflush; - ms_sleep(100); - } - llinfos << "Shutting down." << llendflush; + flushVFSIO(); + llinfos << "Shutting down Views" << llendflush; // Destroy the UI if( gViewerWindow) gViewerWindow->shutdownViews(); + + llinfos << "Cleaning up Selections" << llendflush; + // Clean up selection managers after UI is destroyed, as UI may be observing them. // Clean up before GL is shut down because we might be holding on to objects with texture references LLSelectMgr::cleanupGlobals(); + + llinfos << "Shutting down OpenGL" << llendflush; // Shut down OpenGL if( gViewerWindow) @@ -1272,10 +1348,15 @@ bool LLAppViewer::cleanup() llinfos << "ViewerWindow deleted" << llendflush; } + llinfos << "Cleaning up Keyboard & Joystick" << llendflush; + // viewer UI relies on keyboard so keep it aound until viewer UI isa gone delete gKeyboard; gKeyboard = NULL; + + llinfos << "Cleaning up Objects" << llendflush; + LLViewerObject::cleanupVOClasses(); LLWaterParamManager::cleanupClass(); @@ -1304,6 +1385,8 @@ bool LLAppViewer::cleanup() } LLPrimitive::cleanupVolumeManager(); + llinfos << "Additional Cleanup..." << llendflush; + LLViewerParcelMgr::cleanupGlobals(); // *Note: this is where gViewerStats used to be deleted. @@ -1323,8 +1406,10 @@ bool LLAppViewer::cleanup() // Also after shutting down the messaging system since it has VFS dependencies // + llinfos << "Cleaning up VFS" << llendflush; LLVFile::cleanupClass(); - llinfos << "VFS cleaned up" << llendflush; + + llinfos << "Saving Data" << llendflush; // Quitting with "Remember Password" turned off should always stomp your // saved password, whether or not you successfully logged in. JC @@ -1340,10 +1425,17 @@ bool LLAppViewer::cleanup() // save their rects on delete. gSavedSettings.saveToFile(gSavedSettings.getString("ClientSettingsFile"), TRUE); - // PerAccountSettingsFile should be empty if no use has been logged on. + // PerAccountSettingsFile should be empty if no user has been logged on. // *FIX:Mani This should get really saved in a "logoff" mode. - gSavedPerAccountSettings.saveToFile(gSavedSettings.getString("PerAccountSettingsFile"), TRUE); - llinfos << "Saved settings" << llendflush; + if (gSavedSettings.getString("PerAccountSettingsFile").empty()) + { + llinfos << "Not saving per-account settings; don't know the account name yet." << llendl; + } + else + { + gSavedPerAccountSettings.saveToFile(gSavedSettings.getString("PerAccountSettingsFile"), TRUE); + llinfos << "Saved settings" << llendflush; + } std::string crash_settings_filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, CRASH_SETTINGS_FILE); // save all settings, even if equals defaults @@ -1352,6 +1444,9 @@ bool LLAppViewer::cleanup() // Save URL history file LLURLHistory::saveFile("url_history.xml"); + // Save file- and dirpicker {context, default paths} map. + AIFilePicker::saveFile("filepicker_contexts.xml"); + // save mute list. gMuteList used to also be deleted here too. LLMuteList::getInstance()->cache(gAgent.getID()); @@ -1373,6 +1468,11 @@ bool LLAppViewer::cleanup() removeCacheFiles("*.dsf"); removeCacheFiles("*.bodypart"); removeCacheFiles("*.clothing"); + llinfos << "Cache files removed" << llendflush; + } + else + { + llinfos << "Not removing cache files. Other viewer instance detected." << llendflush; } // @@ -1381,6 +1481,8 @@ bool LLAppViewer::cleanup() // Stop the plugin read thread if it's running. LLPluginProcessParent::setUseReadThread(false); + llinfos << "Shutting down Threads" << llendflush; + // Let threads finish LLTimer idleTimer; idleTimer.reset(); @@ -1418,6 +1520,9 @@ bool LLAppViewer::cleanup() delete sImageDecodeThread; sImageDecodeThread = NULL; + + llinfos << "Cleaning up Media and Textures" << llendflush; + //Note: //LLViewerMedia::cleanupClass() has to be put before gTextureList.shutdown() //because some new image might be generated during cleaning up media. --bao @@ -1480,7 +1585,10 @@ bool LLAppViewer::cleanup() llinfos << "File launched." << llendflush; } - llinfos << "Goodbye" << llendflush; + + ll_close_fail_log(); + + llinfos << "Goodbye!" << llendflush; // return 0; return true; @@ -1948,6 +2056,14 @@ bool LLAppViewer::initConfiguration() { gCrashOnStartup = TRUE; } + + if (clp.hasOption("debugsession")) + { + gDebugSession = TRUE; + gDebugGL = TRUE; + + ll_init_fail_log(gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "test_failures.log")); + } // Handle slurl use. NOTE: Don't let SL-55321 reappear. @@ -2353,7 +2469,12 @@ void LLAppViewer::writeSystemInfo() { gDebugInfo["SLLog"] = LLError::logFileName(); - + gDebugInfo["ClientInfo"]["Name"] = LL_CHANNEL; + + gDebugInfo["ClientInfo"]["MajorVersion"] = LL_VERSION_MAJOR; + gDebugInfo["ClientInfo"]["MinorVersion"] = LL_VERSION_MINOR; + gDebugInfo["ClientInfo"]["PatchVersion"] = LL_VERSION_PATCH; + gDebugInfo["ClientInfo"]["BuildVersion"] = LL_VERSION_BUILD; gDebugInfo["CAFilename"] = gDirUtilp->getCAFile(); @@ -2418,6 +2539,8 @@ void LLAppViewer::handleViewerCrash() { llinfos << "Handle viewer crash entry." << llendl; + llinfos << "Last render pool type: " << LLPipeline::sCurRenderPoolType << llendl ; + //print out recorded call stacks if there are any. LLError::LLCallStacks::print(); @@ -2863,45 +2986,54 @@ void LLAppViewer::migrateCacheDirectory() #endif // LL_WINDOWS || LL_DARWIN } +//static +U32 LLAppViewer::getTextureCacheVersion() +{ + //viewer texture cache version, change if the texture cache format changes. + static const U32 TEXTURE_CACHE_VERSION = 7; + + return TEXTURE_CACHE_VERSION ; +} bool LLAppViewer::initCache() { mPurgeCache = false; BOOL read_only = mSecondInstance ? TRUE : FALSE; LLAppViewer::getTextureCache()->setReadOnly(read_only); - BOOL texture_cache_mismatch = FALSE ; - static const S32 cache_version = 7; - if (gSavedSettings.getS32("LocalCacheVersion") != cache_version) + bool texture_cache_mismatch = false; + if (gSavedSettings.getS32("LocalCacheVersion") != LLAppViewer::getTextureCacheVersion()) { - texture_cache_mismatch = TRUE ; - if (!read_only) + texture_cache_mismatch = true; + if(!read_only) { - gSavedSettings.setS32("LocalCacheVersion", cache_version); + gSavedSettings.setS32("LocalCacheVersion", LLAppViewer::getTextureCacheVersion()); } } if (!read_only) { - // Purge cache if user requested it - if (gSavedSettings.getBOOL("PurgeCacheOnStartup") || - gSavedSettings.getBOOL("PurgeCacheOnNextStartup")) - { - gSavedSettings.setBOOL("PurgeCacheOnNextStartup", false); - mPurgeCache = true; - } + // Purge cache if user requested it + if (gSavedSettings.getBOOL("PurgeCacheOnStartup") || + gSavedSettings.getBOOL("PurgeCacheOnNextStartup")) + { + gSavedSettings.setBOOL("PurgeCacheOnNextStartup", false); + mPurgeCache = true; + // STORM-1141 force purgeAllTextures to get called to prevent a crash here. -brad + texture_cache_mismatch = true; + } - // We have moved the location of the cache directory over time. - migrateCacheDirectory(); + // We have moved the location of the cache directory over time. + migrateCacheDirectory(); - // Setup and verify the cache location - std::string cache_location = gSavedSettings.getString("CacheLocation"); - std::string new_cache_location = gSavedSettings.getString("NewCacheLocation"); - if (new_cache_location != cache_location) - { - gDirUtilp->setCacheDir(gSavedSettings.getString("CacheLocation")); - purgeCache(); // purge old cache - gSavedSettings.setString("CacheLocation", new_cache_location); - } + // Setup and verify the cache location + std::string cache_location = gSavedSettings.getString("CacheLocation"); + std::string new_cache_location = gSavedSettings.getString("NewCacheLocation"); + if (new_cache_location != cache_location) + { + gDirUtilp->setCacheDir(gSavedSettings.getString("CacheLocation")); + purgeCache(); // purge old cache + gSavedSettings.setString("CacheLocation", new_cache_location); + } } if (!gDirUtilp->setCacheDir(gSavedSettings.getString("CacheLocation"))) @@ -3096,18 +3228,6 @@ const std::string& LLAppViewer::getWindowTitle() const return gWindowTitle; } - // OGPX TODO: refactor caps code please, also "PlaceAvatar" is a bit dated, since - // we have since changed the name of the cap -void LLAppViewer::setPlaceAvatarCap(const std::string& uri) -{ - gPlaceAvatarCap = uri; -} - -const std::string& LLAppViewer::getPlaceAvatarCap() const -{ - return gPlaceAvatarCap; -} - // Callback from a dialog indicating user was logged out. bool finish_disconnect(const LLSD& notification, const LLSD& response) { @@ -3228,6 +3348,7 @@ void LLAppViewer::loadNameCache() // Phoenix: Wolfspirit: Loads the Display Name Cache. And set if we are using Display Names. std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "avatar_name_cache.xml"); + LL_INFOS("AvNameCache") << filename << LL_ENDL; llifstream name_cache_stream(filename); if(name_cache_stream.is_open()) { @@ -3757,39 +3878,6 @@ void LLAppViewer::idleShutdown() } } -// OGPX : Instead of sending UDP messages to the sim, tell the Agent Domain about logoff -//... This responder is used with rez_avatar/place when the specialized case -//... of sending a null region name is sent to the agent domain. Null region name means -//... log me off of agent domain. *But* what about cases where you want to be logged into -//... agent domain, but not physically on a region? -class LLLogoutResponder : - public LLHTTPClient::Responder -{ -public: - LLLogoutResponder() - { - } - - ~LLLogoutResponder() - { - } - - void error(U32 statusNum, const std::string& reason) - { - // consider retries - llinfos << "LLLogoutResponder error " - << statusNum << " " << reason << llendl; - } - - void result(const LLSD& content) - { - // perhaps logoutReply should come through this in the future - llinfos << "LLLogoutResponder completed successfully" << llendl; - - } - -}; - void LLAppViewer::idleNameCache() { // Neither old nor new name cache can function before agent has a region @@ -3912,7 +4000,6 @@ void LLAppViewer::idleNetwork() llpushcallstacks ; LLTimer check_message_timer; // Read all available packets from network - stop_glerror(); const S64 frame_count = gFrameCount; // U32->S64 F32 total_time = 0.0f; while (gMessageSystem->checkAllMessages(frame_count, gServicePump)) @@ -3924,7 +4011,6 @@ void LLAppViewer::idleNetwork() // server going down, so this is OK. break; } - stop_glerror(); total_decoded++; gPacketsIn++; @@ -3944,6 +4030,7 @@ void LLAppViewer::idleNetwork() break; #endif } + // Handle per-frame message system processing. gMessageSystem->processAcks(); @@ -3964,8 +4051,6 @@ void LLAppViewer::idleNetwork() // we want to clear the control after sending out all necessary agent updates gAgent.resetControlFlags(); - stop_glerror(); - // Decode enqueued messages... S32 remaining_possible_decodes = MESSAGE_MAX_PER_FRAME - total_decoded; @@ -4120,7 +4205,7 @@ void LLAppViewer::forceErrorBadMemoryAccess() return; } -void LLAppViewer::forceErrorInifiniteLoop() +void LLAppViewer::forceErrorInfiniteLoop() { while(true) { diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h index 933d4150a..d7f99c1bd 100644 --- a/indra/newview/llappviewer.h +++ b/indra/newview/llappviewer.h @@ -64,6 +64,7 @@ public: virtual bool mainLoop(); // Override for the application main loop. Needs to at least gracefully notice the QUITTING state and exit. // Application control + void flushVFSIO(); // waits for vfs transfers to complete void forceQuit(); // Puts the viewer into 'shutting down without error' mode. void requestQuit(); // Request a quit. A kinder, gentler quit. void userQuit(); // The users asks to quit. Confirm, then requestQuit() @@ -95,6 +96,7 @@ public: static LLImageDecodeThread* getImageDecodeThread() { return sImageDecodeThread; } static LLTextureFetch* getTextureFetch() { return sTextureFetch; } + static U32 getTextureCacheVersion(); const std::string& getSerialNumber() { return mSerialNumber; } bool getPurgeCache() const { return mPurgeCache; } @@ -111,13 +113,6 @@ public: void loadNameCache(); void saveNameCache(); - // OGPX : rez_avatar/place cap is used on both initial login, and - // ... then on teleports as well. The same cap should be good for the - // ... life of the connection to an agent domain. This cap is used by the viewer - // ... to request moving an agent between regions. - void setPlaceAvatarCap(const std::string& uri); // OGPX TODO: this should be refactored into own class that handles caps - const std::string& getPlaceAvatarCap() const; // OGPX TODO: ...as above... - void removeMarkerFile(bool leave_logout_marker = false); // LLAppViewer testing helpers. @@ -125,7 +120,7 @@ public: virtual void forceErrorLLError(); virtual void forceErrorBreakpoint(); virtual void forceErrorBadMemoryAccess(); - virtual void forceErrorInifiniteLoop(); + virtual void forceErrorInfiniteLoop(); virtual void forceErrorSoftwareException(); virtual void forceErrorDriverCrash(); @@ -197,8 +192,9 @@ private: void idle(); void idleShutdown(); + // update avatar SLID and display name caches + void idleNameCache(); void idleNetwork(); - void idleNameCache(); void sendLogoutRequest(); void disconnectViewer(); @@ -243,6 +239,10 @@ private: bool mAgentRegionLastAlive; LLUUID mAgentRegionLastID; + + U32 mAvailPhysicalMemInKB ; + U32 mAvailVirtualMemInKB ; + public: //some information for updater typedef struct diff --git a/indra/newview/llappviewerlinux.cpp b/indra/newview/llappviewerlinux.cpp index a19ad5658..4e4bbcb43 100644 --- a/indra/newview/llappviewerlinux.cpp +++ b/indra/newview/llappviewerlinux.cpp @@ -98,6 +98,9 @@ static void exceptionTerminateHandler() int main( int argc, char **argv ) { + Debug(debug::init()); + Debug(libcw_do.on()); + LLMemType mt1(LLMemType::MTYPE_STARTUP); #if LL_SOLARIS && defined(__sparc) diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp index 051a5cdaa..b5a185a0c 100644 --- a/indra/newview/llappviewerwin32.cpp +++ b/indra/newview/llappviewerwin32.cpp @@ -244,6 +244,8 @@ int APIENTRY WINMAIN(HINSTANCE hInstance, } #endif + gGLActive = TRUE; + viewer_app_ptr->cleanup(); #if WINDOWS_CRT_MEM_CHECKS @@ -498,7 +500,11 @@ bool LLAppViewerWin32::initHardwareTest() LL_WARNS("AppInit") << " Someone took over my exception handler (post hardware probe)!" << LL_ENDL; } - gGLManager.mVRAM = gDXHardware.getVRAM(); + if (gGLManager.mVRAM == 0) + { + gGLManager.mVRAM = gDXHardware.getVRAM(); + } + LL_INFOS("AppInit") << "Detected VRAM: " << gGLManager.mVRAM << LL_ENDL; return true; diff --git a/indra/newview/llassetuploadresponders.cpp b/indra/newview/llassetuploadresponders.cpp index 042a53632..d910ab4b2 100644 --- a/indra/newview/llassetuploadresponders.cpp +++ b/indra/newview/llassetuploadresponders.cpp @@ -38,7 +38,6 @@ #include "llagent.h" #include "llcompilequeue.h" #include "llfloaterbuycurrency.h" -#include "llfilepicker.h" #include "llnotify.h" #include "llinventorymodel.h" #include "llinventoryview.h" @@ -129,7 +128,7 @@ void LLAssetUploadResponder::error(U32 statusNum, const std::string& reason) break; } LLUploadDialog::modalUploadFinished(); - LLFilePicker::instance().reset(); // unlock file picker when bulk upload fails + //AIFIXME? LLFilePicker::instance().reset(); // unlock file picker when bulk upload fails } //virtual @@ -293,7 +292,7 @@ void LLNewAgentInventoryResponder::uploadComplete(const LLSD& content) view->getPanel()->setSelection(content["new_inventory_item"].asUUID(), TAKE_FOCUS_NO); if((LLAssetType::AT_TEXTURE == asset_type || LLAssetType::AT_SOUND == asset_type) - && LLFilePicker::instance().getFileCount() <= FILE_COUNT_DISPLAY_THRESHOLD) + /* AIFIXME: && LLFilePicker::instance().getFileCount() <= FILE_COUNT_DISPLAY_THRESHOLD */) { view->getPanel()->openSelected(); } @@ -309,7 +308,8 @@ void LLNewAgentInventoryResponder::uploadComplete(const LLSD& content) // remove the "Uploading..." message LLUploadDialog::modalUploadFinished(); - + +#if 0 // AIFIXME: This needs to be done in some other way. // *FIX: This is a pretty big hack. What this does is check the // file picker if there are any more pending uploads. If so, // upload that file. @@ -339,6 +339,7 @@ void LLNewAgentInventoryResponder::uploadComplete(const LLSD& content) everyone_perms, display_name, callback, expected_upload_cost, userdata); } +#endif } LLSendTexLayerResponder::LLSendTexLayerResponder(const LLSD& post_data, diff --git a/indra/newview/llbuildnewviewsscheduler.h b/indra/newview/llbuildnewviewsscheduler.h index a3d5af66c..2f819288f 100644 --- a/indra/newview/llbuildnewviewsscheduler.h +++ b/indra/newview/llbuildnewviewsscheduler.h @@ -1,6 +1,7 @@ // #include "llinventoryview.h" #include "llinventory.h" +#include "lleventtimer.h" class LLBuildNewViewsScheduler : public LLEventTimer { typedef struct diff --git a/indra/newview/llcallbacklist.cpp b/indra/newview/llcallbacklist.cpp index bba4d021c..6063995cf 100644 --- a/indra/newview/llcallbacklist.cpp +++ b/indra/newview/llcallbacklist.cpp @@ -47,7 +47,7 @@ LLCallbackList gIdleCallbacks; // Member functions // -LLCallbackList::LLCallbackList() +LLCallbackList::LLCallbackList() : mLoopingOverCallbackList(false) { // nothing } @@ -96,7 +96,15 @@ BOOL LLCallbackList::deleteFunction( callback_t func, void *data) callback_list_t::iterator iter = std::find(mCallbackList.begin(), mCallbackList.end(), t); if (iter != mCallbackList.end()) { - mCallbackList.erase(iter); + if (mLoopingOverCallbackList) + { + iter->first = NULL; // Mark for removal later (when we return to LLCallbackList::callFunctions). + mNeedErase = true; + } + else + { + mCallbackList.erase(iter); + } return TRUE; } else @@ -108,16 +116,38 @@ BOOL LLCallbackList::deleteFunction( callback_t func, void *data) void LLCallbackList::deleteAllFunctions() { + llassert(!mLoopingOverCallbackList); // Only called from unit tests. mCallbackList.clear(); } void LLCallbackList::callFunctions() { - for (callback_list_t::iterator iter = mCallbackList.begin(); iter != mCallbackList.end(); ) + llassert(!mLoopingOverCallbackList); + mLoopingOverCallbackList = true; + mNeedErase = false; + for (callback_list_t::iterator iter = mCallbackList.begin(); iter != mCallbackList.end(); ++iter) { - callback_list_t::iterator curiter = iter++; - curiter->first(curiter->second); + if (iter->first) // Not pending removal? + { + iter->first(iter->second); // This can theorectically set any iter->first to NULL, which means the entry should be erased. + } + } + mLoopingOverCallbackList = false; + if (mNeedErase) + { + callback_list_t::iterator iter = mCallbackList.begin(); + while (iter != mCallbackList.end()) + { + if (!iter->first) + { + iter = mCallbackList.erase(iter); + } + else + { + ++iter; + } + } } } diff --git a/indra/newview/llcallbacklist.h b/indra/newview/llcallbacklist.h index be0fe9f5c..240346478 100644 --- a/indra/newview/llcallbacklist.h +++ b/indra/newview/llcallbacklist.h @@ -53,9 +53,11 @@ public: protected: // Use a list so that the callbacks are ordered in case that matters - typedef std::pair callback_pair_t; + typedef std::pair callback_pair_t; // callback_t is a (function) pointer. If it is NULL it means that the entry should be considered deleted. typedef std::list callback_list_t; callback_list_t mCallbackList; + bool mLoopingOverCallbackList; // True while looping over mCallbackList and calling the callback_t functions (see callFunctions). + bool mNeedErase; // True when deleteFunction was called while mLoopingOverCallbackList was true. }; extern LLCallbackList gIdleCallbacks; diff --git a/indra/newview/lldrawable.cpp b/indra/newview/lldrawable.cpp index e8d6daca4..64464f132 100644 --- a/indra/newview/lldrawable.cpp +++ b/indra/newview/lldrawable.cpp @@ -118,6 +118,10 @@ void LLDrawable::initClass() void LLDrawable::destroy() { + if (gDebugGL) + { + gPipeline.checkReferences(this); + } if (isDead()) { sNumZombieDrawables--; @@ -688,13 +692,15 @@ void LLDrawable::updateDistance(LLCamera& camera, bool force_update) LLVOVolume* volume = getVOVolume(); if (volume) { - volume->updateRelativeXform(); - pos = volume->getRelativeXform().getTranslation(); - if (isStatic()) + if (getSpatialGroup()) { - pos += volume->getRegion()->getOriginAgent(); + pos.set(getPositionGroup()); } - + else + { + pos = getPositionAgent(); + } + if (isState(LLDrawable::HAS_ALPHA)) { for (S32 i = 0; i < getNumFaces(); i++) @@ -803,8 +809,7 @@ void LLDrawable::shiftPos(const LLVector3 &shift_vector) if (!volume && facep->hasGeometry()) { - facep->mVertexBuffer = NULL; - facep->mLastVertexBuffer = NULL; + facep->clearVertexBuffer(); } } @@ -913,6 +918,18 @@ void LLDrawable::setSpatialGroup(LLSpatialGroup *groupp) { mSpatialGroupp->setState(LLSpatialGroup::GEOM_DIRTY); }*/ + + if (mSpatialGroupp != groupp && getVOVolume()) + { //NULL out vertex buffer references for volumes on spatial group change to maintain + //requirement that every face vertex buffer is either NULL or points to a vertex buffer + //contained by its drawable's spatial group + for (S32 i = 0; i < getNumFaces(); ++i) + { + LLFace* facep = getFace(i); + facep->clearVertexBuffer(); + } + } + mSpatialGroupp = groupp; } @@ -1030,7 +1047,7 @@ BOOL LLDrawable::isVisible() const //======================================= LLSpatialBridge::LLSpatialBridge(LLDrawable* root, BOOL render_by_group, U32 data_mask) -: LLSpatialPartition(data_mask, render_by_group, FALSE) +: LLSpatialPartition(data_mask, render_by_group, GL_STREAM_DRAW_ARB) { mDrawable = root; root->setSpatialBridge(this); diff --git a/indra/newview/lldrawable.h b/indra/newview/lldrawable.h index 7202f3476..32049da0d 100644 --- a/indra/newview/lldrawable.h +++ b/indra/newview/lldrawable.h @@ -68,6 +68,17 @@ const U32 SILHOUETTE_HIGHLIGHT = 0; class LLDrawable : public LLRefCount { public: + LLDrawable(const LLDrawable& rhs) + { + *this = rhs; + } + + const LLDrawable& operator=(const LLDrawable& rhs) + { + llerrs << "Illegal operation!" << llendl; + return *this; + } + static void initClass(); LLDrawable() { init(); } @@ -103,7 +114,7 @@ public: const LLQuaternion& getRotation() const { return mXform.getRotation(); } F32 getIntensity() const { return llmin(mXform.getScale().mV[0], 4.f); } S32 getLOD() const { return mVObjp ? mVObjp->getLOD() : 1; } - F64 getBinRadius() const { return mBinRadius; } + F32 getBinRadius() const { return mBinRadius; } void getMinMax(LLVector3& min,LLVector3& max) const { mXform.getMinMax(min,max); } LLXformMatrix* getXform() { return &mXform; } @@ -301,9 +312,9 @@ private: F32 mRadius; LLVector3 mExtents[2]; LLVector3d mPositionGroup; - F64 mBinRadius; + F32 mBinRadius; S32 mGeneration; - + LLVector3 mCurrentScale; static U32 sCurVisible; // Counter for what value of mVisible means currently visible diff --git a/indra/newview/lldrawpool.cpp b/indra/newview/lldrawpool.cpp index 0d41ab85f..474538a17 100644 --- a/indra/newview/lldrawpool.cpp +++ b/indra/newview/lldrawpool.cpp @@ -296,13 +296,6 @@ void LLFacePool::drawLoop() } } -void LLFacePool::renderFaceSelected(LLFace *facep, - LLViewerTexture *image, - const LLColor4 &color, - const S32 index_offset, const S32 index_count) -{ -} - void LLFacePool::enqueue(LLFace* facep) { mDrawFace.push_back(facep); diff --git a/indra/newview/lldrawpool.h b/indra/newview/lldrawpool.h index f92756ae3..440a2a845 100644 --- a/indra/newview/lldrawpool.h +++ b/indra/newview/lldrawpool.h @@ -169,10 +169,10 @@ public: LLFacePool(const U32 type); virtual ~LLFacePool(); - virtual void renderForSelect() = 0; + virtual void renderForSelect() {}; //Override if neded. BOOL isDead() { return mReferences.empty(); } virtual void renderFaceSelected(LLFace *facep, LLViewerTexture *image, const LLColor4 &color, - const S32 index_offset = 0, const S32 index_count = 0); + const S32 index_offset = 0, const S32 index_count = 0) {}; //Override if neded. virtual LLViewerTexture *getTexture(); virtual void dirtyTextures(const std::set& textures); diff --git a/indra/newview/lldrawpoolalpha.cpp b/indra/newview/lldrawpoolalpha.cpp index 08c430e62..d6ea59ff7 100644 --- a/indra/newview/lldrawpoolalpha.cpp +++ b/indra/newview/lldrawpoolalpha.cpp @@ -198,7 +198,10 @@ void LLDrawPoolAlpha::render(S32 pass) simple_shader->bind(); pushBatches(LLRenderPass::PASS_ALPHA_MASK, getVertexDataMask()); } - fullbright_shader->bind(); + if (fullbright_shader) + { + fullbright_shader->bind(); + } pushBatches(LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK, getVertexDataMask()); LLGLSLShader::bindNoShader(); } @@ -238,7 +241,7 @@ void LLDrawPoolAlpha::render(S32 pass) gPipeline.enableLightsFullbright(LLColor4(1,1,1,1)); glColor4f(1,0,0,1); LLViewerFetchedTexture::sSmokeImagep->addTextureStats(1024.f*1024.f); - gGL.getTexUnit(0)->bind(LLViewerFetchedTexture::sSmokeImagep.get(), TRUE); + gGL.getTexUnit(0)->bind(LLViewerFetchedTexture::sSmokeImagep, TRUE) ; renderAlphaHighlight(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0); } @@ -280,6 +283,8 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask) { BOOL initialized_lighting = FALSE; BOOL light_enabled = TRUE; + S32 diffuse_channel = 0; + //BOOL is_particle = FALSE; BOOL use_shaders = (LLPipeline::sUnderWaterRender && gPipeline.canUseVertexShaders()) || gPipeline.canUseWindLightShadersOnObjects(); @@ -360,11 +365,13 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask) if (deferred_render && current_shader != NULL) { gPipeline.unbindDeferredShader(*current_shader); + diffuse_channel = 0; } current_shader = target_shader; if (deferred_render) { gPipeline.bindDeferredShader(*current_shader); + diffuse_channel = current_shader->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); } else { @@ -373,10 +380,10 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask) } else if (!use_shaders && current_shader != NULL) { - if (deferred_render) { gPipeline.unbindDeferredShader(*current_shader); + diffuse_channel = 0; } LLGLSLShader::bindNoShader(); current_shader = NULL; @@ -390,7 +397,7 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask) if (params.mTexture.notNull()) { - gGL.getTexUnit(0)->bind(params.mTexture.get()); + gGL.getTexUnit(diffuse_channel)->bind(params.mTexture.get()); if(params.mTexture.notNull()) { params.mTexture->addTextureStats(params.mVSize); diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp index a6e43e5b5..92d257734 100644 --- a/indra/newview/lldrawpoolavatar.cpp +++ b/indra/newview/lldrawpoolavatar.cpp @@ -94,6 +94,7 @@ BOOL gAvatarEmbossBumpMap = FALSE; static BOOL sRenderingSkinned = FALSE; S32 normal_channel = -1; S32 specular_channel = -1; +S32 diffuse_channel = -1; LLDrawPoolAvatar::LLDrawPoolAvatar() : LLFacePool(POOL_AVATAR) @@ -400,6 +401,7 @@ void LLDrawPoolAvatar::beginImpostor() } gPipeline.enableLightsFullbright(LLColor4(1,1,1,1)); + diffuse_channel = 0; } void LLDrawPoolAvatar::endImpostor() @@ -452,6 +454,7 @@ void LLDrawPoolAvatar::beginDeferredImpostor() normal_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::DEFERRED_NORMAL); specular_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::SPECULAR_MAP); + diffuse_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); sVertexProgram->bind(); } @@ -461,6 +464,7 @@ void LLDrawPoolAvatar::endDeferredImpostor() sShaderLevel = mVertexShaderLevel; sVertexProgram->disableTexture(LLViewerShaderMgr::DEFERRED_NORMAL); sVertexProgram->disableTexture(LLViewerShaderMgr::SPECULAR_MAP); + sVertexProgram->disableTexture(LLViewerShaderMgr::DIFFUSE_MAP); sVertexProgram->unbind(); gGL.getTexUnit(0)->activate(); } @@ -659,8 +663,10 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass) gGL.translatef((F32)(pos.mV[VX]), (F32)(pos.mV[VY]), (F32)(pos.mV[VZ])); - gGL.scalef(0.15f, 0.15f, 0.3f); - gSphere.render(); + gGL.scalef(0.15f, 0.15f, 0.3f); + + gSphere.renderGGL(); + gGL.popMatrix(); gGL.setColorMask(true, false); } @@ -702,7 +708,7 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass) avatarp->mImpostor.bindTexture(1, specular_channel); } } - avatarp->renderImpostor(); + avatarp->renderImpostor(LLColor4U(255,255,255,255), diffuse_channel); } else if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_FOOT_SHADOWS) && !LLPipeline::sRenderDeferred) { diff --git a/indra/newview/lldrawpoolavatar.h b/indra/newview/lldrawpoolavatar.h index fc5f9dbff..d24726052 100644 --- a/indra/newview/lldrawpoolavatar.h +++ b/indra/newview/lldrawpoolavatar.h @@ -39,8 +39,6 @@ class LLVOAvatar; class LLDrawPoolAvatar : public LLFacePool { -protected: - S32 mNumFaces; public: enum { diff --git a/indra/newview/lldrawpoolbump.cpp b/indra/newview/lldrawpoolbump.cpp index 6ca90c2be..38837a8cc 100644 --- a/indra/newview/lldrawpoolbump.cpp +++ b/indra/newview/lldrawpoolbump.cpp @@ -152,12 +152,7 @@ void LLStandardBumpmap::addstandard() // llinfos << "Loading bumpmap: " << bump_file << " from viewerart" << llendl; gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount].mLabel = label; gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount].mImage = - LLViewerTextureManager::getFetchedTexture(LLUUID(bump_image_id), - TRUE, - LLViewerTexture::BOOST_NONE, - LLViewerTexture::LOD_TEXTURE, - 0, - 0); + LLViewerTextureManager::getFetchedTexture(LLUUID(bump_image_id)); gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount].mImage->setBoostLevel(LLViewerTexture::BOOST_BUMP) ; gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount].mImage->setLoadedCallback(LLBumpImageList::onSourceStandardLoaded, 0, TRUE, FALSE, NULL, NULL ); LLStandardBumpmap::sStandardBumpmapCount++; @@ -342,30 +337,43 @@ void LLDrawPoolBump::beginShiny(bool invisible) sVertexMask = VERTEX_MASK_SHINY | LLVertexBuffer::MAP_TEXCOORD0; } - if (LLPipeline::sUnderWaterRender) + if (getVertexShaderLevel() > 0) { - shader = &gObjectShinyWaterProgram; + if (LLPipeline::sUnderWaterRender) + { + shader = &gObjectShinyWaterProgram; + } + else + { + shader = &gObjectShinyProgram; + } + shader->bind(); } else { - shader = &gObjectShinyProgram; + shader = NULL; } + bindCubeMap(shader, mVertexShaderLevel, diffuse_channel, cube_channel, invisible); +} + +//static +void LLDrawPoolBump::bindCubeMap(LLGLSLShader* shader, S32 shader_level, S32& diffuse_channel, S32& cube_channel, bool invisible) +{ LLCubeMap* cube_map = gSky.mVOSkyp ? gSky.mVOSkyp->getCubeMap() : NULL; if( cube_map ) { - if (!invisible && LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_OBJECT) > 0 ) + if (!invisible && shader ) { LLMatrix4 mat; mat.initRows(LLVector4(gGLModelView+0), LLVector4(gGLModelView+4), LLVector4(gGLModelView+8), LLVector4(gGLModelView+12)); - shader->bind(); LLVector3 vec = LLVector3(gShinyOrigin) * mat; LLVector4 vec4(vec, gShinyOrigin.mV[3]); shader->uniform4fv(LLViewerShaderMgr::SHINY_ORIGIN, 1, vec4.mV); - if (mVertexShaderLevel > 1) + if (shader_level > 1) { cube_map->setMatrix(1); // Make sure that texture coord generation happens for tex unit 1, as that's the one we use for @@ -427,22 +435,16 @@ void LLDrawPoolBump::renderShiny(bool invisible) } } -void LLDrawPoolBump::endShiny(bool invisible) +//static +void LLDrawPoolBump::unbindCubeMap(LLGLSLShader* shader, S32 shader_level, S32& diffuse_channel, S32& cube_channel, bool invisible) { - LLFastTimer t(LLFastTimer::FTM_RENDER_SHINY); - if ((!invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_SHINY))|| - (invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_INVISI_SHINY))) - { - return; - } - LLCubeMap* cube_map = gSky.mVOSkyp ? gSky.mVOSkyp->getCubeMap() : NULL; if( cube_map ) { cube_map->disable(); cube_map->restoreMatrix(); - if (!invisible && mVertexShaderLevel > 1) + if (!invisible && shader_level > 1) { shader->disableTexture(LLViewerShaderMgr::ENVIRONMENT_MAP, LLTexUnit::TT_CUBE_MAP); @@ -453,7 +455,6 @@ void LLDrawPoolBump::endShiny(bool invisible) shader->disableTexture(LLViewerShaderMgr::DIFFUSE_MAP); } } - shader->unbind(); } } gGL.getTexUnit(diffuse_channel)->disable(); @@ -461,6 +462,22 @@ void LLDrawPoolBump::endShiny(bool invisible) gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); +} + +void LLDrawPoolBump::endShiny(bool invisible) +{ + LLFastTimer t(LLFastTimer::FTM_RENDER_SHINY); + if ((!invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_SHINY))|| + (invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_INVISI_SHINY))) + { + return; + } + + unbindCubeMap(shader, mVertexShaderLevel, diffuse_channel, cube_channel, invisible); + if (shader) + { + shader->unbind(); + } diffuse_channel = -1; cube_channel = 0; @@ -481,7 +498,7 @@ void LLDrawPoolBump::beginFullbrightShiny() if (LLPipeline::sUnderWaterRender) { - shader = &gObjectShinyWaterProgram; + shader = &gObjectFullbrightShinyWaterProgram; } else { @@ -588,18 +605,37 @@ void LLDrawPoolBump::renderGroup(LLSpatialGroup* group, U32 type, U32 mask, BOOL // static BOOL LLDrawPoolBump::bindBumpMap(LLDrawInfo& params, S32 channel) { - LLViewerTexture* bump = NULL; - U8 bump_code = params.mBump; + return bindBumpMap(bump_code, params.mTexture, params.mVSize, channel); +} + +//static +BOOL LLDrawPoolBump::bindBumpMap(LLFace* face, S32 channel) +{ + const LLTextureEntry* te = face->getTextureEntry(); + if (te) + { + U8 bump_code = te->getBumpmap(); + return bindBumpMap(bump_code, face->getTexture(), face->getVirtualSize(), channel); + } + + return FALSE; +} + +//static +BOOL LLDrawPoolBump::bindBumpMap(U8 bump_code, LLViewerTexture* texture, F32 vsize, S32 channel) +{ //Note: texture atlas does not support bump texture now. - LLViewerFetchedTexture* tex = LLViewerTextureManager::staticCastToFetchedTexture(params.mTexture) ; + LLViewerFetchedTexture* tex = LLViewerTextureManager::staticCastToFetchedTexture(texture) ; if(!tex) { //if the texture is not a fetched texture return FALSE; } + LLViewerTexture* bump = NULL; + switch( bump_code ) { case BE_NO_BUMP: @@ -613,7 +649,7 @@ BOOL LLDrawPoolBump::bindBumpMap(LLDrawInfo& params, S32 channel) if( bump_code < LLStandardBumpmap::sStandardBumpmapCount ) { bump = gStandardBumpmapList[bump_code].mImage; - gBumpImageList.addTextureStats(bump_code, tex->getID(), params.mVSize); + gBumpImageList.addTextureStats(bump_code, tex->getID(), vsize); } break; } @@ -968,25 +1004,28 @@ LLViewerTexture* LLBumpImageList::getBrightnessDarknessImage(LLViewerFetchedText } bump_image_map_t::iterator iter = entries_list->find(src_image->getID()); - if (iter != entries_list->end()) + if (iter != entries_list->end() && iter->second.notNull()) { bump = iter->second; } else { LLPointer raw = new LLImageRaw(1,1,1); - raw->clear(0x77, 0x77, 0x77, 0xFF); + raw->clear(0x77, 0x77, 0xFF, 0xFF); (*entries_list)[src_image->getID()] = LLViewerTextureManager::getLocalTexture( raw.get(), TRUE); - (*entries_list)[src_image->getID()]->setExplicitFormat(GL_ALPHA8, GL_ALPHA); - - // Note: this may create an LLImageGL immediately - src_image->setBoostLevel(LLViewerTexture::BOOST_BUMP) ; - src_image->setLoadedCallback( callback_func, 0, TRUE, FALSE, new LLUUID(src_image->getID()), NULL ); bump = (*entries_list)[src_image->getID()]; // In case callback was called immediately and replaced the image + } -// bump_total++; -// llinfos << "*** Creating " << (void*)bump << " " << bump_total << llendl; + if (!src_image->hasCallbacks()) + { //if image has no callbacks but resolutions don't match, trigger raw image loaded callback again + if (src_image->getWidth() != bump->getWidth() || + src_image->getHeight() != bump->getHeight() || + (LLPipeline::sRenderDeferred && bump->getComponents() != 4)) + { + src_image->setBoostLevel(LLViewerTexture::BOOST_BUMP) ; + src_image->setLoadedCallback( callback_func, 0, TRUE, FALSE, new LLUUID(src_image->getID()), NULL ); + } } } @@ -1089,7 +1128,21 @@ void LLBumpImageList::onSourceLoaded( BOOL success, LLViewerTexture *src_vi, LLI { bump_image_map_t& entries_list(bump_code == BE_BRIGHTNESS ? gBumpImageList.mBrightnessEntries : gBumpImageList.mDarknessEntries ); bump_image_map_t::iterator iter = entries_list.find(source_asset_id); - if (iter != entries_list.end()) + + if (iter == entries_list.end() || + iter->second.isNull() || + iter->second->getWidth() != src->getWidth() || + iter->second->getHeight() != src->getHeight()) // bump not cached yet or has changed resolution + { //make sure an entry exists for this image + LLPointer raw = new LLImageRaw(1,1,1); + raw->clear(0x77, 0x77, 0xFF, 0xFF); + + entries_list[src_vi->getID()] = LLViewerTextureManager::getLocalTexture( raw.get(), TRUE); + iter = entries_list.find(src_vi->getID()); + } + + //if (iter->second->getWidth() != src->getWidth() || + // iter->second->getHeight() != src->getHeight()) // bump not cached yet or has changed resolution { LLPointer dst_image = new LLImageRaw(src->getWidth(), src->getHeight(), 1); U8* dst_data = dst_image->getData(); @@ -1216,18 +1269,10 @@ void LLBumpImageList::onSourceLoaded( BOOL success, LLViewerTexture *src_vi, LLI bump->setExplicitFormat(GL_RGBA, GL_RGBA); bump->createGLTexture(0, nrm_image); } - - + iter->second = bump; // derefs (and deletes) old image //--------------------------------------------------- } - else - { - // entry should have been added in LLBumpImageList::getImage(). - - // Not a legit assertion - the bump texture could have been flushed by the bump image manager - //llassert(0); - } } } diff --git a/indra/newview/lldrawpoolbump.h b/indra/newview/lldrawpoolbump.h index f67ba7d3d..9c6569665 100644 --- a/indra/newview/lldrawpoolbump.h +++ b/indra/newview/lldrawpoolbump.h @@ -41,6 +41,7 @@ class LLImageRaw; class LLSpatialGroup; class LLDrawInfo; +class LLGLSLShader; class LLViewerFetchedTexture; class LLDrawPoolBump : public LLRenderPass @@ -79,6 +80,9 @@ public: void renderBump(U32 pass = LLRenderPass::PASS_BUMP); void endBump(U32 pass = LLRenderPass::PASS_BUMP); + static void bindCubeMap(LLGLSLShader* shader, S32 shader_level, S32& diffuse_channel, S32& cube_channel, bool invisible); + static void unbindCubeMap(LLGLSLShader* shader, S32 shader_level, S32& diffuse_channel, S32& cube_channel, bool invisible); + virtual S32 getNumDeferredPasses(); /*virtual*/ void beginDeferredPass(S32 pass); /*virtual*/ void endDeferredPass(S32 pass); @@ -89,7 +93,12 @@ public: /*virtual*/ void endPostDeferredPass(S32 pass); /*virtual*/ void renderPostDeferred(S32 pass); - BOOL bindBumpMap(LLDrawInfo& params, S32 channel = -2); + static BOOL bindBumpMap(LLDrawInfo& params, S32 channel = -2); + static BOOL bindBumpMap(LLFace* face, S32 channel = -2); + +private: + static BOOL bindBumpMap(U8 bump_code, LLViewerTexture* tex, F32 vsize, S32 channel); + }; enum EBumpEffect diff --git a/indra/newview/lldrawpoolclouds.cpp b/indra/newview/lldrawpoolclouds.cpp index 1d159998a..8844c3c71 100644 --- a/indra/newview/lldrawpoolclouds.cpp +++ b/indra/newview/lldrawpoolclouds.cpp @@ -101,6 +101,3 @@ void LLDrawPoolClouds::render(S32 pass) } -void LLDrawPoolClouds::renderForSelect() -{ -} diff --git a/indra/newview/lldrawpoolclouds.h b/indra/newview/lldrawpoolclouds.h index c70dd41f7..7c95b3ec0 100644 --- a/indra/newview/lldrawpoolclouds.h +++ b/indra/newview/lldrawpoolclouds.h @@ -55,7 +55,6 @@ public: /*virtual*/ void enqueue(LLFace *face); /*virtual*/ void beginRenderPass(S32 pass); /*virtual*/ void render(S32 pass = 0); - /*virtual*/ void renderForSelect(); }; #endif // LL_LLDRAWPOOLSKY_H diff --git a/indra/newview/lldrawpoolground.cpp b/indra/newview/lldrawpoolground.cpp index c65524b7c..9d63113d5 100644 --- a/indra/newview/lldrawpoolground.cpp +++ b/indra/newview/lldrawpoolground.cpp @@ -91,7 +91,3 @@ void LLDrawPoolGround::render(S32 pass) glPopMatrix(); } -void LLDrawPoolGround::renderForSelect() -{ -} - diff --git a/indra/newview/lldrawpoolground.h b/indra/newview/lldrawpoolground.h index 6c7d20bec..9ac96ca59 100644 --- a/indra/newview/lldrawpoolground.h +++ b/indra/newview/lldrawpoolground.h @@ -53,7 +53,6 @@ public: /*virtual*/ void prerender(); /*virtual*/ void render(S32 pass = 0); - /*virtual*/ void renderForSelect(); }; #endif // LL_LLDRAWPOOLGROUND_H diff --git a/indra/newview/lldrawpoolsky.cpp b/indra/newview/lldrawpoolsky.cpp index 98c729dfe..b5cc0d31d 100644 --- a/indra/newview/lldrawpoolsky.cpp +++ b/indra/newview/lldrawpoolsky.cpp @@ -43,7 +43,6 @@ #include "llviewercamera.h" #include "llviewertexturelist.h" #include "llviewerregion.h" -#include "llviewerwindow.h" #include "llvosky.h" #include "llworld.h" // To get water height #include "pipeline.h" @@ -70,6 +69,7 @@ void LLDrawPoolSky::prerender() void LLDrawPoolSky::render(S32 pass) { + gGL.flush(); if (mDrawFace.empty()) { return; @@ -118,13 +118,14 @@ void LLDrawPoolSky::render(S32 pass) S32 face_count = (S32)mDrawFace.size(); + LLVertexBuffer::unbind(); + glColor4f(1,1,1,1); + for (S32 i = 0; i < llmin(6, face_count); ++i) { renderSkyCubeFace(i); } - LLGLEnable blend(GL_BLEND); - glPopMatrix(); } @@ -136,6 +137,7 @@ void LLDrawPoolSky::renderSkyCubeFace(U8 side) return; } + llassert(mSkyTex); mSkyTex[side].bindTexture(TRUE); face.renderIndexed(); @@ -149,10 +151,6 @@ void LLDrawPoolSky::renderSkyCubeFace(U8 side) } } -void LLDrawPoolSky::renderForSelect() -{ -} - void LLDrawPoolSky::endRenderPass( S32 pass ) { } diff --git a/indra/newview/lldrawpoolsky.h b/indra/newview/lldrawpoolsky.h index 8595d73ae..3da493cc9 100644 --- a/indra/newview/lldrawpoolsky.h +++ b/indra/newview/lldrawpoolsky.h @@ -64,7 +64,6 @@ public: /*virtual*/ void prerender(); /*virtual*/ void render(S32 pass = 0); - /*virtual*/ void renderForSelect(); /*virtual*/ void endRenderPass(S32 pass); void setSkyTex(LLSkyTex* const st) { mSkyTex = st; } diff --git a/indra/newview/lldrawpooltree.cpp b/indra/newview/lldrawpooltree.cpp index 957869004..762a087ff 100644 --- a/indra/newview/lldrawpooltree.cpp +++ b/indra/newview/lldrawpooltree.cpp @@ -114,11 +114,12 @@ void LLDrawPoolTree::render(S32 pass) iter != mDrawFace.end(); iter++) { LLFace *face = *iter; - if(face->mVertexBuffer.notNull()) + LLVertexBuffer* buff = face->getVertexBuffer(); + if(buff) { - face->mVertexBuffer->setBuffer(LLDrawPoolTree::VERTEX_DATA_MASK); - face->mVertexBuffer->drawRange(LLRender::TRIANGLES, 0, face->mVertexBuffer->getRequestedVerts()-1, face->mVertexBuffer->getRequestedIndices(), 0); - gPipeline.addTrianglesDrawn(face->mVertexBuffer->getRequestedIndices()); + buff->setBuffer(LLDrawPoolTree::VERTEX_DATA_MASK); + buff->drawRange(LLRender::TRIANGLES, 0, buff->getRequestedVerts()-1, buff->getRequestedIndices(), 0); + gPipeline.addTrianglesDrawn(buff->getRequestedIndices()); } } } @@ -167,6 +168,10 @@ void LLDrawPoolTree::beginShadowPass(S32 pass) { LLFastTimer t(LLFastTimer::FTM_SHADOW_TREE); gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.5f); + static const LLCachedControl render_deferred_offset("RenderDeferredTreeShadowOffset",1.f); + static const LLCachedControl render_deferred_bias("RenderDeferredTreeShadowBias",1.f); + glPolygonOffset(render_deferred_offset,render_deferred_bias); + gDeferredShadowProgram.bind(); } @@ -179,7 +184,11 @@ void LLDrawPoolTree::endShadowPass(S32 pass) { LLFastTimer t(LLFastTimer::FTM_SHADOW_TREE); gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); - gDeferredShadowProgram.unbind(); + static const LLCachedControl render_deferred_offset("RenderDeferredTreeShadowOffset",1.f); + static const LLCachedControl render_deferred_bias("RenderDeferredTreeShadowBias",1.f); + glPolygonOffset(render_deferred_offset,render_deferred_bias); + + //gDeferredShadowProgram.unbind(); } @@ -216,7 +225,7 @@ void LLDrawPoolTree::renderForSelect() LLFace *face = *iter; LLDrawable *drawablep = face->getDrawable(); - if (drawablep->isDead() || face->mVertexBuffer.isNull()) + if (drawablep->isDead() || face->getVertexBuffer()) { continue; } @@ -233,9 +242,10 @@ void LLDrawPoolTree::renderForSelect() LLFacePool::LLOverrideFaceColor col(this, color); - face->mVertexBuffer->setBuffer(LLDrawPoolTree::VERTEX_DATA_MASK); - face->mVertexBuffer->drawRange(LLRender::TRIANGLES, 0, face->mVertexBuffer->getRequestedVerts()-1, face->mVertexBuffer->getRequestedIndices(), 0); - gPipeline.addTrianglesDrawn(face->mVertexBuffer->getRequestedIndices()/3); + LLVertexBuffer *buff = face->getVertexBuffer(); + buff->setBuffer(LLDrawPoolTree::VERTEX_DATA_MASK); + buff->drawRange(LLRender::TRIANGLES, 0, buff->getRequestedVerts()-1, buff->getRequestedIndices(), 0); + gPipeline.addTrianglesDrawn(buff->getRequestedIndices()/3); } } } @@ -263,13 +273,13 @@ void LLDrawPoolTree::renderTree(BOOL selecting) LLFace *face = *iter; LLDrawable *drawablep = face->getDrawable(); - if (drawablep->isDead() || face->mVertexBuffer.isNull()) + if (drawablep->isDead() || !face->getVertexBuffer()) { continue; } - face->mVertexBuffer->setBuffer(LLDrawPoolTree::VERTEX_DATA_MASK); - U16* indicesp = (U16*) face->mVertexBuffer->getIndicesPointer(); + face->getVertexBuffer()->setBuffer(LLDrawPoolTree::VERTEX_DATA_MASK); + U16* indicesp = (U16*) face->getVertexBuffer()->getIndicesPointer(); // Render each of the trees LLVOTree *treep = (LLVOTree *)drawablep->getVObj().get(); @@ -323,15 +333,16 @@ void LLDrawPoolTree::renderTree(BOOL selecting) scale_mat *= rot_mat; + //TO-DO: Make these set-able? const F32 THRESH_ANGLE_FOR_BILLBOARD = 7.5f; //Made LoD now a little less aggressive here -Shyotl - /*const F32 BLEND_RANGE_FOR_BILLBOARD = 1.5f;*/ //Unused, really + const F32 BLEND_RANGE_FOR_BILLBOARD = 1.5f; F32 droop = treep->mDroop + 25.f*(1.f - treep->mTrunkBend.magVec()); S32 stop_depth = 0; F32 app_angle = treep->getAppAngle()*LLVOTree::sTreeFactor; F32 alpha = 1.0; - S32 trunk_LOD = 0; + S32 trunk_LOD = LLVOTree::sMAX_NUM_TREE_LOD_LEVELS; for (S32 j = 0; j < 4; j++) { @@ -342,8 +353,12 @@ void LLDrawPoolTree::renderTree(BOOL selecting) break; } } + if(trunk_LOD >= LLVOTree::sMAX_NUM_TREE_LOD_LEVELS) + { + continue ; //do not render. + } - if (app_angle < (THRESH_ANGLE_FOR_BILLBOARD/* - BLEND_RANGE_FOR_BILLBOARD*/)) + if (app_angle < (THRESH_ANGLE_FOR_BILLBOARD - BLEND_RANGE_FOR_BILLBOARD)) { // // Draw only the billboard diff --git a/indra/newview/lldrawpoolwater.cpp b/indra/newview/lldrawpoolwater.cpp index 3e260f8b1..2b93af7b1 100644 --- a/indra/newview/lldrawpoolwater.cpp +++ b/indra/newview/lldrawpoolwater.cpp @@ -45,7 +45,6 @@ #include "lldrawable.h" #include "llface.h" #include "llsky.h" -#include "llviewercamera.h" // to get OGL_TO_CFR_ROTATION #include "llviewertexturelist.h" #include "llviewerregion.h" #include "llvosky.h" @@ -55,7 +54,8 @@ #include "llviewershadermgr.h" #include "llwaterparammanager.h" -const LLUUID WATER_TEST("2bfd3884-7e27-69b9-ba3a-3e673f680004"); +const LLUUID TRANSPARENT_WATER_TEXTURE("2bfd3884-7e27-69b9-ba3a-3e673f680004"); +const LLUUID OPAQUE_WATER_TEXTURE("43c32285-d658-1793-c123-bf86315de055"); static float sTime; @@ -79,9 +79,11 @@ LLDrawPoolWater::LLDrawPoolWater() : mHBTex[1]->setAddressMode(LLTexUnit::TAM_CLAMP); - mWaterImagep = LLViewerTextureManager::getFetchedTexture(WATER_TEST); + mWaterImagep = LLViewerTextureManager::getFetchedTexture(TRANSPARENT_WATER_TEXTURE); llassert(mWaterImagep); - mWaterImagep->setNoDelete() ; + mWaterImagep->setNoDelete(); + mOpaqueWaterImagep = LLViewerTextureManager::getFetchedTexture(OPAQUE_WATER_TEXTURE); + llassert(mOpaqueWaterImagep); mWaterNormp = LLViewerTextureManager::getFetchedTexture(DEFAULT_WATER_NORMAL); mWaterNormp->setNoDelete(); @@ -169,6 +171,13 @@ void LLDrawPoolWater::render(S32 pass) } std::sort(mDrawFace.begin(), mDrawFace.end(), LLFace::CompareDistanceGreater()); + static const LLCachedControl render_transparent_water("RenderTransparentWater",false); + if(!render_transparent_water) + { + // render water for low end hardware + renderOpaqueLegacyWater(); + return; + } LLGLEnable blend(GL_BLEND); @@ -323,6 +332,87 @@ void LLDrawPoolWater::render(S32 pass) gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); } +// for low end hardware +void LLDrawPoolWater::renderOpaqueLegacyWater() +{ + LLVOSky *voskyp = gSky.mVOSkyp; + + stop_glerror(); + + // Depth sorting and write to depth buffer + // since this is opaque, we should see nothing + // behind the water. No blending because + // of no transparency. And no face culling so + // that the underside of the water is also opaque. + LLGLDepthTest gls_depth(GL_TRUE, GL_TRUE); + LLGLDisable no_cull(GL_CULL_FACE); + LLGLDisable no_blend(GL_BLEND); + + gPipeline.disableLights(); + + mOpaqueWaterImagep->addTextureStats(1024.f*1024.f); + + // Activate the texture binding and bind one + // texture since all images will have the same texture + gGL.getTexUnit(0)->activate(); + gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE); + gGL.getTexUnit(0)->bind(mOpaqueWaterImagep); + + // Automatically generate texture coords for water texture + glEnable(GL_TEXTURE_GEN_S); //texture unit 0 + glEnable(GL_TEXTURE_GEN_T); //texture unit 0 + glTexGenf(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); + glTexGenf(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); + + // Use the fact that we know all water faces are the same size + // to save some computation + + // Slowly move texture coordinates over time so the watter appears + // to be moving. + F32 movement_period_secs = 50.f; + + F32 offset = fmod(gFrameTimeSeconds, movement_period_secs); + + if (movement_period_secs != 0) + { + offset /= movement_period_secs; + } + else + { + offset = 0; + } + + F32 tp0[4] = { 16.f / 256.f, 0.0f, 0.0f, offset }; + F32 tp1[4] = { 0.0f, 16.f / 256.f, 0.0f, offset }; + + glTexGenfv(GL_S, GL_OBJECT_PLANE, tp0); + glTexGenfv(GL_T, GL_OBJECT_PLANE, tp1); + + glColor3f(1.f, 1.f, 1.f); + + for (std::vector::iterator iter = mDrawFace.begin(); + iter != mDrawFace.end(); iter++) + { + LLFace *face = *iter; + if (voskyp->isReflFace(face)) + { + continue; + } + + face->renderIndexed(); + } + + stop_glerror(); + + // Reset the settings back to expected values + glDisable(GL_TEXTURE_GEN_S); //texture unit 0 + glDisable(GL_TEXTURE_GEN_T); //texture unit 0 + + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); +} + + void LLDrawPoolWater::renderReflection(LLFace* face) { LLVOSky *voskyp = gSky.mVOSkyp; @@ -603,23 +693,6 @@ void LLDrawPoolWater::shade() } -void LLDrawPoolWater::renderForSelect() -{ - // Can't select water! - return; -} - - -void LLDrawPoolWater::renderFaceSelected(LLFace *facep, - LLViewerTexture *image, - const LLColor4 &color, - const S32 index_offset, const S32 index_count) -{ - // Can't select water - return; -} - - LLViewerTexture *LLDrawPoolWater::getDebugTexture() { return LLViewerFetchedTexture::sSmokeImagep; diff --git a/indra/newview/lldrawpoolwater.h b/indra/newview/lldrawpoolwater.h index 0ce14eae3..fe579ec26 100644 --- a/indra/newview/lldrawpoolwater.h +++ b/indra/newview/lldrawpoolwater.h @@ -45,6 +45,7 @@ class LLDrawPoolWater: public LLFacePool protected: LLPointer mHBTex[2]; LLPointer mWaterImagep; + LLPointer mOpaqueWaterImagep; LLPointer mWaterNormp; public: @@ -79,16 +80,16 @@ public: /*virtual*/ S32 getNumPasses(); /*virtual*/ void render(S32 pass = 0); - /*virtual*/ void renderFaceSelected(LLFace *facep, LLViewerTexture *image, const LLColor4 &color, - const S32 index_offset = 0, const S32 index_count = 0); /*virtual*/ void prerender(); - /*virtual*/ void renderForSelect(); /*virtual*/ LLViewerTexture *getDebugTexture(); /*virtual*/ LLColor3 getDebugColor() const; // For AGP debug display void renderReflection(LLFace* face); void shade(); + +protected: + void renderOpaqueLegacyWater(); }; void cgErrorCallback(); diff --git a/indra/newview/lldrawpoolwlsky.cpp b/indra/newview/lldrawpoolwlsky.cpp index 07ce6c59c..4a6321a69 100644 --- a/indra/newview/lldrawpoolwlsky.cpp +++ b/indra/newview/lldrawpoolwlsky.cpp @@ -42,7 +42,6 @@ #include "llwlparammanager.h" #include "llsky.h" #include "llvowlsky.h" -#include "llagent.h" #include "llviewerregion.h" #include "llface.h" #include "llrender.h" @@ -209,7 +208,7 @@ void LLDrawPoolWLSky::renderSkyClouds(F32 camHeightLocal) const &gWLCloudProgram; LLGLEnable blend(GL_BLEND); - LLGLSBlendFunc blendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + gGL.setSceneBlendType(LLRender::BT_ALPHA); gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); gGL.getTexUnit(0)->bind(sCloudNoiseTexture); diff --git a/indra/newview/llemote.cpp b/indra/newview/llemote.cpp index bacf3daf5..c83846215 100644 --- a/indra/newview/llemote.cpp +++ b/indra/newview/llemote.cpp @@ -39,7 +39,6 @@ #include "llcharacter.h" #include "m3math.h" #include "llvoavatar.h" -#include "llagent.h" //----------------------------------------------------------------------------- // Constants diff --git a/indra/newview/lleventnotifier.cpp b/indra/newview/lleventnotifier.cpp index 63cf2b16a..1e915a266 100644 --- a/indra/newview/lleventnotifier.cpp +++ b/indra/newview/lleventnotifier.cpp @@ -117,7 +117,6 @@ void LLEventNotifier::load(const LLUserAuth::options_t& event_options) } } - BOOL LLEventNotifier::hasNotification(const U32 event_id) { if (mEventNotifications.find(event_id) != mEventNotifications.end()) @@ -127,7 +126,6 @@ BOOL LLEventNotifier::hasNotification(const U32 event_id) return FALSE; } - void LLEventNotifier::add(LLEventInfo &event_info) { // We need to tell the simulator that we want to pay attention to diff --git a/indra/newview/lleventpoll.cpp b/indra/newview/lleventpoll.cpp index 9e79d93d7..3114f2914 100644 --- a/indra/newview/lleventpoll.cpp +++ b/indra/newview/lleventpoll.cpp @@ -39,8 +39,9 @@ #include "llhttpclient.h" #include "llhttpstatuscodes.h" #include "llsdserialize.h" -#include "llsdutil.h" -#include "lltimer.h" +#include "lleventtimer.h" +#include "llsdutil.h" + #include "llviewerregion.h" #include "message.h" #include "lltrans.h" @@ -141,10 +142,7 @@ namespace LLViewerRegion *regionp = gAgent.getRegion(); if (!regionp) { - // OGPX : Changed from llerrs to llwarns. - // No longer an llerrs error, because we might be starting an event queue before we have a region. - - llwarns << "LLEventPoll initialized before region is added." << llendl; + llerrs << "LLEventPoll initialized before region is added." << llendl; } mSender = sender.getIPandPort(); llinfos << "LLEventPoll initialized with sender " << mSender << llendl; @@ -238,12 +236,6 @@ namespace if(gAgent.getRegion() && gAgent.getRegion()->getHost().getIPandPort() == mSender) { llwarns << "Forcing disconnect due to stalled main region event poll." << llendl; - // OGPX - Is this valid in the OGPX case? forceDisconnect() pops up a dialog. - // in the OGPX case, if we lose the connection to the region, we might still - // have one to the Agent Domain. - // Since the viewer doesn't currently implement any functionality that involves - // being connected to the Agent Domain without also being connected to a region, leave the - // call to forceDisconnect() here. LLAppViewer::instance()->forceDisconnect(LLTrans::getString("AgentLostConnection")); } } @@ -252,8 +244,8 @@ namespace //virtual void LLEventPollResponder::result(const LLSD& content) { - LL_DEBUGS("OGPX") << "LLEventPollResponder::result <" << mCount << ">" - << (mDone ? " -- done" : "") << ll_pretty_print_sd(content) << LL_ENDL; + lldebugs << "LLEventPollResponder::result <" << mCount << ">" + << (mDone ? " -- done" : "") << ll_pretty_print_sd(content) << llendl; if (mDone) return; @@ -291,226 +283,6 @@ namespace makeRequest(); } - - // OGPX : So this area of the code is an acknowledged mess... but... - // it is also an area that will be changing a lot as OGPX changes and grows. - // Leave the event queue code completely separate (agent vs region eq) so that - // normal legacy region eq connections aren't subject to the thrashing - // that agent eq code will have. - // - // Similar to the way a sim needs to invoke a request on the client without doing - // an actual inbound http request, this is the similar mechanism for - // the Agent Domain. One area of current investigation is how the viewer - // might accomodate requests from multiple services (i.e., we shouldn't make - // assumptions about how a particular OGPX grid or agent domain has carved up - // the handling of different pieces of functionality). - - - class LLAgentEventPollResponder : public LLHTTPClient::Responder - { - public: - - static LLHTTPClient::ResponderPtr start(const std::string& pollURL); - void stop(); - virtual void makeRequest(); - virtual void makeRequest(const LLSD&); - - private: - LLAgentEventPollResponder(const std::string& pollURL); - ~LLAgentEventPollResponder(); - - //void handleMessage(const LLSD& content); - virtual void error(U32 status, const std::string& reason); - virtual void result(const LLSD& content); - - private: - - bool mDone; - int mAcknowledge ; // OGPX : id of request to send back along with the response to Agent Domain. - // We will probably change the specifics of returning the result of - // a resource request. - - std::string mPollURL; - - // these are only here for debugging so we can see which poller is which - static int sCount; - int mCount; - }; - - - //static - LLHTTPClient::ResponderPtr LLAgentEventPollResponder::start( - const std::string& pollURL) - { - LLHTTPClient::ResponderPtr result = new LLAgentEventPollResponder(pollURL); - LL_INFOS("OGPX") << "LLAgentEventPollResponder::start <" << sCount << "> " - << pollURL << LL_ENDL; - return result; - } - - void LLAgentEventPollResponder::stop() - { - LL_INFOS("OGPX") << "LLAgentEventPollResponder::stop <" << mCount << "> " - << mPollURL << LL_ENDL; - // there should be a way to stop a LLHTTPClient request in progress - mDone = true; - } - - int LLAgentEventPollResponder::sCount = 0; - - LLAgentEventPollResponder::LLAgentEventPollResponder(const std::string& pollURL) - : mDone(false), - mPollURL(pollURL), - mAcknowledge(0), - mCount(++sCount) - { - - makeRequest(); - } - - LLAgentEventPollResponder::~LLAgentEventPollResponder() - { - stop(); - LL_DEBUGS("OGPX") << "LLAgentEventPollResponder::~Impl <" << mCount << "> " - << mPollURL << LL_ENDL; - } - - // OGPX : Should LLAgentEventPollResponder inherits from normal EventPollResponder, - // or will the two classes diverge as we figure out how AgentEventPoll will - // actually work? Me thinks that event queue code will be changed so much that a clear - // sharp division between the classes might not be such a bad thing right now. - // It's especially important to minimize code changes to the XML-RPC legacy path while - // adding OGP code, because that minimizes risk to breaking something in the legacy path. - void LLAgentEventPollResponder::makeRequest() - { - LL_DEBUGS("OGPX") << "LLAgentEventPollResponder::makeRequest <" << mCount << "> "<< LL_ENDL; - LLSD request; - request["ack"] = mAcknowledge; - request["done"] = mDone; - LLHTTPClient::post(mPollURL, request, this); - } - - // OGPX only function passes response back to agent domain. - // This is our backward little way of responding to a request - // for client side resources, and passing something back to the requestor - // in the HTTP stream. The original makeRequest() is in place to provide a - // regular way to 'tap' the agent domain and ask if there were any client side - // resources it needed to request. This function adds the ability to also - // pass back LLSD along with the 'tap' - // - // WARNING: - // This area of the code will change a lot as OGPX is developed. When - // client side resources are invoked, we need some way to pass back - // a response on the event queue. This is one possible way. - void LLAgentEventPollResponder::makeRequest(const LLSD& result_for_agentd) - { - LLSD args; - args["ack"] = mAcknowledge; - args["done"] = mDone; - args["result"] = result_for_agentd; - LL_DEBUGS("OGPX") << "LLAgentEventPollResponder::makeRequest <" << mCount << "> " << ll_pretty_print_sd(result_for_agentd) << LL_ENDL; - LLHTTPClient::post(mPollURL, args, this); - } - - // virtual - void LLAgentEventPollResponder::error(U32 status, const std::string& reason) - { - if (mDone) return; - - if (status != 499) - { - LL_WARNS("OGPX") << "LLAgentEventPollResponder::error: <" << mCount << "> got " - << status << " : " << reason - << (mDone ? " -- done" : "") << LL_ENDL; - stop(); - return; - } - - makeRequest(); - } - - - //virtual - void LLAgentEventPollResponder::result(const LLSD& content) - { - LLSD result_for_agentd; - LL_DEBUGS("OGPX") << "LLAgentEventPollResponder::result <" << mCount << ">" - << (mDone ? " -- done" : "") << LL_ENDL; - - if (mDone) return; - - // was llinfos but now that CoarseRegionUpdate is TCP @ 1/second, it'd be too verbose for viewer logs. -MG - LL_DEBUGS("OGPX") << "LLAgentEventPollResponder::completed <" << mCount << "> " << LL_ENDL; - - - if (!content.get("events") || - !content.get("id")) - { - LL_INFOS("OGPX") << "Received event poll with no events or id key" << LL_ENDL; // was llwarns, but too frequent - makeRequest(); - return; - } - mAcknowledge = 0; - mAcknowledge = content["id"]; - LLSD events = content["events"]; - - if (mAcknowledge!=0) - { - LL_WARNS("OGPX") << " : id undefined" << LL_ENDL; - } - - // was llinfos but now that CoarseRegionUpdate is TCP @ 1/second, it'd be too verbose for viewer logs. -MG - LL_DEBUGS("OGPX") << "LLEventPollResponder::completed <" << mCount << "> " << events.size() << "events (id " - << LLSDXMLStreamer(mAcknowledge) << ")" << LL_ENDL; - - // twiddling with making the messaging system gobble up event queue requests -#if OGPXEVENTHACK - // OGPXEVENTHACK : An attempt at using the message_template.msg as a way to add HTTP messages that - // are handled by the event queue (instead of coming across UDP, and being handled via UDP decoding). - // I found that I was able to do this in a limited way (have a message decoded into LLSD, - // and a handler called for it) for inbound EQ messages. Unsure it gives us the level of control - // we need in OGPX to implement policy and trust between the viewer and other entities. The legacy - // model was "trust everything from the region", and it won't be that way in OGPX. - // Feels weird adding dead code to the patch, but I wanted a record of the experimentation - // OGPX TODO: figure out proper building of services. - - // iterate over the requests sent by agent domain - LLSD::array_const_iterator i = events.beginArray(); - LLSD::array_const_iterator end = events.endArray(); - for (; i != end; ++i) - { - if (i->has("message")) - { - std::string message = i->get("message"); - std::string path = "/message/" + message; // OGPX : mmmm....seems like we are gluing it together so traverse can tear it apart - LLSD context; - // so this tries to traverse over the things registered - // in llhttpnode.cpp, but i had trouble getting anything other than message to work - const LLHTTPNode* handler = messageRootNode().traverse(path, context); - if (!handler) - { - LL_WARNS("Messaging") << " no handler for "<< path << LL_ENDL; - return; - } - - //lldebugs << "data: " << LLSDNotationStreamer(message) << llendl; - - // We've found a handler for the request, call its post() and get its LLSD response - // so, changing from the post that was fussing with response pointer to simpler - result_for_agentd = handler->post(*i); - LL_DEBUGS("OGPX") << "after handling "<< ll_pretty_print_sd(*i) << " sending AD result: " << ll_pretty_print_sd(result_for_agentd) << LL_ENDL; - } - } - // OGPXEVENTHACK end - - // OGPX : result_for_agentd is LLSD and passed back to agentd with the next 'tap' - makeRequest(result_for_agentd); -#else - // OGPX :until eventqueue code is redesigned, just send back the regular 'tap' - makeRequest(); -#endif - } - } LLEventPoll::LLEventPoll(const std::string& poll_url, const LLHost& sender) @@ -524,16 +296,3 @@ LLEventPoll::~LLEventPoll() if (event_poll_responder) event_poll_responder->stop(); } -// OGPX : We maintain an event poll with the Agent Domain and with the region -// while OGP9 svn branch tried to use a funky ReverseHTTP thing for the Responder, -// for now we will revert to simpler code. This poll should remain active for the -// life of the viewer session. -LLAgentEventPoll::LLAgentEventPoll(const std::string& pollURL) - : mImpl(LLAgentEventPollResponder::start(pollURL)) -{ -} - - -LLAgentEventPoll::~LLAgentEventPoll() -{ -} diff --git a/indra/newview/lleventpoll.h b/indra/newview/lleventpoll.h index db60f6bbf..5b0087a51 100644 --- a/indra/newview/lleventpoll.h +++ b/indra/newview/lleventpoll.h @@ -50,21 +50,4 @@ private: LLHTTPClient::ResponderPtr mImpl; }; -// Just like the region uses the event poll to invoke services on the viewer, -// the agent domain also does. There will be lots of changes coming to this code, -// for now a nice clean split from the region's event code. -class LLAgentEventPoll //OGPX - ///< implements the viewer side of server-to-viewer pushed events. -{ -public: - LLAgentEventPoll(const std::string& pollURL); - ///< Start polling the URL. - - virtual ~LLAgentEventPoll(); - ///< will stop polling, cancelling any poll in progress. - - -private: - LLHTTPClient::ResponderPtr mImpl; -}; #endif // LL_LLEVENTPOLL_H diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp index 186870a80..9c7420898 100644 --- a/indra/newview/llface.cpp +++ b/indra/newview/llface.cpp @@ -184,6 +184,11 @@ void LLFace::init(LLDrawable* drawablep, LLViewerObject* objp) void LLFace::destroy() { + if (gDebugGL) + { + gPipeline.checkReferences(this); + } + if(mTexture.notNull()) { mTexture->removeFace(this) ; @@ -228,6 +233,11 @@ void LLFace::setWorldMatrix(const LLMatrix4 &mat) llerrs << "Faces on this drawable are not independently modifiable\n" << llendl; } +void LLFace::setPool(LLFacePool* pool) +{ + mDrawPoolp = pool; +} + void LLFace::setPool(LLFacePool* new_pool, LLViewerTexture *texturep) { LLMemType mt1(LLMemType::MTYPE_DRAWABLE); @@ -329,8 +339,13 @@ void LLFace::setDrawable(LLDrawable *drawable) mXform = &drawable->mXform; } -void LLFace::setSize(const S32 num_vertices, const S32 num_indices) +void LLFace::setSize(S32 num_vertices, const S32 num_indices, bool align) { + if (align) + { + //allocate vertices in blocks of 4 for alignment + num_vertices = (num_vertices + 0x3) & ~0x3; + } if (mGeomCount != num_vertices || mIndicesCount != num_indices) { @@ -339,6 +354,8 @@ void LLFace::setSize(const S32 num_vertices, const S32 num_indices) mVertexBuffer = NULL; mLastVertexBuffer = NULL; } + + llassert(verify()); } //============================================================================ @@ -940,7 +957,7 @@ bool LLFace::canRenderAsMask() ) // do we want masks at all? && (te->getColor().mV[3] == 1.0f) && // can't treat as mask if we have face alpha - !(LLPipeline::sRenderDeferred && te->getFullbright()) && // hack: alpha masking renders fullbright faces invisible in deferred rendering mode, need to figure out why - for now, avoid + //!(LLPipeline::sRenderDeferred && te->getFullbright()) && // hack: alpha masking renders fullbright faces invisible in deferred rendering mode, need to figure out why - for now, avoid (te->getGlow() == 0.f) && // glowing masks are hard to implement - don't mask getTexture()->getIsAlphaMask() // texture actually qualifies for masking (lazily recalculated but expensive) @@ -952,6 +969,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, const LLMatrix4& mat_vert, const LLMatrix3& mat_normal, const U16 &index_offset) { + llassert(verify()); const LLVolumeFace &vf = volume.getVolumeFace(f); S32 num_vertices = (S32)vf.mVertices.size(); S32 num_indices = (S32)vf.mIndices.size(); @@ -1678,3 +1696,16 @@ LLViewerTexture* LLFace::getTexture() const { return mTexture ; } + +void LLFace::setVertexBuffer(LLVertexBuffer* buffer) +{ + mVertexBuffer = buffer; + llassert(verify()); +} + +void LLFace::clearVertexBuffer() +{ + mVertexBuffer = NULL; + mLastVertexBuffer = NULL; +} + diff --git a/indra/newview/llface.h b/indra/newview/llface.h index 9825d4dc2..edbf0bafd 100644 --- a/indra/newview/llface.h +++ b/indra/newview/llface.h @@ -64,6 +64,17 @@ class LLFace { public: + LLFace(const LLFace& rhs) + { + *this = rhs; + } + + const LLFace& operator=(const LLFace& rhs) + { + llerrs << "Illegal operation!" << llendl; + return *this; + } + enum EMasks { LIGHT = 0x0001, @@ -124,13 +135,13 @@ public: LLDrawable* getDrawable() const { return mDrawablep; } LLViewerObject* getViewerObject() const { return mVObjp; } S32 getLOD() const { return mVObjp.notNull() ? mVObjp->getLOD() : 0; } - LLVertexBuffer* getVertexBuffer() const { return mVertexBuffer; } void setPoolType(U32 type) { mPoolType = type; } S32 getTEOffset() { return mTEOffset; } LLViewerTexture* getTexture() const; - + void setViewerObject(LLViewerObject* object); void setPool(LLFacePool *pool, LLViewerTexture *texturep); + void setPool(LLFacePool* pool); void setDrawable(LLDrawable *drawable); void setTEOffset(const S32 te_offset); @@ -167,7 +178,7 @@ public: S32 getColors(LLStrider &colors); S32 getIndices(LLStrider &indices); - void setSize(const S32 numVertices, const S32 num_indices = 0); + void setSize(S32 numVertices, const S32 num_indices = 0, bool align = false); BOOL genVolumeBBoxes(const LLVolume &volume, S32 f, const LLMatrix4& mat, const LLMatrix3& inv_trans_mat, BOOL global_volume = FALSE); @@ -196,6 +207,10 @@ public: F32 getTextureVirtualSize() ; F32 getImportanceToCamera()const {return mImportanceToCamera ;} + //vertex buffer tracking + void setVertexBuffer(LLVertexBuffer* buffer); + void clearVertexBuffer(); //sets mVertexBuffer and mLastVertexBuffer to NULL + LLVertexBuffer* getVertexBuffer() const { return mVertexBuffer; } private: F32 adjustPartialOverlapPixelArea(F32 cos_angle_to_view_dir, F32 radius ); @@ -211,8 +226,6 @@ public: LLVector3 mExtents[2]; LLVector2 mTexExtents[2]; F32 mDistance; - LLPointer mVertexBuffer; - LLPointer mLastVertexBuffer; F32 mLastUpdateTime; F32 mLastMoveTime; LLMatrix4* mTextureMatrix; @@ -222,6 +235,9 @@ private: friend class LLGeometryManager; friend class LLVolumeGeometryManager; + LLPointer mVertexBuffer; + LLPointer mLastVertexBuffer; + U32 mState; LLFacePool* mDrawPoolp; U32 mPoolType; diff --git a/indra/newview/llfasttimerview.cpp b/indra/newview/llfasttimerview.cpp index 27661567e..ab0868237 100644 --- a/indra/newview/llfasttimerview.cpp +++ b/indra/newview/llfasttimerview.cpp @@ -81,8 +81,10 @@ static struct ft_display_info ft_display_table[] = { LLFastTimer::FTM_MESSAGES, " System Messages", &LLColor4::grey1, 1 }, { LLFastTimer::FTM_MOUSEHANDLER, " Mouse", &LLColor4::grey1, 0 }, { LLFastTimer::FTM_KEYHANDLER, " Keyboard", &LLColor4::grey1, 0 }, + { LLFastTimer::FT_STRING_FORMAT, " String Format", &LLColor4::grey3, 0 }, { LLFastTimer::FTM_SLEEP, " Sleep", &LLColor4::grey2, 0 }, { LLFastTimer::FTM_IDLE, " Idle", &blue0, 0 }, + { LLFastTimer::FTM_STATEMACHINE, " State Machines", &LLColor4::yellow1, 0 }, { LLFastTimer::FTM_PUMP, " Pump", &LLColor4::magenta2, 1 }, { LLFastTimer::FTM_CURL, " Curl", &LLColor4::magenta3, 0 }, { LLFastTimer::FTM_PUMPIO, " PumpIO", &LLColor4::magenta1, 0 }, @@ -193,6 +195,19 @@ static struct ft_display_info ft_display_table[] = { LLFastTimer::FTM_RENDER_FAKE_VBO_UPDATE," Fake VBO update", &LLColor4::red2, 0 }, { LLFastTimer::FTM_RENDER_BLOOM, " Bloom", &LLColor4::blue4, 0 }, { LLFastTimer::FTM_RENDER_BLOOM_FBO, " First FBO", &LLColor4::blue, 0 }, + { LLFastTimer::FTM_RENDER_DEFERRED, " Deferred", &LLColor4::cyan4, 1 }, + { LLFastTimer::FTM_BIND_DEFERRED, " Bind", &LLColor4::pink2, 0 }, + { LLFastTimer::FTM_SUN_SHADOW, " Sun Shadow", &LLColor4::cyan5, 0 }, + { LLFastTimer::FTM_SOFTEN_SHADOW, " Soften Shadow", &LLColor4::yellow1, 0 }, + { LLFastTimer::FTM_EDGE_DETECTION, " Edge Detect", &LLColor4::cyan2, 0 }, + { LLFastTimer::FTM_GI_TRACE, " GI Trace", &LLColor4::green6, 0 }, + { LLFastTimer::FTM_GI_GATHER, " GI Gather", &LLColor4::cyan1, 0 }, + { LLFastTimer::FTM_ATMOSPHERICS, " Atmos", &LLColor4::pink1, 0 }, + { LLFastTimer::FTM_LOCAL_LIGHTS, " Local Lights", &LLColor4::blue2, 0 }, + { LLFastTimer::FTM_FULLSCREEN_LIGHTS, " FS Lights", &LLColor4::purple4, 0 }, + { LLFastTimer::FTM_PROJECTORS, " Project", &LLColor4::orange2, 0 }, + { LLFastTimer::FTM_POST, " Postprocess", &LLColor4::red4, 0 }, + { LLFastTimer::FTM_VISIBLE_CLOUD, " Visible Cloud", &LLColor4::blue5, 0 }, { LLFastTimer::FTM_RENDER_UI, " UI", &LLColor4::cyan4, 1 }, { LLFastTimer::FTM_RENDER_TIMER, " Timers", &LLColor4::cyan5, 1, 0 }, { LLFastTimer::FTM_RENDER_FONTS, " Fonts", &LLColor4::pink1, 0 }, diff --git a/indra/newview/llfeaturemanager.cpp b/indra/newview/llfeaturemanager.cpp index 9614f639d..ce1c00d73 100644 --- a/indra/newview/llfeaturemanager.cpp +++ b/indra/newview/llfeaturemanager.cpp @@ -207,7 +207,7 @@ BOOL LLFeatureManager::maskFeatures(const std::string& name) LL_DEBUGS("RenderInit") << "Unknown feature mask " << name << LL_ENDL; return FALSE; } - LL_DEBUGS("RenderInit") << "Applying Feature Mask: " << name << LL_ENDL; + LL_INFOS("RenderInit") << "Applying GPU Feature list: " << name << LL_ENDL; return maskList(*maskp); } @@ -221,22 +221,33 @@ BOOL LLFeatureManager::loadFeatureTables() mSkippedFeatures.insert("RenderVBOEnable"); mSkippedFeatures.insert("RenderFogRatio"); - std::string data_path = gDirUtilp->getAppRODataDir(); + // first table is install with app + std::string app_path = gDirUtilp->getAppRODataDir(); + app_path += gDirUtilp->getDirDelimiter(); - data_path += gDirUtilp->getDirDelimiter(); + std::string filename = FEATURE_TABLE_FILENAME; - data_path += FEATURE_TABLE_FILENAME; - lldebugs << "Looking for feature table in " << data_path << llendl; + + app_path += filename; + + + return parseFeatureTable(app_path); +} + + +BOOL LLFeatureManager::parseFeatureTable(std::string filename) +{ + llinfos << "Looking for feature table in " << filename << llendl; llifstream file; std::string name; U32 version; - file.open(data_path); /*Flawfinder: ignore*/ + file.open(filename); /*Flawfinder: ignore*/ if (!file) { - LL_WARNS("RenderInit") << "Unable to open feature table!" << LL_ENDL; + LL_WARNS("RenderInit") << "Unable to open feature table " << filename << LL_ENDL; return FALSE; } @@ -245,7 +256,7 @@ BOOL LLFeatureManager::loadFeatureTables() file >> version; if (name != "version") { - LL_WARNS("RenderInit") << data_path << " does not appear to be a valid feature table!" << LL_ENDL; + LL_WARNS("RenderInit") << filename << " does not appear to be a valid feature table!" << LL_ENDL; return FALSE; } @@ -284,6 +295,7 @@ BOOL LLFeatureManager::loadFeatureTables() if (!flp) { LL_ERRS("RenderInit") << "Specified parameter before keyword!" << LL_ENDL; + return FALSE; } S32 available; F32 recommended; @@ -298,34 +310,41 @@ BOOL LLFeatureManager::loadFeatureTables() void LLFeatureManager::loadGPUClass() { - std::string data_path = gDirUtilp->getAppRODataDir(); - - data_path += gDirUtilp->getDirDelimiter(); - - data_path += GPU_TABLE_FILENAME; - // defaults mGPUClass = GPU_CLASS_UNKNOWN; mGPUString = gGLManager.getRawGLString(); mGPUSupported = FALSE; + // first table is in the app dir + std::string app_path = gDirUtilp->getAppRODataDir(); + app_path += gDirUtilp->getDirDelimiter(); + app_path += GPU_TABLE_FILENAME; + parseGPUTable(app_path); +} + + +void LLFeatureManager::parseGPUTable(std::string filename) +{ llifstream file; - file.open(data_path); /*Flawfinder: ignore*/ + file.open(filename); if (!file) { - LL_WARNS("RenderInit") << "Unable to open GPU table: " << data_path << "!" << LL_ENDL; + LL_WARNS("RenderInit") << "Unable to open GPU table: " << filename << "!" << LL_ENDL; return; } - std::string renderer = gGLManager.getRawGLString(); + std::string rawRenderer = gGLManager.getRawGLString(); + std::string renderer = rawRenderer; for (std::string::iterator i = renderer.begin(); i != renderer.end(); ++i) { *i = tolower(*i); } - - while (!file.eof()) + + bool gpuFound; + U32 lineNumber; + for (gpuFound = false, lineNumber = 0; !gpuFound && !file.eof(); lineNumber++) { char buffer[MAX_STRING]; /*Flawfinder: ignore*/ buffer[0] = 0; @@ -372,6 +391,7 @@ void LLFeatureManager::loadGPUClass() if (label.empty() || expr.empty() || cls.empty() || supported.empty()) { + LL_WARNS("RenderInit") << "invald gpu_table.txt:" << lineNumber << ": '" << buffer << "'" << LL_ENDL; continue; } @@ -385,18 +405,26 @@ void LLFeatureManager::loadGPUClass() if(boost::regex_search(renderer, re)) { // if we found it, stop! - file.close(); - LL_INFOS("RenderInit") << "GPU is " << label << llendl; + gpuFound = true; mGPUString = label; mGPUClass = (EGPUClass) strtol(cls.c_str(), NULL, 10); mGPUSupported = (BOOL) strtol(supported.c_str(), NULL, 10); - file.close(); - return; } } file.close(); - LL_WARNS("RenderInit") << "Couldn't match GPU to a class: " << gGLManager.getRawGLString() << LL_ENDL; + if ( gpuFound ) + { + LL_INFOS("RenderInit") << "GPU '" << rawRenderer << "' recognized as '" << mGPUString << "'" << LL_ENDL; + if (!mGPUSupported) + { + LL_INFOS("RenderInit") << "GPU '" << mGPUString << "' is not supported." << LL_ENDL; + } + } + else + { + LL_WARNS("RenderInit") << "GPU '" << rawRenderer << "' not recognized" << LL_ENDL; + } } void LLFeatureManager::cleanupFeatureTables() @@ -579,6 +607,10 @@ void LLFeatureManager::applyBaseMasks() { maskFeatures("ATI"); } + if (gGLManager.mHasATIMemInfo && gGLManager.mVRAM < 256) + { + maskFeatures("ATIVramLT256"); + } if (gGLManager.mATIOldDriver) { maskFeatures("ATIOldDriver"); @@ -595,6 +627,14 @@ void LLFeatureManager::applyBaseMasks() { maskFeatures("OpenGLPre15"); } + if (gGLManager.mGLVersion < 3.f) + { + maskFeatures("OpenGLPre30"); + } + if (gGLManager.mNumTextureImageUnits <= 8) + { + maskFeatures("TexUnit8orLess"); + } // now mask by gpu string // Replaces ' ' with '_' in mGPUString to deal with inability for parser to handle spaces diff --git a/indra/newview/llfeaturemanager.h b/indra/newview/llfeaturemanager.h index 537bf0c6a..a9cb33598 100644 --- a/indra/newview/llfeaturemanager.h +++ b/indra/newview/llfeaturemanager.h @@ -98,8 +98,14 @@ protected: class LLFeatureManager : public LLFeatureList, public LLSingleton { public: - LLFeatureManager() : - LLFeatureList("default"), mInited(FALSE), mTableVersion(0), mSafe(FALSE), mGPUClass(GPU_CLASS_UNKNOWN) + LLFeatureManager() + : LLFeatureList("default"), + + mInited(FALSE), + mTableVersion(0), + mSafe(FALSE), + mGPUClass(GPU_CLASS_UNKNOWN), + mGPUSupported(FALSE) { } ~LLFeatureManager() {cleanupFeatureTables();} @@ -139,6 +145,8 @@ public: protected: void loadGPUClass(); + BOOL parseFeatureTable(std::string filename); + void parseGPUTable(std::string filename); void initBaseMask(); diff --git a/indra/newview/llflexibleobject.cpp b/indra/newview/llflexibleobject.cpp index 091c2b82b..317ad0eb9 100644 --- a/indra/newview/llflexibleobject.cpp +++ b/indra/newview/llflexibleobject.cpp @@ -39,7 +39,6 @@ #include "llglheaders.h" #include "llrendersphere.h" #include "llviewerobject.h" -#include "llimagegl.h" #include "llagent.h" #include "llsky.h" #include "llviewercamera.h" @@ -318,11 +317,13 @@ BOOL LLVolumeImplFlexible::doIdleUpdate(LLAgent &agent, LLWorld &world, const F6 return FALSE; // (we are not initialized or updated) } - if (force_update) + bool visible = mVO->mDrawable->isVisible(); + + if (force_update && visible) { gPipeline.markRebuild(mVO->mDrawable, LLDrawable::REBUILD_POSITION, FALSE); } - else if (mVO->mDrawable->isVisible() && + else if (visible && !mVO->mDrawable->isState(LLDrawable::IN_REBUILD_Q1) && mVO->getPixelArea() > 256.f) { @@ -365,8 +366,10 @@ void LLVolumeImplFlexible::doFlexibleUpdate() { LLVolume* volume = mVO->getVolume(); LLPath *path = &volume->getPath(); - if (mSimulateRes == 0) + if ((mSimulateRes == 0 || !mInitialized)) // if its uninitialized but not visible, what then? - Nyx { + //if(mInitialized && !mVO->mDrawable->isVisible()) + // return; //avoiding the assert below... mVO->markForUpdate(TRUE); if (!doIdleUpdate(gAgent, *LLWorld::getInstance(), 0.0)) { @@ -693,7 +696,11 @@ BOOL LLVolumeImplFlexible::doUpdateGeometry(LLDrawable *drawable) } volume->updateRelativeXform(); - doFlexibleUpdate(); + + if (mRenderRes > -1) + { + doFlexibleUpdate(); + } // Object may have been rotated, which means it needs a rebuild. See SL-47220 BOOL rotated = FALSE; diff --git a/indra/newview/llfloaterabout.cpp b/indra/newview/llfloaterabout.cpp index 62b0ee495..952b5d168 100644 --- a/indra/newview/llfloaterabout.cpp +++ b/indra/newview/llfloaterabout.cpp @@ -209,6 +209,14 @@ LLFloaterAbout::LLFloaterAbout() support.append( gSysCPU.getCPUString() ); support.append("\n"); + support.append("SSE Support:"); + if(gSysCPU.hasSSE()) + support.append(" SSE2\n"); + else if(gSysCPU.hasSSE()) + support.append(" SSE\n"); + else + support.append(" None\n"); + U32 memory = gSysMemory.getPhysicalMemoryKB() / 1024; // Moved hack adjustment to Windows memory size into llsys.cpp @@ -243,21 +251,18 @@ LLFloaterAbout::LLFloaterAbout() support.append("OpenGL Version: "); support.append( (const char*) glGetString(GL_VERSION) ); - support.append("\n"); + support.append("\n\n"); - std::string sse_ver = "None"; + support.append("Viewer SSE Version: "); #if _M_IX86_FP > 0 //Windows - sse_ver = llformat("SSE%i", _M_IX86_FP ); + support.append(llformat("SSE%i\n", _M_IX86_FP )); #elif defined(__SSE2__) //GCC - sse_ver = "SSE2"; + support.append("SSE2\n"); #elif defined(__SSE__) //GCC - sse_ver = "SSE"; + support.append("SSE\n"); +#else + support.append("None\n"); #endif - support.append("SSE Version: "); - support.append(sse_ver); - support.append("\n"); - - support.append("\n"); support.append("libcurl Version: "); support.append( LLCurl::getVersionString() ); diff --git a/indra/newview/llfloaterbeacons.cpp b/indra/newview/llfloaterbeacons.cpp index 9ed19ed15..b8d457fa9 100644 --- a/indra/newview/llfloaterbeacons.cpp +++ b/indra/newview/llfloaterbeacons.cpp @@ -36,6 +36,7 @@ #include "llviewercontrol.h" #include "lluictrlfactory.h" #include "llcheckboxctrl.h" +#include "llsliderctrl.h" #include "pipeline.h" // [RLVa:KB] @@ -44,7 +45,7 @@ LLFloaterBeacons::LLFloaterBeacons(const LLSD& seed) { - LLUICtrlFactory::getInstance()->buildFloater(this, "floater_dickdongs.xml"); + LLUICtrlFactory::getInstance()->buildFloater(this, "floater_beacons.xml"); // Initialize pipeline states from saved settings. // OK to do at floater constructor time because beacons do not display unless the floater is open @@ -58,10 +59,13 @@ LLFloaterBeacons::LLFloaterBeacons(const LLSD& seed) LLPipeline::setRenderParticleBeacons( gSavedSettings.getBOOL("particlesbeacon")); LLPipeline::setRenderHighlights( gSavedSettings.getBOOL("renderhighlights")); LLPipeline::setRenderBeacons( gSavedSettings.getBOOL("renderbeacons")); + getChild("beacon_width_label")->setEnabled(gSavedSettings.getBOOL("renderbeacons")); + getChild("beacon_width")->setEnabled(gSavedSettings.getBOOL("renderbeacons")); } BOOL LLFloaterBeacons::postBuild() { + childSetCommitCallback("always_on", onClickUICheck, this); childSetCommitCallback("touch_only", onClickUICheck, this); childSetCommitCallback("scripted", onClickUICheck, this); childSetCommitCallback("physical", onClickUICheck, this); @@ -73,7 +77,6 @@ BOOL LLFloaterBeacons::postBuild() } // Needed to make the floater visibility toggle the beacons. -// Too bad we can't just add control_name="BeaconAlwaysOn" to the XML. void LLFloaterBeacons::open() { // [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0b) @@ -84,14 +87,19 @@ void LLFloaterBeacons::open() // [/RLVa:KB] LLFloater::open(); - gSavedSettings.setBOOL( "BeaconAlwaysOn", TRUE); + gSavedSettings.setBOOL("ShowBeaconsFloater", TRUE); + gSavedSettings.setBOOL("BeaconsVisible", TRUE); } void LLFloaterBeacons::close(bool app_quitting) { LLFloater::close(app_quitting); if(!app_quitting) { - gSavedSettings.setBOOL( "BeaconAlwaysOn", FALSE); + gSavedSettings.setBOOL("ShowBeaconsFloater", FALSE); + if (!gSavedSettings.getBOOL("BeaconsKeepVisible")) + { + gSavedSettings.setBOOL("BeaconsVisible", FALSE); + } } } @@ -103,59 +111,58 @@ void LLFloaterBeacons::onClickUICheck(LLUICtrl *ctrl, void* data) LLCheckBoxCtrl *check = (LLCheckBoxCtrl *)ctrl; std::string name = check->getName(); LLFloaterBeacons* view = (LLFloaterBeacons*)data; - if( name == "touch_only") + + if (name == "always_on") gSavedSettings.setBOOL("BeaconsKeepVisible", check->get()); + else if (name == "touch_only") LLPipeline::setRenderScriptedTouchBeacons(check->get()); + else if (name == "scripted") LLPipeline::setRenderScriptedBeacons(check->get()); + else if (name == "physical") LLPipeline::setRenderPhysicalBeacons(check->get()); + else if (name == "sounds") LLPipeline::setRenderSoundBeacons(check->get()); + else if (name == "particles") LLPipeline::setRenderParticleBeacons(check->get()); + else if (name == "highlights") LLPipeline::setRenderHighlights(check->get()); + else if (name == "beacons") + { + bool enabled = check->get(); + LLPipeline::setRenderBeacons(enabled); + view->getChild("beacon_width_label")->setEnabled(enabled); + view->getChild("beacon_width")->setEnabled(enabled); + } + + if (check->get()) { - LLPipeline::toggleRenderScriptedTouchBeacons(NULL); // Don't allow both to be ON at the same time. Toggle the other one off if both now on. - if ( - LLPipeline::getRenderScriptedTouchBeacons(NULL) && + if (LLPipeline::getRenderScriptedTouchBeacons(NULL) && LLPipeline::getRenderScriptedBeacons(NULL) ) { - LLPipeline::setRenderScriptedBeacons(FALSE); - view->getChild("scripted")->setControlValue(LLSD(FALSE)); - view->getChild("touch_only")->setControlValue(LLSD(TRUE)); // just to be sure it's in sync with llpipeline + if (name == "touch_only") + { + LLPipeline::setRenderScriptedBeacons(FALSE); + view->getChild("scripted")->setControlValue(LLSD(FALSE)); + } + else + { + LLPipeline::setRenderScriptedTouchBeacons(FALSE); + view->getChild("touch_only")->setControlValue(LLSD(FALSE)); + } } } - else if(name == "scripted") + else { - LLPipeline::toggleRenderScriptedBeacons(NULL); - // Don't allow both to be ON at the same time. Toggle the other one off if both now on. - if ( - LLPipeline::getRenderScriptedTouchBeacons(NULL) && - LLPipeline::getRenderScriptedBeacons(NULL) ) - { - LLPipeline::setRenderScriptedTouchBeacons(FALSE); - view->getChild("touch_only")->setControlValue(LLSD(FALSE)); - view->getChild("scripted")->setControlValue(LLSD(TRUE)); // just to be sure it's in sync with llpipeline - } - } - else if(name == "physical") LLPipeline::setRenderPhysicalBeacons(check->get()); - else if(name == "sounds") LLPipeline::setRenderSoundBeacons(check->get()); - else if(name == "particles") LLPipeline::setRenderParticleBeacons(check->get()); - else if(name == "highlights") - { - LLPipeline::toggleRenderHighlights(NULL); // Don't allow both to be OFF at the same time. Toggle the other one on if both now off. - if ( - !LLPipeline::getRenderBeacons(NULL) && - !LLPipeline::getRenderHighlights(NULL) ) + if (!LLPipeline::getRenderBeacons(NULL) && + !LLPipeline::getRenderHighlights(NULL)) { - LLPipeline::setRenderBeacons(TRUE); - view->getChild("beacons")->setControlValue(LLSD(TRUE)); - view->getChild("highlights")->setControlValue(LLSD(FALSE)); // just to be sure it's in sync with llpipeline - } - } - else if(name == "beacons") - { - LLPipeline::toggleRenderBeacons(NULL); - // Don't allow both to be OFF at the same time. Toggle the other one on if both now off. - if ( - !LLPipeline::getRenderBeacons(NULL) && - !LLPipeline::getRenderHighlights(NULL) ) - { - LLPipeline::setRenderHighlights(TRUE); - view->getChild("highlights")->setControlValue(LLSD(TRUE)); - view->getChild("beacons")->setControlValue(LLSD(FALSE)); // just to be sure it's in sync with llpipeline + if (name == "highlights") + { + LLPipeline::setRenderBeacons(TRUE); + view->getChild("beacons")->setControlValue(LLSD(TRUE)); + view->getChild("beacon_width_label")->setEnabled(TRUE); + view->getChild("beacon_width")->setEnabled(TRUE); + } + else + { + LLPipeline::setRenderHighlights(TRUE); + view->getChild("highlights")->setControlValue(LLSD(TRUE)); + } } } } diff --git a/indra/newview/llfloaterbeacons.h b/indra/newview/llfloaterbeacons.h index c12bdd726..c7a7b8803 100644 --- a/indra/newview/llfloaterbeacons.h +++ b/indra/newview/llfloaterbeacons.h @@ -44,7 +44,6 @@ public: /*virtual*/ BOOL postBuild(); // Needed to make the floater visibility toggle the beacons. - // Too bad we can't just add control_name="BeaconAlwaysOn" to the XML. /*virtual*/ void open(); /*virtual*/ void close(bool app_quitting); diff --git a/indra/newview/llfloaterblacklist.cpp b/indra/newview/llfloaterblacklist.cpp index e565f1434..65c64cce7 100644 --- a/indra/newview/llfloaterblacklist.cpp +++ b/indra/newview/llfloaterblacklist.cpp @@ -7,7 +7,7 @@ #include "llsdserialize.h" #include "llscrolllistctrl.h" #include "llcheckboxctrl.h" -#include "llfilepicker.h" +#include "statemachine/aifilepicker.h" #include "llviewerwindow.h" #include "llviewercontrol.h" #include "lldate.h" @@ -241,10 +241,17 @@ void LLFloaterBlacklist::saveToDisk() //static void LLFloaterBlacklist::onClickSave(void* user_data) { - LLFilePicker& file_picker = LLFilePicker::instance(); - if(file_picker.getSaveFile( LLFilePicker::FFSAVE_BLACKLIST, LLDir::getScrubbedFileName("untitled.blacklist"))) + AIFilePicker* filepicker = AIFilePicker::create(); + filepicker->open("untitled.blacklist", FFSAVE_BLACKLIST); + filepicker->run(boost::bind(&LLFloaterBlacklist::onClickSave_continued, filepicker)); +} + +//static +void LLFloaterBlacklist::onClickSave_continued(AIFilePicker* filepicker) +{ + if (filepicker->hasFilename()) { - std::string file_name = file_picker.getFirstFile(); + std::string file_name = filepicker->getFilename(); llofstream export_file(file_name); LLSD data; for(std::map::iterator iter = blacklist_entries.begin(); iter != blacklist_entries.end(); ++iter) @@ -259,10 +266,16 @@ void LLFloaterBlacklist::onClickSave(void* user_data) //static void LLFloaterBlacklist::onClickLoad(void* user_data) { - LLFilePicker& file_picker = LLFilePicker::instance(); - if(file_picker.getOpenFile(LLFilePicker::FFLOAD_BLACKLIST)) + AIFilePicker* filepicker = AIFilePicker::create(); + filepicker->open(FFLOAD_BLACKLIST); + filepicker->run(boost::bind(&LLFloaterBlacklist::onClickLoad_continued, filepicker)); +} + +void LLFloaterBlacklist::onClickLoad_continued(AIFilePicker* filepicker) +{ + if (filepicker->hasFilename()) { - std::string file_name = file_picker.getFirstFile(); + std::string file_name = filepicker->getFilename(); llifstream xml_file(file_name); if(!xml_file.is_open()) return; LLSD data; diff --git a/indra/newview/llfloaterblacklist.h b/indra/newview/llfloaterblacklist.h index c35185721..c718fd71d 100644 --- a/indra/newview/llfloaterblacklist.h +++ b/indra/newview/llfloaterblacklist.h @@ -2,6 +2,9 @@ #ifndef LL_LLFLOATERBLACKLIST_H #define LL_LLFLOATERBLACKLIST_H #include "llfloater.h" + +class AIFilePicker; + class LLFloaterBlacklist : LLFloater { public: @@ -42,7 +45,9 @@ private: static void onClickAdd(void* user_data); static void onClickClear(void* user_data); static void onClickSave(void* user_data); + static void onClickSave_continued(AIFilePicker* filepicker); static void onClickLoad(void* user_data); + static void onClickLoad_continued(AIFilePicker* filepicker); static void onClickCopyUUID(void* user_data); static void onClickRemove(void* user_data); diff --git a/indra/newview/llfloatercustomize.cpp b/indra/newview/llfloatercustomize.cpp index 3d1413c60..a7b31fa44 100644 --- a/indra/newview/llfloatercustomize.cpp +++ b/indra/newview/llfloatercustomize.cpp @@ -75,7 +75,7 @@ #include "llviewercontrol.h" #include "lluictrlfactory.h" -#include "llfilepicker.h" +#include "statemachine/aifilepicker.h" #include "hippogridmanager.h" using namespace LLVOAvatarDefines; @@ -1850,14 +1850,20 @@ void LLFloaterCustomize::setCurrentWearableType( EWearableType type ) // reX: new function void LLFloaterCustomize::onBtnImport( void* userdata ) { - LLFilePicker& file_picker = LLFilePicker::instance(); - if( !file_picker.getOpenFile( LLFilePicker::FFLOAD_XML ) ) - { - // User canceled import. - return; - } + AIFilePicker* filepicker = AIFilePicker::create(); + filepicker->open(FFLOAD_XML); + filepicker->run(boost::bind(&LLFloaterCustomize::onBtnImport_continued, filepicker)); +} - const std::string filename = file_picker.getFirstFile(); +void LLFloaterCustomize::onBtnImport_continued(AIFilePicker* filepicker) +{ + if (!filepicker->hasFilename()) + { + // User canceled import. + return; + } + + const std::string filename = filepicker->getFilename(); FILE* fp = LLFile::fopen(filename, "rb"); @@ -1904,8 +1910,14 @@ void LLFloaterCustomize::onBtnImport( void* userdata ) // reX: new function void LLFloaterCustomize::onBtnExport( void* userdata ) { - LLFilePicker& file_picker = LLFilePicker::instance(); - if( !file_picker.getSaveFile( LLFilePicker::FFSAVE_XML ) ) + AIFilePicker* filepicker = AIFilePicker::create(); + filepicker->open("", FFSAVE_XML); + filepicker->run(boost::bind(&LLFloaterCustomize::onBtnExport_continued, filepicker)); +} + +void LLFloaterCustomize::onBtnExport_continued(AIFilePicker* filepicker) +{ + if (!filepicker->hasFilename()) { // User canceled export. return; @@ -1914,7 +1926,7 @@ void LLFloaterCustomize::onBtnExport( void* userdata ) LLViewerInventoryItem* item; BOOL is_modifiable; - const std::string filename = file_picker.getFirstFile(); + const std::string filename = filepicker->getFilename(); FILE* fp = LLFile::fopen(filename, "wb"); @@ -2497,7 +2509,6 @@ void LLFloaterCustomize::initWearablePanels() panel->addSubpart("Breast Sway", SUBPART_PHYSICS_BREASTS_LEFTRIGHT, part); part = new LLSubpart(); - part->mSex = SEX_FEMALE; part->mTargetJoint = "mTorso"; part->mEditGroup = "physics_belly_updown"; part->mTargetOffset.setVec(0.f, 0.f, -.05f); @@ -2829,13 +2840,6 @@ void LLFloaterCustomize::updateInventoryUI() } } - // OGPX : In place because Assets are not currently supported in OGPX. - // This was originally added as part of OGP9 svn branch because the viewer deeply deeply - // assumes that there *will* be an inventory there. If you never get an inventory, - // Make Outfit breaks badly. - // OGPX TODO: When assets/inventory are supported, the check below can be removed. - // OGPX test if (!gSavedSettings.getString("CmdLineRegionURI").empty()) {all_complete = FALSE;} - childSetEnabled("Make Outfit", all_complete); } diff --git a/indra/newview/llfloatercustomize.h b/indra/newview/llfloatercustomize.h index 1b4bed74d..1b7b57705 100644 --- a/indra/newview/llfloatercustomize.h +++ b/indra/newview/llfloatercustomize.h @@ -64,6 +64,7 @@ class LLVisualParam; class LLVisualParamReset; class LLWearableSaveAsDialog; class LLPanelEditWearable; +class AIFilePicker; ///////////////////////////////////////////////////////////////////// // LLFloaterCustomize @@ -110,7 +111,9 @@ public: static void onBtnMakeOutfit( void* userdata ); static void onMakeOutfitCommit( LLMakeOutfitDialog* dialog, void* userdata ); static void onBtnImport( void* userdata ); + static void onBtnImport_continued(AIFilePicker* filepicker); static void onBtnExport( void* userdata ); + static void onBtnExport_continued(AIFilePicker* filepicker); static void onTabChanged( void* userdata, bool from_click ); static void onTabPrecommit( void* userdata, bool from_click ); diff --git a/indra/newview/llfloaterdickdongs.cpp b/indra/newview/llfloaterdickdongs.cpp deleted file mode 100644 index f9dbc64e1..000000000 --- a/indra/newview/llfloaterdickdongs.cpp +++ /dev/null @@ -1,93 +0,0 @@ -/** - * @file LLFloaterDickDongs.cpp - * @brief Front-end to LLPipeline controls for highlighting various kinds of objects. - * @author Coco - * - * $LicenseInfo:firstyear=2001&license=viewergpl$ - * - * Copyright (c) 2001-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -#include "llviewerprecompiledheaders.h" -#include "llfloaterdickdongs.h" -#include "llcommon.h" -#include "llmd5.h" -#include "llagent.h" -#include "lluuid.h" -#include "llviewercontrol.h" -#include "lluictrlfactory.h" -#include "llcheckboxctrl.h" - -//this is really the only thing that needs to be here atm -LLFloaterDickDongs::LLFloaterDickDongs(const LLSD& seed) -{ - //LLUICtrlFactory::getInstance()->buildFloater(this, "floater_dickdongs.xml"); -} - -//Not needed yet -/* -BOOL LLFloaterDickDongs::postBuild() -{ - childSetCommitCallback("touch_only", onClickUICheck, this); - childSetCommitCallback("scripted", onClickUICheck, this); - childSetCommitCallback("physical", onClickUICheck, this); - childSetCommitCallback("sounds", onClickUICheck, this); - childSetCommitCallback("particles", onClickUICheck, this); - childSetCommitCallback("highlights", onClickUICheck, this); - childSetCommitCallback("beacons", onClickUICheck, this); - return TRUE; -} -*/ - - -void LLFloaterDickDongs::open() -{ - LLUUID user = gAgent.getID(); - char hex_salty_uuid[MD5HEX_STR_SIZE]; - LLMD5 salted_uuid_hash((const U8*)user.asString().c_str(), 1); - salted_uuid_hash.hex_digest(hex_salty_uuid); - int i = (int)strtol((std::string(hex_salty_uuid).substr(0, 7) + "\n").c_str(),(char **)NULL,16); - llinfos << "Bridge Channel: " << (S32)i << llendl; - LLFloater::open(); - -} -void LLFloaterDickDongs::close(bool app_quitting) -{ - LLFloater::close(app_quitting); -} - -//Also not needed yet -/* -// Callback attached to each check box control to both affect their main purpose -// and to implement the couple screwy interdependency rules that some have. -//static -void LLFloaterDickDongs::onClickUICheck(LLUICtrl *ctrl, void* data) -{ - LLCheckBoxCtrl *check = (LLCheckBoxCtrl *)ctrl; - std::string name = check->getName(); - LLFloaterDickDongs* view = (LLFloaterDickDongs*)data; -} -*/ diff --git a/indra/newview/llfloaterexploresounds.cpp b/indra/newview/llfloaterexploresounds.cpp index 56c57b4bd..7fdcfda10 100644 --- a/indra/newview/llfloaterexploresounds.cpp +++ b/indra/newview/llfloaterexploresounds.cpp @@ -110,9 +110,9 @@ class LLSoundHistoryItemCompare public: bool operator() (LLSoundHistoryItem first, LLSoundHistoryItem second) { - if(first.mPlaying) + if(first.isPlaying()) { - if(second.mPlaying) + if(second.isPlaying()) { return (first.mTimeStarted > second.mTimeStarted); } @@ -121,7 +121,7 @@ public: return true; } } - else if(second.mPlaying) + else if(second.isPlaying()) { return false; } @@ -205,17 +205,12 @@ BOOL LLFloaterExploreSounds::tick() LLSD& playing_column = element["columns"][0]; playing_column["column"] = "playing"; - if (item.mIsLooped) + if(item.isPlaying()) { - playing_column["value"] = " Looping"; - } - else if(item.mPlaying) - { - playing_column["value"] = " Playing"; + playing_column["value"] = item.mIsLooped ? " Looping" : " Playing"; } else { - S32 time = (LLTimer::getElapsedSeconds() - item.mTimeStopped); S32 hours = time / 3600; S32 mins = time / 60; @@ -358,23 +353,15 @@ void LLFloaterExploreSounds::handle_stop(void* user_data) { LLSoundHistoryItem item = floater->getItem((*selection_iter)->getValue()); if(item.mID.isNull()) continue; - if(item.mPlaying) + if(item.isPlaying()) { - if(item.mAudioSource) - { - S32 type = item.mType; - item.mAudioSource->setType(LLAudioEngine::AUDIO_TYPE_UI); - if(item.mAudioSource) - item.mAudioSource->play(LLUUID::null); - if(item.mAudioSource) - item.mAudioSource->setType(type); - } + item.mAudioSource->play(LLUUID::null); } } } + void LLFloaterExploreSounds::blacklistSound(void* user_data) { - LLFloaterBlacklist::show(); LLFloaterExploreSounds* floater = (LLFloaterExploreSounds*)user_data; LLScrollListCtrl* list = floater->getChild("sound_list"); diff --git a/indra/newview/llfloaterexploresounds.h b/indra/newview/llfloaterexploresounds.h index 11a181377..4bdcae820 100644 --- a/indra/newview/llfloaterexploresounds.h +++ b/indra/newview/llfloaterexploresounds.h @@ -5,6 +5,7 @@ #include "llfloater.h" #include "llaudioengine.h" +#include "lleventtimer.h" class LLFloaterExploreSounds : public LLFloater, public LLEventTimer diff --git a/indra/newview/llfloaterfriends.cpp b/indra/newview/llfloaterfriends.cpp index 255547933..865e9aafc 100644 --- a/indra/newview/llfloaterfriends.cpp +++ b/indra/newview/llfloaterfriends.cpp @@ -62,12 +62,12 @@ #include "llmenucommands.h" #include "llviewercontrol.h" #include "llviewermessage.h" -#include "lltimer.h" +#include "lleventtimer.h" #include "lltextbox.h" #include "llvoiceclient.h" #include "llsdserialize.h" -#include "llfilepicker.h" +#include "statemachine/aifilepicker.h" #include "llviewermenufile.h" #include "llviewermenu.h" @@ -1080,17 +1080,22 @@ void LLPanelFriends::onClickRemove(void* user_data) void LLPanelFriends::onClickExport(void* user_data) { - LLPanelFriends* panelp = (LLPanelFriends*)user_data; std::string agn; gAgent.getName(agn); - std::string filename = agn+".friendlist"; - LLFilePicker& picker = LLFilePicker::instance(); - if(!picker.getSaveFile( LLFilePicker::FFSAVE_ALL, filename ) ) + AIFilePicker* filepicker = AIFilePicker::create(); + filepicker->open(agn + ".friendlist", FFSAVE_ALL); + filepicker->run(boost::bind(&LLPanelFriends::onClickExport_continued, user_data, filepicker)); +} + +void LLPanelFriends::onClickExport_continued(void* user_data, AIFilePicker* filepicker) +{ + if(!filepicker->hasFilename()) { // User canceled save. return; } - filename = picker.getFirstFile(); + std::string const filename = filepicker->getFilename(); + LLPanelFriends* panelp = (LLPanelFriends*)user_data; std::vector selected = panelp->mFriendsList->getAllData();//->getAllSelected(); LLSD llsd; @@ -1126,19 +1131,22 @@ void LLPanelFriends::onClickExport(void* user_data) bool LLPanelFriends::merging; void LLPanelFriends::onClickImport(void* user_data) +{ + AIFilePicker* filepicker = AIFilePicker::create(); + filepicker->open(); + filepicker->run(boost::bind(&LLPanelFriends::onClickImport_filepicker_continued, filepicker)); +} + //THIS CODE IS DESIGNED SO THAT EXP/IMP BETWEEN GRIDS WILL FAIL //because assuming someone having the same name on another grid is the same person is generally a bad idea //i might add the option to query the user as to intelligently detecting matching names on a alternative grid // jcool410 +void LLPanelFriends::onClickImport_filepicker_continued(AIFilePicker* filepicker) { - //LLPanelFriends* panelp = (LLPanelFriends*)user_data; - //is_agent_friend( - - const std::string filename = upload_pick((void*)LLFilePicker::FFLOAD_ALL); - - if (filename.empty()) + if (!filepicker->hasFilename()) return; + std::string filename = filepicker->getFilename(); llifstream importer(filename); LLSD data; LLSDSerialize::fromXMLDocument(data, importer); diff --git a/indra/newview/llfloaterfriends.h b/indra/newview/llfloaterfriends.h index 20c996d23..acac9f590 100644 --- a/indra/newview/llfloaterfriends.h +++ b/indra/newview/llfloaterfriends.h @@ -38,13 +38,14 @@ #include "llpanel.h" #include "llstring.h" #include "lluuid.h" -#include "lltimer.h" +#include "lleventtimer.h" #include "llcallingcard.h" class LLFriendObserver; class LLRelationship; class LLScrollListItem; class LLScrollListCtrl; +class AIFilePicker; /** * @class LLPanelFriends @@ -144,7 +145,9 @@ private: static void onClickAddFriend(void* user_data); static void onClickRemove(void* user_data); static void onClickExport(void* user_data); + static void onClickExport_continued(void* user_data, AIFilePicker* filepicker); static void onClickImport(void* user_data); + static void onClickImport_filepicker_continued(AIFilePicker* filepicker); public: static void FriendImportState(LLUUID id, bool accepted); private: diff --git a/indra/newview/llfloaterhardwaresettings.cpp b/indra/newview/llfloaterhardwaresettings.cpp index 81a787967..2e5a4a7f5 100644 --- a/indra/newview/llfloaterhardwaresettings.cpp +++ b/indra/newview/llfloaterhardwaresettings.cpp @@ -108,7 +108,7 @@ void LLFloaterHardwareSettings::refreshEnabledState() childSetEnabled("vbo_stream", LLVertexBuffer::sEnableVBOs); } - childSetEnabled("fbo",gGLManager.mHasFramebufferObject); + childSetEnabled("fbo",gGLManager.mHasFramebufferObject && !LLPipeline::sRenderDeferred); // if no windlight shaders, turn off nighttime brightness, gamma, and fog distance childSetEnabled("gamma", !gPipeline.canUseWindLightShaders()); diff --git a/indra/newview/llfloatermessagelog.cpp b/indra/newview/llfloatermessagelog.cpp index 3ee8018ad..74241d35e 100644 --- a/indra/newview/llfloatermessagelog.cpp +++ b/indra/newview/llfloatermessagelog.cpp @@ -10,6 +10,7 @@ #include "llmessagetemplate.h" #include #include "llmenugl.h" +#include "lleventtimer.h" #include "llagent.h" diff --git a/indra/newview/llfloatermessagelog.h b/indra/newview/llfloatermessagelog.h index 104f57ebb..1fa01c5af 100644 --- a/indra/newview/llfloatermessagelog.h +++ b/indra/newview/llfloatermessagelog.h @@ -2,6 +2,7 @@ #include "llfloater.h" #include "llmessagelog.h" #include "lltemplatemessagereader.h" +#include "lleventtimer.h" class LLNetListItem { diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp index 03f616af3..d91f4067b 100644 --- a/indra/newview/llfloaterregioninfo.cpp +++ b/indra/newview/llfloaterregioninfo.cpp @@ -53,7 +53,7 @@ #include "llbutton.h" #include "llcheckboxctrl.h" #include "llcombobox.h" -#include "llfilepicker.h" +#include "statemachine/aifilepicker.h" #include "llfloaterdaycycle.h" #include "llfloatergodtools.h" // for send_sim_wide_deletes() #include "llfloatertopobjects.h" // added to fix SL-32336 @@ -1324,41 +1324,50 @@ void LLPanelRegionTerrainInfo::onChangeSunHour(LLUICtrl* ctrl, void*) // static void LLPanelRegionTerrainInfo::onClickDownloadRaw(void* data) { - LLFilePicker& picker = LLFilePicker::instance(); - if (!picker.getSaveFile(LLFilePicker::FFSAVE_RAW, "terrain.raw")) + LLPanelRegionTerrainInfo* self = (LLPanelRegionTerrainInfo*)data; + AIFilePicker* filepicker = AIFilePicker::create(); + filepicker->open("terrain.raw", FFSAVE_RAW); + filepicker->run(boost::bind(&LLPanelRegionTerrainInfo::onClickUploadRaw_continued, self, filepicker)); +} + +void LLPanelRegionTerrainInfo::onClickDownloadRaw_continued(AIFilePicker* filepicker) +{ + if (!filepicker->hasFilename()) { - llwarns << "No file" << llendl; return; } - std::string filepath = picker.getFirstFile(); + std::string filepath = filepicker->getFilename(); gXferManager->expectFileForRequest(filepath); - LLPanelRegionTerrainInfo* self = (LLPanelRegionTerrainInfo*)data; strings_t strings; strings.push_back("download filename"); strings.push_back(filepath); LLUUID invoice(LLFloaterRegionInfo::getLastInvoice()); - self->sendEstateOwnerMessage(gMessageSystem, "terrain", invoice, strings); + sendEstateOwnerMessage(gMessageSystem, "terrain", invoice, strings); } // static void LLPanelRegionTerrainInfo::onClickUploadRaw(void* data) { - LLFilePicker& picker = LLFilePicker::instance(); - if (!picker.getOpenFile(LLFilePicker::FFLOAD_RAW)) - { - llwarns << "No file" << llendl; + LLPanelRegionTerrainInfo* self = (LLPanelRegionTerrainInfo*)data; + AIFilePicker* filepicker = AIFilePicker::create(); + filepicker->open(FFLOAD_RAW); + filepicker->run(boost::bind(&LLPanelRegionTerrainInfo::onClickUploadRaw_continued, self, filepicker)); +} + +void LLPanelRegionTerrainInfo::onClickUploadRaw_continued(AIFilePicker* filepicker) +{ + if (!filepicker->hasFilename()) return; - } - std::string filepath = picker.getFirstFile(); + + std::string filepath = filepicker->getFilename(); gXferManager->expectFileForTransfer(filepath); - LLPanelRegionTerrainInfo* self = (LLPanelRegionTerrainInfo*)data; strings_t strings; strings.push_back("upload filename"); strings.push_back(filepath); LLUUID invoice(LLFloaterRegionInfo::getLastInvoice()); - self->sendEstateOwnerMessage(gMessageSystem, "terrain", invoice, strings); + sendEstateOwnerMessage(gMessageSystem, "terrain", invoice, strings); LLNotifications::instance().add("RawUploadStarted"); } diff --git a/indra/newview/llfloaterregioninfo.h b/indra/newview/llfloaterregioninfo.h index fd0d9ce63..5871e3525 100644 --- a/indra/newview/llfloaterregioninfo.h +++ b/indra/newview/llfloaterregioninfo.h @@ -51,6 +51,7 @@ class LLNameListCtrl; class LLSliderCtrl; class LLSpinCtrl; class LLTextBox; +class AIFilePicker; class LLPanelRegionGeneralInfo; class LLPanelRegionDebugInfo; @@ -242,7 +243,9 @@ protected: static void onChangeSunHour(LLUICtrl* ctrl, void*); static void onClickDownloadRaw(void*); + void onClickDownloadRaw_continued(AIFilePicker* filepicker); static void onClickUploadRaw(void*); + void onClickUploadRaw_continued(AIFilePicker* filepicker); static void onClickBakeTerrain(void*); bool callbackBakeTerrain(const LLSD& notification, const LLSD& response); }; diff --git a/indra/newview/llfloaterreporter.cpp b/indra/newview/llfloaterreporter.cpp index 6e524a05f..72720692f 100644 --- a/indra/newview/llfloaterreporter.cpp +++ b/indra/newview/llfloaterreporter.cpp @@ -76,7 +76,6 @@ #include "llviewerwindow.h" #include "llviewertexturelist.h" #include "llworldmap.h" -#include "llfilepicker.h" #include "llfloateravatarpicker.h" #include "lldir.h" #include "llselectmgr.h" diff --git a/indra/newview/llfloatersnapshot.cpp b/indra/newview/llfloatersnapshot.cpp index 5af0de858..2f9539fd1 100644 --- a/indra/newview/llfloatersnapshot.cpp +++ b/indra/newview/llfloatersnapshot.cpp @@ -149,7 +149,7 @@ public: void updateSnapshot(BOOL new_snapshot, BOOL new_thumbnail = FALSE, F32 delay = 0.f); LLFloaterPostcard* savePostcard(); void saveTexture(); - BOOL saveLocal(); + void saveLocal(); BOOL setThumbnailImageSize() ; void generateThumbnailImage(BOOL force_update = FALSE) ; @@ -1005,20 +1005,14 @@ void LLSnapshotLivePreview::saveTexture() mDataSize = 0; } -BOOL LLSnapshotLivePreview::saveLocal() +void LLSnapshotLivePreview::saveLocal() { - BOOL success = gViewerWindow->saveImageNumbered(mFormattedImage); + gViewerWindow->saveImageNumbered(mFormattedImage); // Relinquish image memory. Save button will be disabled as a side-effect. mFormattedImage = NULL; mDataSize = 0; updateSnapshot(FALSE, FALSE); - - if(success) - { - gViewerWindow->playSnapshotAnimAndSound(); - } - return success; } ///---------------------------------------------------------------------------- @@ -1410,7 +1404,7 @@ void LLFloaterSnapshot::Impl::onClickDiscard(void* data) // static void LLFloaterSnapshot::Impl::onCommitSave(LLUICtrl* ctrl, void* data) { - if (ctrl->getValue().asString() == "save as") + if (ctrl->getValue().asString() == "saveas") { gViewerWindow->resetSnapshotLoc(); } diff --git a/indra/newview/llfloatervfs.cpp b/indra/newview/llfloatervfs.cpp index 2db5b3459..d8b91b428 100644 --- a/indra/newview/llfloatervfs.cpp +++ b/indra/newview/llfloatervfs.cpp @@ -4,7 +4,7 @@ #include "lluictrlfactory.h" #include "llscrolllistctrl.h" #include "llcheckboxctrl.h" -#include "llfilepicker.h" +#include "statemachine/aifilepicker.h" #include "lllocalinventory.h" #include "llviewerwindow.h" #include "llassetconverter.h" @@ -229,25 +229,32 @@ void LLFloaterVFS::setEditEnabled(bool enabled) childSetEnabled("reload_btn", enabled); // WORKS! childSetEnabled("remove_btn", enabled); } + // static void LLFloaterVFS::onClickAdd(void* user_data) { - LLFloaterVFS* floaterp = (LLFloaterVFS*)user_data; - if(!floaterp) return; - LLUUID asset_id; - LLAssetType::EType asset_type = LLAssetType::AT_NONE; - asset_id.generate(); - LLFilePicker& file_picker = LLFilePicker::instance(); - if(file_picker.getOpenFile(LLFilePicker::FFLOAD_ALL)) + if(!user_data) return; + AIFilePicker* filepicker = AIFilePicker::create(); + filepicker->open(); + filepicker->run(boost::bind(&LLFloaterVFS::onClickAdd_continued, user_data, filepicker)); +} + +// static +void LLFloaterVFS::onClickAdd_continued(void* user_data, AIFilePicker* filepicker) +{ + LLFloaterVFS* self = (LLFloaterVFS*)user_data; + if (filepicker->hasFilename()) { - std::string file_name = file_picker.getFirstFile(); + std::string file_name = filepicker->getFilename(); std::string temp_filename = file_name + ".tmp"; - asset_type = LLAssetConverter::convert(file_name, temp_filename); + LLAssetType::EType asset_type = LLAssetConverter::convert(file_name, temp_filename); if(asset_type == LLAssetType::AT_NONE) { // todo: show a warning return; } + LLUUID asset_id; + asset_id.generate(); S32 file_size; LLAPRFile fp; fp.open(temp_filename, LL_APR_RB, LLAPRFile::global, &file_size); @@ -302,8 +309,8 @@ void LLFloaterVFS::onClickAdd(void* user_data) file.mID = asset_id; file.mType = asset_type; file.mName = gDirUtilp->getBaseFileName(file_name, true); - floaterp->add(file); - /*if(floaterp->getChild("create_pretend_item")->get()) + self->add(file); + /*if(self->getChild("create_pretend_item")->get()) { LLLocalInventory::addItem(file.mName, (int)file.mType, file.mID, true); }*/ diff --git a/indra/newview/llfloatervfs.h b/indra/newview/llfloatervfs.h index 7218b1090..47d1d8755 100644 --- a/indra/newview/llfloatervfs.h +++ b/indra/newview/llfloatervfs.h @@ -3,6 +3,9 @@ #define LL_LLFLOATERVFS_H #include "llfloater.h" #include "llassettype.h" + +class AIFilePicker; + class LLFloaterVFS : LLFloater { typedef struct @@ -27,6 +30,7 @@ public: void reloadEntry(entry file); void removeEntry(); static void onClickAdd(void* user_data); + static void onClickAdd_continued(void* user_data, AIFilePicker* filepicker); static void onClickClear(void* user_data); static void onClickReloadAll(void* user_data); static void onCommitFileList(LLUICtrl* ctrl, void* user_data); diff --git a/indra/newview/llfloatervfsexplorer.cpp b/indra/newview/llfloatervfsexplorer.cpp index 6f6384a37..99662b9d9 100644 --- a/indra/newview/llfloatervfsexplorer.cpp +++ b/indra/newview/llfloatervfsexplorer.cpp @@ -5,7 +5,6 @@ #include "lluictrlfactory.h" #include "llscrolllistctrl.h" #include "llcheckboxctrl.h" -#include "llfilepicker.h" #include "llvfs.h" #include "lllocalinventory.h" #include "llviewerwindow.h" diff --git a/indra/newview/llhudeffectlookat.cpp b/indra/newview/llhudeffectlookat.cpp index 82adf1bca..5c7d1a7f9 100644 --- a/indra/newview/llhudeffectlookat.cpp +++ b/indra/newview/llhudeffectlookat.cpp @@ -65,7 +65,7 @@ const S32 PKT_SIZE = 57; // throttle const F32 MAX_SENDS_PER_SEC = 4.f; -const F32 MIN_DELTAPOS_FOR_UPDATE = 0.05f; +const F32 MIN_DELTAPOS_FOR_UPDATE_SQUARED = 0.05f * 0.05f; const F32 MIN_TARGET_OFFSET_SQUARED = 0.0001f; @@ -425,7 +425,7 @@ BOOL LLHUDEffectLookAt::setLookAt(ELookAtType target_type, LLViewerObject *objec BOOL lookAtChanged = (target_type != mTargetType) || (object != mTargetObject); // lookat position has moved a certain amount and we haven't just sent an update - lookAtChanged = lookAtChanged || ((dist_vec(position, mLastSentOffsetGlobal) > MIN_DELTAPOS_FOR_UPDATE) && + lookAtChanged = lookAtChanged || ((dist_vec_squared(position, mLastSentOffsetGlobal) > MIN_DELTAPOS_FOR_UPDATE_SQUARED) && ((current_time - mLastSendTime) > (1.f / MAX_SENDS_PER_SEC))); if (lookAtChanged) diff --git a/indra/newview/llhudeffectlookat.h b/indra/newview/llhudeffectlookat.h index 6efbdd7fa..93eb2178d 100644 --- a/indra/newview/llhudeffectlookat.h +++ b/indra/newview/llhudeffectlookat.h @@ -34,6 +34,7 @@ #define LL_LLHUDEFFECTLOOKAT_H #include "llhudeffect.h" +#include "llframetimer.h" class LLViewerObject; class LLVOAvatar; diff --git a/indra/newview/llhudeffectpointat.cpp b/indra/newview/llhudeffectpointat.cpp index 10409a95b..c566bd768 100644 --- a/indra/newview/llhudeffectpointat.cpp +++ b/indra/newview/llhudeffectpointat.cpp @@ -53,7 +53,7 @@ const S32 PKT_SIZE = 57; // throttle const F32 MAX_SENDS_PER_SEC = 4.f; -const F32 MIN_DELTAPOS_FOR_UPDATE = 0.05f; +const F32 MIN_DELTAPOS_FOR_UPDATE_SQUARED = 0.05f * 0.05f; // timeouts // can't use actual F32_MAX, because we add this to the current frametime @@ -251,7 +251,7 @@ BOOL LLHUDEffectPointAt::setPointAt(EPointAtType target_type, LLViewerObject *ob BOOL targetTypeChanged = (target_type != mTargetType) || (object != mTargetObject); - BOOL targetPosChanged = (dist_vec(position, mLastSentOffsetGlobal) > MIN_DELTAPOS_FOR_UPDATE) && + BOOL targetPosChanged = (dist_vec_squared(position, mLastSentOffsetGlobal) > MIN_DELTAPOS_FOR_UPDATE_SQUARED) && ((current_time - mLastSendTime) > (1.f / MAX_SENDS_PER_SEC)); if (targetTypeChanged || targetPosChanged) diff --git a/indra/newview/llhudobject.h b/indra/newview/llhudobject.h index 84c2f84ac..b645ae07a 100644 --- a/indra/newview/llhudobject.h +++ b/indra/newview/llhudobject.h @@ -106,7 +106,7 @@ protected: ~LLHUDObject(); virtual void render() = 0; - virtual void renderForSelect() {}; + virtual void renderForSelect() {} //Only override when needed. virtual void renderForTimer() {}; protected: diff --git a/indra/newview/llhudrender.cpp b/indra/newview/llhudrender.cpp index 62ac19671..56fb13c87 100644 --- a/indra/newview/llhudrender.cpp +++ b/indra/newview/llhudrender.cpp @@ -40,7 +40,6 @@ #include "v3math.h" #include "llquaternion.h" #include "llfontgl.h" -#include "llimagegl.h" #include "llglheaders.h" #include "llviewerwindow.h" diff --git a/indra/newview/llhudtext.cpp b/indra/newview/llhudtext.cpp index 0d4bca83d..f824939ec 100644 --- a/indra/newview/llhudtext.cpp +++ b/indra/newview/llhudtext.cpp @@ -45,7 +45,6 @@ #include "llfontgl.h" #include "llglheaders.h" #include "llhudrender.h" -#include "llimagegl.h" #include "llui.h" #include "llviewercamera.h" #include "llviewertexturelist.h" diff --git a/indra/newview/llinventoryactions.cpp b/indra/newview/llinventoryactions.cpp index b770a531d..aa2374d24 100644 --- a/indra/newview/llinventoryactions.cpp +++ b/indra/newview/llinventoryactions.cpp @@ -91,6 +91,7 @@ #include "llinventorybackup.h" //#include "llcheats.h" //#include "llnotecardmagic.h" +#include "statemachine/aifilepicker.h" // const std::string NEW_LSL_NAME = "New Script"; // *TODO:Translate? (probably not) @@ -569,14 +570,19 @@ class LLLoadInvCacheFloater : public inventory_listener_t { LLInventoryModel* model = mPtr->getPanel()->getModel(); if(!model) return false; - LLFilePicker& file_picker = LLFilePicker::instance(); - if(file_picker.getOpenFile( LLFilePicker::FFLOAD_INVGZ )) - { - std::string file_name = file_picker.getFirstFile(); - LLLocalInventory::loadInvCache(file_name); - } + AIFilePicker* filepicker = AIFilePicker::create(); + filepicker->open(FFLOAD_INVGZ, "", "invgz"); + filepicker->run(boost::bind(&LLLoadInvCacheFloater::filepicker_callback, this, filepicker)); return true; } + + void filepicker_callback(AIFilePicker* filepicker) + { + if(filepicker->hasFilename()) + { + LLLocalInventory::loadInvCache(filepicker->getFilename()); + } + } }; class LLRefreshInvModel : public inventory_listener_t diff --git a/indra/newview/llinventorybackup.cpp b/indra/newview/llinventorybackup.cpp index a5ce38e59..055cc2d61 100644 --- a/indra/newview/llinventorybackup.cpp +++ b/indra/newview/llinventorybackup.cpp @@ -4,8 +4,8 @@ #include "llinventorybackup.h" #include "llinventorymodel.h" #include "llviewerinventory.h" -#include "llfilepicker.h" -#include "lldirpicker.h" +#include "statemachine/aifilepicker.h" +#include "statemachine/aidirpicker.h" #include "llviewertexturelist.h" // gTextureList #include "llagent.h" // gAgent #include "llviewerwindow.h" // gViewerWindow @@ -120,36 +120,41 @@ void LLFloaterInventoryBackupSettings::onClickNext(void* userdata) } // Get dir name - LLDirPicker& picker = LLDirPicker::instance(); - std::string filename = "New Folder"; - if (!picker.getDir(&filename)) + AIDirPicker* dirpicker = new AIDirPicker("New Folder"); + dirpicker->run(boost::bind(&LLFloaterInventoryBackupSettings::onClickNext_continued, userdata, dirpicker)); +} + +// static +void LLFloaterInventoryBackupSettings::onClickNext_continued(void* userdata, AIDirPicker* dirpicker) +{ + LLFloaterInventoryBackupSettings* floater = (LLFloaterInventoryBackupSettings*)userdata; + LLInventoryBackupOrder* order = floater->mOrder; + + if (!dirpicker->hasDirname()) { floater->close(); return; } - filename = picker.getDirName(); + std::string dirname = dirpicker->getDirname(); // Make local directory tree - LLFile::mkdir(filename); + LLFile::mkdir(dirname); std::vector::iterator _cat_iter = order->mCats.begin(); std::vector::iterator _cat_end = order->mCats.end(); for( ; _cat_iter != _cat_end; ++_cat_iter) { - std::string path = filename + OS_SEP + LLInventoryBackup::getPath(*_cat_iter, order->mCats); + std::string path = dirname + OS_SEP + LLInventoryBackup::getPath(*_cat_iter, order->mCats); LLFile::mkdir(path); } // Go go backup floater - LLFloaterInventoryBackup* backup_floater = new LLFloaterInventoryBackup(filename, order->mCats, order->mItems); + LLFloaterInventoryBackup* backup_floater = new LLFloaterInventoryBackup(dirname, order->mCats, order->mItems); backup_floater->center(); // Close myself floater->close(); } - - - // static bool LLInventoryBackup::itemIsFolder(LLInventoryItem* item) { @@ -158,64 +163,64 @@ bool LLInventoryBackup::itemIsFolder(LLInventoryItem* item) } // static -LLFilePicker::ESaveFilter LLInventoryBackup::getSaveFilter(LLInventoryItem* item) +ESaveFilter LLInventoryBackup::getSaveFilter(LLInventoryItem* item) { LLAssetType::EType type = item->getType(); EWearableType wear = (EWearableType)(item->getFlags() & 0xFF); switch(type) { case LLAssetType::AT_TEXTURE: - return LLFilePicker::FFSAVE_TGA; + return FFSAVE_TGA; case LLAssetType::AT_SOUND: - return LLFilePicker::FFSAVE_OGG; + return FFSAVE_OGG; case LLAssetType::AT_SCRIPT: case LLAssetType::AT_LSL_TEXT: - return LLFilePicker::FFSAVE_LSL; + return FFSAVE_LSL; case LLAssetType::AT_ANIMATION: - return LLFilePicker::FFSAVE_ANIMATN; + return FFSAVE_ANIMATN; case LLAssetType::AT_GESTURE: - return LLFilePicker::FFSAVE_GESTURE; + return FFSAVE_GESTURE; case LLAssetType::AT_NOTECARD: - return LLFilePicker::FFSAVE_NOTECARD; + return FFSAVE_NOTECARD; case LLAssetType::AT_LANDMARK: - return LLFilePicker::FFSAVE_LANDMARK; + return FFSAVE_LANDMARK; case LLAssetType::AT_BODYPART: case LLAssetType::AT_CLOTHING: switch(wear) { case WT_EYES: - return LLFilePicker::FFSAVE_EYES; + return FFSAVE_EYES; case WT_GLOVES: - return LLFilePicker::FFSAVE_GLOVES; + return FFSAVE_GLOVES; case WT_HAIR: - return LLFilePicker::FFSAVE_HAIR; + return FFSAVE_HAIR; case WT_JACKET: - return LLFilePicker::FFSAVE_JACKET; + return FFSAVE_JACKET; case WT_PANTS: - return LLFilePicker::FFSAVE_PANTS; + return FFSAVE_PANTS; case WT_SHAPE: - return LLFilePicker::FFSAVE_SHAPE; + return FFSAVE_SHAPE; case WT_SHIRT: - return LLFilePicker::FFSAVE_SHIRT; + return FFSAVE_SHIRT; case WT_SHOES: - return LLFilePicker::FFSAVE_SHOES; + return FFSAVE_SHOES; case WT_SKIN: - return LLFilePicker::FFSAVE_SKIN; + return FFSAVE_SKIN; case WT_SKIRT: - return LLFilePicker::FFSAVE_SKIRT; + return FFSAVE_SKIRT; case WT_SOCKS: - return LLFilePicker::FFSAVE_SOCKS; + return FFSAVE_SOCKS; case WT_UNDERPANTS: - return LLFilePicker::FFSAVE_UNDERPANTS; + return FFSAVE_UNDERPANTS; case WT_UNDERSHIRT: - return LLFilePicker::FFSAVE_UNDERSHIRT; + return FFSAVE_UNDERSHIRT; case WT_PHYSICS: - return LLFilePicker::FFSAVE_PHYSICS; + return FFSAVE_PHYSICS; default: - return LLFilePicker::FFSAVE_ALL; + return FFSAVE_ALL; } default: - return LLFilePicker::FFSAVE_ALL; + return FFSAVE_ALL; } } @@ -352,28 +357,9 @@ void LLInventoryBackup::imageCallback(BOOL success, return; } - LLFilePicker& file_picker = LLFilePicker::instance(); - if( !file_picker.getSaveFile( getSaveFilter(item), LLDir::getScrubbedFileName(item->getName())) ) - { - // User canceled or we failed to acquire save file. - return; - } - // remember the user-approved/edited file name. - std::string filename = file_picker.getFirstFile(); - - LLPointer image_tga = new LLImageTGA; - if( !image_tga->encode( src ) ) - { - LLSD args; - args["ERROR_MESSAGE"] = "Couldn't encode file."; - LLNotifications::instance().add("ErrorMessage", args); - } - else if( !image_tga->save( filename ) ) - { - LLSD args; - args["ERROR_MESSAGE"] = "Couldn't write file."; - LLNotifications::instance().add("ErrorMessage", args); - } + AIFilePicker* filepicker = AIFilePicker::create(); + filepicker->open(LLDir::getScrubbedFileName(item->getName()), getSaveFilter(item)); + filepicker->run(boost::bind(&LLInventoryBackup::imageCallback_continued, src, filepicker)); } else { @@ -381,6 +367,28 @@ void LLInventoryBackup::imageCallback(BOOL success, } } +void LLInventoryBackup::imageCallback_continued(LLImageRaw* src, AIFilePicker* filepicker) +{ + if (!filepicker->hasFilename()) + return; + + std::string filename = filepicker->getFilename(); + + LLPointer image_tga = new LLImageTGA; + if( !image_tga->encode( src ) ) + { + LLSD args; + args["ERROR_MESSAGE"] = "Couldn't encode file."; + LLNotifications::instance().add("ErrorMessage", args); + } + else if( !image_tga->save( filename ) ) + { + LLSD args; + args["ERROR_MESSAGE"] = "Couldn't write file."; + LLNotifications::instance().add("ErrorMessage", args); + } +} + // static void LLInventoryBackup::assetCallback(LLVFS *vfs, const LLUUID& asset_uuid, @@ -402,7 +410,7 @@ void LLInventoryBackup::assetCallback(LLVFS *vfs, LLVFile file(vfs, asset_uuid, type, LLVFile::READ); S32 size = file.getSize(); - char* buffer = new char[size]; + char* buffer = new char[size]; // Deleted in assetCallback_continued. if (buffer == NULL) { llerrs << "Memory Allocation Failed" << llendl; @@ -413,18 +421,22 @@ void LLInventoryBackup::assetCallback(LLVFS *vfs, // Write it back out... - LLFilePicker& file_picker = LLFilePicker::instance(); - if( !file_picker.getSaveFile( getSaveFilter(item), LLDir::getScrubbedFileName(item->getName())) ) - { - // User canceled or we failed to acquire save file. - return; - } - // remember the user-approved/edited file name. - std::string filename = file_picker.getFirstFile(); + AIFilePicker* filepicker = AIFilePicker::create(); + filepicker->open(LLDir::getScrubbedFileName(item->getName()), getSaveFilter(item)); + filepicker->run(boost::bind(&LLInventoryBackup::assetCallback_continued, buffer, size, filepicker)); +} - std::ofstream export_file(filename.c_str(), std::ofstream::binary); - export_file.write(buffer, size); - export_file.close(); +// static +void LLInventoryBackup::assetCallback_continued(char* buffer, S32 size, AIFilePicker* filepicker) +{ + if (filepicker->hasFilename()) + { + std::string filename = filepicker->getFilename(); + std::ofstream export_file(filename.c_str(), std::ofstream::binary); + export_file.write(buffer, size); + export_file.close(); + } + delete [] buffer; } // static diff --git a/indra/newview/llinventorybackup.h b/indra/newview/llinventorybackup.h index 98664a9a5..2ee0c197c 100644 --- a/indra/newview/llinventorybackup.h +++ b/indra/newview/llinventorybackup.h @@ -11,10 +11,11 @@ #include "llviewerinventory.h" #include "llfolderview.h" -#include "llfilepicker.h" +#include "statemachine/aifilepicker.h" #include "llviewertexture.h" #include "llfloater.h" +class AIDirPicker; class LLInventoryBackupOrder { @@ -45,6 +46,7 @@ public: LLFloaterInventoryBackupSettings(LLInventoryBackupOrder* order); BOOL postBuild(void); static void onClickNext(void* userdata); + static void onClickNext_continued(void* userdata, AIDirPicker* dirpicker); LLInventoryBackupOrder* mOrder; virtual ~LLFloaterInventoryBackupSettings(); @@ -94,10 +96,12 @@ private: }; +class AIFilePicker; + class LLInventoryBackup { public: - static LLFilePicker::ESaveFilter getSaveFilter(LLInventoryItem* item); + static ESaveFilter getSaveFilter(LLInventoryItem* item); static std::string getExtension(LLInventoryItem* item); static std::string getUniqueFilename(std::string filename, std::string extension); static std::string getUniqueDirname(std::string dirname); @@ -120,10 +124,12 @@ private: S32 discard_level, BOOL final, void* userdata); + static void imageCallback_continued(LLImageRaw* src, AIFilePicker* filepicker); static void assetCallback(LLVFS *vfs, const LLUUID& asset_uuid, LLAssetType::EType type, void* user_data, S32 status, LLExtStat ext_status); + static void assetCallback_continued(char* buffer, S32 size, AIFilePicker* filepicker); static void climb(LLInventoryCategory* cat, std::vector& cats, std::vector& items); diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 3455caf19..d728d4274 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -99,6 +99,7 @@ //#include "llcheats.h" #include "dofloaterhex.h" #include "hgfloatertexteditor.h" +#include "statemachine/aifilepicker.h" // // Editing wearables from inventory is an include-hungry feature -.- -SG @@ -1106,30 +1107,26 @@ void LLItemBridge::performAction(LLFolderView* folder, LLInventoryModel* model, else if("reupload" == action) { LLInventoryItem* item = model->getItem(mUUID); - if(!item) return; - - LLFilePicker& picker = LLFilePicker::instance(); - std::string filename; - - switch(item->getType()) + if (item && item->getType() == LLAssetType::AT_TEXTURE) { - case LLAssetType::AT_TEXTURE: - if(!picker.getOpenFile(LLFilePicker::FFLOAD_IMAGE)) - return; - filename = picker.getFirstFile(); - if(!filename.empty()) - { - LLFloaterImagePreview* floaterp = new LLFloaterImagePreview(filename, item); - LLUICtrlFactory::getInstance()->buildFloater(floaterp, "floater_image_preview.xml"); - } - break; - default: - break; + AIFilePicker* filepicker = AIFilePicker::create(); + filepicker->open(FFLOAD_IMAGE, "", "image"); + filepicker->run(boost::bind(&LLItemBridge::showFloaterImagePreview, item, filepicker)); } } // } +// static +void LLItemBridge::showFloaterImagePreview(LLInventoryItem* item, AIFilePicker* filepicker) +{ + if (filepicker->hasFilename()) + { + LLFloaterImagePreview* floaterp = new LLFloaterImagePreview(filepicker->getFilename(), item); + LLUICtrlFactory::getInstance()->buildFloater(floaterp, "floater_image_preview.xml"); + } +} + void LLItemBridge::selectItem() { LLViewerInventoryItem* item = (LLViewerInventoryItem*)getItem(); diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h index a3108d653..2a668e684 100644 --- a/indra/newview/llinventorybridge.h +++ b/indra/newview/llinventorybridge.h @@ -277,6 +277,7 @@ protected: LLInventoryType::EType mInvType; }; +class AIFilePicker; class LLItemBridge : public LLInvFVBridge { @@ -303,7 +304,7 @@ public: virtual BOOL hasChildren() const { return FALSE; } virtual BOOL isUpToDate() const { return TRUE; } - + static void showFloaterImagePreview(LLInventoryItem* item, AIFilePicker* filepicker); // override for LLInvFVBridge virtual void clearDisplayName() { mDisplayName.clear(); } diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 910d94baf..e65b75e01 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -59,6 +59,7 @@ #include "llviewercontrol.h" #include "llvoavatar.h" #include "llsdutil.h" +#include "statemachine/aievent.h" // #include "llappviewer.h" // gLostItemsRoot // @@ -349,6 +350,13 @@ void LLInventoryModel::getDirectDescendentsOf(const LLUUID& cat_id, items = get_ptr_in_map(mParentChildItemTree, cat_id); } +// Same but just categories. +void LLInventoryModel::getDirectDescendentsOf(const LLUUID& cat_id, + cat_array_t*& categories) const +{ + categories = get_ptr_in_map(mParentChildCategoryTree, cat_id); +} + // SJB: Added version to lock the arrays to catch potential logic bugs void LLInventoryModel::lockDirectDescendentArrays(const LLUUID& cat_id, cat_array_t*& categories, @@ -1310,7 +1318,6 @@ void LLInventoryModel::mock(const LLUUID& root_id) void LLInventoryModel::fetchInventoryResponder::result(const LLSD& content) { - LL_DEBUGS("Inventory") << " fetch http got " << ll_pretty_print_sd(content) << LL_ENDL; // OGPX start_new_inventory_observer(); /*LLUUID agent_id; @@ -1428,7 +1435,6 @@ class fetchDescendentsResponder: public LLHTTPClient::Responder // Note: this is the handler for WebFetchInventoryDescendents and agent/inventory caps void fetchDescendentsResponder::result(const LLSD& content) { - LL_DEBUGS("Inventory") << " fetch descendents got " << ll_pretty_print_sd(content) << LL_ENDL; // OGPX if (content.has("folders")) { @@ -1650,11 +1656,7 @@ void LLInventoryModel::bulkFetch(std::string url) folder_sd["fetch_items"] = (LLSD::Boolean)TRUE; LL_DEBUGS("Inventory") << " fetching "<getUUID()<<" with cat owner "<getOwnerID()<<" and agent" << gAgent.getID() << LL_ENDL; - //OGPX if (ALEXANDRIA_LINDEN_ID == cat->getOwnerID()) - // for OGP it really doesnt make sense to have the decision about whether to fetch - // from the library or user cap be determined by a hard coded UUID. - // if it isnt an item that belongs to the agent, then fetch from the library - if (gAgent.getID() != cat->getOwnerID()) //if i am not the owner, it must be in the library + if (ALEXANDRIA_LINDEN_ID == cat->getOwnerID()) body_lib["folders"].append(folder_sd); else body["folders"].append(folder_sd); @@ -1688,14 +1690,12 @@ void LLInventoryModel::bulkFetch(std::string url) sBulkFetchCount++; if (body["folders"].size()) { - LL_DEBUGS("Inventory") << " fetch descendents post to " << url << ": " << ll_pretty_print_sd(body) << LL_ENDL; // OGPX LLHTTPClient::post(url, body, new fetchDescendentsResponder(body),300.0); } if (body_lib["folders"].size()) { std::string url_lib; url_lib = gAgent.getRegion()->getCapability("FetchLibDescendents"); - LL_DEBUGS("Inventory") << " fetch descendents lib post: " << ll_pretty_print_sd(body_lib) << LL_ENDL; // OGPX LLHTTPClient::post(url_lib, body_lib, new fetchDescendentsResponder(body_lib),300.0); } sFetchTimer.reset(); @@ -1727,7 +1727,6 @@ void LLInventoryModel::startBackgroundFetch(const LLUUID& cat_id) { if (!sAllFoldersFetched) { - sBackgroundFetchActive = TRUE; if (cat_id.isNull()) { if (!sFullFetchStarted) @@ -1735,15 +1734,29 @@ void LLInventoryModel::startBackgroundFetch(const LLUUID& cat_id) sFullFetchStarted = TRUE; sFetchQueue.push_back(gInventoryLibraryRoot); sFetchQueue.push_back(gAgent.getInventoryRootID()); - gIdleCallbacks.addFunction(&LLInventoryModel::backgroundFetch, NULL); + if (!sBackgroundFetchActive) + { + sBackgroundFetchActive = TRUE; + gIdleCallbacks.addFunction(&LLInventoryModel::backgroundFetch, NULL); + } } } else { // specific folder requests go to front of queue - if (sFetchQueue.empty() || sFetchQueue.front() != cat_id) + // Remove it from the queue first, to avoid getting it twice. + if (!sFetchQueue.empty() && sFetchQueue.front() != cat_id) { - sFetchQueue.push_front(cat_id); + std::deque::iterator old_entry = std::find(sFetchQueue.begin(), sFetchQueue.end(), cat_id); + if (old_entry != sFetchQueue.end()) + { + sFetchQueue.erase(old_entry); + } + } + sFetchQueue.push_front(cat_id); + if (!sBackgroundFetchActive) + { + sBackgroundFetchActive = TRUE; gIdleCallbacks.addFunction(&LLInventoryModel::backgroundFetch, NULL); } } @@ -1753,9 +1766,12 @@ void LLInventoryModel::startBackgroundFetch(const LLUUID& cat_id) //static void LLInventoryModel::findLostItems() { - sBackgroundFetchActive = TRUE; sFetchQueue.push_back(LLUUID::null); - gIdleCallbacks.addFunction(&LLInventoryModel::backgroundFetch, NULL); + if (!sBackgroundFetchActive) + { + sBackgroundFetchActive = TRUE; + gIdleCallbacks.addFunction(&LLInventoryModel::backgroundFetch, NULL); + } } //static @@ -1767,7 +1783,11 @@ void LLInventoryModel::stopBackgroundFetch() gIdleCallbacks.deleteFunction(&LLInventoryModel::backgroundFetch, NULL); sBulkFetchCount=0; sMinTimeBetweenFetches=0.0f; -// sFullFetchStarted=FALSE; + if (!sAllFoldersFetched) + { + // We didn't finish this, so set it to FALSE in order to be able to start it again. + sFullFetchStarted=FALSE; + } } } @@ -1776,33 +1796,20 @@ void LLInventoryModel::backgroundFetch(void*) { if (sBackgroundFetchActive && gAgent.getRegion()) { - // OGPX : agent/inventory is on gAgent for OGPX. I check both, and give - // ...preference to the one on gAgent. That way the existing non OGP path will remain the same. - // Q: How *should* I handle deciding which cap to use? Maybe I don't want to trust fetching inventory from the region - // OGPX TODO: manage getting caps from more than one service securely. - std::string url = gAgent.getCapability("agent/inventory"); // was WebFetchInventoryDescendents - if (url.empty()) - { - // OGPX : if we didn't get an agent/inventory cap from the Agent Domain, check to see if there was one on the region - // If we'll be using the capability, we'll be sending batches and the background thing isn't as important. - // OGPX TODO: this should change when Capabilities are refactored. - // ... this is a trust/security issue. if we have an agent/inventory from the Agent Domain, - // maybe we shouldn't trust WFID from region. - LL_DEBUGS("Inventory") << " no agent/inventory not on AD, checking fallback to region " << LL_ENDL; - url = gAgent.getRegion()->getCapability("WebFetchInventoryDescendents"); - } - if (!url.empty()) + // If we'll be using the capability, we'll be sending batches and the background thing isn't as important. + std::string url = gAgent.getRegion()->getCapability("FetchInventoryDescendents"); + if (false /*gSavedSettings.getBOOL("UseHTTPInventory")*/ && !url.empty()) { bulkFetch(url); return; } - // If there was no HTTP cap to fetch with, then do the UDP fetch +#if 1 //DEPRECATED OLD CODE FOLLOWS. // no more categories to fetch, stop fetch process if (sFetchQueue.empty()) { - LL_DEBUGS("Inventory") << "Inventory fetch completed" << LL_ENDL; + llinfos << "Inventory fetch completed" << llendl; if (sFullFetchStarted) { sAllFoldersFetched = TRUE; @@ -1818,7 +1825,7 @@ void LLInventoryModel::backgroundFetch(void*) // double timeouts on failure sMinTimeBetweenFetches = llmin(sMinTimeBetweenFetches * 2.f, 10.f); sMaxTimeBetweenFetches = llmin(sMaxTimeBetweenFetches * 2.f, 120.f); - LL_DEBUGS("Inventory") << "Inventory fetch times grown to (" << sMinTimeBetweenFetches << ", " << sMaxTimeBetweenFetches << ")" << LL_ENDL; + llinfos << "Inventory fetch times grown to (" << sMinTimeBetweenFetches << ", " << sMaxTimeBetweenFetches << ")" << llendl; // fetch is no longer considered "timely" although we will wait for full time-out sTimelyFetchPending = FALSE; } @@ -1913,6 +1920,11 @@ void LLInventoryModel::backgroundFetch(void*) // not enough time has elapsed to do a new fetch break; } + + // + // DEPRECATED OLD CODE + //-------------------------------------------------------------------------------- +#endif } } @@ -1972,6 +1984,23 @@ void LLInventoryModel::addItem(LLViewerInventoryItem* item) //llinfos << "LLInventoryModel::addItem()" << llendl; if(item) { + // This can happen if assettype enums from llassettype.h ever change. + // For example, there is a known backwards compatibility issue in some viewer prototypes prior to when + // the AT_LINK enum changed from 23 to 24. + if ((item->getType() == LLAssetType::AT_NONE) + || LLAssetType::lookup(item->getType()) == LLAssetType::badLookup()) + { + llwarns << "Got bad asset type for item [ name: " << item->getName() << " type: " << item->getType() << " inv-type: " << item->getInventoryType() << " ], ignoring." << llendl; + return; + } + + // This condition means that we tried to add a link without the baseobj being in memory. + // The item will show up as a broken link. + if (item->getIsBrokenLink()) + { + llinfos << "Adding broken link [ name: " << item->getName() << " itemID: " << item->getUUID() << " assetID: " << item->getAssetUUID() << " ) parent: " << item->getParentUUID() << llendl; + } + mItemMap[item->getUUID()] = item; } } @@ -2175,57 +2204,53 @@ bool LLInventoryModel::loadSkeleton( const LLSD& options, const LLUUID& owner_id) { - LL_INFOS("OGPX") << "importing inventory skeleton for " << owner_id << LL_ENDL; - LL_DEBUGS("Inventory") << " skeleton is " << ll_pretty_print_sd(options) << LL_ENDL; + lldebugs << "importing inventory skeleton for " << owner_id << llendl; typedef std::set, InventoryIDPtrLess> cat_set_t; cat_set_t temp_cats; - - update_map_t child_counts; - - LLUUID id; - LLAssetType::EType preferred_type; bool rv = true; - for (LLSD::array_const_iterator it = options.beginArray(); it < options.endArray(); ++it) + + for(LLSD::array_const_iterator it = options.beginArray(), + end = options.endArray(); it != end; ++it) { - LLPointer cat = new LLViewerInventoryCategory(owner_id); - - LL_DEBUGS("Inventory") << "cat name, folder, parent, type " << (*it)["name"].asString() << " " << (*it)["folder_id"].asUUID() << " " << (*it)["parent_id"].asUUID() << " " << (*it)["type_default"].asString() << " " << LL_ENDL; // OGPX - if ((*it)["name"].asString().empty()) goto clean_cat; - cat->rename((*it)["name"].asString().c_str()); - if ((*it)["folder_id"].asUUID().isNull()) goto clean_cat; - id = (*it)["folder_id"].asUUID(); - // if an id is null, it locks the viewer. - if (id.isNull()) goto clean_cat; - cat->setUUID(id); - // OGPX : slight change in snowglobe non OGP handling of things with null parents vs OGP9 SVN branch - // OGPX : so commented this line out for OGPX as well. if((*it)["parent_id"].asUUID().isNull()) goto clean_cat; - id = (*it)["parent_id"].asUUID(); - cat->setParent(id); - if ((*it)["type_default"].asString().empty()) + LLSD name = (*it)["name"]; + LLSD folder_id = (*it)["folder_id"]; + LLSD parent_id = (*it)["parent_id"]; + LLSD version = (*it)["version"]; + if(name.isDefined() + && folder_id.isDefined() + && parent_id.isDefined() + && version.isDefined() + && folder_id.asUUID().notNull() // if an id is null, it locks the viewer. + ) { - preferred_type = LLAssetType::AT_NONE; + LLPointer cat = new LLViewerInventoryCategory(owner_id); + cat->rename(name.asString()); + cat->setUUID(folder_id.asUUID()); + cat->setParent(parent_id.asUUID()); + + LLAssetType::EType preferred_type = LLAssetType::AT_NONE; + LLSD type_default = (*it)["type_default"]; + if(type_default.isDefined()) + { + preferred_type = (LLAssetType::EType)type_default.asInteger(); + } + cat->setPreferredType(preferred_type); + cat->setVersion(version.asInteger()); + temp_cats.insert(cat); } else { - S32 t = (*it)["type_default"].asInteger(); - preferred_type = (LLAssetType::EType)t; + llwarns << "Unable to import near " << name.asString() << llendl; + rv = false; } - cat->setPreferredType(preferred_type); - if ((*it)["version"].asString().empty()) goto clean_cat; - cat->setVersion((*it)["version"].asInteger()); - temp_cats.insert(cat); - continue; - clean_cat: - llwarns << "Unable to import near " << cat->getName() << llendl; - rv = false; - //delete cat; // automatic when cat is reasigned or destroyed } - + S32 cached_category_count = 0; S32 cached_item_count = 0; - if (!temp_cats.empty()) + if(!temp_cats.empty()) { + update_map_t child_counts; cat_array_t categories; item_array_t items; cat_set_t invalid_categories; // Used to mark categories that weren't successfully loaded. @@ -2295,9 +2320,9 @@ bool LLInventoryModel::loadSkeleton( } // go ahead and add the cats returned during the download - std::set::iterator not_cached_id = cached_ids.end(); + std::set::const_iterator not_cached_id = cached_ids.end(); cached_category_count = cached_ids.size(); - for (cat_set_t::iterator it = temp_cats.begin(); it != temp_cats.end(); ++it) + for(cat_set_t::iterator it = temp_cats.begin(); it != temp_cats.end(); ++it) { if (cached_ids.find((*it)->getUUID()) == not_cached_id) { @@ -2313,30 +2338,32 @@ bool LLInventoryModel::loadSkeleton( // Add all the items loaded which are parented to a // category with a correctly cached parent - count = items.count(); S32 bad_link_count = 0; cat_map_t::iterator unparented = mCategoryMap.end(); - for (int i = 0; i < count; ++i) + for(item_array_t::const_iterator item_iter = items.begin(); + item_iter != items.end(); + ++item_iter) { - cat_map_t::iterator cit = mCategoryMap.find(items[i]->getParentUUID()); + LLViewerInventoryItem *item = (*item_iter).get(); + const cat_map_t::iterator cit = mCategoryMap.find(item->getParentUUID()); - if (cit != unparented) + if(cit != unparented) { - LLViewerInventoryCategory* cat = cit->second; - if (cat->getVersion() != NO_VERSION) + const LLViewerInventoryCategory* cat = cit->second.get(); + if(cat->getVersion() != NO_VERSION) { // This can happen if the linked object's baseobj is removed from the cache but the linked object is still in the cache. - if (items[i]->getIsBrokenLink()) + if (item->getIsBrokenLink()) { bad_link_count++; lldebugs << "Attempted to add cached link item without baseobj present ( name: " - << items[i]->getName() << " itemID: " << items[i]->getUUID() - << " assetID: " << items[i]->getAssetUUID() + << item->getName() << " itemID: " << item->getUUID() + << " assetID: " << item->getAssetUUID() << " ). Ignoring and invalidating " << cat->getName() << " . " << llendl; invalid_categories.insert(cit->second); continue; } - addItem(items[i]); + addItem(item); cached_item_count += 1; ++child_counts[cat->getUUID()]; } @@ -2375,17 +2402,17 @@ bool LLInventoryModel::loadSkeleton( // At this point, we need to set the known descendents for each // category which successfully cached so that we do not // needlessly fetch descendents for categories which we have. - update_map_t::iterator no_child_counts = child_counts.end(); - update_map_t::iterator the_count; - for (cat_set_t::iterator it = temp_cats.begin(); it != temp_cats.end(); ++it) + update_map_t::const_iterator no_child_counts = child_counts.end(); + for(cat_set_t::iterator it = temp_cats.begin(); it != temp_cats.end(); ++it) { - LLViewerInventoryCategory* cat = (*it); - if (cat->getVersion() != NO_VERSION) + LLViewerInventoryCategory* cat = (*it).get(); + if(cat->getVersion() != NO_VERSION) { - the_count = child_counts.find(cat->getUUID()); - if (the_count != no_child_counts) + update_map_t::const_iterator the_count = child_counts.find(cat->getUUID()); + if(the_count != no_child_counts) { - cat->setDescendentCount((*the_count).second.mValue); + const S32 num_descendents = (*the_count).second.mValue; + cat->setDescendentCount(num_descendents); } else { @@ -2408,341 +2435,30 @@ bool LLInventoryModel::loadSkeleton( categories.clear(); // will unref and delete entries } - LL_DEBUGS("Inventory") << "Successfully loaded " << cached_category_count + llinfos << "Successfully loaded " << cached_category_count << " categories and " << cached_item_count << " items from cache." - << LL_ENDL; + << llendl; return rv; } +//OGPX crap. Since this function is actually functionally the same as its LLSD variant.. +// just convert options_t to LLSD and route to the LLSD version. Yuck. bool LLInventoryModel::loadSkeleton( const LLInventoryModel::options_t& options, const LLUUID& owner_id) { - lldebugs << "importing inventory skeleton for " << owner_id << llendl; - - typedef std::set, InventoryIDPtrLess> cat_set_t; - cat_set_t temp_cats; - - update_map_t child_counts; - - LLUUID id; - LLAssetType::EType preferred_type; - bool rv = true; + LLSD options_list; for(options_t::const_iterator it = options.begin(); it < options.end(); ++it) { - LLPointer cat = new LLViewerInventoryCategory(owner_id); - response_t::const_iterator no_response = (*it).end(); - response_t::const_iterator skel; - skel = (*it).find("name"); - if(skel == no_response) goto clean_cat; - cat->rename(std::string((*skel).second)); - skel = (*it).find("folder_id"); - if(skel == no_response) goto clean_cat; - id.set((*skel).second); - // if an id is null, it locks the viewer. - if(id.isNull()) goto clean_cat; - cat->setUUID(id); - skel = (*it).find("parent_id"); - if(skel == no_response) goto clean_cat; - id.set((*skel).second); - cat->setParent(id); - skel = (*it).find("type_default"); - if(skel == no_response) + LLSD entry; + for(response_t::const_iterator it2 = it->begin(); it2 != it->end(); ++it2) { - preferred_type = LLAssetType::AT_NONE; + entry[it2->first]=it2->second; } - else - { - S32 t = atoi((*skel).second.c_str()); - preferred_type = (LLAssetType::EType)t; - } - cat->setPreferredType(preferred_type); - skel = (*it).find("version"); - if(skel == no_response) goto clean_cat; - cat->setVersion(atoi((*skel).second.c_str())); - temp_cats.insert(cat); - continue; - clean_cat: - llwarns << "Unable to import near " << cat->getName() << llendl; - rv = false; - //delete cat; // automatic when cat is reasigned or destroyed + options_list.append(entry); } - - S32 cached_category_count = 0; - S32 cached_item_count = 0; - if(!temp_cats.empty()) - { - cat_array_t categories; - item_array_t items; - cat_set_t invalid_categories; // Used to mark categories that weren't successfully loaded. - std::string owner_id_str; - owner_id.toString(owner_id_str); - std::string path(gDirUtilp->getExpandedFilename(LL_PATH_CACHE, owner_id_str)); - std::string inventory_filename; - inventory_filename = llformat(CACHE_FORMAT_STRING, path.c_str()); - const S32 NO_VERSION = LLViewerInventoryCategory::VERSION_UNKNOWN; - std::string gzip_filename(inventory_filename); - gzip_filename.append(".gz"); - LLFILE* fp = LLFile::fopen(gzip_filename, "rb"); - bool remove_inventory_file = false; - if(fp) - { - fclose(fp); - fp = NULL; - if(gunzip_file(gzip_filename, inventory_filename)) - { - // we only want to remove the inventory file if it was - // gzipped before we loaded, and we successfully - // gunziped it. - remove_inventory_file = true; - } - else - { - llinfos << "Unable to gunzip " << gzip_filename << llendl; - } - } - bool is_cache_obsolete = false; - if (loadFromFile(inventory_filename, categories, items, is_cache_obsolete)) - { - // We were able to find a cache of files. So, use what we - // found to generate a set of categories we should add. We - // will go through each category loaded and if the version - // does not match, invalidate the version. - S32 count = categories.count(); - cat_set_t::iterator not_cached = temp_cats.end(); - std::set cached_ids; - for(S32 i = 0; i < count; ++i) - { - LLViewerInventoryCategory* cat = categories[i]; - cat_set_t::iterator cit = temp_cats.find(cat); - if (cit == temp_cats.end()) - { - continue; // cache corruption?? not sure why this happens -SJB - } - LLViewerInventoryCategory* tcat = *cit; - - // we can safely ignore anything loaded from file, but - // not sent down in the skeleton. - if(cit == not_cached) - { - continue; - } - if(cat->getVersion() != tcat->getVersion()) - { - // if the cached version does not match the server version, - // throw away the version we have so we can fetch the - // correct contents the next time the viewer opens the folder. - tcat->setVersion(NO_VERSION); - } - else - { - cached_ids.insert(tcat->getUUID()); - } - } - - // go ahead and add the cats returned during the download - std::set::iterator not_cached_id = cached_ids.end(); - cached_category_count = cached_ids.size(); - for(cat_set_t::iterator it = temp_cats.begin(); it != temp_cats.end(); ++it) - { - if(cached_ids.find((*it)->getUUID()) == not_cached_id) - { - // this check is performed so that we do not - // mark new folders in the skeleton (and not in cache) - // as being cached. - LLViewerInventoryCategory *llvic = (*it); - llvic->setVersion(NO_VERSION); - } - addCategory(*it); - ++child_counts[(*it)->getParentUUID()]; - } - - // Add all the items loaded which are parented to a - // category with a correctly cached parent - count = items.count(); - S32 bad_link_count = 0; - cat_map_t::iterator unparented = mCategoryMap.end(); - for(int i = 0; i < count; ++i) - { - cat_map_t::iterator cit = mCategoryMap.find(items[i]->getParentUUID()); - - if(cit != unparented) - { - LLViewerInventoryCategory* cat = cit->second; - if(cat->getVersion() != NO_VERSION) - { - // This can happen if the linked object's baseobj is removed from the cache but the linked object is still in the cache. - if (items[i]->getIsBrokenLink()) - { - bad_link_count++; - lldebugs << "Attempted to add cached link item without baseobj present ( name: " - << items[i]->getName() << " itemID: " << items[i]->getUUID() - << " assetID: " << items[i]->getAssetUUID() - << " ). Ignoring and invalidating " << cat->getName() << " . " << llendl; - invalid_categories.insert(cit->second); - continue; - } - addItem(items[i]); - cached_item_count += 1; - ++child_counts[cat->getUUID()]; - } - } - } - if (bad_link_count > 0) - { - llinfos << "Attempted to add " << bad_link_count - << " cached link items without baseobj present. " - << "The corresponding categories were invalidated." << llendl; - } - } - else - { - // go ahead and add everything after stripping the version - // information. - for(cat_set_t::iterator it = temp_cats.begin(); it != temp_cats.end(); ++it) - { - LLViewerInventoryCategory *llvic = (*it); - llvic->setVersion(NO_VERSION); - addCategory(*it); - } - } - - // Invalidate all categories that failed fetching descendents for whatever - // reason (e.g. one of the descendents was a broken link). - for (cat_set_t::iterator invalid_cat_it = invalid_categories.begin(); - invalid_cat_it != invalid_categories.end(); - invalid_cat_it++) - { - LLViewerInventoryCategory* cat = (*invalid_cat_it).get(); - cat->setVersion(NO_VERSION); - llinfos << "Invalidating category name: " << cat->getName() << " UUID: " << cat->getUUID() << " due to invalid descendents cache" << llendl; - } - - // At this point, we need to set the known descendents for each - // category which successfully cached so that we do not - // needlessly fetch descendents for categories which we have. - update_map_t::iterator no_child_counts = child_counts.end(); - update_map_t::iterator the_count; - for(cat_set_t::iterator it = temp_cats.begin(); it != temp_cats.end(); ++it) - { - LLViewerInventoryCategory* cat = (*it); - if(cat->getVersion() != NO_VERSION) - { - the_count = child_counts.find(cat->getUUID()); - if(the_count != no_child_counts) - { - cat->setDescendentCount((*the_count).second.mValue); - } - else - { - cat->setDescendentCount(0); - } - } - } - - if(remove_inventory_file) - { - // clean up the gunzipped file. - LLFile::remove(inventory_filename); - } - if (is_cache_obsolete) - { - // If out of date, remove the gzipped file too. - llwarns << "Inv cache out of date, removing" << llendl; - LLFile::remove(gzip_filename); - } - categories.clear(); // will unref and delete entries - } - - LL_DEBUGS("Inventory") << "Successfully loaded " << cached_category_count - << " categories and " << cached_item_count << " items from cache." - << LL_ENDL; - - return rv; -} - -bool LLInventoryModel::loadMeat( - const LLInventoryModel::options_t& options, const LLUUID& owner_id) -{ - llinfos << "importing inventory for " << owner_id << llendl; - LLPermissions default_perm; - default_perm.init(LLUUID::null, owner_id, LLUUID::null, LLUUID::null); - LLPointer item; - LLUUID id; - LLAssetType::EType type; - LLInventoryType::EType inv_type; - bool rv = true; - for(options_t::const_iterator it = options.begin(); it < options.end(); ++it) - { - item = new LLViewerInventoryItem; - response_t::const_iterator no_response = (*it).end(); - response_t::const_iterator meat; - meat = (*it).find("name"); - if(meat == no_response) goto clean_item; - item->rename(std::string((*meat).second)); - meat = (*it).find("item_id"); - if(meat == no_response) goto clean_item; - id.set((*meat).second); - item->setUUID(id); - meat = (*it).find("parent_id"); - if(meat == no_response) goto clean_item; - id.set((*meat).second); - item->setParent(id); - meat = (*it).find("type"); - if(meat == no_response) goto clean_item; - type = (LLAssetType::EType)atoi((*meat).second.c_str()); - item->setType(type); - meat = (*it).find("inv_type"); - if(meat != no_response) - { - inv_type = (LLInventoryType::EType)atoi((*meat).second.c_str()); - item->setInventoryType(inv_type); - } - meat = (*it).find("data_id"); - if(meat == no_response) goto clean_item; - id.set((*meat).second); - if(LLAssetType::AT_CALLINGCARD == type) - { - LLPermissions perm; - perm.init(id, owner_id, LLUUID::null, LLUUID::null); - item->setPermissions(perm); - } - else - { - meat = (*it).find("perm_mask"); - if(meat != no_response) - { - PermissionMask perm_mask = atoi((*meat).second.c_str()); - default_perm.initMasks( - perm_mask, perm_mask, perm_mask, perm_mask, perm_mask); - } - else - { - default_perm.initMasks( - PERM_NONE, PERM_NONE, PERM_NONE, PERM_NONE, PERM_NONE); - } - item->setPermissions(default_perm); - item->setAssetUUID(id); - } - meat = (*it).find("flags"); - if(meat != no_response) - { - item->setFlags(strtoul((*meat).second.c_str(), NULL, 0)); - } - meat = (*it).find("time"); - if(meat != no_response) - { - item->setCreationDate(atoi((*meat).second.c_str())); - } - addItem(item); - continue; - clean_item: - llwarns << "Unable to import near " << item->getName() << llendl; - rv = false; - //delete item; // automatic when item is reassigned or destroyed - } - return rv; + return loadSkeleton(options_list,owner_id); } // This is a brute force method to rebuild the entire parent-child @@ -2941,6 +2657,7 @@ void LLInventoryModel::buildParentChildMap() // root of the agent's inv found. // The inv tree is built. mIsAgentInvUsable = true; + AIEvent::trigger(AIEvent::LLInventoryModel_mIsAgentInvUsable_true); } } llinfos << " finished buildParentChildMap " << llendl; diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h index 6fdb59d1a..697d1e29a 100644 --- a/indra/newview/llinventorymodel.h +++ b/indra/newview/llinventorymodel.h @@ -38,6 +38,7 @@ #include "lluuid.h" #include "llpermissionsflags.h" #include "llstring.h" +#include "llhttpclient.h" #include #include @@ -199,6 +200,9 @@ public: void getDirectDescendentsOf(const LLUUID& cat_id, cat_array_t*& categories, item_array_t*& items) const; + // Same but only get categories. + void getDirectDescendentsOf(const LLUUID& cat_id, + cat_array_t*& categories) const; // Starting with the object specified, add its descendents to the // array provided, but do not add the inventory object specified @@ -382,13 +386,9 @@ public: // during authentication. return true if everything parsed. typedef std::map response_t; typedef std::vector options_t; - // OGPX : Two loadSkeleton(), one for the XML-RPC logins, one for LLSD - //... The concept of a skeleton being different from the cap that - //... we do inventory queries on should be examined, and the usage of - //... the skeleton in querying the wearables needs to be examined as well. - bool loadSkeleton(const options_t& options, const LLUUID& owner_id); - bool loadMeat(const options_t& options, const LLUUID& owner_id); + //OGPX really screwed with the login process. This is needed until it's all sorted out. + bool loadSkeleton(const options_t& options, const LLUUID& owner_id); /** Mutators ** ** *******************************************************************************/ diff --git a/indra/newview/llmanipscale.cpp b/indra/newview/llmanipscale.cpp index eb467f921..5da5ba0aa 100644 --- a/indra/newview/llmanipscale.cpp +++ b/indra/newview/llmanipscale.cpp @@ -222,8 +222,6 @@ void LLManipScale::render() LLVector3 center_agent = gAgent.getPosAgentFromGlobal(LLSelectMgr::getInstance()->getSelectionCenterGlobal()); - F32 range; - F32 range_from_agent; if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) { mBoxHandleSize = BOX_HANDLE_BASE_SIZE * BOX_HANDLE_BASE_FACTOR / (F32) LLViewerCamera::getInstance()->getViewHeightInPixels(); @@ -231,25 +229,25 @@ void LLManipScale::render() } else { - range = dist_vec(gAgent.getCameraPositionAgent(), center_agent); - range_from_agent = dist_vec(gAgent.getPositionAgent(), center_agent); + F32 range_squared = dist_vec_squared(gAgent.getCameraPositionAgent(), center_agent); + F32 range_from_agent_squared = dist_vec_squared(gAgent.getPositionAgent(), center_agent); // Don't draw manip if object too far away if (gSavedSettings.getBOOL("LimitSelectDistance")) { F32 max_select_distance = gSavedSettings.getF32("MaxSelectDistance"); - if (range_from_agent > max_select_distance) + if (range_from_agent_squared > max_select_distance * max_select_distance) { return; } } - if (range > 0.001f) + if (range_squared > 0.001f * 0.001f) { // range != zero F32 fraction_of_fov = BOX_HANDLE_BASE_SIZE / (F32) LLViewerCamera::getInstance()->getViewHeightInPixels(); F32 apparent_angle = fraction_of_fov * LLViewerCamera::getInstance()->getView(); // radians - mBoxHandleSize = range * tan(apparent_angle) * BOX_HANDLE_BASE_FACTOR; + mBoxHandleSize = (F32) sqrtf(range_squared) * tan(apparent_angle) * BOX_HANDLE_BASE_FACTOR; } else { diff --git a/indra/newview/llmediactrl.h b/indra/newview/llmediactrl.h index f185fb9b9..bbf2dfa01 100644 --- a/indra/newview/llmediactrl.h +++ b/indra/newview/llmediactrl.h @@ -34,7 +34,7 @@ #define LL_LLMediaCtrl_H #include "llviewermedia.h" - +#include "llviewermediaobserver.h" #include "lluictrl.h" #include "llframetimer.h" #include "lldynamictexture.h" diff --git a/indra/newview/llnotify.cpp b/indra/newview/llnotify.cpp index 9a36b6542..ffd264b6c 100644 --- a/indra/newview/llnotify.cpp +++ b/indra/newview/llnotify.cpp @@ -99,7 +99,9 @@ bool LLNotifyBox::onNotification(const LLSD& notify) if(notify["sigtype"].asString() == "add" || notify["sigtype"].asString() == "change") { //bring existing notification to top - LLNotifyBox* boxp = LLNotifyBox::getInstance(notification->getID()); + //This getInstance is ugly, as LLNotifyBox is derived from both LLInstanceTracker and LLEventTimer, which also is derived from its own LLInstanceTracker + //Have to explicitly determine which getInstance function to use. + LLNotifyBox* boxp = LLNotifyBox::LLInstanceTracker::getInstance(notification->getID()); if (boxp && !boxp->isDead()) { gNotifyBoxView->showOnly(boxp); @@ -116,7 +118,7 @@ bool LLNotifyBox::onNotification(const LLSD& notify) } else if (notify["sigtype"].asString() == "delete") { - LLNotifyBox* boxp = LLNotifyBox::getInstance(notification->getID()); + LLNotifyBox* boxp = LLNotifyBox::LLInstanceTracker::getInstance(notification->getID()); if (boxp && !boxp->isDead()) { boxp->close(); diff --git a/indra/newview/llnotify.h b/indra/newview/llnotify.h index 15b5a7302..439cae239 100644 --- a/indra/newview/llnotify.h +++ b/indra/newview/llnotify.h @@ -35,7 +35,7 @@ #include "llfontgl.h" #include "llpanel.h" -#include "lltimer.h" +#include "lleventtimer.h" #include "llnotifications.h" #include diff --git a/indra/newview/lloverlaybar.cpp b/indra/newview/lloverlaybar.cpp index 5f74a9ecb..eeed29673 100644 --- a/indra/newview/lloverlaybar.cpp +++ b/indra/newview/lloverlaybar.cpp @@ -325,9 +325,9 @@ void LLOverlayBar::refresh() BOOL sitting = FALSE; if (gAgent.getAvatarObject()) { -// sitting = gAgent.getAvatarObject()->mIsSitting; +// sitting = gAgent.getAvatarObject()->isSitting(); // [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) - sitting = gAgent.getAvatarObject()->mIsSitting && !gRlvHandler.hasBehaviour(RLV_BHVR_UNSIT); + sitting = gAgent.getAvatarObject()->isSitting() && !gRlvHandler.hasBehaviour(RLV_BHVR_UNSIT); // [/RLVa:KB] } button = getChild("Stand Up"); @@ -449,7 +449,7 @@ void LLOverlayBar::onClickMouselook(void*) void LLOverlayBar::onClickStandUp(void*) { // [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) - if ( (gRlvHandler.hasBehaviour(RLV_BHVR_UNSIT)) && (gAgent.getAvatarObject()) && (gAgent.getAvatarObject()->mIsSitting) ) + if ( (gRlvHandler.hasBehaviour(RLV_BHVR_UNSIT)) && (gAgent.getAvatarObject()) && (gAgent.getAvatarObject()->isSitting()) ) { return; } diff --git a/indra/newview/llpanelavatar.cpp b/indra/newview/llpanelavatar.cpp index 52e812924..9a3add526 100644 --- a/indra/newview/llpanelavatar.cpp +++ b/indra/newview/llpanelavatar.cpp @@ -1213,20 +1213,27 @@ void LLPanelAvatarPicks::onClickNew(void* data) } //Pick import and export - RK +// static void LLPanelAvatarPicks::onClickImport(void* data) { LLPanelAvatarPicks* self = (LLPanelAvatarPicks*)data; - LLPanelPick* panel_pick = new LLPanelPick(FALSE); - LLTabContainer* tabs = self->getChild("picks tab"); + self->mPanelPick = new LLPanelPick(FALSE); + self->mPanelPick->importNewPick(&LLPanelAvatarPicks::onClickImport_continued, data); +} - bool import = panel_pick->importNewPick(); - if(tabs && import) +// static +void LLPanelAvatarPicks::onClickImport_continued(void* data, bool import) +{ + LLPanelAvatarPicks* self = (LLPanelAvatarPicks*)data; + LLTabContainer* tabs = self->getChild("picks tab"); + if(tabs && import && self->mPanelPick) { - tabs->addTabPanel(panel_pick, panel_pick->getPickName()); + tabs->addTabPanel(self->mPanelPick, self->mPanelPick->getPickName()); tabs->selectLastTab(); } } +// static void LLPanelAvatarPicks::onClickExport(void* data) { LLPanelAvatarPicks* self = (LLPanelAvatarPicks*)data; diff --git a/indra/newview/llpanelavatar.h b/indra/newview/llpanelavatar.h index 24de55cb5..812da4571 100644 --- a/indra/newview/llpanelavatar.h +++ b/indra/newview/llpanelavatar.h @@ -57,6 +57,7 @@ class LLViewerObject; class LLMessageSystem; class LLIconCtrl; class LLMediaCtrl; +class LLPanelPick; enum EOnlineStatus { @@ -265,9 +266,13 @@ private: //Pick import and export - RK static void onClickImport(void* data); + static void onClickImport_continued(void* self, bool import); static void onClickExport(void* data); bool callbackDelete(const LLSD& notification, const LLSD& response); + + // Used to pass it from onClickImport to onClickImport_continued. + LLPanelPick* mPanelPick; }; diff --git a/indra/newview/llpanelcontents.cpp b/indra/newview/llpanelcontents.cpp index 29929e82d..c8db6b33d 100644 --- a/indra/newview/llpanelcontents.cpp +++ b/indra/newview/llpanelcontents.cpp @@ -136,7 +136,7 @@ void LLPanelContents::getState(LLViewerObject *objectp ) LLViewerObject* pObj = LLSelectMgr::getInstance()->getSelection()->getFirstRootObject(TRUE); LLVOAvatar* pAvatar = gAgent.getAvatarObject(); - editable = (pObj) && (pAvatar) && ((!pAvatar->mIsSitting) || (pAvatar->getRoot() != pObj->getRootEdit())); + editable = (pObj) && (pAvatar) && ((!pAvatar->isSitting()) || (pAvatar->getRoot() != pObj->getRootEdit())); } } // [/RLVa:KB] @@ -185,7 +185,7 @@ void LLPanelContents::onClickNewScript(void *userdata) else if ( (gRlvHandler.hasBehaviour(RLV_BHVR_UNSIT)) || (gRlvHandler.hasBehaviour(RLV_BHVR_SITTP)) ) { LLVOAvatar* pAvatar = gAgent.getAvatarObject(); - if ( (pAvatar) && (pAvatar->mIsSitting) && (pAvatar->getRoot() == object->getRootEdit()) ) + if ( (pAvatar) && (pAvatar->isSitting()) && (pAvatar->getRoot() == object->getRootEdit()) ) return; // .. or in a linkset the avie is sitting on under @unsit=n/@sittp=n } } diff --git a/indra/newview/llpaneldisplay.cpp b/indra/newview/llpaneldisplay.cpp index 47a48755c..4a684a61a 100644 --- a/indra/newview/llpaneldisplay.cpp +++ b/indra/newview/llpaneldisplay.cpp @@ -230,11 +230,10 @@ BOOL LLPanelDisplay::postBuild() //---------------------------------------------------------------------------- // Enable Reflections - mCtrlReflections = getChild("Reflections"); - mCtrlReflections->setCommitCallback(&LLPanelDisplay::onVertexShaderEnable); - mCtrlReflections->setCallbackUserData(this); mCtrlReflectionDetail = getChild("ReflectionDetailCombo"); - + mCtrlReflectionDetail->setCommitCallback(&LLPanelDisplay::onVertexShaderEnable); + mCtrlReflectionDetail->setCallbackUserData(this); + // WindLight mCtrlWindLight = getChild("WindLightUseAtmosShaders"); mCtrlWindLight->setCommitCallback(&LLPanelDisplay::onVertexShaderEnable); @@ -244,9 +243,12 @@ BOOL LLPanelDisplay::postBuild() mCtrlDeferred = getChild("RenderDeferred"); mCtrlDeferred->setCommitCallback(&LLPanelDisplay::onVertexShaderEnable); mCtrlDeferred->setCallbackUserData(this); - mCtrlSunShadow = getChild("RenderDeferredSunShadow"); - mCtrlSunShadow->setCommitCallback(&LLPanelDisplay::onVertexShaderEnable); - mCtrlSunShadow->setCallbackUserData(this); + mCtrlDeferredGI = getChild("RenderDeferredGI"); + mCtrlDeferredGI->setCommitCallback(&LLPanelDisplay::onVertexShaderEnable); + mCtrlDeferredGI->setCallbackUserData(this); + mCtrlShadowDetail = getChild("ShadowDetailCombo"); + mCtrlShadowDetail->setCommitCallback(&LLPanelDisplay::onVertexShaderEnable); + mCtrlShadowDetail->setCallbackUserData(this); //---------------------------------------------------------------------------- // Enable Avatar Shaders @@ -306,6 +308,12 @@ BOOL LLPanelDisplay::postBuild() mCtrlAvatarFactor->setCommitCallback(&LLPanelDisplay::updateSliderText); mCtrlAvatarFactor->setCallbackUserData(mAvatarFactorText); + // Avatar physics detail slider + mCtrlAvatarPhysicsFactor = getChild("AvatarPhysicsDetail"); + mAvatarPhysicsFactorText = getChild("AvatarPhysicsDetailText"); + mCtrlAvatarPhysicsFactor->setCommitCallback(&LLPanelDisplay::updateSliderText); + mCtrlAvatarPhysicsFactor->setCallbackUserData(mAvatarPhysicsFactorText); + // Terrain detail slider mCtrlTerrainFactor = getChild("TerrainMeshDetail"); mTerrainFactorText = getChild("TerrainMeshDetailText"); @@ -334,6 +342,7 @@ BOOL LLPanelDisplay::postBuild() mTerrainText = getChild("TerrainDetailText"); mLightingText = getChild("LightingDetailText"); mMeshDetailText = getChild("MeshDetailText"); + mShadowDetailText = getChild("ShadowDetailText"); refresh(); @@ -397,14 +406,15 @@ void LLPanelDisplay::refresh() mBumpShiny = gSavedSettings.getBOOL("RenderObjectBump"); mShaderEnable = gSavedSettings.getBOOL("VertexShaderEnable"); mWindLight = gSavedSettings.getBOOL("WindLightUseAtmosShaders"); - mReflections = gSavedSettings.getBOOL("RenderWaterReflections"); mAvatarVP = gSavedSettings.getBOOL("RenderAvatarVP"); mDeferred = gSavedSettings.getBOOL("RenderDeferred"); - mSunShadow = gSavedSettings.getBOOL("RenderDeferredSunShadow"); + mDeferredGI = gSavedSettings.getBOOL("RenderDeferredGI"); // reflection radio mReflectionDetail = gSavedSettings.getS32("RenderReflectionDetail"); + mShadowDetail = gSavedSettings.getS32("RenderShadowDetail"); + // avatar settings mAvatarImpostors = gSavedSettings.getBOOL("RenderUseImpostors"); mAvatarCloth = gSavedSettings.getBOOL("RenderAvatarCloth"); @@ -423,7 +433,7 @@ void LLPanelDisplay::refresh() mPostProcess = gSavedSettings.getS32("RenderGlowResolutionPow"); // lighting and terrain radios - mLightingDetail = gSavedSettings.getS32("RenderLightingDetail"); + mLocalLights = gSavedSettings.getBOOL("RenderLocalLights"); mTerrainDetail = gSavedSettings.getS32("RenderTerrainDetail"); // slider text boxes @@ -431,6 +441,7 @@ void LLPanelDisplay::refresh() updateSliderText(mCtrlFlexFactor, mFlexFactorText); updateSliderText(mCtrlTreeFactor, mTreeFactorText); updateSliderText(mCtrlAvatarFactor, mAvatarFactorText); + updateSliderText(mCtrlAvatarPhysicsFactor, mAvatarPhysicsFactorText); updateSliderText(mCtrlTerrainFactor, mTerrainFactorText); updateSliderText(mCtrlPostProcess, mPostProcessText); updateSliderText(mCtrlSkyFactor, mSkyFactorText); @@ -468,13 +479,11 @@ void LLPanelDisplay::refreshEnabledState() BOOL reflections = gSavedSettings.getBOOL("VertexShaderEnable") && gGLManager.mHasCubeMap && LLCubeMap::sUseCubeMaps; - mCtrlReflections->setEnabled(reflections); + mCtrlReflectionDetail->setEnabled(reflections); // Bump & Shiny bool bumpshiny = gGLManager.mHasCubeMap && LLCubeMap::sUseCubeMaps && LLFeatureManager::getInstance()->isFeatureAvailable("RenderObjectBump"); mCtrlBumpShiny->setEnabled(bumpshiny ? TRUE : FALSE); - - mCtrlReflectionDetail->setEnabled(mCtrlReflections->get() && reflections); // Avatar Mode S32 max_avatar_shader = LLViewerShaderMgr::instance()->mMaxAvatarShaderLevel; @@ -501,7 +510,9 @@ void LLPanelDisplay::refreshEnabledState() mCtrlDeferred->setEnabled(can_defer); - mCtrlSunShadow->setEnabled(can_defer && gSavedSettings.getBOOL("RenderDeferred")); + mCtrlShadowDetail->setEnabled(can_defer && gSavedSettings.getBOOL("RenderDeferred")); + //GI won't do anything with shadows off, but disabling it here is less than intuitive. Ignore shadow setting for now. + mCtrlDeferredGI->setEnabled(mCtrlShadowDetail->getEnabled()/* && gSavedSettings.getS32("RenderShadowDetail") > 0*/); // Vertex Shaders // mCtrlShaderEnable->setEnabled(LLFeatureManager::getInstance()->isFeatureAvailable("VertexShaderEnable")); @@ -550,8 +561,8 @@ void LLPanelDisplay::disableUnavailableSettings() mCtrlWindLight->setEnabled(FALSE); mCtrlWindLight->setValue(FALSE); - mCtrlReflections->setEnabled(FALSE); - mCtrlReflections->setValue(FALSE); + mCtrlReflectionDetail->setEnabled(FALSE); + mCtrlReflectionDetail->setValue(FALSE); mCtrlAvatarVP->setEnabled(FALSE); mCtrlAvatarVP->setValue(FALSE); @@ -561,8 +572,10 @@ void LLPanelDisplay::disableUnavailableSettings() mCtrlDeferred->setEnabled(FALSE); mCtrlDeferred->setValue(FALSE); - mCtrlSunShadow->setEnabled(FALSE); - mCtrlSunShadow->setValue(FALSE); + mCtrlDeferredGI->setEnabled(FALSE); + mCtrlDeferredGI->setValue(FALSE); + mCtrlShadowDetail->setEnabled(FALSE); + mCtrlShadowDetail->setValue(FALSE); } // disabled windlight @@ -573,10 +586,10 @@ void LLPanelDisplay::disableUnavailableSettings() } // disabled reflections - if(!LLFeatureManager::getInstance()->isFeatureAvailable("RenderWaterReflections")) + if(!LLFeatureManager::getInstance()->isFeatureAvailable("RenderReflectionDetail")) { - mCtrlReflections->setEnabled(FALSE); - mCtrlReflections->setValue(FALSE); + mCtrlReflectionDetail->setEnabled(FALSE); + mCtrlReflectionDetail->setValue(FALSE); } // disabled av @@ -605,8 +618,10 @@ void LLPanelDisplay::disableUnavailableSettings() { mCtrlDeferred->setEnabled(FALSE); mCtrlDeferred->setValue(FALSE); - mCtrlSunShadow->setEnabled(FALSE); - mCtrlSunShadow->setValue(FALSE); + mCtrlDeferredGI->setEnabled(FALSE); + mCtrlDeferredGI->setValue(FALSE); + mCtrlShadowDetail->setEnabled(FALSE); + mCtrlShadowDetail->setValue(FALSE); } } @@ -668,6 +683,7 @@ void LLPanelDisplay::setHiddenGraphicsState(bool isHidden) mCtrlFlexFactor->setVisible(!isHidden); mCtrlTreeFactor->setVisible(!isHidden); mCtrlAvatarFactor->setVisible(!isHidden); + mCtrlAvatarPhysicsFactor->setVisible(!isHidden); mCtrlTerrainFactor->setVisible(!isHidden); mCtrlSkyFactor->setVisible(!isHidden); mCtrlMaxParticle->setVisible(!isHidden); @@ -677,12 +693,12 @@ void LLPanelDisplay::setHiddenGraphicsState(bool isHidden) mFlexFactorText->setVisible(!isHidden); mTreeFactorText->setVisible(!isHidden); mAvatarFactorText->setVisible(!isHidden); + mAvatarPhysicsFactorText->setVisible(!isHidden); mTerrainFactorText->setVisible(!isHidden); mSkyFactorText->setVisible(!isHidden); mPostProcessText->setVisible(!isHidden); mCtrlBumpShiny->setVisible(!isHidden); - mCtrlReflections->setVisible(!isHidden); mCtrlWindLight->setVisible(!isHidden); mCtrlAvatarVP->setVisible(!isHidden); mCtrlShaderEnable->setVisible(!isHidden); @@ -694,7 +710,8 @@ void LLPanelDisplay::setHiddenGraphicsState(bool isHidden) mCtrlReflectionDetail->setVisible(!isHidden); mCtrlDeferred->setVisible(!isHidden); - mCtrlSunShadow->setVisible(!isHidden); + mCtrlDeferredGI->setVisible(!isHidden); + mCtrlShadowDetail->setVisible(!isHidden); // text boxes mShaderText->setVisible(!isHidden); @@ -704,6 +721,7 @@ void LLPanelDisplay::setHiddenGraphicsState(bool isHidden) mTerrainText->setVisible(!isHidden); mDrawDistanceMeterText1->setVisible(!isHidden); mDrawDistanceMeterText2->setVisible(!isHidden); + mShadowDetailText->setVisible(!isHidden); // hide one meter text if we're making things visible if(!isHidden) @@ -726,17 +744,18 @@ void LLPanelDisplay::cancel() gSavedSettings.setBOOL("RenderObjectBump", mBumpShiny); gSavedSettings.setBOOL("VertexShaderEnable", mShaderEnable); gSavedSettings.setBOOL("WindLightUseAtmosShaders", mWindLight); - gSavedSettings.setBOOL("RenderWaterReflections", mReflections); + gSavedSettings.setBOOL("RenderAvatarVP", mAvatarVP); gSavedSettings.setBOOL("RenderDeferred", mDeferred); - gSavedSettings.setBOOL("RenderDeferredSunShadow", mSunShadow); + gSavedSettings.setBOOL("RenderDeferredGI", mDeferredGI); gSavedSettings.setS32("RenderReflectionDetail", mReflectionDetail); + gSavedSettings.setS32("RenderShadowDetail", mShadowDetail); gSavedSettings.setBOOL("RenderUseImpostors", mAvatarImpostors); gSavedSettings.setBOOL("RenderAvatarCloth", mAvatarCloth); - gSavedSettings.setS32("RenderLightingDetail", mLightingDetail); + gSavedSettings.setBOOL("RenderLocalLights", mLocalLights); gSavedSettings.setS32("RenderTerrainDetail", mTerrainDetail); gSavedSettings.setF32("RenderFarClip", mRenderFarClip); @@ -989,6 +1008,13 @@ void LLPanelDisplay::updateSliderText(LLUICtrl* ctrl, void* user_data) return; } + //Hack to display 'Off' for avatar physics slider. + if(slider->getName() == "AvatarPhysicsDetail" && !slider->getValueF32()) + { + text_box->setText(std::string("Off")); + return; + } + // get range and points when text should change F32 range = slider->getMaxValue() - slider->getMinValue(); llassert(range > 0); @@ -1004,10 +1030,14 @@ void LLPanelDisplay::updateSliderText(LLUICtrl* ctrl, void* user_data) { text_box->setText(std::string("Mid")); } - else + else if(slider->getValueF32() < slider->getMaxValue()) { text_box->setText(std::string("High")); } + else + { + text_box->setText(std::string("Max")); + } } void LLPanelDisplay::updateMeterText(LLUICtrl* ctrl, void* user_data) diff --git a/indra/newview/llpaneldisplay.h b/indra/newview/llpaneldisplay.h index 677f1086c..a36311390 100644 --- a/indra/newview/llpaneldisplay.h +++ b/indra/newview/llpaneldisplay.h @@ -101,18 +101,19 @@ protected: LLSliderCtrl *mCtrlFlexFactor; // Timeslice for flexible objects LLSliderCtrl *mCtrlTreeFactor; // Control tree cutoff distance LLSliderCtrl *mCtrlAvatarFactor; // LOD for avatars + LLSliderCtrl *mCtrlAvatarPhysicsFactor; // Physics LOD for avatars LLSliderCtrl *mCtrlTerrainFactor; // LOD for terrain LLSliderCtrl *mCtrlSkyFactor; // LOD for terrain LLSliderCtrl *mCtrlMaxParticle; // Max Particle LLSliderCtrl *mCtrlPostProcess; // Max Particle LLCheckBoxCtrl *mCtrlBumpShiny; - LLCheckBoxCtrl *mCtrlReflections; LLCheckBoxCtrl *mCtrlWindLight; LLCheckBoxCtrl *mCtrlAvatarVP; LLCheckBoxCtrl *mCtrlShaderEnable; LLCheckBoxCtrl *mCtrlDeferred; - LLCheckBoxCtrl *mCtrlSunShadow; + LLCheckBoxCtrl *mCtrlDeferredGI; + LLComboBox *mCtrlShadowDetail; LLCheckBoxCtrl *mCtrlAvatarImpostors; LLCheckBoxCtrl *mCtrlAvatarCloth; LLRadioGroup *mRadioLightingDetail2; @@ -136,9 +137,11 @@ protected: LLTextBox *mFlexFactorText; LLTextBox *mTreeFactorText; LLTextBox *mAvatarFactorText; + LLTextBox *mAvatarPhysicsFactorText; LLTextBox *mTerrainFactorText; LLTextBox *mSkyFactorText; LLTextBox *mPostProcessText; + LLTextBox *mShadowDetailText; BOOL mFSAutoDetectAspect; F32 mAspectRatio; @@ -151,17 +154,17 @@ protected: BOOL mBumpShiny; BOOL mShaderEnable; BOOL mWindLight; - BOOL mReflections; BOOL mDeferred; - BOOL mSunShadow; + BOOL mDeferredGI; BOOL mAvatarVP; S32 mReflectionDetail; + S32 mShadowDetail; BOOL mAvatarImpostors; BOOL mAvatarCloth; S32 mAvatarMode; - S32 mLightingDetail; + BOOL mLocalLights; S32 mTerrainDetail; F32 mRenderFarClip; diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp index 483b755de..7e340d369 100644 --- a/indra/newview/llpanelface.cpp +++ b/indra/newview/llpanelface.cpp @@ -389,6 +389,11 @@ struct LLPanelFaceSetAlignedTEFunctor : public LLSelectedTEFunctor return true; } + if (facep->getViewerObject()->getVolume()->getNumVolumeFaces() <= te) + { + return true; + } + bool set_aligned = true; if (facep == mCenterFace) { @@ -431,6 +436,12 @@ struct LLPanelFaceGetIsAlignedTEFunctor : public LLSelectedTEFunctor { return false; } + + if (facep->getViewerObject()->getVolume()->getNumVolumeFaces() <= te) + { //volume face does not exist, can't be aligned + return false; + } + if (facep == mCenterFace) { return true; diff --git a/indra/newview/llpanelinventory.cpp b/indra/newview/llpanelinventory.cpp index 38c90783b..f892ff48e 100644 --- a/indra/newview/llpanelinventory.cpp +++ b/indra/newview/llpanelinventory.cpp @@ -447,7 +447,7 @@ BOOL LLTaskInvFVBridge::isItemMovable() else if ( (gRlvHandler.hasBehaviour(RLV_BHVR_UNSIT)) || (gRlvHandler.hasBehaviour(RLV_BHVR_SITTP)) ) { LLVOAvatar* pAvatar = gAgent.getAvatarObject(); - if ( (pAvatar) && (pAvatar->mIsSitting) && (pAvatar->getRoot() == pObj->getRootEdit()) ) + if ( (pAvatar) && (pAvatar->isSitting()) && (pAvatar->getRoot() == pObj->getRootEdit()) ) return FALSE; } } @@ -470,7 +470,7 @@ BOOL LLTaskInvFVBridge::isItemRemovable() else if ( (gRlvHandler.hasBehaviour(RLV_BHVR_UNSIT)) || (gRlvHandler.hasBehaviour(RLV_BHVR_SITTP)) ) { LLVOAvatar* pAvatar = gAgent.getAvatarObject(); - if ( (pAvatar) && (pAvatar->mIsSitting) && (pAvatar->getRoot() == pObjRoot) ) + if ( (pAvatar) && (pAvatar->isSitting()) && (pAvatar->getRoot() == pObjRoot) ) return FALSE; } } diff --git a/indra/newview/llpanelnetwork.cpp b/indra/newview/llpanelnetwork.cpp index 6e66628eb..6bc34989a 100644 --- a/indra/newview/llpanelnetwork.cpp +++ b/indra/newview/llpanelnetwork.cpp @@ -39,7 +39,7 @@ // project includes #include "llcheckboxctrl.h" #include "llradiogroup.h" -#include "lldirpicker.h" +#include "statemachine/aidirpicker.h" #include "lluictrlfactory.h" #include "llviewercontrol.h" #include "llviewerwindow.h" @@ -151,18 +151,24 @@ void LLPanelNetwork::onClickClearCache(void*) // static void LLPanelNetwork::onClickSetCache(void* user_data) { - LLPanelNetwork* self = (LLPanelNetwork*)user_data; - std::string cur_name(gSavedSettings.getString("CacheLocation")); std::string proposed_name(cur_name); - LLDirPicker& picker = LLDirPicker::instance(); - if (! picker.getDir(&proposed_name ) ) + AIDirPicker* dirpicker = new AIDirPicker(proposed_name, "cachelocation"); + dirpicker->run(boost::bind(&LLPanelNetwork::onClickSetCache_continued, user_data, dirpicker)); +} + +// static +void LLPanelNetwork::onClickSetCache_continued(void* user_data, AIDirPicker* dirpicker) +{ + if (!dirpicker->hasDirname()) { return; //Canceled! } - std::string dir_name = picker.getDirName(); + LLPanelNetwork* self = (LLPanelNetwork*)user_data; + std::string cur_name(gSavedSettings.getString("CacheLocation")); + std::string dir_name = dirpicker->getDirname(); if (!dir_name.empty() && dir_name != cur_name) { self->childSetText("cache_location", dir_name); diff --git a/indra/newview/llpanelnetwork.h b/indra/newview/llpanelnetwork.h index a5e2269a4..30dc471e6 100644 --- a/indra/newview/llpanelnetwork.h +++ b/indra/newview/llpanelnetwork.h @@ -35,6 +35,8 @@ #include "llpanel.h" +class AIDirPicker; + class LLPanelNetwork : public LLPanel { public: @@ -49,6 +51,7 @@ public: private: static void onClickClearCache(void*); static void onClickSetCache(void*); + static void onClickSetCache_continued(void* user_data, AIDirPicker* dirpicker); static void onClickResetCache(void*); static void onCommitPort(LLUICtrl* ctrl, void*); static void onCommitSocks5ProxyEnabled(LLUICtrl* ctrl, void* data); diff --git a/indra/newview/llpanelobject.cpp b/indra/newview/llpanelobject.cpp index ba4909d91..d448368ea 100644 --- a/indra/newview/llpanelobject.cpp +++ b/indra/newview/llpanelobject.cpp @@ -505,7 +505,7 @@ void LLPanelObject::getState( ) if ( (rlv_handler_t::isEnabled()) && ((gRlvHandler.hasBehaviour(RLV_BHVR_UNSIT)) || (gRlvHandler.hasBehaviour(RLV_BHVR_SITTP))) ) { LLVOAvatar* pAvatar = gAgent.getAvatarObject(); - if ( (pAvatar) && (pAvatar->mIsSitting) && (pAvatar->getRoot() == objectp->getRootEdit()) ) + if ( (pAvatar) && (pAvatar->isSitting()) && (pAvatar->getRoot() == objectp->getRootEdit()) ) enable_move = enable_scale = enable_rotate = FALSE; } // [/RLVa:KB] diff --git a/indra/newview/llpanelpick.cpp b/indra/newview/llpanelpick.cpp index c7f31f1f9..a33b3dd60 100644 --- a/indra/newview/llpanelpick.cpp +++ b/indra/newview/llpanelpick.cpp @@ -66,7 +66,7 @@ //For pick import and export - RK -#include "llfilepicker.h" +#include "statemachine/aifilepicker.h" #include "llviewernetwork.h" #include "llsdserialize.h" #include "hippogridmanager.h" @@ -201,14 +201,19 @@ void LLPanelPick::initNewPick() } //Imports a new pick from an xml - RK -bool LLPanelPick::importNewPick() +void LLPanelPick::importNewPick(void (*callback)(void*, bool), void* data) { - LLFilePicker& file_picker = LLFilePicker::instance(); + AIFilePicker* filepicker = AIFilePicker::create(); + filepicker->open(FFLOAD_XML, "", "export"); + filepicker->run(boost::bind(&LLPanelPick::importNewPick_continued, this, callback, data, filepicker)); +} - if(!file_picker.getOpenFile(LLFilePicker::FFLOAD_XML)) return false;// User canceled load. - else +void LLPanelPick::importNewPick_continued(void (*callback)(void*, bool), void* data, AIFilePicker* filepicker) +{ + bool result = false; + if (filepicker->hasFilename()) { - std::string file = file_picker.getFirstFile(); + std::string file = filepicker->getFilename(); llifstream importer(file); LLSD data; @@ -231,19 +236,25 @@ bool LLPanelPick::importNewPick() mImporting = true; sendPickInfoUpdate(); - return true; + result = true; } + (*callback)(data, result); } //Exports a pick to an XML - RK void LLPanelPick::exportPick() { - LLFilePicker& file_picker = LLFilePicker::instance(); - - if(!file_picker.getSaveFile(LLFilePicker::FFSAVE_XML)) - return;// User canceled save. + AIFilePicker* filepicker = AIFilePicker::create(); + filepicker->open("", FFSAVE_XML, "", "export"); + filepicker->run(boost::bind(&LLPanelPick::exportPick_continued, this, filepicker)); +} - std::string destination = file_picker.getFirstFile(); +void LLPanelPick::exportPick_continued(AIFilePicker* filepicker) +{ + if (!filepicker->hasFilename()) + return; + + std::string destination = filepicker->getFilename(); LLSD datas; diff --git a/indra/newview/llpanelpick.h b/indra/newview/llpanelpick.h index 49b07924c..bfa702251 100644 --- a/indra/newview/llpanelpick.h +++ b/indra/newview/llpanelpick.h @@ -50,6 +50,7 @@ class LLTextEditor; class LLTextureCtrl; class LLUICtrl; class LLMessageSystem; +class AIFilePicker; class LLPanelPick : public LLPanel { @@ -70,8 +71,10 @@ public: void initNewPick(); //Pick import and export - RK - bool importNewPick(); + void importNewPick(void (*callback)(void*, bool), void* data); + void importNewPick_continued(void (*callback)(void*, bool), void* data, AIFilePicker* filepicker); void exportPick(); + void exportPick_continued(AIFilePicker* filepicker); // We need to know the creator id so the database knows which partition // to query for the pick data. diff --git a/indra/newview/llphysicsmotion.cpp b/indra/newview/llphysicsmotion.cpp index d69ebd0b2..af775f59f 100644 --- a/indra/newview/llphysicsmotion.cpp +++ b/indra/newview/llphysicsmotion.cpp @@ -131,7 +131,8 @@ protected: { return sDefaultController[controller_key]; } - return mCharacter->getVisualParamWeight((*entry).second.c_str()); + const std::string& param_name = (*entry).second.c_str(); + return mCharacter->getVisualParamWeight(param_name.c_str()); } void setParamValue(LLViewerVisualParam *param, const F32 new_value_local, @@ -496,7 +497,9 @@ BOOL LLPhysicsMotionController::onUpdate(F32 time, U8* joint_mask) { // Skip if disabled globally. static const LLCachedControl avatar_physics("AvatarPhysics",false); - if (!avatar_physics || (!((LLVOAvatar*)mCharacter)->isSelf() && !((LLVOAvatar*)mCharacter)->mSupportsPhysics)) + bool supports_physics = !avatar_physics || (!((LLVOAvatar*)mCharacter)->isSelf() && !((LLVOAvatar*)mCharacter)->mSupportsPhysics); + //Treat lod 0 as AvatarPhyiscs:FALSE. AvatarPhyiscs setting is superfluous unless we decide to hook it into param sending. + if (supports_physics || !LLVOAvatar::sPhysicsLODFactor) { if(!mIsDefault) { @@ -507,6 +510,7 @@ BOOL LLPhysicsMotionController::onUpdate(F32 time, U8* joint_mask) } mCharacter->updateVisualParams(); } + if(!supports_physics) //Only use emerald physics if avatarphysiscs is really off, or the client doesn't seem to support new physics. ((LLVOAvatar*)mCharacter)->idleUpdateBoobEffect(); //Fall back to emerald physics return TRUE; } diff --git a/indra/newview/llpolymesh.cpp b/indra/newview/llpolymesh.cpp index a23c199c9..3a82e7304 100644 --- a/indra/newview/llpolymesh.cpp +++ b/indra/newview/llpolymesh.cpp @@ -863,6 +863,687 @@ LLPolyMesh *LLPolyMesh::getMesh(const std::string &name, LLPolyMesh* reference_m return poly_mesh; } +//----------------------------------------------------------------------------- +// LLPolyMesh::getMeshData() +//----------------------------------------------------------------------------- +LLPolyMeshSharedData *LLPolyMesh::getMeshData(const std::string &name) +{ + //------------------------------------------------------------------------- + // search for an existing mesh by this name + //------------------------------------------------------------------------- + LLPolyMeshSharedData* mesh_shared_data = get_if_there(sGlobalSharedMeshList, name, (LLPolyMeshSharedData*)NULL); + + return mesh_shared_data; +} + +//----------------------------------------------------------------------------- +// LLPolyMesh::saveLLM() +//----------------------------------------------------------------------------- +BOOL LLPolyMesh::saveLLM(LLFILE *fp) +{ + if (!fp) + return FALSE; + + //------------------------------------------------------------------------- + // Write a header + //------------------------------------------------------------------------- + if (fwrite(HEADER_BINARY, 1, strlen(HEADER_BINARY), fp) != strlen(HEADER_BINARY)) + { + llwarns << "Short write" << llendl; + } + + if (strlen(HEADER_BINARY) < 24) + { + char padding[24] = {}; // zeroes + int pad = 24 - strlen(HEADER_BINARY); + if (fwrite(&padding, 1, pad, fp) != pad) + { + llwarns << "Short write" << llendl; + } + } + + //---------------------------------------------------------------- + // HasWeights + //---------------------------------------------------------------- + U8 hasWeights = (U8) mSharedData->mHasWeights; + if (fwrite(&hasWeights, sizeof(U8), 1, fp) != 1) + { + llwarns << "Short write" << llendl; + } + + //---------------------------------------------------------------- + // HasDetailTexCoords + //---------------------------------------------------------------- + U8 hasDetailTexCoords = (U8) mSharedData->mHasDetailTexCoords; + if (fwrite(&hasDetailTexCoords, sizeof(U8), 1, fp) != 1) + { + llwarns << "Short write" << llendl; + } + + //---------------------------------------------------------------- + // Position + //---------------------------------------------------------------- + LLVector3 position = mSharedData->mPosition; + llendianswizzle(position.mV, sizeof(float), 3); + if (fwrite(position.mV, sizeof(float), 3, fp) != 3) + { + llwarns << "Short write" << llendl; + } + + //---------------------------------------------------------------- + // Rotation + //---------------------------------------------------------------- + LLQuaternion rotation = mSharedData->mRotation; + F32 roll; + F32 pitch; + F32 yaw; + + rotation.getEulerAngles(&roll, &pitch, &yaw); + + roll *= RAD_TO_DEG; + pitch *= RAD_TO_DEG; + yaw *= RAD_TO_DEG; + + LLVector3 rotationAngles (roll, pitch, yaw); + llendianswizzle(rotationAngles.mV, sizeof(float), 3); + if (fwrite(rotationAngles.mV, sizeof(float), 3, fp) != 3) + { + llwarns << "Short write" << llendl; + } + + U8 rotationOrder = 0; + if (fwrite(&rotationOrder, sizeof(U8), 1, fp) != 1) + { + llwarns << "Short write" << llendl; + } + + //---------------------------------------------------------------- + // Scale + //---------------------------------------------------------------- + LLVector3 scale = mSharedData->mScale; + llendianswizzle(scale.mV, sizeof(float), 3); + if (fwrite(scale.mV, sizeof(float), 3, fp) != 3) + { + llwarns << "Short write" << llendl; + } + + //---------------------------------------------------------------- + // NumVertices + //---------------------------------------------------------------- + U16 numVertices = mSharedData->mNumVertices; + + if (!isLOD()) + { + llendianswizzle(&numVertices, sizeof(U16), 1); + if (fwrite(&numVertices, sizeof(U16), 1, fp) != 1) + { + llwarns << "Short write" << llendl; + } + numVertices = mSharedData->mNumVertices; // without the swizzle again + + //---------------------------------------------------------------- + // Coords + //---------------------------------------------------------------- + LLVector3* coords = mSharedData->mBaseCoords; + + llendianswizzle(coords, sizeof(float), 3*numVertices); + if (fwrite(coords, 3*sizeof(float), numVertices, fp) != numVertices) + { + llwarns << "Short write" << llendl; + } + llendianswizzle(coords, sizeof(float), 3*numVertices); + + //---------------------------------------------------------------- + // Normals + //---------------------------------------------------------------- + LLVector3* normals = mSharedData->mBaseNormals; + + llendianswizzle(normals, sizeof(float), 3*numVertices); + if (fwrite(normals, 3*sizeof(float), numVertices, fp) != numVertices) + { + llwarns << "Short write" << llendl; + } + llendianswizzle(normals, sizeof(float), 3*numVertices); + + //---------------------------------------------------------------- + // Binormals + //---------------------------------------------------------------- + LLVector3* binormals = mSharedData->mBaseBinormals; + + llendianswizzle(binormals, sizeof(float), 3*numVertices); + if (fwrite(binormals, 3*sizeof(float), numVertices, fp) != numVertices) + { + llwarns << "Short write" << llendl; + } + llendianswizzle(binormals, sizeof(float), 3*numVertices); + + //---------------------------------------------------------------- + // TexCoords + //---------------------------------------------------------------- + LLVector2* tex = mSharedData->mTexCoords; + + llendianswizzle(tex, sizeof(float), 2*numVertices); + if (fwrite(tex, 2*sizeof(float), numVertices, fp) != numVertices) + { + llwarns << "Short write" << llendl; + } + llendianswizzle(tex, sizeof(float), 2*numVertices); + + //---------------------------------------------------------------- + // DetailTexCoords + //---------------------------------------------------------------- + if (hasDetailTexCoords) + { + LLVector2* detail = mSharedData->mDetailTexCoords; + + llendianswizzle(detail, sizeof(float), 2*numVertices); + if (fwrite(detail, 2*sizeof(float), numVertices, fp) != numVertices) + { + llwarns << "Short write" << llendl; + } + llendianswizzle(detail, sizeof(float), 2*numVertices); + } + + //---------------------------------------------------------------- + // Weights + //---------------------------------------------------------------- + if (hasWeights) + { + F32* weights = mSharedData->mWeights; + + llendianswizzle(weights, sizeof(float), numVertices); + if (fwrite(weights, sizeof(float), numVertices, fp) != numVertices) + { + llwarns << "Short write" << llendl; + } + llendianswizzle(weights, sizeof(float), numVertices); + } + } + + //---------------------------------------------------------------- + // NumFaces + //---------------------------------------------------------------- + U16 numFaces = mSharedData->mNumFaces; + + llendianswizzle(&numFaces, sizeof(U16), 1); + if (fwrite(&numFaces, sizeof(U16), 1, fp) != 1) + { + llwarns << "Short write" << llendl; + } + numFaces = mSharedData->mNumFaces; // without the swizzle again + + //---------------------------------------------------------------- + // Faces + //---------------------------------------------------------------- + LLPolyFace* faces = mSharedData->mFaces; + S16 face[3]; + U32 i; + for (i = 0; i < numFaces; i++) + { + face[0] = faces[i][0]; + face[1] = faces[i][1]; + face[2] = faces[i][2]; + + llendianswizzle(face, sizeof(U16), 3); + if (fwrite(face, sizeof(U16), 3, fp) != 3) + { + llwarns << "Short write" << llendl; + } + } + + //---------------------------------------------------------------- + // NumSkinJoints + //---------------------------------------------------------------- + + // When reading LOD mesh files, we stop here, but the actual Linden + // .llm files have data with zero items for these, so we do the same. + + U16 numSkinJoints = mSharedData->mNumJointNames; + + // At least one element is always allocated but it may be empty + std::string *jn = &mSharedData->mJointNames[0]; + + if ((numSkinJoints == 1) + && (jn->length() == 0)) + { + numSkinJoints = 0; + } + + if ( hasWeights ) + { + llendianswizzle(&numSkinJoints, sizeof(U16), 1); + if (fwrite(&numSkinJoints, sizeof(U16), 1, fp) != 1) + { + llwarns << "Short write" << llendl; + } + llendianswizzle(&numSkinJoints, sizeof(U16), 1); + + //---------------------------------------------------------------- + // SkinJoints + //---------------------------------------------------------------- + char padding[64] = {}; // zeroes + for (i=0; i < numSkinJoints; i++) + { + jn = &mSharedData->mJointNames[i]; + if (fwrite(jn->c_str(), 1, jn->length(), fp) != jn->length()) + { + llwarns << "Short write" << llendl; + } + + if (jn->length() < 64) + { + int pad = 64 - jn->length(); + if (fwrite(&padding, 1, pad, fp) != pad) + { + llwarns << "Short write" << llendl; + } + } + } + } + + //------------------------------------------------------------------------- + // look for morph section + //------------------------------------------------------------------------- + LLPolyMeshSharedData::morphdata_list_t::iterator iter = mSharedData->mMorphData.begin(); + LLPolyMeshSharedData::morphdata_list_t::iterator end = mSharedData->mMorphData.end(); + + // Sort them + morph_list_t morph_list; + for (; iter != end; ++iter) + { + LLPolyMorphData *morph_data = *iter; + std::string morph_name = morph_data->getName(); + + morph_list.insert(std::pair(morph_name, morph_data)); + } + + char padding[64] = {}; // zeroes + for (morph_list_t::iterator morph_iter = morph_list.begin(); + morph_iter != morph_list.end(); ++morph_iter) + { + const std::string& morph_name = morph_iter->first; + LLPolyMorphData* morph_data = morph_iter->second; + + if (fwrite(morph_name.c_str(), 1, morph_name.length(), fp) != morph_name.length()) + { + llwarns << "Short write" << llendl; + } + + if (morph_name.length() < 64) + { + int pad = 64 - morph_name.length(); + if (fwrite(&padding, 1, pad, fp) != pad) + { + llwarns << "Short write" << llendl; + } + } + + if (!morph_data->saveLLM(fp)) + { + llwarns << "Problem writing morph" << llendl; + } + } + + char end_morphs[64] = "End Morphs"; // padded with zeroes + if (fwrite(end_morphs, sizeof(char), 64, fp) != 64) + { + llwarns << "Short write" << llendl; + } + + //------------------------------------------------------------------------- + // Remaps + //------------------------------------------------------------------------- + S32 numRemaps = mSharedData->mSharedVerts.size(); + llendianswizzle(&numRemaps, sizeof(S32), 1); + if (fwrite(&numRemaps, sizeof(S32), 1, fp) != 1) + { + llwarns << "Short write" << llendl; + } + + std::map::iterator remap_iter = mSharedData->mSharedVerts.begin(); + std::map::iterator remap_end = mSharedData->mSharedVerts.end(); + + for (; remap_iter != remap_end; ++remap_iter) + { + S32 remapSrc = remap_iter->first; + + llendianswizzle(&remapSrc, sizeof(S32), 1); + if (fwrite(&remapSrc, sizeof(S32), 1, fp) != 1) + { + llwarns << "Short write" << llendl; + } + + S32 remapDst = remap_iter->second; + + llendianswizzle(&remapDst, sizeof(S32), 1); + if (fwrite(&remapDst, sizeof(S32), 1, fp) != 1) + { + llwarns << "Short write" << llendl; + } + } + + return TRUE; +} + +//----------------------------------------------------------------------------- +// LLPolyMesh::saveOBJ() +//----------------------------------------------------------------------------- +BOOL LLPolyMesh::saveOBJ(LLFILE *fp) +{ + if (!fp) + return FALSE; + + // If it's an LOD mesh, the LOD vertices are usually at the start of the + // list of vertices, so the number of vertices is just that subset. + // We could also write out the rest of the vertices in case someone wants + // to choose new vertices for the LOD mesh, but that may confuse some people. + + int nverts = mSharedData->mNumVertices; + int nfaces = mSharedData->mNumFaces; + int i; + + LLVector3* coords = getWritableCoords(); + for ( i=0; imNumVertices; + int ntris = mSharedData->mNumFaces; + + int nfaces = 0; + int ncoords = 0; + int nnormals = 0; + int ntexcoords = 0; + + LLVector3* coords = getWritableCoords(); + LLVector3* normals = getWritableNormals(); + LLVector3* binormals = getWritableBinormals(); + LLVector2* tex = getWritableTexCoords(); + LLPolyFace* faces = getFaces(); + + const S32 BUFSIZE = 16384; + char buffer[BUFSIZE]; + // *NOTE: changing the size or type of these buffers will require + // changing the sscanf below. + char keyword[256]; + keyword[0] = 0; + F32 tempX; + F32 tempY; + F32 tempZ; + S32 values; + + while (!feof(fp)) + { + if (fgets(buffer, BUFSIZE, fp) == NULL) + { + buffer[0] = '\0'; + } + + if (sscanf (buffer," %255s", keyword) != 1) + { + // blank line + continue; + } + + if (!strcmp("v", keyword)) + { + values = sscanf (buffer," %255s %f %f %f", keyword, &tempX, &tempY, &tempZ); + if (values != 4) + { + llwarns << "Expecting v x y z, but found: " << buffer <mBaseCoords, mCoords, sizeof(LLVector3) * mSharedData->mNumVertices); + memcpy(mSharedData->mBaseNormals, mNormals, sizeof(LLVector3) * mSharedData->mNumVertices); + memcpy(mSharedData->mBaseBinormals, mBinormals, sizeof(LLVector3) * mSharedData->mNumVertices); + memcpy(mSharedData->mTexCoords, mTexCoords, sizeof(LLVector2) * mSharedData->mNumVertices); + + // Update all avatars by applying the delta + + std::vector< LLCharacter* >::iterator avatar_it; + for(avatar_it = LLCharacter::sInstances.begin(); avatar_it != LLCharacter::sInstances.end(); ++avatar_it) + { + LLVOAvatar* avatarp = (LLVOAvatar*)*avatar_it; + LLPolyMesh* mesh = avatarp->getMesh(mSharedData); + if (mesh) + { + LLVector3 *mesh_coords = mesh->getWritableCoords(); + LLVector3 *mesh_normals = mesh->getWritableNormals(); + LLVector3 *mesh_binormals = mesh->getWritableBinormals(); + LLVector2 *mesh_tex_coords = mesh->getWritableTexCoords(); + LLVector3 *mesh_scaled_normals = mesh->getScaledNormals(); + LLVector3 *mesh_scaled_binormals = mesh->getScaledBinormals(); + + for( vert_index = 0; vert_index < nverts; vert_index++) + { + mesh_coords[vert_index] -= delta_coords[vert_index]; + mesh_tex_coords[vert_index] -= delta_tex_coords[vert_index]; + + mesh_scaled_normals[vert_index] -= delta_normals[vert_index]; + LLVector3 normalized_normal = mesh_scaled_normals[vert_index]; + normalized_normal.normVec(); + mesh_normals[vert_index] = normalized_normal; + + mesh_scaled_binormals[vert_index] -= delta_binormals[vert_index]; + LLVector3 tangent = mesh_scaled_binormals[vert_index] % normalized_normal; + LLVector3 normalized_binormal = normalized_normal % tangent; + normalized_binormal.normVec(); + mesh_binormals[vert_index] = normalized_binormal; + } + + avatarp->dirtyMesh(); + } + } + + return TRUE; +} + +//----------------------------------------------------------------------------- +// LLPolyMesh::getSharedMeshName() +//----------------------------------------------------------------------------- +std::string const* LLPolyMesh::getSharedMeshName(LLPolyMeshSharedData* shared) +{ + //------------------------------------------------------------------------- + // search for an existing mesh with this shared data + //------------------------------------------------------------------------- + for(LLPolyMeshSharedDataTable::iterator iter = sGlobalSharedMeshList.begin(); iter != sGlobalSharedMeshList.end(); ++iter) + { + std::string const* mesh_name = &iter->first; + LLPolyMeshSharedData* mesh = iter->second; + + if (mesh == shared) + return mesh_name; + } + + return NULL; +} + //----------------------------------------------------------------------------- // LLPolyMesh::freeAllMeshes() //----------------------------------------------------------------------------- @@ -882,7 +1563,7 @@ LLPolyMeshSharedData *LLPolyMesh::getSharedData() const //-------------------------------------------------------------------- // LLPolyMesh::dumpDiagInfo() //-------------------------------------------------------------------- -void LLPolyMesh::dumpDiagInfo() +void LLPolyMesh::dumpDiagInfo(void*) { // keep track of totals U32 total_verts = 0; @@ -893,7 +1574,7 @@ void LLPolyMesh::dumpDiagInfo() llinfos << "-----------------------------------------------------" << llendl; llinfos << " Global PolyMesh Table (DEBUG only)" << llendl; - llinfos << " Verts Faces Mem(KB) Name" << llendl; + llinfos << " Verts Faces Mem(KB) Type Name" << llendl; llinfos << "-----------------------------------------------------" << llendl; // print each loaded mesh, and it's memory usage @@ -907,7 +1588,14 @@ void LLPolyMesh::dumpDiagInfo() S32 num_faces = mesh->mNumFaces; U32 num_kb = mesh->getNumKB(); - buf = llformat("%8d %8d %8d %s", num_verts, num_faces, num_kb, mesh_name.c_str()); + std::string type; + if (mesh->isLOD()) { + type = "LOD "; + } else { + type = "base"; + } + + buf = llformat("%8d %8d %8d %s %s", num_verts, num_faces, num_kb, type.c_str(), mesh_name.c_str()); llinfos << buf << llendl; total_verts += num_verts; @@ -996,6 +1684,32 @@ void LLPolyMesh::initializeForMorph() memset(mClothingWeights, 0, sizeof(LLVector4) * mSharedData->mNumVertices); } +//----------------------------------------------------------------------------- +// getMorphList() +//----------------------------------------------------------------------------- +void LLPolyMesh::getMorphList (const std::string& mesh_name, morph_list_t* morph_list) +{ + if (!morph_list) + return; + + LLPolyMeshSharedData* mesh_shared_data = get_if_there(sGlobalSharedMeshList, mesh_name, (LLPolyMeshSharedData*)NULL); + + if (!mesh_shared_data) + return; + + LLPolyMeshSharedData::morphdata_list_t::iterator iter = mesh_shared_data->mMorphData.begin(); + LLPolyMeshSharedData::morphdata_list_t::iterator end = mesh_shared_data->mMorphData.end(); + + for (; iter != end; ++iter) + { + LLPolyMorphData *morph_data = *iter; + std::string morph_name = morph_data->getName(); + + morph_list->insert(std::pair(morph_name, morph_data)); + } + return; +} + //----------------------------------------------------------------------------- // getMorphData() //----------------------------------------------------------------------------- diff --git a/indra/newview/llpolymesh.h b/indra/newview/llpolymesh.h index c23617749..15c284a1a 100644 --- a/indra/newview/llpolymesh.h +++ b/indra/newview/llpolymesh.h @@ -174,6 +174,24 @@ public: // otherwise it is loaded from file, added to the table, and returned. static LLPolyMesh *getMesh( const std::string &name, LLPolyMesh* reference_mesh = NULL); + // Saves the mesh information as a binary Linden Lab Mesh file. + BOOL saveLLM(LLFILE *fp); + + // Saves the mesh information as an OBJ file. + BOOL saveOBJ(LLFILE *fp); + + // Loads new mesh information from an OBJ file. + BOOL loadOBJ(LLFILE *fp); + + // Copies the current mesh to the base mesh. + BOOL setSharedFromCurrent(); + + // Gets the name of the mesh corresponding to the shared data + static const std::string* getSharedMeshName(LLPolyMeshSharedData* shared); + + // Requests mesh data by name. Returns null if not found. + static LLPolyMeshSharedData *getMeshData( const std::string &name ); + // Frees all loaded meshes. // This should only be called once you know there are no outstanding // references to these objects. Generally, upon exit of the application. @@ -312,6 +330,9 @@ public: return mSharedData->mJointNames; } + typedef std::map morph_list_t; + static void getMorphList (const std::string& mesh_name, morph_list_t* morph_list); + LLPolyMorphData* getMorphData(const std::string& morph_name); // void removeMorphData(LLPolyMorphData *morph_target); // void deleteAllMorphData(); @@ -334,11 +355,12 @@ public: U32 mFaceIndexOffset; U32 mFaceIndexCount; U32 mCurVertexCount; -private: - void initializeForMorph(); // Dumps diagnostic information about the global mesh table - static void dumpDiagInfo(); + static void dumpDiagInfo(void*); + +private: + void initializeForMorph(); protected: // mesh data shared across all instances of a given mesh diff --git a/indra/newview/llpolymorph.cpp b/indra/newview/llpolymorph.cpp index 72a332440..4cf59a209 100644 --- a/indra/newview/llpolymorph.cpp +++ b/indra/newview/llpolymorph.cpp @@ -43,6 +43,7 @@ //#include "../tools/imdebug/imdebug.h" const F32 NORMAL_SOFTEN_FACTOR = 0.65f; +const F32 SIGNIFICANT_DELTA = 0.0001f; //----------------------------------------------------------------------------- // LLPolyMorphData() @@ -210,6 +211,297 @@ BOOL LLPolyMorphData::loadBinary(LLFILE *fp, LLPolyMeshSharedData *mesh) return TRUE; } +//----------------------------------------------------------------------------- +// LLPolyMesh::saveLLM() +//----------------------------------------------------------------------------- +BOOL LLPolyMorphData::saveLLM(LLFILE *fp) +{ + if (!fp) + return FALSE; + + S32 numVertices = mNumIndices; + + llendianswizzle(&numVertices, sizeof(S32), 1); + if (fwrite(&numVertices, sizeof(S32), 1, fp) != 1) + { + llwarns << "Short write" << llendl; + } + numVertices = mNumIndices; // without the swizzle again + + //------------------------------------------------------------------------- + // write vertices + //------------------------------------------------------------------------- + for(S32 v = 0; v < numVertices; v++) + { + llendianswizzle(&mVertexIndices[v], sizeof(U32), 1); + if (fwrite(&mVertexIndices[v], sizeof(U32), 1, fp) != 1) + { + llwarns << "Short write" << llendl; + } + llendianswizzle(&mVertexIndices[v], sizeof(U32), 1); + + llendianswizzle(&mCoords[v].mV, sizeof(F32), 3); + if (fwrite(&mCoords[v].mV, sizeof(F32), 3, fp) != 3) + { + llwarns << "Short write" << llendl; + } + llendianswizzle(&mCoords[v].mV, sizeof(F32), 3); + + llendianswizzle(&mNormals[v].mV, sizeof(F32), 3); + if (fwrite(&mNormals[v].mV, sizeof(F32), 3, fp) != 3) + { + llwarns << "Short write" << llendl; + } + llendianswizzle(&mNormals[v].mV, sizeof(F32), 3); + + llendianswizzle(&mBinormals[v].mV, sizeof(F32), 3); + if (fwrite(&mBinormals[v].mV, sizeof(F32), 3, fp) != 3) + { + llwarns << "Short write" << llendl; + } + llendianswizzle(&mBinormals[v].mV, sizeof(F32), 3); + + llendianswizzle(&mTexCoords[v].mV, sizeof(F32), 2); + if (fwrite(&mTexCoords[v].mV, sizeof(F32), 2, fp) != 2) + { + llwarns << "Short write" << llendl; + } + llendianswizzle(&mTexCoords[v].mV, sizeof(F32), 2); + } + + return TRUE; +} + +//----------------------------------------------------------------------------- +// saveOBJ() +//----------------------------------------------------------------------------- +BOOL LLPolyMorphData::saveOBJ(LLFILE *fp) +{ + if (!fp) + return FALSE; + + LLPolyMesh mesh(mMesh, NULL); + + LLVector3 *coords = mesh.getWritableCoords(); + LLVector3 *normals = mesh.getWritableNormals(); + LLVector2 *tex_coords = mesh.getWritableTexCoords(); + + for(U32 vert_index_morph = 0; vert_index_morph < mNumIndices; vert_index_morph++) + { + S32 vert_index_mesh = mVertexIndices[vert_index_morph]; + + coords[vert_index_mesh] += mCoords[vert_index_morph]; + normals[vert_index_mesh] += mNormals[vert_index_morph]; + normals[vert_index_mesh].normVec(); + tex_coords[vert_index_mesh] += mTexCoords[vert_index_morph]; + } + + return mesh.saveOBJ(fp); +} + +//----------------------------------------------------------------------------- +// setMorphFromMesh() +//----------------------------------------------------------------------------- +BOOL LLPolyMorphData::setMorphFromMesh(LLPolyMesh *morph) +{ + if (!morph) + return FALSE; + + LLVector3 *morph_coords = morph->getWritableCoords(); + LLVector3 *morph_normals = morph->getWritableNormals(); + LLVector3 *morph_binormals = morph->getWritableBinormals(); + LLVector2 *morph_tex_coords = morph->getWritableTexCoords(); + + // We now have the morph loaded as a mesh. We have to subtract the + // base mesh to get the delta morph. + + LLPolyMesh delta(mMesh, NULL); + U32 nverts = delta.getNumVertices(); + + LLVector3 *delta_coords = delta.getWritableCoords(); + LLVector3 *delta_normals = delta.getWritableNormals(); + LLVector3 *delta_binormals = delta.getWritableBinormals(); + LLVector2 *delta_tex_coords = delta.getWritableTexCoords(); + + U32 num_significant = 0; + U32 vert_index; + for( vert_index = 0; vert_index < nverts; vert_index++) + { + delta_coords[vert_index] = morph_coords[vert_index] - delta_coords[vert_index]; + delta_normals[vert_index] = morph_normals[vert_index] - delta_normals[vert_index]; + delta_binormals[vert_index] = morph_binormals[vert_index] - delta_binormals[vert_index]; + delta_tex_coords[vert_index] = morph_tex_coords[vert_index] - delta_tex_coords[vert_index]; + + // For the normals and binormals, we really want the deltas + // to be perpendicular to the mesh (bi)normals in the plane + // that contains both the mesh and morph (bi)normals, such + // that the morph (bi)normals form the hypotenuses of right + // triangles. Right now, we just compute the difference vector. + + if (delta_coords[vert_index].length() > SIGNIFICANT_DELTA + || delta_normals[vert_index].length() > SIGNIFICANT_DELTA + || delta_binormals[vert_index].length() > SIGNIFICANT_DELTA + || delta_tex_coords[vert_index].length() > SIGNIFICANT_DELTA) + { + num_significant++; + } + } + + //------------------------------------------------------------------------- + // compute new morph + //------------------------------------------------------------------------- + + // If the morph matches the base mesh, we store one vertex to prevent + // zero length vectors. + + U32 nindices = num_significant; + if (num_significant == 0) + nindices = 1; + + LLVector3* new_coords = new LLVector3[nindices]; + LLVector3* new_normals = new LLVector3[nindices]; + LLVector3* new_binormals = new LLVector3[nindices]; + LLVector2* new_tex_coords = new LLVector2[nindices]; + U32* new_vertex_indices = new U32[nindices]; + + // We'll set the distortion directly + mTotalDistortion = 0.f; + mMaxDistortion = 0.f; + mAvgDistortion.zeroVec(); + + U32 morph_index = 0; + for( vert_index = 0; vert_index < nverts; vert_index++) + { + if (delta_coords[vert_index].length() > SIGNIFICANT_DELTA + || delta_normals[vert_index].length() > SIGNIFICANT_DELTA + || delta_binormals[vert_index].length() > SIGNIFICANT_DELTA + || delta_tex_coords[vert_index].length() > SIGNIFICANT_DELTA + || num_significant == 0) + { + new_vertex_indices[morph_index] = vert_index; + + new_coords[morph_index] = delta_coords[vert_index]; + new_normals[morph_index] = delta_normals[vert_index]; + new_binormals[morph_index] = delta_binormals[vert_index]; + new_tex_coords[morph_index] = delta_tex_coords[vert_index]; + + F32 magnitude = new_coords[morph_index].magVec(); + + mTotalDistortion += magnitude; + mAvgDistortion.mV[VX] += fabs(new_coords[morph_index].mV[VX]); + mAvgDistortion.mV[VY] += fabs(new_coords[morph_index].mV[VY]); + mAvgDistortion.mV[VZ] += fabs(new_coords[morph_index].mV[VZ]); + + if (magnitude > mMaxDistortion) + { + mMaxDistortion = magnitude; + } + + morph_index++; + num_significant = 1; + } + } + + mAvgDistortion = mAvgDistortion * (1.f/(F32)nindices); + mAvgDistortion.normVec(); + + //------------------------------------------------------------------------- + // compute the change in the morph + //------------------------------------------------------------------------- + + // Because meshes are set by continually updating morph weights + // there is no easy way to reapply the morphs, so we just compute + // the change in this morph and apply that appropriately weighted. + + for( morph_index = 0; morph_index < mNumIndices; morph_index++) + { + vert_index = mVertexIndices[morph_index]; + + delta_coords[vert_index] -= mCoords[morph_index]; + delta_normals[vert_index] -= mNormals[morph_index]; + delta_binormals[vert_index] -= mBinormals[morph_index]; + delta_tex_coords[vert_index] -= mTexCoords[morph_index]; + } + + //------------------------------------------------------------------------- + // Update all avatars + //------------------------------------------------------------------------- + + std::vector< LLCharacter* >::iterator avatar_it; + for(avatar_it = LLCharacter::sInstances.begin(); avatar_it != LLCharacter::sInstances.end(); ++avatar_it) + { + LLVOAvatar* avatarp = (LLVOAvatar*)*avatar_it; + + LLPolyMorphTarget* param = (LLPolyMorphTarget*) avatarp->getVisualParam(mName.c_str()); + if (!param) + { + continue; + } + + F32 weight = param->getLastWeight(); + if (weight == 0.0f) + { + continue; + } + + LLPolyMesh* mesh = avatarp->getMesh(mMesh); + if (!mesh) + { + continue; + } + + // If we have a vertex mask, just remove it. It will be recreated. + if (param->undoMask(TRUE)) + { + continue; + } + + LLVector3 *mesh_coords = mesh->getWritableCoords(); + LLVector3 *mesh_normals = mesh->getWritableNormals(); + LLVector3 *mesh_binormals = mesh->getWritableBinormals(); + LLVector2 *mesh_tex_coords = mesh->getWritableTexCoords(); + LLVector3 *mesh_scaled_normals = mesh->getScaledNormals(); + LLVector3 *mesh_scaled_binormals = mesh->getScaledBinormals(); + + for( vert_index = 0; vert_index < nverts; vert_index++) + { + mesh_coords[vert_index] += delta_coords[vert_index] * weight; + mesh_tex_coords[vert_index] += delta_tex_coords[vert_index] * weight; + + mesh_scaled_normals[vert_index] += delta_normals[vert_index] * weight * NORMAL_SOFTEN_FACTOR; + LLVector3 normalized_normal = mesh_scaled_normals[vert_index]; + normalized_normal.normVec(); + mesh_normals[vert_index] = normalized_normal; + + mesh_scaled_binormals[vert_index] += delta_binormals[vert_index] * weight * NORMAL_SOFTEN_FACTOR; + LLVector3 tangent = mesh_scaled_binormals[vert_index] % normalized_normal; + LLVector3 normalized_binormal = normalized_normal % tangent; + normalized_binormal.normVec(); + mesh_binormals[vert_index] = normalized_binormal; + } + + avatarp->dirtyMesh(); + } + + //------------------------------------------------------------------------- + // reallocate vertices + //------------------------------------------------------------------------- + delete [] mVertexIndices; + delete [] mCoords; + delete [] mNormals; + delete [] mBinormals; + delete [] mTexCoords; + + mVertexIndices = new_vertex_indices; + mCoords = new_coords; + mNormals = new_normals; + mBinormals = new_binormals; + mTexCoords = new_tex_coords; + mNumIndices = nindices; + + return TRUE; +} + //----------------------------------------------------------------------------- // LLPolyMorphTargetInfo() //----------------------------------------------------------------------------- @@ -588,10 +880,32 @@ void LLPolyMorphTarget::applyMask(U8 *maskTextureData, S32 width, S32 height, S3 else { // remove effect of previous mask - F32 *maskWeights = (mVertMask) ? mVertMask->getMorphMaskWeights() : NULL; + undoMask(FALSE); + } - if (maskWeights) + mLastWeight = 0.f; + + mVertMask->generateMask(maskTextureData, width, height, num_components, invert, clothing_weights); + + apply(mLastSex); +} + +//----------------------------------------------------------------------------- +// undoMask() +//----------------------------------------------------------------------------- +BOOL LLPolyMorphTarget::undoMask(BOOL delete_mask) +{ + if (!mVertMask) { + return FALSE; + } + + // remove effect of previous mask + + LLVector4 *clothing_weights = getInfo()->mIsClothingMorph ? mMesh->getWritableClothingWeights() : NULL; + + F32 *mask_weights = mVertMask->getMorphMaskWeights(); + LLVector3 *coords = mMesh->getWritableCoords(); LLVector3 *scaled_normals = mMesh->getScaledNormals(); LLVector3 *scaled_binormals = mMesh->getScaledBinormals(); @@ -599,33 +913,42 @@ void LLPolyMorphTarget::applyMask(U8 *maskTextureData, S32 width, S32 height, S3 for(U32 vert = 0; vert < mMorphData->mNumIndices; vert++) { - F32 lastMaskWeight = mLastWeight * maskWeights[vert]; + F32 mask_weight = 1.f; + if (mask_weights) + { + mask_weight = mask_weights[vert]; + } + + F32 last_mask_weight = mLastWeight * mask_weight; S32 out_vert = mMorphData->mVertexIndices[vert]; // remove effect of existing masked morph - coords[out_vert] -= mMorphData->mCoords[vert] * lastMaskWeight; - scaled_normals[out_vert] -= mMorphData->mNormals[vert] * lastMaskWeight * NORMAL_SOFTEN_FACTOR; - scaled_binormals[out_vert] -= mMorphData->mBinormals[vert] * lastMaskWeight * NORMAL_SOFTEN_FACTOR; - tex_coords[out_vert] -= mMorphData->mTexCoords[vert] * lastMaskWeight; + coords[out_vert] -= mMorphData->mCoords[vert] * last_mask_weight; + scaled_normals[out_vert] -= mMorphData->mNormals[vert] * last_mask_weight * NORMAL_SOFTEN_FACTOR; + scaled_binormals[out_vert] -= mMorphData->mBinormals[vert] * last_mask_weight * NORMAL_SOFTEN_FACTOR; + tex_coords[out_vert] -= mMorphData->mTexCoords[vert] * last_mask_weight; if (clothing_weights) { - LLVector3 clothing_offset = mMorphData->mCoords[vert] * lastMaskWeight; + LLVector3 clothing_offset = mMorphData->mCoords[vert] * last_mask_weight; LLVector4* clothing_weight = &clothing_weights[out_vert]; clothing_weight->mV[VX] -= clothing_offset.mV[VX]; clothing_weight->mV[VY] -= clothing_offset.mV[VY]; clothing_weight->mV[VZ] -= clothing_offset.mV[VZ]; } } - } - } // set last weight to 0, since we've removed the effect of this morph mLastWeight = 0.f; - mVertMask->generateMask(maskTextureData, width, height, num_components, invert, clothing_weights); + if (delete_mask) + { + delete mVertMask; + mVertMask = NULL; + addPendingMorphMask(); + } - apply(mLastSex); + return TRUE; } diff --git a/indra/newview/llpolymorph.h b/indra/newview/llpolymorph.h index 3fdaf3785..5137fc1fc 100644 --- a/indra/newview/llpolymorph.h +++ b/indra/newview/llpolymorph.h @@ -56,6 +56,10 @@ public: BOOL loadBinary(LLFILE* fp, LLPolyMeshSharedData *mesh); const std::string& getName() { return mName; } + BOOL saveLLM(LLFILE *fp); + BOOL saveOBJ(LLFILE *fp); + BOOL setMorphFromMesh(LLPolyMesh *morph); + public: std::string mName; @@ -167,6 +171,7 @@ public: /*virtual*/ const LLVector3* getNextDistortion(U32 *index, LLPolyMesh **poly_mesh); void applyMask(U8 *maskData, S32 width, S32 height, S32 num_components, BOOL invert); + BOOL undoMask(BOOL delete_mask); void addPendingMorphMask() { mNumMorphMasksPending++; } protected: diff --git a/indra/newview/llprefsim.cpp b/indra/newview/llprefsim.cpp index 8c1f71b4b..62dc37726 100644 --- a/indra/newview/llprefsim.cpp +++ b/indra/newview/llprefsim.cpp @@ -45,7 +45,7 @@ #include "llviewernetwork.h" #include "lluictrlfactory.h" -#include "lldirpicker.h" +#include "statemachine/aidirpicker.h" #include "hippogridmanager.h" @@ -53,6 +53,8 @@ #include "rlvhandler.h" // [/RLVa:KB] +class AIDirPicker; + class LLPrefsIMImpl : public LLPanel { public: @@ -67,6 +69,7 @@ public: void enableHistory(); static void onClickLogPath(void* user_data); + static void onClickLogPath_continued(void* user_data, AIDirPicker* dirpicker); static void onCommitLogging(LLUICtrl* ctrl, void* user_data); protected: @@ -301,13 +304,20 @@ void LLPrefsIMImpl::onClickLogPath(void* user_data) std::string proposed_name(self->childGetText("log_path_string")); - LLDirPicker& picker = LLDirPicker::instance(); - if (!picker.getDir(&proposed_name ) ) + AIDirPicker* dirpicker = new AIDirPicker(proposed_name); + dirpicker->run(boost::bind(&LLPrefsIMImpl::onClickLogPath_continued, user_data, dirpicker)); +} + +// static +void LLPrefsIMImpl::onClickLogPath_continued(void* user_data, AIDirPicker* dirpicker) +{ + if (!dirpicker->hasDirname()) { return; //Canceled! } - self->childSetText("log_path_string", picker.getDirName()); + LLPrefsIMImpl* self=(LLPrefsIMImpl*)user_data; + self->childSetText("log_path_string", dirpicker->getDirname()); } diff --git a/indra/newview/llpreviewanim.cpp b/indra/newview/llpreviewanim.cpp index f9cb5f210..845129a38 100644 --- a/indra/newview/llpreviewanim.cpp +++ b/indra/newview/llpreviewanim.cpp @@ -40,7 +40,7 @@ #include "llvoavatar.h" #include "llagent.h" // gAgent #include "llkeyframemotion.h" -#include "llfilepicker.h" +#include "statemachine/aifilepicker.h" #include "lllineeditor.h" #include "lluictrlfactory.h" #include "lluictrlfactory.h" @@ -392,21 +392,22 @@ void LLPreviewAnim::gotAssetForSave(LLVFS *vfs, // Write it back out... - LLFilePicker& file_picker = LLFilePicker::instance(); - if( !file_picker.getSaveFile( LLFilePicker::FFSAVE_ANIMATN, LLDir::getScrubbedFileName(self->getItem()->getName())) ) - { - // User canceled or we failed to acquire save file. - return; - } - // remember the user-approved/edited file name. - std::string filename = file_picker.getFirstFile(); + AIFilePicker* filepicker = AIFilePicker::create(); + filepicker->open(LLDir::getScrubbedFileName(self->getItem()->getName()) + ".animatn", FFSAVE_ANIMATN); + filepicker->run(boost::bind(&LLPreviewAnim::gotAssetForSave_continued, buffer, size, filepicker)); +} - std::ofstream export_file(filename.c_str(), std::ofstream::binary); - export_file.write(buffer, size); - export_file.close(); - +// static +void LLPreviewAnim::gotAssetForSave_continued(char* buffer, S32 size, AIFilePicker* filepicker) +{ + if (!filepicker->hasFilename()) + { + std::string filename = filepicker->getFilename(); + std::ofstream export_file(filename.c_str(), std::ofstream::binary); + export_file.write(buffer, size); + export_file.close(); + } delete[] buffer; - buffer = NULL; } // virtual diff --git a/indra/newview/llpreviewanim.h b/indra/newview/llpreviewanim.h index 115419fb6..3b9c53025 100644 --- a/indra/newview/llpreviewanim.h +++ b/indra/newview/llpreviewanim.h @@ -36,6 +36,8 @@ #include "llpreview.h" #include "llcharacter.h" +class AIFilePicker; + class LLPreviewAnim : public LLPreview { public: @@ -59,6 +61,7 @@ public: const LLUUID& asset_uuid, LLAssetType::EType type, void* user_data, S32 status, LLExtStat ext_status); + static void gotAssetForSave_continued(char* buffer, S32 size, AIFilePicker* filepicker); static void copyAnimID(void* userdata); // static void endAnimCallback( void *userdata ); diff --git a/indra/newview/llpreviewnotecard.cpp b/indra/newview/llpreviewnotecard.cpp index c2c3e8869..cf67ca516 100644 --- a/indra/newview/llpreviewnotecard.cpp +++ b/indra/newview/llpreviewnotecard.cpp @@ -61,7 +61,7 @@ #include "lllineeditor.h" #include "lluictrlfactory.h" // -#include "llfilepicker.h" +#include "statemachine/aifilepicker.h" // ///---------------------------------------------------------------------------- @@ -717,17 +717,18 @@ void LLPreviewNotecard::saveAs() if(item) { // gAssetStorage->getAssetData(item->getAssetUUID(), LLAssetType::AT_NOTECARD, LLPreviewNotecard::gotAssetForSave, this, TRUE); - default_filename = LLDir::getScrubbedFileName(item->getName()); + default_filename = LLDir::getScrubbedFileName(item->getName()) + ".notecard"; } - LLFilePicker& file_picker = LLFilePicker::instance(); - if( !file_picker.getSaveFile( LLFilePicker::FFSAVE_NOTECARD, default_filename ) ) - { - // User canceled or we failed to acquire save file. + AIFilePicker* filepicker = AIFilePicker::create(); + filepicker->open(default_filename, FFSAVE_NOTECARD); + filepicker->run(boost::bind(&LLPreviewNotecard::saveAs_continued, this, filepicker)); +} + +void LLPreviewNotecard::saveAs_continued(AIFilePicker* filepicker) +{ + if (!filepicker->hasFilename()) return; - } - // remember the user-approved/edited file name. - std::string filename = file_picker.getFirstFile(); LLViewerTextEditor* editor = getChild("Notecard Editor"); @@ -738,8 +739,9 @@ void LLPreviewNotecard::saveAs() return; } - S32 size = buffer.length() + 1; + S32 size = buffer.length(); + std::string filename = filepicker->getFilename(); std::ofstream export_file(filename.c_str(), std::ofstream::binary); export_file.write(buffer.c_str(), size); export_file.close(); diff --git a/indra/newview/llpreviewnotecard.h b/indra/newview/llpreviewnotecard.h index c3bf0e2f9..04568bf65 100644 --- a/indra/newview/llpreviewnotecard.h +++ b/indra/newview/llpreviewnotecard.h @@ -46,6 +46,7 @@ class LLTextEditor; class LLViewerTextEditor; class LLButton; +class AIFilePicker; class LLPreviewNotecard : public LLPreview { @@ -128,6 +129,7 @@ protected: // virtual BOOL canSaveAs() const; virtual void saveAs(); + void saveAs_continued(AIFilePicker* filepicker); // }; diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp index 7b6bab72e..e4abac51d 100644 --- a/indra/newview/llpreviewscript.cpp +++ b/indra/newview/llpreviewscript.cpp @@ -54,6 +54,7 @@ #include "lltextbox.h" #include "lltooldraganddrop.h" #include "llvfile.h" +#include "statemachine/aifilepicker.h" #include "llagent.h" #include "llnotify.h" @@ -1700,23 +1701,23 @@ void LLPreviewLSL::saveAs() const LLInventoryItem *item = getItem(); if(item) { - default_filename = LLDir::getScrubbedFileName(item->getName()); + default_filename = LLDir::getScrubbedFileName(item->getName()) + ".lsl"; } - LLFilePicker& file_picker = LLFilePicker::instance(); - if( !file_picker.getSaveFile( LLFilePicker::FFSAVE_LSL, default_filename ) ) - { - // User canceled or we failed to acquire save file. + AIFilePicker* filepicker = AIFilePicker::create(); + filepicker->open(default_filename, FFSAVE_LSL); + filepicker->run(boost::bind(&LLPreviewLSL::saveAs_continued, this, filepicker)); +} + +void LLPreviewLSL::saveAs_continued(AIFilePicker* filepicker) +{ + if(!filepicker->hasFilename()) return; - } - // remember the user-approved/edited file name. - std::string filename = file_picker.getFirstFile(); std::string utf8text = mScriptEd->mEditor->getText(); - LLFILE* fp = LLFile::fopen(filename, "wb"); + LLFILE* fp = LLFile::fopen(filepicker->getFilename(), "wb"); fputs(utf8text.c_str(), fp); fclose(fp); - fp = NULL; } // /// --------------------------------------------------------------------------- @@ -2654,19 +2655,19 @@ void LLLiveLSLEditor::saveAs() default_filename = LLDir::getScrubbedFileName(item->getName()); } - LLFilePicker& file_picker = LLFilePicker::instance(); - if( !file_picker.getSaveFile( LLFilePicker::FFSAVE_LSL, default_filename ) ) - { - // User canceled or we failed to acquire save file. + AIFilePicker* filepicker = AIFilePicker::create(); + filepicker->open(default_filename, FFSAVE_LSL); + filepicker->run(boost::bind(&LLLiveLSLEditor::saveAs_continued, this, filepicker)); +} + +void LLLiveLSLEditor::saveAs_continued(AIFilePicker* filepicker) +{ + if (!filepicker->hasFilename()) return; - } - // remember the user-approved/edited file name. - std::string filename = file_picker.getFirstFile(); std::string utf8text = mScriptEd->mEditor->getText(); - LLFILE* fp = LLFile::fopen(filename, "wb"); + LLFILE* fp = LLFile::fopen(filepicker->getFilename(), "wb"); fputs(utf8text.c_str(), fp); fclose(fp); - fp = NULL; } // diff --git a/indra/newview/llpreviewscript.h b/indra/newview/llpreviewscript.h index 58959e445..f4390927d 100644 --- a/indra/newview/llpreviewscript.h +++ b/indra/newview/llpreviewscript.h @@ -40,7 +40,7 @@ #include "llcombobox.h" #include "lliconctrl.h" #include "llframetimer.h" -#include "lltimer.h" +#include "lleventtimer.h" class LLMessageSystem; @@ -53,6 +53,7 @@ struct LLEntryAndEdCore; class LLMenuBarGL; class LLFloaterScriptSearch; class LLKeywordToken; +class AIFilePicker; // Inner, implementation class. LLPreviewScript and LLLiveLSLEditor each own one of these. class LLScriptEdCore : public LLPanel, public LLEventTimer @@ -189,6 +190,7 @@ protected: // virtual BOOL canSaveAs() const; virtual void saveAs(); + void saveAs_continued(AIFilePicker* filepicker); // static void onSearchReplace(void* userdata); @@ -261,6 +263,7 @@ protected: // virtual BOOL canSaveAs() const; virtual void saveAs(); + void saveAs_continued(AIFilePicker* filepicker); // static void onSearchReplace(void* userdata); diff --git a/indra/newview/llpreviewsound.cpp b/indra/newview/llpreviewsound.cpp index e40dddbd2..a91cc25d0 100644 --- a/indra/newview/llpreviewsound.cpp +++ b/indra/newview/llpreviewsound.cpp @@ -48,7 +48,7 @@ #include "llchat.h" #include "llfloaterchat.h" #include "llviewerwindow.h" // for alert -#include "llfilepicker.h" +#include "statemachine/aifilepicker.h" // for ambient play: #include "llviewerregion.h" // @@ -330,18 +330,22 @@ void LLPreviewSound::gotAssetForSave(LLVFS *vfs, // Write it back out... - LLFilePicker& file_picker = LLFilePicker::instance(); - if( !file_picker.getSaveFile( LLFilePicker::FFSAVE_OGG, LLDir::getScrubbedFileName(self->getItem()->getName())) ) - { - // User canceled or we failed to acquire save file. - return; - } - // remember the user-approved/edited file name. - std::string filename = file_picker.getFirstFile(); + AIFilePicker* filepicker = AIFilePicker::create(); + filepicker->open(LLDir::getScrubbedFileName(self->getItem()->getName()) + ".ogg", FFSAVE_OGG); + filepicker->run(boost::bind(&LLPreviewSound::gotAssetForSave_continued, buffer, size, filepicker)); +} - std::ofstream export_file(filename.c_str(), std::ofstream::binary); - export_file.write(buffer, size); - export_file.close(); +// static +void LLPreviewSound::gotAssetForSave_continued(char* buffer, S32 size, AIFilePicker* filepicker) +{ + if (filepicker->hasFilename()) + { + std::string filename = filepicker->getFilename(); + std::ofstream export_file(filename.c_str(), std::ofstream::binary); + export_file.write(buffer, size); + export_file.close(); + } + delete [] buffer; } // virtual diff --git a/indra/newview/llpreviewsound.h b/indra/newview/llpreviewsound.h index 535b233c9..bd8b9c0f0 100644 --- a/indra/newview/llpreviewsound.h +++ b/indra/newview/llpreviewsound.h @@ -35,6 +35,8 @@ #include "llpreview.h" +class AIFilePicker; + class LLPreviewSound : public LLPreview { public: @@ -59,6 +61,7 @@ public: const LLUUID& asset_uuid, LLAssetType::EType type, void* user_data, S32 status, LLExtStat ext_status); + static void gotAssetForSave_continued(char* buffer, S32 size, AIFilePicker* filepicker); // protected: diff --git a/indra/newview/llpreviewtexture.cpp b/indra/newview/llpreviewtexture.cpp index 8eb803401..e23e662ec 100644 --- a/indra/newview/llpreviewtexture.cpp +++ b/indra/newview/llpreviewtexture.cpp @@ -37,7 +37,7 @@ #include "llagent.h" #include "llbutton.h" #include "llcombobox.h" -#include "llfilepicker.h" +#include "statemachine/aifilepicker.h" #include "llimagetga.h" #include "llinventoryview.h" #include "llinventory.h" @@ -380,15 +380,19 @@ void LLPreviewTexture::saveAs() if( mLoadingFullImage ) return; - LLFilePicker& file_picker = LLFilePicker::instance(); const LLViewerInventoryItem* item = getItem() ; - if( !file_picker.getSaveFile( LLFilePicker::FFSAVE_TGA, item ? LLDir::getScrubbedFileName(item->getName()) : LLStringUtil::null) ) - { - // User canceled or we failed to acquire save file. + AIFilePicker* filepicker = AIFilePicker::create(); + filepicker->open(item ? LLDir::getScrubbedFileName(item->getName()) + ".tga" : LLStringUtil::null, FFSAVE_TGA, "", "image"); + filepicker->run(boost::bind(&LLPreviewTexture::saveAs_continued, this, item, filepicker)); +} + +void LLPreviewTexture::saveAs_continued(LLViewerInventoryItem const* item, AIFilePicker* filepicker) +{ + if (!filepicker->hasFilename()) return; - } + // remember the user-approved/edited file name. - mSaveFileName = file_picker.getFirstFile(); + mSaveFileName = filepicker->getFilename(); mLoadingFullImage = TRUE; getWindow()->incBusyCount(); mImage->forceToSaveRawImage(0) ;//re-fetch the raw image if the old one is removed. diff --git a/indra/newview/llpreviewtexture.h b/indra/newview/llpreviewtexture.h index fb75876fc..ce26d4dd4 100644 --- a/indra/newview/llpreviewtexture.h +++ b/indra/newview/llpreviewtexture.h @@ -40,6 +40,7 @@ class LLComboBox; class LLImageRaw; +class AIFilePicker; class LLPreviewTexture : public LLPreview { @@ -64,6 +65,7 @@ public: virtual BOOL canSaveAs() const; virtual void saveAs(); + void saveAs_continued(LLViewerInventoryItem const* item, AIFilePicker* filepicker); virtual LLUUID getItemID(); virtual std::string getItemCreatorName(); virtual std::string getItemCreationDate(); diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp index bbfd90177..afe43a353 100644 --- a/indra/newview/llselectmgr.cpp +++ b/indra/newview/llselectmgr.cpp @@ -33,6 +33,7 @@ #include "llviewerprecompiledheaders.h" // file include +#define LLSELECTMGR_CPP #include "llselectmgr.h" // library includes @@ -93,8 +94,6 @@ #include "rlvhandler.h" // [/RLVa:KB] -#include "llglheaders.h" - LLViewerObject* getSelectedParentObject(LLViewerObject *object) ; // // Consts @@ -102,7 +101,6 @@ LLViewerObject* getSelectedParentObject(LLViewerObject *object) ; const S32 NUM_SELECTION_UNDO_ENTRIES = 200; const F32 SILHOUETTE_UPDATE_THRESHOLD_SQUARED = 0.02f; -const S32 OWNERSHIP_COST_PER_OBJECT = 10; // Must be the same as economy_constants.price_object_claim in the database. const S32 MAX_ACTION_QUEUE_SIZE = 20; const S32 MAX_SILS_PER_FRAME = 50; const S32 MAX_OBJECTS_PER_PACKET = 254; @@ -112,13 +110,12 @@ const S32 TE_SELECT_MASK_ALL = 0xFFFFFFFF; // Globals // -BOOL gDebugSelectMgr = FALSE; +//BOOL gDebugSelectMgr = FALSE; -BOOL gHideSelectedObjects = FALSE; -BOOL gAllowSelectAvatar = FALSE; +//BOOL gHideSelectedObjects = FALSE; +//BOOL gAllowSelectAvatar = FALSE; BOOL LLSelectMgr::sRectSelectInclusive = TRUE; -BOOL LLSelectMgr::sRenderSelectionHighlights = TRUE; BOOL LLSelectMgr::sRenderHiddenSelections = TRUE; BOOL LLSelectMgr::sRenderLightRadius = FALSE; F32 LLSelectMgr::sHighlightThickness = 0.f; @@ -134,7 +131,6 @@ LLColor4 LLSelectMgr::sHighlightInspectColor; LLColor4 LLSelectMgr::sHighlightParentColor; LLColor4 LLSelectMgr::sHighlightChildColor; LLColor4 LLSelectMgr::sContextSilhouetteColor; -std::set LLSelectMgr::sObjectPropertiesFamilyRequests; static LLObjectSelection *get_null_object_selection(); template<> @@ -181,11 +177,17 @@ LLObjectSelection *get_null_object_selection() return sNullSelection; } +// Build time optimization, generate this function once here +template class LLSelectMgr* LLSingleton::getInstance(); //----------------------------------------------------------------------------- // LLSelectMgr() //----------------------------------------------------------------------------- LLSelectMgr::LLSelectMgr() + : mHideSelectedObjects(LLCachedControl("HideSelectedObjects", false)), + mRenderHighlightSelections(LLCachedControl("RenderHighlightSelections", false)), + mAllowSelectAvatar( LLCachedControl("AllowSelectAvatar", false)), + mDebugSelectMgr(LLCachedControl( "DebugSelectMgr", false)) { mTEMode = FALSE; mLastCameraPos.clearVec(); @@ -564,6 +566,121 @@ BOOL LLSelectMgr::removeObjectFromSelections(const LLUUID &id) return object_found; } +bool LLSelectMgr::linkObjects() +{ + if (!LLSelectMgr::getInstance()->selectGetAllRootsValid()) + { + LLNotifications::getInstance()->add("UnableToLinkWhileDownloading"); + return true; + } + + S32 object_count = LLSelectMgr::getInstance()->getSelection()->getObjectCount(); + if (object_count > MAX_CHILDREN_PER_TASK + 1) + { + LLSD args; + args["COUNT"] = llformat("%d", object_count); + int max = MAX_CHILDREN_PER_TASK+1; + args["MAX"] = llformat("%d", max); + LLNotifications::getInstance()->add("UnableToLinkObjects", args); + return true; + } + + if (LLSelectMgr::getInstance()->getSelection()->getRootObjectCount() < 2) + { + LLNotifications::instance().add("CannotLinkIncompleteSet"); + return true; + } + + if (!LLSelectMgr::getInstance()->selectGetRootsModify()) + { + LLNotifications::instance().add("CannotLinkModify"); + return true; + } + + LLUUID owner_id; + std::string owner_name; + if (!LLSelectMgr::getInstance()->selectGetOwner(owner_id, owner_name)) + { + // we don't actually care if you're the owner, but novices are + // the most likely to be stumped by this one, so offer the + // easiest and most likely solution. + LLNotifications::instance().add("CannotLinkDifferentOwners"); + return true; + } + + LLSelectMgr::getInstance()->sendLink(); + + return true; +} + +bool LLSelectMgr::unlinkObjects() +{ +// [RLVa:KB] - Checked: 2010-04-01 (RLVa-1.1.3b) | Modified: RLVa-0.2.0g | OK + if ( (rlv_handler_t::isEnabled()) && (!gRlvHandler.canStand()) ) + { + // Allow only if the avie isn't sitting on any of the selected objects + LLObjectSelectionHandle hSel = LLSelectMgr::getInstance()->getSelection(); + RlvSelectIsSittingOn f(gAgent.getAvatarObject()->getRoot()); + if ( (hSel.notNull()) && (hSel->getFirstRootNode(&f, TRUE)) ) + return true; + } +// [/RLVa:KB] + LLSelectMgr::getInstance()->sendDelink(); + return true; +} + +// in order to link, all objects must have the same owner, and the +// agent must have the ability to modify all of the objects. However, +// we're not answering that question with this method. The question +// we're answering is: does the user have a reasonable expectation +// that a link operation should work? If so, return true, false +// otherwise. this allows the handle_link method to more finely check +// the selection and give an error message when the uer has a +// reasonable expectation for the link to work, but it will fail. +bool LLSelectMgr::enableLinkObjects() +{ + bool new_value = false; + // check if there are at least 2 objects selected, and that the + // user can modify at least one of the selected objects. + + // in component mode, can't link + if (!gSavedSettings.getBOOL("EditLinkedParts")) + { + if(LLSelectMgr::getInstance()->selectGetAllRootsValid() && LLSelectMgr::getInstance()->getSelection()->getRootObjectCount() >= 2) + { + struct f : public LLSelectedObjectFunctor + { + virtual bool apply(LLViewerObject* object) + { + return object->permModify(); + } + } func; + const bool firstonly = true; + new_value = LLSelectMgr::getInstance()->getSelection()->applyToRootObjects(&func, firstonly); + } + } + return new_value; +} + +bool LLSelectMgr::enableUnlinkObjects() +{ + LLViewerObject* first_editable_object = LLSelectMgr::getInstance()->getSelection()->getFirstEditableObject(); + + bool new_value = LLSelectMgr::getInstance()->selectGetAllRootsValid() && + first_editable_object && + !first_editable_object->isAttachment(); +// [RLVa:KB] - Checked: 2010-04-01 (RLVa-1.1.3b) | Modified: RLVa-0.2.0g | OK + if ( (new_value) && (!gRlvHandler.canStand()) ) + { + // Allow only if the avie isn't sitting on any of the selected objects + LLObjectSelectionHandle handleSel = LLSelectMgr::getInstance()->getSelection(); + RlvSelectIsSittingOn f(gAgent.getAvatarObject()->getRoot()); + new_value = handleSel->getFirstRootNode(&f, TRUE) == NULL; + } +// [/RLVa:KB] + return new_value; +} + void LLSelectMgr::deselectObjectAndFamily(LLViewerObject* object, BOOL send_to_sim, BOOL include_entire_object) { // bail if nothing selected or if object wasn't selected in the first place @@ -690,7 +807,7 @@ void LLSelectMgr::addAsFamily(std::vector& objects, BOOL add_to // Can't select yourself if (objectp->mID == gAgentID - && !gAllowSelectAvatar) + && !LLSelectMgr::getInstance()->mAllowSelectAvatar) { continue; } @@ -839,7 +956,12 @@ LLObjectSelectionHandle LLSelectMgr::setHoverObject(LLViewerObject *objectp, S32 LLSelectNode *LLSelectMgr::getHoverNode() { - return getHoverObjects()->getFirstRootNode(); + return mHoverObjects->getFirstRootNode(); +} + +LLSelectNode *LLSelectMgr::getPrimaryHoverNode() +{ + return mHoverObjects->mSelectNodeMap[mHoverObjects->mPrimaryObject]; } void LLSelectMgr::highlightObjectOnly(LLViewerObject* objectp) @@ -854,8 +976,8 @@ void LLSelectMgr::highlightObjectOnly(LLViewerObject* objectp) return; } - if ((gSavedSettings.getBOOL("SelectOwnedOnly") && !objectp->permYouOwner()) || - (gSavedSettings.getBOOL("SelectMovableOnly") && !objectp->permMove())) + if ((gSavedSettings.getBOOL("SelectOwnedOnly") && !objectp->permYouOwner()) + || (gSavedSettings.getBOOL("SelectMovableOnly") && !objectp->permMove())) { // only select my own objects return; @@ -2253,6 +2375,26 @@ BOOL LLSelectMgr::selectGetAllValid() return TRUE; } +//----------------------------------------------------------------------------- +// selectGetAllValidAndObjectsFound() - return TRUE if selections are +// valid and objects are found. +// +// For EXT-3114 - same as selectGetModify() without the modify check. +//----------------------------------------------------------------------------- +BOOL LLSelectMgr::selectGetAllValidAndObjectsFound() +{ + for (LLObjectSelection::iterator iter = getSelection()->begin(); + iter != getSelection()->end(); iter++ ) + { + LLSelectNode* node = *iter; + LLViewerObject* object = node->getObject(); + if( !object || !node->mValid ) + { + return FALSE; + } + } + return TRUE; +} //----------------------------------------------------------------------------- // selectGetModify() - return TRUE if current agent can modify all @@ -2382,6 +2524,7 @@ BOOL LLSelectMgr::selectGetCreator(LLUUID& result_id, std::string& name) } if (first_id.isNull()) { + name.assign("Nobody"); return FALSE; } @@ -2664,11 +2807,6 @@ BOOL LLSelectMgr::selectGetPerm(U8 which_perm, U32* mask_on, U32* mask_off) -BOOL LLSelectMgr::selectGetOwnershipCost(S32* out_cost) -{ - return mSelectedObjects->getOwnershipCost(*out_cost); -} - BOOL LLSelectMgr::selectGetPermissions(LLPermissions& result_perm) { BOOL first = TRUE; @@ -3517,7 +3655,7 @@ void LLSelectMgr::deselectAllIfTooFar() if (select_dist_sq > deselect_dist_sq) { - if (gDebugSelectMgr) + if (mDebugSelectMgr) { llinfos << "Selection manager: auto-deselecting, select_dist = " << fsqrtf(select_dist_sq) << llendl; llinfos << "agent pos global = " << gAgent.getPositionGlobal() << llendl; @@ -3596,7 +3734,7 @@ void LLSelectMgr::selectionSetObjectSaleInfo(const LLSaleInfo& sale_info) // Attachments //---------------------------------------------------------------------- -void LLSelectMgr::sendAttach(U8 attachment_point) +void LLSelectMgr::sendAttach(U8 attachment_point, bool replace) { LLViewerObject* attach_object = mSelectedObjects->getFirstRootObject(); @@ -3610,7 +3748,7 @@ void LLSelectMgr::sendAttach(U8 attachment_point) if (0 == attachment_point || get_if_there(gAgent.getAvatarObject()->mAttachmentPoints, (S32)attachment_point, (LLViewerJointAttachment*)NULL)) { - if (attachment_point != 0 && gHippoGridManager->getConnectedGrid()->supportsInvLinks()) + if ((!replace || attachment_point != 0) && gHippoGridManager->getConnectedGrid()->supportsInvLinks()) { // If we know the attachment point then we got here by clicking an // "Attach to..." context menu item, so we should add, not replace. @@ -4300,10 +4438,6 @@ void LLSelectMgr::sendListToRegions(const std::string& message_name, void LLSelectMgr::requestObjectPropertiesFamily(LLViewerObject* object) { - // Remember that we asked the properties of this object. - sObjectPropertiesFamilyRequests.insert(object->mID); - //llinfos << "Registered an ObjectPropertiesFamily request for object " << object->mID << llendl; - LLMessageSystem* msg = gMessageSystem; msg->newMessageFast(_PREHASH_RequestObjectPropertiesFamily); @@ -4381,7 +4515,7 @@ void LLSelectMgr::processObjectProperties(LLMessageSystem* msg, void** user_data msg->getStringFast(_PREHASH_ObjectData, _PREHASH_SitName, sit_name, i); //unpack TE IDs - std::vector texture_ids; + uuid_vec_t texture_ids; S32 size = msg->getSizeFast(_PREHASH_ObjectData, i, _PREHASH_TextureID); if (size > 0) { @@ -4493,8 +4627,9 @@ void LLSelectMgr::processObjectProperties(LLMessageSystem* msg, void** user_data // static void LLSelectMgr::processObjectPropertiesFamily(LLMessageSystem* msg, void** user_data) { - U32 request_flags; LLUUID id; + + U32 request_flags; LLUUID creator_id; LLUUID owner_id; LLUUID group_id; @@ -4525,15 +4660,6 @@ void LLSelectMgr::processObjectPropertiesFamily(LLMessageSystem* msg, void** use std::string desc; msg->getStringFast(_PREHASH_ObjectData, _PREHASH_Description, desc); - //llinfos << "Got ObjectPropertiesFamily reply for object " << id << llendl; - if(sObjectPropertiesFamilyRequests.count(id) != 0 ) - { - // Send to export floaters - //LLFloaterExport::receiveObjectProperties(id, name, desc); - // We got the reply, so remove the object from the list of pending requests - sObjectPropertiesFamilyRequests.erase(id); - } - // the reporter widget askes the server for info about picked objects if (request_flags & (COMPLAINT_REPORT_REQUEST | BUG_REPORT_REQUEST)) { @@ -4562,7 +4688,7 @@ void LLSelectMgr::processObjectPropertiesFamily(LLMessageSystem* msg, void** use return (node->getObject() && node->getObject()->mID == mID); } } func(id); - LLSelectNode* node = LLSelectMgr::getInstance()->getHoverObjects()->getFirstNode(&func); + LLSelectNode* node = LLSelectMgr::getInstance()->mHoverObjects->getFirstNode(&func); if (node) { @@ -4897,12 +5023,12 @@ void LLSelectMgr::updateSelectionSilhouette(LLObjectSelectionHandle object_handl } void LLSelectMgr::renderSilhouettes(BOOL for_hud) { - if (!mRenderSilhouettes || !LLSelectMgr::sRenderSelectionHighlights) + if (!mRenderSilhouettes || !mRenderHighlightSelections) { return; } - gGL.getTexUnit(0)->bind(mSilhouetteImagep.get()); + gGL.getTexUnit(0)->bind(mSilhouetteImagep); LLGLSPipelineSelection gls_select; gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.f); LLGLEnable blend(GL_BLEND); @@ -4917,13 +5043,13 @@ void LLSelectMgr::renderSilhouettes(BOOL for_hud) // set up transform to encompass bounding box of HUD glMatrixMode(GL_PROJECTION); - glPushMatrix(); + gGL.pushMatrix(); glLoadIdentity(); F32 depth = llmax(1.f, hud_bbox.getExtentLocal().mV[VX] * 1.1f); glOrtho(-0.5f * LLViewerCamera::getInstance()->getAspect(), 0.5f * LLViewerCamera::getInstance()->getAspect(), -0.5f, 0.5f, 0.f, depth); glMatrixMode(GL_MODELVIEW); - glPushMatrix(); + gGL.pushMatrix(); glLoadIdentity(); glLoadMatrixf(OGL_TO_CFR_ROTATION); // Load Cory's favorite reference frame glTranslatef(-hud_bbox.getCenterLocal().mV[VX] + (depth *0.5f), 0.f, 0.f); @@ -4932,7 +5058,8 @@ void LLSelectMgr::renderSilhouettes(BOOL for_hud) if (mSelectedObjects->getNumNodes()) { LLUUID inspect_item_id = LLFloaterInspect::getSelectedUUID(); - + + LLUUID focus_item_id = LLViewerMediaFocus::getInstance()->getSelectedUUID(); // //for (S32 pass = 0; pass < 2; pass++) //{ @@ -4948,7 +5075,11 @@ void LLSelectMgr::renderSilhouettes(BOOL for_hud) { continue; } - if(objectp->getID() == inspect_item_id) + if (objectp->getID() == focus_item_id) + { + node->renderOneSilhouette(gFocusMgr.getFocusColor()); + } + else if(objectp->getID() == inspect_item_id) { node->renderOneSilhouette(sHighlightInspectColor); } @@ -5007,10 +5138,10 @@ void LLSelectMgr::renderSilhouettes(BOOL for_hud) if (isAgentAvatarValid() && for_hud) { glMatrixMode(GL_PROJECTION); - glPopMatrix(); + gGL.popMatrix(); glMatrixMode(GL_MODELVIEW); - glPopMatrix(); + gGL.popMatrix(); stop_glerror(); } @@ -5118,13 +5249,14 @@ void LLSelectNode::selectTE(S32 te_index, BOOL selected) { return; } - if (selected) - { - mTESelectMask |= (0x1 << te_index); + S32 mask = 0x1 << te_index; + if(selected) + { + mTESelectMask |= mask; } else { - mTESelectMask &= ~(0x1 << te_index); + mTESelectMask &= ~mask; } mLastTESelected = te_index; } @@ -5178,13 +5310,13 @@ void LLSelectNode::saveColors() } } -void LLSelectNode::saveTextures(const std::vector& textures) +void LLSelectNode::saveTextures(const uuid_vec_t& textures) { if (mObject.notNull()) { mSavedTextures.clear(); - for (std::vector::const_iterator texture_it = textures.begin(); + for (uuid_vec_t::const_iterator texture_it = textures.begin(); texture_it != textures.end(); ++texture_it) { mSavedTextures.push_back(*texture_it); @@ -5349,7 +5481,7 @@ void LLSelectNode::renderOneSilhouette(const LLColor4 &color) } glMatrixMode(GL_MODELVIEW); - glPushMatrix(); + gGL.pushMatrix(); if (!is_hud_object) { glLoadIdentity(); @@ -5468,7 +5600,7 @@ void LLSelectNode::renderOneSilhouette(const LLColor4 &color) gGL.end(); gGL.flush(); } - glPopMatrix(); + gGL.popMatrix(); } // @@ -5477,13 +5609,21 @@ void LLSelectNode::renderOneSilhouette(const LLColor4 &color) // Update everyone who cares about the selection list void dialog_refresh_all() + { + // This is the easiest place to fire the update signal, as it will + // make cleaning up the functions below easier. Also, sometimes entities + // outside the selection manager change properties of selected objects + // and call into this function. Yuck. + LLSelectMgr::getInstance()->mUpdateSignal(); + if (gNoRender) { return; } - //could refresh selected object info in toolbar here + // *TODO: Eliminate all calls into outside classes below, make those + // objects register with the update signal. gFloaterTools->dirty(); @@ -5897,6 +6037,27 @@ void LLSelectMgr::setAgentHUDZoom(F32 target_zoom, F32 current_zoom) gAgent.mHUDCurZoom = current_zoom; } +///////////////////////////////////////////////////////////////////////////// +// Object selection iterator helpers +///////////////////////////////////////////////////////////////////////////// +bool LLObjectSelection::is_root::operator()(LLSelectNode *node) +{ + LLViewerObject* object = node->getObject(); + return (object != NULL) && !node->mIndividualSelection && (object->isRootEdit() || object->isJointChild()); +} + +bool LLObjectSelection::is_valid_root::operator()(LLSelectNode *node) +{ + LLViewerObject* object = node->getObject(); + return (object != NULL) && node->mValid && !node->mIndividualSelection && (object->isRootEdit() || object->isJointChild()); +} + +bool LLObjectSelection::is_root_object::operator()(LLSelectNode *node) +{ + LLViewerObject* object = node->getObject(); + return (object != NULL) && (object->isRootEdit() || object->isJointChild()); +} + LLObjectSelection::LLObjectSelection() : LLRefCount(), mSelectType(SELECT_TYPE_WORLD) @@ -5988,16 +6149,6 @@ BOOL LLObjectSelection::isEmpty() const return (mList.size() == 0); } -//----------------------------------------------------------------------------- -// getOwnershipCost() -//----------------------------------------------------------------------------- -BOOL LLObjectSelection::getOwnershipCost(S32 &cost) -{ - S32 count = getObjectCount(); - cost = count * OWNERSHIP_COST_PER_OBJECT; - return (count > 0); -} - //----------------------------------------------------------------------------- // getObjectCount() - returns number of non null objects @@ -6138,6 +6289,29 @@ bool LLObjectSelection::applyToRootNodes(LLSelectedNodeFunctor *func, bool first return result; } +BOOL LLObjectSelection::isMultipleTESelected() +{ + BOOL te_selected = FALSE; + // ...all faces + for (LLObjectSelection::iterator iter = begin(); + iter != end(); iter++) + { + LLSelectNode* nodep = *iter; + for (S32 i = 0; i < SELECT_MAX_TES; i++) + { + if(nodep->isTESelected(i)) + { + if(te_selected) + { + return TRUE; + } + te_selected = TRUE; + } + } + } + return FALSE; +} + //----------------------------------------------------------------------------- // contains() //----------------------------------------------------------------------------- @@ -6404,23 +6578,24 @@ bool LLSelectMgr::selectionMove(const LLVector3& displ, if (update_position) { // calculate the distance of the object closest to the camera origin - F32 min_dist = 1e+30f; + F32 min_dist_squared = F32_MAX; // value will be overridden in the loop + LLVector3 obj_pos; for (LLObjectSelection::root_iterator it = getSelection()->root_begin(); it != getSelection()->root_end(); ++it) { obj_pos = (*it)->getObject()->getPositionEdit(); - F32 obj_dist = dist_vec(obj_pos, LLViewerCamera::getInstance()->getOrigin()); - if (obj_dist < min_dist) + F32 obj_dist_squared = dist_vec_squared(obj_pos, LLViewerCamera::getInstance()->getOrigin()); + if (obj_dist_squared < min_dist_squared) { - min_dist = obj_dist; + min_dist_squared = obj_dist_squared; } } - // factor the distance inside the displacement vector. This will get us + // factor the distance into the displacement vector. This will get us // equally visible movements for both close and far away selections. - min_dist = sqrt(min_dist) / 2; + F32 min_dist = sqrt((F32) sqrtf(min_dist_squared)) / 2; displ_global.setVec(displ.mV[0]*min_dist, displ.mV[1]*min_dist, displ.mV[2]*min_dist); diff --git a/indra/newview/llselectmgr.h b/indra/newview/llselectmgr.h index 1ebe341bf..be482b725 100644 --- a/indra/newview/llselectmgr.h +++ b/indra/newview/llselectmgr.h @@ -35,7 +35,6 @@ #include "llcharacter.h" #include "lleditmenuhandler.h" -#include "llstring.h" #include "llundo.h" #include "lluuid.h" #include "llmemory.h" @@ -47,14 +46,15 @@ #include "llframetimer.h" #include "llbbox.h" #include "llpermissions.h" -#include "llviewerobject.h" +#include "llcontrol.h" +#include "llviewerobject.h" // LLObjectSelection::getSelectedTEValue template #include -#include "boost/iterator/filter_iterator.hpp" +#include +#include class LLMessageSystem; class LLViewerTexture; -class LLViewerObject; class LLColor4; class LLVector3; class LLSelectNode; @@ -146,7 +146,7 @@ public: void setObject(LLViewerObject* object); // *NOTE: invalidate stored textures and colors when # faces change void saveColors(); - void saveTextures(const std::vector& textures); + void saveTextures(const uuid_vec_t& textures); void saveTextureScaleRatios(); BOOL allowOperationOnNode(PermissionBit op, U64 group_proxy_power) const; @@ -182,7 +182,7 @@ public: std::string mSitName; U64 mCreationDate; std::vector mSavedColors; - std::vector mSavedTextures; + uuid_vec_t mSavedTextures; std::vector mTextureScaleRatios; std::vector mSilhouetteVertices; // array of vertices to render silhouette of object std::vector mSilhouetteNormals; // array of normals to render silhouette of object @@ -202,13 +202,9 @@ class LLObjectSelection : public LLRefCount protected: ~LLObjectSelection(); - // List public: typedef std::list list_t; -private: - list_t mList; -public: // Iterators struct is_non_null { @@ -234,11 +230,7 @@ public: struct is_root { - bool operator()(LLSelectNode* node) - { - LLViewerObject* object = node->getObject(); - return (object != NULL) && !node->mIndividualSelection && (object->isRootEdit() || object->isJointChild()); - } + bool operator()(LLSelectNode* node); }; typedef boost::filter_iterator root_iterator; root_iterator root_begin() { return root_iterator(mList.begin(), mList.end()); } @@ -246,11 +238,7 @@ public: struct is_valid_root { - bool operator()(LLSelectNode* node) - { - LLViewerObject* object = node->getObject(); - return (object != NULL) && node->mValid && !node->mIndividualSelection && (object->isRootEdit() || object->isJointChild()); - } + bool operator()(LLSelectNode* node); }; typedef boost::filter_iterator valid_root_iterator; valid_root_iterator valid_root_begin() { return valid_root_iterator(mList.begin(), mList.end()); } @@ -258,11 +246,7 @@ public: struct is_root_object { - bool operator()(LLSelectNode* node) - { - LLViewerObject* object = node->getObject(); - return (object != NULL) && (object->isRootEdit() || object->isJointChild()); - } + bool operator()(LLSelectNode* node); }; typedef boost::filter_iterator root_object_iterator; root_object_iterator root_object_begin() { return root_object_iterator(mList.begin(), mList.end()); } @@ -272,12 +256,9 @@ public: LLObjectSelection(); void updateEffects(); - void cleanupNodes(); BOOL isEmpty() const; - S32 getOwnershipCost(S32 &cost); - LLSelectNode* getFirstNode(LLSelectedNodeFunctor* func = NULL); LLSelectNode* getFirstRootNode(LLSelectedNodeFunctor* func = NULL, BOOL non_root_ok = FALSE); LLViewerObject* getFirstSelectedObject(LLSelectedNodeFunctor* func, BOOL get_parent = FALSE); @@ -294,12 +275,8 @@ public: // iterate through texture entries template bool getSelectedTEValue(LLSelectedTEGetFunctor* func, T& res); - - void addNode(LLSelectNode *nodep); - void addNodeAtEnd(LLSelectNode *nodep); - void moveNodeToFront(LLSelectNode *nodep); - void removeNode(LLSelectNode *nodep); - void deleteAllNodes(); // Delete all nodes + template bool isMultipleTEValue(LLSelectedTEGetFunctor* func, const T& ignore_value); + S32 getNumNodes(); LLSelectNode* findNode(LLViewerObject* objectp); @@ -308,6 +285,7 @@ public: S32 getTECount(); S32 getRootObjectCount(); + BOOL isMultipleTESelected(); BOOL contains(LLViewerObject* object); BOOL contains(LLViewerObject* object, S32 te); @@ -326,6 +304,16 @@ public: ESelectType getSelectType() const { return mSelectType; } private: + void addNode(LLSelectNode *nodep); + void addNodeAtEnd(LLSelectNode *nodep); + void moveNodeToFront(LLSelectNode *nodep); + void removeNode(LLSelectNode *nodep); + void deleteAllNodes(); + void cleanupNodes(); + + +private: + list_t mList; const LLObjectSelection &operator=(const LLObjectSelection &); LLPointer mPrimaryObject; @@ -335,11 +323,15 @@ private: typedef LLSafeHandle LLObjectSelectionHandle; +// Build time optimization, generate this once in .cpp file +#ifndef LLSELECTMGR_CPP +extern template class LLSelectMgr* LLSingleton::getInstance(); +#endif + class LLSelectMgr : public LLEditMenuHandler, public LLSingleton { public: static BOOL sRectSelectInclusive; // do we need to surround an object to pick it? - static BOOL sRenderSelectionHighlights; // do we show selection silhouettes? static BOOL sRenderHiddenSelections; // do we show selection silhouettes that are occluded? static BOOL sRenderLightRadius; // do we show the radius of selected lights? static F32 sHighlightThickness; @@ -356,6 +348,11 @@ public: static LLColor4 sHighlightInspectColor; static LLColor4 sContextSilhouetteColor; + LLCachedControl mHideSelectedObjects; + LLCachedControl mRenderHighlightSelections; + LLCachedControl mAllowSelectAvatar; + LLCachedControl mDebugSelectMgr; + public: LLSelectMgr(); ~LLSelectMgr(); @@ -394,13 +391,16 @@ public: // Add //////////////////////////////////////////////////////////////// + // This method is meant to select an object, and then select all + // of the ancestors and descendants. This should be the normal behavior. + // + // *NOTE: You must hold on to the object selection handle, otherwise + // the objects will be automatically deselected in 1 frame. + LLObjectSelectionHandle selectObjectAndFamily(LLViewerObject* object, BOOL add_to_end = FALSE); + // For when you want just a child object. LLObjectSelectionHandle selectObjectOnly(LLViewerObject* object, S32 face = SELECT_ALL_TES); - // This method is meant to select an object, and then select all - // of the ancestors and descendents. This should be the normal behavior. - LLObjectSelectionHandle selectObjectAndFamily(LLViewerObject* object, BOOL add_to_end = FALSE); - // Same as above, but takes a list of objects. Used by rectangle select. LLObjectSelectionHandle selectObjectAndFamily(const std::vector& object_list, BOOL send_to_sim = TRUE); @@ -408,6 +408,8 @@ public: LLObjectSelectionHandle selectHighlightedObjects(); LLObjectSelectionHandle setHoverObject(LLViewerObject *objectp, S32 face = -1); + LLSelectNode *getHoverNode(); + LLSelectNode *getPrimaryHoverNode(); void highlightObjectOnly(LLViewerObject *objectp); void highlightObjectAndFamily(LLViewerObject *objectp); @@ -439,16 +441,25 @@ public: BOOL removeObjectFromSelections(const LLUUID &id); + //////////////////////////////////////////////////////////////// + // Selection editing + //////////////////////////////////////////////////////////////// + bool linkObjects(); + + bool unlinkObjects(); + + bool enableLinkObjects(); + + bool enableUnlinkObjects(); + //////////////////////////////////////////////////////////////// // Selection accessors //////////////////////////////////////////////////////////////// - LLObjectSelectionHandle getHoverObjects() { return mHoverObjects; } LLObjectSelectionHandle getSelection() { return mSelectedObjects; } // right now this just renders the selection with root/child colors instead of a single color LLObjectSelectionHandle getEditSelection() { convertTransient(); return mSelectedObjects; } LLObjectSelectionHandle getHighlightedObjects() { return mHighlightedObjects; } - - LLSelectNode *getHoverNode(); + LLObjectSelectionHandle getHoverObjects() { return mHoverObjects; } //////////////////////////////////////////////////////////////// // Grid manipulation @@ -503,7 +514,7 @@ public: void selectionSetTexGen( U8 texgen ); void selectionSetShiny( U8 shiny ); void selectionSetFullbright( U8 fullbright ); - void selectionSetMediaTypeAndURL( U8 media_type, const std::string& media_url ); + void selectionSetMediaTypeAndURL(U8 media_type, const std::string& media_url); void selectionSetClickAction(U8 action); void selectionSetIncludeInSearch(bool include_in_search); void selectionSetGlow(const F32 glow); @@ -535,6 +546,7 @@ public: // Returns TRUE if the viewer has information on all selected objects BOOL selectGetAllRootsValid(); BOOL selectGetAllValid(); + BOOL selectGetAllValidAndObjectsFound(); // returns TRUE if you can modify all selected objects. BOOL selectGetRootsModify(); @@ -554,7 +566,6 @@ public: // the value found if available. BOOL selectGetGroup(LLUUID& id); BOOL selectGetPerm( U8 which_perm, U32* mask_on, U32* mask_off); // TRUE if all have data, returns two masks, each indicating which bits are all on and all off - BOOL selectGetOwnershipCost(S32* cost); // sum of all ownership costs BOOL selectIsGroupOwned(); // TRUE if all root objects have valid data and are group owned. @@ -610,7 +621,7 @@ public: // verification only, if it doesn't match region info then sale is // canceled void sendBuy(const LLUUID& buyer_id, const LLUUID& category_id, const LLSaleInfo sale_info); - void sendAttach(U8 attachment_point); + void sendAttach(U8 attachment_point, bool replace=true); void sendDetach(); void sendDropAttachment(); void sendLink(); @@ -689,7 +700,13 @@ private: static void packPermissionsHead(void* user_data); static void packGodlikeHead(void* user_data); static bool confirmDelete(const LLSD& notification, const LLSD& response, LLObjectSelectionHandle handle); - + +public: + // Observer/callback support for when object selection changes or + // properties are received/updated + typedef boost::signals2::signal< void ()> update_signal_t; + update_signal_t mUpdateSignal; + private: LLPointer mSilhouetteImagep; LLObjectSelectionHandle mSelectedObjects; @@ -719,12 +736,12 @@ private: BOOL mForceSelection; LLAnimPauseRequest mPauseRequest; - - static std::set sObjectPropertiesFamilyRequests; }; -// Utilities -void dialog_refresh_all(); // Update subscribers to the selection list +// *DEPRECATED: For callbacks or observers, use +// LLSelectMgr::getInstance()->mUpdateSignal.connect( callback ) +// Update subscribers to the selection list +void dialog_refresh_all(); // Templates //----------------------------------------------------------------------------- diff --git a/indra/newview/llsky.cpp b/indra/newview/llsky.cpp index b6f4dedbd..de99cb86f 100644 --- a/indra/newview/llsky.cpp +++ b/indra/newview/llsky.cpp @@ -52,7 +52,6 @@ #include "llviewerobject.h" #include "llviewercamera.h" #include "pipeline.h" -#include "llagent.h" #include "lldrawpool.h" #include "llvosky.h" diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp index b9b9adafb..1c789e1ca 100644 --- a/indra/newview/llspatialpartition.cpp +++ b/indra/newview/llspatialpartition.cpp @@ -286,6 +286,10 @@ LLSpatialGroup::~LLSpatialGroup() llerrs << "Illegal deletion of LLSpatialGroup!" << llendl; }*/ + if (gDebugGL) + { + gPipeline.checkReferences(this); + } if (isState(DEAD)) { sZombieGroups--; @@ -293,9 +297,15 @@ LLSpatialGroup::~LLSpatialGroup() sNodeCount--; - if (gGLManager.mHasOcclusionQuery && mOcclusionQuery[LLViewerCamera::sCurCameraID]) + if (gGLManager.mHasOcclusionQuery) { - sQueryPool.release(mOcclusionQuery[LLViewerCamera::sCurCameraID]); + for (U32 i = 0; i < LLViewerCamera::NUM_CAMERAS; ++i) + { + if (mOcclusionQuery[i]) + { + sQueryPool.release(mOcclusionQuery[i]); + } + } } delete [] mOcclusionVerts; @@ -317,7 +327,7 @@ BOOL LLSpatialGroup::isRecentlyVisible() const BOOL LLSpatialGroup::isVisible() const { - return mVisible[LLViewerCamera::sCurCameraID] == LLDrawable::getCurrentFrame() ? TRUE : FALSE; + return mVisible[LLViewerCamera::sCurCameraID] >= LLDrawable::getCurrentFrame() ? TRUE : FALSE; } void LLSpatialGroup::setVisible() @@ -392,7 +402,7 @@ void LLSpatialGroup::checkStates() void validate_draw_info(LLDrawInfo& params) { #if LL_OCTREE_PARANOIA_CHECK - if (params.mVertexBuffer.isNull()) + if (!params.mVertexBuffer) { llerrs << "Draw batch has no vertex buffer." << llendl; } @@ -767,13 +777,14 @@ void LLSpatialGroup::shift(const LLVector3 &offset) if (mOcclusionVerts) { - for (U32 i = 0; i < 8; i++) + setState(OCCLUSION_DIRTY); + /*for (U32 i = 0; i < 8; i++) { F32* v = mOcclusionVerts+i*3; v[0] += offset.mV[0]; v[1] += offset.mV[1]; v[2] += offset.mV[2]; - } + }*/ } } @@ -969,12 +980,23 @@ void LLSpatialGroup::setOcclusionState(eOcclusionState state, S32 mode) for (U32 i = 0; i < LLViewerCamera::NUM_CAMERAS; i++) { mOcclusionState[i] |= state; + + if ((state & DISCARD_QUERY) && mOcclusionQuery[i]) + { + sQueryPool.release(mOcclusionQuery[i]); + mOcclusionQuery[i] = 0; + } } } } else { mOcclusionState[LLViewerCamera::sCurCameraID] |= state; + if ((state & DISCARD_QUERY) && mOcclusionQuery[LLViewerCamera::sCurCameraID]) + { + sQueryPool.release(mOcclusionQuery[LLViewerCamera::sCurCameraID]); + mOcclusionQuery[LLViewerCamera::sCurCameraID] = 0; + } } } @@ -1053,6 +1075,9 @@ LLSpatialGroup::LLSpatialGroup(OctreeNode* node, LLSpatialPartition* part) : sNodeCount++; LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); + mExtents[0] = mExtents[1] = mObjectBounds[0] = mObjectBounds[1] = + mObjectExtents[0] = mObjectExtents[1] = mViewAngle; + sg_assert(mOctreeNode->getListenerCount() == 0); mOctreeNode->addListener(this); setState(SG_INITIAL_STATE_MASK); @@ -1117,9 +1142,9 @@ F32 LLSpatialPartition::calcDistance(LLSpatialGroup* group, LLCamera& camera) { if (!group->mSpatialPartition->isBridge()) { - LLVector3 view_angle = LLVector3(eye * LLVector3(1,0,0), + LLVector3 view_angle = eye;/*LLVector3(eye * LLVector3(1,0,0), //WTF is this? eye * LLVector3(0,1,0), - eye * LLVector3(0,0,1)); + eye * LLVector3(0,0,1));*/ if ((view_angle-group->mLastUpdateViewAngle).magVec() > 0.64f) { @@ -1174,7 +1199,9 @@ F32 LLSpatialGroup::getUpdateUrgency() const } else { - return (gFrameTimeSeconds - mLastUpdateTime+4.f)/mDistance; + //return (gFrameTimeSeconds - mLastUpdateTime+4.f)/mDistance; + F32 time = gFrameTimeSeconds-mLastUpdateTime+4.f; + return (time + (mObjectBounds[1]*mObjectBounds[1]) + 1.f)/mDistance; } } @@ -1185,7 +1212,7 @@ BOOL LLSpatialGroup::needsUpdate() BOOL LLSpatialGroup::changeLOD() { - if (isState(ALPHA_DIRTY)) + if (isState(ALPHA_DIRTY | OBJECT_DIRTY)) { ///an alpha sort is going to happen, update distance and LOD return TRUE; } @@ -1199,7 +1226,8 @@ BOOL LLSpatialGroup::changeLOD() return TRUE; } - if (mDistance > mRadius) + //if (mDistance > mRadius) + if (mDistance > mRadius*2.f) { return FALSE; } @@ -1309,8 +1337,7 @@ void LLSpatialGroup::destroyGL() for (S32 j = 0; j < drawable->getNumFaces(); j++) { LLFace* facep = drawable->getFace(j); - facep->mVertexBuffer = NULL; - facep->mLastVertexBuffer = NULL; + facep->clearVertexBuffer(); } } } @@ -1399,12 +1426,29 @@ void LLSpatialGroup::checkOcclusion() } else if (isOcclusionState(QUERY_PENDING)) { //otherwise, if a query is pending, read it back + GLuint available = 0; + if (mOcclusionQuery[LLViewerCamera::sCurCameraID]) + { + glGetQueryObjectuivARB(mOcclusionQuery[LLViewerCamera::sCurCameraID], GL_QUERY_RESULT_AVAILABLE_ARB, &available); + } + else + { + available = 1; + } + + if (available) + { //result is available, read it back, otherwise wait until next frame GLuint res = 1; if (!isOcclusionState(DISCARD_QUERY) && mOcclusionQuery[LLViewerCamera::sCurCameraID]) { glGetQueryObjectuivARB(mOcclusionQuery[LLViewerCamera::sCurCameraID], GL_QUERY_RESULT_ARB, &res); - } - + } + else if (mOcclusionQuery[LLViewerCamera::sCurCameraID]) + { //delete the query to avoid holding onto hundreds of pending queries + sQueryPool.release(mOcclusionQuery[LLViewerCamera::sCurCameraID]); + mOcclusionQuery[LLViewerCamera::sCurCameraID] = 0; + } + if (isOcclusionState(DISCARD_QUERY)) { res = 2; @@ -1424,6 +1468,7 @@ void LLSpatialGroup::checkOcclusion() } clearOcclusionState(QUERY_PENDING | DISCARD_QUERY); + } } else if (mSpatialPartition->isOcclusionEnabled() && isOcclusionState(LLSpatialGroup::OCCLUDED)) { //check occlusion has been issued for occluded node that has not had a query issued @@ -1440,8 +1485,9 @@ void LLSpatialGroup::doOcclusion(LLCamera* camera) { //static const LLCachedControl render_water_void_culling("RenderWaterVoidCulling", TRUE); // Don't cull hole/edge water, unless RenderWaterVoidCulling is set and we have the GL_ARB_depth_clamp extension. - if ((mSpatialPartition->mDrawableType == LLDrawPool::POOL_VOIDWATER && !gGLManager.mHasDepthClamp) || - earlyFail(camera, this)) + //if ((mSpatialPartition->mDrawableType == LLDrawPool::POOL_VOIDWATER && !gGLManager.mHasDepthClamp) || + // earlyFail(camera, this)) + if (earlyFail(camera, this)) { setOcclusionState(LLSpatialGroup::DISCARD_QUERY); assert_states_valid(this); @@ -1450,54 +1496,83 @@ void LLSpatialGroup::doOcclusion(LLCamera* camera) } else { + if (!isOcclusionState(QUERY_PENDING) || isOcclusionState(DISCARD_QUERY)) { - LLFastTimer t(LLFastTimer::FTM_RENDER_OCCLUSION); + { //no query pending, or previous query to be discarded + //LLFastTimer t(FTM_RENDER_OCCLUSION); - if (!mOcclusionQuery[LLViewerCamera::sCurCameraID]) - { - mOcclusionQuery[LLViewerCamera::sCurCameraID] = sQueryPool.allocate(); - } + if (!mOcclusionQuery[LLViewerCamera::sCurCameraID]) + { + mOcclusionQuery[LLViewerCamera::sCurCameraID] = sQueryPool.allocate(); + } - if (!mOcclusionVerts || isState(LLSpatialGroup::OCCLUSION_DIRTY)) - { - buildOcclusion(); - } + if (!mOcclusionVerts || isState(LLSpatialGroup::OCCLUSION_DIRTY)) + { + buildOcclusion(); + } - // Depth clamp all water to avoid it being culled as a result of being - // behind the far clip plane, and in the case of edge water to avoid - // it being culled while still visible. - bool const use_depth_clamp = gGLManager.mHasDepthClamp && - (mSpatialPartition->mDrawableType == LLDrawPool::POOL_WATER || - mSpatialPartition->mDrawableType == LLDrawPool::POOL_VOIDWATER); - if (use_depth_clamp) - { - glEnable(GL_DEPTH_CLAMP); + // Depth clamp all water to avoid it being culled as a result of being + // behind the far clip plane, and in the case of edge water to avoid + // it being culled while still visible. + bool const use_depth_clamp = gGLManager.mHasDepthClamp && + (mSpatialPartition->mDrawableType == LLDrawPool::POOL_WATER || + mSpatialPartition->mDrawableType == LLDrawPool::POOL_VOIDWATER); + + LLGLEnable clamp(use_depth_clamp ? GL_DEPTH_CLAMP : 0); + +#if !LL_DARWIN + U32 mode = gGLManager.mHasOcclusionQuery2 ? /*GL_ANY_SAMPLES_PASSED*/0x8C2F : GL_SAMPLES_PASSED_ARB; +#else + U32 mode = GL_SAMPLES_PASSED_ARB; +#endif + + { + //LLFastTimer t(FTM_PUSH_OCCLUSION_VERTS); + glBeginQueryARB(mode, mOcclusionQuery[LLViewerCamera::sCurCameraID]); + glVertexPointer(3, GL_FLOAT, 0, mOcclusionVerts); + if (!use_depth_clamp && mSpatialPartition->mDrawableType == LLDrawPool::POOL_VOIDWATER) + { + LLGLSquashToFarClip squash(glh_get_current_projection(), 1); + if (camera->getOrigin().isExactlyZero()) + { //origin is invalid, draw entire box + glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8, + GL_UNSIGNED_BYTE, sOcclusionIndices); + glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8, + GL_UNSIGNED_BYTE, sOcclusionIndices+b111*8); + } + else + { + glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8, + GL_UNSIGNED_BYTE, get_box_fan_indices(camera, mBounds[0])); + } + } + else + { + if (camera->getOrigin().isExactlyZero()) + { //origin is invalid, draw entire box + glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8, + GL_UNSIGNED_BYTE, sOcclusionIndices); + glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8, + GL_UNSIGNED_BYTE, sOcclusionIndices+b111*8); + + } + else + { + glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8, + GL_UNSIGNED_BYTE, get_box_fan_indices(camera, mBounds[0])); + } + } + + glEndQueryARB(mode); + } } - glBeginQueryARB(GL_SAMPLES_PASSED_ARB, mOcclusionQuery[LLViewerCamera::sCurCameraID]); - glVertexPointer(3, GL_FLOAT, 0, mOcclusionVerts); - if (camera->getOrigin().isExactlyZero()) - { //origin is invalid, draw entire box - glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8, - GL_UNSIGNED_BYTE, sOcclusionIndices); - glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8, - GL_UNSIGNED_BYTE, sOcclusionIndices+b111*8); - } - else { - glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8, - GL_UNSIGNED_BYTE, get_box_fan_indices(camera, mBounds[0])); - } - glEndQueryARB(GL_SAMPLES_PASSED_ARB); - - if (use_depth_clamp) - { - glDisable(GL_DEPTH_CLAMP); + //LLFastTimer t(FTM_SET_OCCLUSION_STATE); + setOcclusionState(LLSpatialGroup::QUERY_PENDING); + clearOcclusionState(LLSpatialGroup::DISCARD_QUERY); } } - - setOcclusionState(LLSpatialGroup::QUERY_PENDING); - clearOcclusionState(LLSpatialGroup::DISCARD_QUERY); } } } @@ -1519,7 +1594,6 @@ LLSpatialPartition::LLSpatialPartition(U32 data_mask, BOOL render_by_group, U32 mSlopRatio = 0.25f; mInfiniteFarClip = FALSE; - LLGLNamePool::registerPool(&sQueryPool); mOctree = new LLSpatialGroup::OctreeRoot(LLVector3d(0,0,0), LLVector3d(1,1,1), @@ -1626,13 +1700,12 @@ void LLSpatialPartition::move(LLDrawable *drawablep, LLSpatialGroup *curp, BOOL class LLSpatialShift : public LLSpatialGroup::OctreeTraveler { public: - LLSpatialShift(LLVector3 offset) : mOffset(offset) { } + const LLVector3& mOffset; + LLSpatialShift(const LLVector3 &offset) : mOffset(offset) { } virtual void visit(const LLSpatialGroup::OctreeNode* branch) { ((LLSpatialGroup*) branch->getListener(0))->shift(mOffset); } - - LLVector3 mOffset; }; void LLSpatialPartition::shift(const LLVector3 &offset) @@ -1934,6 +2007,8 @@ public: void drawBox(const LLVector3& c, const LLVector3& r) { + LLVertexBuffer::unbind(); + gGL.begin(LLRender::TRIANGLE_STRIP); //left front gGL.vertex3fv((c+r.scaledVec(LLVector3(-1,1,-1))).mV); @@ -2179,7 +2254,7 @@ void pushVerts(LLSpatialGroup* group, U32 mask) void pushVerts(LLFace* face, U32 mask) { - LLVertexBuffer* buffer = face->mVertexBuffer; + LLVertexBuffer* buffer = face->getVertexBuffer(); if (buffer) { @@ -2309,7 +2384,7 @@ void renderOctree(LLSpatialGroup* group) for (S32 j = 0; j < drawable->getNumFaces(); j++) { LLFace* face = drawable->getFace(j); - if (face->mVertexBuffer.notNull()) + if (face->getVertexBuffer()) { if (gFrameTimeSeconds - face->mLastUpdateTime < 0.5f) { @@ -2324,10 +2399,10 @@ void renderOctree(LLSpatialGroup* group) continue; } - face->mVertexBuffer->setBuffer(LLVertexBuffer::MAP_VERTEX); + face->getVertexBuffer()->setBuffer(LLVertexBuffer::MAP_VERTEX); //drawBox((face->mExtents[0] + face->mExtents[1])*0.5f, // (face->mExtents[1]-face->mExtents[0])*0.5f); - face->mVertexBuffer->draw(LLRender::TRIANGLES, face->getIndicesCount(), face->getIndicesStart()); + face->getVertexBuffer()->draw(LLRender::TRIANGLES, face->getIndicesCount(), face->getIndicesStart()); } } @@ -2354,7 +2429,11 @@ void renderOctree(LLSpatialGroup* group) } gGL.color4fv(col.mV); - drawBox(group->mObjectBounds[0], group->mObjectBounds[1]*1.01f+LLVector3(0.001f, 0.001f, 0.001f)); + + { + LLGLDepthTest depth(GL_TRUE, GL_FALSE); + drawBox(group->mObjectBounds[0], group->mObjectBounds[1]*1.01f+LLVector3(0.001f, 0.001f, 0.001f)); + } gGL.setSceneBlendType(LLRender::BT_ALPHA); @@ -2663,7 +2742,6 @@ void renderPoints(LLDrawable* drawablep) { gGL.begin(LLRender::POINTS); gGL.color3f(1,1,1); - LLVector3 center(drawablep->getPositionGroup()); for (S32 i = 0; i < drawablep->getNumFaces(); i++) { gGL.vertex3fv(drawablep->getFace(i)->mCenterLocal.mV); @@ -3314,6 +3392,11 @@ LLDrawInfo::~LLDrawInfo() { mFace->setDrawInfo(NULL); } + + if (gDebugGL) + { + gPipeline.checkReferences(this); + } } LLVertexBuffer* LLGeometryManager::createVertexBuffer(U32 type_mask, U32 usage) diff --git a/indra/newview/llspatialpartition.h b/indra/newview/llspatialpartition.h index abf58a79b..093a13d78 100644 --- a/indra/newview/llspatialpartition.h +++ b/indra/newview/llspatialpartition.h @@ -295,6 +295,13 @@ public: virtual void handleChildAddition(const OctreeNode* parent, OctreeNode* child); virtual void handleChildRemoval(const OctreeNode* parent, const OctreeNode* child); + LLVector3 mBounds[2]; + LLVector3 mExtents[2]; + + LLVector3 mObjectExtents[2]; + LLVector3 mObjectBounds[2]; + LLVector3 mViewAngle; + LLVector3 mLastUpdateViewAngle; protected: virtual ~LLSpatialGroup(); @@ -310,11 +317,6 @@ public: F32 mBuilt; OctreeNode* mOctreeNode; LLSpatialPartition* mSpatialPartition; - LLVector3 mBounds[2]; - LLVector3 mExtents[2]; - - LLVector3 mObjectExtents[2]; - LLVector3 mObjectBounds[2]; LLPointer mVertexBuffer; F32* mOcclusionVerts; @@ -328,9 +330,6 @@ public: F32 mDepth; F32 mLastUpdateDistance; F32 mLastUpdateTime; - - LLVector3 mViewAngle; - LLVector3 mLastUpdateViewAngle; F32 mPixelArea; F32 mRadius; @@ -466,6 +465,7 @@ public: sg_list_t::iterator beginAlphaGroups(); sg_list_t::iterator endAlphaGroups(); + bool hasOcclusionGroups() { return mOcclusionGroupsSize > 0; } sg_list_t::iterator beginOcclusionGroups(); sg_list_t::iterator endOcclusionGroups(); diff --git a/indra/newview/llsprite.cpp b/indra/newview/llsprite.cpp index dce4e9d14..45d7165ca 100644 --- a/indra/newview/llsprite.cpp +++ b/indra/newview/llsprite.cpp @@ -192,14 +192,15 @@ void LLSprite::updateFace(LLFace &face) U16 index_offset; // Setup face - if (face.mVertexBuffer.isNull()) + if (!face.getVertexBuffer()) { - face.mVertexBuffer = new LLVertexBuffer(LLVertexBuffer::MAP_VERTEX | + LLVertexBuffer* buff = new LLVertexBuffer(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, GL_STREAM_DRAW_ARB); - face.mVertexBuffer->allocateBuffer(4, 12, TRUE); + buff->allocateBuffer(4, 12, TRUE); face.setGeomIndex(0); face.setIndicesIndex(0); + face.setVertexBuffer(buff); } index_offset = face.getGeometry(verticesp,normalsp,tex_coordsp, indicesp); @@ -248,7 +249,7 @@ void LLSprite::updateFace(LLFace &face) *indicesp++ = 3 + index_offset; } - face.mVertexBuffer->setBuffer(0); + face.getVertexBuffer()->setBuffer(0); face.mCenterAgent = mPosition; } diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index cb216c2ea..4ebedf7b5 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -54,12 +54,12 @@ #include "hippogridmanager.h" #include "hippolimits.h" #include "floaterao.h" +#include "statemachine/aifilepicker.h" #include "llares.h" #include "llcachename.h" #include "llviewercontrol.h" #include "lldir.h" -#include "lleventpoll.h" // OGPX for Agent Domain event queue #include "llerrorcontrol.h" #include "llfiltersd2xmlrpc.h" #include "llfocusmgr.h" @@ -139,7 +139,6 @@ #include "llpreview.h" #include "llpreviewscript.h" #include "llproductinforequest.h" -#include "llsdhttpserver.h" // OGPX might not need when EVENTHACK is sorted #include "llsecondlifeurls.h" #include "llselectmgr.h" #include "llsky.h" @@ -635,6 +634,12 @@ bool idle_startup() LLStartUp::handleSocksProxy(false); + //------------------------------------------------- + // Load file- and dirpicker {context, default path} map. + //------------------------------------------------- + + AIFilePicker::loadFile("filepicker_contexts.xml"); + //------------------------------------------------- // Init audio, which may be needed for prefs dialog // or audio cues in connection UI. @@ -2024,7 +2029,7 @@ bool idle_startup() LLFloaterActiveSpeakers::showInstance(); } - if (gSavedSettings.getBOOL("BeaconAlwaysOn")) + if (gSavedSettings.getBOOL("ShowBeaconsFloater")) { LLFloaterBeacons::showInstance(); } diff --git a/indra/newview/lltexlayer.cpp b/indra/newview/lltexlayer.cpp index 3dce4b321..f204bc227 100644 --- a/indra/newview/lltexlayer.cpp +++ b/indra/newview/lltexlayer.cpp @@ -218,7 +218,7 @@ BOOL LLTexLayerSetBuffer::needsRender() { LLVOAvatar* avatar = mTexLayerSet->getAvatar(); BOOL upload_now = needsUploadNow(); - BOOL needs_update = (mNeedsUpdate || upload_now) && !avatar->mAppearanceAnimating; + BOOL needs_update = (mNeedsUpdate || upload_now) && !avatar->getIsAppearanceAnimating(); if (needs_update) { BOOL invalid_skirt = avatar->getBakedTE(mTexLayerSet) == TEX_SKIRT_BAKED && !avatar->isWearingWearableType(WT_SKIRT); @@ -1736,7 +1736,7 @@ BOOL LLTexLayer::renderAlphaMasks( S32 x, S32 y, S32 width, S32 height, LLColor4 for( morph_list_t::iterator iter3 = mMaskedMorphs.begin(); iter3 != mMaskedMorphs.end(); iter3++ ) { - LLMaskedMorph* maskedMorph = &(*iter3); + LLVOAvatar::LLMaskedMorph* maskedMorph = &(*iter3); maskedMorph->mMorphTarget->applyMask(alpha_data, width, height, 1, maskedMorph->mInvert); } } @@ -1749,7 +1749,7 @@ void LLTexLayer::applyMorphMask(U8* tex_data, S32 width, S32 height, S32 num_com for( morph_list_t::iterator iter = mMaskedMorphs.begin(); iter != mMaskedMorphs.end(); iter++ ) { - LLMaskedMorph* maskedMorph = &(*iter); + LLVOAvatar::LLMaskedMorph* maskedMorph = &(*iter); maskedMorph->mMorphTarget->applyMask(tex_data, width, height, num_components, maskedMorph->mInvert); } } @@ -1832,7 +1832,7 @@ void LLTexLayer::requestUpdate() void LLTexLayer::addMaskedMorph(LLPolyMorphTarget* morph_target, BOOL invert) { - mMaskedMorphs.push_front(LLMaskedMorph(morph_target, invert)); + mMaskedMorphs.push_front(LLVOAvatar::LLMaskedMorph(morph_target, invert)); } void LLTexLayer::invalidateMorphMasks() @@ -2619,11 +2619,3 @@ BOOL LLTexStaticImageList::loadImageRaw( const std::string& file_name, LLImageRa return success; } -//----------------------------------------------------------------------------- -// LLMaskedMorph() -//----------------------------------------------------------------------------- -LLMaskedMorph::LLMaskedMorph( LLPolyMorphTarget *morph_target, BOOL invert ) : mMorphTarget(morph_target), mInvert(invert) -{ - morph_target->addPendingMorphMask(); -} - diff --git a/indra/newview/lltexlayer.h b/indra/newview/lltexlayer.h index 05becfd95..d88466f50 100644 --- a/indra/newview/lltexlayer.h +++ b/indra/newview/lltexlayer.h @@ -45,6 +45,7 @@ #include "llwearable.h" #include "v4color.h" #include "llfloater.h" +#include "llvoavatar.h" class LLTexLayerSetInfo; class LLTexLayerSet; @@ -309,20 +310,6 @@ protected: LLTexLayerSetInfo *mInfo; }; -//----------------------------------------------------------------------------- -// LLMaskedMorph -//----------------------------------------------------------------------------- - -class LLMaskedMorph -{ -public: - LLMaskedMorph( LLPolyMorphTarget *morph_target, BOOL invert ); - -public: - LLPolyMorphTarget *mMorphTarget; - BOOL mInvert; -}; - //----------------------------------------------------------------------------- // LLTexLayer // A single texture layer @@ -374,7 +361,7 @@ protected: alpha_list_t mParamAlphaList; - typedef std::deque morph_list_t; + typedef std::deque morph_list_t; morph_list_t mMaskedMorphs; typedef std::map alpha_cache_t; alpha_cache_t mAlphaCache; diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp index 319f1cb57..e92a5185c 100644 --- a/indra/newview/lltexturectrl.cpp +++ b/indra/newview/lltexturectrl.cpp @@ -74,7 +74,6 @@ // tag: vaa emerald local_asset_browser [begin] #include "floaterlocalassetbrowse.h" #include "llscrolllistctrl.h" -#include "llfilepicker.h" #define LOCALLIST_COL_ID 1 // tag: vaa emerald local_asset_browser [end] diff --git a/indra/newview/lltoolbar.cpp b/indra/newview/lltoolbar.cpp index ee1165815..11fb9ada1 100644 --- a/indra/newview/lltoolbar.cpp +++ b/indra/newview/lltoolbar.cpp @@ -295,7 +295,7 @@ void LLToolBar::refresh() BOOL sitting = FALSE; if (gAgent.getAvatarObject()) { - sitting = gAgent.getAvatarObject()->mIsSitting; + sitting = gAgent.getAvatarObject()->isSitting(); } childSetEnabled("fly_btn", (gAgent.canFly() || gAgent.getFlying() || gSavedSettings.getBOOL("AscentFlyAlwaysEnabled")) && !sitting ); diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp index c14169ff4..ebedef626 100644 --- a/indra/newview/lltooldraganddrop.cpp +++ b/indra/newview/lltooldraganddrop.cpp @@ -2068,7 +2068,7 @@ EAcceptance LLToolDragAndDrop::willObjectAcceptInventory(LLViewerObject* obj, LL else if ( (gRlvHandler.hasBehaviour(RLV_BHVR_UNSIT)) || (gRlvHandler.hasBehaviour(RLV_BHVR_SITTP)) ) { LLVOAvatar* pAvatar = gAgent.getAvatarObject(); - if ( (pAvatar) && (pAvatar->mIsSitting) && (pAvatar->getRoot() == pObjRoot) ) + if ( (pAvatar) && (pAvatar->isSitting()) && (pAvatar->getRoot() == pObjRoot) ) return ACCEPT_NO_LOCKED; // ... or on a linkset the avie is sitting on under @unsit=n/@sittp=n } } diff --git a/indra/newview/lltoolmorph.cpp b/indra/newview/lltoolmorph.cpp index 2fb245b37..3516bc38c 100644 --- a/indra/newview/lltoolmorph.cpp +++ b/indra/newview/lltoolmorph.cpp @@ -146,7 +146,7 @@ void LLVisualParamHint::requestHintUpdates( LLVisualParamHint* exception1, LLVis BOOL LLVisualParamHint::needsRender() { - return mNeedsUpdate && mDelayFrames-- <= 0 && !gAgent.getAvatarObject()->mAppearanceAnimating && mAllowsUpdates; + return mNeedsUpdate && mDelayFrames-- <= 0 && !gAgent.getAvatarObject()->getIsAppearanceAnimating() && mAllowsUpdates; } void LLVisualParamHint::preRender(BOOL clear_depth) diff --git a/indra/newview/lltoolpie.cpp b/indra/newview/lltoolpie.cpp index bcdaf45c5..5fbb48258 100644 --- a/indra/newview/lltoolpie.cpp +++ b/indra/newview/lltoolpie.cpp @@ -204,7 +204,7 @@ BOOL LLToolPie::pickAndShowMenu(BOOL always_show) // touch behavior down below... break; case CLICK_ACTION_SIT: - if ((gAgent.getAvatarObject() != NULL) && (!gAgent.getAvatarObject()->mIsSitting) + if ((gAgent.getAvatarObject() != NULL) && (!gAgent.getAvatarObject()->isSitting()) && (!gSavedSettings.getBOOL("DisableClickSit"))) // agent not already sitting { handle_sit_or_stand(); @@ -552,9 +552,9 @@ ECursorType cursor_from_object(LLViewerObject* object) switch(click_action) { case CLICK_ACTION_SIT: -// if ((gAgent.getAvatarObject() != NULL) && (!gAgent.getAvatarObject()->mIsSitting)) // not already sitting? +// if ((gAgent.getAvatarObject() != NULL) && (!gAgent.getAvatarObject()->isSitting())) // not already sitting? // [RLVa:KB] - Checked: 2009-12-22 (RLVa-1.1.0k) | Added: RLVa-1.1.0j - if ( ((gAgent.getAvatarObject() != NULL) && (!gAgent.getAvatarObject()->mIsSitting)) && // not already sitting? + if ( ((gAgent.getAvatarObject() != NULL) && (!gAgent.getAvatarObject()->isSitting())) && // not already sitting? ((!rlv_handler_t::isEnabled()) || (gRlvHandler.canSit(object, gViewerWindow->getHoverPick().mObjectOffset))) ) // [/RLVa:KB] { diff --git a/indra/newview/lltoolselect.cpp b/indra/newview/lltoolselect.cpp index 1e412de26..b68e19f19 100644 --- a/indra/newview/lltoolselect.cpp +++ b/indra/newview/lltoolselect.cpp @@ -56,9 +56,6 @@ #include "llfloatertools.h" // [/RLVa:KB] -// Globals -extern BOOL gAllowSelectAvatar; - const F32 SELECTION_ROTATION_TRESHOLD = 0.1f; LLToolSelect::LLToolSelect( LLToolComposite* composite ) @@ -137,7 +134,7 @@ LLObjectSelectionHandle LLToolSelect::handleObjectSelection(const LLPickInfo& pi BOOL select_movable = gSavedSettings.getBOOL("SelectMovableOnly"); // *NOTE: These settings must be cleaned up at bottom of function. - if (temp_select || gAllowSelectAvatar) + if (temp_select || LLSelectMgr::getInstance()->mAllowSelectAvatar) { gSavedSettings.setBOOL("SelectOwnedOnly", FALSE); gSavedSettings.setBOOL("SelectMovableOnly", FALSE); @@ -267,7 +264,7 @@ LLObjectSelectionHandle LLToolSelect::handleObjectSelection(const LLPickInfo& pi } //if(!object) // Cleanup temp select settings above. - if (temp_select || gAllowSelectAvatar) + if (temp_select || LLSelectMgr::getInstance()->mAllowSelectAvatar) { gSavedSettings.setBOOL("SelectOwnedOnly", select_owned); gSavedSettings.setBOOL("SelectMovableOnly", select_movable); diff --git a/indra/newview/lluploaddialog.cpp b/indra/newview/lluploaddialog.cpp index 2ba87f01b..a860e5303 100644 --- a/indra/newview/lluploaddialog.cpp +++ b/indra/newview/lluploaddialog.cpp @@ -161,10 +161,6 @@ void LLUploadDialog::setMessage( const std::string& msg) LLUploadDialog::~LLUploadDialog() { gFocusMgr.releaseFocusIfNeeded( this ); - -// LLFilePicker::instance().reset(); - - LLUploadDialog::sDialog = NULL; } diff --git a/indra/newview/llurlhistory.cpp b/indra/newview/llurlhistory.cpp index a93cc2ff7..5f17aef78 100644 --- a/indra/newview/llurlhistory.cpp +++ b/indra/newview/llurlhistory.cpp @@ -77,7 +77,7 @@ bool LLURLHistory::saveFile(const std::string& filename) std::string temp_str = gDirUtilp->getLindenUserDir(true); if( temp_str.empty() ) { - llwarns << "Can't save. No user directory set." << llendl; + llinfos << "Can't save URL history - no user directory set yet." << llendl; return false; } diff --git a/indra/newview/llurlwhitelist.cpp b/indra/newview/llurlwhitelist.cpp index da69039cf..46bc9276c 100644 --- a/indra/newview/llurlwhitelist.cpp +++ b/indra/newview/llurlwhitelist.cpp @@ -121,6 +121,12 @@ bool LLUrlWhiteList::save () // build filename for each user std::string resolvedFilename = gDirUtilp->getExpandedFilename ( LL_PATH_PER_SL_ACCOUNT, mFilename ); + if (resolvedFilename.empty()) + { + llinfos << "No per-user dir for saving URL whitelist - presumably not logged in yet. Skipping." << llendl; + return false; + } + // open a file for writing llofstream file ( resolvedFilename ); if ( file.is_open () ) diff --git a/indra/newview/llviewercamera.cpp b/indra/newview/llviewercamera.cpp index 260c6e253..022f7bc59 100644 --- a/indra/newview/llviewercamera.cpp +++ b/indra/newview/llviewercamera.cpp @@ -729,6 +729,10 @@ LLVector3 LLViewerCamera::roundToPixel(const LLVector3 &pos_agent) BOOL LLViewerCamera::cameraUnderWater() const { + if(!gAgent.getRegion()) + { + return FALSE ; + } return getOrigin().mV[VZ] < gAgent.getRegion()->getWaterHeight(); } diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp index 6ef3d762a..410dcc004 100644 --- a/indra/newview/llviewercontrol.cpp +++ b/indra/newview/llviewercontrol.cpp @@ -75,6 +75,7 @@ #include "llnetmap.h" #include "llrender.h" #include "llfloaterchat.h" +#include "statemachine/aistatemachine.h" #include "aithreadsafe.h" #include "llviewerobjectlist.h" #include "lldrawpoolbump.h" @@ -119,6 +120,11 @@ static bool handleTerrainDetailChanged(const LLSD& newvalue) return true; } +bool handleStateMachineMaxTimeChanged(const LLSD& newvalue) +{ + AIStateMachine::updateSettings(); + return true; +} static bool handleSetShaderChanged(const LLSD& newvalue) { @@ -186,6 +192,12 @@ static bool handleSetSelfInvisible( const LLSD& newvalue) return true; } +bool handleRenderTransparentWaterChanged(const LLSD& newvalue) +{ + LLWorld::getInstance()->updateWaterObjects(); + return true; +} + static bool handleReleaseGLBufferChanged(const LLSD& newvalue) { if (gPipeline.isInit()) @@ -400,15 +412,6 @@ static bool handleWLSkyDetailChanged(const LLSD&) return true; } -static bool handleRenderLightingDetailChanged(const LLSD& newvalue) -{ - if (gPipeline.isInit()) - { - gPipeline.setLightingDetail(newvalue.asInteger()); - } - return true; -} - static bool handleResetVertexBuffersChanged(const LLSD&) { if (gPipeline.isInit()) @@ -424,6 +427,12 @@ static bool handleRenderDynamicLODChanged(const LLSD& newvalue) return true; } +static bool handleRenderLocalLightsChanged(const LLSD& newvalue) +{ + gPipeline.setLightingDetail(-1); + return true; +} + static bool handleRenderUseFBOChanged(const LLSD& newvalue) { LLRenderTarget::sUseFBO = newvalue.asBoolean(); @@ -542,6 +551,7 @@ bool handleAscentSelfTag(const LLSD& newvalue) gAgent.getAvatarObject()->mClientTag = ""; return true; } + bool handleAscentGlobalTag(const LLSD& newvalue) { S32 object_count = gObjectList.getNumObjects(); @@ -554,6 +564,13 @@ bool handleAscentGlobalTag(const LLSD& newvalue) return true; } +bool handleAscentAvatarModifier(const LLSD& newvalue) +{ + llinfos << "Calling gAgent.sendAgentSetAppearance() because AscentAvatar*Modifier changed." << llendl; + gAgent.sendAgentSetAppearance(); + return true; +} + // [Ansariel: Display name support] static bool handlePhoenixNameSystemChanged(const LLSD& newvalue) { @@ -574,8 +591,12 @@ void settings_setup_listeners() gSavedSettings.getControl("RenderAnimateTrees")->getSignal()->connect(boost::bind(&handleResetVertexBuffersChanged, _1)); gSavedSettings.getControl("RenderAvatarVP")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _1)); gSavedSettings.getControl("VertexShaderEnable")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _1)); + gSavedSettings.getControl("RenderSpecularResX")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _1)); + gSavedSettings.getControl("RenderSpecularResY")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _1)); + gSavedSettings.getControl("RenderSpecularExponent")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _1)); gSavedSettings.getControl("RenderFSAASamples")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _1)); gSavedSettings.getControl("RenderAnisotropic")->getSignal()->connect(boost::bind(&handleAnisotropicChanged, _1)); + gSavedSettings.getControl("RenderShadowResolutionScale")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _1)); gSavedSettings.getControl("RenderGlow")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _1)); gSavedSettings.getControl("RenderGlow")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _1)); gSavedSettings.getControl("EnableRippleWater")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _1)); @@ -587,22 +608,16 @@ void settings_setup_listeners() gSavedSettings.getControl("RenderAvatarInvisible")->getSignal()->connect(boost::bind(&handleSetSelfInvisible, _1)); gSavedSettings.getControl("RenderVolumeLODFactor")->getSignal()->connect(boost::bind(&handleVolumeLODChanged, _1)); gSavedSettings.getControl("RenderAvatarLODFactor")->getSignal()->connect(boost::bind(&handleAvatarLODChanged, _1)); + gSavedSettings.getControl("RenderAvatarPhysicsLODFactor")->getSignal()->connect(boost::bind(&handleAvatarPhysicsLODChanged, _1)); gSavedSettings.getControl("RenderTerrainLODFactor")->getSignal()->connect(boost::bind(&handleTerrainLODChanged, _1)); gSavedSettings.getControl("RenderTreeLODFactor")->getSignal()->connect(boost::bind(&handleTreeLODChanged, _1)); - gSavedSettings.getControl("RenderAvatarPhysicsLODFactor")->getSignal()->connect(boost::bind(&handleAvatarPhysicsLODChanged, _1)); gSavedSettings.getControl("RenderFlexTimeFactor")->getSignal()->connect(boost::bind(&handleFlexLODChanged, _1)); gSavedSettings.getControl("ThrottleBandwidthKBPS")->getSignal()->connect(boost::bind(&handleBandwidthChanged, _1)); gSavedSettings.getControl("RenderGamma")->getSignal()->connect(boost::bind(&handleGammaChanged, _1)); - gSavedSettings.getControl("EmeraldBoobMass")->getSignal()->connect(boost::bind(&handleAvatarBoobMassChanged, _1)); - gSavedSettings.getControl("EmeraldBoobHardness")->getSignal()->connect(boost::bind(&handleAvatarBoobHardnessChanged, _1)); - gSavedSettings.getControl("EmeraldBoobVelMax")->getSignal()->connect(boost::bind(&handleAvatarBoobVelMaxChanged, _1)); - gSavedSettings.getControl("EmeraldBoobFriction")->getSignal()->connect(boost::bind(&handleAvatarBoobFrictionChanged, _1)); - gSavedSettings.getControl("EmeraldBoobVelMin")->getSignal()->connect(boost::bind(&handleAvatarBoobVelMinChanged, _1)); - gSavedSettings.getControl("EmeraldBreastPhysicsToggle")->getSignal()->connect(boost::bind(&handleAvatarBoobToggleChanged, _1)); - gSavedSettings.getControl("EmeraldBoobXYInfluence")->getSignal()->connect(boost::bind(&handleAvatarBoobXYInfluence, _1)); gSavedSettings.getControl("RenderFogRatio")->getSignal()->connect(boost::bind(&handleFogRatioChanged, _1)); gSavedSettings.getControl("RenderMaxPartCount")->getSignal()->connect(boost::bind(&handleMaxPartCountChanged, _1)); gSavedSettings.getControl("RenderDynamicLOD")->getSignal()->connect(boost::bind(&handleRenderDynamicLODChanged, _1)); + gSavedSettings.getControl("RenderLocalLights")->getSignal()->connect(boost::bind(&handleRenderLocalLightsChanged, _1)); gSavedSettings.getControl("RenderDebugTextureBind")->getSignal()->connect(boost::bind(&handleResetVertexBuffersChanged, _1)); gSavedSettings.getControl("RenderFastAlpha")->getSignal()->connect(boost::bind(&handleResetVertexBuffersChanged, _1)); gSavedSettings.getControl("RenderObjectBump")->getSignal()->connect(boost::bind(&handleResetVertexBuffersChanged, _1)); @@ -617,7 +632,11 @@ void settings_setup_listeners() gSavedSettings.getControl("RenderDebugPipeline")->getSignal()->connect(boost::bind(&handleRenderDebugPipelineChanged, _1)); gSavedSettings.getControl("RenderResolutionDivisor")->getSignal()->connect(boost::bind(&handleRenderResolutionDivisorChanged, _1)); gSavedSettings.getControl("RenderDeferred")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _1)); + gSavedSettings.getControl("RenderShadowDetail")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _1)); + gSavedSettings.getControl("RenderDeferredSSAO")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _1)); + gSavedSettings.getControl("RenderDeferredGI")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _1)); gSavedSettings.getControl("TextureMemory")->getSignal()->connect(boost::bind(&handleVideoMemoryChanged, _1)); + gSavedSettings.getControl("AuditTexture")->getSignal()->connect(boost::bind(&handleAuditTextureChanged, _1)); gSavedSettings.getControl("ChatFontSize")->getSignal()->connect(boost::bind(&handleChatFontSizeChanged, _1)); gSavedSettings.getControl("ChatPersistTime")->getSignal()->connect(boost::bind(&handleChatPersistTimeChanged, _1)); gSavedSettings.getControl("UploadBakedTexOld")->getSignal()->connect(boost::bind(&handleUploadBakedTexOldChanged, _1)); @@ -632,7 +651,6 @@ void settings_setup_listeners() gSavedSettings.getControl("AudioLevelDoppler")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _1)); gSavedSettings.getControl("AudioLevelRolloff")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _1)); gSavedSettings.getControl("AudioStreamingMusic")->getSignal()->connect(boost::bind(&handleAudioStreamMusicChanged, _1)); - gSavedSettings.getControl("AuditTexture")->getSignal()->connect(boost::bind(&handleAuditTextureChanged, _1)); gSavedSettings.getControl("MuteAudio")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _1)); gSavedSettings.getControl("MuteMusic")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _1)); gSavedSettings.getControl("MuteMedia")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _1)); @@ -641,8 +659,8 @@ void settings_setup_listeners() gSavedSettings.getControl("MuteUI")->getSignal()->connect(boost::bind(&handleAudioVolumeChanged, _1)); gSavedSettings.getControl("RenderVBOEnable")->getSignal()->connect(boost::bind(&handleRenderUseVBOChanged, _1)); gSavedSettings.getControl("RenderVBOMappingDisable")->getSignal()->connect(boost::bind(&handleRenderUseVBOMappingChanged, _1)); + gSavedSettings.getControl("RenderPreferStreamDraw")->getSignal()->connect(boost::bind(&handleResetVertexBuffersChanged, _1)); gSavedSettings.getControl("WLSkyDetail")->getSignal()->connect(boost::bind(&handleWLSkyDetailChanged, _1)); - gSavedSettings.getControl("RenderLightingDetail")->getSignal()->connect(boost::bind(&handleRenderLightingDetailChanged, _1)); gSavedSettings.getControl("NumpadControl")->getSignal()->connect(boost::bind(&handleNumpadControlChanged, _1)); gSavedSettings.getControl("JoystickAxis0")->getSignal()->connect(boost::bind(&handleJoystickChanged, _1)); gSavedSettings.getControl("JoystickAxis1")->getSignal()->connect(boost::bind(&handleJoystickChanged, _1)); @@ -707,10 +725,20 @@ void settings_setup_listeners() gSavedSettings.getControl("AudioLevelMic")->getSignal()->connect(boost::bind(&handleVoiceClientPrefsChanged, _1)); gSavedSettings.getControl("LipSyncEnabled")->getSignal()->connect(boost::bind(&handleVoiceClientPrefsChanged, _1)); gSavedSettings.getControl("TranslateChat")->getSignal()->connect(boost::bind(&handleTranslateChatPrefsChanged, _1)); + gSavedSettings.getControl("StateMachineMaxTime")->getSignal()->connect(boost::bind(&handleStateMachineMaxTimeChanged, _1)); gSavedSettings.getControl("CloudsEnabled")->getSignal()->connect(boost::bind(&handleCloudSettingsChanged, _1)); gSavedSettings.getControl("SkyUseClassicClouds")->getSignal()->connect(boost::bind(&handleCloudSettingsChanged, _1)); + gSavedSettings.getControl("RenderTransparentWater")->getSignal()->connect(boost::bind(&handleRenderTransparentWaterChanged, _1)); + gSavedSettings.getControl("EmeraldBoobMass")->getSignal()->connect(boost::bind(&handleAvatarBoobMassChanged, _1)); + gSavedSettings.getControl("EmeraldBoobHardness")->getSignal()->connect(boost::bind(&handleAvatarBoobHardnessChanged, _1)); + gSavedSettings.getControl("EmeraldBoobVelMax")->getSignal()->connect(boost::bind(&handleAvatarBoobVelMaxChanged, _1)); + gSavedSettings.getControl("EmeraldBoobFriction")->getSignal()->connect(boost::bind(&handleAvatarBoobFrictionChanged, _1)); + gSavedSettings.getControl("EmeraldBoobVelMin")->getSignal()->connect(boost::bind(&handleAvatarBoobVelMinChanged, _1)); + gSavedSettings.getControl("EmeraldBreastPhysicsToggle")->getSignal()->connect(boost::bind(&handleAvatarBoobToggleChanged, _1)); + gSavedSettings.getControl("EmeraldBoobXYInfluence")->getSignal()->connect(boost::bind(&handleAvatarBoobXYInfluence, _1)); + gSavedSettings.getControl("AscentUseTag")->getSignal()->connect(boost::bind(&handleAscentSelfTag,_1)); gSavedSettings.getControl("AscentUseCustomTag")->getSignal()->connect(boost::bind(&handleAscentSelfTag,_1)); gSavedSettings.getControl("AscentCustomTagColor")->getSignal()->connect(boost::bind(&handleAscentSelfTag,_1)); @@ -718,6 +746,9 @@ void settings_setup_listeners() gSavedSettings.getControl("AscentReportClientUUID")->getSignal()->connect(boost::bind(&handleAscentSelfTag,_1)); gSavedSettings.getControl("AscentShowFriendsTag")->getSignal()->connect(boost::bind(&handleAscentGlobalTag,_1)); gSavedSettings.getControl("AscentUseStatusColors")->getSignal()->connect(boost::bind(&handleAscentGlobalTag,_1)); + gSavedSettings.getControl("AscentAvatarXModifier")->getSignal()->connect(boost::bind(&handleAscentAvatarModifier, _1)); + gSavedSettings.getControl("AscentAvatarYModifier")->getSignal()->connect(boost::bind(&handleAscentAvatarModifier, _1)); + gSavedSettings.getControl("AscentAvatarZModifier")->getSignal()->connect(boost::bind(&handleAscentAvatarModifier, _1)); // [Ansariel: Display name support] gSavedSettings.getControl("PhoenixNameSystem")->getSignal()->connect(boost::bind(&handlePhoenixNameSystemChanged, _1)); @@ -803,6 +834,16 @@ template <> eControlType get_control_type(const LLSD& in, LLSD& out) return TYPE_LLSD; } +void onCommitControlSetting_gSavedSettings(LLUICtrl* ctrl, void* name) +{ + gSavedSettings.setValue((const char*)name,ctrl->getValue()); +} + +void onCommitControlSetting_gSavedPerAccountSettings(LLUICtrl* ctrl, void* name) +{ + gSavedPerAccountSettings.setValue((const char*)name,ctrl->getValue()); +} + #if TEST_CACHED_CONTROL #define DECL_LLCC(T, V) static LLCachedControl mySetting_##T("TestCachedControl"#T, V) @@ -826,7 +867,7 @@ static LLCachedControl test_BrowserHomePage("BrowserHomePage", "hah void test_cached_control() { -#define TEST_LLCC(T, V) if((T)mySetting_##T != V) llerrs << "Fail "#T << llendl +#define do { TEST_LLCC(T, V) if((T)mySetting_##T != V) llerrs << "Fail "#T << llendl; } while(0) TEST_LLCC(U32, 666); TEST_LLCC(S32, (S32)-666); TEST_LLCC(F32, (F32)-666.666); diff --git a/indra/newview/llviewercontrol.h b/indra/newview/llviewercontrol.h index 8835146ad..f22f96f27 100644 --- a/indra/newview/llviewercontrol.h +++ b/indra/newview/llviewercontrol.h @@ -35,9 +35,10 @@ #include #include "llcontrol.h" -#include "lluictrl.h" #include "aithreadsafe.h" +class LLUICtrl; + // Enabled this definition to compile a 'hacked' viewer that // allows a hacked godmode to be toggled on and off. #define TOGGLE_HACKED_GODLIKE_VIEWER @@ -75,8 +76,8 @@ bool handleCloudSettingsChanged(const LLSD& newvalue); //A template would be a little awkward to use here.. so.. a preprocessor macro. Alas. onCommitControlSetting(gSavedSettings) etc. -inline void onCommitControlSetting_gSavedSettings(LLUICtrl* ctrl, void* name) {gSavedSettings.setValue((const char*)name,ctrl->getValue());} -inline void onCommitControlSetting_gSavedPerAccountSettings(LLUICtrl* ctrl, void* name) {gSavedPerAccountSettings.setValue((const char*)name,ctrl->getValue());} +void onCommitControlSetting_gSavedSettings(LLUICtrl* ctrl, void* name); +void onCommitControlSetting_gSavedPerAccountSettings(LLUICtrl* ctrl, void* name); #define onCommitControlSetting(controlgroup) onCommitControlSetting_##controlgroup //#define TEST_CACHED_CONTROL 1 diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp index ab8dc18f8..8e62a5753 100644 --- a/indra/newview/llviewerdisplay.cpp +++ b/indra/newview/llviewerdisplay.cpp @@ -648,14 +648,14 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot, boo && gSavedSettings.getBOOL("UseOcclusion") && gGLManager.mHasOcclusionQuery) ? 2 : 0; - if (LLPipeline::sUseOcclusion && LLPipeline::sRenderDeferred) + /*if (LLPipeline::sUseOcclusion && LLPipeline::sRenderDeferred) { //force occlusion on for all render types if doing deferred render LLPipeline::sUseOcclusion = 3; - } + }*/ LLPipeline::sFastAlpha = gSavedSettings.getBOOL("RenderFastAlpha"); LLPipeline::sUseFarClip = gSavedSettings.getBOOL("RenderUseFarClip"); - LLVOAvatar::sMaxVisible = gSavedSettings.getS32("RenderAvatarMaxVisible"); + LLVOAvatar::sMaxVisible = (U32)gSavedSettings.getS32("RenderAvatarMaxVisible"); LLPipeline::sDelayVBUpdate = gSavedSettings.getBOOL("RenderDelayVBUpdate"); S32 occlusion = LLPipeline::sUseOcclusion; @@ -784,7 +784,6 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot, boo { LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD; gFrameStats.start(LLFrameStats::STATE_SORT); - gPipeline.sAllowRebuildPriorityGroup = TRUE ; gPipeline.stateSort(*LLViewerCamera::getInstance(), result); stop_glerror(); @@ -904,6 +903,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot, boo for (U32 i = 0; i < 16; i++) { gGLLastModelView[i] = gGLModelView[i]; + gGLLastProjection[i] = gGLProjection[i]; } stop_glerror(); } @@ -915,12 +915,29 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot, boo if (LLPipeline::sRenderDeferred && !LLPipeline::sUnderWaterRender) { gPipeline.mDeferredScreen.flush(); + if(LLRenderTarget::sUseFBO) + { + LLRenderTarget::copyContentsToFramebuffer(gPipeline.mDeferredScreen, 0, 0, gPipeline.mDeferredScreen.getWidth(), + gPipeline.mDeferredScreen.getHeight(), 0, 0, + gPipeline.mDeferredScreen.getWidth(), + gPipeline.mDeferredScreen.getHeight(), + GL_DEPTH_BUFFER_BIT, GL_NEAREST); + } } else if(!tiling) { gPipeline.mScreen.flush(); + if(LLRenderTarget::sUseFBO) + { + LLRenderTarget::copyContentsToFramebuffer(gPipeline.mScreen, 0, 0, gPipeline.mScreen.getWidth(), + gPipeline.mScreen.getHeight(), 0, 0, + gPipeline.mScreen.getWidth(), + gPipeline.mScreen.getHeight(), + GL_DEPTH_BUFFER_BIT, GL_NEAREST); + } } } + //gGL.flush(); if (LLPipeline::sRenderDeferred && !LLPipeline::sUnderWaterRender) { @@ -936,9 +953,11 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot, boo render_ui(); } - gPipeline.rebuildGroups(); LLSpatialGroup::sNoDelete = FALSE; + gPipeline.clearReferences(); + + gPipeline.rebuildGroups(); } LLAppViewer::instance()->pingMainloopTimeout("Display:FrameStats"); @@ -1061,7 +1080,7 @@ void render_hud_attachments() glh_set_current_modelview(current_mod); } -BOOL setup_hud_matrices() +LLRect get_whole_screen_region() { LLRect whole_screen = gViewerWindow->getVirtualWindowRect(); @@ -1078,11 +1097,10 @@ BOOL setup_hud_matrices() whole_screen.setLeftTopAndSize(tile_x * tile_width, gViewerWindow->getWindowHeight() - (tile_y * tile_height), tile_width, tile_height); } - - return setup_hud_matrices(whole_screen); + return whole_screen; } -BOOL setup_hud_matrices(const LLRect& screen_region) +bool get_hud_matrices(const LLRect& screen_region, glh::matrix4f &proj, glh::matrix4f &model) { LLVOAvatar* my_avatarp = gAgent.getAvatarObject(); if (my_avatarp && my_avatarp->hasHUDAttachment()) @@ -1091,11 +1109,10 @@ BOOL setup_hud_matrices(const LLRect& screen_region) LLBBox hud_bbox = my_avatarp->getHUDBBox(); // set up transform to keep HUD objects in front of camera - glMatrixMode(GL_PROJECTION); F32 hud_depth = llmax(1.f, hud_bbox.getExtentLocal().mV[VX] * 1.1f); - glh::matrix4f proj = gl_ortho(-0.5f * LLViewerCamera::getInstance()->getAspect(), 0.5f * LLViewerCamera::getInstance()->getAspect(), -0.5f, 0.5f, 0.f, hud_depth); + proj = gl_ortho(-0.5f * LLViewerCamera::getInstance()->getAspect(), 0.5f * LLViewerCamera::getInstance()->getAspect(), -0.5f, 0.5f, 0.f, hud_depth); proj.element(2,2) = -0.01f; - + F32 aspect_ratio = LLViewerCamera::getInstance()->getAspect(); glh::matrix4f mat; @@ -1105,22 +1122,16 @@ BOOL setup_hud_matrices(const LLRect& screen_region) mat.set_translate( glh::vec3f(clamp_rescale((F32)screen_region.getCenterX(), 0.f, (F32)gViewerWindow->getWindowWidth(), 0.5f * scale_x * aspect_ratio, -0.5f * scale_x * aspect_ratio), clamp_rescale((F32)screen_region.getCenterY(), 0.f, (F32)gViewerWindow->getWindowHeight(), 0.5f * scale_y, -0.5f * scale_y), - 0.f)); + 0.f)); proj *= mat; - - glLoadMatrixf(proj.m); - glh_set_current_projection(proj); - - glMatrixMode(GL_MODELVIEW); - glh::matrix4f model((GLfloat*) OGL_TO_CFR_ROTATION); + + glh::matrix4f tmp_model((GLfloat*) OGL_TO_CFR_ROTATION); mat.set_scale(glh::vec3f(zoom_level, zoom_level, zoom_level)); mat.set_translate(glh::vec3f(-hud_bbox.getCenterLocal().mV[VX] + (hud_depth * 0.5f), 0.f, 0.f)); - - model *= mat; - glLoadMatrixf(model.m); - glh_set_current_modelview(model); - + + tmp_model *= mat; + model = tmp_model; return TRUE; } else @@ -1129,15 +1140,46 @@ BOOL setup_hud_matrices(const LLRect& screen_region) } } +bool get_hud_matrices(glh::matrix4f &proj, glh::matrix4f &model) +{ + LLRect whole_screen = get_whole_screen_region(); + return get_hud_matrices(whole_screen, proj, model); +} +BOOL setup_hud_matrices() +{ + LLRect whole_screen = get_whole_screen_region(); + return setup_hud_matrices(whole_screen); +} + +BOOL setup_hud_matrices(const LLRect& screen_region) +{ + glh::matrix4f proj, model; + bool result = get_hud_matrices(screen_region, proj, model); + if (!result) return result; + + // set up transform to keep HUD objects in front of camera + glMatrixMode(GL_PROJECTION); + glLoadMatrixf(proj.m); + glh_set_current_projection(proj); + + glMatrixMode(GL_MODELVIEW); + glLoadMatrixf(model.m); + glh_set_current_modelview(model); + return TRUE; +} void render_ui(F32 zoom_factor, int subfield, bool tiling) { LLGLState::checkStates(); - glPushMatrix(); - glLoadMatrixd(gGLLastModelView); glh::matrix4f saved_view = glh_get_current_modelview(); - glh_set_current_modelview(glh_copy_matrix(gGLLastModelView)); + + if (!gSnapshot) + { + glPushMatrix(); + glLoadMatrixd(gGLLastModelView); + glh_set_current_modelview(glh_copy_matrix(gGLLastModelView)); + } { BOOL to_texture = gPipeline.canUseVertexShaders() && @@ -1195,8 +1237,11 @@ void render_ui(F32 zoom_factor, int subfield, bool tiling) LLVertexBuffer::unbind(); } - glh_set_current_modelview(saved_view); - glPopMatrix(); + if (!gSnapshot) + { + glh_set_current_modelview(saved_view); + glPopMatrix(); + } if (gDisplaySwapBuffers) { @@ -1338,7 +1383,7 @@ void render_ui_2d() // render outline for HUD if (gAgent.getAvatarObject() && gAgent.mHUDCurZoom < 0.98f) { - glPushMatrix(); + gGL.pushMatrix(); S32 half_width = (gViewerWindow->getWindowWidth() / 2); S32 half_height = (gViewerWindow->getWindowHeight() / 2); glScalef(LLUI::sGLScaleFactor.mV[0], LLUI::sGLScaleFactor.mV[1], 1.f); @@ -1347,7 +1392,7 @@ void render_ui_2d() glScalef(zoom,zoom,1.f); gGL.color4fv(LLColor4::white.mV); gl_rect_2d(-half_width, half_height, half_width, -half_height, FALSE); - glPopMatrix(); + gGL.popMatrix(); stop_glerror(); } gViewerWindow->draw(); diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index fd779746e..e154234b1 100644 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -273,7 +273,6 @@ void LLViewerInventoryItem::setTransactionID(const LLTransactionID& transaction_ // virtual void LLViewerInventoryItem::packMessage(LLMessageSystem* msg) const { - LL_INFOS("Inventory") << " UDP Rez/UpdateObject of UUID " << mUUID << " parent = " << mParentUUID << " type= " << mType << " transaction= "<< mTransactionID << LL_ENDL; // OGPX msg->addUUIDFast(_PREHASH_ItemID, mUUID); msg->addUUIDFast(_PREHASH_FolderID, mParentUUID); mPermissions.packMessage(msg); @@ -503,11 +502,20 @@ bool LLViewerInventoryCategory::fetchDescendents() // This comes from LLInventoryFilter from llfolderview.h U32 sort_order = gSavedSettings.getU32("InventorySortOrder") & 0x1; - std::string url = gAgent.getCapability("agent/inventory"); // OGPX : was WebFetchInventoryDescendents - if (url.empty()) //OGPX : agent/inventory Capability not found on agent domain. See if the region has one. + // *NOTE: For bug EXT-2879, originally commented out + // gAgent.getRegion()->getCapability in order to use the old + // message-based system. This has been uncommented now that + // AIS folks are aware of the issue and have a fix in process. + // see ticket for details. + + std::string url; + if (gAgent.getRegion()) { - llinfos << " agent/inventory not on AD, checking fallback to region " << llendl; //OGPX - url = gAgent.getRegion()->getCapability("WebFetchInventoryDescendents"); + url = gAgent.getRegion()->getCapability("FetchInventoryDescendents"); + } + else + { + llwarns << "agent region is null" << llendl; } if (!url.empty()) //Capability found. Build up LLSD and use it. { @@ -515,7 +523,7 @@ bool LLViewerInventoryCategory::fetchDescendents() } else { //Deprecated, but if we don't have a capability, use the old system. - llinfos << "WebFetchInventoryDescendents or agent/inventory capability not found. Using deprecated UDP message." << llendl; + llinfos << "FetchInventoryDescendents capability not found. Using deprecated UDP message." << llendl; LLMessageSystem* msg = gMessageSystem; msg->newMessage("FetchInventoryDescendents"); msg->nextBlock("AgentData"); diff --git a/indra/newview/llviewerjointattachment.h b/indra/newview/llviewerjointattachment.h index 269f7158b..7ca508a3c 100644 --- a/indra/newview/llviewerjointattachment.h +++ b/indra/newview/llviewerjointattachment.h @@ -71,7 +71,7 @@ public: void setPieSlice(S32 pie_slice) { mPieSlice = pie_slice; } void setVisibleInFirstPerson(BOOL visibility) { mVisibleInFirst = visibility; } - BOOL getVisibleInFirstPerson() { return mVisibleInFirst; } + BOOL getVisibleInFirstPerson() const { return mVisibleInFirst; } void setGroup(S32 group) { mGroup = group; } void setOriginalPosition(LLVector3 &position); void setAttachmentVisibility(BOOL visible); diff --git a/indra/newview/llviewerjointmesh.cpp b/indra/newview/llviewerjointmesh.cpp index 055e488ff..926a9f9c7 100644 --- a/indra/newview/llviewerjointmesh.cpp +++ b/indra/newview/llviewerjointmesh.cpp @@ -509,7 +509,7 @@ int compare_int(const void *a, const void *b) U32 LLViewerJointMesh::drawShape( F32 pixelArea, BOOL first_pass, BOOL is_dummy) { if (!mValid || !mMesh || !mFace || !mVisible || - mFace->mVertexBuffer.isNull() || + !mFace->getVertexBuffer() || mMesh->getNumFaces() == 0) { return 0; @@ -599,7 +599,7 @@ U32 LLViewerJointMesh::drawShape( F32 pixelArea, BOOL first_pass, BOOL is_dummy) } } - mFace->mVertexBuffer->setBuffer(sRenderMask); + mFace->getVertexBuffer()->setBuffer(sRenderMask); U32 start = mMesh->mFaceVertexOffset; U32 end = start + mMesh->mFaceVertexCount - 1; @@ -616,14 +616,14 @@ U32 LLViewerJointMesh::drawShape( F32 pixelArea, BOOL first_pass, BOOL is_dummy) } } - mFace->mVertexBuffer->drawRange(LLRender::TRIANGLES, start, end, count, offset); + mFace->getVertexBuffer()->drawRange(LLRender::TRIANGLES, start, end, count, offset); } else { glPushMatrix(); LLMatrix4 jointToWorld = getWorldMatrix(); glMultMatrixf((GLfloat*)jointToWorld.mMatrix); - mFace->mVertexBuffer->drawRange(LLRender::TRIANGLES, start, end, count, offset); + mFace->getVertexBuffer()->drawRange(LLRender::TRIANGLES, start, end, count, offset); glPopMatrix(); } gPipeline.addTrianglesDrawn(count/3); @@ -672,7 +672,7 @@ void LLViewerJointMesh::updateFaceData(LLFace *face, F32 pixel_area, BOOL damp_w { mFace = face; - if (mFace->mVertexBuffer.isNull()) + if (!mFace->getVertexBuffer()) { return; } @@ -692,7 +692,7 @@ void LLViewerJointMesh::updateFaceData(LLFace *face, F32 pixel_area, BOOL damp_w stop_glerror(); face->getGeometryAvatar(verticesp, normalsp, tex_coordsp, vertex_weightsp, clothing_weightsp); stop_glerror(); - face->mVertexBuffer->getIndexStrider(indicesp); + face->getVertexBuffer()->getIndexStrider(indicesp); stop_glerror(); verticesp += mMesh->mFaceVertexOffset; @@ -809,7 +809,7 @@ void LLViewerJointMesh::updateGeometryOriginal(LLFace *mFace, LLPolyMesh *mMesh) LLStrider o_normals; //get vertex and normal striders - LLVertexBuffer *buffer = mFace->mVertexBuffer; + LLVertexBuffer *buffer = mFace->getVertexBuffer(); buffer->getVertexStrider(o_vertices, 0); buffer->getNormalStrider(o_normals, 0); @@ -966,7 +966,7 @@ void LLViewerJointMesh::updateJointGeometry() && mMesh && mFace && mMesh->hasWeights() - && mFace->mVertexBuffer.notNull() + && mFace->getVertexBuffer() && LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_AVATAR) == 0)) { return; diff --git a/indra/newview/llviewerjointmesh_sse.cpp b/indra/newview/llviewerjointmesh_sse.cpp index f4056e1af..2f2635246 100644 --- a/indra/newview/llviewerjointmesh_sse.cpp +++ b/indra/newview/llviewerjointmesh_sse.cpp @@ -89,7 +89,7 @@ void LLViewerJointMesh::updateGeometrySSE(LLFace *face, LLPolyMesh *mesh) LLStrider o_vertices; LLStrider o_normals; - LLVertexBuffer *buffer = face->mVertexBuffer; + LLVertexBuffer *buffer = face->getVertexBuffer(); buffer->getVertexStrider(o_vertices, mesh->mFaceVertexOffset); buffer->getNormalStrider(o_normals, mesh->mFaceVertexOffset); diff --git a/indra/newview/llviewerjointmesh_sse2.cpp b/indra/newview/llviewerjointmesh_sse2.cpp index ac9d18778..bfd8bb69b 100644 --- a/indra/newview/llviewerjointmesh_sse2.cpp +++ b/indra/newview/llviewerjointmesh_sse2.cpp @@ -96,7 +96,7 @@ void LLViewerJointMesh::updateGeometrySSE2(LLFace *face, LLPolyMesh *mesh) LLStrider o_vertices; LLStrider o_normals; - LLVertexBuffer *buffer = face->mVertexBuffer; + LLVertexBuffer *buffer = face->getVertexBuffer(); buffer->getVertexStrider(o_vertices, mesh->mFaceVertexOffset); buffer->getNormalStrider(o_normals, mesh->mFaceVertexOffset); diff --git a/indra/newview/llviewerjointmesh_vec.cpp b/indra/newview/llviewerjointmesh_vec.cpp index 8fb9d1cf6..91b97b07d 100644 --- a/indra/newview/llviewerjointmesh_vec.cpp +++ b/indra/newview/llviewerjointmesh_vec.cpp @@ -79,7 +79,7 @@ void LLViewerJointMesh::updateGeometryVectorized(LLFace *face, LLPolyMesh *mesh) LLStrider o_vertices; LLStrider o_normals; - LLVertexBuffer *buffer = face->mVertexBuffer; + LLVertexBuffer *buffer = face->getVertexBuffer(); buffer->getVertexStrider(o_vertices, mesh->mFaceVertexOffset); buffer->getNormalStrider(o_normals, mesh->mFaceVertexOffset); diff --git a/indra/newview/llviewerkeyboard.cpp b/indra/newview/llviewerkeyboard.cpp index 65a3b2a9b..67df36631 100644 --- a/indra/newview/llviewerkeyboard.cpp +++ b/indra/newview/llviewerkeyboard.cpp @@ -842,7 +842,7 @@ EKeyboardMode LLViewerKeyboard::getMode() { return MODE_EDIT_AVATAR; } - else if (gAgent.getAvatarObject() && gAgent.getAvatarObject()->mIsSitting) + else if (gAgent.getAvatarObject() && gAgent.getAvatarObject()->isSitting()) { return MODE_SITTING; } diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index dbb83b1ee..0beed949a 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -47,84 +47,12 @@ #include "lluuid.h" #include "llkeyboard.h" - // Merov: Temporary definitions while porting the new viewer media code to Snowglobe const int LEFT_BUTTON = 0; const int RIGHT_BUTTON = 1; -// Move this to its own file. - -LLViewerMediaEventEmitter::~LLViewerMediaEventEmitter() -{ - observerListType::iterator iter = mObservers.begin(); - - while( iter != mObservers.end() ) - { - LLViewerMediaObserver *self = *iter; - iter++; - remObserver(self); - } -} - /////////////////////////////////////////////////////////////////////////////// -// -bool LLViewerMediaEventEmitter::addObserver( LLViewerMediaObserver* observer ) -{ - if ( ! observer ) - return false; - - if ( std::find( mObservers.begin(), mObservers.end(), observer ) != mObservers.end() ) - return false; - - mObservers.push_back( observer ); - observer->mEmitters.push_back( this ); - - return true; -} - -/////////////////////////////////////////////////////////////////////////////// -// -bool LLViewerMediaEventEmitter::remObserver( LLViewerMediaObserver* observer ) -{ - if ( ! observer ) - return false; - - mObservers.remove( observer ); - observer->mEmitters.remove(this); - - return true; -} - -/////////////////////////////////////////////////////////////////////////////// -// -void LLViewerMediaEventEmitter::emitEvent( LLPluginClassMedia* media, LLPluginClassMediaOwner::EMediaEvent event ) -{ - observerListType::iterator iter = mObservers.begin(); - - while( iter != mObservers.end() ) - { - LLViewerMediaObserver *self = *iter; - ++iter; - self->handleMediaEvent( media, event ); - } -} - -// Move this to its own file. -LLViewerMediaObserver::~LLViewerMediaObserver() -{ - std::list::iterator iter = mEmitters.begin(); - - while( iter != mEmitters.end() ) - { - LLViewerMediaEventEmitter *self = *iter; - iter++; - self->remObserver( this ); - } -} - - -// Move this to its own file. -// helper class that tries to download a URL from a web site and calls a method +// Helper class that tries to download a URL from a web site and calls a method // on the Panel Land Media and to discover the MIME type class LLMimeDiscoveryResponder : public LLHTTPClient::Responder { @@ -279,9 +207,10 @@ void LLViewerMedia::updateBrowserUserAgent() for(; iter != end; iter++) { LLViewerMediaImpl* pimpl = *iter; - if(pimpl->mMediaSource && pimpl->mMediaSource->pluginSupportsMediaBrowser()) + LLPluginClassMedia* plugin = pimpl->getMediaPlugin(); + if(plugin && plugin->pluginSupportsMediaBrowser()) { - pimpl->mMediaSource->setBrowserUserAgent(user_agent); + plugin->setBrowserUserAgent(user_agent); } } @@ -366,7 +295,6 @@ LLViewerMediaImpl::LLViewerMediaImpl(const std::string& media_url, U8 media_loop, const std::string& mime_type) : - mMediaSource( NULL ), mMovieImageHasMips(false), mTextureId(texture_id), mMediaWidth(media_width), @@ -399,7 +327,7 @@ LLViewerMediaImpl::~LLViewerMediaImpl() ////////////////////////////////////////////////////////////////////////////////////////// bool LLViewerMediaImpl::initializeMedia(const std::string& mime_type) { - if((mMediaSource == NULL) || (mMimeType != mime_type)) + if((mPluginBase == NULL) || (mMimeType != mime_type)) { if(! initializePlugin(mime_type)) { @@ -413,7 +341,7 @@ bool LLViewerMediaImpl::initializeMedia(const std::string& mime_type) } // play(); - return (mMediaSource != NULL); + return (mPluginBase != NULL); } ////////////////////////////////////////////////////////////////////////////////////////// @@ -434,14 +362,13 @@ void LLViewerMediaImpl::createMediaSource() void LLViewerMediaImpl::destroyMediaSource() { mNeedsNewTexture = true; - if(! mMediaSource) + if (!mPluginBase) { return; } // Restore the texture updateMovieImage(LLUUID::null, false); - delete mMediaSource; - mMediaSource = NULL; + destroyPlugin(); } ////////////////////////////////////////////////////////////////////////////////////////// @@ -472,10 +399,12 @@ LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_ if(LLFile::stat(launcher_name, &s)) { LL_WARNS("Media") << "Couldn't find launcher at " << launcher_name << LL_ENDL; + llassert(false); // Fail in debugging mode. } else if(LLFile::stat(plugin_name, &s)) { LL_WARNS("Media") << "Couldn't find plugin at " << plugin_name << LL_ENDL; + llassert(false); // Fail in debugging mode. } else { @@ -514,16 +443,17 @@ LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_ LLNotifications::instance().add("NoPlugin", args); return NULL; -} +} ////////////////////////////////////////////////////////////////////////////////////////// bool LLViewerMediaImpl::initializePlugin(const std::string& media_type) { - if(mMediaSource) + LLPluginClassMedia* plugin = getMediaPlugin(); + if (plugin) { // Save the previous media source's last set size before destroying it. - mMediaWidth = mMediaSource->getSetWidth(); - mMediaHeight = mMediaSource->getSetHeight(); + mMediaWidth = plugin->getSetWidth(); + mMediaHeight = plugin->getSetHeight(); } // Always delete the old media impl first. @@ -541,7 +471,7 @@ bool LLViewerMediaImpl::initializePlugin(const std::string& media_type) media_source->setAutoScale(mMediaAutoScale); media_source->setBrowserUserAgent(LLViewerMedia::getCurrentUserAgent()); - mMediaSource = media_source; + mPluginBase = media_source; return true; } @@ -550,34 +480,38 @@ bool LLViewerMediaImpl::initializePlugin(const std::string& media_type) void LLViewerMediaImpl::setSize(int width, int height) { + LLPluginClassMedia* plugin = getMediaPlugin(); mMediaWidth = width; mMediaHeight = height; - if(mMediaSource) + if (plugin) { - mMediaSource->setSize(width, height); + plugin->setSize(width, height); } } ////////////////////////////////////////////////////////////////////////////////////////// void LLViewerMediaImpl::play() { + LLPluginClassMedia* plugin = getMediaPlugin(); + // first stop any previously playing media // stop(); - // mMediaSource->addObserver( this ); - if(mMediaSource == NULL) + // plugin->addObserver( this ); + if (!plugin) { if(!initializePlugin(mMimeType)) { // Plugin failed initialization... should assert or something return; } + plugin = getMediaPlugin(); } // updateMovieImage(mTextureId, true); - mMediaSource->loadURI( mMediaURL ); - if(/*mMediaSource->pluginSupportsMediaTime()*/ true) + plugin->loadURI( mMediaURL ); + if(/*plugin->pluginSupportsMediaTime()*/ true) { start(); } @@ -586,9 +520,10 @@ void LLViewerMediaImpl::play() ////////////////////////////////////////////////////////////////////////////////////////// void LLViewerMediaImpl::stop() { - if(mMediaSource) + LLPluginClassMedia* plugin = getMediaPlugin(); + if (plugin) { - mMediaSource->stop(); + plugin->stop(); // destroyMediaSource(); } } @@ -596,52 +531,57 @@ void LLViewerMediaImpl::stop() ////////////////////////////////////////////////////////////////////////////////////////// void LLViewerMediaImpl::pause() { - if(mMediaSource) + LLPluginClassMedia* plugin = getMediaPlugin(); + if (plugin) { - mMediaSource->pause(); + plugin->pause(); } } ////////////////////////////////////////////////////////////////////////////////////////// void LLViewerMediaImpl::start() { - if(mMediaSource) + LLPluginClassMedia* plugin = getMediaPlugin(); + if (plugin) { - mMediaSource->start(); + plugin->start(); } } ////////////////////////////////////////////////////////////////////////////////////////// void LLViewerMediaImpl::seek(F32 time) { - if(mMediaSource) + LLPluginClassMedia* plugin = getMediaPlugin(); + if (plugin) { - mMediaSource->seek(time); + plugin->seek(time); } } ////////////////////////////////////////////////////////////////////////////////////////// void LLViewerMediaImpl::setVolume(F32 volume) { - if(mMediaSource) + LLPluginClassMedia* plugin = getMediaPlugin(); + if (plugin) { - mMediaSource->setVolume(volume); + plugin->setVolume(volume); } } ////////////////////////////////////////////////////////////////////////////////////////// void LLViewerMediaImpl::focus(bool focus) { - if (mMediaSource) + LLPluginClassMedia* plugin = getMediaPlugin(); + if (plugin) { // call focus just for the hell of it, even though this apopears to be a nop - mMediaSource->focus(focus); + plugin->focus(focus); if (focus) { // spoof a mouse click to *actually* pass focus // Don't do this anymore -- it actually clicks through now. -// mMediaSource->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_DOWN, 1, 1, 0); -// mMediaSource->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_UP, 1, 1, 0); +// plugin->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_DOWN, 1, 1, 0); +// plugin->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_UP, 1, 1, 0); } } } @@ -649,57 +589,62 @@ void LLViewerMediaImpl::focus(bool focus) ////////////////////////////////////////////////////////////////////////////////////////// void LLViewerMediaImpl::mouseDown(S32 x, S32 y) { + LLPluginClassMedia* plugin = getMediaPlugin(); scaleMouse(&x, &y); mLastMouseX = x; mLastMouseY = y; - if (mMediaSource) + if (plugin) { - mMediaSource->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_DOWN, LEFT_BUTTON, x, y, 0); + plugin->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_DOWN, LEFT_BUTTON, x, y, 0); } } ////////////////////////////////////////////////////////////////////////////////////////// void LLViewerMediaImpl::mouseUp(S32 x, S32 y) { + LLPluginClassMedia* plugin = getMediaPlugin(); scaleMouse(&x, &y); mLastMouseX = x; mLastMouseY = y; - if (mMediaSource) + if (plugin) { - mMediaSource->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_UP, LEFT_BUTTON, x, y, 0); + plugin->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_UP, LEFT_BUTTON, x, y, 0); } } ////////////////////////////////////////////////////////////////////////////////////////// void LLViewerMediaImpl::mouseMove(S32 x, S32 y) { + LLPluginClassMedia* plugin = getMediaPlugin(); scaleMouse(&x, &y); mLastMouseX = x; mLastMouseY = y; - if (mMediaSource) + if (plugin) { - mMediaSource->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_MOVE, LEFT_BUTTON, x, y, 0); + plugin->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_MOVE, LEFT_BUTTON, x, y, 0); } } ////////////////////////////////////////////////////////////////////////////////////////// void LLViewerMediaImpl::mouseLeftDoubleClick(S32 x, S32 y) { + LLPluginClassMedia* plugin = getMediaPlugin(); scaleMouse(&x, &y); mLastMouseX = x; mLastMouseY = y; - if (mMediaSource) + if (plugin) { - mMediaSource->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_DOUBLE_CLICK, LEFT_BUTTON, x, y, 0); + plugin->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_DOUBLE_CLICK, LEFT_BUTTON, x, y, 0); } } ////////////////////////////////////////////////////////////////////////////////////////// void LLViewerMediaImpl::onMouseCaptureLost() { - if (mMediaSource) + LLPluginClassMedia* plugin = getMediaPlugin(); + if (plugin) { - mMediaSource->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_UP, LEFT_BUTTON, mLastMouseX, mLastMouseY, 0); + plugin->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_UP, LEFT_BUTTON, mLastMouseX, mLastMouseY, 0); } } @@ -720,15 +665,17 @@ BOOL LLViewerMediaImpl::handleMouseUp(S32 x, S32 y, MASK mask) ////////////////////////////////////////////////////////////////////////////////////////// void LLViewerMediaImpl::navigateHome() { - if(mMediaSource) + LLPluginClassMedia* plugin = getMediaPlugin(); + if (plugin) { - mMediaSource->loadURI( mHomeURL ); + plugin->loadURI( mHomeURL ); } } ////////////////////////////////////////////////////////////////////////////////////////// void LLViewerMediaImpl::navigateTo(const std::string& url, const std::string& mime_type, bool rediscover_type) { + LLPluginClassMedia* plugin = getMediaPlugin(); if(rediscover_type) { @@ -745,7 +692,7 @@ void LLViewerMediaImpl::navigateTo(const std::string& url, const std::string& mi // We use "data" internally for a text/html url for loading the login screen if(initializeMedia("text/html")) { - mMediaSource->loadURI( url ); + plugin->loadURI( url ); } } else @@ -753,17 +700,17 @@ void LLViewerMediaImpl::navigateTo(const std::string& url, const std::string& mi // This catches 'rtsp://' urls if(initializeMedia(scheme)) { - mMediaSource->loadURI( url ); + plugin->loadURI( url ); } } } - else if (mMediaSource) + else if (plugin) { - mMediaSource->loadURI( url ); + plugin->loadURI( url ); } - else if(initializeMedia(mime_type) && mMediaSource) + else if(initializeMedia(mime_type) && (plugin = getMediaPlugin())) { - mMediaSource->loadURI( url ); + plugin->loadURI( url ); } else { @@ -777,9 +724,10 @@ void LLViewerMediaImpl::navigateTo(const std::string& url, const std::string& mi ////////////////////////////////////////////////////////////////////////////////////////// void LLViewerMediaImpl::navigateStop() { - if(mMediaSource) + LLPluginClassMedia* plugin = getMediaPlugin(); + if (plugin) { - mMediaSource->browse_stop(); + plugin->browse_stop(); } } @@ -788,8 +736,9 @@ void LLViewerMediaImpl::navigateStop() bool LLViewerMediaImpl::handleKeyHere(KEY key, MASK mask) { bool result = false; + LLPluginClassMedia* plugin = getMediaPlugin(); - if (mMediaSource) + if (plugin) { // FIXME: THIS IS SO WRONG. // Menu keys should be handled by the menu system and not passed to UI elements, but this is how LLTextEditor and LLLineEditor do it... @@ -797,19 +746,19 @@ bool LLViewerMediaImpl::handleKeyHere(KEY key, MASK mask) { if( 'C' == key ) { - mMediaSource->copy(); + plugin->copy(); result = true; } else if( 'V' == key ) { - mMediaSource->paste(); + plugin->paste(); result = true; } else if( 'X' == key ) { - mMediaSource->cut(); + plugin->cut(); result = true; } } @@ -819,9 +768,9 @@ bool LLViewerMediaImpl::handleKeyHere(KEY key, MASK mask) LLSD native_key_data = LLSD::emptyMap(); - result = mMediaSource->keyEvent(LLPluginClassMedia::KEY_EVENT_DOWN ,key, mask, native_key_data); + result = plugin->keyEvent(LLPluginClassMedia::KEY_EVENT_DOWN ,key, mask, native_key_data); // Since the viewer internal event dispatching doesn't give us key-up events, simulate one here. - (void)mMediaSource->keyEvent(LLPluginClassMedia::KEY_EVENT_UP ,key, mask, native_key_data); + (void)plugin->keyEvent(LLPluginClassMedia::KEY_EVENT_UP ,key, mask, native_key_data); } } @@ -832,8 +781,9 @@ bool LLViewerMediaImpl::handleKeyHere(KEY key, MASK mask) bool LLViewerMediaImpl::handleUnicodeCharHere(llwchar uni_char) { bool result = false; + LLPluginClassMedia* plugin = getMediaPlugin(); - if (mMediaSource) + if (plugin) { // only accept 'printable' characters, sigh... if (uni_char >= 32 // discard 'control' characters @@ -841,7 +791,7 @@ bool LLViewerMediaImpl::handleUnicodeCharHere(llwchar uni_char) { LLSD native_key_data = LLSD::emptyMap(); - mMediaSource->textInput(wstring_to_utf8str(LLWString(1, uni_char)), gKeyboard->currentMask(FALSE), native_key_data); + plugin->textInput(wstring_to_utf8str(LLWString(1, uni_char)), gKeyboard->currentMask(FALSE), native_key_data); } } @@ -851,10 +801,11 @@ bool LLViewerMediaImpl::handleUnicodeCharHere(llwchar uni_char) ////////////////////////////////////////////////////////////////////////////////////////// bool LLViewerMediaImpl::canNavigateForward() { - BOOL result = FALSE; - if (mMediaSource) + bool result = false; + LLPluginClassMedia* plugin = getMediaPlugin(); + if (plugin) { - result = mMediaSource->getHistoryForwardAvailable(); + result = plugin->getHistoryForwardAvailable(); } return result; } @@ -862,10 +813,11 @@ bool LLViewerMediaImpl::canNavigateForward() ////////////////////////////////////////////////////////////////////////////////////////// bool LLViewerMediaImpl::canNavigateBack() { - BOOL result = FALSE; - if (mMediaSource) + bool result = false; + LLPluginClassMedia* plugin = getMediaPlugin(); + if (plugin) { - result = mMediaSource->getHistoryBackAvailable(); + result = plugin->getHistoryBackAvailable(); } return result; } @@ -909,20 +861,21 @@ void LLViewerMediaImpl::updateMovieImage(const LLUUID& uuid, BOOL active) ////////////////////////////////////////////////////////////////////////////////////////// void LLViewerMediaImpl::update() { - if(mMediaSource == NULL) + LLPluginClassMedia* plugin = getMediaPlugin(); + if (!plugin) { return; } - mMediaSource->idle(); + plugin->idle(); - if(mMediaSource->isPluginExited()) + if (plugin->isPluginExited()) { destroyMediaSource(); return; } - if(!mMediaSource->textureValid()) + if (!plugin->textureValid()) { return; } @@ -937,7 +890,7 @@ void LLViewerMediaImpl::update() if(placeholder_image) { LLRect dirty_rect; - if(mMediaSource->getDirty(&dirty_rect)) + if (plugin->getDirty(&dirty_rect)) { // Constrain the dirty rect to be inside the texture S32 x_pos = llmax(dirty_rect.mLeft, 0); @@ -948,16 +901,16 @@ void LLViewerMediaImpl::update() if(width > 0 && height > 0) { - U8* data = mMediaSource->getBitsData(); + U8* data = plugin->getBitsData(); // Offset the pixels pointer to match x_pos and y_pos - data += ( x_pos * mMediaSource->getTextureDepth() * mMediaSource->getBitsWidth() ); - data += ( y_pos * mMediaSource->getTextureDepth() ); + data += ( x_pos * plugin->getTextureDepth() * plugin->getBitsWidth() ); + data += ( y_pos * plugin->getTextureDepth() ); placeholder_image->setSubImage( data, - mMediaSource->getBitsWidth(), - mMediaSource->getBitsHeight(), + plugin->getBitsWidth(), + plugin->getBitsHeight(), x_pos, y_pos, width, @@ -966,7 +919,7 @@ void LLViewerMediaImpl::update() } - mMediaSource->resetDirty(); + plugin->resetDirty(); } } } @@ -988,24 +941,25 @@ void LLViewerMediaImpl::updateImagesMediaStreams() } LLViewerMediaTexture* placeholder_image = (LLViewerMediaTexture*)LLViewerTextureManager::getFetchedTexture( mTextureId ); - + LLPluginClassMedia* plugin = getMediaPlugin(); + placeholder_image->getLastReferencedTimer()->reset(); if (mNeedsNewTexture || placeholder_image->getUseMipMaps() || ! placeholder_image->mIsMediaTexture - || (placeholder_image->getWidth() != mMediaSource->getTextureWidth()) - || (placeholder_image->getHeight() != mMediaSource->getTextureHeight()) - || (mTextureUsedWidth != mMediaSource->getWidth()) - || (mTextureUsedHeight != mMediaSource->getHeight()) + || (placeholder_image->getWidth() != plugin->getTextureWidth()) + || (placeholder_image->getHeight() != plugin->getTextureHeight()) + || (mTextureUsedWidth != plugin->getWidth()) + || (mTextureUsedHeight != plugin->getHeight()) ) { llinfos << "initializing media placeholder" << llendl; llinfos << "movie image id " << mTextureId << llendl; - int texture_width = mMediaSource->getTextureWidth(); - int texture_height = mMediaSource->getTextureHeight(); - int texture_depth = mMediaSource->getTextureDepth(); + int texture_width = plugin->getTextureWidth(); + int texture_height = plugin->getTextureHeight(); + int texture_depth = plugin->getTextureDepth(); // MEDIAOPT: check to see if size actually changed before doing work placeholder_image->destroyGLTexture(); @@ -1019,10 +973,10 @@ void LLViewerMediaImpl::updateImagesMediaStreams() int discard_level = 0; // ask media source for correct GL image format constants - placeholder_image->setExplicitFormat(mMediaSource->getTextureFormatInternal(), - mMediaSource->getTextureFormatPrimary(), - mMediaSource->getTextureFormatType(), - mMediaSource->getTextureFormatSwapBytes()); + placeholder_image->setExplicitFormat(plugin->getTextureFormatInternal(), + plugin->getTextureFormatPrimary(), + plugin->getTextureFormatType(), + plugin->getTextureFormatSwapBytes()); placeholder_image->createGLTexture(discard_level, raw); @@ -1035,8 +989,8 @@ void LLViewerMediaImpl::updateImagesMediaStreams() // If the amount of the texture being drawn by the media goes down in either width or height, // recreate the texture to avoid leaving parts of the old image behind. - mTextureUsedWidth = mMediaSource->getWidth(); - mTextureUsedHeight = mMediaSource->getHeight(); + mTextureUsedWidth = plugin->getWidth(); + mTextureUsedHeight = plugin->getHeight(); } return placeholder_image; @@ -1052,24 +1006,25 @@ LLUUID LLViewerMediaImpl::getMediaTextureID() ////////////////////////////////////////////////////////////////////////////////////////// void LLViewerMediaImpl::setVisible(bool visible) { + LLPluginClassMedia* plugin = getMediaPlugin(); mVisible = visible; if(mVisible) { - if(mMediaSource && mMediaSource->isPluginExited()) + if(plugin && plugin->isPluginExited()) { destroyMediaSource(); } - if(!mMediaSource) + if(!plugin) { createMediaSource(); } } - if(mMediaSource) + if(plugin) { - mMediaSource->setPriority(mVisible?LLPluginClassMedia::PRIORITY_NORMAL:LLPluginClassMedia::PRIORITY_HIDDEN); + plugin->setPriority(mVisible?LLPluginClassBasic::PRIORITY_NORMAL:LLPluginClassBasic::PRIORITY_SLEEP); } } @@ -1082,10 +1037,11 @@ void LLViewerMediaImpl::mouseCapture() ////////////////////////////////////////////////////////////////////////////////////////// void LLViewerMediaImpl::getTextureSize(S32 *texture_width, S32 *texture_height) { - if(mMediaSource && mMediaSource->textureValid()) + LLPluginClassMedia* plugin = getMediaPlugin(); + if(plugin && plugin->textureValid()) { - S32 real_texture_width = mMediaSource->getBitsWidth(); - S32 real_texture_height = mMediaSource->getBitsHeight(); + S32 real_texture_width = plugin->getBitsWidth(); + S32 real_texture_height = plugin->getBitsHeight(); { // The "texture width" coming back from the plugin may not be a power of two (thanks to webkit). @@ -1126,10 +1082,11 @@ void LLViewerMediaImpl::scaleMouse(S32 *mouse_x, S32 *mouse_y) bool LLViewerMediaImpl::isMediaPlaying() { bool result = false; + LLPluginClassMedia* plugin = getMediaPlugin(); - if(mMediaSource) + if(plugin) { - EMediaStatus status = mMediaSource->getStatus(); + EMediaStatus status = plugin->getStatus(); if(status == MEDIA_PLAYING || status == MEDIA_LOADING) result = true; } @@ -1140,10 +1097,11 @@ bool LLViewerMediaImpl::isMediaPlaying() bool LLViewerMediaImpl::isMediaPaused() { bool result = false; + LLPluginClassMedia* plugin = getMediaPlugin(); - if(mMediaSource) + if(plugin) { - if(mMediaSource->getStatus() == MEDIA_PAUSED) + if(plugin->getStatus() == MEDIA_PAUSED) result = true; } @@ -1154,7 +1112,7 @@ bool LLViewerMediaImpl::isMediaPaused() // bool LLViewerMediaImpl::hasMedia() { - return mMediaSource != NULL; + return mPluginBase != NULL; } ////////////////////////////////////////////////////////////////////////////////////////// @@ -1181,8 +1139,9 @@ void LLViewerMediaImpl::handleMediaEvent(LLPluginClassMedia* self, LLPluginClass void LLViewerMediaImpl::cut() { - if (mMediaSource) - mMediaSource->cut(); + LLPluginClassMedia* plugin = getMediaPlugin(); + if (plugin) + plugin->cut(); } //////////////////////////////////////////////////////////////////////////////// @@ -1190,8 +1149,9 @@ LLViewerMediaImpl::cut() BOOL LLViewerMediaImpl::canCut() const { - if (mMediaSource) - return mMediaSource->canCut(); + LLPluginClassMedia* plugin = getMediaPlugin(); + if (plugin) + return plugin->canCut(); else return FALSE; } @@ -1201,8 +1161,9 @@ LLViewerMediaImpl::canCut() const void LLViewerMediaImpl::copy() { - if (mMediaSource) - mMediaSource->copy(); + LLPluginClassMedia* plugin = getMediaPlugin(); + if (plugin) + plugin->copy(); } //////////////////////////////////////////////////////////////////////////////// @@ -1210,8 +1171,9 @@ LLViewerMediaImpl::copy() BOOL LLViewerMediaImpl::canCopy() const { - if (mMediaSource) - return mMediaSource->canCopy(); + LLPluginClassMedia* plugin = getMediaPlugin(); + if (plugin) + return plugin->canCopy(); else return FALSE; } @@ -1221,8 +1183,9 @@ LLViewerMediaImpl::canCopy() const void LLViewerMediaImpl::paste() { - if (mMediaSource) - mMediaSource->paste(); + LLPluginClassMedia* plugin = getMediaPlugin(); + if (plugin) + plugin->paste(); } //////////////////////////////////////////////////////////////////////////////// @@ -1230,8 +1193,9 @@ LLViewerMediaImpl::paste() BOOL LLViewerMediaImpl::canPaste() const { - if (mMediaSource) - return mMediaSource->canPaste(); + LLPluginClassMedia* plugin = getMediaPlugin(); + if (plugin) + return plugin->canPaste(); else return FALSE; } diff --git a/indra/newview/llviewermedia.h b/indra/newview/llviewermedia.h index 1e9ef6c90..6b8bd2217 100644 --- a/indra/newview/llviewermedia.h +++ b/indra/newview/llviewermedia.h @@ -33,34 +33,17 @@ #ifndef LLVIEWERMEDIA_H #define LLVIEWERMEDIA_H +#include "llviewermediaeventemitter.h" +#include "llviewerpluginmanager.h" #include "llfocusmgr.h" - #include "llpanel.h" -#include "llpluginclassmediaowner.h" - -#include "llviewermediaobserver.h" class LLViewerMediaImpl; class LLUUID; -//class LLViewerMediaTexture; +class LLSD; class LLViewerTexture; typedef LLPointer viewer_media_t; -/////////////////////////////////////////////////////////////////////////////// -// -class LLViewerMediaEventEmitter -{ -public: - virtual ~LLViewerMediaEventEmitter(); - - bool addObserver( LLViewerMediaObserver* subject ); - bool remObserver( LLViewerMediaObserver* subject ); - void emitEvent(LLPluginClassMedia* self, LLPluginClassMediaOwner::EMediaEvent event); - -private: - typedef std::list< LLViewerMediaObserver* > observerListType; - observerListType mObservers; -}; class LLViewerMedia { @@ -93,7 +76,7 @@ class LLViewerMedia // Implementation functions not exported into header file class LLViewerMediaImpl - : public LLMouseHandler, public LLRefCount, public LLPluginClassMediaOwner, public LLViewerMediaEventEmitter, public LLEditMenuHandler + : public LLViewerPluginManager, public LLMouseHandler, public LLPluginClassMediaOwner, public LLViewerMediaEventEmitter, public LLEditMenuHandler { LOG_CLASS(LLViewerMediaImpl); public: @@ -112,9 +95,12 @@ public: void setMediaType(const std::string& media_type); bool initializeMedia(const std::string& mime_type); bool initializePlugin(const std::string& media_type); - LLPluginClassMedia* getMediaPlugin() { return mMediaSource; } + LLPluginClassMedia* getMediaPlugin() const { return (LLPluginClassMedia*)mPluginBase; } void setSize(int width, int height); + // Inherited from LLViewerPluginManager. + /*virtual*/ void update(); + void play(); void stop(); void pause(); @@ -141,7 +127,6 @@ public: void getTextureSize(S32 *texture_width, S32 *texture_height); void scaleMouse(S32 *mouse_x, S32 *mouse_y); - void update(); void updateMovieImage(const LLUUID& image_id, BOOL active); void updateImagesMediaStreams(); LLUUID getMediaTextureID(); @@ -201,7 +186,6 @@ public: public: // a single media url with some data and an impl. - LLPluginClassMedia* mMediaSource; LLUUID mTextureId; bool mMovieImageHasMips; std::string mMediaURL; @@ -219,7 +203,6 @@ public: bool mSuspendUpdates; bool mVisible; - private: /*LLViewerMediaTexture*/LLViewerTexture *updatePlaceholderImage(); }; diff --git a/indra/newview/llviewermediaeventemitter.cpp b/indra/newview/llviewermediaeventemitter.cpp new file mode 100644 index 000000000..39e0b2b52 --- /dev/null +++ b/indra/newview/llviewermediaeventemitter.cpp @@ -0,0 +1,85 @@ +/** + * @file llviewermediaeventemitter.cpp + * @brief Implementation of LLViewerMediaEventEmitter + * + * $LicenseInfo:firstyear=2007&license=viewergpl$ + * + * Copyright (c) 2007-2010, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" +#include "llviewermediaeventemitter.h" +#include "llviewermediaobserver.h" +#include + +LLViewerMediaEventEmitter::~LLViewerMediaEventEmitter() +{ + observerListType::iterator iter = mObservers.begin(); + + while (iter != mObservers.end()) + { + LLViewerMediaObserver* self = *iter; + ++iter; + remObserver(self); + } +} + +bool LLViewerMediaEventEmitter::addObserver(LLViewerMediaObserver* observer) +{ + if (!observer) + return false; + + if (std::find(mObservers.begin(), mObservers.end(), observer) != mObservers.end()) + return false; + + mObservers.push_back(observer); + observer->mEmitters.push_back(this); + + return true; +} + +bool LLViewerMediaEventEmitter::remObserver(LLViewerMediaObserver* observer) +{ + if (!observer) + return false; + + mObservers.remove(observer); + observer->mEmitters.remove(this); + + return true; +} + +void LLViewerMediaEventEmitter::emitEvent(LLPluginClassMedia* media, LLPluginClassMediaOwner::EMediaEvent event) +{ + observerListType::iterator iter = mObservers.begin(); + + while (iter != mObservers.end()) + { + LLViewerMediaObserver* self = *iter; + ++iter; + self->handleMediaEvent(media, event); + } +} diff --git a/indra/newview/llfloaterdickdongs.h b/indra/newview/llviewermediaeventemitter.h similarity index 59% rename from indra/newview/llfloaterdickdongs.h rename to indra/newview/llviewermediaeventemitter.h index fe4d7697d..17453a9e1 100644 --- a/indra/newview/llfloaterdickdongs.h +++ b/indra/newview/llviewermediaeventemitter.h @@ -1,11 +1,10 @@ -/** - * @file llfloaterbeacons.h - * @brief Front-end to LLPipeline controls for highlighting various kinds of objects. - * @author Coco +/** + * @file llviewermediaeventemitter.h + * @brief Helper class * - * $LicenseInfo:firstyear=2002&license=viewergpl$ + * $LicenseInfo:firstyear=2007&license=viewergpl$ * - * Copyright (c) 2002-2009, Linden Research, Inc. + * Copyright (c) 2007-2010, Linden Research, Inc. * * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab @@ -31,27 +30,27 @@ * $/LicenseInfo$ */ -#ifndef LL_LLFLOATERDICKDONGS_H -#define LL_LLFLOATERDICKDONGS_H +#ifndef LLVIEWERMEDIAEVENTEMITTER_H +#define LLVIEWERMEDIAEVENTEMITTER_H -#include "llfloater.h" +#include "llpluginclassmediaowner.h" +#include -class LLFloaterDickDongs : public LLFloater, public LLFloaterSingleton +class LLViewerMediaObserver; +class LLPluginClassMedia; + +class LLViewerMediaEventEmitter { - friend class LLUISingleton >; - public: - // /*virtual*/ BOOL postBuild(); - - // Needed to make the floater visibility toggle the beacons. - // Too bad we can't just add control_name="BeaconAlwaysOn" to the XML. - /*virtual*/ void open(); - /*virtual*/ void close(bool app_quitting); + virtual ~LLViewerMediaEventEmitter(); + + bool addObserver(LLViewerMediaObserver* subject); + bool remObserver(LLViewerMediaObserver* subject); + void emitEvent(LLPluginClassMedia* self, LLPluginClassMediaOwner::EMediaEvent event); private: - LLFloaterDickDongs(const LLSD& seed); - - //static void onClickUICheck(LLUICtrl *ctrl, void* data); + typedef std::list< LLViewerMediaObserver*> observerListType; + observerListType mObservers; }; -#endif +#endif // LLVIEWERMEDIAEVENTEMITTER_H diff --git a/indra/newview/llviewermediaobserver.cpp b/indra/newview/llviewermediaobserver.cpp new file mode 100644 index 000000000..6bed14311 --- /dev/null +++ b/indra/newview/llviewermediaobserver.cpp @@ -0,0 +1,47 @@ +/** + * @file llviewermediaobserver.cpp + * @brief Implementation of class LLViewerMediaObserver. + * + * $LicenseInfo:firstyear=2007&license=viewergpl$ + * + * Copyright (c) 2007-2010, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" +#include "llviewermediaeventemitter.h" +#include "llviewermediaobserver.h" + +LLViewerMediaObserver::~LLViewerMediaObserver() +{ + std::list::iterator iter = mEmitters.begin(); + + while (iter != mEmitters.end()) + { + LLViewerMediaEventEmitter* self = *iter; + ++iter; + self->remObserver(this); + } +} diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 7fde31b24..6599123bb 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -69,6 +69,7 @@ #include "lltimer.h" #include "llvfile.h" #include "llvolumemgr.h" +#include "statemachine/aifilepicker.h" // newview includes #include "llagent.h" @@ -110,7 +111,6 @@ #include "llfloaterchat.h" #include "llfloatercustomize.h" #include "llfloaterdaycycle.h" -//#include "llfloaterdickdongs.h" No need for the custom floater right now, I think. -HgB #include "llfloaterdirectory.h" #include "llfloatereditui.h" #include "llfloaterchatterbox.h" @@ -181,7 +181,7 @@ #include "llparcel.h" - +#include "llpolymesh.h" #include "llprimitive.h" #include "llresmgr.h" #include "llselectmgr.h" @@ -281,13 +281,15 @@ void handle_test_load_url(void*); // // Evil hackish imported globals // -extern BOOL gRenderLightGlows; -extern BOOL gRenderAvatar; -extern BOOL gHideSelectedObjects; +//extern BOOL gHideSelectedObjects; +//extern BOOL gAllowSelectAvatar; +extern BOOL gDebugClicks; +extern BOOL gDebugWindowProc; +extern BOOL gDebugTextEditorTips; +//extern BOOL gDebugSelectMgr; +extern BOOL gDebugAvatarRotation; extern BOOL gShowOverlayTitle; extern BOOL gOcclusionCull; -extern BOOL gAllowSelectAvatar; - // // Globals // @@ -428,13 +430,16 @@ void handle_area_search(void*); // for pose stand LLUUID current_pose = LLUUID::null; +bool on_pose_stand; void set_current_pose(std::string anim) { - if (current_pose == LLUUID::null) + if (!on_pose_stand) + { + on_pose_stand = true; gSavedSettings.setF32("AscentAvatarZModifier", gSavedSettings.getF32("AscentAvatarZModifier") + 7.5); + } - gAgent.sendAgentSetAppearance(); gAgent.sendAnimationRequest(current_pose, ANIM_REQUEST_STOP); current_pose.set(anim); gAgent.sendAnimationRequest(current_pose, ANIM_REQUEST_START); @@ -445,14 +450,18 @@ void handle_pose_stand(void*) } void handle_pose_stand_stop(void*) { - if (current_pose != LLUUID::null) + if (on_pose_stand) { gSavedSettings.setF32("AscentAvatarZModifier", gSavedSettings.getF32("AscentAvatarZModifier") - 7.5); - gAgent.sendAgentSetAppearance(); + on_pose_stand = false; gAgent.sendAnimationRequest(current_pose, ANIM_REQUEST_STOP); current_pose = LLUUID::null; } } +void cleanup_pose_stand(void) +{ + handle_pose_stand_stop(NULL); +} void handle_toggle_pose(void* userdata) { if(current_pose.isNull()) @@ -571,6 +580,13 @@ void handle_toggle_pg(void*); void handle_dump_attachments(void *); void handle_show_overlay_title(void*); void handle_dump_avatar_local_textures(void*); +void handle_meshes_and_morphs(void*); +void handle_mesh_save_llm(void* data); +void handle_mesh_save_current_obj(void*); +void handle_mesh_save_obj(void*); +void handle_mesh_load_obj(void*); +void handle_morph_save_obj(void*); +void handle_morph_load_obj(void*); void handle_debug_avatar_textures(void*); void handle_grab_texture(void*); BOOL enable_grab_texture(void*); @@ -1223,29 +1239,26 @@ void init_debug_world_menu(LLMenuGL* menu) menu->createJumpKeys(); } - +static void handle_export_menus_to_xml_continued(AIFilePicker* filepicker); void handle_export_menus_to_xml(void*) { + AIFilePicker* filepicker = AIFilePicker::create(); + filepicker->open("", FFSAVE_XML); + filepicker->run(boost::bind(&handle_export_menus_to_xml_continued, filepicker)); +} - LLFilePicker& picker = LLFilePicker::instance(); - if(!picker.getSaveFile(LLFilePicker::FFSAVE_XML)) +static void handle_export_menus_to_xml_continued(AIFilePicker* filepicker) +{ + if(!filepicker->hasFilename()) { - llwarns << "No file" << llendl; return; } - std::string filename = picker.getFirstFile(); - - llofstream out(filename); + llofstream out(filepicker->getFilename()); LLXMLNodePtr node = gMenuBarView->getXML(); node->writeToOstream(out); out.close(); } -extern BOOL gDebugClicks; -extern BOOL gDebugWindowProc; -extern BOOL gDebugTextEditorTips; -extern BOOL gDebugSelectMgr; - void init_debug_ui_menu(LLMenuGL* menu) { menu->append(new LLMenuItemCheckGL("Rotate Mini-Map", menu_toggle_control, NULL, menu_check_control, (void*)"MiniMapRotate")); @@ -1271,7 +1284,7 @@ void init_debug_ui_menu(LLMenuGL* menu) (void*)"DoubleClickTeleport")); menu->appendSeparator(); // menu->append(new LLMenuItemCallGL( "Print Packets Lost", &print_packets_lost, NULL, NULL, 'L', MASK_SHIFT )); - menu->append(new LLMenuItemToggleGL("Debug SelectMgr", &gDebugSelectMgr)); + menu->append(new LLMenuItemCheckGL("Debug SelectMgr", menu_toggle_control, NULL, menu_check_control, (void*)"DebugSelectMgr")); menu->append(new LLMenuItemToggleGL("Debug Clicks", &gDebugClicks)); menu->append(new LLMenuItemToggleGL("Debug Views", &LLView::sDebugRects)); menu->append(new LLMenuItemCheckGL("Show Name Tooltips", toggle_show_xui_names, NULL, check_show_xui_names, NULL)); @@ -1500,7 +1513,7 @@ void init_debug_rendering_menu(LLMenuGL* menu) //menu->append(new LLMenuItemCheckGL("Cull Small Objects", toggle_cull_small, NULL, menu_check_control, (void*)"RenderCullBySize")); menu->appendSeparator(); - menu->append(new LLMenuItemToggleGL("Hide Selected", &gHideSelectedObjects)); + menu->append(new LLMenuItemCheckGL("Hide Selected", menu_toggle_control, NULL, menu_check_control, (void*)"HideSelectedObjects")); menu->appendSeparator(); menu->append(new LLMenuItemCheckGL("Tangent Basis", menu_toggle_control, NULL, menu_check_control, (void*)"ShowTangentBasis")); menu->append(new LLMenuItemCallGL("Selected Texture Info", handle_selected_texture_info, NULL, NULL, 'T', MASK_CONTROL|MASK_SHIFT|MASK_ALT)); @@ -1586,7 +1599,7 @@ void init_debug_avatar_menu(LLMenuGL* menu) sub_menu->append(new LLMenuItemCallGL("Toggle PG", handle_toggle_pg)); - sub_menu->append(new LLMenuItemToggleGL("Allow Select Avatar", &gAllowSelectAvatar)); + sub_menu->append(new LLMenuItemCheckGL("Allow Select Avatar", menu_toggle_control, NULL, menu_check_control, (void*)"AllowSelectAvatar")); sub_menu->createJumpKeys(); menu->appendMenu(sub_menu); @@ -1627,6 +1640,11 @@ void init_debug_avatar_menu(LLMenuGL* menu) // //#endif // + + LLMenuItemCallGL* mesh_item = new LLMenuItemCallGL("Meshes And Morphs...", handle_meshes_and_morphs); + mesh_item->setUserData((void*)mesh_item); // So we can remove it later + menu->append(mesh_item); + menu->createJumpKeys(); } @@ -3502,7 +3520,7 @@ class LLSelfSitOrStand : public view_listener_t { bool handleEvent(LLPointer event, const LLSD& userdata) { - if (gAgent.getAvatarObject() && gAgent.getAvatarObject()->mIsSitting) + if (gAgent.getAvatarObject() && gAgent.getAvatarObject()->isSitting()) { // [RLVa:KB] - Alternate: Snowglobe-1.3.X | Checked: 2009-12-29 (RLVa-1.1.0k) | Added: RLVa-1.1.0k | OK if (gRlvHandler.hasBehaviour(RLV_BHVR_UNSIT)) @@ -3544,7 +3562,7 @@ class LLSelfEnableSitOrStand : public view_listener_t stand_text = param.substr(offset+1); } - if (gAgent.getAvatarObject() && gAgent.getAvatarObject()->mIsSitting) + if (gAgent.getAvatarObject() && gAgent.getAvatarObject()->isSitting()) { // [RLVa:KB] - Alternate: Snowglobe-1.3.X | Checked: 2009-12-29 (RLVa-1.1.0k) | Added: RLVa-1.1.0k | OK new_value &= (!gRlvHandler.hasBehaviour(RLV_BHVR_UNSIT)); @@ -3738,7 +3756,7 @@ void handle_force_ground_sit(void*) { if (gAgent.getAvatarObject()) { - if(!gAgent.getAvatarObject()->mIsSitting) + if(!gAgent.getAvatarObject()->isSitting()) { gAgent.setControlFlags(AGENT_CONTROL_SIT_ON_GROUND); } @@ -3939,7 +3957,7 @@ bool handle_sit_or_stand() // [RLVa:KB] - Checked: 2010-08-29 (RLVa-1.1.3b) | Added: RLVa-1.2.1c | OK if ( (gRlvHandler.hasBehaviour(RLV_BHVR_STANDTP)) && (gAgent.getAvatarObject()) ) { - if (gAgent.getAvatarObject()->mIsSitting) + if (gAgent.getAvatarObject()->isSitting()) { if (gRlvHandler.canStand()) gAgent.setControlFlags(AGENT_CONTROL_STAND_UP); @@ -4056,7 +4074,7 @@ class LLWorldEnableFly : public view_listener_t BOOL sitting = FALSE; if (gAgent.getAvatarObject()) { - sitting = gAgent.getAvatarObject()->mIsSitting; + sitting = gAgent.getAvatarObject()->isSitting(); } gMenuHolder->findControl(userdata["control"].asString())->setValue(!sitting); return true; @@ -5139,7 +5157,7 @@ BOOL sitting_on_selection() return FALSE; } - return (avatar->mIsSitting && avatar->getRoot() == root_object); + return (avatar->isSitting() && avatar->getRoot() == root_object); } class LLToolsSaveToInventory : public view_listener_t @@ -5320,26 +5338,7 @@ class LLToolsEnableLink : public view_listener_t { bool handleEvent(LLPointer event, const LLSD& userdata) { - bool new_value = false; - // check if there are at least 2 objects selected, and that the - // user can modify at least one of the selected objects. - - // in component mode, can't link - if (!gSavedSettings.getBOOL("EditLinkedParts")) - { - if(LLSelectMgr::getInstance()->selectGetAllRootsValid() && LLSelectMgr::getInstance()->getSelection()->getRootObjectCount() >= 2) - { - struct f : public LLSelectedObjectFunctor - { - virtual bool apply(LLViewerObject* object) - { - return object->permModify(); - } - } func; - const bool firstonly = true; - new_value = LLSelectMgr::getInstance()->getSelection()->applyToRootObjects(&func, firstonly); - } - } + bool new_value = LLSelectMgr::getInstance()->enableLinkObjects(); gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); return true; } @@ -5349,45 +5348,7 @@ class LLToolsLink : public view_listener_t { bool handleEvent(LLPointer event, const LLSD& userdata) { - if(!LLSelectMgr::getInstance()->selectGetAllRootsValid()) - { - LLNotifications::instance().add("UnableToLinkWhileDownloading"); - return true; - } - - S32 object_count = LLSelectMgr::getInstance()->getSelection()->getObjectCount(); - if (object_count > MAX_CHILDREN_PER_TASK + 1) - { - LLSD args; - args["COUNT"] = llformat("%d", object_count); - int max = MAX_CHILDREN_PER_TASK+1; - args["MAX"] = llformat("%d", max); - LLNotifications::instance().add("UnableToLinkObjects", args); - return true; - } - - if(LLSelectMgr::getInstance()->getSelection()->getRootObjectCount() < 2) - { - LLNotifications::instance().add("CannotLinkIncompleteSet"); - return true; - } - if(!LLSelectMgr::getInstance()->selectGetRootsModify()) - { - LLNotifications::instance().add("CannotLinkModify"); - return true; - } - LLUUID owner_id; - std::string owner_name; - if(!LLSelectMgr::getInstance()->selectGetOwner(owner_id, owner_name)) - { - // we don't actually care if you're the owner, but novices are - // the most likely to be stumped by this one, so offer the - // easiest and most likely solution. - LLNotifications::instance().add("CannotLinkDifferentOwners"); - return true; - } - LLSelectMgr::getInstance()->sendLink(); - return true; + return LLSelectMgr::getInstance()->linkObjects(); } }; @@ -5395,19 +5356,7 @@ class LLToolsEnableUnlink : public view_listener_t { bool handleEvent(LLPointer event, const LLSD& userdata) { - bool new_value = LLSelectMgr::getInstance()->selectGetAllRootsValid() && - LLSelectMgr::getInstance()->getSelection()->getFirstEditableObject() && - !LLSelectMgr::getInstance()->getSelection()->getFirstEditableObject()->isAttachment(); -// [RLVa:KB] - Checked: 2010-04-01 (RLVa-1.1.3b) | Modified: RLVa-0.2.0g | OK - if ( (new_value) && (!gRlvHandler.canStand()) ) - { - // Allow only if the avie isn't sitting on any of the selected objects - LLObjectSelectionHandle handleSel = LLSelectMgr::getInstance()->getSelection(); - RlvSelectIsSittingOn f(gAgent.getAvatarObject()->getRoot()); - if (handleSel->getFirstRootNode(&f, TRUE) != NULL) - new_value = false; - } -// [/RLVa:KB] + bool new_value = LLSelectMgr::getInstance()->enableUnlinkObjects(); gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); return true; } @@ -5417,18 +5366,7 @@ class LLToolsUnlink : public view_listener_t { bool handleEvent(LLPointer event, const LLSD& userdata) { -// [RLVa:KB] - Checked: 2010-04-01 (RLVa-1.1.3b) | Modified: RLVa-0.2.0g | OK - if ( (rlv_handler_t::isEnabled()) && (!gRlvHandler.canStand()) ) - { - // Allow only if the avie isn't sitting on any of the selected objects - LLObjectSelectionHandle hSel = LLSelectMgr::getInstance()->getSelection(); - RlvSelectIsSittingOn f(gAgent.getAvatarObject()->getRoot()); - if ( (hSel.notNull()) && (hSel->getFirstRootNode(&f, TRUE)) ) - return true; - } -// [/RLVa:KB] - - LLSelectMgr::getInstance()->sendDelink(); + LLSelectMgr::getInstance()->unlinkObjects(); return true; } }; @@ -5985,7 +5923,7 @@ class LLWorldSitOnGround : public view_listener_t { if (gAgent.getAvatarObject()) { - if(!gAgent.getAvatarObject()->mIsSitting) + if(!gAgent.getAvatarObject()->isSitting()) { gAgent.setControlFlags(AGENT_CONTROL_SIT_ON_GROUND); } @@ -6587,10 +6525,10 @@ class LLShowFloater : public view_listener_t { LLFloaterActiveSpeakers::toggleInstance(LLSD()); } - /*else if (floater_name == "beacons") + else if (floater_name == "beacons") { - LLFloaterBeacons::toggleInstance(LLSD()); NO - }*/ + LLFloaterBeacons::toggleInstance(LLSD()); + } else if (floater_name == "perm prefs") { LLFloaterPerms::toggleInstance(LLSD()); @@ -6654,14 +6592,10 @@ class LLFloaterVisible : public view_listener_t { new_value = LLFloaterActiveSpeakers::instanceVisible(LLSD()); } - /*else if (floater_name == "beacons") + else if (floater_name == "beacons") { - new_value = LLFloaterBeacons::instanceVisible(LLSD()); Oh man fuck this floater so much. + new_value = LLFloaterBeacons::instanceVisible(LLSD()); } - else if (floater_name == "dickdongs") - { - new_value = LLFloaterDickDongs::instanceVisible(LLSD()); Not needed any more. - }*/ else if (floater_name == "inventory") { LLInventoryView* iv = LLInventoryView::getActiveInventory(); @@ -8285,9 +8219,8 @@ class LLToolsShowSelectionHighlights : public view_listener_t { bool handleEvent(LLPointer event, const LLSD& userdata) { - LLSelectMgr::sRenderSelectionHighlights = !LLSelectMgr::sRenderSelectionHighlights; - - gSavedSettings.setBOOL("RenderHighlightSelections", LLSelectMgr::sRenderSelectionHighlights); + LLControlVariable *ctrl = gSavedSettings.getControl("RenderHighlightSelections"); + ctrl->setValue(!ctrl->getValue().asBoolean()); return true; } }; @@ -8369,6 +8302,410 @@ void handle_dump_avatar_local_textures(void*) } } +void handle_meshes_and_morphs(void* menu_item) +{ + LLMenuItemCallGL* item = (LLMenuItemCallGL*) menu_item; + LLMenuGL* parent_menu = (LLMenuGL*) item->getParent(); + parent_menu->remove(item); + + LLMenuGL* menu = new LLMenuGL("Meshes And Morphs"); + menu->append(new LLMenuItemCallGL("Dump Avatar Mesh Info", &LLPolyMesh::dumpDiagInfo)); + menu->appendSeparator(); + + LLVOAvatar::mesh_info_t mesh_info; + LLVOAvatar::getMeshInfo(&mesh_info); + + for(LLVOAvatar::mesh_info_t::iterator info_iter = mesh_info.begin(); + info_iter != mesh_info.end(); ++info_iter) + { + const std::string& type = info_iter->first; + LLVOAvatar::lod_mesh_map_t& lod_mesh = info_iter->second; + + LLMenuGL* type_menu = new LLMenuGL(type); + + for(LLVOAvatar::lod_mesh_map_t::iterator lod_iter = lod_mesh.begin(); + lod_iter != lod_mesh.end(); ++lod_iter) + { + S32 lod = lod_iter->first; + std::string& mesh = lod_iter->second; + + std::string caption = llformat ("%s LOD %d", type.c_str(), lod); + + if (lod == 0) + { + caption = type; + } + + LLPolyMeshSharedData* mesh_shared = LLPolyMesh::getMeshData(mesh); + + LLPolyMesh::morph_list_t morph_list; + LLPolyMesh::getMorphList(mesh, &morph_list); + + LLMenuGL* lod_menu = new LLMenuGL(caption); + lod_menu->append(new LLMenuItemCallGL("Save LLM", handle_mesh_save_llm, NULL, (void*) mesh_shared)); + + LLMenuGL* action_menu = new LLMenuGL("Base Mesh"); + action_menu->append(new LLMenuItemCallGL("Save OBJ", handle_mesh_save_obj, NULL, (void*) mesh_shared)); + + if (lod == 0) + { + // Since an LOD mesh has only faces, we won't enable this for + // LOD meshes until we add code for processing the face commands. + + action_menu->append(new LLMenuItemCallGL("Load OBJ", handle_mesh_load_obj, NULL, (void*) mesh_shared)); + } + + action_menu->createJumpKeys(); + lod_menu->appendMenu(action_menu); + + action_menu = new LLMenuGL("Current Mesh"); + + action_menu->append(new LLMenuItemCallGL("Save OBJ", handle_mesh_save_current_obj, NULL, (void*) mesh_shared)); + + action_menu->createJumpKeys(); + lod_menu->appendMenu(action_menu); + + lod_menu->appendSeparator(); + + for(LLPolyMesh::morph_list_t::iterator morph_iter = morph_list.begin(); + morph_iter != morph_list.end(); ++morph_iter) + { + std::string const& morph_name = morph_iter->first; + LLPolyMorphData* morph_data = morph_iter->second; + + action_menu = new LLMenuGL(morph_name); + + action_menu->append(new LLMenuItemCallGL("Save OBJ", handle_morph_save_obj, NULL, (void*) morph_data)); + action_menu->append(new LLMenuItemCallGL("Load OBJ", handle_morph_load_obj, NULL, (void*) morph_data)); + + action_menu->createJumpKeys(); + lod_menu->appendMenu(action_menu); + } + + lod_menu->createJumpKeys(); + type_menu->appendMenu(lod_menu); + } + type_menu->createJumpKeys(); + menu->appendMenu(type_menu); + } + + menu->createJumpKeys(); + menu->updateParent(LLMenuGL::sMenuContainer); + parent_menu->appendMenu(menu); + + LLMenuGL::sMenuContainer->hideMenus(); + LLFloater* tear_off_menu = LLTearOffMenu::create(menu); + tear_off_menu->setFocus(TRUE); +} + +static void handle_mesh_save_llm_continued(void* data, AIFilePicker* filepicker); +void handle_mesh_save_llm(void* data) +{ + LLPolyMeshSharedData* mesh_shared = (LLPolyMeshSharedData*) data; + std::string const* mesh_name = LLPolyMesh::getSharedMeshName(mesh_shared); + std::string default_path = gDirUtilp->getExpandedFilename(LL_PATH_CHARACTER, ""); + + if (!mesh_name) + { + llwarns << "LPolyMesh::getSharedMeshName returned NULL" << llendl; + return; + } + + AIFilePicker* filepicker = AIFilePicker::create(); + filepicker->open(*mesh_name, FFSAVE_ALL, default_path, "mesh_llm"); + filepicker->run(boost::bind(&handle_mesh_save_llm_continued, data, filepicker)); +} + +static void handle_mesh_save_llm_continued(void* data, AIFilePicker* filepicker) +{ + if (!filepicker->hasFilename()) + { + llwarns << "No file" << llendl; + return; + } + std::string selected_filename = filepicker->getFilename(); + LLPolyMeshSharedData* mesh_shared = (LLPolyMeshSharedData*) data; + std::string const* mesh_name = LLPolyMesh::getSharedMeshName(mesh_shared); + + llinfos << "Selected " << selected_filename << " for mesh " << *mesh_name <getExpandedFilename(LL_PATH_CHARACTER, ""); + + AIFilePicker* filepicker = AIFilePicker::create(); + filepicker->open(file_name, FFSAVE_ALL, default_path, "mesh_obj"); + filepicker->run(boost::bind(&handle_mesh_save_current_obj_continued, data, filepicker)); +} + +static void handle_mesh_save_current_obj_continued(void* data, AIFilePicker* filepicker) +{ + if(!filepicker->hasFilename()) + { + llwarns << "No file" << llendl; + return; + } + std::string selected_filename = filepicker->getFilename(); + LLPolyMeshSharedData* mesh_shared = (LLPolyMeshSharedData*)data; + std::string const* mesh_name = LLPolyMesh::getSharedMeshName(mesh_shared); + + llinfos << "Selected " << selected_filename << " for mesh " << *mesh_name <getMesh (mesh_shared); + mesh->saveOBJ(fp); + } + fclose(fp); +} + +static void handle_mesh_save_obj_continued(void* data, AIFilePicker* filepicker); +void handle_mesh_save_obj(void* data) +{ + LLPolyMeshSharedData* mesh_shared = (LLPolyMeshSharedData*) data; + std::string const* mesh_name = LLPolyMesh::getSharedMeshName(mesh_shared); + + if (!mesh_name) + { + llwarns << "LPolyMesh::getSharedMeshName returned NULL" << llendl; + return; + } + + std::string file_name = *mesh_name + ".obj"; + std::string default_path = gDirUtilp->getExpandedFilename(LL_PATH_CHARACTER, ""); + + AIFilePicker* filepicker = AIFilePicker::create(); + filepicker->open(file_name, FFSAVE_ALL, default_path, "mesh_obj"); + filepicker->run(boost::bind(&handle_mesh_save_obj_continued, data, filepicker)); +} + +static void handle_mesh_save_obj_continued(void* data, AIFilePicker* filepicker) +{ + if(!filepicker->hasFilename()) + { + llwarns << "No file" << llendl; + return; + } + std::string selected_filename = filepicker->getFilename(); + LLPolyMeshSharedData* mesh_shared = (LLPolyMeshSharedData*) data; + std::string const* mesh_name = LLPolyMesh::getSharedMeshName(mesh_shared); + + llinfos << "Selected " << selected_filename << " for mesh " << *mesh_name <getExpandedFilename(LL_PATH_CHARACTER, ""); + + if (!mesh_name) + { + llwarns << "LPolyMesh::getSharedMeshName returned NULL" << llendl; + return; + } + + AIFilePicker* filepicker = AIFilePicker::create(); + filepicker->open(FFLOAD_ALL, default_path, "mesh_obj"); + filepicker->run(boost::bind(&handle_mesh_load_obj_continued, data, filepicker)); +} + +static void handle_mesh_load_obj_continued(void* data, AIFilePicker* filepicker) +{ + if(!filepicker->hasFilename()) + { + llwarns << "No file" << llendl; + return; + } + std::string selected_filename = filepicker->getFilename(); + LLPolyMeshSharedData* mesh_shared = (LLPolyMeshSharedData*) data; + std::string const* mesh_name = LLPolyMesh::getSharedMeshName(mesh_shared); + + llinfos << "Selected " << selected_filename << " for mesh " << *mesh_name <mMesh; + std::string const* mesh_name = LLPolyMesh::getSharedMeshName(mesh_shared); + std::string const& morph_name = morph_data->getName(); + + if (!mesh_name) + { + llwarns << "LPolyMesh::getSharedMeshName returned NULL" << llendl; + return; + } + + llinfos << "Save morph OBJ " << morph_name << " of mesh " << *mesh_name <getExpandedFilename(LL_PATH_CHARACTER, ""); + + AIFilePicker* filepicker = AIFilePicker::create(); + filepicker->open(file_name, FFSAVE_ALL, default_path, "mesh_obj"); + filepicker->run(boost::bind(&handle_morph_save_obj_continued, data, filepicker)); +} + +static void handle_morph_save_obj_continued(void* data, AIFilePicker* filepicker) +{ + if (!filepicker->hasFilename()) + { + llwarns << "No file" << llendl; + return; + } + std::string selected_filename = filepicker->getFilename(); + LLPolyMorphData* morph_data = (LLPolyMorphData*)data; + + llinfos << "Selected " << selected_filename << llendl; + + LLFILE* fp = LLFile::fopen(selected_filename, "wb"); /*Flawfinder: ignore*/ + if (!fp) + { + llerrs << "can't open: " << selected_filename << llendl; + return; + } + + morph_data->saveOBJ(fp); + fclose(fp); +} + +static void handle_morph_load_obj_continued(void* data, AIFilePicker* filepicker); +void handle_morph_load_obj(void* data) +{ + LLPolyMorphData* morph_data = (LLPolyMorphData*) data; + LLPolyMeshSharedData* mesh_shared = morph_data->mMesh; + std::string const* mesh_name = LLPolyMesh::getSharedMeshName(mesh_shared); + std::string const& morph_name = morph_data->getName(); + std::string default_path = gDirUtilp->getExpandedFilename(LL_PATH_CHARACTER, ""); + + if (!mesh_name) + { + llwarns << "LPolyMesh::getSharedMeshName returned NULL" << llendl; + return; + } + + llinfos << "Load morph OBJ " << morph_name << " of mesh " << *mesh_name <open(FFLOAD_ALL, default_path, "mesh_obj"); + filepicker->run(boost::bind(&handle_morph_load_obj_continued, data, filepicker)); +} + +static void handle_morph_load_obj_continued(void* data, AIFilePicker* filepicker) +{ + if(!filepicker->hasFilename()) + { + llwarns << "No file" << llendl; + return; + } + std::string selected_filename = filepicker->getFilename(); + LLPolyMorphData* morph_data = (LLPolyMorphData*) data; + LLPolyMeshSharedData* mesh_shared = morph_data->mMesh; + + llinfos << "Selected " << selected_filename <setMorphFromMesh(&mesh); +} + void handle_debug_avatar_textures(void*) { LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); @@ -8544,7 +8881,7 @@ void force_error_bad_memory_access(void *) void force_error_infinite_loop(void *) { - LLAppViewer::instance()->forceErrorInifiniteLoop(); + LLAppViewer::instance()->forceErrorInfiniteLoop(); } void force_error_software_exception(void *) @@ -8626,6 +8963,7 @@ const LLRect LLViewerMenuHolderGL::getMenuRect() const return LLRect(0, getRect().getHeight() - MENU_BAR_HEIGHT, getRect().getWidth(), STATUS_BAR_HEIGHT); } +static void handle_save_to_xml_continued(LLFloater* frontmost, AIFilePicker* filepicker); void handle_save_to_xml(void*) { LLFloater* frontmost = gFloaterView->getFrontmost(); @@ -8645,20 +8983,33 @@ void handle_save_to_xml(void*) LLStringUtil::replaceChar(default_name, ':', '_'); LLStringUtil::replaceChar(default_name, '"', '_'); - LLFilePicker& picker = LLFilePicker::instance(); - if (picker.getSaveFile(LLFilePicker::FFSAVE_XML, default_name)) + AIFilePicker* filepicker = AIFilePicker::create(); + filepicker->open(default_name, FFSAVE_XML); + filepicker->run(boost::bind(&handle_save_to_xml_continued, frontmost, filepicker)); +} + +static void handle_save_to_xml_continued(LLFloater* frontmost, AIFilePicker* filepicker) +{ + if (filepicker->hasFilename()) { - std::string filename = picker.getFirstFile(); + std::string filename = filepicker->getFilename(); LLUICtrlFactory::getInstance()->saveToXML(frontmost, filename); } } +static void handle_load_from_xml_continued(AIFilePicker* filepicker); void handle_load_from_xml(void*) { - LLFilePicker& picker = LLFilePicker::instance(); - if (picker.getOpenFile(LLFilePicker::FFLOAD_XML)) + AIFilePicker* filepicker = AIFilePicker::create(); + filepicker->open(FFLOAD_XML); + filepicker->run(boost::bind(&handle_load_from_xml_continued, filepicker)); +} + +static void handle_load_from_xml_continued(AIFilePicker* filepicker) +{ + if (filepicker->hasFilename()) { - std::string filename = picker.getFirstFile(); + std::string filename = filepicker->getFilename(); LLFloater* floater = new LLFloater("sample_floater"); LLUICtrlFactory::getInstance()->buildFloater(floater, filename); } @@ -9129,1104 +9480,12 @@ class LLWorldDayCycle : public view_listener_t } }; - - static void addMenu(view_listener_t *menu, const std::string& name) { sMenus.push_back(menu); menu->registerListener(gMenuHolder, name); } - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -//Chalice - Old beacon style -class LLViewBeaconWidth : public view_listener_t -{ - bool handleEvent(LLPointer event, const LLSD& userdata) - { - std::string width = userdata.asString(); - if(width == "1") - { - gSavedSettings.setS32("DebugBeaconLineWidth", 1); - } - else if(width == "4") - { - gSavedSettings.setS32("DebugBeaconLineWidth", 4); - } - else if(width == "16") - { - gSavedSettings.setS32("DebugBeaconLineWidth", 16); - } - else if(width == "32") - { - gSavedSettings.setS32("DebugBeaconLineWidth", 32); - } - - return true; - } -}; - -//PURPLESL - Old beacon style -class LLViewToggleBeacon : public view_listener_t -{ - bool handleEvent(LLPointer event, const LLSD& userdata) - { - std::string beacon = userdata.asString(); - if (beacon == "scriptsbeacon") - { - LLPipeline::toggleRenderScriptedBeacons(NULL); - gSavedSettings.setBOOL( "scriptsbeacon", LLPipeline::getRenderScriptedBeacons(NULL) ); - // toggle the other one off if it's on - if (LLPipeline::getRenderScriptedBeacons(NULL) && LLPipeline::getRenderScriptedTouchBeacons(NULL)) - { - LLPipeline::toggleRenderScriptedTouchBeacons(NULL); - gSavedSettings.setBOOL( "scripttouchbeacon", LLPipeline::getRenderScriptedTouchBeacons(NULL) ); - } - } - else if (beacon == "physicalbeacon") - { - LLPipeline::toggleRenderPhysicalBeacons(NULL); - gSavedSettings.setBOOL( "physicalbeacon", LLPipeline::getRenderPhysicalBeacons(NULL) ); - } - else if (beacon == "soundsbeacon") - { - LLPipeline::toggleRenderSoundBeacons(NULL); - gSavedSettings.setBOOL( "soundsbeacon", LLPipeline::getRenderSoundBeacons(NULL) ); - } - else if (beacon == "particlesbeacon") - { - LLPipeline::toggleRenderParticleBeacons(NULL); - gSavedSettings.setBOOL( "particlesbeacon", LLPipeline::getRenderParticleBeacons(NULL) ); - } - else if (beacon == "scripttouchbeacon") - { - LLPipeline::toggleRenderScriptedTouchBeacons(NULL); - gSavedSettings.setBOOL( "scripttouchbeacon", LLPipeline::getRenderScriptedTouchBeacons(NULL) ); - // toggle the other one off if it's on - if (LLPipeline::getRenderScriptedBeacons(NULL) && LLPipeline::getRenderScriptedTouchBeacons(NULL)) - { - LLPipeline::toggleRenderScriptedBeacons(NULL); - gSavedSettings.setBOOL( "scriptsbeacon", LLPipeline::getRenderScriptedBeacons(NULL) ); - } - } - else if (beacon == "renderbeacons") - { - LLPipeline::toggleRenderBeacons(NULL); - gSavedSettings.setBOOL( "renderbeacons", LLPipeline::getRenderBeacons(NULL) ); - // toggle the other one on if it's not - if (!LLPipeline::getRenderBeacons(NULL) && !LLPipeline::getRenderHighlights(NULL)) - { - LLPipeline::toggleRenderHighlights(NULL); - gSavedSettings.setBOOL( "renderhighlights", LLPipeline::getRenderHighlights(NULL) ); - } - } - else if (beacon == "renderhighlights") - { - LLPipeline::toggleRenderHighlights(NULL); - gSavedSettings.setBOOL( "renderhighlights", LLPipeline::getRenderHighlights(NULL) ); - // toggle the other one on if it's not - if (!LLPipeline::getRenderBeacons(NULL) && !LLPipeline::getRenderHighlights(NULL)) - { - LLPipeline::toggleRenderBeacons(NULL); - gSavedSettings.setBOOL( "renderbeacons", LLPipeline::getRenderBeacons(NULL) ); - } - } - - return true; - } -}; -//PURPLESL - Old beacon style -class LLViewCheckBeaconEnabled : public view_listener_t -{ - bool handleEvent(LLPointer event, const LLSD& userdata) - { - std::string beacon = userdata["data"].asString(); - bool new_value = false; - if (beacon == "scriptsbeacon") - { - new_value = gSavedSettings.getBOOL( "scriptsbeacon"); - LLPipeline::setRenderScriptedBeacons(new_value); - } - else if (beacon == "physicalbeacon") - { - new_value = gSavedSettings.getBOOL( "physicalbeacon"); - LLPipeline::setRenderPhysicalBeacons(new_value); - } - else if (beacon == "soundsbeacon") - { - new_value = gSavedSettings.getBOOL( "soundsbeacon"); - LLPipeline::setRenderSoundBeacons(new_value); - } - else if (beacon == "particlesbeacon") - { - new_value = gSavedSettings.getBOOL( "particlesbeacon"); - LLPipeline::setRenderParticleBeacons(new_value); - } - else if (beacon == "scripttouchbeacon") - { - new_value = gSavedSettings.getBOOL( "scripttouchbeacon"); - LLPipeline::setRenderScriptedTouchBeacons(new_value); - } - else if (beacon == "renderbeacons") - { - new_value = gSavedSettings.getBOOL( "renderbeacons"); - LLPipeline::setRenderBeacons(new_value); - } - else if (beacon == "renderhighlights") - { - new_value = gSavedSettings.getBOOL( "renderhighlights"); - LLPipeline::setRenderHighlights(new_value); - } - gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); - return true; - } -}; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void initialize_menus() { // A parameterized event handler used as ctrl-8/9/0 zoom controls below. @@ -10298,8 +9557,6 @@ void initialize_menus() addMenu(new LLViewLookAtLastChatter(), "View.LookAtLastChatter"); addMenu(new LLViewShowHoverTips(), "View.ShowHoverTips"); addMenu(new LLViewHighlightTransparent(), "View.HighlightTransparent"); - addMenu(new LLViewToggleBeacon(), "View.ToggleBeacon"); - addMenu(new LLViewBeaconWidth(), "View.BeaconWidth"); addMenu(new LLViewToggleRenderType(), "View.ToggleRenderType"); addMenu(new LLViewShowHUDAttachments(), "View.ShowHUDAttachments"); addMenu(new LLZoomer(1.2f), "View.ZoomOut"); @@ -10317,7 +9574,6 @@ void initialize_menus() addMenu(new LLViewCheckJoystickFlycam(), "View.CheckJoystickFlycam"); addMenu(new LLViewCheckShowHoverTips(), "View.CheckShowHoverTips"); addMenu(new LLViewCheckHighlightTransparent(), "View.CheckHighlightTransparent"); - addMenu(new LLViewCheckBeaconEnabled(), "View.CheckBeaconEnabled"); addMenu(new LLViewCheckRenderType(), "View.CheckRenderType"); addMenu(new LLViewCheckHUDAttachments(), "View.CheckHUDAttachments"); diff --git a/indra/newview/llviewermenu.h b/indra/newview/llviewermenu.h index e9fedf37d..a6d96c08c 100644 --- a/indra/newview/llviewermenu.h +++ b/indra/newview/llviewermenu.h @@ -35,9 +35,6 @@ #include "llmenugl.h" -//newview includes -#include "llfilepicker.h" - class LLUICtrl; class LLView; class LLParcelSelection; diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp index b4d01d476..d246ffe62 100644 --- a/indra/newview/llviewermenufile.cpp +++ b/indra/newview/llviewermenufile.cpp @@ -41,7 +41,7 @@ #include "llimagepng.h" #include "llimagebmp.h" -#include "llfilepicker.h" +#include "statemachine/aifilepicker.h" #include "llfloateranimpreview.h" #include "llfloaterbuycurrency.h" @@ -125,26 +125,26 @@ static std::string SLOBJECT_EXTENSIONS = "slobject"; #endif static std::string ALL_FILE_EXTENSIONS = "*.*"; -std::string build_extensions_string(LLFilePicker::ELoadFilter filter) +std::string build_extensions_string(ELoadFilter filter) { switch(filter) { #if LL_WINDOWS - case LLFilePicker::FFLOAD_IMAGE: + case FFLOAD_IMAGE: return IMAGE_EXTENSIONS; - case LLFilePicker::FFLOAD_WAV: + case FFLOAD_WAV: return SOUND_EXTENSIONS; - case LLFilePicker::FFLOAD_ANIM: + case FFLOAD_ANIM: return ANIM_EXTENSIONS; - case LLFilePicker::FFLOAD_SLOBJECT: + case FFLOAD_SLOBJECT: return SLOBJECT_EXTENSIONS; #ifdef _CORY_TESTING - case LLFilePicker::FFLOAD_GEOMETRY: + case FFLOAD_GEOMETRY: return GEOMETRY_EXTENSIONS; #endif - case LLFilePicker::FFLOAD_XML: + case FFLOAD_XML: return XML_EXTENSIONS; - case LLFilePicker::FFLOAD_ALL: + case FFLOAD_ALL: return ALL_FILE_EXTENSIONS; #endif default: @@ -152,48 +152,51 @@ std::string build_extensions_string(LLFilePicker::ELoadFilter filter) } } -/** - char* upload_pick(void* data) +class AIFileUpload { + protected: + AIFilePicker* mPicker; - If applicable, brings up a file chooser in which the user selects a file - to upload for a particular task. If the file is valid for the given action, - returns the string to the full path filename, else returns NULL. - Data is the load filter for the type of file as defined in LLFilePicker. + public: + AIFileUpload(void) : mPicker(NULL) { } + virtual ~AIFileUpload() { llassert(!mPicker); if (mPicker) { mPicker->abort(); mPicker = NULL; } } - Eventually I'd really like to have a built-in browser that gave you all - valid filetypes, default permissions, "Temp when available", and a single - upload button. Maybe let it show the contents of multiple folders. The main - purpose of this features is to deal with the problem of SL just up and - disconnecting if you take more than like 30 seconds to look for a file. -HgB -**/ -const std::string upload_pick(void* data) + public: + bool is_valid(std::string const& filename, ELoadFilter type); + void filepicker_callback(ELoadFilter type); + void start_filepicker(ELoadFilter type, char const* context); + + protected: + virtual void handle_event(std::string const& filename) = 0; +}; + +void AIFileUpload::start_filepicker(ELoadFilter filter, char const* context) { - if( gAgent.cameraMouselook() ) + if( gAgent.cameraMouselook() ) { gAgent.changeCameraToDefault(); // This doesn't seem necessary. JC // display(); } - LLFilePicker::ELoadFilter type; - if(data) - { - type = (LLFilePicker::ELoadFilter)((intptr_t)data); - } - else - { - type = LLFilePicker::FFLOAD_ALL; - } + llassert(!mPicker); + mPicker = AIFilePicker::create(); + mPicker->open(filter, "", context); + mPicker->run(boost::bind(&AIFileUpload::filepicker_callback, this, filter)); +} - LLFilePicker& picker = LLFilePicker::instance(); - if (!picker.getOpenFile(type)) +void AIFileUpload::filepicker_callback(ELoadFilter type) +{ + if (mPicker->hasFilename()) { - llinfos << "Couldn't import objects from file" << llendl; - return std::string(); + std::string filename = mPicker->getFilename(); + if (is_valid(filename, type)) + handle_event(filename); } + mPicker = NULL; +} - - const std::string& filename = picker.getFirstFile(); +bool AIFileUpload::is_valid(std::string const& filename, ELoadFilter type) +{ std::string ext = gDirUtilp->getExtension(filename); //strincmp doesn't like NULL pointers @@ -205,7 +208,7 @@ const std::string upload_pick(void* data) LLSD args; args["FILE"] = short_name; LLNotifications::instance().add("NoFileExtension", args); - return std::string(); + return false; } else { @@ -248,7 +251,7 @@ const std::string upload_pick(void* data) args["EXTENSION"] = ext; args["VALIDS"] = valid_extensions; LLNotifications::instance().add("InvalidFileExtension", args); - return NULL; + return false; } }//end else (non-null extension) @@ -257,7 +260,7 @@ const std::string upload_pick(void* data) //now we check to see //if the file is actually a valid image/sound/etc. //Consider completely disabling this, see how SL handles it. Maybe we can get full song uploads again! -HgB - if (type == LLFilePicker::FFLOAD_WAV) + if (type == FFLOAD_WAV) { // pre-qualify wavs to make sure the format is acceptable std::string error_msg; @@ -267,103 +270,68 @@ const std::string upload_pick(void* data) LLSD args; args["FILE"] = filename; LLNotifications::instance().add( error_msg, args ); - return std::string(); + return false; } }//end if a wave/sound file - return filename; + return true; } -class LLFileUploadImage : public view_listener_t +class LLFileUploadImage : public view_listener_t, public AIFileUpload { + public: bool handleEvent(LLPointer event, const LLSD& userdata) { - std::string filename = upload_pick((void *)LLFilePicker::FFLOAD_IMAGE); - if (!filename.empty()) - { - LLFloaterImagePreview* floaterp = new LLFloaterImagePreview(filename); - LLUICtrlFactory::getInstance()->buildFloater(floaterp, "floater_image_preview.xml"); - } - return TRUE; + start_filepicker(FFLOAD_IMAGE, "image"); + return true; + } + + protected: + // Inherited from AIFileUpload. + /*virtual*/ void handle_event(std::string const& filename) + { + LLFloaterImagePreview* floaterp = new LLFloaterImagePreview(filename); + LLUICtrlFactory::getInstance()->buildFloater(floaterp, "floater_image_preview.xml"); } }; -class LLFileUploadSound : public view_listener_t +class LLFileUploadSound : public view_listener_t, public AIFileUpload { bool handleEvent(LLPointer event, const LLSD& userdata) { - std::string filename = upload_pick((void*)LLFilePicker::FFLOAD_WAV); - if (!filename.empty()) - { - LLFloaterNameDesc* floaterp = new LLFloaterNameDesc(filename); - LLUICtrlFactory::getInstance()->buildFloater(floaterp, "floater_sound_preview.xml"); - floaterp->childSetLabelArg("ok_btn", "[AMOUNT]", llformat("%d", LLGlobalEconomy::Singleton::getInstance()->getPriceUpload() )); - } + start_filepicker(FFLOAD_WAV, "sound"); return true; } + + protected: + // Inherited from AIFileUpload. + /*virtual*/ void handle_event(std::string const& filename) + { + LLFloaterNameDesc* floaterp = new LLFloaterNameDesc(filename); + LLUICtrlFactory::getInstance()->buildFloater(floaterp, "floater_sound_preview.xml"); + floaterp->childSetLabelArg("ok_btn", "[AMOUNT]", llformat("%d", LLGlobalEconomy::Singleton::getInstance()->getPriceUpload() )); + } }; -class LLFileUploadAnim : public view_listener_t +class LLFileUploadAnim : public view_listener_t, public AIFileUpload { bool handleEvent(LLPointer event, const LLSD& userdata) { - const std::string filename = upload_pick((void*)LLFilePicker::FFLOAD_ANIM); - if (!filename.empty()) - { - LLFloaterAnimPreview* floaterp = new LLFloaterAnimPreview(filename); - LLUICtrlFactory::getInstance()->buildFloater(floaterp, "floater_animation_preview.xml"); - } + start_filepicker(FFLOAD_ANIM, "animations"); return true; } + + protected: + // Inherited from AIFileUpload. + /*virtual*/ void handle_event(std::string const& filename) + { + LLFloaterAnimPreview* floaterp = new LLFloaterAnimPreview(filename); + LLUICtrlFactory::getInstance()->buildFloater(floaterp, "floater_animation_preview.xml"); + } }; class LLFileUploadBulk : public view_listener_t { - static bool onConfirmBulkUploadTemp(const LLSD& notification, const LLSD& response ) - { - S32 option = LLNotification::getSelectedOption(notification, response); - BOOL enabled; - if(option == 0) // yes - enabled = TRUE; - else if(option == 1) //no - enabled = FALSE; - else //cancel - return false; - - LLFilePicker& picker = LLFilePicker::instance(); - if (picker.getMultipleOpenFiles()) - { - //const std::string& filename = picker.getFirstFile(); - std::string filename; - while(!(filename = picker.getNextFile()).empty()) - { - std::string name = gDirUtilp->getBaseFileName(filename, true); - - std::string asset_name = name; - LLStringUtil::replaceNonstandardASCII( asset_name, '?' ); - LLStringUtil::replaceChar(asset_name, '|', '?'); - LLStringUtil::stripNonprintable(asset_name); - LLStringUtil::trim(asset_name); - - std::string display_name = LLStringUtil::null; - LLAssetStorage::LLStoreAssetCallback callback = NULL; - S32 expected_upload_cost = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload(); - void *userdata = NULL; - gSavedSettings.setBOOL("TemporaryUpload",enabled); - upload_new_resource(filename, asset_name, asset_name, 0, LLAssetType::AT_NONE, LLInventoryType::IT_NONE, - LLFloaterPerms::getNextOwnerPerms(), LLFloaterPerms::getGroupPerms(), LLFloaterPerms::getEveryonePerms(), - display_name, - callback, expected_upload_cost, userdata); - - } - } - else - { - llinfos << "Couldn't import objects from file" << llendl; - gSavedSettings.setBOOL("TemporaryUpload",FALSE); - } - return false; - } bool handleEvent(LLPointer event, const LLSD& userdata) { if( gAgent.cameraMouselook() ) @@ -388,45 +356,59 @@ class LLFileUploadBulk : public view_listener_t msg.append(llformat("\nWARNING: Each upload costs L$%d if it's not temporary.",expected_upload_cost)); args["MESSAGE"] = msg; LLNotifications::instance().add("GenericAlertYesNoCancel", args, LLSD(), onConfirmBulkUploadTemp); - /* moved to the callback for the above - LLFilePicker& picker = LLFilePicker::instance(); - if (picker.getMultipleOpenFiles()) - { - // - - //const std::string& filename = picker.getFirstFile(); - std::string filename; - while(!(filename = picker.getNextFile()).empty()) - { - // - std::string name = gDirUtilp->getBaseFileName(filename, true); - - std::string asset_name = name; - LLStringUtil::replaceNonstandardASCII( asset_name, '?' ); - LLStringUtil::replaceChar(asset_name, '|', '?'); - LLStringUtil::stripNonprintable(asset_name); - LLStringUtil::trim(asset_name); - - std::string display_name = LLStringUtil::null; - LLAssetStorage::LLStoreAssetCallback callback = NULL; - S32 expected_upload_cost = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload(); - void *userdata = NULL; - upload_new_resource(filename, asset_name, asset_name, 0, LLAssetType::AT_NONE, LLInventoryType::IT_NONE, - LLFloaterPerms::getNextOwnerPerms(), LLFloaterPerms::getGroupPerms(), LLFloaterPerms::getEveryonePerms(), - display_name, - callback, expected_upload_cost, userdata); + return true; + } + + static bool onConfirmBulkUploadTemp(const LLSD& notification, const LLSD& response ) + { + S32 option = LLNotification::getSelectedOption(notification, response); + bool enabled; + if (option == 0) // yes + enabled = true; + else if(option == 1) // no + enabled = false; + else // cancel + return false; + + AIFilePicker* filepicker = AIFilePicker::create(); + filepicker->open(FFLOAD_ALL, "", "openfile", true); + filepicker->run(boost::bind(&LLFileUploadBulk::onConfirmBulkUploadTemp_continued, enabled, filepicker)); + return true; + } + + static void onConfirmBulkUploadTemp_continued(bool enabled, AIFilePicker* filepicker) + { + if (filepicker->hasFilename()) + { + std::vector const& file_names(filepicker->getFilenames()); + for (std::vector::const_iterator iter = file_names.begin(); iter != file_names.end(); ++iter) + { + std::string const& filename(*iter); + if (filename.empty()) + continue; + std::string name = gDirUtilp->getBaseFileName(filename, true); + + std::string asset_name = name; + LLStringUtil::replaceNonstandardASCII( asset_name, '?' ); + LLStringUtil::replaceChar(asset_name, '|', '?'); + LLStringUtil::stripNonprintable(asset_name); + LLStringUtil::trim(asset_name); + + std::string display_name = LLStringUtil::null; + LLAssetStorage::LLStoreAssetCallback callback = NULL; + S32 expected_upload_cost = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload(); + void *userdata = NULL; + gSavedSettings.setBOOL("TemporaryUpload", enabled); + upload_new_resource(filename, asset_name, asset_name, 0, LLAssetType::AT_NONE, LLInventoryType::IT_NONE, + LLFloaterPerms::getNextOwnerPerms(), LLFloaterPerms::getGroupPerms(), LLFloaterPerms::getEveryonePerms(), + display_name, callback, expected_upload_cost, userdata); - // *NOTE: Ew, we don't iterate over the file list here, - // we handle the next files in upload_done_callback() - // not anymore! } } else { - llinfos << "Couldn't import objects from file" << llendl; + gSavedSettings.setBOOL("TemporaryUpload", FALSE); } - */ - return true; } }; @@ -438,7 +420,7 @@ void upload_error(const std::string& error_message, const std::string& label, co { lldebugs << "unable to remove temp file" << llendl; } - LLFilePicker::instance().reset(); + //AIFIXME? LLFilePicker::instance().reset(); } class LLFileEnableCloseWindow : public view_listener_t @@ -552,8 +534,6 @@ class LLFileTakeSnapshotToDisk : public view_listener_t 6144, supersample)) { - gViewerWindow->playSnapshotAnimAndSound(); - LLPointer formatted; switch(LLFloaterSnapshot::ESnapshotFormat(gSavedSettings.getS32("SnapshotFormat"))) { @@ -603,44 +583,39 @@ class LLFileQuit : public view_listener_t } }; -void handle_upload(void* data) -{ - const std::string filename = upload_pick(data); - if (!filename.empty()) - { - LLFloaterNameDesc* floaterp = new LLFloaterNameDesc(filename); - LLUICtrlFactory::getInstance()->buildFloater(floaterp, "floater_name_description.xml"); - floaterp->childSetLabelArg("ok_btn", "[AMOUNT]", llformat("%d", LLGlobalEconomy::Singleton::getInstance()->getPriceUpload() )); - } -} - +static void handle_compress_image_continued(AIFilePicker* filepicker); void handle_compress_image(void*) { - LLFilePicker& picker = LLFilePicker::instance(); - if (picker.getMultipleOpenFiles(LLFilePicker::FFLOAD_IMAGE)) + AIFilePicker* filepicker = AIFilePicker::create(); + filepicker->open(FFLOAD_IMAGE, "", "openfile", true); + filepicker->run(boost::bind(&handle_compress_image_continued, filepicker)); +} + +static void handle_compress_image_continued(AIFilePicker* filepicker) +{ + if (!filepicker->hasFilename()) + return; + + std::vector const& filenames(filepicker->getFilenames()); + for(std::vector::const_iterator filename = filenames.begin(); filename != filenames.end(); ++filename) { - std::string infile = picker.getFirstFile(); - while (!infile.empty()) + std::string const& infile(*filename); + std::string outfile = infile + ".j2c"; + + llinfos << "Input: " << infile << llendl; + llinfos << "Output: " << outfile << llendl; + + BOOL success; + + success = LLViewerTextureList::createUploadFile(infile, outfile, IMG_CODEC_TGA); + + if (success) { - std::string outfile = infile + ".j2c"; - - llinfos << "Input: " << infile << llendl; - llinfos << "Output: " << outfile << llendl; - - BOOL success; - - success = LLViewerTextureList::createUploadFile(infile, outfile, IMG_CODEC_TGA); - - if (success) - { - llinfos << "Compression complete" << llendl; - } - else - { - llinfos << "Compression failed: " << LLImage::getLastError() << llendl; - } - - infile = picker.getNextFile(); + llinfos << "Compression complete" << llendl; + } + else + { + llinfos << "Compression failed: " << LLImage::getLastError() << llendl; } } } @@ -990,7 +965,7 @@ void upload_new_resource(const std::string& src_filename, std::string name, { lldebugs << "unable to remove temp file" << llendl; } - LLFilePicker::instance().reset(); + //AIFIXME? LLFilePicker::instance().reset(); } } // @@ -1139,32 +1114,6 @@ void upload_done_callback(const LLUUID& uuid, void* user_data, S32 result, LLExt LLUploadDialog::modalUploadFinished(); delete data; - - // *NOTE: This is a pretty big hack. What this does is check the - // file picker if there are any more pending uploads. If so, - // upload that file. - /* Agreed, let's not use it. -HgB - const std::string& next_file = LLFilePicker::instance().getNextFile(); - if(is_balance_sufficient && !next_file.empty()) - { - std::string asset_name = gDirUtilp->getBaseFileName(next_file, true); - LLStringUtil::replaceNonstandardASCII( asset_name, '?' ); - LLStringUtil::replaceChar(asset_name, '|', '?'); - LLStringUtil::stripNonprintable(asset_name); - LLStringUtil::trim(asset_name); - - std::string display_name = LLStringUtil::null; - LLAssetStorage::LLStoreAssetCallback callback = NULL; - void *userdata = NULL; - upload_new_resource(next_file, asset_name, asset_name, // file - 0, LLAssetType::AT_NONE, LLInventoryType::IT_NONE, - PERM_NONE, PERM_NONE, PERM_NONE, - display_name, - callback, - expected_upload_cost, // assuming next in a group of uploads is of roughly the same type, i.e. same upload cost - userdata); - } - */ } void upload_new_resource(const LLTransactionID &tid, LLAssetType::EType asset_type, diff --git a/indra/newview/llviewermenufile.h b/indra/newview/llviewermenufile.h index 0e03429e9..c92e82da3 100644 --- a/indra/newview/llviewermenufile.h +++ b/indra/newview/llviewermenufile.h @@ -78,6 +78,4 @@ void upload_new_resource(const LLTransactionID &tid, S32 expected_upload_cost, void *userdata); -const std::string upload_pick(void* data); - #endif diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 6a8c61174..a670b229f 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -49,7 +49,6 @@ #include "llchat.h" #include "lldbstrings.h" #include "lleconomy.h" -#include "llfilepicker.h" #include "llfocusmgr.h" #include "llfollowcamparams.h" #include "llinstantmessage.h" @@ -64,7 +63,7 @@ #include "llxfermanager.h" #include "message.h" #include "sound_ids.h" -#include "lltimer.h" +#include "lleventtimer.h" #include "llmd5.h" #include "llagent.h" @@ -3703,19 +3702,6 @@ void process_teleport_finish(LLMessageSystem* msg, void**) effectp->setColor(LLColor4U(gAgent.getEffectColor())); LLHUDManager::getInstance()->sendEffects(); - // OGPX : when using agent domain, we get tp finish with ip of 0.0.0.0 and port 0. - // try bailing out early if tp state is PLACE_AVATAR (so legacy should still execute rest of this path) - // not really wild about this, but it's a way to test if we can get TP working w/o receiving TP finish - // TODO: can be removed *when* agent domain no longer sends tp finish - // - // OGPX TODO: see if we can nuke TELEPORT_PLACE_AVATAR state once TeleportFinish is - // completely removed from all SL and OS region code - - if (gAgent.getTeleportState() == LLAgent::TELEPORT_PLACE_AVATAR ) - { - llinfos << "Got teleport location message when doing agentd TP" << llendl; - return; - } U32 location_id; U32 sim_ip; U16 sim_port; @@ -3888,10 +3874,8 @@ void process_agent_movement_complete(LLMessageSystem* msg, void**) gCacheName->setUpstream(msg->getSender()); gViewerThrottle.sendToSim(); gViewerWindow->sendShapeToSim(); - // if this is an AgentMovementComplete message that happened as the result of a teleport, - // then we need to do things like chat the URL and reset the camera. - bool is_teleport = (gAgent.getTeleportState() & (LLAgent::TELEPORT_MOVING | LLAgent::TELEPORT_PLACE_AVATAR)); //OGPX - llinfos << " is_teleport =" << is_teleport << llendl; + + bool is_teleport = gAgent.getTeleportState() == LLAgent::TELEPORT_MOVING; if( is_teleport ) { @@ -3927,11 +3911,6 @@ void process_agent_movement_complete(LLMessageSystem* msg, void**) avatarp->clearChat(); avatarp->slamPosition(); } - // OGPX TODO: remove all usage of TELEPORT_PLACE_AVATAR state once Teleport UDP sequence finalized - if ( gAgent.getTeleportState() == LLAgent::TELEPORT_PLACE_AVATAR ) // unset TP state, agent domain is done. OGPX - { - gAgent.setTeleportState( LLAgent::TELEPORT_NONE ); - } // add teleport destination to the list of visited places gFloaterTeleportHistory->addPendingEntry(regionp->getName(), (S16)agent_pos.mV[VX], (S16)agent_pos.mV[VY], (S16)agent_pos.mV[VZ]); @@ -3940,6 +3919,17 @@ void process_agent_movement_complete(LLMessageSystem* msg, void**) { // This is likely just the initial logging in phase. gAgent.setTeleportState( LLAgent::TELEPORT_NONE ); + + if(LLStartUp::getStartupState() < STATE_STARTED) + { // This is initial log-in, not a region crossing: + // Set the camera looking ahead of the AV so send_agent_update() below + // will report the correct location to the server. + LLVector3 look_at_point = look_at; + look_at_point = agent_pos + look_at_point.rotVec(gAgent.getQuat()); + + static LLVector3 up_direction(0.0f, 0.0f, 1.0f); + LLViewerCamera::getInstance()->lookAt(agent_pos, look_at_point, up_direction); + } } if ( LLTracker::isTracking(NULL) ) @@ -4304,7 +4294,6 @@ void process_object_update(LLMessageSystem *mesgsys, void **user_data) // Update the object... gObjectList.processObjectUpdate(mesgsys, user_data, OUT_FULL); - stop_glerror(); } void process_compressed_object_update(LLMessageSystem *mesgsys, void **user_data) @@ -4322,7 +4311,6 @@ void process_compressed_object_update(LLMessageSystem *mesgsys, void **user_data // Update the object... gObjectList.processCompressedObjectUpdate(mesgsys, user_data, OUT_FULL_COMPRESSED); - stop_glerror(); } void process_cached_object_update(LLMessageSystem *mesgsys, void **user_data) @@ -4340,7 +4328,6 @@ void process_cached_object_update(LLMessageSystem *mesgsys, void **user_data) // Update the object... gObjectList.processCachedObjectUpdate(mesgsys, user_data, OUT_FULL_CACHED); - stop_glerror(); } @@ -4949,7 +4936,7 @@ void process_avatar_sit_response(LLMessageSystem *mesgsys, void **user_data) if (object) { LLVector3 sit_spot = object->getPositionAgent() + (sitPosition * object->getRotation()); - if (!use_autopilot || (avatar && avatar->mIsSitting && avatar->getRoot() == object->getRoot())) + if (!use_autopilot || (avatar && avatar->isSitting() && avatar->getRoot() == object->getRoot())) { //we're already sitting on this object, so don't autopilot } diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index 74a84cd00..3a68d6133 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -4576,7 +4576,11 @@ LLViewerObject::ExtraParameter* LLViewerObject::createNewParameterEntry(U16 para new_block = new LLSculptParams(); break; } - + case LLNetworkData::PARAMS_LIGHT_IMAGE: + { + new_block = new LLLightImageParams(); + break; + } default: { llinfos << "Unknown param type." << llendl; diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h index 4833b96d8..2a08b5f50 100644 --- a/indra/newview/llviewerobject.h +++ b/indra/newview/llviewerobject.h @@ -73,6 +73,7 @@ class LLViewerPartSourceScript; class LLViewerRegion; class LLViewerObjectMedia; class LLVOInventoryListener; +class LLPartSysData; typedef enum e_object_update_type { diff --git a/indra/newview/llviewerobjectbackup.cpp b/indra/newview/llviewerobjectbackup.cpp index c944780af..0ec25719e 100644 --- a/indra/newview/llviewerobjectbackup.cpp +++ b/indra/newview/llviewerobjectbackup.cpp @@ -56,7 +56,7 @@ #include "llagent.h" #include "llappviewer.h" #include "llassetuploadresponders.h" -#include "llfilepicker.h" +#include "statemachine/aifilepicker.h" #include "llfloateranimpreview.h" #include "llfloaterbuycurrency.h" #include "llfloaterimagepreview.h" @@ -341,14 +341,20 @@ void LLObjectBackup::exportObject() mThisGroup.clear(); // Open the file save dialog - LLFilePicker& file_picker = LLFilePicker::instance(); - if (!file_picker.getSaveFile(LLFilePicker::FFSAVE_XML)) + AIFilePicker* filepicker = AIFilePicker::create(); + filepicker->open("", FFSAVE_XML); + filepicker->run(boost::bind(&LLObjectBackup::exportObject_continued, this, filepicker)); +} + +void LLObjectBackup::exportObject_continued(AIFilePicker* filepicker) +{ + if (!filepicker->hasFilename()) { // User canceled save. return; } - mFileName = file_picker.getCurFile(); + mFileName = filepicker->getFilename(); mFolder = gDirUtilp->getDirName(mFileName); mNonExportedTextures = TEXTURE_OK; @@ -733,14 +739,19 @@ void LLObjectBackup::importObject(bool upload) mRetexture = upload; // Open the file open dialog - LLFilePicker& file_picker = LLFilePicker::instance(); - if (!file_picker.getOpenFile(LLFilePicker::FFLOAD_XML)) - { - // User canceled save. - return; - } + AIFilePicker* filepicker = AIFilePicker::create(); + filepicker->open(FFLOAD_XML, "", "import"); + filepicker->run(boost::bind(&LLObjectBackup::importObject_continued, this, filepicker)); - std::string file_name = file_picker.getFirstFile().c_str(); + return; +} + +void LLObjectBackup::importObject_continued(AIFilePicker* filepicker) +{ + if (!filepicker->hasFilename()) + return; + + std::string file_name = filepicker->getFilename(); mFolder = gDirUtilp->getDirName(file_name); llifstream import_file(file_name); LLSDSerialize::fromXML(mLLSD, import_file); @@ -762,7 +773,7 @@ void LLObjectBackup::importObject(bool upload) if (mObjects <= 0) { LLSD args; - args["MESSAGE"] = std::string("Object import failed.\nThe XML file has an incompatble format or does not contain any objects."); + args["MESSAGE"] = std::string("Object import failed.\nThe XML file has an incompatible format or does not contain any objects."); LLNotifications::instance().add("GenericAlert", args); llwarns << "Trying to import illegal XML object file." << llendl; return; diff --git a/indra/newview/llviewerobjectbackup.h b/indra/newview/llviewerobjectbackup.h index 46ca5f916..5ae33c382 100644 --- a/indra/newview/llviewerobjectbackup.h +++ b/indra/newview/llviewerobjectbackup.h @@ -56,9 +56,11 @@ public: // Import entry point void importObject(bool upload=FALSE); + void importObject_continued(AIFilePicker* filepicker); // Export entry point void exportObject(); + void exportObject_continued(AIFilePicker* filepicker); // Update map from texture worker void updateMap(LLUUID uploaded_asset); diff --git a/indra/newview/llviewerobjectlist.cpp b/indra/newview/llviewerobjectlist.cpp index 5e62531d1..94e519604 100644 --- a/indra/newview/llviewerobjectlist.cpp +++ b/indra/newview/llviewerobjectlist.cpp @@ -103,6 +103,7 @@ LLViewerObjectList::LLViewerObjectList() mCurLazyUpdateIndex = 0; mCurBin = 0; mNumDeadObjects = 0; + mMinNumDeadObjects = 20; mNumOrphans = 0; mNumNewObjects = 0; mWasPaused = FALSE; @@ -586,23 +587,27 @@ void LLViewerObjectList::dirtyAllObjectInventory() void LLViewerObjectList::updateApparentAngles(LLAgent &agent) { S32 i; - S32 num_objects = 0; + S32 const objects_size = mObjects.size(); LLViewerObject *objectp; S32 num_updates, max_value; + // The list can have shrinked since mCurLazyUpdateIndex was last updated. + if (mCurLazyUpdateIndex >= objects_size) + { + mCurLazyUpdateIndex = 0; + } if (NUM_BINS - 1 == mCurBin) { - num_updates = (S32) mObjects.size() - mCurLazyUpdateIndex; - max_value = (S32) mObjects.size(); + num_updates = objects_size - mCurLazyUpdateIndex; + max_value = objects_size; gTextureList.setUpdateStats(TRUE); } else { - num_updates = ((S32) mObjects.size() / NUM_BINS) + 1; - max_value = llmin((S32) mObjects.size(), mCurLazyUpdateIndex + num_updates); + num_updates = (objects_size / NUM_BINS) + 1; + max_value = llmin(objects_size, mCurLazyUpdateIndex + num_updates); } - if (!gNoRender) { // Slam priorities for textures that we care about (hovered, selected, and focused) @@ -639,8 +644,6 @@ void LLViewerObjectList::updateApparentAngles(LLAgent &agent) objectp = mObjects[i]; if (!objectp->isDead()) { - num_objects++; - // Update distance & gpw objectp->setPixelAreaAndAngle(agent); // Also sets the approx. pixel area objectp->updateTextures(); // Update the image levels of textures for this object. @@ -648,7 +651,7 @@ void LLViewerObjectList::updateApparentAngles(LLAgent &agent) } mCurLazyUpdateIndex = max_value; - if (mCurLazyUpdateIndex == mObjects.size()) + if (mCurLazyUpdateIndex == objects_size) { mCurLazyUpdateIndex = 0; } @@ -809,7 +812,7 @@ void LLViewerObjectList::update(LLAgent &agent, LLWorld &world) } */ - mNumObjectsStat.addValue((S32) mObjects.size()); + mNumObjectsStat.addValue((S32) mObjects.size() - mNumDeadObjects); mNumActiveObjectsStat.addValue(num_active_objects); mNumSizeCulledStat.addValue(mNumSizeCulled); mNumVisCulledStat.addValue(mNumVisCulled); @@ -819,7 +822,12 @@ void LLViewerObjectList::clearDebugText() { for (vobj_list_t::iterator iter = mObjects.begin(); iter != mObjects.end(); ++iter) { - (*iter)->setDebugText(""); + LLViewerObject *objectp = *iter; + if (objectp->isDead()) + { + continue; + } + objectp->setDebugText(""); } } @@ -949,7 +957,8 @@ void LLViewerObjectList::killAllObjects() objectp = *iter; killObject(objectp); - llassert(objectp->isDead()); + // Object must be dead, or it's the LLVOAvatarSelf which never dies. + llassert((objectp == gAgent.getAvatarObject()) || objectp->isDead()); } cleanDeadObjects(FALSE); @@ -975,34 +984,60 @@ void LLViewerObjectList::killAllObjects() void LLViewerObjectList::cleanDeadObjects(BOOL use_timer) { - if (!mNumDeadObjects) + if (use_timer && mNumDeadObjects < mMinNumDeadObjects) { - // No dead objects, don't need to scan object list. + // Not enough dead objects, don't scan the whole object list until there are a few. + // However, the longer it takes to reach this quota, the less demanding we are, + // so decrease the lower limit but never demand less than 20. + mMinNumDeadObjects = llmax(20, mMinNumDeadObjects - 1); return; } + // If we got this many now, we might as well demand it for the next calls too (they + // tend to come in batches). However, never demand more than 100. + mMinNumDeadObjects = llmin(100, mNumDeadObjects); + // Scan for all of the dead objects and remove any "global" references to them. + + // We first move all dead objects to the end of the std::vector (the swap + // is VERY cheap) and only then call erase once: calling erase on a vector + // is very expensive! + + vobj_list_t::iterator iter = mObjects.begin(); // Runs over all objects. + vobj_list_t::iterator const end = mObjects.end(); + vobj_list_t::iterator last = end; // Points to the last object that is not dead. S32 num_removed = 0; - LLViewerObject *objectp; - for (vobj_list_t::iterator iter = mObjects.begin(); iter != mObjects.end(); ) - { - // Scan for all of the dead objects and remove any "global" references to them. - objectp = *iter; - if (objectp->isDead()) - { - iter = mObjects.erase(iter); - num_removed++; - if (num_removed == mNumDeadObjects) - { - // We've cleaned up all of the dead objects. - break; - } - } - else + // Find the first Dead object. + while (iter != last && !(*iter)->isDead()) + ++iter; + + // While iter did not bumb into last, continue the search. + while (iter != last) + { + // Find the next not Dead object from the end. + do { + --last; + ++num_removed; + } while (last != iter && (*last)->isDead()); + if (iter == last) { - ++iter; + // There no more Dead objects left before last. + break; } + // Swap both object Pointers. + vobj_list_t::value_type::swap(*iter, *last); + if (num_removed == mNumDeadObjects) + { + // There aren't any more dead objects. + break; + } + // Find the next Dead object at the beginning. + do { + ++iter; + } while (iter != last && !(*iter)->isDead()); } + llassert(end - last == num_removed); + mObjects.erase(last, end); // We've cleaned the global object list, now let's do some paranoia testing on objects // before blowing away the dead list. diff --git a/indra/newview/llviewerobjectlist.h b/indra/newview/llviewerobjectlist.h index 43d25229e..f2255d22e 100644 --- a/indra/newview/llviewerobjectlist.h +++ b/indra/newview/llviewerobjectlist.h @@ -190,6 +190,7 @@ public: S32 mNumDeadObjectUpdates; S32 mNumUnknownKills; S32 mNumDeadObjects; + S32 mMinNumDeadObjects; protected: std::vector mOrphanParents; // LocalID/ip,port of orphaned objects std::vector mOrphanChildren; // UUID's of orphaned objects diff --git a/indra/newview/llviewerparcelmedia.h b/indra/newview/llviewerparcelmedia.h index 7531a0f59..50e7aaa2c 100644 --- a/indra/newview/llviewerparcelmedia.h +++ b/indra/newview/llviewerparcelmedia.h @@ -34,6 +34,7 @@ #define LLVIEWERPARCELMEDIA_H #include "llviewermedia.h" +#include "llviewermediaobserver.h" // For use by other patches so they know that media filtering is implemented. #define MEDIA_FILTERING 1 @@ -42,7 +43,6 @@ class LLMessageSystem; class LLParcel; class LLViewerParcelMediaNavigationObserver; - // This class understands land parcels, network traffic, LSL media // transport commands, and talks to the LLViewerMedia class to actually // do playback. It allows us to remove code from LLViewerParcelMgr. diff --git a/indra/newview/llviewerparcelmediaautoplay.h b/indra/newview/llviewerparcelmediaautoplay.h index 16279e7f1..243da2f38 100644 --- a/indra/newview/llviewerparcelmediaautoplay.h +++ b/indra/newview/llviewerparcelmediaautoplay.h @@ -33,7 +33,7 @@ #ifndef LLVIEWERPARCELMEDIAAUTOPLAY_H #define LLVIEWERPARCELMEDIAAUTOPLAY_H -#include "lltimer.h" +#include "lleventtimer.h" // timer to automatically play media class LLViewerParcelMediaAutoPlay : LLEventTimer diff --git a/indra/newview/llviewerpluginmanager.cpp b/indra/newview/llviewerpluginmanager.cpp new file mode 100644 index 000000000..fdd48736e --- /dev/null +++ b/indra/newview/llviewerpluginmanager.cpp @@ -0,0 +1,66 @@ +/** + * @file llviewerpluginmanager.cpp + * @brief Client interface to the plugin engine + * + * $LicenseInfo:firstyear=2007&license=viewergpl$ + * + * Copyright (c) 2007-2010, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" +#include "llviewerpluginmanager.h" +#include "llnotifications.h" + +void LLViewerPluginManager::destroyPlugin() +{ + delete mPluginBase; + mPluginBase = NULL; +} + +void LLViewerPluginManager::update() +{ + if (!mPluginBase) + { + return; + } + + mPluginBase->idle(); + + if (mPluginBase->isPluginExited()) + { + destroyPlugin(); + return; + } +} + +void LLViewerPluginManager::send_plugin_failure_warning(std::string const& plugin_basename) +{ + LL_WARNS("Plugin") << "plugin intialization failed for plugin: " << plugin_basename << LL_ENDL; + LLSD args; + args["MIME_TYPE"] = plugin_basename; // FIXME: Use different notification. + LLNotifications::instance().add("NoPlugin", args); +} + diff --git a/indra/newview/llviewerpluginmanager.h b/indra/newview/llviewerpluginmanager.h new file mode 100644 index 000000000..6525a5403 --- /dev/null +++ b/indra/newview/llviewerpluginmanager.h @@ -0,0 +1,114 @@ +/** + * @file llviewerpluginmanager.h + * @brief Client interface to the plugin engine + * + * $LicenseInfo:firstyear=2007&license=viewergpl$ + * + * Copyright (c) 2007-2010, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LLVIEWERPLUGINMANAGER_H +#define LLVIEWERPLUGINMANAGER_H + +#include +#include "llmemory.h" +#include "llerror.h" +#include "lldir.h" +#include "llfile.h" +#include "llviewercontrol.h" +#include "llpluginclassbasic.h" + +class LLViewerPluginManager : public LLRefCount +{ + LOG_CLASS(LLViewerPluginManager); + +public: + // Construct an uninitialized LLViewerPluginManager object. + LLViewerPluginManager(void) : mPluginBase(NULL) { } + + // Create a PLUGIN_TYPE (must be derived from LLPluginClassBasic). + // This uses PLUGIN_TYPE::launcher_name() and PLUGIN_TYPE::plugin_basename(). + // If successful, returns the created LLPluginClassBasic, NULL otherwise. + template + LLPluginClassBasic* createPlugin(T* user_data); + + // Delete the plugin. + void destroyPlugin(); + + // Handle plugin messages. + virtual void update(); + + // Return pointer to plugin. + LLPluginClassBasic* getPlugin(void) const { return mPluginBase; } + +private: + // Called from createPlugin. + void send_plugin_failure_warning(std::string const& plugin_basename); + +protected: + LLPluginClassBasic* mPluginBase; //!< Pointer to the base class of the underlaying plugin. +}; + +template +LLPluginClassBasic* LLViewerPluginManager::createPlugin(T* user_data) +{ + // Always delete the old plugin first. + destroyPlugin(); + + std::string plugin_name = gDirUtilp->getLLPluginFilename(PLUGIN_TYPE::plugin_basename()); + + // See if the plugin executable exists. + llstat s; + if (LLFile::stat(PLUGIN_TYPE::launcher_name(), &s)) + { + LL_WARNS("Plugin") << "Couldn't find launcher at " << PLUGIN_TYPE::launcher_name() << LL_ENDL; + } + else if (LLFile::stat(plugin_name, &s)) + { + LL_WARNS("Plugin") << "Couldn't find plugin at " << plugin_name << LL_ENDL; + } + else + { + LLPluginClassBasic* plugin = new PLUGIN_TYPE(user_data); + if (plugin->init(PLUGIN_TYPE::launcher_name(), plugin_name, gSavedSettings.getBOOL("PluginAttachDebuggerToPlugins"))) + { + mPluginBase = plugin; + } + else + { + LL_WARNS("Plugin") << "Failed to init plugin. Destroying." << LL_ENDL; + delete plugin; + } + } + + if (mPluginBase) + return mPluginBase; + + send_plugin_failure_warning(PLUGIN_TYPE::plugin_basename()); + return NULL; +} + +#endif // LLVIEWERPLUGINMANAGER_H diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index b3a123eed..3ab4390d7 100644 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -1452,9 +1452,13 @@ void LLViewerRegion::setSeedCapability(const std::string& url) capabilityNames.append("DispatchRegionInfo"); capabilityNames.append("EstateChangeInfo"); capabilityNames.append("EventQueueGet"); - capabilityNames.append("FetchInventory"); - capabilityNames.append("FetchLib"); - capabilityNames.append("FetchLibDescendents"); + if (false)//gSavedSettings.getBOOL("UseHTTPInventory")) //Caps suffixed with 2 by LL. Don't update until rest of fetch system is updated first. + { + capabilityNames.append("FetchLib"); + capabilityNames.append("FetchLibDescendents"); + capabilityNames.append("FetchInventory"); + capabilityNames.append("FetchInventoryDescendents"); + } capabilityNames.append("GetTexture"); capabilityNames.append("GroupProposalBallot"); capabilityNames.append("GetDisplayNames"); @@ -1491,10 +1495,6 @@ void LLViewerRegion::setSeedCapability(const std::string& url) capabilityNames.append("UploadBakedTexture"); capabilityNames.append("ViewerStartAuction"); capabilityNames.append("ViewerStats"); - capabilityNames.append("WebFetchInventoryDescendents"); // OGPX : since this is asking the region - // leave the old naming in place, on agent domain - // it is now called agent/inventory. Both - // caps have the same LLSD returned. // Please add new capabilities alphabetically to reduce // merge conflicts. diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index 00d89e45d..0ab17f6d7 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -79,6 +79,7 @@ LLGLSLShader gObjectFullbrightProgram(LLViewerShaderMgr::SHADER_OBJECT); LLGLSLShader gObjectFullbrightWaterProgram(LLViewerShaderMgr::SHADER_OBJECT); LLGLSLShader gObjectFullbrightShinyProgram(LLViewerShaderMgr::SHADER_OBJECT); +LLGLSLShader gObjectFullbrightShinyWaterProgram(LLViewerShaderMgr::SHADER_OBJECT); LLGLSLShader gObjectShinyProgram(LLViewerShaderMgr::SHADER_OBJECT); LLGLSLShader gObjectShinyWaterProgram(LLViewerShaderMgr::SHADER_OBJECT); @@ -106,6 +107,7 @@ LLGLSLShader gPostGaussianBlurProgram(LLViewerShaderMgr::SHADER_EFFECT); //Not // Deferred rendering shaders LLGLSLShader gDeferredImpostorProgram(LLViewerShaderMgr::SHADER_DEFERRED); +LLGLSLShader gDeferredEdgeProgram(LLViewerShaderMgr::SHADER_DEFERRED); LLGLSLShader gDeferredWaterProgram(LLViewerShaderMgr::SHADER_DEFERRED); //calculatesAtmospherics LLGLSLShader gDeferredDiffuseProgram(LLViewerShaderMgr::SHADER_DEFERRED);//Not in mShaderList LLGLSLShader gDeferredBumpProgram(LLViewerShaderMgr::SHADER_DEFERRED); //Not in mShaderList @@ -115,14 +117,22 @@ LLGLSLShader gDeferredAvatarProgram(LLViewerShaderMgr::SHADER_DEFERRED); //Not LLGLSLShader gDeferredAvatarAlphaProgram(LLViewerShaderMgr::SHADER_DEFERRED); //calculatesAtmospherics LLGLSLShader gDeferredLightProgram(LLViewerShaderMgr::SHADER_DEFERRED); LLGLSLShader gDeferredMultiLightProgram(LLViewerShaderMgr::SHADER_DEFERRED); +LLGLSLShader gDeferredSpotLightProgram(LLViewerShaderMgr::SHADER_DEFERRED); //Not in mShaderList +LLGLSLShader gDeferredMultiSpotLightProgram(LLViewerShaderMgr::SHADER_DEFERRED); //Not in mShaderList LLGLSLShader gDeferredSunProgram(LLViewerShaderMgr::SHADER_DEFERRED); LLGLSLShader gDeferredBlurLightProgram(LLViewerShaderMgr::SHADER_DEFERRED); LLGLSLShader gDeferredSoftenProgram(LLViewerShaderMgr::SHADER_DEFERRED); -LLGLSLShader gDeferredShadowProgram(LLViewerShaderMgr::SHADER_DEFERRED); //Not in mShaderList +LLGLSLShader gDeferredShadowProgram(LLViewerShaderMgr::SHADER_DEFERRED); //Not in mShaderList LLGLSLShader gDeferredAvatarShadowProgram(LLViewerShaderMgr::SHADER_DEFERRED);//Not in mShaderList LLGLSLShader gDeferredAlphaProgram(LLViewerShaderMgr::SHADER_DEFERRED); //calculatesAtmospherics LLGLSLShader gDeferredFullbrightProgram(LLViewerShaderMgr::SHADER_DEFERRED); //calculatesAtmospherics +LLGLSLShader gDeferredGIProgram(LLViewerShaderMgr::SHADER_DEFERRED); +LLGLSLShader gDeferredGIFinalProgram(LLViewerShaderMgr::SHADER_DEFERRED); +LLGLSLShader gDeferredPostGIProgram(LLViewerShaderMgr::SHADER_DEFERRED); +LLGLSLShader gDeferredPostProgram(LLViewerShaderMgr::SHADER_DEFERRED); +LLGLSLShader gDeferredPostNoDoFProgram(LLViewerShaderMgr::SHADER_DEFERRED); +LLGLSLShader gLuminanceGatherProgram(LLViewerShaderMgr::SHADER_DEFERRED); //current avatar shader parameter pointer GLint gAvatarMatrixParam; @@ -154,6 +164,7 @@ void LLViewerShaderMgr::initAttribsAndUniforms(void) mReservedAttribs.push_back("materialColor"); mReservedAttribs.push_back("specularColor"); mReservedAttribs.push_back("binormal"); + mReservedAttribs.push_back("object_weight"); mAvatarAttribs.reserve(5); mAvatarAttribs.push_back("weight"); @@ -195,13 +206,35 @@ void LLViewerShaderMgr::initAttribsAndUniforms(void) mReservedUniforms.push_back("shadowMap1"); mReservedUniforms.push_back("shadowMap2"); mReservedUniforms.push_back("shadowMap3"); + mReservedUniforms.push_back("shadowMap4"); + mReservedUniforms.push_back("shadowMap5"); + mReservedUniforms.push_back("normalMap"); mReservedUniforms.push_back("positionMap"); mReservedUniforms.push_back("diffuseRect"); mReservedUniforms.push_back("specularRect"); mReservedUniforms.push_back("noiseMap"); + mReservedUniforms.push_back("lightFunc"); mReservedUniforms.push_back("lightMap"); - + mReservedUniforms.push_back("luminanceMap"); + mReservedUniforms.push_back("giLightMap"); + mReservedUniforms.push_back("giMip"); + mReservedUniforms.push_back("edgeMap"); + mReservedUniforms.push_back("bloomMap"); + mReservedUniforms.push_back("sunLightMap"); + mReservedUniforms.push_back("localLightMap"); + mReservedUniforms.push_back("projectionMap"); + mReservedUniforms.push_back("diffuseGIMap"); + mReservedUniforms.push_back("specularGIMap"); + mReservedUniforms.push_back("normalGIMap"); + mReservedUniforms.push_back("minpGIMap"); + mReservedUniforms.push_back("maxpGIMap"); + mReservedUniforms.push_back("depthGIMap"); + mReservedUniforms.push_back("lastDiffuseGIMap"); + mReservedUniforms.push_back("lastNormalGIMap"); + mReservedUniforms.push_back("lastMinpGIMap"); + mReservedUniforms.push_back("lastMaxpGIMap"); + mWLUniforms.push_back("camPosLocal"); mTerrainUniforms.reserve(5); @@ -314,7 +347,21 @@ void LLViewerShaderMgr::setShaders() LLFeatureManager::getInstance()->isFeatureAvailable("WindLightUseAtmosShaders") && gSavedSettings.getBOOL("WindLightUseAtmosShaders")) { - deferred_class = 1; + if (gSavedSettings.getS32("RenderShadowDetail") > 0) + { + if (gSavedSettings.getBOOL("RenderDeferredGI")) + { //shadows + gi + deferred_class = 3; + } + else + { //shadows + deferred_class = 2; + } + } + else + { //no shadows + deferred_class = 1; + } //make sure framebuffer objects are enabled gSavedSettings.setBOOL("RenderUseFBO", TRUE); @@ -322,6 +369,8 @@ void LLViewerShaderMgr::setShaders() //make sure hardware skinning is enabled gSavedSettings.setBOOL("RenderAvatarVP", TRUE); } + + if (!(LLFeatureManager::getInstance()->isFeatureAvailable("WindLightUseAtmosShaders") && gSavedSettings.getBOOL("WindLightUseAtmosShaders"))) { @@ -520,7 +569,7 @@ BOOL LLViewerShaderMgr::loadBasicShaders() // (in order of shader function call depth for reference purposes, deepest level first) shaders.clear(); - shaders.reserve(12); + shaders.reserve(13); shaders.push_back( make_pair( "windlight/atmosphericsVarsF.glsl", mVertexShaderLevel[SHADER_WINDLIGHT] ) ); shaders.push_back( make_pair( "windlight/gammaF.glsl", mVertexShaderLevel[SHADER_WINDLIGHT]) ); shaders.push_back( make_pair( "windlight/atmosphericsF.glsl", mVertexShaderLevel[SHADER_WINDLIGHT] ) ); @@ -533,6 +582,7 @@ BOOL LLViewerShaderMgr::loadBasicShaders() shaders.push_back( make_pair( "lighting/lightShinyF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) ); shaders.push_back( make_pair( "lighting/lightFullbrightShinyF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) ); shaders.push_back( make_pair( "lighting/lightShinyWaterF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) ); + shaders.push_back( make_pair( "lighting/lightFullbrightShinyWaterF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) ); for (U32 i = 0; i < shaders.size(); i++) { @@ -829,7 +879,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() { gDeferredMultiLightProgram.mName = "Deferred MultiLight Shader"; gDeferredMultiLightProgram.mShaderFiles.clear(); - gDeferredMultiLightProgram.mShaderFiles.push_back(make_pair("deferred/pointLightV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredMultiLightProgram.mShaderFiles.push_back(make_pair("deferred/multiPointLightV.glsl", GL_VERTEX_SHADER_ARB)); gDeferredMultiLightProgram.mShaderFiles.push_back(make_pair("deferred/multiPointLightF.glsl", GL_FRAGMENT_SHADER_ARB)); gDeferredMultiLightProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; success = gDeferredMultiLightProgram.createShader(NULL, NULL); @@ -837,10 +887,41 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() if (success) { + gDeferredSpotLightProgram.mName = "Deferred SpotLight Shader"; + gDeferredSpotLightProgram.mShaderFiles.clear(); + gDeferredSpotLightProgram.mShaderFiles.push_back(make_pair("deferred/pointLightV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredSpotLightProgram.mShaderFiles.push_back(make_pair("deferred/multiSpotLightF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredSpotLightProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + success = gDeferredSpotLightProgram.createShader(NULL, NULL); + } + + if (success) + { + gDeferredMultiSpotLightProgram.mName = "Deferred MultiSpotLight Shader"; + gDeferredMultiSpotLightProgram.mShaderFiles.clear(); + gDeferredMultiSpotLightProgram.mShaderFiles.push_back(make_pair("deferred/pointLightV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredMultiSpotLightProgram.mShaderFiles.push_back(make_pair("deferred/multiSpotLightF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredMultiSpotLightProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + success = gDeferredMultiSpotLightProgram.createShader(NULL, NULL); + } + + if (success) + { + std::string fragment; + + if (gSavedSettings.getBOOL("RenderDeferredSSAO")) + { + fragment = "deferred/sunLightSSAOF.glsl"; + } + else + { + fragment = "deferred/sunLightF.glsl"; + } + gDeferredSunProgram.mName = "Deferred Sun Shader"; gDeferredSunProgram.mShaderFiles.clear(); gDeferredSunProgram.mShaderFiles.push_back(make_pair("deferred/sunLightV.glsl", GL_VERTEX_SHADER_ARB)); - gDeferredSunProgram.mShaderFiles.push_back(make_pair("deferred/sunLightF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredSunProgram.mShaderFiles.push_back(make_pair(fragment, GL_FRAGMENT_SHADER_ARB)); gDeferredSunProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; success = gDeferredSunProgram.createShader(NULL, NULL); } @@ -900,10 +981,21 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() if (success) { + std::string fragment; + + if (mVertexShaderLevel[SHADER_DEFERRED] < 2 && !gSavedSettings.getBOOL("RenderDeferredSSAO")) + { + fragment = "deferred/softenLightNoSSAOF.glsl"; + } + else + { + fragment = "deferred/softenLightF.glsl"; + } + gDeferredSoftenProgram.mName = "Deferred Soften Shader"; gDeferredSoftenProgram.mShaderFiles.clear(); gDeferredSoftenProgram.mShaderFiles.push_back(make_pair("deferred/softenLightV.glsl", GL_VERTEX_SHADER_ARB)); - gDeferredSoftenProgram.mShaderFiles.push_back(make_pair("deferred/softenLightF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredSoftenProgram.mShaderFiles.push_back(make_pair(fragment, GL_FRAGMENT_SHADER_ARB)); gDeferredSoftenProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; success = gDeferredSoftenProgram.createShader(NULL, NULL); } @@ -961,11 +1053,97 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredAvatarAlphaProgram.mFeatures.hasLighting = true; gDeferredAvatarAlphaProgram.mShaderFiles.clear(); gDeferredAvatarAlphaProgram.mShaderFiles.push_back(make_pair("deferred/avatarAlphaV.glsl", GL_VERTEX_SHADER_ARB)); - gDeferredAvatarAlphaProgram.mShaderFiles.push_back(make_pair("deferred/avatarAlphaF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredAvatarAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaF.glsl", GL_FRAGMENT_SHADER_ARB)); gDeferredAvatarAlphaProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; success = gDeferredAvatarAlphaProgram.createShader(&mAvatarAttribs, &mAvatarUniforms); } + if (success) + { + gDeferredPostProgram.mName = "Deferred Post Shader"; + gDeferredPostProgram.mShaderFiles.clear(); + gDeferredPostProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredPostProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredPostProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + success = gDeferredPostProgram.createShader(NULL, NULL); + } + + if (success) + { + gDeferredPostNoDoFProgram.mName = "Deferred Post Shader"; + gDeferredPostNoDoFProgram.mShaderFiles.clear(); + gDeferredPostNoDoFProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredPostNoDoFProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredNoDoFF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredPostNoDoFProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + success = gDeferredPostNoDoFProgram.createShader(NULL, NULL); + } + + if (mVertexShaderLevel[SHADER_DEFERRED] > 1) + { + if (success) + { + gDeferredEdgeProgram.mName = "Deferred Edge Shader"; + gDeferredEdgeProgram.mShaderFiles.clear(); + gDeferredEdgeProgram.mShaderFiles.push_back(make_pair("deferred/edgeV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredEdgeProgram.mShaderFiles.push_back(make_pair("deferred/edgeF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredEdgeProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + success = gDeferredEdgeProgram.createShader(NULL, NULL); + } + } + + if (mVertexShaderLevel[SHADER_DEFERRED] > 2) + { + if (success) + { + gDeferredPostProgram.mName = "Deferred Post Shader"; + gDeferredPostProgram.mShaderFiles.clear(); + gDeferredPostProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredPostProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredPostProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + success = gDeferredPostProgram.createShader(NULL, NULL); + } + + if (success) + { + gDeferredPostGIProgram.mName = "Deferred Post GI Shader"; + gDeferredPostGIProgram.mShaderFiles.clear(); + gDeferredPostGIProgram.mShaderFiles.push_back(make_pair("deferred/postgiV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredPostGIProgram.mShaderFiles.push_back(make_pair("deferred/postgiF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredPostGIProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + success = gDeferredPostGIProgram.createShader(NULL, NULL); + } + + if (success) + { + gDeferredGIProgram.mName = "Deferred GI Shader"; + gDeferredGIProgram.mShaderFiles.clear(); + gDeferredGIProgram.mShaderFiles.push_back(make_pair("deferred/giV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredGIProgram.mShaderFiles.push_back(make_pair("deferred/giF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredGIProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + success = gDeferredGIProgram.createShader(NULL, NULL); + } + + if (success) + { + gDeferredGIFinalProgram.mName = "Deferred GI Final Shader"; + gDeferredGIFinalProgram.mShaderFiles.clear(); + gDeferredGIFinalProgram.mShaderFiles.push_back(make_pair("deferred/giFinalV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredGIFinalProgram.mShaderFiles.push_back(make_pair("deferred/giFinalF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredGIFinalProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + success = gDeferredGIFinalProgram.createShader(NULL, NULL); + } + + if (success) + { + gLuminanceGatherProgram.mName = "Luminance Gather Shader"; + gLuminanceGatherProgram.mShaderFiles.clear(); + gLuminanceGatherProgram.mShaderFiles.push_back(make_pair("deferred/luminanceV.glsl", GL_VERTEX_SHADER_ARB)); + gLuminanceGatherProgram.mShaderFiles.push_back(make_pair("deferred/luminanceF.glsl", GL_FRAGMENT_SHADER_ARB)); + gLuminanceGatherProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + success = gLuminanceGatherProgram.createShader(NULL, NULL); + } + } + return success; } @@ -1085,6 +1263,22 @@ BOOL LLViewerShaderMgr::loadShadersObject() success = gObjectFullbrightShinyProgram.createShader(NULL, &mShinyUniforms); } + if (success) + { + gObjectFullbrightShinyWaterProgram.mName = "Fullbright Shiny Water Shader"; + gObjectFullbrightShinyWaterProgram.mFeatures.calculatesAtmospherics = true; + gObjectFullbrightShinyWaterProgram.mFeatures.isFullbright = true; + gObjectFullbrightShinyWaterProgram.mFeatures.isShiny = true; + gObjectFullbrightShinyWaterProgram.mFeatures.hasGamma = true; + gObjectFullbrightShinyWaterProgram.mFeatures.hasTransport = true; + gObjectFullbrightShinyWaterProgram.mFeatures.hasWaterFog = true; + gObjectFullbrightShinyWaterProgram.mShaderFiles.clear(); + gObjectFullbrightShinyWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyV.glsl", GL_VERTEX_SHADER_ARB)); + gObjectFullbrightShinyWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); + gObjectFullbrightShinyWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; + gObjectFullbrightShinyWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; + success = gObjectFullbrightShinyWaterProgram.createShader(NULL, &mShinyUniforms); + } if( !success ) { diff --git a/indra/newview/llviewershadermgr.h b/indra/newview/llviewershadermgr.h index 8fa582909..f952b1a6f 100644 --- a/indra/newview/llviewershadermgr.h +++ b/indra/newview/llviewershadermgr.h @@ -82,6 +82,7 @@ public: MATERIAL_COLOR = 0, SPECULAR_COLOR, BINORMAL, + OBJECT_WEIGHT, END_RESERVED_ATTRIBS } eGLSLReservedAttribs; @@ -116,12 +117,33 @@ public: DEFERRED_SHADOW1, DEFERRED_SHADOW2, DEFERRED_SHADOW3, + DEFERRED_SHADOW4, + DEFERRED_SHADOW5, DEFERRED_NORMAL, DEFERRED_POSITION, DEFERRED_DIFFUSE, DEFERRED_SPECULAR, DEFERRED_NOISE, + DEFERRED_LIGHTFUNC, DEFERRED_LIGHT, + DEFERRED_LUMINANCE, + DEFERRED_GI_LIGHT, + DEFERRED_GI_MIP, + DEFERRED_EDGE, + DEFERRED_BLOOM, + DEFERRED_SUN_LIGHT, + DEFERRED_LOCAL_LIGHT, + DEFERRED_PROJECTION, + DEFERRED_GI_DIFFUSE, + DEFERRED_GI_SPECULAR, + DEFERRED_GI_NORMAL, + DEFERRED_GI_MIN_POS, + DEFERRED_GI_MAX_POS, + DEFERRED_GI_DEPTH, + DEFERRED_GI_LAST_DIFFUSE, + DEFERRED_GI_LAST_NORMAL, + DEFERRED_GI_LAST_MIN_POS, + DEFERRED_GI_LAST_MAX_POS, END_RESERVED_UNIFORMS } eGLSLReservedUniforms; @@ -293,6 +315,7 @@ extern LLGLSLShader gObjectSimpleLODProgram; extern LLGLSLShader gObjectFullbrightLODProgram; extern LLGLSLShader gObjectFullbrightShinyProgram; +extern LLGLSLShader gObjectFullbrightShinyWaterProgram; extern LLGLSLShader gObjectShinyProgram; extern LLGLSLShader gObjectShinyWaterProgram; @@ -324,6 +347,7 @@ extern LLGLSLShader gPostGaussianBlurProgram; // Deferred rendering shaders extern LLGLSLShader gDeferredImpostorProgram; +extern LLGLSLShader gDeferredEdgeProgram; extern LLGLSLShader gDeferredWaterProgram; extern LLGLSLShader gDeferredDiffuseProgram; extern LLGLSLShader gDeferredBumpProgram; @@ -331,16 +355,25 @@ extern LLGLSLShader gDeferredTerrainProgram; extern LLGLSLShader gDeferredTreeProgram; extern LLGLSLShader gDeferredLightProgram; extern LLGLSLShader gDeferredMultiLightProgram; +extern LLGLSLShader gDeferredSpotLightProgram; +extern LLGLSLShader gDeferredMultiSpotLightProgram; extern LLGLSLShader gDeferredSunProgram; +extern LLGLSLShader gDeferredGIProgram; +extern LLGLSLShader gDeferredGIFinalProgram; extern LLGLSLShader gDeferredBlurLightProgram; extern LLGLSLShader gDeferredAvatarProgram; extern LLGLSLShader gDeferredSoftenProgram; extern LLGLSLShader gDeferredShadowProgram; +extern LLGLSLShader gDeferredPostGIProgram; +extern LLGLSLShader gDeferredPostProgram; +extern LLGLSLShader gDeferredPostNoDoFProgram; extern LLGLSLShader gDeferredAvatarShadowProgram; extern LLGLSLShader gDeferredAlphaProgram; extern LLGLSLShader gDeferredFullbrightProgram; extern LLGLSLShader gDeferredAvatarAlphaProgram; +extern LLGLSLShader gLuminanceGatherProgram; + //current avatar shader parameter pointer extern GLint gAvatarMatrixParam; diff --git a/indra/newview/llviewerstats.cpp b/indra/newview/llviewerstats.cpp index 5c1b22fa6..997a393ff 100644 --- a/indra/newview/llviewerstats.cpp +++ b/indra/newview/llviewerstats.cpp @@ -531,7 +531,7 @@ void update_statistics(U32 frame_count) } } LLViewerStats::getInstance()->setStat(LLViewerStats::ST_ENABLE_VBO, (F64)gSavedSettings.getBOOL("RenderVBOEnable")); - LLViewerStats::getInstance()->setStat(LLViewerStats::ST_LIGHTING_DETAIL, (F64)gSavedSettings.getS32("RenderLightingDetail")); + //LLViewerStats::getInstance()->setStat(LLViewerStats::ST_LIGHTING_DETAIL, (F64)gSavedSettings.getS32("RenderLightingDetail")); LLViewerStats::getInstance()->setStat(LLViewerStats::ST_DRAW_DIST, (F64)gSavedSettings.getF32("RenderFarClip")); LLViewerStats::getInstance()->setStat(LLViewerStats::ST_CHAT_BUBBLES, (F64)gSavedSettings.getBOOL("UseChatBubbles")); #if 0 // 1.9.2 diff --git a/indra/newview/llviewertexteditor.cpp b/indra/newview/llviewertexteditor.cpp index 2055f54b2..a2baf176e 100644 --- a/indra/newview/llviewertexteditor.cpp +++ b/indra/newview/llviewertexteditor.cpp @@ -416,6 +416,7 @@ void LLEmbeddedItems::bindEmbeddedChars( const LLFontGL* font ) const break; case LLAssetType::AT_SOUND: img_name = "inv_item_sound.tga"; break; + case LLAssetType::AT_CALLINGCARD: img_name = "inv_item_callingcard_online.tga"; break; case LLAssetType::AT_LANDMARK: if (item->getFlags() & LLInventoryItemFlags::II_FLAGS_LANDMARK_VISITED) { diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index e818cd514..d1c3a40f2 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -2681,7 +2681,12 @@ void LLViewerFetchedTexture::setCachedRawImage() { --i ; } - + if (mRawImage->getComponents() == 5) + { + llwarns << "IMP-582: Trying to scale an image (" << mID << ") with 5 components!" << llendl; + mIsRawImageValid = 0; + return; + } mRawImage->scale(w >> i, h >> i) ; } if(mCachedRawImage.notNull()) @@ -2716,6 +2721,13 @@ void LLViewerFetchedTexture::saveRawImage() return ; } + // This shouldn't happen, but it did on Snowglobe 1.5. Better safe than sorry? + if (!mRawImage->getData()) + { + llwarns << "mRawImage->getData() returns NULL" << llendl; + return; + } + mSavedRawDiscardLevel = mRawDiscardLevel ; mSavedRawImage = new LLImageRaw(mRawImage->getData(), mRawImage->getWidth(), mRawImage->getHeight(), mRawImage->getComponents()) ; diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index a82fdb3d5..6b633b523 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -89,7 +89,7 @@ #include "llmaniptranslate.h" #include "llface.h" #include "llfeaturemanager.h" -#include "llfilepicker.h" +#include "statemachine/aifilepicker.h" #include "llfloater.h" #include "llfloateractivespeakers.h" #include "llfloaterbuildoptions.h" @@ -522,8 +522,8 @@ public: ypos += y_inc; } // only display these messages if we are actually rendering beacons at this moment - static const LLCachedControl beacon_always_on("BeaconAlwaysOn",false); - if (LLPipeline::getRenderBeacons(NULL) && beacon_always_on) + static const LLCachedControl beacons_visible("BeaconsVisible",false); + if (LLPipeline::getRenderBeacons(NULL) && beacons_visible) { if (LLPipeline::getRenderParticleBeacons(NULL)) { @@ -553,7 +553,7 @@ public: } if (LLPipeline::getRenderSoundBeacons(NULL)) { - addText(xpos, ypos, "Viewing sound beacons (yellow)"); + addText(xpos, ypos, "Viewing sound beacons (blue/cyan/green/yellow/red)"); ypos += y_inc; } } @@ -3385,7 +3385,7 @@ void LLViewerWindow::renderSelections( BOOL for_gl_pick, BOOL pick_parcel_walls, ((gRlvHandler.hasBehaviour(RLV_BHVR_UNSIT)) || (gRlvHandler.hasBehaviour(RLV_BHVR_SITTP))) ) { LLVOAvatar* pAvatar = gAgent.getAvatarObject(); - if ( (pAvatar) && (pAvatar->mIsSitting) && (pAvatar->getRoot() == object->getRootEdit()) ) + if ( (pAvatar) && (pAvatar->isSitting()) && (pAvatar->getRoot() == object->getRootEdit()) ) moveable_object_selected = this_object_movable = FALSE; } // [/RLVa:KB] @@ -3988,50 +3988,62 @@ BOOL LLViewerWindow::mousePointOnLandGlobal(const S32 x, const S32 y, LLVector3d } // Saves an image to the harddrive as "SnapshotX" where X >= 1. -BOOL LLViewerWindow::saveImageNumbered(LLImageFormatted *image) +void LLViewerWindow::saveImageNumbered(LLPointer image) { if (!image) { - return FALSE; + return; } - LLFilePicker::ESaveFilter pick_type; + ESaveFilter pick_type; std::string extension("." + image->getExtension()); if (extension == ".j2c") - pick_type = LLFilePicker::FFSAVE_J2C; + pick_type = FFSAVE_J2C; else if (extension == ".bmp") - pick_type = LLFilePicker::FFSAVE_BMP; + pick_type = FFSAVE_BMP; else if (extension == ".jpg") - pick_type = LLFilePicker::FFSAVE_JPEG; + pick_type = FFSAVE_JPEG; else if (extension == ".png") - pick_type = LLFilePicker::FFSAVE_PNG; + pick_type = FFSAVE_PNG; else if (extension == ".tga") - pick_type = LLFilePicker::FFSAVE_TGA; + pick_type = FFSAVE_TGA; else - pick_type = LLFilePicker::FFSAVE_ALL; // ??? + pick_type = FFSAVE_ALL; // ??? // Get a base file location if needed. if ( ! isSnapshotLocSet()) { std::string proposed_name( sSnapshotBaseName ); - // getSaveFile will append an appropriate extension to the proposed name, based on the ESaveFilter constant passed in. + // AIFilePicker will append an appropriate extension to the proposed name, based on the ESaveFilter constant passed in. // pick a directory in which to save - LLFilePicker& picker = LLFilePicker::instance(); - if (!picker.getSaveFile(pick_type, proposed_name)) - { - // Clicked cancel - return FALSE; - } + AIFilePicker* filepicker = AIFilePicker::create(); // Deleted in LLViewerWindow::saveImageNumbered_continued1 + filepicker->open(proposed_name, pick_type, "", "snapshot"); + filepicker->run(boost::bind(&LLViewerWindow::saveImageNumbered_continued1, this, image, extension, filepicker)); + return; + } + // LLViewerWindow::sSnapshotBaseName and LLViewerWindow::sSnapshotDir already known. Go straight to saveImageNumbered_continued2. + saveImageNumbered_continued2(image, extension); +} + +void LLViewerWindow::saveImageNumbered_continued1(LLPointer image, std::string const& extension, AIFilePicker* filepicker) +{ + if (filepicker->hasFilename()) + { // Copy the directory + file name - std::string filepath = picker.getFirstFile(); + std::string filepath = filepicker->getFilename(); LLViewerWindow::sSnapshotBaseName = gDirUtilp->getBaseFileName(filepath, true); LLViewerWindow::sSnapshotDir = gDirUtilp->getDirName(filepath); - } + saveImageNumbered_continued2(image, extension); + } +} + +void LLViewerWindow::saveImageNumbered_continued2(LLPointer image, std::string const& extension) +{ // Look for an unused file name std::string filepath; S32 i = 1; @@ -4051,7 +4063,10 @@ BOOL LLViewerWindow::saveImageNumbered(LLImageFormatted *image) } while( -1 != err ); // search until the file is not found (i.e., stat() gives an error). - return image->save(filepath); + if (image->save(filepath)) + { + playSnapshotAnimAndSound(); + } } void LLViewerWindow::resetSnapshotLoc() @@ -4329,6 +4344,21 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei image_width *= internal_scale; #endif //shy_mod + //Hack until hud ui works in high-res shots again (nameplates and hud attachments are buggered). + if ((image_width > window_width || image_height > window_height)) + { + if(LLPipeline::sShowHUDAttachments) + { + hide_hud=true; + LLPipeline::sShowHUDAttachments = FALSE; + } + if(show_ui) + { + show_ui=false; + LLPipeline::toggleRenderDebugFeature((void*)LLPipeline::RENDER_DEBUG_FEATURE_UI); + } + } + if(!keep_window_aspect) //image cropping { F32 ratio = llmin( (F32)window_width / image_width , (F32)window_height / image_height) ; @@ -4520,7 +4550,7 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei gDepthDirty = TRUE; // POST SNAPSHOT - if (!gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI)) + if (prev_draw_ui != gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI)) { LLPipeline::toggleRenderDebugFeature((void*)LLPipeline::RENDER_DEBUG_FEATURE_UI); } diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h index 21867f7eb..dec5a177c 100644 --- a/indra/newview/llviewerwindow.h +++ b/indra/newview/llviewerwindow.h @@ -60,6 +60,7 @@ class LLTextBox; class LLImageRaw; class LLHUDIcon; class LLMouseHandler; +class AIFilePicker; #define PICK_HALF_WIDTH 5 #define PICK_DIAMETER (2 * PICK_HALF_WIDTH + 1) @@ -282,19 +283,21 @@ public: // snapshot functionality. // perhaps some of this should move to llfloatershapshot? -MG - typedef enum e_snapshot_type + enum ESnapshotType { SNAPSHOT_TYPE_COLOR, SNAPSHOT_TYPE_DEPTH, SNAPSHOT_TYPE_OBJECT_ID - } ESnapshotType; + }; BOOL saveSnapshot(const std::string& filename, S32 image_width, S32 image_height, BOOL show_ui = TRUE, BOOL do_rebuild = FALSE, ESnapshotType type = SNAPSHOT_TYPE_COLOR); BOOL rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_height, BOOL keep_window_aspect = TRUE, BOOL is_texture = FALSE, BOOL show_ui = TRUE, BOOL do_rebuild = FALSE, ESnapshotType type = SNAPSHOT_TYPE_COLOR, S32 max_size = MAX_SNAPSHOT_IMAGE_SIZE, F32 supersample = 1.f ); BOOL thumbnailSnapshot(LLImageRaw *raw, S32 preview_width, S32 preview_height, BOOL show_ui, BOOL do_rebuild, ESnapshotType type) ; BOOL isSnapshotLocSet() const { return ! sSnapshotDir.empty(); } void resetSnapshotLoc() const { sSnapshotDir.clear(); } - BOOL saveImageNumbered(LLImageFormatted *image); + void saveImageNumbered(LLPointer image); + void saveImageNumbered_continued1(LLPointer image, std::string const& extension, AIFilePicker* filepicker); + void saveImageNumbered_continued2(LLPointer image, std::string const& extension); // Reset the directory where snapshots are saved. // Client will open directory picker on next snapshot save. diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 85d0e5f4c..4f2b44210 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -168,7 +168,7 @@ const S32 MIN_REQUIRED_PIXEL_AREA_PELVIS_FIX = 40; const S32 TEX_IMAGE_SIZE_SELF = 512; const S32 TEX_IMAGE_AREA_SELF = TEX_IMAGE_SIZE_SELF * TEX_IMAGE_SIZE_SELF; -const S32 TEX_IMAGE_SIZE_OTHER = TEX_IMAGE_SIZE_SELF / 4; // The size of local textures for other (!mIsSelf) avatars +const S32 TEX_IMAGE_SIZE_OTHER = TEX_IMAGE_SIZE_SELF / 4; // The size of local textures for other (!isSelf()) avatars const S32 TEX_IMAGE_AREA_OTHER = TEX_IMAGE_SIZE_OTHER * TEX_IMAGE_SIZE_OTHER; const F32 HEAD_MOVEMENT_AVG_TIME = 0.9f; @@ -229,7 +229,7 @@ struct LLTextureMaskData /********************************************************************************* ** ** - ** Begin LLVOAvatar Support classes + ** Begin private LLVOAvatar Support classes ** **/ @@ -285,85 +285,6 @@ private: bone_info_list_t mBoneInfoList; }; - -//------------------------------------------------------------------------ -// LLVOAvatarXmlInfo -// One instance (in LLVOAvatar) with common data parsed from the XML files -//------------------------------------------------------------------------ -class LLVOAvatarXmlInfo -{ - friend class LLVOAvatar; -public: - LLVOAvatarXmlInfo(); - ~LLVOAvatarXmlInfo(); - -private: - BOOL parseXmlSkeletonNode(LLXmlTreeNode* root); - BOOL parseXmlMeshNodes(LLXmlTreeNode* root); - BOOL parseXmlColorNodes(LLXmlTreeNode* root); - BOOL parseXmlLayerNodes(LLXmlTreeNode* root); - BOOL parseXmlDriverNodes(LLXmlTreeNode* root); - - struct LLVOAvatarMeshInfo - { - typedef std::pair morph_info_pair_t; - typedef std::vector morph_info_list_t; - - LLVOAvatarMeshInfo() : mLOD(0), mMinPixelArea(.1f) {} - ~LLVOAvatarMeshInfo() - { - morph_info_list_t::iterator iter; - for (iter = mPolyMorphTargetInfoList.begin(); iter != mPolyMorphTargetInfoList.end(); iter++) - { - delete iter->first; - } - mPolyMorphTargetInfoList.clear(); - } - - std::string mType; - S32 mLOD; - std::string mMeshFileName; - std::string mReferenceMeshName; - F32 mMinPixelArea; - morph_info_list_t mPolyMorphTargetInfoList; - }; - typedef std::vector mesh_info_list_t; - mesh_info_list_t mMeshInfoList; - - typedef std::vector skeletal_distortion_info_list_t; - skeletal_distortion_info_list_t mSkeletalDistortionInfoList; - - struct LLVOAvatarAttachmentInfo - { - LLVOAvatarAttachmentInfo() - : mGroup(-1), mAttachmentID(-1), mPieMenuSlice(-1), mVisibleFirstPerson(FALSE), - mIsHUDAttachment(FALSE), mHasPosition(FALSE), mHasRotation(FALSE) {} - std::string mName; - std::string mJointName; - LLVector3 mPosition; - LLVector3 mRotationEuler; - S32 mGroup; - S32 mAttachmentID; - S32 mPieMenuSlice; - BOOL mVisibleFirstPerson; - BOOL mIsHUDAttachment; - BOOL mHasPosition; - BOOL mHasRotation; - }; - typedef std::vector attachment_info_list_t; - attachment_info_list_t mAttachmentInfoList; - - LLTexGlobalColorInfo *mTexSkinColorInfo; - LLTexGlobalColorInfo *mTexHairColorInfo; - LLTexGlobalColorInfo *mTexEyeColorInfo; - - typedef std::vector layer_info_list_t; - layer_info_list_t mLayerInfoList; - - typedef std::vector driver_info_list_t; - driver_info_list_t mDriverInfoList; -}; - //----------------------------------------------------------------------------- // class LLBodyNoiseMotion //----------------------------------------------------------------------------- @@ -689,10 +610,10 @@ LLXmlTree LLVOAvatar::sXMLTree; LLXmlTree LLVOAvatar::sSkeletonXMLTree; BOOL LLVOAvatar::sDebugAvatarRotation = FALSE; LLVOAvatarSkeletonInfo* LLVOAvatar::sAvatarSkeletonInfo = NULL; -LLVOAvatarXmlInfo* LLVOAvatar::sAvatarXmlInfo = NULL; +LLVOAvatar::LLVOAvatarXmlInfo* LLVOAvatar::sAvatarXmlInfo = NULL; LLVOAvatarDictionary *LLVOAvatar::sAvatarDictionary = NULL; S32 LLVOAvatar::sFreezeCounter = 0; -S32 LLVOAvatar::sMaxVisible = 50; +U32 LLVOAvatar::sMaxVisible = 50; LLMap< LLGLenum, LLGLuint*> LLVOAvatar::sScratchTexNames; LLMap< LLGLenum, F32*> LLVOAvatar::sScratchTexLastBindTime; S32 LLVOAvatar::sScratchTexBytes = 0; @@ -716,7 +637,7 @@ const LLUUID LLVOAvatar::sStepSounds[LL_MCODE_END] = }; S32 LLVOAvatar::sRenderName = RENDER_NAME_ALWAYS; -BOOL LLVOAvatar::sRenderGroupTitles = TRUE; +bool LLVOAvatar::sRenderGroupTitles = true; S32 LLVOAvatar::sNumVisibleChatBubbles = 0; BOOL LLVOAvatar::sDebugInvisible = FALSE; BOOL LLVOAvatar::sShowAttachmentPoints = FALSE; @@ -729,10 +650,6 @@ BOOL LLVOAvatar::sUseImpostors = FALSE; BOOL LLVOAvatar::sJointDebug = FALSE; EmeraldGlobalBoobConfig LLVOAvatar::sBoobConfig; - -F32 LLVOAvatar::sAvMorphTime = 0.65f; - - F32 LLVOAvatar::sUnbakedTime = 0.f; F32 LLVOAvatar::sUnbakedUpdateTime = 0.f; F32 LLVOAvatar::sGreyTime = 0.f; @@ -771,17 +688,17 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id, mAppearanceAnimating(FALSE), mNameString(), mTitle(), - mNameAway(FALSE), - mNameBusy(FALSE), - mNameMute(FALSE), - mNameAppearance(FALSE), + mNameAway(false), + mNameBusy(false), + mNameMute(false), + mNameAppearance(false), mRenderedName(), mUsedNameSystem(), mClientName(), mRenderGroupTitles(sRenderGroupTitles), mNameFromChatOverride(false), mNameFromChatChanged(false), - mRenderTag(FALSE), + mRenderTag(false), mLastRegionHandle(0), mRegionCrossingCount(0), mFirstTEMessageReceived( FALSE ), @@ -827,15 +744,15 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id, } } - mBakedTextureData.resize(BAKED_NUM_INDICES); - for (U32 i = 0; i < mBakedTextureData.size(); i++ ) + mBakedTextureDatas.resize(BAKED_NUM_INDICES); + for (U32 i = 0; i < mBakedTextureDatas.size(); i++ ) { - mBakedTextureData[i].mLastTextureIndex = IMG_DEFAULT_AVATAR; - mBakedTextureData[i].mTexLayerSet = NULL; - mBakedTextureData[i].mIsLoaded = false; - mBakedTextureData[i].mIsUsed = false; - mBakedTextureData[i].mMaskTexName = 0; - mBakedTextureData[i].mTextureIndex = getTextureIndex((EBakedTextureIndex)i); + mBakedTextureDatas[i].mLastTextureIndex = IMG_DEFAULT_AVATAR; + mBakedTextureDatas[i].mTexLayerSet = NULL; + mBakedTextureDatas[i].mIsLoaded = false; + mBakedTextureDatas[i].mIsUsed = false; + mBakedTextureDatas[i].mMaskTexName = 0; + mBakedTextureDatas[i].mTextureIndex = getTextureIndex((EBakedTextureIndex)i); } mDirtyMesh = 2; // Dirty geometry, need to regenerate. @@ -970,7 +887,7 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id, iter != mMeshLOD[mesh_index]->mMeshParts.end(); iter++) { LLViewerJointMesh* mesh = (LLViewerJointMesh*) *iter; - mBakedTextureData[(int)baked_texture_index].mMeshes.push_back(mesh); + mBakedTextureDatas[(int)baked_texture_index].mMeshes.push_back(mesh); } } @@ -1078,7 +995,7 @@ LLVOAvatar::~LLVOAvatar() { lldebugs << "LLVOAvatar Destructor (0x" << this << ") id:" << mID << llendl; - if (mIsSelf) + if (isSelf()) { gAgent.setAvatarObject(NULL); } @@ -1097,10 +1014,10 @@ LLVOAvatar::~LLVOAvatar() mNumJoints = 0; - for (U32 i = 0; i < mBakedTextureData.size(); i++) + for (U32 i = 0; i < mBakedTextureDatas.size(); i++) { - delete mBakedTextureData[i].mTexLayerSet; - mBakedTextureData[i].mTexLayerSet = NULL; + delete mBakedTextureDatas[i].mTexLayerSet; + mBakedTextureDatas[i].mTexLayerSet = NULL; } std::for_each(mAttachmentPoints.begin(), mAttachmentPoints.end(), DeletePairedPointer()); @@ -1115,9 +1032,10 @@ LLVOAvatar::~LLVOAvatar() std::for_each(mMeshes.begin(), mMeshes.end(), DeletePairedPointer()); mMeshes.clear(); - std::vector::iterator jointIter; - for (jointIter = mMeshLOD.begin(); - jointIter != mMeshLOD.end(); jointIter++) + + for (std::vector::iterator jointIter = mMeshLOD.begin(); + jointIter != mMeshLOD.end(); + ++jointIter) { LLViewerJoint* joint = (LLViewerJoint *) *jointIter; std::for_each(joint->mMeshParts.begin(), joint->mMeshParts.end(), DeletePointer()); @@ -1144,7 +1062,6 @@ void LLVOAvatar::markDead() mNameText = NULL; sNumVisibleChatBubbles--; } - mVoiceVisualizer->markDead(); mBeam = NULL; @@ -1157,9 +1074,9 @@ BOOL LLVOAvatar::isFullyBaked() if (mIsDummy) return TRUE; if (getNumTEs() == 0) return FALSE; - for (U32 i = 0; i < mBakedTextureData.size(); i++) + for (U32 i = 0; i < mBakedTextureDatas.size(); i++) { - if (!isTextureDefined(mBakedTextureData[i].mTextureIndex) + if (!isTextureDefined(mBakedTextureDatas[i].mTextureIndex) && ( (i != BAKED_SKIRT) || isWearingWearableType(WT_SKIRT) ) ) { return FALSE; @@ -1170,19 +1087,21 @@ BOOL LLVOAvatar::isFullyBaked() void LLVOAvatar::deleteLayerSetCaches(bool clearAll) { - for (U32 i = 0; i < mBakedTextureData.size(); i++) + for (U32 i = 0; i < mBakedTextureDatas.size(); i++) { - if (mBakedTextureData[i].mTexLayerSet) + if (mBakedTextureDatas[i].mTexLayerSet) { - if ((i != BAKED_HAIR || mIsSelf) && !clearAll) // Backwards compatibility - can be removed after hair baking is mandatory on the grid + // ! BACKWARDS COMPATIBILITY ! + // Can be removed after hair baking is mandatory on the grid + if ((i != BAKED_HAIR || isSelf()) && !clearAll) { - mBakedTextureData[i].mTexLayerSet->deleteCaches(); + mBakedTextureDatas[i].mTexLayerSet->deleteCaches(); } } - if (mBakedTextureData[i].mMaskTexName) + if (mBakedTextureDatas[i].mMaskTexName) { - glDeleteTextures(1, (GLuint*)&(mBakedTextureData[i].mMaskTexName)); - mBakedTextureData[i].mMaskTexName = 0 ; + glDeleteTextures(1, (GLuint*)&(mBakedTextureDatas[i].mMaskTexName)); + mBakedTextureDatas[i].mMaskTexName = 0 ; } } } @@ -1193,7 +1112,7 @@ BOOL LLVOAvatar::areAllNearbyInstancesBaked(S32& grey_avatars) BOOL res = TRUE; grey_avatars = 0; for (std::vector::iterator iter = LLCharacter::sInstances.begin(); - iter != LLCharacter::sInstances.end(); ++iter) + iter != LLCharacter::sInstances.end(); ++iter) { LLVOAvatar* inst = (LLVOAvatar*) *iter; if( inst->isDead() ) @@ -1205,8 +1124,7 @@ BOOL LLVOAvatar::areAllNearbyInstancesBaked(S32& grey_avatars) // { // return res; // Assumes sInstances is sorted by pixel area. // } - else - if( !inst->isFullyBaked() ) + else if( !inst->isFullyBaked() ) { res = FALSE; if (inst->mHasGrey) @@ -1264,14 +1182,13 @@ void LLVOAvatar::getMeshInfo (mesh_info_t* mesh_info) return; } - // static void LLVOAvatar::dumpBakedStatus() { LLVector3d camera_pos_global = gAgent.getCameraPositionGlobal(); for (std::vector::iterator iter = LLCharacter::sInstances.begin(); - iter != LLCharacter::sInstances.end(); ++iter) + iter != LLCharacter::sInstances.end(); ++iter) { LLVOAvatar* inst = (LLVOAvatar*) *iter; llinfos << "Avatar "; @@ -1325,7 +1242,7 @@ void LLVOAvatar::dumpBakedStatus() for (LLVOAvatarDictionary::baked_map_t::const_iterator iter = LLVOAvatarDictionary::getInstance()->getBakedTextures().begin(); iter != LLVOAvatarDictionary::getInstance()->getBakedTextures().end(); - iter++) + ++iter) { const LLVOAvatarDictionary::BakedDictionaryEntry *baked_dict = iter->second; const ETextureIndex index = baked_dict->mTextureIndex; @@ -1334,7 +1251,6 @@ void LLVOAvatar::dumpBakedStatus() llcont << " " << LLVOAvatarDictionary::getInstance()->getTexture(index)->mName; } } - llcont << " ) " << inst->getUnbakedPixelAreaRank(); if( inst->isCulled() ) { @@ -1353,9 +1269,9 @@ void LLVOAvatar::restoreGL() { LLVOAvatar* inst = (LLVOAvatar*) *iter; inst->setCompositeUpdatesEnabled( TRUE ); - for (U32 i = 0; i < inst->mBakedTextureData.size(); i++) + for (U32 i = 0; i < inst->mBakedTextureDatas.size(); i++) { - inst->invalidateComposite( inst->mBakedTextureData[i].mTexLayerSet, FALSE ); + inst->invalidateComposite( inst->mBakedTextureDatas[i].mTexLayerSet, FALSE ); } inst->updateMeshTextures(); } @@ -1373,7 +1289,7 @@ void LLVOAvatar::destroyGL() void LLVOAvatar::resetImpostors() { for (std::vector::iterator iter = LLCharacter::sInstances.begin(); - iter != LLCharacter::sInstances.end(); ++iter) + iter != LLCharacter::sInstances.end(); ++iter) { LLVOAvatar* avatar = (LLVOAvatar*) *iter; avatar->mImpostor.release(); @@ -1430,7 +1346,7 @@ if(gAuditTexture) { lldebugs << "Deleting layer set caches" << llendl; for (std::vector::iterator iter = LLCharacter::sInstances.begin(); - iter != LLCharacter::sInstances.end(); ++iter) + iter != LLCharacter::sInstances.end(); ++iter) { LLVOAvatar* inst = (LLVOAvatar*) *iter; inst->deleteLayerSetCaches(clearAll); @@ -1588,7 +1504,7 @@ void LLVOAvatar::cleanupClass() const LLVector3 LLVOAvatar::getRenderPosition() const { - if (!mDrawable || mDrawable.isNull() || mDrawable->getGeneration() < 0) + if (mDrawable.isNull() || mDrawable->getGeneration() < 0) { return getPositionAgent(); } @@ -1730,11 +1646,9 @@ BOOL LLVOAvatar::lineSegmentIntersect(const LLVector3& start, const LLVector3& e LLVector3* intersection, LLVector2* tex_coord, LLVector3* normal, - LLVector3* bi_normal - ) + LLVector3* bi_normal) { - - if ((mIsSelf && !gAgent.needsRenderAvatar()) || !LLPipeline::sPickAvatar) + if ((isSelf() && !gAgent.needsRenderAvatar()) || !LLPipeline::sPickAvatar) { return FALSE; } @@ -1893,7 +1807,7 @@ BOOL LLVOAvatar::setupBone(const LLVOAvatarBoneInfo* info, LLViewerJoint* parent // setup children LLVOAvatarBoneInfo::child_list_t::const_iterator iter; - for (iter = info->mChildList.begin(); iter != info->mChildList.end(); iter++) + for (iter = info->mChildList.begin(); iter != info->mChildList.end(); ++iter) { LLVOAvatarBoneInfo *child_info = *iter; if (!setupBone(child_info, joint, volume_num, joint_num)) @@ -1939,7 +1853,7 @@ BOOL LLVOAvatar::buildSkeleton(const LLVOAvatarSkeletonInfo *info) S32 current_joint_num = 0; S32 current_volume_num = 0; LLVOAvatarSkeletonInfo::bone_info_list_t::const_iterator iter; - for (iter = info->mBoneInfoList.begin(); iter != info->mBoneInfoList.end(); iter++) + for (iter = info->mBoneInfoList.begin(); iter != info->mBoneInfoList.end(); ++iter) { LLVOAvatarBoneInfo *info = *iter; if (!setupBone(info, NULL, current_volume_num, current_joint_num)) @@ -1950,7 +1864,7 @@ BOOL LLVOAvatar::buildSkeleton(const LLVOAvatarSkeletonInfo *info) } // add special-purpose "screen" joint - if (mIsSelf) + if (isSelf()) { mScreenp = new LLViewerJoint("mScreen", NULL); // for now, put screen at origin, as it is only used during special @@ -2011,11 +1925,11 @@ void LLVOAvatar::buildCharacter() // clear mesh data //------------------------------------------------------------------------- for (std::vector::iterator jointIter = mMeshLOD.begin(); - jointIter != mMeshLOD.end(); jointIter++) + jointIter != mMeshLOD.end(); ++jointIter) { LLViewerJoint* joint = (LLViewerJoint*) *jointIter; for (std::vector::iterator meshIter = joint->mMeshParts.begin(); - meshIter != joint->mMeshParts.end(); meshIter++) + meshIter != joint->mMeshParts.end(); ++meshIter) { LLViewerJointMesh * mesh = (LLViewerJointMesh *) *meshIter; mesh->setMesh(NULL); @@ -2039,9 +1953,9 @@ void LLVOAvatar::buildCharacter() // gPrintMessagesThisFrame = TRUE; lldebugs << "Avatar load took " << timer.getElapsedTimeF32() << " seconds." << llendl; - if ( ! status ) + if (!status) { - if ( mIsSelf ) + if (isSelf()) { llerrs << "Unable to load user's avatar" << llendl; } @@ -2077,24 +1991,24 @@ void LLVOAvatar::buildCharacter() //------------------------------------------------------------------------- // Make sure "well known" pointers exist //------------------------------------------------------------------------- - if (!(mPelvisp && - mTorsop && - mChestp && - mNeckp && - mHeadp && - mSkullp && - mHipLeftp && - mHipRightp && - mKneeLeftp && - mKneeRightp && - mAnkleLeftp && - mAnkleRightp && - mFootLeftp && - mFootRightp && - mWristLeftp && - mWristRightp && - mEyeLeftp && - mEyeRightp)) + if (!(mPelvisp && + mTorsop && + mChestp && + mNeckp && + mHeadp && + mSkullp && + mHipLeftp && + mHipRightp && + mKneeLeftp && + mKneeRightp && + mAnkleLeftp && + mAnkleRightp && + mFootLeftp && + mFootRightp && + mWristLeftp && + mWristRightp && + mEyeLeftp && + mEyeRightp)) { llerrs << "Failed to create avatar." << llendl; return; @@ -2143,7 +2057,7 @@ void LLVOAvatar::buildCharacter() //------------------------------------------------------------------------- // build the attach and detach menus //------------------------------------------------------------------------- - if (mIsSelf) + if (isSelf()) { // *TODO: Translate gAttachBodyPartPieMenus[0] = NULL; @@ -2377,14 +2291,15 @@ void LLVOAvatar::releaseMeshData() // cleanup mesh data for (std::vector::iterator iter = mMeshLOD.begin(); - iter != mMeshLOD.end(); iter++) + iter != mMeshLOD.end(); + ++iter) { LLViewerJoint* joint = (LLViewerJoint*) *iter; joint->setValid(FALSE, TRUE); } //cleanup data - if (mDrawable && mDrawable.notNull()) + if (mDrawable.notNull()) { LLFace* facep = mDrawable->getFace(0); facep->setSize(0, 0); @@ -2394,12 +2309,12 @@ void LLVOAvatar::releaseMeshData() facep->setSize(0, 0); } } - - for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); - iter != mAttachmentPoints.end(); ) + + for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); + iter != mAttachmentPoints.end(); + ++iter) { - attachment_map_t::iterator curiter = iter++; - LLViewerJointAttachment* attachment = curiter->second; + LLViewerJointAttachment* attachment = iter->second; if (!attachment->getIsHUDAttachment()) { attachment->setAttachmentVisibility(FALSE); @@ -2419,17 +2334,17 @@ void LLVOAvatar::restoreMeshData() mMeshValid = TRUE; updateJointLODs(); - if (mIsSelf) + if (isSelf()) { updateAttachmentVisibility(gAgent.getCameraMode()); } else { - for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); - iter != mAttachmentPoints.end(); ) + for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); + iter != mAttachmentPoints.end(); + ++iter) { - attachment_map_t::iterator curiter = iter++; - LLViewerJointAttachment* attachment = curiter->second; + LLViewerJointAttachment* attachment = iter->second; if (!attachment->getIsHUDAttachment()) { attachment->setAttachmentVisibility(TRUE); @@ -2446,7 +2361,7 @@ void LLVOAvatar::restoreMeshData() //----------------------------------------------------------------------------- void LLVOAvatar::updateMeshData() { - if (mDrawable && mDrawable.notNull()) + if (mDrawable.notNull()) { stop_glerror(); @@ -2496,21 +2411,22 @@ void LLVOAvatar::updateMeshData() bool terse_update = false; - if(facep->mVertexBuffer.isNull()) + if(!facep->getVertexBuffer()) { - facep->mVertexBuffer = new LLVertexBufferAvatar(); - facep->mVertexBuffer->allocateBuffer(num_vertices, num_indices, TRUE); + LLVertexBuffer *buff = new LLVertexBufferAvatar(); + buff->allocateBuffer(num_vertices, num_indices, TRUE); + facep->setVertexBuffer(buff); } else { - if (facep->mVertexBuffer->getRequestedIndices() == num_indices && - facep->mVertexBuffer->getRequestedVerts() == num_vertices) + if (facep->getVertexBuffer()->getRequestedIndices() == num_indices && + facep->getVertexBuffer()->getRequestedVerts() == num_vertices) { terse_update = true; } else { - facep->mVertexBuffer->resizeBuffer(num_vertices, num_indices) ; + facep->getVertexBuffer()->resizeBuffer(num_vertices, num_indices) ; } } @@ -2530,7 +2446,7 @@ void LLVOAvatar::updateMeshData() } stop_glerror(); - facep->mVertexBuffer->setBuffer(0); + facep->getVertexBuffer()->setBuffer(0); if(!f_num) { @@ -2654,7 +2570,7 @@ U32 LLVOAvatar::processUpdateMessage(LLMessageSystem *mesgsys, if (update_type == OUT_FULL ) { - if(mIsSelf) + if(isSelf()) { if(gSavedSettings.getBOOL("ReSit")) { @@ -2715,7 +2631,7 @@ BOOL LLVOAvatar::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) setPixelAreaAndAngle(gAgent); // force asynchronous drawable update - if(mDrawable && mDrawable.notNull() && !gNoRender) + if(mDrawable.notNull() && !gNoRender) { LLFastTimer t(LLFastTimer::FTM_JOINT_UPDATE); @@ -2746,7 +2662,7 @@ BOOL LLVOAvatar::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) // set alpha flag depending on state //-------------------------------------------------------------------- - if (mIsSelf) + if (isSelf()) { LLViewerObject::idleUpdate(agent, world, time); @@ -2767,7 +2683,7 @@ BOOL LLVOAvatar::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) // attach objects that were waiting for a drawable lazyAttach(); /* - if (mIsSelf) + if (isSelf()) { checkAttachments(); } @@ -2785,7 +2701,7 @@ BOOL LLVOAvatar::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) } //Emerald performs some force-bakes stuff here. Added it in because we noticed slow responses with client tag ident. -HgB - if(mIsSelf) + if(isSelf()) { for(U8 i=0;isetVoiceEnabled( voice_enabled && !(mIsSelf && gAgent.cameraMouselook()) ); + mVoiceVisualizer->setVoiceEnabled( voice_enabled && !(isSelf() && gAgent.cameraMouselook()) ); if ( voice_enabled ) { //---------------------------------------------------------------- // Only do gesture triggering for your own avatar, and only when you're in a proximal channel. //---------------------------------------------------------------- - if( mIsSelf ) + if( isSelf() ) { //---------------------------------------------------------------------------------------- // The following takes the voice signal and uses that to trigger gesticulations. @@ -2878,7 +2794,7 @@ void LLVOAvatar::idleUpdateVoiceVisualizer(bool voice_enabled) } } - } //if( mIsSelf ) + } //if( isSelf() ) //----------------------------------------------------------------------------------------------------------------- // If the avatar is speaking, then the voice amplitude signal is passed to the voice visualizer. @@ -2898,7 +2814,7 @@ void LLVOAvatar::idleUpdateVoiceVisualizer(bool voice_enabled) mVoiceVisualizer->setSpeakingAmplitude( gVoiceClient->getCurrentPower( mID ) ); - if( mIsSelf ) + if( isSelf() ) { gAgent.clearAFK(); } @@ -2955,11 +2871,11 @@ void LLVOAvatar::idleUpdateMisc(bool detailed_update) if (detailed_update || !sUseImpostors) { LLFastTimer t(LLFastTimer::FTM_ATTACHMENT_UPDATE); - for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); - iter != mAttachmentPoints.end(); ) + for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); + iter != mAttachmentPoints.end(); + ++iter) { - attachment_map_t::iterator curiter = iter++; - LLViewerJointAttachment* attachment = curiter->second; + LLViewerJointAttachment* attachment = iter->second; for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin(); attachment_iter != attachment->mAttachedObjects.end(); @@ -3055,7 +2971,7 @@ void LLVOAvatar::idleUpdateAppearanceAnimation() { ESex avatar_sex = getSex(); F32 appearance_anim_time = mAppearanceMorphTimer.getElapsedTimeF32(); - if (appearance_anim_time >= sAvMorphTime) + if (appearance_anim_time >= APPEARANCE_MORPH_TIME) { mAppearanceAnimating = FALSE; for (LLVisualParam *param = getFirstVisualParam(); @@ -3068,7 +2984,7 @@ void LLVOAvatar::idleUpdateAppearanceAnimation() } } updateVisualParams(); - if (mIsSelf) + if (isSelf()) { gAgent.sendAgentSetAppearance(); } @@ -3076,14 +2992,14 @@ void LLVOAvatar::idleUpdateAppearanceAnimation() } else { - F32 blend_frac = calc_bouncy_animation(appearance_anim_time / sAvMorphTime); - F32 last_blend_frac = calc_bouncy_animation(mLastAppearanceBlendTime / sAvMorphTime); + F32 blend_frac = calc_bouncy_animation(appearance_anim_time / APPEARANCE_MORPH_TIME); + F32 last_blend_frac = calc_bouncy_animation(mLastAppearanceBlendTime / APPEARANCE_MORPH_TIME); F32 morph_amt; // if it's over 5 seconds, just forget the bouncy anim - if(sAvMorphTime > 5.f) + if(APPEARANCE_MORPH_TIME > 5.f) { - blend_frac = appearance_anim_time / sAvMorphTime; - last_blend_frac = mLastAppearanceBlendTime / sAvMorphTime; + blend_frac = appearance_anim_time / APPEARANCE_MORPH_TIME; + last_blend_frac = mLastAppearanceBlendTime / APPEARANCE_MORPH_TIME; } if (last_blend_frac == 1.f) { @@ -3428,7 +3344,7 @@ void LLVOAvatar::getClientInfo(std::string& client, LLColor4& color, BOOL useCom std::string uuid_str = getTE(TEX_HEAD_BODYPAINT)->getID().asString(); //UUID of the head texture static const LLCachedControl avatar_name_color("AvatarNameColor",LLColor4(LLColor4U(251, 175, 93, 255)), gColors ); - if (mIsSelf) + if (isSelf()) { static const LLCachedControl ascent_use_custom_tag("AscentUseCustomTag", false); static const LLCachedControl ascent_custom_tag_color("AscentCustomTagColor", LLColor4(.5f,1.f,.25f,1.f)); @@ -3586,7 +3502,7 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last) mNameFromChatOverride)); // If it's your own avatar, don't draw in mouselook, and don't // draw if we're specifically hiding our own name. - if (mIsSelf) + if (isSelf()) { render_name = render_name && !gAgent.cameraMouselook() @@ -3767,7 +3683,7 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last) } static const LLCachedControl ascent_use_status_colors("AscentUseStatusColors",true); - if (!mIsSelf && ascent_use_status_colors) + if (!isSelf() && ascent_use_status_colors) { LLViewerRegion* parent_estate = LLWorld::getInstance()->getRegionFromPosGlobal(this->getPositionGlobal()); LLUUID estate_owner = LLUUID::null; @@ -3799,8 +3715,8 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last) } client = mClientTag; - if ((mIsSelf && gSavedSettings.getBOOL("AscentShowSelfTagColor")) - || (!mIsSelf && gSavedSettings.getBOOL("AscentShowOthersTagColor"))) + if ((isSelf() && gSavedSettings.getBOOL("AscentShowSelfTagColor")) + || (!isSelf() && gSavedSettings.getBOOL("AscentShowOthersTagColor"))) avatar_name_color = mClientColor; @@ -3870,14 +3786,14 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last) } } - BOOL is_away = mSignaledAnimations.find(ANIM_AGENT_AWAY) != mSignaledAnimations.end(); + bool is_away = mSignaledAnimations.find(ANIM_AGENT_AWAY) != mSignaledAnimations.end(); if(mNameAway && ! is_away) mIdleTimer.reset(); - BOOL is_busy = mSignaledAnimations.find(ANIM_AGENT_BUSY) != mSignaledAnimations.end(); + bool is_busy = mSignaledAnimations.find(ANIM_AGENT_BUSY) != mSignaledAnimations.end(); if(mNameBusy && ! is_busy) mIdleTimer.reset(); - BOOL is_appearance = mSignaledAnimations.find(ANIM_AGENT_CUSTOMIZE) != mSignaledAnimations.end(); + bool is_appearance = mSignaledAnimations.find(ANIM_AGENT_CUSTOMIZE) != mSignaledAnimations.end(); if(mNameAppearance && ! is_appearance) mIdleTimer.reset(); - BOOL is_muted; - if (mIsSelf) + bool is_muted; + if (isSelf()) { is_muted = FALSE; } @@ -3983,8 +3899,8 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last) { if ((client != "")&&(client != "?")) { - if ((mIsSelf && gSavedSettings.getBOOL("AscentShowSelfTag")) - || (!mIsSelf && gSavedSettings.getBOOL("AscentShowOthersTag"))) + if ((isSelf() && gSavedSettings.getBOOL("AscentShowSelfTag")) + || (!isSelf() && gSavedSettings.getBOOL("AscentShowOthersTag"))) { additions += client; need_comma = TRUE; @@ -4033,7 +3949,7 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last) line += "\n"; line += "(Editing Appearance)"; } - if(!mIsSelf && mIdleTimer.getElapsedTimeF32() > 120 && gSavedSettings.getBOOL("AscentShowIdleTime")) + if(!isSelf() && mIdleTimer.getElapsedTimeF32() > 120 && gSavedSettings.getBOOL("AscentShowIdleTime")) { line += "\n"; line += getIdleTime(); @@ -4174,13 +4090,13 @@ void LLVOAvatar::invalidateNameTag(const LLUUID& agent_id) avatar->clearNameTag(); } -//staticmNameString.empty() +//static void LLVOAvatar::invalidateNameTags() { - for (std::vector::iterator iter = LLCharacter::sInstances.begin(); - iter != LLCharacter::sInstances.end(); ++iter) + std::vector::iterator it = LLCharacter::sInstances.begin(); + for ( ; it != LLCharacter::sInstances.end(); ++it) { - LLVOAvatar* avatar = (LLVOAvatar*) *iter; + LLVOAvatar* avatar = dynamic_cast(*it); if (!avatar) continue; if (avatar->isDead()) continue; @@ -4194,7 +4110,7 @@ void LLVOAvatar::idleUpdateTractorBeam() //-------------------------------------------------------------------- // draw tractor beam when editing objects //-------------------------------------------------------------------- - if (!mIsSelf) + if (!isSelf()) { return; } @@ -4294,7 +4210,7 @@ void LLVOAvatar::slamPosition() gAgent.setPositionAgent(getPositionAgent()); mRoot.setWorldPosition(getPositionAgent()); // teleport setChanged(TRANSLATED); - if (mDrawable && mDrawable.notNull()) + if (mDrawable.notNull()) { gPipeline.updateMoveNormalAsync(mDrawable); } @@ -4350,7 +4266,7 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent) if (gNoRender) { // Hack if we're running drones... - if (mIsSelf) + if (isSelf()) { gAgent.setPositionAgent(getPositionAgent()); } @@ -4369,7 +4285,7 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent) // For fading out the names above heads, only let the timer // run if we're visible. - if (mDrawable && mDrawable.notNull() && !visible) + if (mDrawable.notNull() && !visible) { mTimeVisible.reset(); } @@ -4379,30 +4295,30 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent) // the rest should only be done occasionally for far away avatars //-------------------------------------------------------------------- - if (visible && !mIsSelf && !mIsDummy && sUseImpostors && !mNeedsAnimUpdate && !sFreezeCounter) + if (visible && !isSelf() && !mIsDummy && sUseImpostors && !mNeedsAnimUpdate && !sFreezeCounter) { F32 impostor_area = 256.f*512.f*(8.125f - LLVOAvatar::sLODFactor*8.f); if (LLMuteList::getInstance()->isMuted(getID())) { // muted avatars update at 16 hz mUpdatePeriod = 16; } - else if (visible && mVisibilityRank <= LLVOAvatar::sMaxVisible * 0.25f) + else if (mVisibilityRank <= LLVOAvatar::sMaxVisible * 0.25f) { //first 25% of max visible avatars are not impostored mUpdatePeriod = 1; } - else if (visible && mVisibilityRank > LLVOAvatar::sMaxVisible * 0.75f) + else if (mVisibilityRank > LLVOAvatar::sMaxVisible * 0.75f) { //back 25% of max visible avatars are slow updating impostors mUpdatePeriod = 8; } - else if (visible && mVisibilityRank > (U32) LLVOAvatar::sMaxVisible) + else if (mVisibilityRank > (U32) LLVOAvatar::sMaxVisible) { //background avatars are REALLY slow updating impostors mUpdatePeriod = 16; } - else if (visible && mImpostorPixelArea <= impostor_area) + else if (mImpostorPixelArea <= impostor_area) { // stuff in between gets an update period based on pixel area mUpdatePeriod = llclamp((S32) sqrtf(impostor_area*4.f/mImpostorPixelArea), 2, 8); } - else if (visible && mVisibilityRank > LLVOAvatar::sMaxVisible * 0.25f) + else if (mVisibilityRank > LLVOAvatar::sMaxVisible * 0.25f) { // force nearby impostors in ultra crowded areas mUpdatePeriod = 2; } @@ -4414,14 +4330,17 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent) visible = (LLDrawable::getCurrentFrame()+mID.mData[0])%mUpdatePeriod == 0 ? TRUE : FALSE; } - if (!visible && !mIsSelf) + // don't early out for your own avatar, as we rely on your animations playing reliably + // for example, the "turn around" animation when entering customize avatar needs to trigger + // even when your avatar is offscreen + if (!visible && !isSelf()) { updateMotions(LLCharacter::HIDDEN_UPDATE); return FALSE; } // change animation time quanta based on avatar render load - if (!mIsSelf && !mIsDummy) + if (!isSelf() && !mIsDummy) { F32 time_quantum = clamp_rescale((F32)sInstances.size(), 10.f, 35.f, 0.f, 0.25f); F32 pixel_area_scale = clamp_rescale(mPixelArea, 100, 5000, 1.f, 0.f); @@ -4490,7 +4409,7 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent) LLVector3d root_pos; LLVector3d ground_under_pelvis; - if (mIsSelf) + if (isSelf()) { gAgent.setPositionAgent(getRenderPosition()); } @@ -4535,7 +4454,7 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent) // more than 90 from the view, if necessary, flip the velocity vector. LLVector3 primDir; - if (mIsSelf) + if (isSelf()) { primDir = agent.getAtAxis() - projected_vec(agent.getAtAxis(), agent.getReferenceUpVector()); primDir.normalize(); @@ -4555,7 +4474,7 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent) } } LLVector3 fwdDir = lerp(primDir, velDir, clamp_rescale(speed, 0.5f, 2.0f, 0.0f, 1.0f)); - if (mIsSelf && gAgent.cameraMouselook()) + if (isSelf() && gAgent.cameraMouselook()) { // make sure fwdDir stays in same general direction as primdir if (gAgent.getFlying()) @@ -4594,7 +4513,7 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent) // When moving very slow, the pelvis is allowed to deviate from the // forward direction to allow it to hold it's position while the torso // and head turn. Once in motion, it must conform however. - BOOL self_in_mouselook = mIsSelf && gAgent.cameraMouselook(); + BOOL self_in_mouselook = isSelf() && gAgent.cameraMouselook(); LLVector3 pelvisDir( mRoot.getWorldMatrix().getFwdRow4().mV ); F32 pelvis_rot_threshold = clamp_rescale(speed, 0.1f, 1.0f, PELVIS_ROT_THRESHOLD_SLOW, PELVIS_ROT_THRESHOLD_FAST); @@ -4645,7 +4564,7 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent) fwdDir = leftDir % upDir; LLQuaternion wQv( fwdDir, leftDir, upDir ); - if (mIsSelf && mTurning) + if (isSelf() && mTurning) { if ((fwdDir % pelvisDir) * upDir > 0.f) { @@ -4682,7 +4601,7 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent) } } - else if (mDrawable && mDrawable.notNull()) + else if (mDrawable.notNull()) { mRoot.setPosition(mDrawable->getPosition()); mRoot.setRotation(mDrawable->getRotation()); @@ -4810,10 +4729,10 @@ void LLVOAvatar::updateHeadOffset() { // since we only care about Z, just grab one of the eyes LLVector3 midEyePt = mEyeLeftp->getWorldPosition(); - midEyePt -= (mDrawable && mDrawable.notNull()) ? mDrawable->getWorldPosition() : mRoot.getWorldPosition(); + midEyePt -= mDrawable.notNull() ? mDrawable->getWorldPosition() : mRoot.getWorldPosition(); midEyePt.mV[VZ] = llmax(-mPelvisToFoot + LLViewerCamera::getInstance()->getNear(), midEyePt.mV[VZ]); - if (mDrawable && mDrawable.notNull()) + if (mDrawable.notNull()) { midEyePt = midEyePt * ~mDrawable->getWorldRotation(); } @@ -4839,7 +4758,7 @@ void LLVOAvatar::updateVisibility() { visible = TRUE; } - else if (!mDrawable || mDrawable.isNull()) + else if (mDrawable.isNull()) { visible = FALSE; } @@ -4854,7 +4773,7 @@ void LLVOAvatar::updateVisibility() visible = FALSE; } - if( mIsSelf ) + if(isSelf()) { if( !gAgent.areWearablesLoaded()) { @@ -4912,7 +4831,8 @@ void LLVOAvatar::updateVisibility() /*llinfos << "SPA: " << sel_pos_agent << llendl; llinfos << "WPA: " << wrist_right_pos_agent << llendl;*/ for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); - iter != mAttachmentPoints.end(); iter++) + iter != mAttachmentPoints.end(); + ++iter) { LLViewerJointAttachment* attachment = iter->second; @@ -4966,6 +4886,16 @@ void LLVOAvatar::updateVisibility() mVisible = visible; } +// private +bool LLVOAvatar::shouldAlphaMask() +{ + const bool should_alpha_mask = mSupportsAlphaLayers && !LLDrawPoolAlpha::sShowDebugAlpha // Don't alpha mask if "Highlight Transparent" checked + && !LLDrawPoolAvatar::sSkipTransparent && mHasBakedHair; + + return should_alpha_mask; + +} + //------------------------------------------------------------------------ // needsRenderBeam() //------------------------------------------------------------------------ @@ -5001,7 +4931,7 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass) LLFace* face = mDrawable->getFace(0); - bool needs_rebuild = !face || face->mVertexBuffer.isNull() || mDrawable->isState(LLDrawable::REBUILD_GEOMETRY); + bool needs_rebuild = !face || !face->getVertexBuffer() || mDrawable->isState(LLDrawable::REBUILD_GEOMETRY); if (needs_rebuild || mDirtyMesh) { //LOD changed or new mesh created, allocate new vertex buffer if needed @@ -5027,7 +4957,7 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass) mMeshLOD[MESH_ID_SKIRT]->updateJointGeometry(); } - if (!mIsSelf || gAgent.needsRenderHead() || LLPipeline::sShadowRender) + if (!isSelf() || gAgent.needsRenderHead() || LLPipeline::sShadowRender) { mMeshLOD[MESH_ID_EYELASH]->updateJointGeometry(); mMeshLOD[MESH_ID_HEAD]->updateJointGeometry(); @@ -5035,7 +4965,7 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass) } mNeedsSkin = FALSE; - LLVertexBuffer* vb = mDrawable->getFace(0)->mVertexBuffer; + LLVertexBuffer* vb = mDrawable->getFace(0)->getVertexBuffer(); if (vb) { vb->setBuffer(0); @@ -5077,7 +5007,7 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass) return num_indices; } - if (mIsSelf && !gAgent.needsRenderAvatar()) + if (isSelf() && !gAgent.needsRenderAvatar()) { return num_indices; } @@ -5086,7 +5016,7 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass) // *NOTE: this is disabled (there is no UI for enabling sShowFootPlane) due // to DEV-14477. the code is left here to aid in tracking down the cause // of the crash in the future. -brad - if (!gRenderForSelect && sShowFootPlane && mDrawable && mDrawable.notNull()) + if (!gRenderForSelect && sShowFootPlane && mDrawable.notNull()) { LLVector3 slaved_pos = mDrawable->getPositionAgent(); LLVector3 foot_plane_normal(mFootPlane.mV[VX], mFootPlane.mV[VY], mFootPlane.mV[VZ]); @@ -5127,17 +5057,10 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass) if (pass == AVATAR_RENDER_PASS_SINGLE) { - const bool should_alpha_mask = mSupportsAlphaLayers && mHasBakedHair - && !LLDrawPoolAlpha::sShowDebugAlpha // Don't alpha mask if "Highlight Transparent" checked - && !LLDrawPoolAvatar::sSkipTransparent; - - - - - + const bool should_alpha_mask = shouldAlphaMask(); LLGLState test(GL_ALPHA_TEST, should_alpha_mask); - + if (should_alpha_mask) { gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.5f); @@ -5146,7 +5069,7 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass) BOOL first_pass = TRUE; if (!LLDrawPoolAvatar::sSkipOpaque) { - if (!mIsSelf || gAgent.needsRenderHead() || LLPipeline::sShadowRender) + if (!isSelf() || gAgent.needsRenderHead() || LLPipeline::sShadowRender) { if (isTextureVisible(TEX_HEAD_BAKED) || mIsDummy) { @@ -5197,7 +5120,7 @@ U32 LLVOAvatar::renderTransparent(BOOL first_pass) gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); } - if (!mIsSelf || gAgent.needsRenderHead() || LLPipeline::sShadowRender) + if (!isSelf() || gAgent.needsRenderHead() || LLPipeline::sShadowRender) { if (LLPipeline::sImpostorRender) { @@ -5237,7 +5160,7 @@ U32 LLVOAvatar::renderRigid() return 0; } - if (mIsSelf && (!gAgent.needsRenderAvatar() || !gAgent.needsRenderHead())) + if (isSelf() && (!gAgent.needsRenderAvatar() || !gAgent.needsRenderHead())) { return 0; } @@ -5247,14 +5170,7 @@ U32 LLVOAvatar::renderRigid() return 0; } - - - - - const bool should_alpha_mask = mSupportsAlphaLayers && mHasBakedHair - && !LLDrawPoolAlpha::sShowDebugAlpha // Don't alpha mask if "Highlight Transparent" checked - && !LLDrawPoolAvatar::sSkipTransparent; - + const bool should_alpha_mask = shouldAlphaMask(); LLGLState test(GL_ALPHA_TEST, should_alpha_mask); if (should_alpha_mask) @@ -5282,7 +5198,7 @@ U32 LLVOAvatar::renderFootShadows() return 0; } - if (mIsSelf && (!gAgent.needsRenderAvatar() || !gAgent.needsRenderHead())) + if (isSelf() && (!gAgent.needsRenderAvatar() || !gAgent.needsRenderHead())) { return 0; } @@ -5321,7 +5237,7 @@ U32 LLVOAvatar::renderFootShadows() return num_indices; } -U32 LLVOAvatar::renderImpostor(LLColor4U color) +U32 LLVOAvatar::renderImpostor(LLColor4U color, S32 diffuse_channel) { if (!mImpostor.isComplete()) { @@ -5341,7 +5257,7 @@ U32 LLVOAvatar::renderImpostor(LLColor4U color) gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.f); gGL.color4ubv(color.mV); - gGL.getTexUnit(0)->bind(&mImpostor); + gGL.getTexUnit(diffuse_channel)->bind(&mImpostor); gGL.begin(LLRender::QUADS); gGL.texCoord2f(0,0); gGL.vertex3fv((pos+left-up).mV); @@ -5369,7 +5285,7 @@ void LLVOAvatar::updateTextures() return; } - if( mIsSelf ) + if( isSelf() ) { render_avatar = TRUE; } @@ -5379,23 +5295,23 @@ void LLVOAvatar::updateTextures() } std::vector layer_baked; - for (U32 i = 0; i < mBakedTextureData.size(); i++) + for (U32 i = 0; i < mBakedTextureDatas.size(); i++) { - layer_baked.push_back(isTextureDefined(mBakedTextureData[i].mTextureIndex)); + layer_baked.push_back(isTextureDefined(mBakedTextureDatas[i].mTextureIndex)); // bind the texture so that they'll be decoded slightly // inefficient, we can short-circuit this if we have to if( render_avatar && !gGLManager.mIsDisabled ) { - if (layer_baked[i] && !mBakedTextureData[i].mIsLoaded) + if (layer_baked[i] && !mBakedTextureDatas[i].mIsLoaded) { - gGL.getTexUnit(0)->bind(getTEImage( mBakedTextureData[i].mTextureIndex )); + gGL.getTexUnit(0)->bind(getTEImage( mBakedTextureDatas[i].mTextureIndex )); } } } /* // JAMESDEBUG - if (mIsSelf) + if (isSelf()) { S32 null_count = 0; S32 default_count = 0; @@ -5427,7 +5343,7 @@ void LLVOAvatar::updateTextures() if (imagep) { // Debugging code - maybe non-self avatars are downloading textures? - //llinfos << "avatar self " << mIsSelf << " tex " << index + //llinfos << "avatar self " << isSelf() << " tex " << index // << " decode " << imagep->getDecodePriority() // << " boost " << imagep->getBoostLevel() // << " size " << imagep->getWidth() << "x" << imagep->getHeight() @@ -5437,7 +5353,7 @@ void LLVOAvatar::updateTextures() const LLTextureEntry *te = getTE(index); F32 texel_area_ratio = fabs(te->mScaleS * te->mScaleT); - S32 boost_level = mIsSelf ? LLViewerTexture::BOOST_AVATAR_BAKED_SELF : LLViewerTexture::BOOST_AVATAR_BAKED; + S32 boost_level = isSelf() ? LLViewerTexture::BOOST_AVATAR_BAKED_SELF : LLViewerTexture::BOOST_AVATAR_BAKED; // Spam if this is a baked texture, not set to default image, without valid host info if (isIndexBakedTexture((ETextureIndex)index) @@ -5447,7 +5363,7 @@ void LLVOAvatar::updateTextures() { LL_WARNS_ONCE("Texture") << "LLVOAvatar::updateTextures No host for texture " << imagep->getID() << " for avatar " - << (mIsSelf ? "" : getID().asString()) + << (isSelf() ? "" : getID().asString()) << " on host " << getRegion()->getHost() << llendl; } @@ -5490,12 +5406,12 @@ void LLVOAvatar::addLocalTextureStats( ETextureIndex idx, LLViewerTexture* image { if (!isIndexLocalTexture(idx)) return; - if (!covered_by_baked && render_avatar) // render_avatar is always true if mIsSelf + if (!covered_by_baked && render_avatar) // render_avatar is always true if isSelf() { if (getLocalTextureID(idx) != IMG_DEFAULT_AVATAR) { F32 desired_pixels; - if( mIsSelf ) + if( isSelf() ) { desired_pixels = llmax(mPixelArea, (F32)TEX_IMAGE_AREA_SELF ); imagep->setBoostLevel(LLViewerTexture::BOOST_AVATAR_SELF); @@ -5659,7 +5575,7 @@ void LLVOAvatar::processAnimationStateChanges() if (found_anim == mSignaledAnimations.end()) { - if (mIsSelf) + if (isSelf()) { if ((gSavedSettings.getBOOL("AOEnabled")) && LLFloaterAO::stopMotion(anim_it->first, FALSE)) // if the AO replaced this anim serverside then stop it serverside { @@ -5691,7 +5607,7 @@ void LLVOAvatar::processAnimationStateChanges() // if (processSingleAnimationStateChange(anim_it->first, TRUE)) { - if (mIsSelf && gSavedSettings.getBOOL("AOEnabled")) // AO is only for ME + if (isSelf() && gSavedSettings.getBOOL("AOEnabled")) // AO is only for ME { LLFloaterAO::startMotion(anim_it->first, 0,FALSE); // AO overrides the anim if needed } @@ -5706,7 +5622,7 @@ void LLVOAvatar::processAnimationStateChanges() } // clear source information for animations which have been stopped - if (mIsSelf) + if (isSelf()) { AnimSourceIterator source_it = mAnimationSources.begin(); @@ -5725,80 +5641,6 @@ void LLVOAvatar::processAnimationStateChanges() stop_glerror(); } -//Here's that undeform function I was talking about. -HgB -/* Bug-fixed Linden Labs style. Comment out 4ever. -std::string undeformers[] = -{ - "7a8a3dfc-acd1-7ac3-9cdf-71cd9be89969", - "3feba1c0-971b-f2bb-1b9c-79e81b096c94", - "383ef55f-5e70-02fb-8ef4-1b591b09fd49", - "e2f6bc07-97a5-1f55-6c5f-fbcb02511651", - "1370bf7d-eb29-c1dd-fc3c-cc8e06d57ac0", - "5833be17-3d69-faa0-8f18-58696a326b44", - "7746596d-b88a-216a-2335-06e28167ed31", - "edf75cf0-a2f3-d126-7cdf-5009382ec10b", - "430e8872-1095-4cff-5a39-7c991f32fffb", - "a83bab1b-2ff0-4365-1b6b-6b6e52efc69d", - "7db75c3d-ae67-4312-9734-1510f12a1392", - "551b8c1f-5241-b73e-7ce2-d78fc4ac316f", - "91d73df8-5dfa-e1f2-0a32-77327e56b8dd", - "b2b2fb93-aad5-a7a8-9731-ee8ed72f7acd", - "984eabe8-0953-a93b-f33d-6e21c405cc78", - "f6212696-dc74-b17f-4ea8-f90c37cb032e", - "aa825c4d-aa84-df7d-6ae6-fbf2dcb6f281", - "14ef74d1-93ad-09cb-7a39-fbac3bd80e64" -}; - -void LLVOAvatar::undeform() -{ - if(!mIsSelf) return; - - AnimIterator anim_it; - for (anim_it = mPlayingAnimations.begin(); anim_it != mPlayingAnimations.end();) - { - AnimIterator found_anim = mSignaledAnimations.find(anim_it->first); - - if (found_anim == mSignaledAnimations.end()) - { - if (mIsSelf) - { - if ((gSavedSettings.getBOOL("AOEnabled")) && LLFloaterAO::stopMotion(anim_it->first, FALSE)) // if the AO replaced this anim serverside then stop it serverside - { -// return TRUE; //no local stop needed - } - } - - processSingleAnimationStateChange(anim_it->first, FALSE); - mPlayingAnimations.erase(anim_it++); - continue; - } - ++anim_it; - } - - AnimSourceIterator source_it = mAnimationSources.begin(); - - for (source_it = mAnimationSources.begin(); source_it != mAnimationSources.end();) - { - if (mSignaledAnimations.find(source_it->second) == mSignaledAnimations.end()) - { - mAnimationSources.erase(source_it++); - } - else - { - ++source_it; - } - } - U8 i=0; - for(i; i < 18; ++i) - { - gAgent.sendAnimationRequest( (LLUUID)undeformers[i], ANIM_REQUEST_START ); - startMotion((LLUUID)undeformers[i]); - } - - stop_glerror(); -}*/ - - //----------------------------------------------------------------------------- // processSingleAnimationStateChange(); @@ -5821,7 +5663,7 @@ BOOL LLVOAvatar::processSingleAnimationStateChange( const LLUUID& anim_id, BOOL { // RN: uncomment this to play on typing sound at fixed volume once sound engine is fixed // to support both spatialized and non-spatialized instances of the same sound - //if (mIsSelf) + //if (isSelf()) //{ // gAudiop->triggerSound(LLUUID(gSavedSettings.getString("UISndTyping")), 1.0f, LLAudioEngine::AUDIO_TYPE_UI); //} @@ -5867,7 +5709,7 @@ BOOL LLVOAvatar::processSingleAnimationStateChange( const LLUUID& anim_id, BOOL //----------------------------------------------------------------------------- // isAnyAnimationSignaled() //----------------------------------------------------------------------------- -BOOL LLVOAvatar::isAnyAnimationSignaled(const LLUUID *anim_array, const S32 num_anims) +BOOL LLVOAvatar::isAnyAnimationSignaled(const LLUUID *anim_array, const S32 num_anims) const { for (S32 i = 0; i < num_anims; i++) { @@ -5971,7 +5813,7 @@ BOOL LLVOAvatar::startMotion(const LLUUID& id, F32 time_offset) LLUUID remap_id = remapMotionID(id); - if (mIsSelf && remap_id == ANIM_AGENT_AWAY) + if (isSelf() && remap_id == ANIM_AGENT_AWAY) { gAgent.setAFK(); } @@ -5987,7 +5829,7 @@ BOOL LLVOAvatar::stopMotion(const LLUUID& id, BOOL stop_immediate) LLUUID remap_id = remapMotionID(id); - if (mIsSelf) + if (isSelf()) { gAgent.onAnimStop(remap_id); } @@ -6000,7 +5842,7 @@ BOOL LLVOAvatar::stopMotion(const LLUUID& id, BOOL stop_immediate) //----------------------------------------------------------------------------- void LLVOAvatar::stopMotionFromSource(const LLUUID& source_id) { - if (!mIsSelf) + if (!isSelf()) { return; } @@ -6294,7 +6136,7 @@ LLJoint *LLVOAvatar::getCharacterJoint( U32 num ) void LLVOAvatar::requestStopMotion( LLMotion* motion ) { // Only agent avatars should handle the stop motion notifications. - if ( mIsSelf ) + if ( isSelf() ) { // Notify agent that motion has stopped gAgent.requestStopMotion( motion ); @@ -6402,7 +6244,7 @@ BOOL LLVOAvatar::loadAvatar() const LLVOAvatarDictionary::BakedDictionaryEntry *baked_dict = baked_iter->second; if (layer_set->isBodyRegion(baked_dict->mName)) { - mBakedTextureData[baked_iter->first].mTexLayerSet = layer_set; + mBakedTextureDatas[baked_iter->first].mTexLayerSet = layer_set; layer_set->setBakedTexIndex(baked_iter->first); found_baked_entry = true; break; @@ -6762,7 +6604,7 @@ void LLVOAvatar::setPixelAreaAndAngle(LLAgent &agent) } // We always want to look good to ourselves - if( mIsSelf ) + if( isSelf() ) { mPixelArea = llmax( mPixelArea, F32(TEX_IMAGE_SIZE_SELF / 16) ); } @@ -6780,7 +6622,7 @@ BOOL LLVOAvatar::updateJointLODs() F32 area_scale = 0.16f; { - if (mIsSelf) + if (isSelf()) { if(gAgent.cameraCustomizeAvatar() || gAgent.cameraMouselook()) { @@ -6927,7 +6769,7 @@ void LLVOAvatar::updateShadowFaces() // Render sprite sprite.setNormal(normal); - if (mIsSelf && gAgent.getCameraMode() == CAMERA_MODE_MOUSELOOK) + if (isSelf() && gAgent.getCameraMode() == CAMERA_MODE_MOUSELOOK) { sprite.setColor(0.f, 0.f, 0.f, 0.f); } @@ -6960,7 +6802,7 @@ void LLVOAvatar::updateShadowFaces() // Render sprite sprite.setNormal(normal); - if (mIsSelf && gAgent.getCameraMode() == CAMERA_MODE_MOUSELOOK) + if (isSelf() && gAgent.getCameraMode() == CAMERA_MODE_MOUSELOOK) { sprite.setColor(0.f, 0.f, 0.f, 0.f); } @@ -6985,9 +6827,9 @@ void LLVOAvatar::updateShadowFaces() //----------------------------------------------------------------------------- void LLVOAvatar::updateSexDependentLayerSets( BOOL set_by_user ) { - invalidateComposite( mBakedTextureData[BAKED_HEAD].mTexLayerSet, set_by_user ); - invalidateComposite( mBakedTextureData[BAKED_UPPER].mTexLayerSet, set_by_user ); - invalidateComposite( mBakedTextureData[BAKED_LOWER].mTexLayerSet, set_by_user ); + invalidateComposite( mBakedTextureDatas[BAKED_HEAD].mTexLayerSet, set_by_user ); + invalidateComposite( mBakedTextureDatas[BAKED_UPPER].mTexLayerSet, set_by_user ); + invalidateComposite( mBakedTextureDatas[BAKED_LOWER].mTexLayerSet, set_by_user ); updateMeshTextures(); } @@ -7010,6 +6852,22 @@ void LLVOAvatar::hideSkirt() mMeshLOD[MESH_ID_SKIRT]->setVisible(FALSE, TRUE); } +//----------------------------------------------------------------------------- +// getMesh( LLPolyMeshSharedData *shared_data ) +//----------------------------------------------------------------------------- +LLPolyMesh* LLVOAvatar::getMesh( LLPolyMeshSharedData *shared_data ) +{ + for (polymesh_map_t::iterator i = mMeshes.begin(); i != mMeshes.end(); ++i) + { + LLPolyMesh* mesh = i->second; + if (mesh->getSharedData() == shared_data) + { + return mesh; + } + } + return NULL; +} + //----------------------------------------------------------------------------- // requestLayerSetUpdate() //----------------------------------------------------------------------------- @@ -7024,9 +6882,9 @@ void LLVOAvatar::requestLayerSetUpdate(ETextureIndex index ) if (!texture_dict->mIsLocalTexture || !texture_dict->mIsUsedByBakedTexture) return; const EBakedTextureIndex baked_index = texture_dict->mBakedTextureIndex; - if (mBakedTextureData[baked_index].mTexLayerSet) + if (mBakedTextureDatas[baked_index].mTexLayerSet) { - mBakedTextureData[baked_index].mTexLayerSet->requestUpdate(); + mBakedTextureDatas[baked_index].mTexLayerSet->requestUpdate(); } } @@ -7133,7 +6991,7 @@ BOOL LLVOAvatar::attachObject(LLViewerObject *viewer_object) LLSelectMgr::getInstance()->updatePointAt(); } - if (mIsSelf) + if (isSelf()) { updateAttachmentVisibility(gAgent.getCameraMode()); @@ -7157,7 +7015,7 @@ BOOL LLVOAvatar::attachObject(LLViewerObject *viewer_object) LLSelectMgr::getInstance()->updatePointAt(); } - if (mIsSelf) + if (isSelf()) { updateAttachmentVisibility(gAgent.getCameraMode()); @@ -7267,7 +7125,7 @@ BOOL LLVOAvatar::detachObject(LLViewerObject *viewer_object) { // [RLVa:KB] - Checked: 2010-03-05 (RLVa-1.2.0a) | Added: RLVa-1.2.0a // NOTE: RLVa event handlers should be invoked *before* LLVOAvatar::detachObject() calls LLViewerJointAttachment::removeObject() - if ( (rlv_handler_t::isEnabled()) && (mIsSelf) ) + if ( (rlv_handler_t::isEnabled()) && (isSelf()) ) { for (attachment_map_t::const_iterator itAttachPt = mAttachmentPoints.begin(); itAttachPt != mAttachmentPoints.end(); ++itAttachPt) { @@ -7283,7 +7141,7 @@ BOOL LLVOAvatar::detachObject(LLViewerObject *viewer_object) LLUUID item_id = viewer_object->getAttachmentItemID(); attachment->removeObject(viewer_object); - if (mIsSelf) + if (isSelf()) { // the simulator should automatically handle // permission revocation @@ -7309,7 +7167,7 @@ BOOL LLVOAvatar::detachObject(LLViewerObject *viewer_object) // [/RLVa:KB] } lldebugs << "Detaching object " << viewer_object->mID << " from " << attachment->getName() << llendl; - if (mIsSelf) + if (isSelf()) { // Then make sure the inventory is in sync with the avatar. gInventory.addChangedMask(LLInventoryObserver::LABEL, item_id); @@ -7343,7 +7201,7 @@ BOOL LLVOAvatar::detachObject(LLViewerObject *viewer_object) if((*iter).second == item_id) { mUnsupportedAttachmentPoints.erase((*iter).first); - if (mIsSelf) + if (isSelf()) { // the simulator should automatically handle // permission revocation @@ -7383,7 +7241,7 @@ BOOL LLVOAvatar::detachObject(LLViewerObject *viewer_object) //----------------------------------------------------------------------------- void LLVOAvatar::sitOnObject(LLViewerObject *sit_object) { - if (!mDrawable || mDrawable.isNull() || sit_object->mDrawable.isNull()) + if (mDrawable.isNull() || sit_object->mDrawable.isNull()) { return; } @@ -7405,7 +7263,7 @@ void LLVOAvatar::sitOnObject(LLViewerObject *sit_object) stopMotion(ANIM_AGENT_BODY_NOISE); - if (mIsSelf) + if (isSelf()) { // [RLVa:KB] - Checked: 2010-08-29 (RLVa-1.2.1c) | Modified: RLVa-1.2.1c if (rlv_handler_t::isEnabled()) @@ -7435,7 +7293,7 @@ void LLVOAvatar::sitOnObject(LLViewerObject *sit_object) //----------------------------------------------------------------------------- void LLVOAvatar::getOffObject() { - if (!mDrawable || mDrawable.isNull()) + if (mDrawable.isNull()) { return; } @@ -7449,7 +7307,7 @@ void LLVOAvatar::getOffObject() LLViewerObject::const_child_list_t& child_list = sit_object->getChildren(); for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin(); - iter != child_list.end(); iter++) + iter != child_list.end(); ++iter) { LLViewerObject* child_objectp = *iter; @@ -7477,7 +7335,7 @@ void LLVOAvatar::getOffObject() startMotion(ANIM_AGENT_BODY_NOISE); LLFloaterAO::ChangeStand(); - if (mIsSelf) + if (isSelf()) { // [RLVa:KB] - Checked: 2010-08-29 (RLVa-1.2.1c) | Modified: RLVa-1.2.1c if (rlv_handler_t::isEnabled()) @@ -7709,28 +7567,27 @@ void LLVOAvatar::onLocalTextureLoaded( BOOL success, LLViewerFetchedTexture *src void LLVOAvatar::updateComposites() { - for (U32 i = 0; i < mBakedTextureData.size(); i++) + for (U32 i = 0; i < mBakedTextureDatas.size(); i++) { - if ( mBakedTextureData[i].mTexLayerSet + if ( mBakedTextureDatas[i].mTexLayerSet && ((i != BAKED_SKIRT) || isWearingWearableType( WT_SKIRT )) ) { - mBakedTextureData[i].mTexLayerSet->updateComposite(); + mBakedTextureDatas[i].mTexLayerSet->updateComposite(); } } } -LLColor4 LLVOAvatar::getGlobalColor( const std::string& color_name ) +LLColor4 LLVOAvatar::getGlobalColor( const std::string& color_name ) const { - if( color_name=="skin_color" && mTexSkinColor ) + if (color_name=="skin_color" && mTexSkinColor) { return mTexSkinColor->getColor(); } - else - if( color_name=="hair_color" && mTexHairColor ) + else if(color_name=="hair_color" && mTexHairColor) { return mTexHairColor->getColor(); } - if( color_name=="eye_color" && mTexEyeColor ) + if(color_name=="eye_color" && mTexEyeColor) { return mTexEyeColor->getColor(); } @@ -7786,7 +7643,7 @@ void LLVOAvatar::invalidateComposite( LLTexLayerSet* layerset, BOOL set_by_user if( set_by_user ) { - llassert( mIsSelf ); + llassert( isSelf() ); ETextureIndex baked_te = getBakedTE( layerset ); setTEImage( baked_te, LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT_AVATAR,0)); @@ -7796,56 +7653,60 @@ void LLVOAvatar::invalidateComposite( LLTexLayerSet* layerset, BOOL set_by_user void LLVOAvatar::invalidateAll() { - for (U32 i = 0; i < mBakedTextureData.size(); i++) + for (U32 i = 0; i < mBakedTextureDatas.size(); i++) { - invalidateComposite(mBakedTextureData[i].mTexLayerSet, TRUE); + invalidateComposite(mBakedTextureDatas[i].mTexLayerSet, TRUE); } updateMeshTextures(); } -void LLVOAvatar::onGlobalColorChanged( LLTexGlobalColor* global_color, BOOL set_by_user ) +void LLVOAvatar::onGlobalColorChanged(const LLTexGlobalColor* global_color, BOOL set_by_user ) { - if( global_color == mTexSkinColor ) + if (global_color == mTexSkinColor) { // llinfos << "invalidateComposite cause: onGlobalColorChanged( skin color )" << llendl; - invalidateComposite( mBakedTextureData[BAKED_HEAD].mTexLayerSet, set_by_user ); - invalidateComposite( mBakedTextureData[BAKED_UPPER].mTexLayerSet, set_by_user ); - invalidateComposite( mBakedTextureData[BAKED_LOWER].mTexLayerSet, set_by_user ); + invalidateComposite( mBakedTextureDatas[BAKED_HEAD].mTexLayerSet, set_by_user ); + invalidateComposite( mBakedTextureDatas[BAKED_UPPER].mTexLayerSet, set_by_user ); + invalidateComposite( mBakedTextureDatas[BAKED_LOWER].mTexLayerSet, set_by_user ); } - else - if( global_color == mTexHairColor ) + else if (global_color == mTexHairColor) { // llinfos << "invalidateComposite cause: onGlobalColorChanged( hair color )" << llendl; - invalidateComposite( mBakedTextureData[BAKED_HEAD].mTexLayerSet, set_by_user ); - invalidateComposite( mBakedTextureData[BAKED_HAIR].mTexLayerSet, set_by_user ); + invalidateComposite( mBakedTextureDatas[BAKED_HEAD].mTexLayerSet, set_by_user ); + invalidateComposite( mBakedTextureDatas[BAKED_HAIR].mTexLayerSet, set_by_user ); // ! BACKWARDS COMPATIBILITY ! // Fix for dealing with avatars from viewers that don't bake hair. - if (!isTextureDefined(mBakedTextureData[BAKED_HAIR].mTextureIndex)) + if (!isTextureDefined(mBakedTextureDatas[BAKED_HAIR].mTextureIndex)) { LLColor4 color = mTexHairColor->getColor(); - for (U32 i = 0; i < mBakedTextureData[BAKED_HAIR].mMeshes.size(); i++) + for (U32 i = 0; i < mBakedTextureDatas[BAKED_HAIR].mMeshes.size(); i++) { - mBakedTextureData[BAKED_HAIR].mMeshes[i]->setColor( color.mV[VX], color.mV[VY], color.mV[VZ], color.mV[VW] ); + mBakedTextureDatas[BAKED_HAIR].mMeshes[i]->setColor( color.mV[VX], color.mV[VY], color.mV[VZ], color.mV[VW] ); } } } - else - if( global_color == mTexEyeColor ) + else if (global_color == mTexEyeColor) { // llinfos << "invalidateComposite cause: onGlobalColorChanged( eyecolor )" << llendl; - invalidateComposite( mBakedTextureData[BAKED_EYES].mTexLayerSet, set_by_user ); + invalidateComposite( mBakedTextureDatas[BAKED_EYES].mTexLayerSet, set_by_user ); } updateMeshTextures(); } +BOOL LLVOAvatar::isVisible() const +{ + return mDrawable.notNull() + && (mDrawable->isVisible() || mIsDummy); +} + void LLVOAvatar::forceBakeAllTextures(bool slam_for_debug) { llinfos << "TAT: forced full rebake. " << llendl; - for (U32 i = 0; i < mBakedTextureData.size(); i++) + for (U32 i = 0; i < mBakedTextureDatas.size(); i++) { - ETextureIndex baked_index = mBakedTextureData[i].mTextureIndex; + ETextureIndex baked_index = mBakedTextureDatas[i].mTextureIndex; LLTexLayerSet* layer_set = getLayerSet(baked_index); if (layer_set) { @@ -8003,12 +7864,6 @@ void LLVOAvatar::dumpTotalLocalTextureByteCount() llinfos << "Total Avatar LocTex GL:" << (total_gl_bytes/1024) << "KB" << llendl; } -BOOL LLVOAvatar::isVisible() -{ - return mDrawable && mDrawable.notNull() - && (mDrawable->isVisible() || mIsDummy); -} - // call periodically to keep isFullyLoaded up to date. // returns true if the value has changed. @@ -8026,7 +7881,7 @@ BOOL LLVOAvatar::updateIsFullyLoaded() } // - if (mIsSelf) + if (isSelf()) { if (!isTextureDefined(TEX_HAIR)) { @@ -8053,13 +7908,13 @@ BOOL LLVOAvatar::updateIsFullyLoaded() // texture info for our shirt/pants, stay unloaded: if (!mPreviousFullyLoaded) { - if ((!isLocalTextureDataAvailable(mBakedTextureData[BAKED_LOWER].mTexLayerSet)) && + if ((!isLocalTextureDataAvailable(mBakedTextureDatas[BAKED_LOWER].mTexLayerSet)) && (!isTextureDefined(TEX_LOWER_BAKED))) { loading = TRUE; } - if ((!isLocalTextureDataAvailable(mBakedTextureData[BAKED_UPPER].mTexLayerSet)) && + if ((!isLocalTextureDataAvailable(mBakedTextureDatas[BAKED_UPPER].mTexLayerSet)) && (!isTextureDefined(TEX_UPPER_BAKED))) { loading = TRUE; @@ -8092,7 +7947,7 @@ BOOL LLVOAvatar::updateIsFullyLoaded() -BOOL LLVOAvatar::isFullyLoaded() +BOOL LLVOAvatar::isFullyLoaded() const { // [SL:KB] - Patch: Appearance-SyncAttach | Checked: 2010-09-22 (Catznip-2.2.0a) | Added: Catznip-2.2.0a // Changes to LLAppearanceMgr::updateAppearanceFromCOF() expect this function to actually return mFullyLoaded for gAgentAvatarp @@ -8138,7 +7993,7 @@ void LLVOAvatar::updateRuthTimer(bool loading) //----------------------------------------------------------------------------- // findMotion() //----------------------------------------------------------------------------- -LLMotion* LLVOAvatar::findMotion(const LLUUID& id) +LLMotion* LLVOAvatar::findMotion(const LLUUID& id) const { return mMotionController.findMotion(id); } @@ -8266,7 +8121,7 @@ LLGLuint LLVOAvatar::getScratchTexName( LLGLenum format, U32* texture_bytes ) //----------------------------------------------------------------------------- void LLVOAvatar::setLocTexTE( U8 te, LLViewerTexture* image, BOOL set_by_user ) { - if( !mIsSelf ) + if( !isSelf() ) { llassert( 0 ); return; @@ -8306,12 +8161,12 @@ void LLVOAvatar::setLocTexTE( U8 te, LLViewerTexture* image, BOOL set_by_user ) void LLVOAvatar::setupComposites() { - for (U32 i = 0; i < mBakedTextureData.size(); i++) + for (U32 i = 0; i < mBakedTextureDatas.size(); i++) { - bool layer_baked = isTextureDefined(mBakedTextureData[i].mTextureIndex); - if (mBakedTextureData[i].mTexLayerSet) + bool layer_baked = isTextureDefined(mBakedTextureDatas[i].mTextureIndex); + if (mBakedTextureDatas[i].mTexLayerSet) { - mBakedTextureData[i].mTexLayerSet->setUpdatesEnabled( !layer_baked ); + mBakedTextureDatas[i].mTexLayerSet->setUpdatesEnabled( !layer_baked ); } } } @@ -8335,18 +8190,18 @@ void LLVOAvatar::updateMeshTextures() } } - const BOOL self_customizing = mIsSelf && gAgent.cameraCustomizeAvatar(); // During face edit mode, we don't use baked textures - const BOOL other_culled = !mIsSelf && mCulled; + const BOOL self_customizing = isSelf() && gAgent.cameraCustomizeAvatar(); // During face edit mode, we don't use baked textures + const BOOL other_culled = !isSelf() && mCulled; std::vector is_layer_baked; - is_layer_baked.resize(mBakedTextureData.size(), false); + is_layer_baked.resize(mBakedTextureDatas.size(), false); std::vector use_lkg_baked_layer; // lkg = "last known good" - use_lkg_baked_layer.resize(mBakedTextureData.size(), false); + use_lkg_baked_layer.resize(mBakedTextureDatas.size(), false); - for (U32 i=0; i < mBakedTextureData.size(); i++) + for (U32 i=0; i < mBakedTextureDatas.size(); i++) { - is_layer_baked[i] = isTextureDefined(mBakedTextureData[i].mTextureIndex); + is_layer_baked[i] = isTextureDefined(mBakedTextureDatas[i].mTextureIndex); if (!other_culled) { @@ -8354,21 +8209,21 @@ void LLVOAvatar::updateMeshTextures() // use the last-known good baked texture until it finish the first // render of the new layerset. use_lkg_baked_layer[i] = (!is_layer_baked[i] - && (mBakedTextureData[i].mLastTextureIndex != IMG_DEFAULT_AVATAR) - && mBakedTextureData[i].mTexLayerSet - && !mBakedTextureData[i].mTexLayerSet->getComposite()->isInitialized()); + && (mBakedTextureDatas[i].mLastTextureIndex != IMG_DEFAULT_AVATAR) + && mBakedTextureDatas[i].mTexLayerSet + && !mBakedTextureDatas[i].mTexLayerSet->getComposite()->isInitialized()); if (use_lkg_baked_layer[i]) { - mBakedTextureData[i].mTexLayerSet->setUpdatesEnabled(TRUE); + mBakedTextureDatas[i].mTexLayerSet->setUpdatesEnabled(TRUE); } } else { use_lkg_baked_layer[i] = (!is_layer_baked[i] - && mBakedTextureData[i].mLastTextureIndex != IMG_DEFAULT_AVATAR); - if (mBakedTextureData[i].mTexLayerSet) + && mBakedTextureDatas[i].mLastTextureIndex != IMG_DEFAULT_AVATAR); + if (mBakedTextureDatas[i].mTexLayerSet) { - mBakedTextureData[i].mTexLayerSet->destroyComposite(); + mBakedTextureDatas[i].mTexLayerSet->destroyComposite(); } } @@ -8384,60 +8239,60 @@ void LLVOAvatar::updateMeshTextures() llwarns << "updateMeshTextures: invalid host for object: " << getID() << llendl; } - for (U32 i=0; i < mBakedTextureData.size(); i++) + for (U32 i=0; i < mBakedTextureDatas.size(); i++) { if (use_lkg_baked_layer[i] && !self_customizing ) { - LLViewerFetchedTexture* baked_img = LLViewerTextureManager::getFetchedTextureFromHost( mBakedTextureData[i].mLastTextureIndex, target_host ); - mBakedTextureData[i].mIsUsed = TRUE; - for (U32 k=0; k < mBakedTextureData[i].mMeshes.size(); k++) + LLViewerFetchedTexture* baked_img = LLViewerTextureManager::getFetchedTextureFromHost( mBakedTextureDatas[i].mLastTextureIndex, target_host ); + mBakedTextureDatas[i].mIsUsed = TRUE; + for (U32 k=0; k < mBakedTextureDatas[i].mMeshes.size(); k++) { - mBakedTextureData[i].mMeshes[k]->setTexture( baked_img ); + mBakedTextureDatas[i].mMeshes[k]->setTexture( baked_img ); } } else if (!self_customizing && is_layer_baked[i]) { - LLViewerFetchedTexture* baked_img = LLViewerTextureManager::staticCastToFetchedTexture(getTEImage( mBakedTextureData[i].mTextureIndex ), TRUE) ; - if( baked_img->getID() == mBakedTextureData[i].mLastTextureIndex ) + LLViewerFetchedTexture* baked_img = LLViewerTextureManager::staticCastToFetchedTexture(getTEImage( mBakedTextureDatas[i].mTextureIndex ), TRUE) ; + if( baked_img->getID() == mBakedTextureDatas[i].mLastTextureIndex ) { // Even though the file may not be finished loading, we'll consider it loaded and use it (rather than doing compositing). useBakedTexture( baked_img->getID() ); } else { - mBakedTextureData[i].mIsLoaded = FALSE; - if ((baked_img->getID() != IMG_INVISIBLE) && (i == BAKED_HEAD || i == BAKED_UPPER || i == BAKED_LOWER)) + mBakedTextureDatas[i].mIsLoaded = FALSE; + if ( (baked_img->getID() != IMG_INVISIBLE) && ((i == BAKED_HEAD) || (i == BAKED_UPPER) || (i == BAKED_LOWER)) ) { baked_img->setLoadedCallback(onBakedTextureMasksLoaded, MORPH_MASK_REQUESTED_DISCARD, TRUE, TRUE, new LLTextureMaskData( mID ), NULL); } baked_img->setLoadedCallback(onBakedTextureLoaded, SWITCH_TO_BAKED_DISCARD, FALSE, FALSE, new LLUUID( mID ), NULL); } } - else if (mBakedTextureData[i].mTexLayerSet + else if (mBakedTextureDatas[i].mTexLayerSet && !other_culled - && (i != BAKED_HAIR || is_layer_baked[i] || mIsSelf)) // ! BACKWARDS COMPATIBILITY ! workaround for old viewers. + && (i != BAKED_HAIR || is_layer_baked[i] || isSelf())) // ! BACKWARDS COMPATIBILITY ! workaround for old viewers. { - mBakedTextureData[i].mTexLayerSet->createComposite(); - mBakedTextureData[i].mTexLayerSet->setUpdatesEnabled( TRUE ); - mBakedTextureData[i].mIsUsed = FALSE; - for (U32 k=0; k < mBakedTextureData[i].mMeshes.size(); k++) + mBakedTextureDatas[i].mTexLayerSet->createComposite(); + mBakedTextureDatas[i].mTexLayerSet->setUpdatesEnabled( TRUE ); + mBakedTextureDatas[i].mIsUsed = FALSE; + for (U32 k=0; k < mBakedTextureDatas[i].mMeshes.size(); k++) { - mBakedTextureData[i].mMeshes[k]->setLayerSet( mBakedTextureData[i].mTexLayerSet ); + mBakedTextureDatas[i].mMeshes[k]->setLayerSet( mBakedTextureDatas[i].mTexLayerSet ); } } } // ! BACKWARDS COMPATIBILITY ! // Workaround for viewing avatars from old viewers that haven't baked hair textures. - // if (!isTextureDefined(mBakedTextureData[BAKED_HAIR].mTextureIndex)) + // if (!isTextureDefined(mBakedTextureDatas[BAKED_HAIR].mTextureIndex)) if (!is_layer_baked[BAKED_HAIR] || self_customizing) { const LLColor4 color = mTexHairColor ? mTexHairColor->getColor() : LLColor4(1,1,1,1); LLViewerTexture* hair_img = getTEImage( TEX_HAIR ); - for (U32 i = 0; i < mBakedTextureData[BAKED_HAIR].mMeshes.size(); i++) + for (U32 i = 0; i < mBakedTextureDatas[BAKED_HAIR].mMeshes.size(); i++) { - mBakedTextureData[BAKED_HAIR].mMeshes[i]->setColor( color.mV[VX], color.mV[VY], color.mV[VZ], color.mV[VW] ); - mBakedTextureData[BAKED_HAIR].mMeshes[i]->setTexture( hair_img ); + mBakedTextureDatas[BAKED_HAIR].mMeshes[i]->setColor( color.mV[VX], color.mV[VY], color.mV[VZ], color.mV[VW] ); + mBakedTextureDatas[BAKED_HAIR].mMeshes[i]->setTexture( hair_img ); } mHasBakedHair = FALSE; } @@ -8447,21 +8302,21 @@ void LLVOAvatar::updateMeshTextures() } /* // Head - BOOL head_baked_ready = (is_layer_baked[BAKED_HEAD] && mBakedTextureData[BAKED_HEAD].mIsLoaded) || other_culled; + BOOL head_baked_ready = (is_layer_baked[BAKED_HEAD] && mBakedTextureDatas[BAKED_HEAD].mIsLoaded) || other_culled; setLocalTexture( TEX_HEAD_BODYPAINT, getTEImage( TEX_HEAD_BODYPAINT ), head_baked_ready ); */ for (LLVOAvatarDictionary::baked_map_t::const_iterator baked_iter = LLVOAvatarDictionary::getInstance()->getBakedTextures().begin(); baked_iter != LLVOAvatarDictionary::getInstance()->getBakedTextures().end(); - baked_iter++) + ++baked_iter) { const EBakedTextureIndex baked_index = baked_iter->first; const LLVOAvatarDictionary::BakedDictionaryEntry *baked_dict = baked_iter->second; for (texture_vec_t::const_iterator local_tex_iter = baked_dict->mLocalTextures.begin(); local_tex_iter != baked_dict->mLocalTextures.end(); - local_tex_iter++) + ++local_tex_iter) { const ETextureIndex texture_index = *local_tex_iter; - const BOOL is_baked_ready = (is_layer_baked[baked_index] && mBakedTextureData[baked_index].mIsLoaded) || other_culled; + const BOOL is_baked_ready = (is_layer_baked[baked_index] && mBakedTextureDatas[baked_index].mIsLoaded) || other_culled; setLocalTexture(texture_index, LLViewerTextureManager::staticCastToFetchedTexture(getTEImage(texture_index)), is_baked_ready ); } } @@ -8475,7 +8330,7 @@ void LLVOAvatar::setLocalTexture( ETextureIndex index, LLViewerFetchedTexture* t { if (!isIndexLocalTexture(index)) return; - S32 desired_discard = mIsSelf ? 0 : 2; + S32 desired_discard = isSelf() ? 0 : 2; LocalTextureData &local_tex_data = mLocalTextureData[index]; if (!baked_version_ready) { @@ -8491,11 +8346,11 @@ void LLVOAvatar::setLocalTexture( ETextureIndex index, LLViewerFetchedTexture* t if (tex_discard >= 0 && tex_discard <= desired_discard) { local_tex_data.mDiscard = tex_discard; - if( mIsSelf && !gAgent.cameraCustomizeAvatar() ) + if( isSelf() && !gAgent.cameraCustomizeAvatar() ) { requestLayerSetUpdate( index ); } - else if( mIsSelf && gAgent.cameraCustomizeAvatar() ) + else if( isSelf() && gAgent.cameraCustomizeAvatar() ) { LLVisualParamHint::requestHintUpdates(); } @@ -8517,12 +8372,12 @@ void LLVOAvatar::setLocalTexture( ETextureIndex index, LLViewerFetchedTexture* t //----------------------------------------------------------------------------- void LLVOAvatar::requestLayerSetUploads() { - for (U32 i = 0; i < mBakedTextureData.size(); i++) + for (U32 i = 0; i < mBakedTextureDatas.size(); i++) { - bool layer_baked = isTextureDefined(mBakedTextureData[i].mTextureIndex); - if ( !layer_baked && mBakedTextureData[i].mTexLayerSet ) + bool layer_baked = isTextureDefined(mBakedTextureDatas[i].mTextureIndex); + if ( !layer_baked && mBakedTextureDatas[i].mTexLayerSet ) { - mBakedTextureData[i].mTexLayerSet->requestUpload(); + mBakedTextureDatas[i].mTexLayerSet->requestUpload(); } } } @@ -8533,11 +8388,11 @@ void LLVOAvatar::requestLayerSetUploads() //----------------------------------------------------------------------------- void LLVOAvatar::setCompositeUpdatesEnabled( BOOL b ) { - for (U32 i = 0; i < mBakedTextureData.size(); i++) + for (U32 i = 0; i < mBakedTextureDatas.size(); i++) { - if (mBakedTextureData[i].mTexLayerSet ) + if (mBakedTextureDatas[i].mTexLayerSet ) { - mBakedTextureData[i].mTexLayerSet->setUpdatesEnabled( b ); + mBakedTextureDatas[i].mTexLayerSet->setUpdatesEnabled( b ); } } } @@ -8597,9 +8452,9 @@ S32 LLVOAvatar::getLocalDiscardLevel( ETextureIndex index ) //----------------------------------------------------------------------------- BOOL LLVOAvatar::isLocalTextureDataFinal( const LLTexLayerSet* layerset ) { - for (U32 i = 0; i < mBakedTextureData.size(); i++) + for (U32 i = 0; i < mBakedTextureDatas.size(); i++) { - if (layerset == mBakedTextureData[i].mTexLayerSet) + if (layerset == mBakedTextureDatas[i].mTexLayerSet) { const LLVOAvatarDictionary::BakedDictionaryEntry *baked_dict = LLVOAvatarDictionary::getInstance()->getBakedTexture((EBakedTextureIndex)i); for (texture_vec_t::const_iterator local_tex_iter = baked_dict->mLocalTextures.begin(); @@ -8626,14 +8481,14 @@ BOOL LLVOAvatar::isLocalTextureDataFinal( const LLTexLayerSet* layerset ) //----------------------------------------------------------------------------- BOOL LLVOAvatar::isLocalTextureDataAvailable( const LLTexLayerSet* layerset ) { - /* if( layerset == mBakedTextureData[BAKED_HEAD].mTexLayerSet ) + /* if( layerset == mBakedTextureDatas[BAKED_HEAD].mTexLayerSet ) return getLocalDiscardLevel( TEX_HEAD_BODYPAINT ) >= 0; */ for (LLVOAvatarDictionary::baked_map_t::const_iterator baked_iter = LLVOAvatarDictionary::getInstance()->getBakedTextures().begin(); baked_iter != LLVOAvatarDictionary::getInstance()->getBakedTextures().end(); baked_iter++) { const EBakedTextureIndex baked_index = baked_iter->first; - if (layerset == mBakedTextureData[baked_index].mTexLayerSet) + if (layerset == mBakedTextureDatas[baked_index].mTexLayerSet) { bool ret = true; const LLVOAvatarDictionary::BakedDictionaryEntry *baked_dict = baked_iter->second; @@ -8657,11 +8512,11 @@ BOOL LLVOAvatar::isLocalTextureDataAvailable( const LLTexLayerSet* layerset ) //----------------------------------------------------------------------------- ETextureIndex LLVOAvatar::getBakedTE( LLTexLayerSet* layerset ) { - for (U32 i = 0; i < mBakedTextureData.size(); i++) + for (U32 i = 0; i < mBakedTextureDatas.size(); i++) { - if (layerset == mBakedTextureData[i].mTexLayerSet ) + if (layerset == mBakedTextureDatas[i].mTexLayerSet ) { - return mBakedTextureData[i].mTextureIndex; + return mBakedTextureDatas[i].mTextureIndex; } } @@ -8697,7 +8552,7 @@ void LLVOAvatar::setNewBakedTexture( ETextureIndex te, const LLUUID& uuid ) if (text_dict->mIsBakedTexture) { llinfos << "New baked texture: " << text_dict->mName << " UUID: " << uuid <mBakedTextureIndex].mTexLayerSet->requestUpdate(); + //mBakedTextureDatas[text_dict->mBakedTextureIndex].mTexLayerSet->requestUpdate(); } else { @@ -8714,9 +8569,9 @@ void LLVOAvatar::setNewBakedTexture( ETextureIndex te, const LLUUID& uuid ) bool LLVOAvatar::hasPendingBakedUploads() { - for (U32 i = 0; i < mBakedTextureData.size(); i++) + for (U32 i = 0; i < mBakedTextureDatas.size(); i++) { - bool upload_pending = (mBakedTextureData[i].mTexLayerSet && mBakedTextureData[i].mTexLayerSet->getComposite()->uploadPending()); + bool upload_pending = (mBakedTextureDatas[i].mTexLayerSet && mBakedTextureDatas[i].mTexLayerSet->getComposite()->uploadPending()); if (upload_pending) { return true; @@ -8737,11 +8592,11 @@ void LLVOAvatar::setCachedBakedTexture( ETextureIndex te, const LLUUID& uuid ) case TEX_HEAD_BAKED: if( mHeadLayerSet ) mHeadLayerSet->cancelUpload(); */ - for (U32 i = 0; i < mBakedTextureData.size(); i++) + for (U32 i = 0; i < mBakedTextureDatas.size(); i++) { - if ( mBakedTextureData[i].mTextureIndex == te && mBakedTextureData[i].mTexLayerSet) + if ( mBakedTextureDatas[i].mTextureIndex == te && mBakedTextureDatas[i].mTexLayerSet) { - mBakedTextureData[i].mTexLayerSet->cancelUpload(); + mBakedTextureDatas[i].mTexLayerSet->cancelUpload(); } } } @@ -8749,10 +8604,14 @@ void LLVOAvatar::setCachedBakedTexture( ETextureIndex te, const LLUUID& uuid ) //----------------------------------------------------------------------------- // releaseUnneccesaryTextures() // release any component texture UUIDs for which we have a baked texture +// ! BACKWARDS COMPATIBILITY ! +// This is only called for non-self avatars, it can be taken out once component +// textures aren't communicated by non-self avatars. //----------------------------------------------------------------------------- void LLVOAvatar::releaseUnnecessaryTextures() { - // Backwards Compat: detect if the baked hair texture actually wasn't sent, and if so set to default + // ! BACKWARDS COMPATIBILITY ! + // Detect if the baked hair texture actually wasn't sent, and if so set to default if (isTextureDefined(TEX_HAIR_BAKED) && getTEImage(TEX_HAIR_BAKED)->getID() == getTEImage(TEX_SKIRT_BAKED)->getID()) { if (getTEImage(TEX_HAIR_BAKED)->getID() != IMG_INVISIBLE) @@ -8826,7 +8685,7 @@ void LLVOAvatar::onChangeSelfInvisible(BOOL newvalue) } } - +//static BOOL LLVOAvatar::teToColorParams( ETextureIndex te, const char* param_name[3] ) { switch( te ) @@ -8929,15 +8788,15 @@ LLColor4 LLVOAvatar::getClothesColor( ETextureIndex te ) -void LLVOAvatar::dumpAvatarTEs( const std::string& context ) +void LLVOAvatar::dumpAvatarTEs( const std::string& context ) const { /* const char* te_name[] = { "TEX_HEAD_BODYPAINT ", "TEX_UPPER_SHIRT ", */ - llinfos << (mIsSelf ? "Self: " : "Other: ") << context << llendl; + llinfos << (isSelf() ? "Self: " : "Other: ") << context << llendl; for (LLVOAvatarDictionary::texture_map_t::const_iterator iter = LLVOAvatarDictionary::getInstance()->getTextures().begin(); iter != LLVOAvatarDictionary::getInstance()->getTextures().end(); - iter++) + ++iter) { const LLVOAvatarDictionary::TextureDictionaryEntry *text_dict = iter->second; const LLViewerTexture* te_image = getTEImage(iter->first); @@ -9028,9 +8887,9 @@ void LLVOAvatar::setInvisible(BOOL newvalue) if (newvalue) { setCompositeUpdatesEnabled(FALSE); - for (U32 i = 0; i < mBakedTextureData.size(); i++ ) + for (U32 i = 0; i < mBakedTextureDatas.size(); i++ ) { - setNewBakedTexture(mBakedTextureData[i].mTextureIndex, IMG_INVISIBLE); + setNewBakedTexture(mBakedTextureDatas[i].mTextureIndex, IMG_INVISIBLE); } gAgent.sendAgentSetAppearance(); } @@ -9059,7 +8918,7 @@ EWearableType LLVOAvatar::getTEWearableType(ETextureIndex index ) } // Unlike most wearable functions, this works for both self and other. -BOOL LLVOAvatar::isWearingWearableType( EWearableType type ) +BOOL LLVOAvatar::isWearingWearableType( EWearableType type ) const { if (mIsDummy) return TRUE; @@ -9079,14 +8938,14 @@ BOOL LLVOAvatar::isWearingWearableType( EWearableType type ) indicator_te = TEX_UPPER_SHIRT; */ for (LLVOAvatarDictionary::texture_map_t::const_iterator tex_iter = LLVOAvatarDictionary::getInstance()->getTextures().begin(); tex_iter != LLVOAvatarDictionary::getInstance()->getTextures().end(); - tex_iter++) + ++tex_iter) { const LLVOAvatarDefines::ETextureIndex index = tex_iter->first; const LLVOAvatarDictionary::TextureDictionaryEntry *text_dict = tex_iter->second; if (text_dict->mWearableType == type) { // If you're checking your own clothing, check the component texture - if (mIsSelf) + if (isSelf()) { if (isTextureDefined(index)) { @@ -9149,9 +9008,9 @@ void LLVOAvatar::wearableUpdated(EWearableType type, BOOL upload_result) const EWearableType comp_type = *type_iter; if (comp_type == type) { - if (mBakedTextureData[index].mTexLayerSet) + if (mBakedTextureDatas[index].mTexLayerSet) { - invalidateComposite(mBakedTextureData[index].mTexLayerSet, upload_result); + invalidateComposite(mBakedTextureDatas[index].mTexLayerSet, upload_result); updateMeshTextures(); } break; @@ -9178,11 +9037,11 @@ void LLVOAvatar::clampAttachmentPositions() { return; } - for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); - iter != mAttachmentPoints.end(); ) + for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); + iter != mAttachmentPoints.end(); + ++iter) { - attachment_map_t::iterator curiter = iter++; - LLViewerJointAttachment* attachment = curiter->second; + LLViewerJointAttachment* attachment = iter->second; if (attachment) { attachment->clampObjectPosition(); @@ -9192,8 +9051,9 @@ void LLVOAvatar::clampAttachmentPositions() BOOL LLVOAvatar::hasHUDAttachment() const { - for (attachment_map_t::const_iterator iter = mAttachmentPoints.begin(); - iter != mAttachmentPoints.end(); ++iter) + for (attachment_map_t::const_iterator iter = mAttachmentPoints.begin(); + iter != mAttachmentPoints.end(); + ++iter) { LLViewerJointAttachment* attachment = iter->second; if (attachment->getIsHUDAttachment() && attachment->getNumObjects() > 0) @@ -9207,8 +9067,9 @@ BOOL LLVOAvatar::hasHUDAttachment() const LLBBox LLVOAvatar::getHUDBBox() const { LLBBox bbox; - for (attachment_map_t::const_iterator iter = mAttachmentPoints.begin(); - iter != mAttachmentPoints.end(); ++iter) + for (attachment_map_t::const_iterator iter = mAttachmentPoints.begin(); + iter != mAttachmentPoints.end(); + ++iter) { LLViewerJointAttachment* attachment = iter->second; if (attachment->getIsHUDAttachment()) @@ -9255,18 +9116,18 @@ void LLVOAvatar::onFirstTEMessageReceived() { mFirstTEMessageReceived = TRUE; - for (U32 i = 0; i < mBakedTextureData.size(); i++) + for (U32 i = 0; i < mBakedTextureDatas.size(); i++) { - bool layer_baked = isTextureDefined(mBakedTextureData[i].mTextureIndex); + const bool layer_baked = isTextureDefined(mBakedTextureDatas[i].mTextureIndex); // Use any baked textures that we have even if they haven't downloaded yet. // (That is, don't do a transition from unbaked to baked.) if (layer_baked) { - LLViewerFetchedTexture* image = LLViewerTextureManager::staticCastToFetchedTexture(getTEImage( mBakedTextureData[i].mTextureIndex )); - mBakedTextureData[i].mLastTextureIndex = image->getID(); + LLViewerFetchedTexture* image = LLViewerTextureManager::staticCastToFetchedTexture(getTEImage( mBakedTextureDatas[i].mTextureIndex )); + mBakedTextureDatas[i].mLastTextureIndex = image->getID(); // If we have more than one texture for the other baked layers, we'll want to call this for them too. - if ((image->getID() != IMG_INVISIBLE) && (i == BAKED_HEAD || i == BAKED_UPPER || i == BAKED_LOWER)) + if ( (image->getID() != IMG_INVISIBLE) && ((i == BAKED_HEAD) || (i == BAKED_UPPER) || (i == BAKED_LOWER)) ) { image->setLoadedCallback( onBakedTextureMasksLoaded, MORPH_MASK_REQUESTED_DISCARD, TRUE, TRUE, new LLTextureMaskData( mID ), NULL); } @@ -9297,7 +9158,7 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys ) mFirstAppearanceMessageReceived = TRUE; - if( mIsSelf ) + if( isSelf() ) { llwarns << "Received AvatarAppearance for self" << llendl; if( mFirstTEMessageReceived ) @@ -9314,7 +9175,7 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys ) ESex old_sex = getSex(); -// llinfos << "ady LLVOAvatar::processAvatarAppearance()" << llendl; +// llinfos << "LLVOAvatar::processAvatarAppearance()" << llendl; // dumpAvatarTEs( "PRE processAvatarAppearance()" ); unpackTEMessage(mesgsys, _PREHASH_ObjectData); // dumpAvatarTEs( "POST processAvatarAppearance()" ); @@ -9334,19 +9195,19 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys ) }*/ // prevent the overwriting of valid baked textures with invalid baked textures - for (U8 baked_index = 0; baked_index < mBakedTextureData.size(); baked_index++) + for (U8 baked_index = 0; baked_index < mBakedTextureDatas.size(); baked_index++) { - if (!isTextureDefined(mBakedTextureData[baked_index].mTextureIndex) - && mBakedTextureData[baked_index].mLastTextureIndex != IMG_DEFAULT + if (!isTextureDefined(mBakedTextureDatas[baked_index].mTextureIndex) + && mBakedTextureDatas[baked_index].mLastTextureIndex != IMG_DEFAULT && baked_index != BAKED_SKIRT) { - setTEImage(mBakedTextureData[baked_index].mTextureIndex, - LLViewerTextureManager::getFetchedTexture(mBakedTextureData[baked_index].mLastTextureIndex, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE)); + setTEImage(mBakedTextureDatas[baked_index].mTextureIndex, + LLViewerTextureManager::getFetchedTexture(mBakedTextureDatas[baked_index].mLastTextureIndex, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE)); } } - //llinfos << "Received AvatarAppearance: " << (mIsSelf ? "(self): " : "(other): ") << std::endl << + //llinfos << "Received AvatarAppearance: " << (isSelf() ? "(self): " : "(other): ") << std::endl << // (isTextureDefined(TEX_HEAD_BAKED) ? "HEAD " : "head " ) << (getTEImage(TEX_HEAD_BAKED)->getID()) << std::endl << // (isTextureDefined(TEX_UPPER_BAKED) ? "UPPER " : "upper " ) << (getTEImage(TEX_UPPER_BAKED)->getID()) << std::endl << // (isTextureDefined(TEX_LOWER_BAKED) ? "LOWER " : "lower " ) << (getTEImage(TEX_LOWER_BAKED)->getID()) << std::endl << @@ -9363,7 +9224,7 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys ) mMeshTexturesDirty = TRUE; gPipeline.markGLRebuild(this); - if (!mIsSelf) + if (!isSelf()) { //releaseUnnecessaryTextures(); Commented out to ensure that users get the right client data -HgB } @@ -9560,14 +9421,14 @@ void LLVOAvatar::onBakedTextureMasksLoaded( BOOL success, LLViewerFetchedTexture gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR); /* if( id == head_baked->getID() ) - if (self->mBakedTextureData[BAKED_HEAD].mTexLayerSet) + if (self->mBakedTextureDatas[BAKED_HEAD].mTexLayerSet) //llinfos << "onBakedTextureMasksLoaded for head " << id << " discard = " << discard_level << llendl; - self->mBakedTextureData[BAKED_HEAD].mTexLayerSet->applyMorphMask(aux_src->getData(), aux_src->getWidth(), aux_src->getHeight(), 1); + self->mBakedTextureDatas[BAKED_HEAD].mTexLayerSet->applyMorphMask(aux_src->getData(), aux_src->getWidth(), aux_src->getHeight(), 1); maskData->mLastDiscardLevel = discard_level; */ bool found_texture_id = false; for (LLVOAvatarDictionary::texture_map_t::const_iterator iter = LLVOAvatarDictionary::getInstance()->getTextures().begin(); iter != LLVOAvatarDictionary::getInstance()->getTextures().end(); - iter++) + ++iter) { const LLVOAvatarDictionary::TextureDictionaryEntry *text_dict = iter->second; @@ -9578,16 +9439,16 @@ void LLVOAvatar::onBakedTextureMasksLoaded( BOOL success, LLViewerFetchedTexture if (baked_img && id == baked_img->getID()) { const EBakedTextureIndex baked_index = text_dict->mBakedTextureIndex; - if (self->mBakedTextureData[baked_index].mTexLayerSet) + if (self->mBakedTextureDatas[baked_index].mTexLayerSet) { //llinfos << "onBakedTextureMasksLoaded for " << text_dict->mName << " " << id << " discard = " << discard_level << llendl; - self->mBakedTextureData[baked_index].mTexLayerSet->applyMorphMask(aux_src->getData(), aux_src->getWidth(), aux_src->getHeight(), 1); + self->mBakedTextureDatas[baked_index].mTexLayerSet->applyMorphMask(aux_src->getData(), aux_src->getWidth(), aux_src->getHeight(), 1); maskData->mLastDiscardLevel = discard_level; - if (self->mBakedTextureData[baked_index].mMaskTexName) + if (self->mBakedTextureDatas[baked_index].mMaskTexName) { - LLImageGL::deleteTextures(1, &(self->mBakedTextureData[baked_index].mMaskTexName)); + LLImageGL::deleteTextures(1, &(self->mBakedTextureDatas[baked_index].mMaskTexName)); } - self->mBakedTextureData[baked_index].mMaskTexName = gl_name; + self->mBakedTextureDatas[baked_index].mMaskTexName = gl_name; } else { @@ -9667,26 +9528,26 @@ void LLVOAvatar::useBakedTexture( const LLUUID& id ) mLastHeadBakedID = id; mHeadMesh0.setTexture( head_baked ); mHeadMesh1.setTexture( head_baked ); */ - for (U32 i = 0; i < mBakedTextureData.size(); i++) + for (U32 i = 0; i < mBakedTextureDatas.size(); i++) { - LLViewerTexture* image_baked = getTEImage( mBakedTextureData[i].mTextureIndex ); + LLViewerTexture* image_baked = getTEImage( mBakedTextureDatas[i].mTextureIndex ); if (id == image_baked->getID()) { - mBakedTextureData[i].mIsLoaded = true; - mBakedTextureData[i].mIsUsed = true; - mBakedTextureData[i].mLastTextureIndex = id; - for (U32 k = 0; k < mBakedTextureData[i].mMeshes.size(); k++) + mBakedTextureDatas[i].mIsLoaded = true; + mBakedTextureDatas[i].mLastTextureIndex = id; + mBakedTextureDatas[i].mIsUsed = true; + for (U32 k = 0; k < mBakedTextureDatas[i].mMeshes.size(); k++) { - mBakedTextureData[i].mMeshes[k]->setTexture( image_baked ); + mBakedTextureDatas[i].mMeshes[k]->setTexture( image_baked ); } - if (mBakedTextureData[i].mTexLayerSet) + if (mBakedTextureDatas[i].mTexLayerSet) { - mBakedTextureData[i].mTexLayerSet->destroyComposite(); + mBakedTextureDatas[i].mTexLayerSet->destroyComposite(); } const LLVOAvatarDictionary::BakedDictionaryEntry *baked_dict = LLVOAvatarDictionary::getInstance()->getBakedTexture((EBakedTextureIndex)i); for (texture_vec_t::const_iterator local_tex_iter = baked_dict->mLocalTextures.begin(); local_tex_iter != baked_dict->mLocalTextures.end(); - local_tex_iter++) + ++local_tex_iter) { setLocalTexture(*local_tex_iter, LLViewerTextureManager::staticCastToFetchedTexture(getTEImage(*local_tex_iter)), TRUE); } @@ -9696,9 +9557,9 @@ void LLVOAvatar::useBakedTexture( const LLUUID& id ) // This is paired with similar code in updateMeshTextures that sets hair mesh color. if (i == BAKED_HAIR) { - for (U32 i = 0; i < mBakedTextureData[BAKED_HAIR].mMeshes.size(); i++) + for (U32 i = 0; i < mBakedTextureDatas[BAKED_HAIR].mMeshes.size(); i++) { - mBakedTextureData[BAKED_HAIR].mMeshes[i]->setColor( 1.f, 1.f, 1.f, 1.f ); + mBakedTextureDatas[BAKED_HAIR].mMeshes[i]->setColor( 1.f, 1.f, 1.f, 1.f ); } } } @@ -9758,19 +9619,13 @@ void LLVOAvatar::dumpArchetypeXML( void* ) apr_file_printf( file, "\n\n" ); } - -U32 LLVOAvatar::getVisibilityRank() -{ - return mVisibilityRank; -} - void LLVOAvatar::setVisibilityRank(U32 rank) { - if (!mDrawable || mDrawable.isNull() || mDrawable->isDead()) - { //do nothing + if (mDrawable.isNull() || mDrawable->isDead()) + { + // do nothing return; } - mVisibilityRank = rank; } @@ -9779,15 +9634,14 @@ S32 LLVOAvatar::getUnbakedPixelAreaRank() { S32 rank = 1; for (std::vector::iterator iter = LLCharacter::sInstances.begin(); - iter != LLCharacter::sInstances.end(); ++iter) + iter != LLCharacter::sInstances.end(); ++iter) { LLVOAvatar* inst = (LLVOAvatar*) *iter; - if( inst == this ) + if (inst == this) { return rank; } - else - if( !inst->isDead() && !inst->isFullyBaked() ) + else if (!inst->isDead() && !inst->isFullyBaked()) { rank++; } @@ -9799,7 +9653,7 @@ S32 LLVOAvatar::getUnbakedPixelAreaRank() struct CompareScreenAreaGreater { - bool operator()(const LLCharacter* const& lhs, const LLCharacter* const& rhs) + BOOL operator()(const LLCharacter* const& lhs, const LLCharacter* const& rhs) { return lhs->getPixelArea() > rhs->getPixelArea(); } @@ -9837,7 +9691,7 @@ void LLVOAvatar::cullAvatarsByPixelArea() { inst->setVisibilityRank(0); } - else if (inst->mDrawable && inst->mDrawable.notNull() && inst->mDrawable->isVisible()) + else if (inst->mDrawable.notNull() && inst->mDrawable->isVisible()) { inst->setVisibilityRank(rank++); } @@ -10018,12 +9872,12 @@ void LLVOAvatar::startAppearanceAnimation(BOOL set_by_user, BOOL play_sound) void LLVOAvatar::removeMissingBakedTextures() { - if (!mIsSelf) return; + if (!isSelf()) return; BOOL removed = FALSE; - for (U32 i = 0; i < mBakedTextureData.size(); i++) + for (U32 i = 0; i < mBakedTextureDatas.size(); i++) { - const S32 te = mBakedTextureData[i].mTextureIndex; + const S32 te = mBakedTextureDatas[i].mTextureIndex; if (getTEImage(te)->isMissingAsset()) { setTEImage(te, LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT_AVATAR)); @@ -10033,26 +9887,25 @@ void LLVOAvatar::removeMissingBakedTextures() if (removed) { - for(U32 i = 0; i < mBakedTextureData.size(); i++) + for(U32 i = 0; i < mBakedTextureDatas.size(); i++) { - invalidateComposite(mBakedTextureData[i].mTexLayerSet, FALSE); + invalidateComposite(mBakedTextureDatas[i].mTexLayerSet, FALSE); } updateMeshTextures(); requestLayerSetUploads(); } } - //----------------------------------------------------------------------------- // LLVOAvatarXmlInfo //----------------------------------------------------------------------------- -LLVOAvatarXmlInfo::LLVOAvatarXmlInfo() +LLVOAvatar::LLVOAvatarXmlInfo::LLVOAvatarXmlInfo() : mTexSkinColorInfo(0), mTexHairColorInfo(0), mTexEyeColorInfo(0) { } -LLVOAvatarXmlInfo::~LLVOAvatarXmlInfo() +LLVOAvatar::LLVOAvatarXmlInfo::~LLVOAvatarXmlInfo() { std::for_each(mMeshInfoList.begin(), mMeshInfoList.end(), DeletePointer()); std::for_each(mSkeletalDistortionInfoList.begin(), mSkeletalDistortionInfoList.end(), DeletePointer()); @@ -10173,7 +10026,7 @@ BOOL LLVOAvatarSkeletonInfo::parseXml(LLXmlTreeNode* node) //----------------------------------------------------------------------------- // parseXmlSkeletonNode(): parses nodes from XML tree //----------------------------------------------------------------------------- -BOOL LLVOAvatarXmlInfo::parseXmlSkeletonNode(LLXmlTreeNode* root) +BOOL LLVOAvatar::LLVOAvatarXmlInfo::parseXmlSkeletonNode(LLXmlTreeNode* root) { LLXmlTreeNode* node = root->getChildByName( "skeleton" ); if( !node ) @@ -10279,7 +10132,7 @@ BOOL LLVOAvatarXmlInfo::parseXmlSkeletonNode(LLXmlTreeNode* root) //----------------------------------------------------------------------------- // parseXmlMeshNodes(): parses nodes from XML tree //----------------------------------------------------------------------------- -BOOL LLVOAvatarXmlInfo::parseXmlMeshNodes(LLXmlTreeNode* root) +BOOL LLVOAvatar::LLVOAvatarXmlInfo::parseXmlMeshNodes(LLXmlTreeNode* root) { for (LLXmlTreeNode* node = root->getChildByName( "mesh" ); node; @@ -10369,7 +10222,7 @@ BOOL LLVOAvatarXmlInfo::parseXmlMeshNodes(LLXmlTreeNode* root) //----------------------------------------------------------------------------- // parseXmlColorNodes(): parses nodes from XML tree //----------------------------------------------------------------------------- -BOOL LLVOAvatarXmlInfo::parseXmlColorNodes(LLXmlTreeNode* root) +BOOL LLVOAvatar::LLVOAvatarXmlInfo::parseXmlColorNodes(LLXmlTreeNode* root) { for (LLXmlTreeNode* color_node = root->getChildByName( "global_color" ); color_node; @@ -10431,7 +10284,7 @@ BOOL LLVOAvatarXmlInfo::parseXmlColorNodes(LLXmlTreeNode* root) //----------------------------------------------------------------------------- // parseXmlLayerNodes(): parses nodes from XML tree //----------------------------------------------------------------------------- -BOOL LLVOAvatarXmlInfo::parseXmlLayerNodes(LLXmlTreeNode* root) +BOOL LLVOAvatar::LLVOAvatarXmlInfo::parseXmlLayerNodes(LLXmlTreeNode* root) { for (LLXmlTreeNode* layer_node = root->getChildByName( "layer_set" ); layer_node; @@ -10455,7 +10308,7 @@ BOOL LLVOAvatarXmlInfo::parseXmlLayerNodes(LLXmlTreeNode* root) //----------------------------------------------------------------------------- // parseXmlDriverNodes(): parses nodes from XML tree //----------------------------------------------------------------------------- -BOOL LLVOAvatarXmlInfo::parseXmlDriverNodes(LLXmlTreeNode* root) +BOOL LLVOAvatar::LLVOAvatarXmlInfo::parseXmlDriverNodes(LLXmlTreeNode* root) { LLXmlTreeNode* driver = root->getChildByName( "driver_parameters" ); if( driver ) @@ -10493,7 +10346,7 @@ S32 LLVOAvatar::getAttachmentCount() //virtual void LLVOAvatar::updateRegion(LLViewerRegion *regionp) { - if (mIsSelf) + if (isSelf()) { if (regionp->getHandle() != mLastRegionHandle) { @@ -10541,7 +10394,7 @@ LLTexLayerSet* LLVOAvatar::getLayerSet(ETextureIndex index) const if (text_dict->mIsUsedByBakedTexture) { const EBakedTextureIndex baked_index = text_dict->mBakedTextureIndex; - return mBakedTextureData[baked_index].mTexLayerSet; + return mBakedTextureDatas[baked_index].mTexLayerSet; } return NULL; } @@ -10585,7 +10438,7 @@ BOOL LLVOAvatar::updateLOD() BOOL res = updateJointLODs(); LLFace* facep = mDrawable->getFace(0); - if (facep->mVertexBuffer.isNull()) + if (!facep->getVertexBuffer()) { dirtyMesh(2); } @@ -10604,7 +10457,8 @@ BOOL LLVOAvatar::updateLOD() } U32 LLVOAvatar::getPartitionType() const -{ //avatars merely exist as drawables in the bridge partition +{ + // Avatars merely exist as drawables in the bridge partition return LLViewerRegion::PARTITION_BRIDGE; } @@ -10758,7 +10612,7 @@ const std::string LLVOAvatar::getBakedStatusForPrintout() const for (LLVOAvatarDictionary::texture_map_t::const_iterator iter = LLVOAvatarDictionary::getInstance()->getTextures().begin(); iter != LLVOAvatarDictionary::getInstance()->getTextures().end(); - iter++) + ++iter) { const ETextureIndex index = iter->first; const LLVOAvatarDictionary::TextureDictionaryEntry *text_dict = iter->second; diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index e21337c90..6ec9179c8 100644 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -69,561 +69,170 @@ class LLTexLayerSet; class LLVoiceVisualizer; class LLHUDText; class LLHUDEffectSpiral; - class LLTexGlobalColor; - +class LLTexGlobalColorInfo; +class LLTexLayerSetInfo; +class LLDriverParamInfo; class LLVOAvatarBoneInfo; class LLVOAvatarSkeletonInfo; -class LLVOAvatarXmlInfo; - - -//------------------------------------------------------------------------ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // LLVOAvatar -//------------------------------------------------------------------------ +// +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ class LLVOAvatar : public LLViewerObject, public LLCharacter { protected: - virtual ~LLVOAvatar(); + struct LLVOAvatarXmlInfo; + +/******************************************************************************** + ** ** + ** INITIALIZATION + **/ public: LLVOAvatar(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp); /*virtual*/ void markDead(); - void startDefaultMotions(); + static void initClass(); // Initialize data that's only init'd once per class. + static void cleanupClass(); // Cleanup data that's only init'd once per class. +protected: + virtual ~LLVOAvatar(); + BOOL loadSkeletonNode(); + BOOL loadMeshNodes(); - static void updateImpostors(); +/** Initialization + ** ** + *******************************************************************************/ - // - void getClientInfo(std::string& clientTag, LLColor4& tagColor, BOOL useComment=FALSE); - std::string extraMetadata; - // +/******************************************************************************** + ** ** + ** INHERITED + **/ - // EmeraldBoobUtils - bool mSupportsPhysics; //Client supports v2 wearable physics. Disable emerald physics. - //-------------------------------------------------------------------- - // LLViewerObject interface + // LLViewerObject interface and related //-------------------------------------------------------------------- public: virtual void updateGL(); - static void initClass(); // Initialize data that's only init'd once per class. - static void cleanupClass(); // Cleanup data that's only init'd once per class. - static BOOL parseSkeletonFile(const std::string& filename); - virtual U32 processUpdateMessage(LLMessageSystem *mesgsys, - void **user_data, - U32 block_num, - const EObjectUpdateType update_type, - LLDataPacker *dp); + virtual U32 processUpdateMessage(LLMessageSystem *mesgsys, + void **user_data, + U32 block_num, + const EObjectUpdateType update_type, + LLDataPacker *dp); /*virtual*/ BOOL idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time); - void idleUpdateVoiceVisualizer(bool voice_enabled); - void idleUpdateMisc(bool detailed_update); + virtual BOOL updateLOD(); + BOOL updateJointLODs(); + /*virtual*/ BOOL isActive() const; // Whether this object needs to do an idleUpdate. + /*virtual*/ void updateTextures(); + /*virtual*/ S32 setTETexture(const U8 te, const LLUUID& uuid); // If setting a baked texture, need to request it from a non-local sim. + /*virtual*/ void onShift(const LLVector3& shift_vector); + virtual U32 getPartitionType() const; + virtual const LLVector3 getRenderPosition() const; + virtual void updateDrawable(BOOL force_damped); + /*virtual*/ LLDrawable* createDrawable(LLPipeline *pipeline); + /*virtual*/ BOOL updateGeometry(LLDrawable *drawable); + /*virtual*/ void setPixelAreaAndAngle(LLAgent &agent); + virtual void updateRegion(LLViewerRegion *regionp); + void updateSpatialExtents(LLVector3& newMin, LLVector3 &newMax); + void getSpatialExtents(LLVector3& newMin, LLVector3& newMax); + /*virtual*/ BOOL lineSegmentIntersect(const LLVector3& start, const LLVector3& end, + S32 face = -1, // which face to check, -1 = ALL_SIDES + BOOL pick_transparent = FALSE, + S32* face_hit = NULL, // which face was hit + LLVector3* intersection = NULL, // return the intersection point + LLVector2* tex_coord = NULL, // return the texture coordinates of the intersection point + LLVector3* normal = NULL, // return the surface normal at the intersection point + LLVector3* bi_normal = NULL); // return the surface bi-normal at the intersection point + + //-------------------------------------------------------------------- + // LLCharacter interface and related + //-------------------------------------------------------------------- +public: + virtual LLVector3 getCharacterPosition(); + virtual LLQuaternion getCharacterRotation(); + virtual LLVector3 getCharacterVelocity(); + virtual LLVector3 getCharacterAngularVelocity(); + virtual LLJoint* getCharacterJoint(U32 num); + virtual BOOL allocateCharacterJoints(U32 num); + + LLUUID remapMotionID(const LLUUID& id); + virtual BOOL startMotion(const LLUUID& id, F32 time_offset = 0.f); + virtual BOOL stopMotion(const LLUUID& id, BOOL stop_immediate = FALSE); + virtual void stopMotionFromSource(const LLUUID& source_id); + virtual void requestStopMotion(LLMotion* motion); + LLMotion* findMotion(const LLUUID& id) const; + void startDefaultMotions(); + + virtual LLJoint* getJoint(const std::string &name); + virtual LLJoint* getRootJoint() { return &mRoot; } + + virtual const char* getAnimationPrefix() { return "avatar"; } + virtual const LLUUID& getID(); + virtual LLVector3 getVolumePos(S32 joint_index, LLVector3& volume_offset); + virtual LLJoint* findCollisionVolume(U32 volume_id); + virtual S32 getCollisionVolumeID(std::string &name); + virtual void addDebugText(const std::string& text); + virtual F32 getTimeDilation(); + virtual void getGround(const LLVector3 &inPos, LLVector3 &outPos, LLVector3 &outNorm); + virtual F32 getPixelArea() const; + virtual LLPolyMesh* getHeadMesh(); + virtual LLPolyMesh* getUpperBodyMesh(); + virtual LLVector3d getPosGlobalFromAgent(const LLVector3 &position); + virtual LLVector3 getPosAgentFromGlobal(const LLVector3d &position); + virtual void updateVisualParams(); + + +/** Inherited + ** ** + *******************************************************************************/ + +/******************************************************************************** + ** ** + ** STATE + **/ + +public: + bool isSelf() const { return mIsSelf; } // True if this avatar is for this viewer's agent + bool isBuilt() const { return mIsBuilt; } +private: + BOOL mSupportsAlphaLayers; // For backwards compatibility, TRUE for 1.23+ clients + + //-------------------------------------------------------------------- + // Updates + //-------------------------------------------------------------------- +public: + BOOL updateCharacter(LLAgent &agent); + void idleUpdateVoiceVisualizer(bool voice_enabled); + void idleUpdateMisc(bool detailed_update); void idleUpdateAppearanceAnimation(); - void idleUpdateLipSync(bool voice_enabled); - void idleUpdateLoadingEffect(); - void idleUpdateWindEffect(); - void idleUpdateBoobEffect(); - void idleUpdateNameTag(const LLVector3& root_pos_last); + void idleUpdateLipSync(bool voice_enabled); + void idleUpdateLoadingEffect(); + void idleUpdateWindEffect(); + void idleUpdateNameTag(const LLVector3& root_pos_last); void clearNameTag(); static void invalidateNameTag(const LLUUID& agent_id); // force all name tags to rebuild, useful when display names turned on/off static void invalidateNameTags(); - void idleUpdateRenderCost(); - void idleUpdateTractorBeam(); - void idleUpdateBelowWater(); - -public: - virtual BOOL updateLOD(); - /*virtual*/ BOOL isActive() const; // Whether this object needs to do an idleUpdate. - - // Graphical stuff for objects - maybe broken out into render class later? - U32 renderFootShadows(); - U32 renderImpostor(LLColor4U color = LLColor4U(255,255,255,255)); - U32 renderRigid(); - U32 renderSkinned(EAvatarRenderPass pass); - U32 renderTransparent(BOOL first_pass); - void renderCollisionVolumes(); + void idleUpdateRenderCost(); + void idleUpdateBelowWater(); + void idleUpdateTractorBeam(); //1.23 + void idleUpdateBoobEffect(); //Emerald - /*virtual*/ BOOL lineSegmentIntersect(const LLVector3& start, const LLVector3& end, - S32 face = -1, // which face to check, -1 = ALL_SIDES - BOOL pick_transparent = FALSE, - S32* face_hit = NULL, // which face was hit - LLVector3* intersection = NULL, // return the intersection point - LLVector2* tex_coord = NULL, // return the texture coordinates of the intersection point - LLVector3* normal = NULL, // return the surface normal at the intersection point - LLVector3* bi_normal = NULL // return the surface bi-normal at the intersection point - ); - - /*virtual*/ void updateTextures(); - // If setting a baked texture, need to request it from a non-local sim. - /*virtual*/ S32 setTETexture(const U8 te, const LLUUID& uuid); - /*virtual*/ void onShift(const LLVector3& shift_vector); - virtual U32 getPartitionType() const; - - void updateVisibility(); - void updateAttachmentVisibility(U32 camera_mode); - void clampAttachmentPositions(); - S32 getAttachmentCount(); // Warning: order(N) not order(1) - BOOL canAttachMoreObjects() const; - - // HUD functions - BOOL hasHUDAttachment() const; - LLBBox getHUDBBox() const; - void rebuildHUD(); - - /*virtual*/ LLDrawable* createDrawable(LLPipeline *pipeline); - /*virtual*/ BOOL updateGeometry(LLDrawable *drawable); - - /*virtual*/ void setPixelAreaAndAngle(LLAgent &agent); - BOOL updateJointLODs(); - - virtual void updateRegion(LLViewerRegion *regionp); - - virtual const LLVector3 getRenderPosition() const; - virtual void updateDrawable(BOOL force_damped); - void updateSpatialExtents(LLVector3& newMin, LLVector3 &newMax); - void getSpatialExtents(LLVector3& newMin, LLVector3& newMax); - BOOL isImpostor() const; - BOOL needsImpostorUpdate() const; - const LLVector3& getImpostorOffset() const; - const LLVector2& getImpostorDim() const; - void getImpostorValues(LLVector3* extents, LLVector3& angle, F32& distance) const; - void cacheImpostorValues(); - void setImpostorDim(const LLVector2& dim); - - //-------------------------------------------------------------------- - // LLCharacter interface - //-------------------------------------------------------------------- -public: - virtual const char *getAnimationPrefix() { return "avatar"; } - virtual LLJoint *getRootJoint() { return &mRoot; } - virtual LLVector3 getCharacterPosition(); - virtual LLQuaternion getCharacterRotation(); - virtual LLVector3 getCharacterVelocity(); - virtual LLVector3 getCharacterAngularVelocity(); - virtual F32 getTimeDilation(); - virtual void getGround(const LLVector3 &inPos, LLVector3 &outPos, LLVector3 &outNorm); - virtual BOOL allocateCharacterJoints( U32 num ); - virtual LLJoint *getCharacterJoint( U32 num ); - virtual void requestStopMotion( LLMotion* motion ); - virtual F32 getPixelArea() const; - virtual LLPolyMesh* getHeadMesh(); - virtual LLPolyMesh* getUpperBodyMesh(); - virtual LLVector3d getPosGlobalFromAgent(const LLVector3 &position); - virtual LLVector3 getPosAgentFromGlobal(const LLVector3d &position); - virtual void updateVisualParams(); - LLUUID remapMotionID(const LLUUID& id); - virtual BOOL startMotion(const LLUUID& id, F32 time_offset = 0.f); - virtual BOOL stopMotion(const LLUUID& id, BOOL stop_immediate = FALSE); - virtual void stopMotionFromSource(const LLUUID& source_id); - virtual LLVector3 getVolumePos(S32 joint_index, LLVector3& volume_offset); - virtual LLJoint* findCollisionVolume(U32 volume_id); - virtual S32 getCollisionVolumeID(std::string &name); - virtual void addDebugText(const std::string& text); - virtual const LLUUID& getID(); - virtual LLJoint *getJoint( const std::string &name ); - - //-------------------------------------------------------------------- - // Other public functions - //-------------------------------------------------------------------- -public: - static void onCustomizeStart(); - static void onCustomizeEnd(); - - - + void updateAttachmentVisibility(U32 camera_mode); //Agent only LLFrameTimer mIdleTimer; - void undeform(); - std::string getIdleTime(); - - - - static void dumpTotalLocalTextureByteCount(); -protected: - void getLocalTextureByteCount( S32* gl_byte_count ); - -public: - LLMotion* findMotion(const LLUUID& id); - - BOOL isVisible(); - BOOL isSelf() const { return mIsSelf; } - BOOL isCulled() const { return mCulled; } - bool isBuilt() const { return mIsBuilt; } -public: - static void cullAvatarsByPixelArea(); - void setVisibilityRank(U32 rank); - U32 getVisibilityRank(); // unused -protected: - S32 getUnbakedPixelAreaRank(); - -public: - void dumpLocalTextures(); - const LLUUID& grabLocalTexture(LLVOAvatarDefines::ETextureIndex index); - BOOL canGrabLocalTexture(LLVOAvatarDefines::ETextureIndex index); - BOOL isTextureDefined(U8 te) const; - BOOL isTextureVisible(U8 te) const; - void startAppearanceAnimation(BOOL set_by_user, BOOL play_sound); - - void setCompositeUpdatesEnabled(BOOL b); - - void addChat(const LLChat& chat); - void clearChat(); - void startTyping() { mTyping = TRUE; mTypingTimer.reset(); mIdleTimer.reset();} - void stopTyping() { mTyping = FALSE; } - - void setNameFromChat(const std::string &text) { mNameFromChatOverride = mNameFromChatChanged = true; mNameFromChatText = text; } - void clearNameFromChat() { mNameFromChatOverride = false; mNameFromChatChanged = true; mNameFromChatText = ""; } - - // Returns "FirstName LastName" - std::string getFullname() const; - - BOOL updateCharacter(LLAgent &agent); - void updateHeadOffset(); - - F32 getPelvisToFoot() const { return mPelvisToFoot; } - -public: - BOOL isAnyAnimationSignaled(const LLUUID *anim_array, const S32 num_anims); - void processAnimationStateChanges(); -protected: - BOOL processSingleAnimationStateChange(const LLUUID &anim_id, BOOL start); - void resetAnimations(); - -public: - void resolveHeightGlobal(const LLVector3d &inPos, LLVector3d &outPos, LLVector3 &outNorm); - void resolveHeightAgent(const LLVector3 &inPos, LLVector3 &outPos, LLVector3 &outNorm); - void resolveRayCollisionAgent(const LLVector3d start_pt, const LLVector3d end_pt, LLVector3d &out_pos, LLVector3 &out_norm); - void slamPosition(); // Slam position to transmitted position (for teleport); - - // morph targets and such - void processAvatarAppearance( LLMessageSystem* mesgsys ); - void onFirstTEMessageReceived(); - void updateSexDependentLayerSets( BOOL set_by_user ); - void hideSkirt(); - - - virtual BOOL setParent(LLViewerObject* parent); - virtual void addChild(LLViewerObject *childp); - virtual void removeChild(LLViewerObject *childp); - -// [RLVa:KB] - Checked: 2009-12-18 (RLVa-1.1.0i) | Added: RLVa-1.1.0i - LLViewerJointAttachment* getTargetAttachmentPoint(const LLViewerObject* viewer_object) const; -// [/RLVa:KB] - BOOL attachObject(LLViewerObject *viewer_object); - BOOL detachObject(LLViewerObject *viewer_object); - void lazyAttach(); - - static BOOL detachAttachmentIntoInventory(const LLUUID& item_id); - - void sitOnObject(LLViewerObject *sit_object); - void getOffObject(); - - BOOL isWearingAttachment( const LLUUID& inv_item_id ); - // testzone attachpt - BOOL isWearingUnsupportedAttachment( const LLUUID& inv_item_id ); - // - LLViewerObject* getWornAttachment( const LLUUID& inv_item_id ); -// [RLVa:KB] - Checked: 2010-03-14 (RLVa-1.2.0a) | Added: RLVa-1.1.0i - LLViewerJointAttachment* getWornAttachmentPoint(const LLUUID& inv_item_id) const; -// [/RLVa:KB] - const std::string getAttachedPointName(const LLUUID& inv_item_id); - - static LLVOAvatar* findAvatarFromAttachment( LLViewerObject* obj ); - - void updateMeshTextures(); - //-------------------------------------------------------------------- - // texture compositing (used only by the LLTexLayer series of classes) - //-------------------------------------------------------------------- -public: - LLColor4 getGlobalColor( const std::string& color_name ); - BOOL isLocalTextureDataAvailable( const LLTexLayerSet* layerset ); - BOOL isLocalTextureDataFinal( const LLTexLayerSet* layerset ); - LLVOAvatarDefines::ETextureIndex getBakedTE( LLTexLayerSet* layerset ); - void updateComposites(); - void onGlobalColorChanged( LLTexGlobalColor* global_color, BOOL set_by_user ); - //BOOL getLocalTextureRaw( LLVOAvatarDefines::ETextureIndex index, LLImageRaw* image_raw_pp ); - BOOL getLocalTextureGL( LLVOAvatarDefines::ETextureIndex index, LLViewerTexture** image_gl_pp ); - const LLUUID& getLocalTextureID( LLVOAvatarDefines::ETextureIndex index ); - LLGLuint getScratchTexName( LLGLenum format, U32* texture_bytes ); - BOOL bindScratchTexture( LLGLenum format ); - void invalidateComposite( LLTexLayerSet* layerset, BOOL set_by_user ); - void invalidateAll(); - void forceBakeAllTextures(bool slam_for_debug = false); - static void processRebakeAvatarTextures(LLMessageSystem* msg, void**); - void setNewBakedTexture( LLVOAvatarDefines::ETextureIndex i, const LLUUID& uuid ); - void setCachedBakedTexture( LLVOAvatarDefines::ETextureIndex i, const LLUUID& uuid ); - void releaseUnnecessaryTextures(); - void requestLayerSetUploads(); - bool hasPendingBakedUploads(); - static void onLocalTextureLoaded( BOOL succcess, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata ); - static void dumpArchetypeXML( void* ); - static void dumpScratchTextureByteCount(); - static void dumpBakedStatus(); - static void deleteCachedImages(bool clearAll=true); - static void destroyGL(); - static void restoreGL(); - static void resetImpostors(); - static enum EWearableType getTEWearableType(LLVOAvatarDefines::ETextureIndex te ); - static LLUUID getDefaultTEImageID(LLVOAvatarDefines::ETextureIndex te ); - static void onChangeSelfInvisible(BOOL newvalue); - void setInvisible(BOOL newvalue); - static LLColor4 getDummyColor(); - - - - //-------------------------------------------------------------------- - // Clothing colors (conventience functions to access visual parameters - //-------------------------------------------------------------------- -public: - void setClothesColor( LLVOAvatarDefines::ETextureIndex te, const LLColor4& new_color, BOOL set_by_user ); - LLColor4 getClothesColor( LLVOAvatarDefines::ETextureIndex te ); - BOOL teToColorParams( LLVOAvatarDefines::ETextureIndex te, const char* param_name[3] ); - - BOOL isWearingWearableType( EWearableType type ); - void wearableUpdated(EWearableType type, BOOL upload_result = TRUE); - - //-------------------------------------------------------------------- - // texture compositing - //-------------------------------------------------------------------- -public: - void setLocTexTE( U8 te, LLViewerTexture* image, BOOL set_by_user ); - void setupComposites(); - - typedef std::map lod_mesh_map_t; - typedef std::map mesh_info_t; - - static void getMeshInfo (mesh_info_t* mesh_info); - - //-------------------------------------------------------------------- - // Handling partially loaded avatars (Ruth) - //-------------------------------------------------------------------- -public: - BOOL isFullyLoaded(); - //BOOL isReallyFullyLoaded(); - BOOL updateIsFullyLoaded(); -protected: - bool sendAvatarTexturesRequest(); - void updateRuthTimer(bool loading); -private: - BOOL mFullyLoaded; - BOOL mPreviousFullyLoaded; - BOOL mFullyLoadedInitialized; - S32 mFullyLoadedFrameCounter; - LLFrameTimer mFullyLoadedTimer; - LLFrameTimer mRuthTimer; - - //-------------------------------------------------------------------- - // Collision Volumes - //-------------------------------------------------------------------- -public: - S32 mNumCollisionVolumes; - LLViewerJointCollisionVolume* mCollisionVolumes; - - //-------------------------------------------------------------------- - // cached pointers to well known joints - //-------------------------------------------------------------------- -public: - LLViewerJoint* mPelvisp; - LLViewerJoint* mTorsop; - LLViewerJoint* mChestp; - LLViewerJoint* mNeckp; - LLViewerJoint* mHeadp; - LLViewerJoint* mSkullp; - LLViewerJoint* mEyeLeftp; - LLViewerJoint* mEyeRightp; - LLViewerJoint* mHipLeftp; - LLViewerJoint* mHipRightp; - LLViewerJoint* mKneeLeftp; - LLViewerJoint* mKneeRightp; - LLViewerJoint* mAnkleLeftp; - LLViewerJoint* mAnkleRightp; - LLViewerJoint* mFootLeftp; - LLViewerJoint* mFootRightp; - LLViewerJoint* mWristLeftp; - LLViewerJoint* mWristRightp; - - //-------------------------------------------------------------------- - // impostor state - //-------------------------------------------------------------------- -public: - LLRenderTarget mImpostor; - BOOL mNeedsImpostorUpdate; -private: - LLVector3 mImpostorOffset; - LLVector2 mImpostorDim; - BOOL mNeedsAnimUpdate; - LLVector3 mImpostorExtents[2]; - LLVector3 mImpostorAngle; - F32 mImpostorDistance; - F32 mImpostorPixelArea; - LLVector3 mLastAnimExtents[2]; - - //-------------------------------------------------------------------- - // Misc Render State - //-------------------------------------------------------------------- -public: - BOOL mIsDummy; // For special views - S32 mSpecialRenderMode; // Special lighting - - //-------------------------------------------------------------------- - // animation state data - //-------------------------------------------------------------------- -public: - typedef std::map::iterator AnimIterator; - - std::map mSignaledAnimations; // requested state of Animation name/value - std::map mPlayingAnimations; // current state of Animation name/value - - typedef std::multimap AnimationSourceMap; - typedef AnimationSourceMap::iterator AnimSourceIterator; - AnimationSourceMap mAnimationSources; // object ids that triggered anim ids - - //-------------------------------------------------------------------- - // Shadowing - //-------------------------------------------------------------------- -public: - void updateShadowFaces(); - LLDrawable* mShadow; -private: - LLFace* mShadow0Facep; - LLFace* mShadow1Facep; - LLPointer mShadowImagep; - - //-------------------------------------------------------------------- - // Keeps track of foot step state for generating sounds - //-------------------------------------------------------------------- -public: - void setFootPlane(const LLVector4 &plane) { mFootPlane = plane; } - LLVector4 mFootPlane; -private: - BOOL mWasOnGroundLeft; - BOOL mWasOnGroundRight; - - //-------------------------------------------------------------------- - // Pelvis height adjustment members. - //-------------------------------------------------------------------- -public: - LLVector3 mBodySize; - S32 mLastSkeletonSerialNum; -private: - F32 mPelvisToFoot; - - //-------------------------------------------------------------------- - // Display the name, then optionally fade it out - //-------------------------------------------------------------------- -public: - LLFrameTimer mChatTimer; - LLPointer mNameText; -private: - LLFrameTimer mTimeVisible; - std::deque mChats; - BOOL mTyping; - LLFrameTimer mTypingTimer; - static void on_avatar_name_response(const LLUUID& agent_id, const LLAvatarName& av_name, void *userdata); - - //-------------------------------------------------------------------- - // wind rippling in clothes - //-------------------------------------------------------------------- -public: - LLVector4 mWindVec; - F32 mRipplePhase; - BOOL mBelowWater; -private: - F32 mWindFreq; - LLFrameTimer mRippleTimer; - F32 mRippleTimeLast; - LLVector3 mRippleAccel; - LLVector3 mLastVel; - - //-------------------------------------------------------------------- - // appearance morphing - //-------------------------------------------------------------------- -public: - BOOL mAppearanceAnimating; -private: - LLFrameTimer mAppearanceMorphTimer; - BOOL mAppearanceAnimSetByUser; - F32 mLastAppearanceBlendTime; - - //-------------------------------------------------------------------- - // boob bounce stuff - //-------------------------------------------------------------------- - -private: - bool mFirstSetActualBoobGravRan; - //bool mFirstSetActualButtGravRan; - //bool mFirstSetActualFatGravRan; - LLFrameTimer mBoobBounceTimer; - EmeraldAvatarLocalBoobConfig mLocalBoobConfig; - EmeraldBoobState mBoobState; - //EmeraldBoobState mButtState; - //EmeraldBoobState mFatState; - -public: - //boob - F32 getActualBoobGrav() { return mLocalBoobConfig.actualBoobGrav; } - void setActualBoobGrav(F32 grav) - { - mLocalBoobConfig.actualBoobGrav = grav; - if(!mFirstSetActualBoobGravRan) - { - mBoobState.boobGrav = grav; - mFirstSetActualBoobGravRan = true; - } - } - - //butt - /*F32 getActualButtGrav() { return mLocalBoobConfig.actualButtGrav; } - void setActualButtGrav(F32 grav) - { - mLocalBoobConfig.actualButtGrav = grav; - if(!mFirstSetActualButtGravRan) - { - mButtState.boobGrav = grav; - mFirstSetActualButtGravRan = true; - } - } - //fat - F32 getActualFatGrav() { return mLocalBoobConfig.actualFatGrav; } - void setActualFatGrav(F32 grav) - { - mLocalBoobConfig.actualFatGrav = grav; - if(!mFirstSetActualFatGravRan) - { - mFatState.boobGrav = grav; - mFirstSetActualFatGravRan = true; - } - } - */ - static EmeraldGlobalBoobConfig sBoobConfig; - - //-------------------------------------------------------------------- - // Attachments - //-------------------------------------------------------------------- -public: - // map of attachment points, by ID - typedef std::map attachment_map_t; - attachment_map_t mAttachmentPoints; - std::vector > mPendingAttachment; - // - std::map mUnsupportedAttachmentPoints; - // -protected: - U32 getNumAttachments() const; // O(N), not O(1) - - //-------------------------------------------------------------------- - // static preferences that are controlled by user settings/menus + // Static preferences (controlled by user settings/menus) //-------------------------------------------------------------------- public: static S32 sRenderName; - static BOOL sRenderGroupTitles; - static S32 sMaxVisible; - static F32 sRenderDistance; //distance at which avatars will render (affected by control "RenderAvatarMaxVisible") + static bool sRenderGroupTitles; + static U32 sMaxVisible; //(affected by control "RenderAvatarMaxVisible") + static F32 sRenderDistance; //distance at which avatars will render. static BOOL sShowAnimationDebug; // show animation debug info static BOOL sUseImpostors; //use impostors for far away avatars static BOOL sShowFootPlane; // show foot collision plane reported by server @@ -635,186 +244,911 @@ public: static F32 sLODFactor; // user-settable LOD factor static F32 sPhysicsLODFactor; // user-settable physics LOD factor static BOOL sJointDebug; // output total number of joints being touched for each avatar - static BOOL sDebugAvatarRotation; - static F32 sAvMorphTime; + static BOOL sDebugAvatarRotation; - static S32 sNumVisibleAvatars; // Number of instances of this class + //-------------------------------------------------------------------- + // Region state + //-------------------------------------------------------------------- +public: + LLHost getObjectHost() const; + + //-------------------------------------------------------------------- + // Loading state + //-------------------------------------------------------------------- +public: + BOOL isFullyLoaded() const; + //BOOL isReallyFullyLoaded(); + BOOL updateIsFullyLoaded(); +protected: + bool sendAvatarTexturesRequest(); + void updateRuthTimer(bool loading); +private: + BOOL mFullyLoaded; + BOOL mPreviousFullyLoaded; + BOOL mFullyLoadedInitialized; + S32 mFullyLoadedFrameCounter; + LLFrameTimer mFullyLoadedTimer; + LLFrameTimer mRuthTimer; + +/** State + ** ** + *******************************************************************************/ + +/******************************************************************************** + ** ** + ** SKELETON + **/ + +public: + void updateHeadOffset(); + F32 getPelvisToFoot() const { return mPelvisToFoot; } + + LLVector3 mHeadOffset; // current head position + LLViewerJoint mRoot; +protected: + static BOOL parseSkeletonFile(const std::string& filename); + void buildCharacter(); + BOOL loadAvatar(); + + BOOL setupBone(const LLVOAvatarBoneInfo* info, LLViewerJoint* parent, S32 ¤t_volume_num, S32 ¤t_joint_num); + BOOL buildSkeleton(const LLVOAvatarSkeletonInfo *info); +private: + BOOL mIsBuilt; // state of deferred character building + S32 mNumJoints; + LLViewerJoint* mSkeleton; //-------------------------------------------------------------------- - // Miscellaneous public variables. + // Pelvis height adjustment members. + //-------------------------------------------------------------------- +public: + LLVector3 mBodySize; + S32 mLastSkeletonSerialNum; +private: + F32 mPelvisToFoot; + + //-------------------------------------------------------------------- + // Cached pointers to well known joints + //-------------------------------------------------------------------- +public: + LLViewerJoint* mPelvisp; + LLViewerJoint* mTorsop; + LLViewerJoint* mChestp; + LLViewerJoint* mNeckp; + LLViewerJoint* mHeadp; + LLViewerJoint* mSkullp; + LLViewerJoint* mEyeLeftp; + LLViewerJoint* mEyeRightp; + LLViewerJoint* mHipLeftp; + LLViewerJoint* mHipRightp; + LLViewerJoint* mKneeLeftp; + LLViewerJoint* mKneeRightp; + LLViewerJoint* mAnkleLeftp; + LLViewerJoint* mAnkleRightp; + LLViewerJoint* mFootLeftp; + LLViewerJoint* mFootRightp; + LLViewerJoint* mWristLeftp; + LLViewerJoint* mWristRightp; + + //-------------------------------------------------------------------- + // XML parse tree + //-------------------------------------------------------------------- +private: + static LLXmlTree sXMLTree; // avatar config file + static LLXmlTree sSkeletonXMLTree; // avatar skeleton file + +/** Skeleton + ** ** + *******************************************************************************/ + +/******************************************************************************** + ** ** + ** RENDERING + **/ + +public: + // Graphical stuff for objects - maybe broken out into render class later? + U32 renderFootShadows(); + U32 renderImpostor(LLColor4U color = LLColor4U(255,255,255,255), S32 diffuse_channel = 0); + U32 renderRigid(); + U32 renderSkinned(EAvatarRenderPass pass); + U32 renderTransparent(BOOL first_pass); + void renderCollisionVolumes(); + static void deleteCachedImages(bool clearAll=true); + static void destroyGL(); + static void restoreGL(); + BOOL mIsDummy; // for special views + S32 mSpecialRenderMode; // special lighting +private: + bool shouldAlphaMask(); + + BOOL mNeedsSkin; // avatar has been animated and verts have not been updated + S32 mUpdatePeriod; + S32 mNumInitFaces; //number of faces generated when creating the avatar drawable, does not inculde splitted faces due to long vertex buffer. + + //-------------------------------------------------------------------- + // Visibility + //-------------------------------------------------------------------- +protected: + void updateVisibility(); +private: + U32 mVisibilityRank; + BOOL mVisible; + + //-------------------------------------------------------------------- + // Shadowing + //-------------------------------------------------------------------- +public: + void updateShadowFaces(); + LLDrawable* mShadow; +private: + LLFace* mShadow0Facep; + LLFace* mShadow1Facep; + LLPointer mShadowImagep; + + //-------------------------------------------------------------------- + // Impostors + //-------------------------------------------------------------------- +public: + BOOL isImpostor() const; + BOOL needsImpostorUpdate() const; + const LLVector3& getImpostorOffset() const; + const LLVector2& getImpostorDim() const; + void getImpostorValues(LLVector3* extents, LLVector3& angle, F32& distance) const; + void cacheImpostorValues(); + void setImpostorDim(const LLVector2& dim); + static void resetImpostors(); + static void updateImpostors(); + LLRenderTarget mImpostor; + BOOL mNeedsImpostorUpdate; +private: + LLVector3 mImpostorOffset; + LLVector2 mImpostorDim; + BOOL mNeedsAnimUpdate; + LLVector3 mImpostorExtents[2]; + LLVector3 mImpostorAngle; + F32 mImpostorDistance; + F32 mImpostorPixelArea; + LLVector3 mLastAnimExtents[2]; + + //-------------------------------------------------------------------- + // Wind rippling in clothes + //-------------------------------------------------------------------- +public: + LLVector4 mWindVec; + F32 mRipplePhase; + BOOL mBelowWater; +private: + F32 mWindFreq; + LLFrameTimer mRippleTimer; + F32 mRippleTimeLast; + LLVector3 mRippleAccel; + LLVector3 mLastVel; + + //-------------------------------------------------------------------- + // Culling + //-------------------------------------------------------------------- +public: + static void cullAvatarsByPixelArea(); + BOOL isCulled() const { return mCulled; } +private: + BOOL mCulled; + + //-------------------------------------------------------------------- + // Freeze counter + //-------------------------------------------------------------------- +public: + static void updateFreezeCounter(S32 counter = 0); +private: + static S32 sFreezeCounter; + + //-------------------------------------------------------------------- + // Internal functions + //-------------------------------------------------------------------- +protected: + BOOL needsRenderBeam(); +/** Rendering + ** ** + *******************************************************************************/ + +/******************************************************************************** + ** ** + ** TEXTURES + **/ + + //-------------------------------------------------------------------- + // Loading status + //-------------------------------------------------------------------- +public: + BOOL isTextureDefined(U8 te) const; + BOOL isTextureVisible(U8 te) const; + +protected: + BOOL isFullyBaked(); + static BOOL areAllNearbyInstancesBaked(S32& grey_avatars); + + //-------------------------------------------------------------------- + // Baked textures + //-------------------------------------------------------------------- +public: +protected: + static void onBakedTextureMasksLoaded(BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata); + static void onInitialBakedTextureLoaded(BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata); + static void onBakedTextureLoaded(BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata); + void removeMissingBakedTextures(); + void useBakedTexture(const LLUUID& id); + + struct BakedTextureData + { + LLUUID mLastTextureIndex; + LLTexLayerSet* mTexLayerSet; // Only exists for self + bool mIsLoaded; + bool mIsUsed; + LLVOAvatarDefines::ETextureIndex mTextureIndex; + U32 mMaskTexName; + // Stores pointers to the joint meshes that this baked texture deals with + std::vector< LLViewerJointMesh * > mMeshes; // std::vector mJoints[i]->mMeshParts + }; + typedef std::vector bakedtexturedata_vec_t; + bakedtexturedata_vec_t mBakedTextureDatas; + //-------------------------------------------------------------------- + // Local Textures + //-------------------------------------------------------------------- +protected: + void setLocalTexture(LLVOAvatarDefines::ETextureIndex i, LLViewerFetchedTexture* tex, BOOL baked_version_exits); + void addLocalTextureStats(LLVOAvatarDefines::ETextureIndex i, LLViewerTexture* imagep, F32 texel_area_ratio, BOOL rendered, BOOL covered_by_baked); + //-------------------------------------------------------------------- + // Layers + //-------------------------------------------------------------------- +protected: + void deleteLayerSetCaches(bool clearAll = true); + void addBakedTextureStats(LLViewerFetchedTexture* imagep, F32 pixel_area, F32 texel_area_ratio, S32 boost_level); + + //-------------------------------------------------------------------- + // Composites + //-------------------------------------------------------------------- +public: + void invalidateComposite( LLTexLayerSet* layerset, BOOL set_by_user ); + void invalidateAll(); + + //-------------------------------------------------------------------- + // Static texture/mesh/baked dictionary + //-------------------------------------------------------------------- +public: + static BOOL isIndexLocalTexture(LLVOAvatarDefines::ETextureIndex i); + static BOOL isIndexBakedTexture(LLVOAvatarDefines::ETextureIndex i); +private: + static const LLVOAvatarDefines::LLVOAvatarDictionary *getDictionary() { return sAvatarDictionary; } + static LLVOAvatarDefines::LLVOAvatarDictionary* sAvatarDictionary; + static LLVOAvatarSkeletonInfo* sAvatarSkeletonInfo; + static LLVOAvatarXmlInfo* sAvatarXmlInfo; + + //-------------------------------------------------------------------- + // Messaging + //-------------------------------------------------------------------- +public: + void onFirstTEMessageReceived(); +private: + BOOL mFirstTEMessageReceived; + BOOL mFirstAppearanceMessageReceived; + + +//Most this stuff is Agent only + + //-------------------------------------------------------------------- + // Textures and Layers + //-------------------------------------------------------------------- +protected: + void requestLayerSetUpdate(LLVOAvatarDefines::ETextureIndex i); + + + LLTexLayerSet* getLayerSet(LLVOAvatarDefines::ETextureIndex index) const; + S32 getLocalDiscardLevel(LLVOAvatarDefines::ETextureIndex index); + + //-------------------------------------------------------------------- + // Other public functions + //-------------------------------------------------------------------- +public: + static void dumpTotalLocalTextureByteCount(); +protected: + void getLocalTextureByteCount( S32* gl_byte_count ); + +public: + void dumpLocalTextures(); + const LLUUID& grabLocalTexture(LLVOAvatarDefines::ETextureIndex index); + BOOL canGrabLocalTexture(LLVOAvatarDefines::ETextureIndex index); + + void setCompositeUpdatesEnabled(BOOL b); + + void setNameFromChat(const std::string &text) { mNameFromChatOverride = mNameFromChatChanged = true; mNameFromChatText = text; } + void clearNameFromChat() { mNameFromChatOverride = false; mNameFromChatChanged = true; mNameFromChatText = ""; } + +public: + + + //-------------------------------------------------------------------- + // texture compositing (used only by the LLTexLayer series of classes) + //-------------------------------------------------------------------- +public: + BOOL isLocalTextureDataAvailable( const LLTexLayerSet* layerset ); + BOOL isLocalTextureDataFinal( const LLTexLayerSet* layerset ); + LLVOAvatarDefines::ETextureIndex getBakedTE( LLTexLayerSet* layerset ); + void updateComposites(); + //BOOL getLocalTextureRaw( LLVOAvatarDefines::ETextureIndex index, LLImageRaw* image_raw_pp ); + BOOL getLocalTextureGL( LLVOAvatarDefines::ETextureIndex index, LLViewerTexture** image_gl_pp ); + const LLUUID& getLocalTextureID( LLVOAvatarDefines::ETextureIndex index ); + LLGLuint getScratchTexName( LLGLenum format, U32* texture_bytes ); + BOOL bindScratchTexture( LLGLenum format ); + void forceBakeAllTextures(bool slam_for_debug = false); + static void processRebakeAvatarTextures(LLMessageSystem* msg, void**); + void setNewBakedTexture( LLVOAvatarDefines::ETextureIndex i, const LLUUID& uuid ); + void setCachedBakedTexture( LLVOAvatarDefines::ETextureIndex i, const LLUUID& uuid ); + void releaseUnnecessaryTextures(); + void requestLayerSetUploads(); + bool hasPendingBakedUploads(); + static void onLocalTextureLoaded( BOOL succcess, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata ); + static enum EWearableType getTEWearableType(LLVOAvatarDefines::ETextureIndex te ); + static LLUUID getDefaultTEImageID(LLVOAvatarDefines::ETextureIndex te ); + static void onChangeSelfInvisible(BOOL newvalue); + void setInvisible(BOOL newvalue); + + void wearableUpdated(EWearableType type, BOOL upload_result = TRUE); + + //-------------------------------------------------------------------- + // texture compositing + //-------------------------------------------------------------------- +public: + void setLocTexTE( U8 te, LLViewerTexture* image, BOOL set_by_user ); + void setupComposites(); + +/** Textures + ** ** + *******************************************************************************/ + +/******************************************************************************** + ** ** + ** MESHES + **/ + +public: + void updateMeshTextures(); + void updateSexDependentLayerSets(BOOL set_by_user); + void dirtyMesh(); // Dirty the avatar mesh + void updateMeshData(); +protected: + void releaseMeshData(); + void restoreMeshData(); +private: + void dirtyMesh(S32 priority); // Dirty the avatar mesh, with priority + S32 mDirtyMesh; // 0 -- not dirty, 1 -- morphed, 2 -- LOD + BOOL mMeshTexturesDirty; + + typedef std::multimap polymesh_map_t; + polymesh_map_t mMeshes; + std::vector mMeshLOD; + + //-------------------------------------------------------------------- + // Destroy invisible mesh + //-------------------------------------------------------------------- +protected: + BOOL mMeshValid; + LLFrameTimer mMeshInvisibleTime; + +/** Meshes + ** ** + *******************************************************************************/ + +/******************************************************************************** + ** ** + ** APPEARANCE + **/ + +public: + void processAvatarAppearance(LLMessageSystem* mesgsys); + void hideSkirt(); + void startAppearanceAnimation(BOOL set_by_user, BOOL play_sound); + LLPolyMesh* getMesh(LLPolyMeshSharedData* shared_data); + + //-------------------------------------------------------------------- + // Appearance morphing + //-------------------------------------------------------------------- +public: + BOOL getIsAppearanceAnimating() const { return mAppearanceAnimating; } +private: + BOOL mAppearanceAnimating; + LLFrameTimer mAppearanceMorphTimer; + F32 mLastAppearanceBlendTime; + BOOL mAppearanceAnimSetByUser; //1.23 + +public: + typedef std::map lod_mesh_map_t; + typedef std::map mesh_info_t; + + static void getMeshInfo(mesh_info_t* mesh_info); + + //-------------------------------------------------------------------- + // Clothing colors (convenience functions to access visual parameters) + //-------------------------------------------------------------------- +public: + void setClothesColor( LLVOAvatarDefines::ETextureIndex te, const LLColor4& new_color, BOOL set_by_user ); + LLColor4 getClothesColor(LLVOAvatarDefines::ETextureIndex te); + static BOOL teToColorParams( LLVOAvatarDefines::ETextureIndex te, const char* param_name[3] ); + + //-------------------------------------------------------------------- + // Global colors + //-------------------------------------------------------------------- +public: + LLColor4 getGlobalColor(const std::string& color_name ) const; + void onGlobalColorChanged(const LLTexGlobalColor* global_color, BOOL set_by_user ); +private: + LLTexGlobalColor* mTexSkinColor; + LLTexGlobalColor* mTexHairColor; + LLTexGlobalColor* mTexEyeColor; + + //-------------------------------------------------------------------- + // Visibility + //-------------------------------------------------------------------- +public: + BOOL isVisible() const; + void setVisibilityRank(U32 rank); + U32 getVisibilityRank() const { return mVisibilityRank; } // unused + static S32 sNumVisibleAvatars; // Number of instances of this class + static LLColor4 getDummyColor(); + + //-------------------------------------------------------------------- + // Customize + //-------------------------------------------------------------------- +public: + static void onCustomizeStart(); + static void onCustomizeEnd(); +/** Appearance + ** ** + *******************************************************************************/ + +/******************************************************************************** + ** ** + ** WEARABLES + **/ + +public: + BOOL isWearingWearableType( EWearableType type ) const; + + //-------------------------------------------------------------------- + // Attachments + //-------------------------------------------------------------------- +public: + void clampAttachmentPositions(); + BOOL attachObject(LLViewerObject *viewer_object); + BOOL detachObject(LLViewerObject *viewer_object); + static LLVOAvatar* findAvatarFromAttachment( LLViewerObject* obj ); +protected: +// [RLVa:KB] - Checked: 2009-12-18 (RLVa-1.1.0i) | Added: RLVa-1.1.0i + LLViewerJointAttachment* getTargetAttachmentPoint(const LLViewerObject* viewer_object) const; +// [/RLVa:KB] + void lazyAttach(); + + //-------------------------------------------------------------------- + // Map of attachment points, by ID + //-------------------------------------------------------------------- +public: + S32 getAttachmentCount(); // Warning: order(N) not order(1) // currently used only by -self + typedef std::map attachment_map_t; + attachment_map_t mAttachmentPoints; + std::vector > mPendingAttachment; + //-------------------------------------------------------------------- + // HUD functions + //-------------------------------------------------------------------- +public: + BOOL hasHUDAttachment() const; + LLBBox getHUDBBox() const; + void rebuildHUD(); + void resetHUDAttachments(); + BOOL canAttachMoreObjects() const; +protected: + U32 getNumAttachments() const; // O(N), not O(1) + + //-------------------------------------------------------------------- + // Old/nonstandard/Agent-only functions + //-------------------------------------------------------------------- +public: + static BOOL detachAttachmentIntoInventory(const LLUUID& item_id); + BOOL isWearingAttachment( const LLUUID& inv_item_id ); + // testzone attachpt + BOOL isWearingUnsupportedAttachment( const LLUUID& inv_item_id ); + // + LLViewerObject* getWornAttachment( const LLUUID& inv_item_id ); +// [RLVa:KB] - Checked: 2010-03-14 (RLVa-1.2.0a) | Added: RLVa-1.1.0i + LLViewerJointAttachment* getWornAttachmentPoint(const LLUUID& inv_item_id) const; +// [/RLVa:KB] + const std::string getAttachedPointName(const LLUUID& inv_item_id); + + // + std::map mUnsupportedAttachmentPoints; + // + +/** Wearables + ** ** + *******************************************************************************/ + +/******************************************************************************** + ** ** + ** ACTIONS + **/ + + //-------------------------------------------------------------------- + // Animations + //-------------------------------------------------------------------- +public: + BOOL isAnyAnimationSignaled(const LLUUID *anim_array, const S32 num_anims) const; + void processAnimationStateChanges(); +protected: + BOOL processSingleAnimationStateChange(const LLUUID &anim_id, BOOL start); + void resetAnimations(); +private: + LLTimer mAnimTimer; + F32 mTimeLast; + + //-------------------------------------------------------------------- + // Animation state data + //-------------------------------------------------------------------- +public: + typedef std::map::iterator AnimIterator; + std::map mSignaledAnimations; // requested state of Animation name/value + std::map mPlayingAnimations; // current state of Animation name/value + + typedef std::multimap AnimationSourceMap; + typedef AnimationSourceMap::iterator AnimSourceIterator; + AnimationSourceMap mAnimationSources; // object ids that triggered anim ids + + //-------------------------------------------------------------------- + // Chat + //-------------------------------------------------------------------- +public: + void addChat(const LLChat& chat); + void clearChat(); + void startTyping() { mTyping = TRUE; mTypingTimer.reset(); mIdleTimer.reset();} + void stopTyping() { mTyping = FALSE; } +private: + BOOL mVisibleChat; + + //-------------------------------------------------------------------- + // Lip synch morphs + //-------------------------------------------------------------------- +private: + bool mLipSyncActive; // we're morphing for lip sync + LLVisualParam* mOohMorph; // cached pointers morphs for lip sync + LLVisualParam* mAahMorph; // cached pointers morphs for lip sync + + //-------------------------------------------------------------------- + // Flight //-------------------------------------------------------------------- public: BOOL mInAir; LLFrameTimer mTimeInAir; - LLVector3 mHeadOffset; // current head position - LLViewerJoint mRoot; // avatar skeleton - BOOL mIsSitting; // sitting state - static bool updateClientTags(); - static bool loadClientTags(); - std::string mClientTag; //Zwagoth's new client identification system. -HgB - LLColor4 mClientColor; //Zwagoth's new client identification system. -HgB +/** Actions + ** ** + *******************************************************************************/ + +/******************************************************************************** + ** ** + ** PHYSICS + **/ + +private: + F32 mSpeedAccum; // measures speed (for diagnostics mostly). + BOOL mTurning; // controls hysteresis on avatar rotation + F32 mSpeed; // misc. animation repeated state //-------------------------------------------------------------------- - // Private member variables. + // Collision volumes + //-------------------------------------------------------------------- +public: + S32 mNumCollisionVolumes; + LLViewerJointCollisionVolume* mCollisionVolumes; +protected: + BOOL allocateCollisionVolumes(U32 num); + + //-------------------------------------------------------------------- + // Dimensions + //-------------------------------------------------------------------- +public: + void resolveHeightGlobal(const LLVector3d &inPos, LLVector3d &outPos, LLVector3 &outNorm); + void resolveHeightAgent(const LLVector3 &inPos, LLVector3 &outPos, LLVector3 &outNorm); + void resolveRayCollisionAgent(const LLVector3d start_pt, const LLVector3d end_pt, LLVector3d &out_pos, LLVector3 &out_norm); + void slamPosition(); // Slam position to transmitted position (for teleport); +protected: + void computeBodySize(); + + //-------------------------------------------------------------------- + // Material being stepped on //-------------------------------------------------------------------- private: - BOOL mIsSelf; // True if this avatar is for this viewer's agent + BOOL mStepOnLand; + U8 mStepMaterial; + LLVector3 mStepObjectVelocity; - LLViewerJoint *mScreenp; // special purpose joint for HUD attachments - BOOL mIsBuilt; // state of deferred character building - F32 mSpeedAccum; // measures speed (for diagnostics mostly). - - BOOL mSupportsAlphaLayers; // For backwards compatibility, TRUE for 1.23+ clients + //-------------------------------------------------------------------- + // Emerald legacy boob bounce + //-------------------------------------------------------------------- +public: + F32 getActualBoobGrav() const { return mLocalBoobConfig.actualBoobGrav; } + void setActualBoobGrav(F32 grav) + { + mLocalBoobConfig.actualBoobGrav = grav; + if(!mFirstSetActualBoobGravRan) + { + mBoobState.boobGrav = grav; + mFirstSetActualBoobGravRan = true; + } + } + static EmeraldGlobalBoobConfig sBoobConfig; +private: + bool mFirstSetActualBoobGravRan; + LLFrameTimer mBoobBounceTimer; + EmeraldAvatarLocalBoobConfig mLocalBoobConfig; + EmeraldBoobState mBoobState; - // LLFrameTimer mUpdateLODTimer; // controls frequency of LOD change calculations - BOOL mTurning; // controls hysteresis on avatar rotation - F32 mSpeed; // misc. animation repeated state - - // Keep track of the material being stepped on - BOOL mStepOnLand; - U8 mStepMaterial; - LLVector3 mStepObjectVelocity; - - // Destroy mesh data after being invisible for a while - BOOL mMeshValid; - BOOL mVisible; - LLFrameTimer mMeshInvisibleTime; +public: + bool mSupportsPhysics; //Client supports v2 wearable physics. Disable emerald physics. - // Lip synch morph stuff - bool mLipSyncActive; // we're morphing for lip sync - LLVisualParam* mOohMorph; // cached pointers morphs for lip sync - LLVisualParam* mAahMorph; // cached pointers morphs for lip sync +/** Physics + ** ** + *******************************************************************************/ - // Skeleton for skinned avatar - S32 mNumJoints; - LLViewerJoint* mSkeleton; +/******************************************************************************** + ** ** + ** HIERARCHY + **/ - // Scratch textures used for compositing - static LLMap< LLGLenum, LLGLuint*> sScratchTexNames; - static LLMap< LLGLenum, F32*> sScratchTexLastBindTime; - static S32 sScratchTexBytes; +public: + virtual BOOL setParent(LLViewerObject* parent); + virtual void addChild(LLViewerObject *childp); + virtual void removeChild(LLViewerObject *childp); - // Global table of sound ids per material, and the ground - const static LLUUID sStepSounds[LL_MCODE_END]; - const static LLUUID sStepSoundOnLand; + //-------------------------------------------------------------------- + // Sitting + //-------------------------------------------------------------------- +public: + BOOL isSitting() const {return mIsSitting;} + void sitOnObject(LLViewerObject *sit_object); + void getOffObject(); +private: + // set this property only with LLVOAvatar::sitDown method + BOOL mIsSitting; - // Xml parse tree of avatar config file - static LLXmlTree sXMLTree; - // Xml parse tree of avatar skeleton file - static LLXmlTree sSkeletonXMLTree; +/** Hierarchy + ** ** + *******************************************************************************/ - // Voice Visualizer is responsible for detecting the user's voice signal, and when the - // user speaks, it puts a voice symbol over the avatar's head, and triggering gesticulations - LLVoiceVisualizer* mVoiceVisualizer; - int mCurrentGesticulationLevel; +/******************************************************************************** + ** ** + ** NAME + **/ + +public: + std::string getFullname() const; // Returns "FirstName LastName" +protected: + static void getAnimLabels(LLDynamicArray* labels); + static void getAnimNames(LLDynamicArray* names); +private: + LLWString mNameString; + std::string mSubNameString; + std::string mTitle; + bool mNameAway; + bool mNameBusy; + bool mNameMute; + bool mNameAppearance; + bool mRenderTag; + bool mRenderGroupTitles; + std::string mRenderedName; + std::string mClientName; + S32 mUsedNameSystem; + + //-------------------------------------------------------------------- + // Display the name (then optionally fade it out) + //-------------------------------------------------------------------- +public: + LLFrameTimer mChatTimer; + LLPointer mNameText; +private: +private: + LLFrameTimer mTimeVisible; + std::deque mChats; + BOOL mTyping; + LLFrameTimer mTypingTimer; + static void on_avatar_name_response(const LLUUID& agent_id, const LLAvatarName& av_name, void *userdata); + + //-------------------------------------------------------------------- + // Client tagging + //-------------------------------------------------------------------- +public: + // + void getClientInfo(std::string& clientTag, LLColor4& tagColor, BOOL useComment=FALSE); + std::string extraMetadata; + // - // Animation timer - LLTimer mAnimTimer; - F32 mTimeLast; - - static LLSD sClientResolutionList; - - bool isUnknownClient(); - static void resolveClient(LLColor4& avatar_name_color, std::string& client, LLVOAvatar* avatar); - friend class LLFloaterAvatarList; + static bool updateClientTags(); + static bool loadClientTags(); + std::string mClientTag; //Zwagoth's new client identification system. -HgB + LLColor4 mClientColor; //Zwagoth's new client identification system. -HgB bool mNameFromChatOverride; bool mNameFromChatChanged; std::string mNameFromChatText; std::string mNameFromAttachment; - LLPointer mBeam; - LLFrameTimer mBeamTimer; +/** Name + ** ** + *******************************************************************************/ - F32 mAdjustedPixelArea; +/******************************************************************************** + ** ** + ** SOUNDS + **/ - LLWString mNameString; - std::string mSubNameString; - std::string mTitle; - BOOL mNameAway; - BOOL mNameBusy; - BOOL mNameMute; - BOOL mNameAppearance; - BOOL mRenderTag; - BOOL mVisibleChat; - BOOL mRenderGroupTitles; - std::string mRenderedName; - std::string mClientName; - S32 mUsedNameSystem; + //-------------------------------------------------------------------- + // Voice visualizer + //-------------------------------------------------------------------- +public: + // Responsible for detecting the user's voice signal (and when the + // user speaks, it puts a voice symbol over the avatar's head) and gesticulations + LLPointer mVoiceVisualizer; + int mCurrentGesticulationLevel; - std::string mDebugText; - U64 mLastRegionHandle; - LLFrameTimer mRegionCrossingTimer; - S32 mRegionCrossingCount; + //-------------------------------------------------------------------- + // Step sound + //-------------------------------------------------------------------- +protected: + const LLUUID& getStepSound() const; +private: + // Global table of sound ids per material, and the ground + const static LLUUID sStepSounds[LL_MCODE_END]; + const static LLUUID sStepSoundOnLand; + + //-------------------------------------------------------------------- + // Foot step state (for generating sounds) + //-------------------------------------------------------------------- +public: + void setFootPlane(const LLVector4 &plane) { mFootPlane = plane; } + LLVector4 mFootPlane; +private: + BOOL mWasOnGroundLeft; + BOOL mWasOnGroundRight; + +/** Sounds + ** ** + *******************************************************************************/ + +/******************************************************************************** + ** ** + ** DIAGNOSTICS + **/ //-------------------------------------------------------------------- - // local textures for compositing. + // General //-------------------------------------------------------------------- +public: + static void dumpArchetypeXML(void*); + static void dumpScratchTextureByteCount(); //Agent only + static void dumpBakedStatus(); + const std::string getBakedStatusForPrintout() const; + void dumpAvatarTEs(const std::string& context) const; + + static F32 sUnbakedTime; // Total seconds with >=1 unbaked avatars + static F32 sUnbakedUpdateTime; // Last time stats were updated (to prevent multiple updates per frame) + static F32 sGreyTime; // Total seconds with >=1 grey avatars + static F32 sGreyUpdateTime; // Last time stats were updated (to prevent multiple updates per frame) +protected: + S32 getUnbakedPixelAreaRank(); + BOOL mHasGrey; private: LLUUID mSavedTE[ LLVOAvatarDefines::TEX_NUM_INDICES ]; - BOOL mFirstTEMessageReceived; - BOOL mFirstAppearanceMessageReceived; BOOL mHasBakedHair; + F32 mMinPixelArea; + F32 mMaxPixelArea; + F32 mAdjustedPixelArea; + std::string mDebugText; - BOOL mCulled; - U32 mVisibilityRank; - F32 mMinPixelArea; // debug - F32 mMaxPixelArea; // debug - BOOL mHasGrey; // debug +/** Diagnostics + ** ** + *******************************************************************************/ + +/******************************************************************************** + ** ** + ** SUPPORT CLASSES + **/ + +protected: // Shared with LLVOAvatarSelf + + struct LLVOAvatarXmlInfo + { + LLVOAvatarXmlInfo(); + ~LLVOAvatarXmlInfo(); + + BOOL parseXmlSkeletonNode(LLXmlTreeNode* root); + BOOL parseXmlMeshNodes(LLXmlTreeNode* root); + BOOL parseXmlColorNodes(LLXmlTreeNode* root); + BOOL parseXmlLayerNodes(LLXmlTreeNode* root); + BOOL parseXmlDriverNodes(LLXmlTreeNode* root); + + struct LLVOAvatarMeshInfo + { + typedef std::pair morph_info_pair_t; + typedef std::vector morph_info_list_t; + + LLVOAvatarMeshInfo() : mLOD(0), mMinPixelArea(.1f) {} + ~LLVOAvatarMeshInfo() + { + morph_info_list_t::iterator iter; + for (iter = mPolyMorphTargetInfoList.begin(); iter != mPolyMorphTargetInfoList.end(); iter++) + { + delete iter->first; + } + mPolyMorphTargetInfoList.clear(); + } + + std::string mType; + S32 mLOD; + std::string mMeshFileName; + std::string mReferenceMeshName; + F32 mMinPixelArea; + morph_info_list_t mPolyMorphTargetInfoList; + }; + typedef std::vector mesh_info_list_t; + mesh_info_list_t mMeshInfoList; + + typedef std::vector skeletal_distortion_info_list_t; + skeletal_distortion_info_list_t mSkeletalDistortionInfoList; - //-------------------------------------------------------------------- - // Global Colors - //-------------------------------------------------------------------- -private: - LLTexGlobalColor* mTexSkinColor; - LLTexGlobalColor* mTexHairColor; - LLTexGlobalColor* mTexEyeColor; + struct LLVOAvatarAttachmentInfo + { + LLVOAvatarAttachmentInfo() + : mGroup(-1), mAttachmentID(-1), mPieMenuSlice(-1), mVisibleFirstPerson(FALSE), + mIsHUDAttachment(FALSE), mHasPosition(FALSE), mHasRotation(FALSE) {} + std::string mName; + std::string mJointName; + LLVector3 mPosition; + LLVector3 mRotationEuler; + S32 mGroup; + S32 mAttachmentID; + S32 mPieMenuSlice; + BOOL mVisibleFirstPerson; + BOOL mIsHUDAttachment; + BOOL mHasPosition; + BOOL mHasRotation; + }; + typedef std::vector attachment_info_list_t; + attachment_info_list_t mAttachmentInfoList; + + LLTexGlobalColorInfo *mTexSkinColorInfo; + LLTexGlobalColorInfo *mTexHairColorInfo; + LLTexGlobalColorInfo *mTexEyeColorInfo; - BOOL mNeedsSkin; //if TRUE, avatar has been animated and verts have not been updated - S32 mUpdatePeriod; + typedef std::vector layer_info_list_t; + layer_info_list_t mLayerInfoList; - //-------------------------------------------------------------------- - // Internal functions - //-------------------------------------------------------------------- -protected: - void buildCharacter(); - void releaseMeshData(); - void restoreMeshData(); - void updateMeshData(); - void computeBodySize(); - const LLUUID& getStepSound() const; - BOOL needsRenderBeam(); + typedef std::vector driver_info_list_t; + driver_info_list_t mDriverInfoList; + }; - BOOL allocateCollisionVolumes( U32 num ); - void resetHUDAttachments(); - static void getAnimLabels( LLDynamicArray* labels ); - static void getAnimNames( LLDynamicArray* names ); +public: //Public until pulled out of LLTexLayer + struct LLMaskedMorph + { + LLMaskedMorph(LLPolyMorphTarget *morph_target, BOOL invert) : + mMorphTarget(morph_target), + mInvert(invert) + { + morph_target->addPendingMorphMask(); + } + + LLPolyMorphTarget *mMorphTarget; + BOOL mInvert; + }; + +/** Support classes + ** ** + *******************************************************************************/ - //-------------------------------------------------------------------- - // Textures and Layers - //-------------------------------------------------------------------- -protected: - BOOL loadSkeletonNode(); - BOOL loadMeshNodes(); - BOOL isFullyBaked(); - void deleteLayerSetCaches(bool clearAll = true); - static BOOL areAllNearbyInstancesBaked(S32& grey_avatars); - static void onBakedTextureMasksLoaded(BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata); - void setLocalTexture(LLVOAvatarDefines::ETextureIndex i, LLViewerFetchedTexture* tex, BOOL baked_version_exits); - void requestLayerSetUpdate(LLVOAvatarDefines::ETextureIndex i); - void addLocalTextureStats(LLVOAvatarDefines::ETextureIndex i, LLViewerTexture* imagep, F32 texel_area_ratio, BOOL rendered, BOOL covered_by_baked); - void addBakedTextureStats( LLViewerFetchedTexture* imagep, F32 pixel_area, F32 texel_area_ratio, S32 boost_level); - static void onInitialBakedTextureLoaded( BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata ); - static void onBakedTextureLoaded(BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata); - void useBakedTexture(const LLUUID& id); - void dumpAvatarTEs(const std::string& context); - void removeMissingBakedTextures(); - LLTexLayerSet* getLayerSet(LLVOAvatarDefines::ETextureIndex index) const; - LLHost getObjectHost() const; - S32 getLocalDiscardLevel(LLVOAvatarDefines::ETextureIndex index); -public: - static void updateFreezeCounter(S32 counter = 0 ); // public: @@ -828,35 +1162,11 @@ public: // private: - static S32 sFreezeCounter; - - //----------------------------------------------------------------------------------------------- - // Avatar skeleton setup. - //----------------------------------------------------------------------------------------------- -private: - BOOL loadAvatar(); - BOOL setupBone(const LLVOAvatarBoneInfo* info, LLViewerJoint* parent, S32 ¤t_volume_num, S32 ¤t_joint_num); - BOOL buildSkeleton(const LLVOAvatarSkeletonInfo *info); - //----------------------------------------------------------------------------------------------- // Per-avatar information about texture data. // To-do: Move this to private implementation class //----------------------------------------------------------------------------------------------- - struct BakedTextureData - { - LLUUID mLastTextureIndex; - LLTexLayerSet* mTexLayerSet; - bool mIsLoaded; - bool mIsUsed; - LLVOAvatarDefines::ETextureIndex mTextureIndex; - U32 mMaskTexName; - // Stores pointers to the joint meshes that this baked texture deals with - std::vector< LLViewerJointMesh * > mMeshes; // std::vector mJoints[i]->mMeshParts - }; - typedef std::vector bakedtexturedata_vec_t; - bakedtexturedata_vec_t mBakedTextureData; - struct LocalTextureData { LocalTextureData() : mIsBakedReady(false), mDiscard(MAX_DISCARD_LEVEL+1), mImage(NULL) @@ -868,41 +1178,33 @@ private: typedef std::map localtexture_map_t; localtexture_map_t mLocalTextureData; - typedef std::multimap polymesh_map_t; - polymesh_map_t mMeshes; - std::vector mMeshLOD; - S32 mNumInitFaces ; //number of faces generated when creating the avatar drawable, does not inculde splitted faces due to long vertex buffer. - //----------------------------------------------------------------------------------------------- - // Static texture/mesh/baked dictionary for avatars - //----------------------------------------------------------------------------------------------- -public: - static BOOL isIndexLocalTexture(LLVOAvatarDefines::ETextureIndex i); - static BOOL isIndexBakedTexture(LLVOAvatarDefines::ETextureIndex i); -private: - static const LLVOAvatarDefines::LLVOAvatarDictionary *getDictionary() { return sAvatarDictionary; } - static LLVOAvatarDefines::LLVOAvatarDictionary *sAvatarDictionary; - static LLVOAvatarSkeletonInfo* sAvatarSkeletonInfo; - static LLVOAvatarXmlInfo* sAvatarXmlInfo; + //-------------------------------------------------------------------- + // Private member variables. + //-------------------------------------------------------------------- + BOOL mIsSelf; // True if this avatar is for this viewer's agent -public: - void dirtyMesh(); -private: - void dirtyMesh(S32 priority); // Dirty the avatar mesh, with priority - S32 mDirtyMesh; // 0 -- not dirty, 1 -- morphed, 2 -- LOD - BOOL mMeshTexturesDirty; + LLViewerJoint *mScreenp; // special purpose joint for HUD attachments + + // Scratch textures used for compositing + static LLMap< LLGLenum, LLGLuint*> sScratchTexNames; + static LLMap< LLGLenum, F32*> sScratchTexLastBindTime; + static S32 sScratchTexBytes; - //----------------------------------------------------------------------------------------------- - // Diagnostics - //----------------------------------------------------------------------------------------------- -public: - static F32 sUnbakedTime; // Total seconds with >=1 unbaked avatars - static F32 sUnbakedUpdateTime; // Last time stats were updated (to prevent multiple updates per frame) - static F32 sGreyTime; // Total seconds with >=1 grey avatars - static F32 sGreyUpdateTime; // Last time stats were updated (to prevent multiple updates per frame) - static bool sDoProperArc; + static LLSD sClientResolutionList; - const std::string getBakedStatusForPrintout() const; + bool isUnknownClient(); + static void resolveClient(LLColor4& avatar_name_color, std::string& client, LLVOAvatar* avatar); + friend class LLFloaterAvatarList; + + LLPointer mBeam; + LLFrameTimer mBeamTimer; + + U64 mLastRegionHandle; + LLFrameTimer mRegionCrossingTimer; + S32 mRegionCrossingCount; + + static bool sDoProperArc; }; //----------------------------------------------------------------------------------------------- diff --git a/indra/newview/llvograss.cpp b/indra/newview/llvograss.cpp index 0cd754a8d..f13b973da 100644 --- a/indra/newview/llvograss.cpp +++ b/indra/newview/llvograss.cpp @@ -465,7 +465,7 @@ void LLVOGrass::plantBlades() face->setTexture(getTEImage(0)); face->setState(LLFace::GLOBAL); face->setSize(mNumBlades * 8, mNumBlades * 12); - face->mVertexBuffer = NULL; + face->setVertexBuffer(NULL); face->setTEOffset(0); face->mCenterLocal = mPosition + mRegionp->getOriginAgent(); diff --git a/indra/newview/llvoground.cpp b/indra/newview/llvoground.cpp index 0ef0196cc..2c22deb7c 100644 --- a/indra/newview/llvoground.cpp +++ b/indra/newview/llvoground.cpp @@ -37,7 +37,6 @@ #include "llviewercontrol.h" -#include "llagent.h" #include "lldrawable.h" #include "llface.h" #include "llsky.h" @@ -104,13 +103,14 @@ BOOL LLVOGround::updateGeometry(LLDrawable *drawable) drawable->addFace(poolp, NULL); face = drawable->getFace(0); - if (face->mVertexBuffer.isNull()) + if (!face->getVertexBuffer()) { face->setSize(5, 12); - face->mVertexBuffer = new LLVertexBuffer(LLDrawPoolGround::VERTEX_DATA_MASK, GL_STREAM_DRAW_ARB); - face->mVertexBuffer->allocateBuffer(face->getGeomCount(), face->getIndicesCount(), TRUE); + LLVertexBuffer* buff = new LLVertexBuffer(LLDrawPoolGround::VERTEX_DATA_MASK, GL_STREAM_DRAW_ARB); + buff->allocateBuffer(face->getGeomCount(), face->getIndicesCount(), TRUE); face->setGeomIndex(0); face->setIndicesIndex(0); + face->setVertexBuffer(buff); } index_offset = face->getGeometry(verticesp,normalsp,texCoordsp, indicesp); @@ -168,7 +168,7 @@ BOOL LLVOGround::updateGeometry(LLDrawable *drawable) *(texCoordsp++) = LLVector2(0.f, 1.f); *(texCoordsp++) = LLVector2(0.5f, 0.5f); - face->mVertexBuffer->setBuffer(0); + face->getVertexBuffer()->setBuffer(0); LLPipeline::sCompiles++; return TRUE; } diff --git a/indra/newview/llvopartgroup.cpp b/indra/newview/llvopartgroup.cpp index b6ba7e50f..978fbd509 100644 --- a/indra/newview/llvopartgroup.cpp +++ b/indra/newview/llvopartgroup.cpp @@ -457,7 +457,7 @@ void LLParticlePartition::getGeometry(LLSpatialGroup* group) LLAlphaObject* object = (LLAlphaObject*) facep->getViewerObject(); facep->setGeomIndex(vertex_count); facep->setIndicesIndex(index_count); - facep->mVertexBuffer = buffer; + facep->setVertexBuffer(buffer); facep->setPoolType(LLDrawPool::POOL_ALPHA); object->getGeometry(facep->getTEOffset(), verticesp, normalsp, texcoordsp, colorsp, indicesp); @@ -486,7 +486,9 @@ void LLParticlePartition::getGeometry(LLSpatialGroup* group) U32 end = start + facep->getGeomCount()-1; U32 offset = facep->getIndicesStart(); U32 count = facep->getIndicesCount(); - LLDrawInfo* info = new LLDrawInfo(start,end,count,offset,facep->getTexture(), buffer, fullbright); + LLDrawInfo* info = new LLDrawInfo(start,end,count,offset,facep->getTexture(), + //facep->getTexture(), + buffer, fullbright); info->mExtents[0] = group->mObjectExtents[0]; info->mExtents[1] = group->mObjectExtents[1]; info->mVSize = vsize; diff --git a/indra/newview/llvosky.cpp b/indra/newview/llvosky.cpp index f2f835220..00e48687d 100644 --- a/indra/newview/llvosky.cpp +++ b/indra/newview/llvosky.cpp @@ -309,7 +309,7 @@ void LLSkyTex::createGLImage(S32 which) void LLSkyTex::bindTexture(BOOL curr) { - gGL.getTexUnit(0)->bind(mTexture[getWhich(curr)]); + gGL.getTexUnit(0)->bind(mTexture[getWhich(curr)], true); } /*************************************** @@ -1039,7 +1039,7 @@ void LLVOSky::calcAtmospherics(void) // Since WL scales everything by 2, there should always be at least a 2:1 brightness ratio // between sunlight and point lights in windlight to normalize point lights. - static const LLCachedControl render_sun_dynamic_range("RenderSunDynamicRange", 1); + static const LLCachedControl render_sun_dynamic_range("RenderSunDynamicRange", 1.f); F32 sun_dynamic_range = llmax((float)render_sun_dynamic_range, 0.0001f); LLWLParamManager::instance()->mSceneLightStrength = 2.0f * (1.0f + sun_dynamic_range * dp); @@ -1190,7 +1190,7 @@ BOOL LLVOSky::updateSky() } } - if (mDrawable.notNull() && mDrawable->getFace(0) && mDrawable->getFace(0)->mVertexBuffer.isNull()) + if (mDrawable.notNull() && mDrawable->getFace(0) && !mDrawable->getFace(0)->getVertexBuffer()) { gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, TRUE); } @@ -1241,10 +1241,11 @@ void LLVOSky::createDummyVertexBuffer() mFace[FACE_DUMMY] = mDrawable->addFace(poolp, NULL); } - if(mFace[FACE_DUMMY]->mVertexBuffer.isNull()) + if(!mFace[FACE_DUMMY]->getVertexBuffer()) { - mFace[FACE_DUMMY]->mVertexBuffer = new LLVertexBuffer(LLDrawPoolSky::VERTEX_DATA_MASK, GL_DYNAMIC_DRAW_ARB); - mFace[FACE_DUMMY]->mVertexBuffer->allocateBuffer(1, 1, TRUE); + LLVertexBuffer* buff = new LLVertexBuffer(LLDrawPoolSky::VERTEX_DATA_MASK, GL_DYNAMIC_DRAW_ARB); + buff->allocateBuffer(1, 1, TRUE); + mFace[FACE_DUMMY]->setVertexBuffer(buff); } } @@ -1261,13 +1262,13 @@ void LLVOSky::updateDummyVertexBuffer() LLFastTimer t(LLFastTimer::FTM_RENDER_FAKE_VBO_UPDATE) ; - if(!mFace[FACE_DUMMY] || mFace[FACE_DUMMY]->mVertexBuffer.isNull()) + if(!mFace[FACE_DUMMY] || !mFace[FACE_DUMMY]->getVertexBuffer()) createDummyVertexBuffer() ; LLStrider vertices ; - mFace[FACE_DUMMY]->mVertexBuffer->getVertexStrider(vertices, 0); + mFace[FACE_DUMMY]->getVertexBuffer()->getVertexStrider(vertices, 0); *vertices = mCameraPosAgent ; - mFace[FACE_DUMMY]->mVertexBuffer->setBuffer(0) ; + mFace[FACE_DUMMY]->getVertexBuffer()->setBuffer(0) ; } //---------------------------------- //end of fake vertex buffer updating @@ -1309,14 +1310,15 @@ BOOL LLVOSky::updateGeometry(LLDrawable *drawable) { face = mFace[FACE_SIDE0 + side]; - if (face->mVertexBuffer.isNull()) + if (!face->getVertexBuffer()) { face->setSize(4, 6); face->setGeomIndex(0); face->setIndicesIndex(0); - face->mVertexBuffer = new LLVertexBuffer(LLDrawPoolSky::VERTEX_DATA_MASK, GL_STREAM_DRAW_ARB); - face->mVertexBuffer->allocateBuffer(4, 6, TRUE); - + LLVertexBuffer* buff = new LLVertexBuffer(LLDrawPoolSky::VERTEX_DATA_MASK, GL_STREAM_DRAW_ARB); + buff->allocateBuffer(4, 6, TRUE); + face->setVertexBuffer(buff); + index_offset = face->getGeometry(verticesp,normalsp,texCoordsp, indicesp); S32 vtx = 0; @@ -1349,7 +1351,7 @@ BOOL LLVOSky::updateGeometry(LLDrawable *drawable) *indicesp++ = index_offset + 3; *indicesp++ = index_offset + 2; - face->mVertexBuffer->setBuffer(0); + buff->setBuffer(0); } } @@ -1476,13 +1478,14 @@ BOOL LLVOSky::updateHeavenlyBodyGeometry(LLDrawable *drawable, const S32 f, cons facep = mFace[f]; - if (facep->mVertexBuffer.isNull()) + if (!facep->getVertexBuffer()) { - facep->setSize(4, 6); - facep->mVertexBuffer = new LLVertexBuffer(LLDrawPoolSky::VERTEX_DATA_MASK, GL_STREAM_DRAW_ARB); - facep->mVertexBuffer->allocateBuffer(facep->getGeomCount(), facep->getIndicesCount(), TRUE); + facep->setSize(4, 6); + LLVertexBuffer* buff = new LLVertexBuffer(LLDrawPoolSky::VERTEX_DATA_MASK, GL_STREAM_DRAW_ARB); + buff->allocateBuffer(facep->getGeomCount(), facep->getIndicesCount(), TRUE); facep->setGeomIndex(0); facep->setIndicesIndex(0); + facep->setVertexBuffer(buff); } index_offset = facep->getGeometry(verticesp,normalsp,texCoordsp, indicesp); @@ -1511,7 +1514,7 @@ BOOL LLVOSky::updateHeavenlyBodyGeometry(LLDrawable *drawable, const S32 f, cons *indicesp++ = index_offset + 2; *indicesp++ = index_offset + 3; - facep->mVertexBuffer->setBuffer(0); + facep->getVertexBuffer()->setBuffer(0); if (is_sun) { @@ -1880,13 +1883,14 @@ void LLVOSky::updateReflectionGeometry(LLDrawable *drawable, F32 H, LLFace *face = mFace[FACE_REFLECTION]; - if (face->mVertexBuffer.isNull() || quads*4 != face->getGeomCount()) + if (!face->getVertexBuffer() || quads*4 != face->getGeomCount()) { face->setSize(quads * 4, quads * 6); - face->mVertexBuffer = new LLVertexBuffer(LLDrawPoolWater::VERTEX_DATA_MASK, GL_STREAM_DRAW_ARB); - face->mVertexBuffer->allocateBuffer(face->getGeomCount(), face->getIndicesCount(), TRUE); + LLVertexBuffer* buff = new LLVertexBuffer(LLDrawPoolWater::VERTEX_DATA_MASK, GL_STREAM_DRAW_ARB); + buff->allocateBuffer(face->getGeomCount(), face->getIndicesCount(), TRUE); face->setIndicesIndex(0); face->setGeomIndex(0); + face->setVertexBuffer(buff); } LLStrider verticesp; @@ -2024,7 +2028,7 @@ void LLVOSky::updateReflectionGeometry(LLDrawable *drawable, F32 H, } } - face->mVertexBuffer->setBuffer(0); + face->getVertexBuffer()->setBuffer(0); } diff --git a/indra/newview/llvosurfacepatch.cpp b/indra/newview/llvosurfacepatch.cpp index 0cb390f02..70ffbd794 100644 --- a/indra/newview/llvosurfacepatch.cpp +++ b/indra/newview/llvosurfacepatch.cpp @@ -845,7 +845,7 @@ void LLVOSurfacePatch::dirtyGeom() if (mDrawable) { gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL, TRUE); - mDrawable->getFace(0)->mVertexBuffer = NULL; + mDrawable->getFace(0)->setVertexBuffer(NULL); mDrawable->movePartition(); } } @@ -1064,7 +1064,7 @@ void LLTerrainPartition::getGeometry(LLSpatialGroup* group) facep->setIndicesIndex(indices_index); facep->setGeomIndex(index_offset); - facep->mVertexBuffer = buffer; + facep->setVertexBuffer(buffer); LLVOSurfacePatch* patchp = (LLVOSurfacePatch*) facep->getViewerObject(); patchp->getGeometry(vertices, normals, colors, texcoords, texcoords2, indices); diff --git a/indra/newview/llvotree.cpp b/indra/newview/llvotree.cpp index ff59a39a7..b16547398 100644 --- a/indra/newview/llvotree.cpp +++ b/indra/newview/llvotree.cpp @@ -389,12 +389,11 @@ BOOL LLVOTree::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) } } - S32 trunk_LOD = 0; + S32 trunk_LOD = sMAX_NUM_TREE_LOD_LEVELS ; F32 app_angle = getAppAngle()*LLVOTree::sTreeFactor; - for (S32 j = 0; j < 4; j++) + for (S32 j = 0; j < sMAX_NUM_TREE_LOD_LEVELS; j++) { - if (app_angle > LLVOTree::sLODAngles[j]) { trunk_LOD = j; @@ -532,7 +531,14 @@ BOOL LLVOTree::updateGeometry(LLDrawable *drawable) { LLFastTimer ftm(LLFastTimer::FTM_UPDATE_TREE); - if (mReferenceBuffer.isNull() || mDrawable->getFace(0)->mVertexBuffer.isNull()) + if(mTrunkLOD >= sMAX_NUM_TREE_LOD_LEVELS) //do not display the tree. + { + mReferenceBuffer = NULL ; + mDrawable->getFace(0)->setVertexBuffer(NULL); + return TRUE ; + } + + if (mReferenceBuffer.isNull() || !mDrawable->getFace(0)->getVertexBuffer()) { const F32 SRR3 = 0.577350269f; // sqrt(1/3) const F32 SRR2 = 0.707106781f; // sqrt(1/2) @@ -870,7 +876,7 @@ BOOL LLVOTree::updateGeometry(LLDrawable *drawable) //Using an && here is incorrect, and will cause instability. if (/*gLLWindEnabled || */render_animate_trees) { - mDrawable->getFace(0)->mVertexBuffer = mReferenceBuffer; + mDrawable->getFace(0)->setVertexBuffer(mReferenceBuffer); } else { @@ -929,8 +935,9 @@ void LLVOTree::updateMesh() calcNumVerts(vert_count, index_count, mTrunkLOD, stop_depth, mDepth, mTrunkDepth, mBranches); LLFace* facep = mDrawable->getFace(0); - facep->mVertexBuffer = new LLVertexBuffer(LLDrawPoolTree::VERTEX_DATA_MASK, GL_STATIC_DRAW_ARB); - facep->mVertexBuffer->allocateBuffer(vert_count, index_count, TRUE); + LLVertexBuffer* buff = new LLVertexBuffer(LLDrawPoolTree::VERTEX_DATA_MASK, GL_STATIC_DRAW_ARB); + buff->allocateBuffer(vert_count, index_count, TRUE); + facep->setVertexBuffer(buff); LLStrider vertices; LLStrider normals; @@ -938,16 +945,15 @@ void LLVOTree::updateMesh() LLStrider indices; U16 idx_offset = 0; - facep->mVertexBuffer->getVertexStrider(vertices); - facep->mVertexBuffer->getNormalStrider(normals); - facep->mVertexBuffer->getTexCoord0Strider(tex_coords); - facep->mVertexBuffer->getIndexStrider(indices); + buff->getVertexStrider(vertices); + buff->getNormalStrider(normals); + buff->getTexCoord0Strider(tex_coords); + buff->getIndexStrider(indices); genBranchPipeline(vertices, normals, tex_coords, indices, idx_offset, scale_mat, mTrunkLOD, stop_depth, mDepth, mTrunkDepth, 1.0, mTwist, droop, mBranches, alpha); mReferenceBuffer->setBuffer(0); - facep->mVertexBuffer->setBuffer(0); - + buff->setBuffer(0); } void LLVOTree::appendMesh(LLStrider& vertices, @@ -1331,7 +1337,7 @@ U32 LLVOTree::getPartitionType() const } LLTreePartition::LLTreePartition() -: LLSpatialPartition(0, FALSE, 0) +: LLSpatialPartition(0, FALSE, GL_DYNAMIC_DRAW_ARB) { mDrawableType = LLPipeline::RENDER_TYPE_TREE; mPartitionType = LLViewerRegion::PARTITION_TREE; diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 62c9ec640..a7c797f51 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -72,7 +72,7 @@ const F32 FORCE_SIMPLE_RENDER_AREA = 512.f; const F32 FORCE_CULL_AREA = 8.f; BOOL gAnimateTextures = TRUE; -extern BOOL gHideSelectedObjects; +//extern BOOL gHideSelectedObjects; F32 LLVOVolume::sLODFactor = 1.f; F32 LLVOVolume::sLODSlopDistanceFactor = 0.5f; //Changing this to zero, effectively disables the LOD transition slop @@ -95,6 +95,7 @@ LLVOVolume::LLVOVolume(const LLUUID &id, const LLPCode pcode, LLViewerRegion *re mNumFaces = 0; mLODChanged = FALSE; mSculptChanged = FALSE; + mSpotLightPriority = 0.f; mIndexInTex = 0; } @@ -614,6 +615,19 @@ void LLVOVolume::updateTextureVirtualSize() } } + if (getLightTextureID().notNull()) + { + LLLightImageParams* params = (LLLightImageParams*) getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE); + LLUUID id = params->getLightTexture(); + mLightTexture = LLViewerTextureManager::getFetchedTexture(id); + if (mLightTexture.notNull()) + { + F32 rad = getLightRadius(); + mLightTexture->addTextureStats(gPipeline.calcPixelArea(getPositionAgent(), + LLVector3(rad,rad,rad), + *camera)); + } + } if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_AREA)) { @@ -968,6 +982,11 @@ void LLVOVolume::updateFaceFlags() for (S32 i = 0; i < getVolume()->getNumFaces(); i++) { LLFace *face = mDrawable->getFace(i); + if (!face) + { + return; + } + BOOL fullbright = getTE(i)->getFullbright(); face->clearState(LLFace::FULLBRIGHT | LLFace::HUD_RENDER | LLFace::LIGHT); @@ -1040,6 +1059,10 @@ BOOL LLVOVolume::genBBoxes(BOOL force_global) for (S32 i = 0; i < getVolume()->getNumFaces(); i++) { LLFace *face = mDrawable->getFace(i); + if (!face) + { + continue; + } res &= face->genVolumeBBoxes(*getVolume(), i, mRelativeXform, mRelativeXformInvTrans, (mVolumeImpl && mVolumeImpl->isVolumeGlobal()) || force_global); @@ -1258,6 +1281,17 @@ BOOL LLVOVolume::updateGeometry(LLDrawable *drawable) regenFaces(); } genBBoxes(FALSE); + + if (mSculptChanged) + { //changes in sculpt maps can thrash an object bounding box without + //triggering a spatial group bounding box update -- force spatial group + //to update bounding boxes + LLSpatialGroup* group = mDrawable->getSpatialGroup(); + if (group) + { + group->unbound(); + } + } } } } @@ -1494,6 +1528,41 @@ void LLVOVolume::updateTEData() //---------------------------------------------------------------------------- +void LLVOVolume::setLightTextureID(LLUUID id) +{ + if (id.notNull()) + { + if (!hasLightTexture()) + { + setParameterEntryInUse(LLNetworkData::PARAMS_LIGHT_IMAGE, TRUE, true); + } + LLLightImageParams* param_block = (LLLightImageParams*) getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE); + if (param_block && param_block->getLightTexture() != id) + { + param_block->setLightTexture(id); + parameterChanged(LLNetworkData::PARAMS_LIGHT_IMAGE, true); + } + } + else + { + if (hasLightTexture()) + { + setParameterEntryInUse(LLNetworkData::PARAMS_LIGHT_IMAGE, FALSE, true); + mLightTexture = NULL; + } + } +} + +void LLVOVolume::setSpotLightParams(LLVector3 params) +{ + LLLightImageParams* param_block = (LLLightImageParams*) getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE); + if (param_block && param_block->getParams() != params) + { + param_block->setParams(params); + parameterChanged(LLNetworkData::PARAMS_LIGHT_IMAGE, true); + } +} + void LLVOVolume::setIsLight(BOOL is_light) { if (is_light != getIsLight()) @@ -1620,6 +1689,94 @@ LLColor3 LLVOVolume::getLightColor() const } } +LLUUID LLVOVolume::getLightTextureID() const +{ + if (getParameterEntryInUse(LLNetworkData::PARAMS_LIGHT_IMAGE)) + { + const LLLightImageParams *param_block = (const LLLightImageParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE); + if (param_block) + { + return param_block->getLightTexture(); + } + } + + return LLUUID::null; +} + + +LLVector3 LLVOVolume::getSpotLightParams() const +{ + if (getParameterEntryInUse(LLNetworkData::PARAMS_LIGHT_IMAGE)) + { + const LLLightImageParams *param_block = (const LLLightImageParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE); + if (param_block) + { + return param_block->getParams(); + } + } + + return LLVector3(); +} + +F32 LLVOVolume::getSpotLightPriority() const +{ + return mSpotLightPriority; +} + +void LLVOVolume::updateSpotLightPriority() +{ + LLVector3 pos = mDrawable->getPositionAgent(); + LLVector3 at(0,0,-1); + at *= getRenderRotation(); + + F32 r = getLightRadius()*0.5f; + + pos += at * r; + + at = LLViewerCamera::getInstance()->getAtAxis(); + + pos -= at * r; + + mSpotLightPriority = gPipeline.calcPixelArea(pos, LLVector3(r,r,r), *LLViewerCamera::getInstance()); + + if (mLightTexture.notNull()) + { + mLightTexture->addTextureStats(mSpotLightPriority); + mLightTexture->setBoostLevel(LLViewerTexture::BOOST_CLOUDS); + } +} + + +bool LLVOVolume::isLightSpotlight() const +{ + LLLightImageParams* params = (LLLightImageParams*) getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE); + if (params) + { + return params->isLightSpotlight(); + } + return false; +} + + +LLViewerTexture* LLVOVolume::getLightTexture() +{ + LLUUID id = getLightTextureID(); + + if (id.notNull()) + { + if (mLightTexture.isNull() || id != mLightTexture->getID()) + { + mLightTexture = LLViewerTextureManager::getFetchedTexture(id); + } + } + else + { + mLightTexture = NULL; + } + + return mLightTexture; +} + F32 LLVOVolume::getLightIntensity() const { const LLLightParams *param_block = (const LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT); @@ -1711,6 +1868,16 @@ BOOL LLVOVolume::isSculpted() const return FALSE; } +BOOL LLVOVolume::hasLightTexture() const +{ + if (getParameterEntryInUse(LLNetworkData::PARAMS_LIGHT_IMAGE)) + { + return TRUE; + } + + return FALSE; +} + BOOL LLVOVolume::isVolumeGlobal() const { if (mVolumeImpl) @@ -2037,7 +2204,7 @@ BOOL LLVOVolume::lineSegmentIntersect(const LLVector3& start, const LLVector3& e if (!mbCanSelect || // (gHideSelectedObjects && isSelected()) || // [RLVa:KB] - Checked: 2010-09-28 (RLVa-1.1.3b) | Modified: RLVa-1.1.3b - ( (gHideSelectedObjects && isSelected()) && + ( (LLSelectMgr::getInstance()->mHideSelectedObjects && isSelected()) && ((!rlv_handler_t::isEnabled()) || (!isHUDAttachment()) || (!gRlvAttachmentLocks.isLockedAttachment(getRootEdit()))) ) || // [/RLVa:KB] mDrawable->isDead() || @@ -2184,7 +2351,7 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, // if (facep->getViewerObject()->isSelected() && gHideSelectedObjects) // [RLVa:KB] - Checked: 2010-09-28 (RLVa-1.1.3b) | Modified: RLVa-1.2.1f const LLViewerObject* pObj = facep->getViewerObject(); - if ( (pObj->isSelected() && gHideSelectedObjects) && + if ( (pObj->isSelected() && LLSelectMgr::getInstance()->mHideSelectedObjects) && ((!rlv_handler_t::isEnabled()) || (!pObj->isHUDAttachment()) || (!gRlvAttachmentLocks.isLockedAttachment(pObj->getRootEdit()))) ) // [/RLVa:KB] { @@ -2200,7 +2367,7 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, (type == LLRenderPass::PASS_INVISIBLE) || (type == LLRenderPass::PASS_ALPHA && facep->isState(LLFace::FULLBRIGHT)); - if (!fullbright && type != LLRenderPass::PASS_GLOW && !facep->mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_NORMAL)) + if (!fullbright && type != LLRenderPass::PASS_GLOW && !facep->getVertexBuffer()->hasDataType(LLVertexBuffer::TYPE_NORMAL)) { llwarns << "Non fullbright face has no normals!" << llendl; return; @@ -2236,13 +2403,13 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, glow = (U8) (facep->getTextureEntry()->getGlow() * 255); } - if (facep->mVertexBuffer.isNull()) + if (!facep->getVertexBuffer()) { llerrs << "WTF?" << llendl; } if (idx >= 0 && - draw_vec[idx]->mVertexBuffer == facep->mVertexBuffer && + draw_vec[idx]->mVertexBuffer == facep->getVertexBuffer() && draw_vec[idx]->mEnd == facep->getGeomIndex()-1 && (LLPipeline::sTextureBindTest || draw_vec[idx]->mTexture == tex) && #if LL_DARWIN @@ -2269,7 +2436,7 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, U32 offset = facep->getIndicesStart(); U32 count = facep->getIndicesCount(); LLPointer draw_info = new LLDrawInfo(start,end,count,offset,tex, - facep->mVertexBuffer, fullbright, bump); + facep->getVertexBuffer(), fullbright, bump); draw_info->mGroup = group; draw_info->mVSize = facep->getVirtualSize(); draw_vec.push_back(draw_info); @@ -2366,20 +2533,23 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) //for each face for (S32 i = 0; i < drawablep->getNumFaces(); i++) { + LLFace* facep = drawablep->getFace(i); + + //ALWAYS null out vertex buffer on rebuild -- if the face lands in a render + // batch, it will recover its vertex buffer reference from the spatial group + facep->setVertexBuffer(NULL); //sum up face verts and indices drawablep->updateFaceSize(i); - LLFace* facep = drawablep->getFace(i); if (cur_total > max_total || facep->getIndicesCount() <= 0 || facep->getGeomCount() <= 0) { - facep->mVertexBuffer = NULL; - facep->mLastVertexBuffer = NULL; + facep->clearVertexBuffer(); continue; } cur_total += facep->getGeomCount(); - if (facep->hasGeometry() && facep->mPixelArea > FORCE_CULL_AREA) + if (facep->hasGeometry() && facep->getPixelArea() > FORCE_CULL_AREA) { const LLTextureEntry* te = facep->getTextureEntry(); LLViewerTexture* tex = facep->getTexture(); @@ -2392,7 +2562,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) } } - BOOL force_simple = (facep->mPixelArea < FORCE_SIMPLE_RENDER_AREA); + BOOL force_simple = (facep->getPixelArea() < FORCE_SIMPLE_RENDER_AREA); U32 type = gPipeline.getPoolTypeFromTE(te, tex); if (type != LLDrawPool::POOL_ALPHA && force_simple) { @@ -2478,8 +2648,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) } else { //face has no renderable geometry - facep->mVertexBuffer = NULL; - facep->mLastVertexBuffer = NULL; + facep->clearVertexBuffer(); } } } @@ -2550,7 +2719,7 @@ void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group) for (S32 i = 0; i < drawablep->getNumFaces(); ++i) { LLFace* face = drawablep->getFace(i); - if (face && face->mVertexBuffer.notNull()) + if (face && face->getVertexBuffer()) { face->getGeometryVolume(*volume, face->getTEOffset(), vobj->getRelativeXform(), vobj->getRelativeXformInvTrans(), face->getGeomIndex()); @@ -2601,9 +2770,10 @@ void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group) for (S32 i = 0; i < drawablep->getNumFaces(); ++i) { LLFace* face = drawablep->getFace(i); - if (face && face->mVertexBuffer.notNull() && face->mVertexBuffer->isLocked()) + LLVertexBuffer* buff = face ? face->getVertexBuffer() : NULL; + if (buff && buff->isLocked()) { - face->mVertexBuffer->setBuffer(0) ; + buff->setBuffer(0) ; } } } @@ -2705,14 +2875,13 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std:: buffer->allocateBuffer(geom_count, index_count, TRUE); } else - { - if (LLVertexBuffer::sEnableVBOs && buffer->getUsage() != group->mBufferUsage) + { //resize pre-existing buffer + if (LLVertexBuffer::sEnableVBOs && buffer->getUsage() != group->mBufferUsage || + buffer->getTypeMask() != mask) { - //Using group->mSpatialPartition->mVertexDataMask may be dropping MAP_BINORMAL on RENDER_BUMP... - buffer = createVertexBuffer(mask /*group->mSpatialPartition->mVertexDataMask*/, + buffer = createVertexBuffer(mask, group->mBufferUsage); buffer->allocateBuffer(geom_count, index_count, TRUE); - llassert_always(buffer->getTypeMask() == mask); } else { @@ -2728,11 +2897,12 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std:: U16 index_offset = 0; while (face_iter < i) - { + { //update face indices for new buffer facep = *face_iter; - facep->mIndicesIndex = indices_index; - facep->mGeomIndex = index_offset; - facep->mVertexBuffer = buffer; + facep->setIndicesIndex(indices_index); + facep->setGeomIndex(index_offset); + facep->setVertexBuffer(buffer); + { facep->updateRebuildFlags(); if (!LLPipeline::sDelayVBUpdate) @@ -2753,9 +2923,12 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std:: } index_offset += facep->getGeomCount(); - indices_index += facep->mIndicesCount; + indices_index += facep->getIndicesCount(); - BOOL force_simple = facep->mPixelArea < FORCE_SIMPLE_RENDER_AREA; + + //append face to appropriate render batch + + BOOL force_simple = facep->getPixelArea() < FORCE_SIMPLE_RENDER_AREA; BOOL fullbright = facep->isState(LLFace::FULLBRIGHT); if ((mask & LLVertexBuffer::MAP_NORMAL) == 0) { //paranoia check to make sure GL doesn't try to read non-existant normals @@ -2924,7 +3097,7 @@ void LLGeometryManager::addGeometryCount(LLSpatialGroup* group, U32 &vertex_coun //sum up face verts and indices drawablep->updateFaceSize(i); LLFace* facep = drawablep->getFace(i); - if (facep->hasGeometry() && facep->mPixelArea > FORCE_CULL_AREA) + if (facep->hasGeometry() && facep->getPixelArea() > FORCE_CULL_AREA) { vertex_count += facep->getGeomCount(); index_count += facep->getIndicesCount(); @@ -2934,8 +3107,7 @@ void LLGeometryManager::addGeometryCount(LLSpatialGroup* group, U32 &vertex_coun } else { - facep->mVertexBuffer = NULL; - facep->mLastVertexBuffer = NULL; + facep->clearVertexBuffer(); } } } diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h index 8f1b11bae..8b7dc172e 100644 --- a/indra/newview/llvovolume.h +++ b/indra/newview/llvovolume.h @@ -201,9 +201,19 @@ public: void setLightRadius(F32 radius); void setLightFalloff(F32 falloff); void setLightCutoff(F32 cutoff); + void setLightTextureID(LLUUID id); + void setSpotLightParams(LLVector3 params); + BOOL getIsLight() const; LLColor3 getLightBaseColor() const; // not scaled by intensity LLColor3 getLightColor() const; // scaled by intensity + LLUUID getLightTextureID() const; + bool isLightSpotlight() const; + LLVector3 getSpotLightParams() const; + void updateSpotLightPriority(); + F32 getSpotLightPriority() const; + + LLViewerTexture* getLightTexture(); F32 getLightIntensity() const; F32 getLightRadius() const; F32 getLightFalloff() const; @@ -213,6 +223,8 @@ public: U32 getVolumeInterfaceID() const; virtual BOOL isFlexible() const; virtual BOOL isSculpted() const; + virtual BOOL hasLightTexture() const; + BOOL isVolumeGlobal() const; BOOL canBeFlexible() const; BOOL setIsFlexible(BOOL is_flexible); @@ -237,12 +249,14 @@ private: S32 mLOD; BOOL mLODChanged; BOOL mSculptChanged; + F32 mSpotLightPriority; LLMatrix4 mRelativeXform; LLMatrix3 mRelativeXformInvTrans; BOOL mVolumeChanged; F32 mVObjRadius; LLVolumeInterface *mVolumeImpl; LLPointer mSculptTexture; + LLPointer mLightTexture; S32 mIndexInTex; // statics diff --git a/indra/newview/llvowater.cpp b/indra/newview/llvowater.cpp index 0e80c62b2..347eb21b3 100644 --- a/indra/newview/llvowater.cpp +++ b/indra/newview/llvowater.cpp @@ -37,7 +37,6 @@ #include "imageids.h" #include "llviewercontrol.h" -#include "llagent.h" #include "lldrawable.h" #include "lldrawpoolwater.h" #include "llface.h" @@ -56,8 +55,6 @@ const BOOL gUseRoam = FALSE; /////////////////////////////////// -#include "randgauss.h" - template inline T LERP(T a, T b, F32 factor) { return a + (b - a) * factor; @@ -69,7 +66,9 @@ const U32 WIDTH = (N_RES * WAVE_STEP); //128.f //64 // width of wave tile, in const F32 WAVE_STEP_INV = (1. / WAVE_STEP); -LLVOWater::LLVOWater(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp) : +LLVOWater::LLVOWater(const LLUUID &id, + const LLPCode pcode, + LLViewerRegion *regionp) : LLStaticViewerObject(id, pcode, regionp), mRenderType(LLPipeline::RENDER_TYPE_WATER) { @@ -160,21 +159,29 @@ BOOL LLVOWater::updateGeometry(LLDrawable *drawable) LLStrider indicesp; U16 index_offset; - S32 size = 16; - S32 num_quads = size*size; - face->setSize(4*num_quads, 6*num_quads); + // A quad is 4 vertices and 6 indices (making 2 triangles) + static const unsigned int vertices_per_quad = 4; + static const unsigned int indices_per_quad = 6; - if (face->mVertexBuffer.isNull()) + static const LLCachedControl render_transparent_water("RenderTransparentWater",false); + const S32 size = render_transparent_water ? 16 : 1; + const S32 num_quads = size * size; + face->setSize(vertices_per_quad * num_quads, + indices_per_quad * num_quads); + + LLVertexBuffer* buff = face->getVertexBuffer(); + if (!buff) { - face->mVertexBuffer = new LLVertexBuffer(LLDrawPoolWater::VERTEX_DATA_MASK, GL_DYNAMIC_DRAW_ARB); - face->mVertexBuffer->allocateBuffer(face->getGeomCount(), face->getIndicesCount(), TRUE); + buff = new LLVertexBuffer(LLDrawPoolWater::VERTEX_DATA_MASK, GL_DYNAMIC_DRAW_ARB); + buff->allocateBuffer(face->getGeomCount(), face->getIndicesCount(), TRUE); face->setIndicesIndex(0); face->setGeomIndex(0); + face->setVertexBuffer(buff); } else { - face->mVertexBuffer->resizeBuffer(face->getGeomCount(), face->getIndicesCount()); + buff->resizeBuffer(face->getGeomCount(), face->getIndicesCount()); } index_offset = face->getGeometry(verticesp,normalsp,texCoordsp, indicesp); @@ -228,7 +235,7 @@ BOOL LLVOWater::updateGeometry(LLDrawable *drawable) } } - face->mVertexBuffer->setBuffer(0); + buff->setBuffer(0); mDrawable->movePartition(); LLPipeline::sCompiles++; @@ -282,7 +289,7 @@ U32 LLVOVoidWater::getPartitionType() const } LLWaterPartition::LLWaterPartition() -: LLSpatialPartition(0, FALSE, 0) +: LLSpatialPartition(0, FALSE, GL_DYNAMIC_DRAW_ARB) { mInfiniteFarClip = TRUE; mDrawableType = LLPipeline::RENDER_TYPE_WATER; diff --git a/indra/newview/llwindebug.cpp b/indra/newview/llwindebug.cpp index bc8281480..4d175a071 100644 --- a/indra/newview/llwindebug.cpp +++ b/indra/newview/llwindebug.cpp @@ -429,7 +429,7 @@ void WINAPI Get_Call_Stack(const EXCEPTION_RECORD* exception_record, if (Get_Module_By_Ret_Addr(Ebp->Ret_Addr, Module_Name, Module_Addr)) { // Save module's address and full path. - tmp_info["CallStack"][Ret_Addr_I]["ModuleName"] = ll_convert_wide_to_string(Module_Name); + tmp_info["CallStack"][Ret_Addr_I]["ModuleName"] = ll_convert_wide_to_string(Module_Name,CP_ACP); tmp_info["CallStack"][Ret_Addr_I]["ModuleAddress"] = (int)Module_Addr; tmp_info["CallStack"][Ret_Addr_I]["CallOffset"] = (int)(Ebp->Ret_Addr - Module_Addr); @@ -548,7 +548,7 @@ LLSD WINAPI Get_Exception_Info(PEXCEPTION_POINTERS pException) Get_Version_Str(info); GetModuleFileName(NULL, Str, MAX_PATH); - info["Process"] = ll_convert_wide_to_string(Str); + info["Process"] = ll_convert_wide_to_string(Str,CP_ACP); info["ThreadID"] = (S32)GetCurrentThreadId(); // If exception occurred. @@ -560,7 +560,7 @@ LLSD WINAPI Get_Exception_Info(PEXCEPTION_POINTERS pException) // If module with E.ExceptionAddress found - save its path and date. if (Get_Module_By_Ret_Addr((PBYTE)E.ExceptionAddress, Module_Name, Module_Addr)) { - info["Module"] = ll_convert_wide_to_string(Module_Name); + info["Module"] = ll_convert_wide_to_string(Module_Name,CP_ACP); if ((hFile = CreateFile(Module_Name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) != INVALID_HANDLE_VALUE) diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 3562733ea..cae557a60 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -106,6 +106,26 @@ #include "rlvhandler.h" // [/RLVa:KB] +void check_stack_depth(S32 stack_depth) +{ + if (gDebugGL || gDebugSession) + { + GLint depth; + glGetIntegerv(GL_MODELVIEW_STACK_DEPTH, &depth); + if (depth != stack_depth) + { + if (gDebugSession) + { + ll_fail("GL matrix stack corrupted."); + } + else + { + llerrs << "GL matrix stack corrupted!" << llendl; + } + } + } +} + #ifdef _DEBUG // Debug indices is disabled for now for debug performance - djs 4/24/02 //#define DEBUG_INDICES @@ -126,7 +146,7 @@ const S32 MAX_OCCLUDER_COUNT = 2; extern S32 gBoxFrame; extern BOOL gRenderLightGlows; -extern BOOL gHideSelectedObjects; +//extern BOOL gHideSelectedObjects; extern BOOL gDisplaySwapBuffers; extern BOOL gDebugGL; @@ -166,6 +186,9 @@ std::string gPoolNames[] = "POOL_INVALID_OUCH_CATASTROPHE_ERROR" }; +void drawBox(const LLVector3& c, const LLVector3& r); +void drawBoxOutline(const LLVector3& pos, const LLVector3& size); + U32 nhpo2(U32 v) { U32 r = 1; @@ -195,6 +218,16 @@ glh::matrix4f glh_get_current_projection() return glh_copy_matrix(gGLProjection); } +glh::matrix4f glh_get_last_modelview() +{ + return glh_copy_matrix(gGLLastModelView); +} + +glh::matrix4f glh_get_last_projection() +{ + return glh_copy_matrix(gGLLastProjection); +} + void glh_copy_matrix(const glh::matrix4f& src, GLdouble* dst) { for (U32 i = 0; i < 16; i++) @@ -258,7 +291,6 @@ BOOL LLPipeline::sRenderFrameTest = FALSE; BOOL LLPipeline::sRenderAttachedLights = TRUE; BOOL LLPipeline::sRenderAttachedParticles = TRUE; BOOL LLPipeline::sRenderDeferred = FALSE; -BOOL LLPipeline::sAllowRebuildPriorityGroup = FALSE ; S32 LLPipeline::sVisibleLightCount = 0; F32 LLPipeline::sMinRenderSize = 0.f; @@ -277,11 +309,11 @@ static const U32 gl_cube_face[] = void validate_framebuffer_object(); + void addDeferredAttachments(LLRenderTarget& target) { - target.addColorAttachment(GL_RGBA16F_ARB); //specular - target.addColorAttachment(GL_RGBA16F_ARB); //normal+z - target.addColorAttachment(GL_RGBA16F_ARB); //position + target.addColorAttachment(GL_RGBA); //specular + target.addColorAttachment(GL_RGBA); //normal+z } LLPipeline::LLPipeline() : @@ -305,6 +337,8 @@ LLPipeline::LLPipeline() : mRenderDebugFeatureMask(0), mRenderDebugMask(0), mOldRenderDebugMask(0), + mGroupQ1Locked(false), + mGroupQ2Locked(false), mLastRebuildPool(NULL), mAlphaPool(NULL), mSkyPool(NULL), @@ -322,6 +356,8 @@ LLPipeline::LLPipeline() : mLightingDetail(0) { mNoiseMap = 0; + mTrueNoiseMap = 0; + mLightFunc = 0; } void LLPipeline::init() @@ -332,6 +368,7 @@ void LLPipeline::init() sRenderBump = gSavedSettings.getBOOL("RenderObjectBump"); LLVertexBuffer::sUseStreamDraw = gSavedSettings.getBOOL("ShyotlRenderUseStreamVBO"); LLVertexBuffer::sOmitBlank = gSavedSettings.getBOOL("SianaRenderOmitBlankVBO"); + LLVertexBuffer::sPreferStreamDraw = gSavedSettings.getBOOL("RenderPreferStreamDraw"); sRenderAttachedLights = gSavedSettings.getBOOL("RenderAttachedLights"); sRenderAttachedParticles = gSavedSettings.getBOOL("RenderAttachedParticles"); @@ -377,6 +414,11 @@ void LLPipeline::init() LLViewerShaderMgr::instance()->setShaders(); stop_glerror(); + + for (U32 i = 0; i < 2; ++i) + { + mSpotLightFade[i] = 1.f; + } setLightingDetail(-1); } @@ -503,26 +545,134 @@ void LLPipeline::allocateScreenBuffer(U32 resX, U32 resY) if (LLPipeline::sRenderDeferred) { - //allocate deferred rendering color buffers - mDeferredScreen.allocate(resX, resY, GL_RGBA16F_ARB, TRUE, TRUE, LLTexUnit::TT_RECT_TEXTURE, FALSE); - addDeferredAttachments(mDeferredScreen); - mScreen.allocate(resX, resY, GL_RGBA16F_ARB, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE); - - for (U32 i = 0; i < 2; i++) - { - mDeferredLight[i].allocate(resX, resY, GL_RGB, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE); - } - - //HACK: make alpha masking work on ATI depth shadows (work around for ATI driver bug) - U32 shadow_fmt = 0;/*gGLManager.mIsATI ? GL_ALPHA : 0;*/ + S32 shadow_detail = gSavedSettings.getS32("RenderShadowDetail"); + BOOL ssao = gSavedSettings.getBOOL("RenderDeferredSSAO"); + bool gi = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_DEFERRED); - for (U32 i = 0; i < 4; i++) - { - mSunShadow[i].allocate(1024,1024, shadow_fmt, TRUE, FALSE); + //allocate deferred rendering color buffers + static const LLCachedControl shadow_precision("DeferredHighPrecision",true); + const GLuint format = shadow_precision ? GL_RGBA : GL_RGBA16F_ARB; //TO-DO: Profile 16bit format later + mDeferredScreen.allocate(resX, resY, format, TRUE, TRUE, LLTexUnit::TT_RECT_TEXTURE, FALSE); + mDeferredDepth.allocate(resX, resY, 0, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE); + addDeferredAttachments(mDeferredScreen); + + mScreen.allocate(resX, resY, format, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE); + +#if LL_DARWIN + // As of OS X 10.6.7, Apple doesn't support multiple color formats in a single FBO + mEdgeMap.allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE); +#else + mEdgeMap.allocate(resX, resY, GL_ALPHA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE); +#endif + + if (shadow_detail > 0 || ssao) + { //only need mDeferredLight[0] for shadows OR ssao + mDeferredLight[0].allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE); } + else + { + mDeferredLight[0].release(); + } + + if (ssao || gi) + { //only need mDeferredLight[1] for ssao... and GI + mDeferredLight[1].allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE); + } + else + { + mDeferredLight[1].release(); + } + + if (gi) + { //only need mDeferredLight[2] and mGIMapPost for gi + mDeferredLight[2].allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE); + for (U32 i = 0; i < 2; i++) + { +#if LL_DARWIN + // As of OS X 10.6.7, Apple doesn't support multiple color formats in a single FBO + mGIMapPost[i].allocate(resX,resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE); +#else + mGIMapPost[i].allocate(resX,resY, GL_RGB, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE); +#endif + } + } + else + { + mDeferredLight[2].release(); + + for (U32 i = 0; i < 2; i++) + { + mGIMapPost[i].release(); + } + } + + F32 scale = gSavedSettings.getF32("RenderShadowResolutionScale"); + +#if LL_DARWIN + U32 shadow_fmt = 0; +#else + //HACK: make alpha masking work on ATI depth shadows (work around for ATI driver bug) + //TO-DO: Test if this is actually needed. + U32 shadow_fmt = gGLManager.mIsATI ? GL_ALPHA : 0; +#endif + + if (shadow_detail > 0) + { //allocate 4 sun shadow maps + for (U32 i = 0; i < 4; i++) + { + mShadow[i].allocate(U32(resX*scale),U32(resY*scale), shadow_fmt, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE); + } + } + else + { + for (U32 i = 0; i < 4; i++) + { + mShadow[i].release(); + } + } + + U32 width = nhpo2(U32(resX*scale))/2; + U32 height = width; + + if (shadow_detail > 1) + { //allocate two spot shadow maps + for (U32 i = 4; i < 6; i++) + { + mShadow[i].allocate(width, height, shadow_fmt, TRUE, FALSE); + } + } + else + { + for (U32 i = 4; i < 6; i++) + { + mShadow[i].release(); + } + } + + width = nhpo2(resX)/2; + height = nhpo2(resY)/2; + mLuminanceMap.allocate(width,height, GL_RGBA, FALSE, FALSE); } else { + for (U32 i = 0; i < 3; i++) + { + mDeferredLight[i].release(); + } + for (U32 i = 0; i < 2; i++) + { + mGIMapPost[i].release(); + } + for (U32 i = 0; i < 6; i++) + { + mShadow[i].release(); + } + mScreen.release(); + mDeferredScreen.release(); //make sure to release any render targets that share a depth buffer with mDeferredScreen first + mDeferredDepth.release(); + mEdgeMap.release(); + mLuminanceMap.release(); + mScreen.allocate(resX, resY, GL_RGBA, TRUE, TRUE, LLTexUnit::TT_RECT_TEXTURE, FALSE); } @@ -531,9 +681,12 @@ void LLPipeline::allocateScreenBuffer(U32 resX, U32 resY) { if (LLPipeline::sRenderDeferred) { - mSampleBuffer.allocate(resX,resY,GL_RGBA16F_ARB,TRUE,TRUE,LLTexUnit::TT_RECT_TEXTURE,FALSE,samples); + static const LLCachedControl shadow_precision("DeferredHighPrecision",true); + const GLuint format = shadow_precision ? GL_RGBA : GL_RGBA16F_ARB; //TO-DO: Profile 16bit format later + mSampleBuffer.allocate(resX,resY,format,TRUE,TRUE,LLTexUnit::TT_RECT_TEXTURE,FALSE,samples); addDeferredAttachments(mSampleBuffer); mDeferredScreen.setSampleBuffer(&mSampleBuffer); + mEdgeMap.setSampleBuffer(&mSampleBuffer); } else { @@ -544,12 +697,20 @@ void LLPipeline::allocateScreenBuffer(U32 resX, U32 resY) stop_glerror(); } + else + { + mSampleBuffer.release(); + } + if (LLPipeline::sRenderDeferred) { //share depth buffer between deferred targets mDeferredScreen.shareDepthBuffer(mScreen); - for (U32 i = 0; i < 2; i++) - { - mDeferredScreen.shareDepthBuffer(mDeferredLight[i]); + for (U32 i = 0; i < 3; i++) + { //share stencil buffer with screen space lightmap to stencil out sky + if (mDeferredLight[i].getTexture(0)) + { + mDeferredScreen.shareDepthBuffer(mDeferredLight[i]); + } } } @@ -563,12 +724,16 @@ void LLPipeline::allocateScreenBuffer(U32 resX, U32 resY) void LLPipeline::updateRenderDeferred() { sRenderDeferred = (gSavedSettings.getBOOL("RenderDeferred") && - LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferred") && LLRenderTarget::sUseFBO && + LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferred") && gSavedSettings.getBOOL("VertexShaderEnable") && gSavedSettings.getBOOL("RenderAvatarVP") && gSavedSettings.getBOOL("WindLightUseAtmosShaders") && !gUseWireframe); + if (sRenderDeferred) + { //must render glow when rendering deferred since post effect pass is needed to present any lighting at all + sRenderGlow = TRUE; + } } void LLPipeline::releaseGLBuffers() @@ -581,21 +746,40 @@ void LLPipeline::releaseGLBuffers() mNoiseMap = 0; } + if (mTrueNoiseMap) + { + LLImageGL::deleteTextures(1, &mTrueNoiseMap); + mTrueNoiseMap = 0; + } + + if (mLightFunc) + { + LLImageGL::deleteTextures(1, &mLightFunc); + mLightFunc = 0; + } + mWaterRef.release(); mWaterDis.release(); mScreen.release(); - mSampleBuffer.releaseSampleBuffer(); + mSampleBuffer.release(); mDeferredScreen.release(); - - - for (U32 i = 0; i < 2; i++) + mDeferredDepth.release(); + for (U32 i = 0; i < 3; i++) { mDeferredLight[i].release(); } - for (U32 i = 0; i < 4; i++) + + mEdgeMap.release(); + mGIMap.release(); + mGIMapPost[0].release(); + mGIMapPost[1].release(); + mLuminanceMap.release(); + + for (U32 i = 0; i < 6; i++) { - mSunShadow[i].release(); + mShadow[i].release(); } + for (U32 i = 0; i < 3; i++) { mGlow[i].release(); @@ -635,11 +819,11 @@ void LLPipeline::createGLBuffers() } allocateScreenBuffer(resX,resY); + } if (sRenderDeferred) { - if (!mNoiseMap) { const U32 noiseRes = 128; @@ -659,6 +843,66 @@ void LLPipeline::createGLBuffers() LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_RGB16F_ARB, noiseRes, noiseRes, GL_RGB, GL_FLOAT, noise); gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT); } + + if (!mTrueNoiseMap) + { + const U32 noiseRes = 128; + F32 noise[noiseRes*noiseRes*3]; + for (U32 i = 0; i < noiseRes*noiseRes*3; i++) + { + noise[i] = ll_frand()*2.0-1.0; + } + + LLImageGL::generateTextures(1, &mTrueNoiseMap); + gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mTrueNoiseMap); + LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_RGB16F_ARB, noiseRes, noiseRes, GL_RGB,GL_FLOAT, noise); + gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT); + } + + if (!mLightFunc) + { + U32 lightResX = gSavedSettings.getU32("RenderSpecularResX"); + U32 lightResY = gSavedSettings.getU32("RenderSpecularResY"); + U8* lg = new U8[lightResX*lightResY]; + + for (U32 y = 0; y < lightResY; ++y) + { + for (U32 x = 0; x < lightResX; ++x) + { + //spec func + F32 sa = (F32) x/(lightResX-1); + F32 spec = (F32) y/(lightResY-1); + //lg[y*lightResX+x] = (U8) (powf(sa, 128.f*spec*spec)*255); + + //F32 sp = acosf(sa)/(1.f-spec); + + sa = powf(sa, gSavedSettings.getF32("RenderSpecularExponent")); + F32 a = acosf(sa*0.25f+0.75f); + F32 m = llmax(0.5f-spec*0.5f, 0.001f); + F32 t2 = tanf(a)/m; + t2 *= t2; + + F32 c4a = (3.f+4.f*cosf(2.f*a)+cosf(4.f*a))/8.f; + F32 bd = 1.f/(4.f*m*m*c4a)*powf(F_E, -t2); + + lg[y*lightResX+x] = (U8) (llclamp(bd, 0.f, 1.f)*255); + } + } + + LLImageGL::generateTextures(1, &mLightFunc); + gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mLightFunc); + LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_ALPHA, lightResX, lightResY, GL_ALPHA, GL_UNSIGNED_BYTE, lg); + gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); + gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_TRILINEAR); + + delete [] lg; + } + + if (gSavedSettings.getBOOL("RenderDeferredGI")) + { + mGIMap.allocate(512,512,GL_RGBA, TRUE, FALSE); + addDeferredAttachments(mGIMap); + } } } @@ -749,24 +993,24 @@ S32 LLPipeline::getMaxLightingDetail() const S32 LLPipeline::setLightingDetail(S32 level) { - assertInitialized(); - if (level < 0) { - level = gSavedSettings.getS32("RenderLightingDetail"); - } - level = llclamp(level, 0, getMaxLightingDetail()); - if (level != mLightingDetail) - { - gSavedSettings.setS32("RenderLightingDetail", level); - - mLightingDetail = level; - - if (mVertexShadersLoaded == 1) + if (gSavedSettings.getBOOL("RenderLocalLights")) { - LLViewerShaderMgr::instance()->setShaders(); + level = 1; + } + else + { + level = 0; } } + level = llclamp(level, 0, getMaxLightingDetail()); + //Bugfix: If setshaders was called with RenderLocalLights off then enabling RenderLocalLights later will not work. Reloading shaders fixes this. + if (level != mLightingDetail && mVertexShadersLoaded) + { + LLViewerShaderMgr::instance()->setShaders(); + } + mLightingDetail = level; return mLightingDetail; } @@ -1036,6 +1280,21 @@ void LLPipeline::unlinkDrawable(LLDrawable *drawable) break; } } + + for (U32 i = 0; i < 2; ++i) + { + if (mShadowSpotLight[i] == drawablep) + { + mShadowSpotLight[i] = NULL; + } + + if (mTargetShadowSpotLight[i] == drawablep) + { + mTargetShadowSpotLight[i] = NULL; + } + } + + } U32 LLPipeline::addObject(LLViewerObject *vobj) @@ -1300,7 +1559,7 @@ F32 LLPipeline::calcPixelArea(LLVector3 center, LLVector3 size, LLCamera &camera //get area of circle around node F32 app_angle = atanf(size.length()/dist); F32 radius = app_angle*LLDrawable::sCurPixelAngle; - return radius*radius * 3.14159f; + return radius*radius * F_PI; } void LLPipeline::grabReferences(LLCullResult& result) @@ -1308,6 +1567,184 @@ void LLPipeline::grabReferences(LLCullResult& result) sCull = &result; } +void LLPipeline::clearReferences() +{ + sCull = NULL; +} + +void check_references(LLSpatialGroup* group, LLDrawable* drawable) +{ + for (LLSpatialGroup::element_iter i = group->getData().begin(); i != group->getData().end(); ++i) + { + if (drawable == *i) + { + llerrs << "LLDrawable deleted while actively reference by LLPipeline." << llendl; + } + } +} + +void check_references(LLDrawable* drawable, LLFace* face) +{ + for (S32 i = 0; i < drawable->getNumFaces(); ++i) + { + if (drawable->getFace(i) == face) + { + llerrs << "LLFace deleted while actively referenced by LLPipeline." << llendl; + } + } +} + +void check_references(LLSpatialGroup* group, LLFace* face) +{ + for (LLSpatialGroup::element_iter i = group->getData().begin(); i != group->getData().end(); ++i) + { + LLDrawable* drawable = *i; + check_references(drawable, face); + } +} + +void LLPipeline::checkReferences(LLFace* face) +{ +#if 0 + if (sCull) + { + for (LLCullResult::sg_list_t::iterator iter = sCull->beginVisibleGroups(); iter != sCull->endVisibleGroups(); ++iter) + { + LLSpatialGroup* group = *iter; + check_references(group, face); + } + + for (LLCullResult::sg_list_t::iterator iter = sCull->beginAlphaGroups(); iter != sCull->endAlphaGroups(); ++iter) + { + LLSpatialGroup* group = *iter; + check_references(group, face); + } + + for (LLCullResult::sg_list_t::iterator iter = sCull->beginDrawableGroups(); iter != sCull->endDrawableGroups(); ++iter) + { + LLSpatialGroup* group = *iter; + check_references(group, face); + } + + for (LLCullResult::drawable_list_t::iterator iter = sCull->beginVisibleList(); iter != sCull->endVisibleList(); ++iter) + { + LLDrawable* drawable = *iter; + check_references(drawable, face); + } + } +#endif +} + +void LLPipeline::checkReferences(LLDrawable* drawable) +{ +#if 0 + if (sCull) + { + for (LLCullResult::sg_list_t::iterator iter = sCull->beginVisibleGroups(); iter != sCull->endVisibleGroups(); ++iter) + { + LLSpatialGroup* group = *iter; + check_references(group, drawable); + } + + for (LLCullResult::sg_list_t::iterator iter = sCull->beginAlphaGroups(); iter != sCull->endAlphaGroups(); ++iter) + { + LLSpatialGroup* group = *iter; + check_references(group, drawable); + } + + for (LLCullResult::sg_list_t::iterator iter = sCull->beginDrawableGroups(); iter != sCull->endDrawableGroups(); ++iter) + { + LLSpatialGroup* group = *iter; + check_references(group, drawable); + } + + for (LLCullResult::drawable_list_t::iterator iter = sCull->beginVisibleList(); iter != sCull->endVisibleList(); ++iter) + { + if (drawable == *iter) + { + llerrs << "LLDrawable deleted while actively referenced by LLPipeline." << llendl; + } + } + } +#endif +} + +void check_references(LLSpatialGroup* group, LLDrawInfo* draw_info) +{ + for (LLSpatialGroup::draw_map_t::iterator i = group->mDrawMap.begin(); i != group->mDrawMap.end(); ++i) + { + LLSpatialGroup::drawmap_elem_t& draw_vec = i->second; + for (LLSpatialGroup::drawmap_elem_t::iterator j = draw_vec.begin(); j != draw_vec.end(); ++j) + { + LLDrawInfo* params = *j; + if (params == draw_info) + { + llerrs << "LLDrawInfo deleted while actively referenced by LLPipeline." << llendl; + } + } + } +} + + +void LLPipeline::checkReferences(LLDrawInfo* draw_info) +{ +#if 0 + if (sCull) + { + for (LLCullResult::sg_list_t::iterator iter = sCull->beginVisibleGroups(); iter != sCull->endVisibleGroups(); ++iter) + { + LLSpatialGroup* group = *iter; + check_references(group, draw_info); + } + + for (LLCullResult::sg_list_t::iterator iter = sCull->beginAlphaGroups(); iter != sCull->endAlphaGroups(); ++iter) + { + LLSpatialGroup* group = *iter; + check_references(group, draw_info); + } + + for (LLCullResult::sg_list_t::iterator iter = sCull->beginDrawableGroups(); iter != sCull->endDrawableGroups(); ++iter) + { + LLSpatialGroup* group = *iter; + check_references(group, draw_info); + } + } +#endif +} + +void LLPipeline::checkReferences(LLSpatialGroup* group) +{ +#if 0 + if (sCull) + { + for (LLCullResult::sg_list_t::iterator iter = sCull->beginVisibleGroups(); iter != sCull->endVisibleGroups(); ++iter) + { + if (group == *iter) + { + llerrs << "LLSpatialGroup deleted while actively referenced by LLPipeline." << llendl; + } + } + + for (LLCullResult::sg_list_t::iterator iter = sCull->beginAlphaGroups(); iter != sCull->endAlphaGroups(); ++iter) + { + if (group == *iter) + { + llerrs << "LLSpatialGroup deleted while actively referenced by LLPipeline." << llendl; + } + } + + for (LLCullResult::sg_list_t::iterator iter = sCull->beginDrawableGroups(); iter != sCull->endDrawableGroups(); ++iter) + { + if (group == *iter) + { + llerrs << "LLSpatialGroup deleted while actively referenced by LLPipeline." << llendl; + } + } + } +#endif +} + + BOOL LLPipeline::visibleObjectsInFrustum(LLCamera& camera) { for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); @@ -1336,8 +1773,10 @@ BOOL LLPipeline::visibleObjectsInFrustum(LLCamera& camera) BOOL LLPipeline::getVisibleExtents(LLCamera& camera, LLVector3& min, LLVector3& max) { - min = LLVector3(F32_MAX, F32_MAX, F32_MAX); - max = LLVector3(-F32_MAX, -F32_MAX, -F32_MAX); + const F32 X = 65536.f; + + min = LLVector3(X,X,X); + max = LLVector3(-X,-X,-X); U32 saved_camera_id = LLViewerCamera::sCurCameraID; LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD; @@ -1371,7 +1810,7 @@ BOOL LLPipeline::getVisibleExtents(LLCamera& camera, LLVector3& min, LLVector3& } -void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_clip) +void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_clip, LLPlane* planep) { LLFastTimer t(LLFastTimer::FTM_CULL); LLMemType mt(LLMemType::MTYPE_PIPELINE); @@ -1391,10 +1830,15 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_cl mScreen.bindTarget(); } - /*glMatrixMode(GL_PROJECTION); + if (sUseOcclusion > 1) + { + gGL.setColorMask(false, false); + } + + glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadMatrixd(gGLLastProjection); - glMatrixMode(GL_MODELVIEW);*/ + glMatrixMode(GL_MODELVIEW); glPushMatrix(); gGLLastMatrix = NULL; glLoadMatrixd(gGLLastModelView); @@ -1405,10 +1849,37 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_cl LLGLDisable test(GL_ALPHA_TEST); gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - if (sUseOcclusion > 1) + + //setup a clip plane in projection matrix for reflection renders (prevents flickering from occlusion culling) + LLViewerRegion* region = gAgent.getRegion(); + LLPlane plane; + + if (planep) { - gGL.setColorMask(false, false); + plane = *planep; } + else + { + if (region) + { + LLVector3 pnorm; + F32 height = region->getWaterHeight(); + if (water_clip < 0) + { //camera is above water, clip plane points up + pnorm.setVec(0,0,1); + plane.setVec(pnorm, -height); + } + else if (water_clip > 0) + { //camera is below water, clip plane points down + pnorm = LLVector3(0,0,-1); + plane.setVec(pnorm, height); + } + } + } + + glh::matrix4f modelview = glh_get_last_modelview(); + glh::matrix4f proj = glh_get_last_projection(); + LLGLUserClipPlane clip(plane, modelview, proj, water_clip != 0 && LLPipeline::sReflectionRender); LLGLDepthTest depth(GL_TRUE, GL_FALSE); @@ -1463,9 +1934,9 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_cl } - /*glMatrixMode(GL_PROJECTION); + glMatrixMode(GL_PROJECTION); glPopMatrix(); - glMatrixMode(GL_MODELVIEW);*/ + glMatrixMode(GL_MODELVIEW); glPopMatrix(); if (sUseOcclusion > 1) @@ -1477,10 +1948,10 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_cl { mScreen.flush(); } - else if (LLPipeline::sUseOcclusion > 1) + /*else if (LLPipeline::sUseOcclusion > 1) { glFlush(); - } + }*/ } void LLPipeline::markNotCulled(LLSpatialGroup* group, LLCamera& camera) @@ -1549,33 +2020,34 @@ void LLPipeline::markOccluder(LLSpatialGroup* group) void LLPipeline::doOcclusion(LLCamera& camera) { - LLVertexBuffer::unbind(); + if (LLPipeline::sUseOcclusion > 1 && sCull->hasOcclusionGroups()) + { + LLVertexBuffer::unbind(); - if (hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCCLUSION)) - { - gGL.setColorMask(true, false, false, false); - } - else - { - gGL.setColorMask(false, false); - } - LLGLDisable blend(GL_BLEND); - LLGLDisable test(GL_ALPHA_TEST); - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - LLGLDepthTest depth(GL_TRUE, GL_FALSE); + if (hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCCLUSION)) + { + gGL.setColorMask(true, false, false, false); + } + else + { + gGL.setColorMask(false, false); + } + LLGLDisable blend(GL_BLEND); + LLGLDisable test(GL_ALPHA_TEST); + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + LLGLDepthTest depth(GL_TRUE, GL_FALSE); - LLGLDisable cull(GL_CULL_FACE); - if (LLPipeline::sUseOcclusion > 1) - { + LLGLDisable cull(GL_CULL_FACE); + for (LLCullResult::sg_list_t::iterator iter = sCull->beginOcclusionGroups(); iter != sCull->endOcclusionGroups(); ++iter) { LLSpatialGroup* group = *iter; group->doOcclusion(&camera); group->clearOcclusionState(LLSpatialGroup::ACTIVE_OCCLUSION); } + + gGL.setColorMask(true, false); } - - gGL.setColorMask(true, false); } BOOL LLPipeline::updateDrawableGeom(LLDrawable* drawablep, BOOL priority) @@ -1602,17 +2074,13 @@ void LLPipeline::updateGL() void LLPipeline::rebuildPriorityGroups() { - if(!sAllowRebuildPriorityGroup) - { - return ; - } - sAllowRebuildPriorityGroup = FALSE ; - LLTimer update_timer; LLMemType mt(LLMemType::MTYPE_PIPELINE); assertInitialized(); + + mGroupQ1Locked = true; // Iterate through all drawables on the priority build queue, for (LLSpatialGroup::sg_vector_t::iterator iter = mGroupQ1.begin(); iter != mGroupQ1.end(); ++iter) @@ -1623,10 +2091,18 @@ void LLPipeline::rebuildPriorityGroups() } mGroupQ1.clear(); + mGroupQ1Locked = false; + } void LLPipeline::rebuildGroups() { + if (mGroupQ2.empty()) + { + return; + } + + mGroupQ2Locked = true; // Iterate through some drawables on the non-priority build queue S32 size = (S32) mGroupQ2.size(); S32 min_count = llclamp((S32) ((F32) (size * size)/4096*0.25f), 1, size); @@ -1636,33 +2112,30 @@ void LLPipeline::rebuildGroups() std::sort(mGroupQ2.begin(), mGroupQ2.end(), LLSpatialGroup::CompareUpdateUrgency()); LLSpatialGroup::sg_vector_t::iterator iter; + LLSpatialGroup::sg_vector_t::iterator last_iter = mGroupQ2.begin(); + for (iter = mGroupQ2.begin(); - iter != mGroupQ2.end(); ++iter) + iter != mGroupQ2.end() && count <= min_count; ++iter) { LLSpatialGroup* group = *iter; + last_iter = iter; - if (group->isDead()) + if (!group->isDead()) { - continue; - } - - group->rebuildGeom(); - - if (group->mSpatialPartition->mRenderByGroup) - { - count++; - } + group->rebuildGeom(); - group->clearState(LLSpatialGroup::IN_BUILD_Q2); - - if (count > min_count) - { - ++iter; - break; + if (group->mSpatialPartition->mRenderByGroup) + { + count++; + } } + + group->clearState(LLSpatialGroup::IN_BUILD_Q2); } - mGroupQ2.erase(mGroupQ2.begin(), iter); + mGroupQ2.erase(mGroupQ2.begin(), ++last_iter); + + mGroupQ2Locked = false; updateMovedList(mMovedBridge); } @@ -1774,41 +2247,39 @@ void LLPipeline::updateGeom(F32 max_dtime) void LLPipeline::markVisible(LLDrawable *drawablep, LLCamera& camera) { LLMemType mt(LLMemType::MTYPE_PIPELINE); - if(!drawablep || drawablep->isDead()) + + if(drawablep && !drawablep->isDead()) { - return; - } - - if (drawablep->isSpatialBridge()) - { - const LLDrawable* root = ((LLSpatialBridge*) drawablep)->mDrawable; - llassert(root); // trying to catch a bad assumption - if (root && // // this test may not be needed, see above - root->getVObj()->isAttachment()) + if (drawablep->isSpatialBridge()) { - LLDrawable* rootparent = root->getParent(); - if (rootparent) // this IS sometimes NULL + const LLDrawable* root = ((LLSpatialBridge*) drawablep)->mDrawable; + llassert(root); // trying to catch a bad assumption + if (root && // // this test may not be needed, see above + root->getVObj()->isAttachment()) { - LLViewerObject *vobj = rootparent->getVObj(); - llassert(vobj); // trying to catch a bad assumption - if (vobj) // this test may not be needed, see above + LLDrawable* rootparent = root->getParent(); + if (rootparent) // this IS sometimes NULL { - if (vobj->isAvatar() && ((LLVOAvatar*)vobj)->isImpostor()) + LLViewerObject *vobj = rootparent->getVObj(); + llassert(vobj); // trying to catch a bad assumption + if (vobj) // this test may not be needed, see above { - return; + if (vobj->isAvatar() && ((LLVOAvatar*)vobj)->isImpostor()) + { + return; + } } } } + sCull->pushBridge((LLSpatialBridge*) drawablep); + } + else + { + sCull->pushDrawable(drawablep); } - - sCull->pushBridge((LLSpatialBridge*) drawablep); - } - else - { - sCull->pushDrawable(drawablep); - } - drawablep->setVisible(camera); + drawablep->setVisible(camera); + } } void LLPipeline::markMoved(LLDrawable *drawablep, BOOL damped_motion) @@ -1955,6 +2426,8 @@ void LLPipeline::markRebuild(LLSpatialGroup* group, BOOL priority) { if (!group->isState(LLSpatialGroup::IN_BUILD_Q1)) { + llassert_always(!mGroupQ1Locked); + mGroupQ1.push_back(group); group->setState(LLSpatialGroup::IN_BUILD_Q1); @@ -1971,11 +2444,12 @@ void LLPipeline::markRebuild(LLSpatialGroup* group, BOOL priority) } else if (!group->isState(LLSpatialGroup::IN_BUILD_Q2 | LLSpatialGroup::IN_BUILD_Q1)) { + llassert_always(!mGroupQ2Locked); //llerrs << "Non-priority updates not yet supported!" << llendl; - if (std::find(mGroupQ2.begin(), mGroupQ2.end(), group) != mGroupQ2.end()) + /*if (std::find(mGroupQ2.begin(), mGroupQ2.end(), group) != mGroupQ2.end()) { llerrs << "WTF?" << llendl; - } + }*/ mGroupQ2.push_back(group); group->setState(LLSpatialGroup::IN_BUILD_Q2); @@ -2053,6 +2527,42 @@ void LLPipeline::stateSort(LLCamera& camera, LLCullResult &result) } } } + + if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD) + { + LLSpatialGroup* last_group = NULL; + for (LLCullResult::bridge_list_t::iterator i = sCull->beginVisibleBridge(); i != sCull->endVisibleBridge(); ++i) + { + LLCullResult::bridge_list_t::iterator cur_iter = i; + LLSpatialBridge* bridge = *cur_iter; + LLSpatialGroup* group = bridge->getSpatialGroup(); + + if (last_group == NULL) + { + last_group = group; + } + + if (!bridge->isDead() && group && !group->isOcclusionState(LLSpatialGroup::OCCLUDED)) + { + stateSort(bridge, camera); + } + + if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD && + last_group != group && last_group->changeLOD()) + { + last_group->mLastUpdateDistance = last_group->mDistance; + } + + last_group = group; + } + + if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD && + last_group && last_group->changeLOD()) + { + last_group->mLastUpdateDistance = last_group->mDistance; + } + } + for (LLCullResult::sg_list_t::iterator iter = sCull->beginVisibleGroups(); iter != sCull->endVisibleGroups(); ++iter) { LLSpatialGroup* group = *iter; @@ -2068,19 +2578,6 @@ void LLPipeline::stateSort(LLCamera& camera, LLCullResult &result) } } - if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD) - { - for (LLCullResult::bridge_list_t::iterator i = sCull->beginVisibleBridge(); i != sCull->endVisibleBridge(); ++i) - { - LLCullResult::bridge_list_t::iterator cur_iter = i; - LLSpatialBridge* bridge = *cur_iter; - LLSpatialGroup* group = bridge->getSpatialGroup(); - if (!bridge->isDead() && group && !group->isOcclusionState(LLSpatialGroup::OCCLUDED)) - { - stateSort(bridge, camera); - } - } - } { LLFastTimer ftm(LLFastTimer::FTM_STATESORT_DRAWABLE); for (LLCullResult::drawable_list_t::iterator iter = sCull->beginVisibleList(); @@ -2112,6 +2609,11 @@ void LLPipeline::stateSort(LLSpatialGroup* group, LLCamera& camera) LLDrawable* drawablep = *i; stateSort(drawablep, camera); } + + if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD) + { //avoid redundant stateSort calls + group->mLastUpdateDistance = group->mDistance; + } } } @@ -2119,7 +2621,7 @@ void LLPipeline::stateSort(LLSpatialGroup* group, LLCamera& camera) void LLPipeline::stateSort(LLSpatialBridge* bridge, LLCamera& camera) { LLMemType mt(LLMemType::MTYPE_PIPELINE); - if (!sShadowRender && !sSkipUpdate && bridge->getSpatialGroup()->changeLOD()) + if (/*!sShadowRender && */!sSkipUpdate && bridge->getSpatialGroup()->changeLOD()) { bool force_update = false; bridge->updateDistance(camera, force_update); @@ -2137,7 +2639,7 @@ void LLPipeline::stateSort(LLDrawable* drawablep, LLCamera& camera) return; } - if (gHideSelectedObjects) + if (LLSelectMgr::getInstance()->mHideSelectedObjects) { // if (drawablep->getVObj().notNull() && // drawablep->getVObj()->isSelected()) @@ -2183,10 +2685,11 @@ void LLPipeline::stateSort(LLDrawable* drawablep, LLCamera& camera) if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD) { - LLSpatialGroup* group = drawablep->getSpatialGroup(); + /*LLSpatialGroup* group = drawablep->getSpatialGroup(); if (!group || group->changeLOD()) { - if (drawablep->isVisible() && !sSkipUpdate) + if (drawablep->isVisible() && !sSkipUpdate)*/ + if(!sSkipUpdate) { if (!drawablep->isActive()) { @@ -2199,7 +2702,7 @@ void LLPipeline::stateSort(LLDrawable* drawablep, LLCamera& camera) drawablep->updateDistance(camera, force_update); // calls vobj->updateLOD() which calls LLVOAvatar::updateVisibility() } } - } + //} } if(!drawablep->getVOVolume()) @@ -2258,7 +2761,8 @@ void renderScriptedBeacons(LLDrawable* drawablep) { if (gPipeline.sRenderBeacons) { - gObjectList.addDebugBeacon(vobj->getPositionAgent(), "", LLColor4(1.f, 0.f, 0.f, 0.5f), LLColor4(1.f, 1.f, 1.f, 0.5f), gSavedSettings.getS32("DebugBeaconLineWidth")); + static const LLCachedControl debug_beacon_line_width("DebugBeaconLineWidth",1); + gObjectList.addDebugBeacon(vobj->getPositionAgent(), "", LLColor4(1.f, 0.f, 0.f, 0.5f), LLColor4(1.f, 1.f, 1.f, 0.5f), debug_beacon_line_width); } if (gPipeline.sRenderHighlight) @@ -2284,7 +2788,8 @@ void renderScriptedTouchBeacons(LLDrawable* drawablep) { if (gPipeline.sRenderBeacons) { - gObjectList.addDebugBeacon(vobj->getPositionAgent(), "", LLColor4(1.f, 0.f, 0.f, 0.5f), LLColor4(1.f, 1.f, 1.f, 0.5f), gSavedSettings.getS32("DebugBeaconLineWidth")); + static const LLCachedControl debug_beacon_line_width("DebugBeaconLineWidth",1); + gObjectList.addDebugBeacon(vobj->getPositionAgent(), "", LLColor4(1.f, 0.f, 0.f, 0.5f), LLColor4(1.f, 1.f, 1.f, 0.5f), debug_beacon_line_width); } if (gPipeline.sRenderHighlight) @@ -2309,7 +2814,8 @@ void renderPhysicalBeacons(LLDrawable* drawablep) { if (gPipeline.sRenderBeacons) { - gObjectList.addDebugBeacon(vobj->getPositionAgent(), "", LLColor4(0.f, 1.f, 0.f, 0.5f), LLColor4(1.f, 1.f, 1.f, 0.5f), gSavedSettings.getS32("DebugBeaconLineWidth")); + static const LLCachedControl debug_beacon_line_width("DebugBeaconLineWidth",1); + gObjectList.addDebugBeacon(vobj->getPositionAgent(), "", LLColor4(0.f, 1.f, 0.f, 0.5f), LLColor4(1.f, 1.f, 1.f, 0.5f), debug_beacon_line_width); } if (gPipeline.sRenderHighlight) @@ -2334,7 +2840,8 @@ void renderParticleBeacons(LLDrawable* drawablep) if (gPipeline.sRenderBeacons) { LLColor4 light_blue(0.5f, 0.5f, 1.f, 0.5f); - gObjectList.addDebugBeacon(vobj->getPositionAgent(), "", light_blue, LLColor4(1.f, 1.f, 1.f, 0.5f), gSavedSettings.getS32("DebugBeaconLineWidth")); + static const LLCachedControl debug_beacon_line_width("DebugBeaconLineWidth",1); + gObjectList.addDebugBeacon(vobj->getPositionAgent(), "", light_blue, LLColor4(1.f, 1.f, 1.f, 0.5f), debug_beacon_line_width); } if (gPipeline.sRenderHighlight) @@ -2509,8 +3016,8 @@ void LLPipeline::postSort(LLCamera& camera) } llpushcallstacks ; // only render if the flag is set. The flag is only set if we are in edit mode or the toggle is set in the menus - static const LLCachedControl beacon_always_on("BeaconAlwaysOn",false); - if (beacon_always_on && !sShadowRender) + static const LLCachedControl beacons_visible("BeaconsVisible", false); + if (beacons_visible && !sShadowRender) { if (sRenderScriptedTouchBeacons) { @@ -2548,8 +3055,36 @@ void LLPipeline::postSort(LLCamera& camera) LLVector3 pos = gAgent.getPosAgentFromGlobal(pos_global); if (gPipeline.sRenderBeacons) { - //pos += LLVector3(0.f, 0.f, 0.2f); - gObjectList.addDebugBeacon(pos, "", LLColor4(1.f, 1.f, 0.f, 0.5f), LLColor4(1.f, 1.f, 1.f, 0.5f), gSavedSettings.getS32("DebugBeaconLineWidth")); + // + LLAudioChannel* channel = sourcep->getChannel(); + bool const is_playing = channel && channel->isPlaying(); + S32 width = 2; + LLColor4 color = LLColor4(0.f, 0.f, 1.f, 0.5f); // Blue: Not playing and not muted. + if (is_playing) + { + static const LLCachedControl debug_beacon_line_width("DebugBeaconLineWidth",1); + llassert(!sourcep->isMuted()); + F32 gain = sourcep->getGain() * channel->getSecondaryGain(); + if (gain == 0.f) + { + color = LLColor4(1.f, 0.f, 0.f, 0.5f); // Red: Playing with gain == 0. This sucks up CPU, these should be muted. + } + else if (gain == 1.f) + { + color = LLColor4(0.f, 1.f, 0.f, 0.5f); // Green: Playing with gain == 1. + width = debug_beacon_line_width; + } + else + { + color = LLColor4(1.f, 1.f, 0.f, 0.5f); // Yellow: Playing with 0 < gain < 1. + width = 1 + gain * (debug_beacon_line_width - 1); + } + } + else if (sourcep->isMuted()) + color = LLColor4(0.f, 1.f, 1.f, 0.5f); // Cyan: Muted sound source. + gObjectList.addDebugBeacon(pos, "", color, LLColor4(1.f, 1.f, 1.f, 0.5f), width); + // + //gObjectList.addDebugBeacon(pos, "", LLColor4(1.f, 1.f, 0.f, 0.5f), LLColor4(1.f, 1.f, 1.f, 0.5f), debug_beacon_line_width); } } // now deal with highlights for all those seeable sound sources @@ -2606,7 +3141,8 @@ void render_hud_elements() gGL.color4f(1,1,1,1); if (!LLPipeline::sReflectionRender && gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI)) { - LLGLEnable multisample(GL_MULTISAMPLE_ARB); + static const LLCachedControl fsaa_samples("RenderFSAASamples",0); + LLGLEnable multisample(fsaa_samples > 0 ? GL_MULTISAMPLE_ARB : 0); gViewerWindow->renderSelections(FALSE, FALSE, FALSE); // For HUD version in render_ui_3d() // Draw the tracking overlays @@ -2617,15 +3153,8 @@ void render_hud_elements() LLViewerParcelMgr::getInstance()->render(); LLViewerParcelMgr::getInstance()->renderParcelCollision(); - // Render debugging beacons. - //gObjectList.renderObjectBeacons(); - - //TO-DO: - //V2 moved this line from LLPipeline::renderGeom - //Uncomment once multisample z-buffer issues are figured out on ati cards. - LLHUDObject::renderAll(); - - //gObjectList.resetObjectBeacons(); + // Render name tags. + LLHUDObject::renderAll(); } else if (gForceRenderLandFence) { @@ -2707,6 +3236,8 @@ void LLPipeline::renderHighlights() } } +//debug use +U32 LLPipeline::sCurRenderPoolType = 0 ; void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate) { LLMemType mt(LLMemType::MTYPE_PIPELINE); @@ -2727,6 +3258,13 @@ void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate) } } + S32 stack_depth = 0; + + if (gDebugGL) + { + glGetIntegerv(GL_MODELVIEW_STACK_DEPTH, &stack_depth); + } + /////////////////////////////////////////// // // Sync and verify GL state @@ -2768,7 +3306,8 @@ void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate) glMatrixMode(GL_MODELVIEW); LLGLSPipeline gls_pipeline; - LLGLEnable multisample(GL_MULTISAMPLE_ARB); + static const LLCachedControl fsaa_samples("RenderFSAASamples",0); + LLGLEnable multisample(fsaa_samples > 0 ? GL_MULTISAMPLE_ARB : 0); LLGLState gls_color_material(GL_COLOR_MATERIAL, mLightingDetail < 2); @@ -2832,6 +3371,9 @@ void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate) cur_type = poolp->getType(); + //debug use + sCurRenderPoolType = cur_type ; + if (occlude && cur_type >= LLDrawPool::POOL_GRASS) { occlude = FALSE; @@ -2864,14 +3406,9 @@ void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate) } poolp->endRenderPass(i); LLVertexBuffer::unbind(); - if (gDebugGL || gDebugPipeline) + if (gDebugGL) { - GLint depth; - glGetIntegerv(GL_MODELVIEW_STACK_DEPTH, &depth); - if (depth > 3) - { - llerrs << "GL matrix stack corrupted!" << llendl; - } + check_stack_depth(stack_depth); std::string msg = llformat("%s pass %d", gPoolNames[cur_type].c_str(), i); LLGLState::checkStates(msg); LLGLState::checkTextureChannels(msg); @@ -2947,10 +3484,6 @@ void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate) { // Render debugging beacons. gObjectList.renderObjectBeacons(); - //TO-DO: - //V2 moved this line to LLPipeline::render_hud_elements - //Migrate once multisample z-buffer issues are figured out on ati cards. - //LLHUDObject::renderAll(); gObjectList.resetObjectBeacons(); } else @@ -3008,7 +3541,8 @@ void LLPipeline::renderGeomDeferred(LLCamera& camera) } } - LLGLEnable multisample(GL_MULTISAMPLE_ARB); + static const LLCachedControl fsaa_samples("RenderFSAASamples",0); + LLGLEnable multisample(fsaa_samples > 0 ? GL_MULTISAMPLE_ARB : 0); LLVertexBuffer::unbind(); @@ -3096,7 +3630,8 @@ void LLPipeline::renderGeomPostDeferred(LLCamera& camera) LLGLEnable cull(GL_CULL_FACE); - LLGLEnable multisample(GL_MULTISAMPLE_ARB); + static const LLCachedControl fsaa_samples("RenderFSAASamples",0); + LLGLEnable multisample(fsaa_samples > 0 ? GL_MULTISAMPLE_ARB : 0); calcNearbyLights(camera); setupHWLights(NULL); @@ -3179,33 +3714,6 @@ void LLPipeline::renderGeomPostDeferred(LLCamera& camera) gGLLastMatrix = NULL; glLoadMatrixd(gGLModelView); - //TO-DO: - //V2 moved block to LLPipeline::renderDeferredLighting - //Migrate once multisample z-buffer issues are figured out on ati cards. - /*if(!sImpostorRender) - { - renderHighlights(); - mHighlightFaces.clear(); - - renderDebug(); - - LLVertexBuffer::unbind(); - - if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI)) - { - // Render debugging beacons. - gObjectList.renderObjectBeacons(); - LLHUDObject::renderAll(); - gObjectList.resetObjectBeacons(); - } - else - { - // Make sure particle effects disappear - LLHUDObject::renderAllForTimer(); - } - }*/ - //END - if (occlude) { occlude = FALSE; @@ -3333,7 +3841,7 @@ void LLPipeline::renderDebug() for (LLCullResult::bridge_list_t::const_iterator i = sCull->beginVisibleBridge(); i != sCull->endVisibleBridge(); ++i) { LLSpatialBridge* bridge = *i; - if (!bridge->isDead() && !bridge->isState(LLSpatialGroup::OCCLUDED) && hasRenderType(bridge->mDrawableType)) + if (!bridge->isDead() && hasRenderType(bridge->mDrawableType)) { glPushMatrix(); glMultMatrixf((F32*)bridge->mDrawable->getRenderMatrix().mMatrix); @@ -3344,79 +3852,115 @@ void LLPipeline::renderDebug() if (hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA)) { + LLVertexBuffer::unbind(); + + LLGLEnable blend(GL_BLEND); + LLGLDepthTest depth(TRUE, FALSE); + LLGLDisable cull(GL_CULL_FACE); + gGL.color4f(1,1,1,1); gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + F32 a = 0.1f; + F32 col[] = { - 1,1,0, - 0,1,1, - 1,0,1, - 1,1,1, - 1,0,0, - 0,1,0, - 0,0,1, - 0,0,0 + 1,0,0,a, + 0,1,0,a, + 0,0,1,a, + 1,0,1,a, + + 1,1,0,a, + 0,1,1,a, + 1,1,1,a, + 1,0,1,a, }; for (U32 i = 0; i < 8; i++) { - gGL.color3fv(col+i*3); - - gGL.begin(LLRender::LINES); - LLVector3* frust = mShadowCamera[i].mAgentFrustum; - gGL.vertex3fv(frust[0].mV); gGL.vertex3fv(frust[1].mV); - gGL.vertex3fv(frust[1].mV); gGL.vertex3fv(frust[2].mV); - gGL.vertex3fv(frust[2].mV); gGL.vertex3fv(frust[3].mV); - gGL.vertex3fv(frust[3].mV); gGL.vertex3fv(frust[0].mV); - - gGL.vertex3fv(frust[4].mV); gGL.vertex3fv(frust[5].mV); - gGL.vertex3fv(frust[5].mV); gGL.vertex3fv(frust[6].mV); - gGL.vertex3fv(frust[6].mV); gGL.vertex3fv(frust[7].mV); - gGL.vertex3fv(frust[7].mV); gGL.vertex3fv(frust[4].mV); - - gGL.vertex3fv(frust[0].mV); gGL.vertex3fv(frust[4].mV); - gGL.vertex3fv(frust[1].mV); gGL.vertex3fv(frust[5].mV); - gGL.vertex3fv(frust[2].mV); gGL.vertex3fv(frust[6].mV); - gGL.vertex3fv(frust[3].mV); gGL.vertex3fv(frust[7].mV); - - if (i < 4) + if (i > 3) + { //render shadow frusta as volumes + if (mShadowFrustPoints[i-4].empty()) { - LLVector3* ext = mShadowExtents[i]; - - LLVector3 box[] = - { - LLVector3(ext[0][0], ext[0][1], ext[0][2]), - LLVector3(ext[1][0], ext[0][1], ext[0][2]), - LLVector3(ext[1][0], ext[1][1], ext[0][2]), - LLVector3(ext[0][0], ext[1][1], ext[0][2]), - LLVector3(ext[0][0], ext[0][1], ext[1][2]), - LLVector3(ext[1][0], ext[0][1], ext[1][2]), - LLVector3(ext[1][0], ext[1][1], ext[1][2]), - LLVector3(ext[0][0], ext[1][1], ext[1][2]), - }; - - gGL.vertex3fv(box[0].mV); gGL.vertex3fv(box[1].mV); - gGL.vertex3fv(box[1].mV); gGL.vertex3fv(box[2].mV); - gGL.vertex3fv(box[2].mV); gGL.vertex3fv(box[3].mV); - gGL.vertex3fv(box[3].mV); gGL.vertex3fv(box[0].mV); + continue; + } - gGL.vertex3fv(box[4].mV); gGL.vertex3fv(box[5].mV); - gGL.vertex3fv(box[5].mV); gGL.vertex3fv(box[6].mV); - gGL.vertex3fv(box[6].mV); gGL.vertex3fv(box[7].mV); - gGL.vertex3fv(box[7].mV); gGL.vertex3fv(box[4].mV); + gGL.color4fv(col+(i-4)*4); + + gGL.begin(LLRender::TRIANGLE_STRIP); + gGL.vertex3fv(frust[0].mV); gGL.vertex3fv(frust[4].mV); + gGL.vertex3fv(frust[1].mV); gGL.vertex3fv(frust[5].mV); + gGL.vertex3fv(frust[2].mV); gGL.vertex3fv(frust[6].mV); + gGL.vertex3fv(frust[3].mV); gGL.vertex3fv(frust[7].mV); + gGL.vertex3fv(frust[0].mV); gGL.vertex3fv(frust[4].mV); + gGL.end(); - gGL.vertex3fv(box[0].mV); gGL.vertex3fv(box[4].mV); - gGL.vertex3fv(box[1].mV); gGL.vertex3fv(box[5].mV); - gGL.vertex3fv(box[2].mV); gGL.vertex3fv(box[6].mV); - gGL.vertex3fv(box[3].mV); gGL.vertex3fv(box[7].mV); + + gGL.begin(LLRender::TRIANGLE_STRIP); + gGL.vertex3fv(frust[0].mV); + gGL.vertex3fv(frust[1].mV); + gGL.vertex3fv(frust[3].mV); + gGL.vertex3fv(frust[2].mV); + gGL.end(); + + gGL.begin(LLRender::TRIANGLE_STRIP); + gGL.vertex3fv(frust[4].mV); + gGL.vertex3fv(frust[5].mV); + gGL.vertex3fv(frust[7].mV); + gGL.vertex3fv(frust[6].mV); + gGL.end(); } - gGL.end(); - - for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); + + if (i < 4) + { + + if (i == 0 || !mShadowFrustPoints[i].empty()) + { + //render visible point cloud + gGL.flush(); + glPointSize(8.f); + gGL.begin(LLRender::POINTS); + + F32* c = col+i*4; + gGL.color3fv(c); + + for (U32 j = 0; j < mShadowFrustPoints[i].size(); ++j) + { + gGL.vertex3fv(mShadowFrustPoints[i][j].mV); + } + gGL.end(); + + gGL.flush(); + glPointSize(1.f); + + LLVector3* ext = mShadowExtents[i]; + LLVector3 pos = (ext[0]+ext[1])*0.5f; + LLVector3 size = (ext[1]-ext[0])*0.5f; + drawBoxOutline(pos, size); + + //render camera frustum splits as outlines + gGL.begin(LLRender::LINES); + gGL.vertex3fv(frust[0].mV); gGL.vertex3fv(frust[1].mV); + gGL.vertex3fv(frust[1].mV); gGL.vertex3fv(frust[2].mV); + gGL.vertex3fv(frust[2].mV); gGL.vertex3fv(frust[3].mV); + gGL.vertex3fv(frust[3].mV); gGL.vertex3fv(frust[0].mV); + gGL.vertex3fv(frust[4].mV); gGL.vertex3fv(frust[5].mV); + gGL.vertex3fv(frust[5].mV); gGL.vertex3fv(frust[6].mV); + gGL.vertex3fv(frust[6].mV); gGL.vertex3fv(frust[7].mV); + gGL.vertex3fv(frust[7].mV); gGL.vertex3fv(frust[4].mV); + gGL.vertex3fv(frust[0].mV); gGL.vertex3fv(frust[4].mV); + gGL.vertex3fv(frust[1].mV); gGL.vertex3fv(frust[5].mV); + gGL.vertex3fv(frust[2].mV); gGL.vertex3fv(frust[6].mV); + gGL.vertex3fv(frust[3].mV); gGL.vertex3fv(frust[7].mV); + gGL.end(); + } + + } + + /*for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); iter != LLWorld::getInstance()->getRegionList().end(); ++iter) { LLViewerRegion* region = *iter; @@ -3431,7 +3975,7 @@ void LLPipeline::renderDebug() } } } - } + }*/ } } @@ -3471,13 +4015,19 @@ void LLPipeline::renderDebug() if (mRenderDebugMask & LLPipeline::RENDER_DEBUG_BUILD_QUEUE) { U32 count = 0; - U32 size = mBuildQ2.size(); + U32 size = mGroupQ2.size(); LLColor4 col; + LLVertexBuffer::unbind(); LLGLEnable blend(GL_BLEND); + gGL.setSceneBlendType(LLRender::BT_ALPHA); LLGLDepthTest depth(GL_TRUE, GL_FALSE); gGL.getTexUnit(0)->bind(LLViewerFetchedTexture::sWhiteImagep); + gGL.pushMatrix(); + glLoadMatrixd(gGLModelView); + gGLLastMatrix = NULL; + for (LLSpatialGroup::sg_vector_t::iterator iter = mGroupQ2.begin(); iter != mGroupQ2.end(); ++iter) { LLSpatialGroup* group = *iter; @@ -3499,7 +4049,7 @@ void LLPipeline::renderDebug() glMultMatrixf((F32*)bridge->mDrawable->getRenderMatrix().mMatrix); } - F32 alpha = (F32) (size-count)/size; + F32 alpha = llclamp((F32) (size-count)/size, 0.f, 1.f); LLVector2 c(1.f-alpha, alpha); @@ -3507,7 +4057,7 @@ void LLPipeline::renderDebug() ++count; - col.set(c.mV[0], c.mV[1], 0, alpha*0.5f+0.1f); + col.set(c.mV[0], c.mV[1], 0, alpha*0.5f+0.5f); group->drawObjectBox(col); if (bridge) @@ -3515,8 +4065,10 @@ void LLPipeline::renderDebug() gGL.popMatrix(); } } + + gGL.popMatrix(); } - + gGL.flush(); } @@ -3607,7 +4159,7 @@ void LLPipeline::renderForSelect(std::set& objects, BOOL render LLDrawable* drawable = vobj->mDrawable; if (vobj->isDead() || vobj->isHUDAttachment() || - (gHideSelectedObjects && vobj->isSelected()) || + (LLSelectMgr::getInstance()->mHideSelectedObjects && vobj->isSelected()) || drawable->isDead() || !hasRenderType(drawable->getRenderType())) { @@ -3733,7 +4285,7 @@ void LLPipeline::rebuildPools() max_count--; } - if (gAgent.getAvatarObject()) + if (isAgentAvatarValid()) { gAgent.getAvatarObject()->rebuildHUD(); } @@ -4028,16 +4580,19 @@ void LLPipeline::setupAvatarLights(BOOL for_edit) light_pos.normalize(); + LLLightState* light = gGL.getLight(1); + mHWLightColors[1] = diffuse; - glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuse.mV); - glLightfv(GL_LIGHT1, GL_AMBIENT, LLColor4::black.mV); - glLightfv(GL_LIGHT1, GL_SPECULAR, LLColor4::black.mV); - glLightfv(GL_LIGHT1, GL_POSITION, light_pos.mV); - glLightf (GL_LIGHT1, GL_CONSTANT_ATTENUATION, 1.0f); - glLightf (GL_LIGHT1, GL_LINEAR_ATTENUATION, 0.0f); - glLightf (GL_LIGHT1, GL_QUADRATIC_ATTENUATION, 0.0f); - glLightf (GL_LIGHT1, GL_SPOT_EXPONENT, 0.0f); - glLightf (GL_LIGHT1, GL_SPOT_CUTOFF, 180.0f); + + light->setDiffuse(diffuse); + light->setAmbient(LLColor4::black); + light->setSpecular(LLColor4::black); + light->setPosition(light_pos); + light->setConstantAttenuation(1.f); + light->setLinearAttenuation(0.f); + light->setQuadraticAttenuation(0.f); + light->setSpotExponent(0.f); + light->setSpotCutoff(180.f); } else if (gAvatarBacklight) // Always true (unless overridden in a devs .ini) { @@ -4068,22 +4623,28 @@ void LLPipeline::setupAvatarLights(BOOL for_edit) backlight_diffuse *= backlight_mag / max_component; mHWLightColors[1] = backlight_diffuse; - glLightfv(GL_LIGHT1, GL_POSITION, backlight_pos.mV); // this is just sun/moon direction - glLightfv(GL_LIGHT1, GL_DIFFUSE, backlight_diffuse.mV); - glLightfv(GL_LIGHT1, GL_AMBIENT, LLColor4::black.mV); - glLightfv(GL_LIGHT1, GL_SPECULAR, LLColor4::black.mV); - glLightf (GL_LIGHT1, GL_CONSTANT_ATTENUATION, 1.0f); - glLightf (GL_LIGHT1, GL_LINEAR_ATTENUATION, 0.0f); - glLightf (GL_LIGHT1, GL_QUADRATIC_ATTENUATION, 0.0f); - glLightf (GL_LIGHT1, GL_SPOT_EXPONENT, 0.0f); - glLightf (GL_LIGHT1, GL_SPOT_CUTOFF, 180.0f); + + LLLightState* light = gGL.getLight(1); + + light->setPosition(backlight_pos); + light->setDiffuse(backlight_diffuse); + light->setAmbient(LLColor4::black); + light->setSpecular(LLColor4::black); + light->setConstantAttenuation(1.f); + light->setLinearAttenuation(0.f); + light->setQuadraticAttenuation(0.f); + light->setSpotExponent(0.f); + light->setSpotCutoff(180.f); } else { + LLLightState* light = gGL.getLight(1); + mHWLightColors[1] = LLColor4::black; - glLightfv(GL_LIGHT1, GL_DIFFUSE, LLColor4::black.mV); - glLightfv(GL_LIGHT1, GL_AMBIENT, LLColor4::black.mV); - glLightfv(GL_LIGHT1, GL_SPECULAR, LLColor4::black.mV); + + light->setDiffuse(LLColor4::black); + light->setAmbient(LLColor4::black); + light->setSpecular(LLColor4::black); } } @@ -4267,15 +4828,17 @@ void LLPipeline::setupHWLights(LLDrawPool* pool) LLVector4 light_pos(mSunDir, 0.0f); LLColor4 light_diffuse = mSunDiffuse; mHWLightColors[0] = light_diffuse; - glLightfv(GL_LIGHT0, GL_POSITION, light_pos.mV); // this is just sun/moon direction - glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse.mV); - glLightfv(GL_LIGHT0, GL_AMBIENT, LLColor4::black.mV); - glLightfv(GL_LIGHT0, GL_SPECULAR, LLColor4::black.mV); - glLightf (GL_LIGHT0, GL_CONSTANT_ATTENUATION, 1.0f); - glLightf (GL_LIGHT0, GL_LINEAR_ATTENUATION, 0.0f); - glLightf (GL_LIGHT0, GL_QUADRATIC_ATTENUATION, 0.0f); - glLightf (GL_LIGHT0, GL_SPOT_EXPONENT, 0.0f); - glLightf (GL_LIGHT0, GL_SPOT_CUTOFF, 180.0f); + + LLLightState* light = gGL.getLight(0); + light->setPosition(light_pos); + light->setDiffuse(light_diffuse); + light->setAmbient(LLColor4::black); + light->setSpecular(LLColor4::black); + light->setConstantAttenuation(1.f); + light->setLinearAttenuation(0.f); + light->setQuadraticAttenuation(0.f); + light->setSpotExponent(0.f); + light->setSpotCutoff(180.f); } // Light 1 = Backlight (for avatars) @@ -4333,21 +4896,46 @@ void LLPipeline::setupHWLights(LLDrawPool* pool) float linatten = x / (light_radius); // % of brightness at radius mHWLightColors[cur_light] = light_color; - S32 gllight = GL_LIGHT0+cur_light; - glLightfv(gllight, GL_POSITION, light_pos_gl.mV); - glLightfv(gllight, GL_DIFFUSE, light_color.mV); - glLightfv(gllight, GL_AMBIENT, LLColor4::black.mV); - glLightf (gllight, GL_CONSTANT_ATTENUATION, 0.0f); - glLightf (gllight, GL_LINEAR_ATTENUATION, linatten); - glLightf (gllight, GL_QUADRATIC_ATTENUATION, 0.0f); - //Point lights + LLLightState* light_state = gGL.getLight(cur_light); + + light_state->setPosition(light_pos_gl); + light_state->setDiffuse(light_color); + light_state->setAmbient(LLColor4::black); + light_state->setConstantAttenuation(0.f); + if (sRenderDeferred) { - glLightf (gllight, GL_SPOT_EXPONENT, 0.0f); - glLightf (gllight, GL_SPOT_CUTOFF, 180.0f); + light_state->setLinearAttenuation(light_radius*1.5f); + light_state->setQuadraticAttenuation(light->getLightFalloff()*0.5f+1.f); + } + else + { + light_state->setLinearAttenuation(linatten); + light_state->setQuadraticAttenuation(0.f); + } + + static const LLCachedControl render_spot_lights_in_nondeferred("RenderSpotLightsInNondeferred",false); + if (light->isLightSpotlight() // directional (spot-)light + && (LLPipeline::sRenderDeferred || render_spot_lights_in_nondeferred)) // these are only rendered as GL spotlights if we're in deferred rendering mode *or* the setting forces them on + { + LLVector3 spotparams = light->getSpotLightParams(); + LLQuaternion quat = light->getRenderRotation(); + LLVector3 at_axis(0,0,-1); // this matches deferred rendering's object light direction + at_axis *= quat; + light_state->setSpotDirection(at_axis); + light_state->setSpotCutoff(90.f); + light_state->setSpotExponent(2.f); + + light_state->setSpecular(LLColor4::black); + } + else // omnidirectional (point) light + { + light_state->setSpotExponent(0.f); + light_state->setSpotCutoff(180.f); + // we use specular.w = 1.0 as a cheap hack for the shaders to know that this is omnidirectional rather than a spotlight - const float specular[] = {0.f, 0.f, 0.f, 1.f}; - glLightfv(gllight, GL_SPECULAR, specular); + const LLColor4 specular(0.f, 0.f, 0.f, 1.f); + light_state->setSpecular(specular); //llinfos << "boring light" << llendl; } cur_light++; @@ -4360,12 +4948,12 @@ void LLPipeline::setupHWLights(LLDrawPool* pool) for ( ; cur_light < 8 ; cur_light++) { mHWLightColors[cur_light] = LLColor4::black; - S32 gllight = GL_LIGHT0+cur_light; - glLightfv(gllight, GL_DIFFUSE, LLColor4::black.mV); - glLightfv(gllight, GL_AMBIENT, LLColor4::black.mV); - glLightfv(gllight, GL_SPECULAR, LLColor4::black.mV); - } + LLLightState* light = gGL.getLight(cur_light); + light->setDiffuse(LLColor4::black); + light->setAmbient(LLColor4::black); + light->setSpecular(LLColor4::black); + } if (isAgentAvatarValid() && gAgent.getAvatarObject()->mSpecialRenderMode == 3) { @@ -4381,23 +4969,24 @@ void LLPipeline::setupHWLights(LLDrawPool* pool) float linatten = x / (light_radius); // % of brightness at radius mHWLightColors[2] = light_color; - S32 gllight = GL_LIGHT2; - glLightfv(gllight, GL_POSITION, light_pos_gl.mV); - glLightfv(gllight, GL_DIFFUSE, light_color.mV); - glLightfv(gllight, GL_AMBIENT, LLColor4::black.mV); - glLightfv(gllight, GL_SPECULAR, LLColor4::black.mV); - glLightf (gllight, GL_CONSTANT_ATTENUATION, 0.0f); - glLightf (gllight, GL_LINEAR_ATTENUATION, linatten); - glLightf (gllight, GL_QUADRATIC_ATTENUATION, 0.0f); - glLightf (gllight, GL_SPOT_EXPONENT, 0.0f); - glLightf (gllight, GL_SPOT_CUTOFF, 180.0f); + LLLightState* light = gGL.getLight(2); + + light->setPosition(light_pos_gl); + light->setDiffuse(light_color); + light->setAmbient(LLColor4::black); + light->setSpecular(LLColor4::black); + light->setQuadraticAttenuation(0.f); + light->setConstantAttenuation(0.f); + light->setLinearAttenuation(linatten); + light->setSpotExponent(0.f); + light->setSpotCutoff(180.f); } // Init GL state glDisable(GL_LIGHTING); - for (S32 gllight=GL_LIGHT0; gllight<=GL_LIGHT7; gllight++) + for (S32 i = 0; i < 8; ++i) { - glDisable(gllight); + gGL.getLight(i)->disable(); } mLightMask = 0; } @@ -4420,15 +5009,16 @@ void LLPipeline::enableLights(U32 mask) { for (S32 i=0; i<8; i++) { + LLLightState* light = gGL.getLight(i); if (mask & (1<enable(); + light->setDiffuse(mHWLightColors[i]); } else { - glDisable(GL_LIGHT0 + i); - glLightfv(GL_LIGHT0 + i, GL_DIFFUSE, LLColor4::black.mV); + light->disable(); + light->setDiffuse(LLColor4::black); } } } @@ -4449,7 +5039,6 @@ void LLPipeline::enableLightsStatic() if (mLightingDetail >= 2) { mask |= mLightMovingMask; // Hardware moving lights - glColor4f(0.f, 0.f, 0.f, 1.0f); // no local lighting by default } else { @@ -4463,10 +5052,7 @@ void LLPipeline::enableLightsDynamic() assertInitialized(); U32 mask = 0xff & (~2); // Local lights enableLights(mask); - if (mLightingDetail >= 2) - { - glColor4f(0.f, 0.f, 0.f, 1.f); // no local lighting by default - } + LLVOAvatar* avatarp = gAgent.getAvatarObject(); @@ -4506,16 +5092,12 @@ void LLPipeline::enableLightsFullbright(const LLColor4& color) enableLights(mask); glLightModelfv(GL_LIGHT_MODEL_AMBIENT,color.mV); - /*if (mLightingDetail >= 2) - { - glColor4f(0.f, 0.f, 0.f, 1.f); // no local lighting by default - }*/ } void LLPipeline::disableLights() { enableLights(0); // no lighting (full bright) - glColor4f(1.f, 1.f, 1.f, 1.f); // lighting color = white by default + glColor4f(1.f, 1.f, 1.f, 1.f); } //============================================================================ @@ -4766,7 +5348,10 @@ void LLPipeline::toggleRenderPairedTypeControl(void *data) for(U8 i = 1 ;i < NUM_RENDER_TYPES; ++i) { if( typeflags & (1ULL<mNameText.notNull() && av->mNameText->lineSegmentIntersect(start, local_end, position)) + if (av->mNameText.notNull() + && av->mNameText->lineSegmentIntersect(start, local_end, position)) { drawable = av->mDrawable; local_end = position; @@ -5139,8 +5725,7 @@ void LLPipeline::resetVertexBuffers(LLDrawable* drawable) for (S32 i = 0; i < drawable->getNumFaces(); i++) { LLFace* facep = drawable->getFace(i); - facep->mVertexBuffer = NULL; - facep->mLastVertexBuffer = NULL; + facep->clearVertexBuffer(); } } @@ -5276,6 +5861,10 @@ void validate_framebuffer_object() case GL_FRAMEBUFFER_COMPLETE_EXT: //framebuffer OK, no error. break; + case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT: + // frame buffer not OK: probably means unsupported depth buffer format + llerrs << "Framebuffer Incomplete Missing Attachment." << llendl; + break; case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT: // frame buffer not OK: probably means unsupported depth buffer format llerrs << "Framebuffer Incomplete Dimensions." << llendl; @@ -5326,7 +5915,7 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield, b if (res_mod > 1) { - tc2 /= (F32) res_mod; + tc2 /= (F32) res_mod.get(); } gGL.setColorMask(true, true); @@ -5412,8 +6001,8 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield, b gGlowExtractProgram.bind(); static const LLCachedControl minLum("RenderGlowMinLuminance",2.5); - static const LLCachedControl maxAlpha("RenderGlowMaxExtractAlpha",0.065f); - static const LLCachedControl warmthAmount("RenderGlowWarmthAmount",0.0f); + static const LLCachedControl maxAlpha("RenderGlowMaxExtractAlpha",0.065f); + static const LLCachedControl warmthAmount("RenderGlowWarmthAmount",0.0f); static const LLCachedControl lumWeights("RenderGlowLumWeights",LLVector3(.299f,.587f,.114f)); static const LLCachedControl warmthWeights("RenderGlowWarmthWeights",LLVector3(1.f,.5f,.7f)); gGlowExtractProgram.uniform1f("minLuminance", llmax(minLum.get(),0.0f)); @@ -5453,8 +6042,6 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield, b tc1.setVec(0,0); tc2.setVec(2,2); - - // power of two between 1 and 1024 static const LLCachedControl glowResPow("RenderGlowResolutionPow",9); const U32 glow_res = llmax(1, @@ -5505,7 +6092,7 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield, b gGL.begin(LLRender::TRIANGLE_STRIP); gGL.texCoord2f(tc1.mV[0], tc1.mV[1]); gGL.vertex2f(-1,-1); - + gGL.texCoord2f(tc1.mV[0], tc2.mV[1]); gGL.vertex2f(-1,3); @@ -5527,15 +6114,176 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield, b gViewerWindow->setupViewport(); + tc2.setVec((F32) gViewerWindow->getWindowDisplayWidth(), + (F32) gViewerWindow->getWindowDisplayHeight()); + gGL.flush(); - { - LLVertexBuffer::unbind(); + LLVertexBuffer::unbind(); + if (LLPipeline::sRenderDeferred && !LLViewerCamera::getInstance()->cameraUnderWater()) + { + bool dof_enabled = true; + + LLGLSLShader* shader = &gDeferredPostProgram; + static const LLCachedControl render_dof("RenderDepthOfField",false); + if (LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_DEFERRED) > 2) + { + shader = &gDeferredGIFinalProgram; + dof_enabled = false; + } + else if (LLToolMgr::getInstance()->inBuildMode() || !render_dof) + { //squish focal length when in build mode (or if DoF is disabled) so DoF doesn't make editing objects difficult + shader = &gDeferredPostNoDoFProgram; + dof_enabled = false; + } - tc2.setVec((F32) gViewerWindow->getWindowDisplayWidth(), - (F32) gViewerWindow->getWindowDisplayHeight()); + LLGLDisable blend(GL_BLEND); + bindDeferredShader(*shader); + + if (dof_enabled) + { + //depth of field focal plane calculations + + static F32 current_distance = 16.f; + static F32 start_distance = 16.f; + static F32 transition_time = 1.f; + + LLVector3 focus_point; + + /*LLViewerObject* obj = LLViewerMediaFocus::getInstance()->getFocusedObject(); + if (obj && obj->mDrawable && obj->isSelected()) + { //focus on selected media object + S32 face_idx = LLViewerMediaFocus::getInstance()->getFocusedFace(); + if (obj && obj->mDrawable) + { + LLFace* face = obj->mDrawable->getFace(face_idx); + if (face) + { + focus_point = face->getPositionAgent(); + } + } + }*/ + + if (focus_point.isExactlyZero()) + { + if (LLViewerJoystick::getInstance()->getOverrideCamera()) + { //focus on point under cursor + focus_point = gDebugRaycastIntersection; + } + else if (gAgent.cameraMouselook()) + { //focus on point under mouselook crosshairs + gViewerWindow->cursorIntersect(-1, -1, 512.f, NULL, -1, FALSE, + NULL, + &focus_point); + } + else + { + LLViewerObject* obj = gAgent.getFocusObject(); + if (obj) + { //focus on alt-zoom target + focus_point = LLVector3(gAgent.getFocusGlobal()-gAgent.getRegion()->getOriginGlobal()); + } + else + { //focus on your avatar + focus_point = gAgent.getPositionAgent(); + } + } + } + + LLVector3 eye = LLViewerCamera::getInstance()->getOrigin(); + F32 target_distance = 16.f; + if (!focus_point.isExactlyZero()) + { + target_distance = LLViewerCamera::getInstance()->getAtAxis() * (focus_point-eye); + } + + if (transition_time >= 1.f && + fabsf(current_distance-target_distance)/current_distance > 0.01f) + { //large shift happened, interpolate smoothly to new target distance + transition_time = 0.f; + start_distance = current_distance; + } + else if (transition_time < 1.f) + { //currently in a transition, continue interpolating + static const LLCachedControl cam_focus_transition_time("CameraFocusTransitionTime",.5f); + transition_time += 1.f/cam_focus_transition_time*gFrameIntervalSeconds; + transition_time = llmin(transition_time, 1.f); + + F32 t = cosf(transition_time*F_PI+F_PI)*0.5f+0.5f; + current_distance = start_distance + (target_distance-start_distance)*t; + } + else + { //small or no change, just snap to target distance + current_distance = target_distance; + } + + //convert to mm + F32 subject_distance = current_distance*1000.f; + static const LLCachedControl fnumber("CameraFNumber",9.f); + static const LLCachedControl default_focal_length("CameraFocalLength",50.f); + static const LLCachedControl cam_field_of_view("CameraFieldOfView",60.f); + + F32 fov = LLViewerCamera::getInstance()->getView(); + + const F32 default_fov = cam_field_of_view * F_PI/180.f; + //const F32 default_aspect_ratio = gSavedSettings.getF32("CameraAspectRatio"); + + //F32 aspect_ratio = (F32) mScreen.getWidth()/(F32)mScreen.getHeight(); + + F32 dv = 2.f*default_focal_length * tanf(default_fov/2.f); + //F32 dh = 2.f*default_focal_length * tanf(default_fov*default_aspect_ratio/2.f); + + F32 focal_length = dv/(2*tanf(fov/2.f)); + + //F32 tan_pixel_angle = tanf(LLDrawable::sCurPixelAngle); + + // from wikipedia -- c = |s2-s1|/s2 * f^2/(N(S1-f)) + // where N = fnumber + // s2 = dot distance + // s1 = subject distance + // f = focal length + // + + F32 blur_constant = focal_length*focal_length/(fnumber*(subject_distance-focal_length)); + blur_constant /= 1000.f; //convert to meters for shader + F32 magnification = focal_length/(subject_distance-focal_length); + + shader->uniform1f("focal_distance", -subject_distance/1000.f); + shader->uniform1f("blur_constant", blur_constant); + shader->uniform1f("tan_pixel_angle", tanf(1.f/LLDrawable::sCurPixelAngle)); + shader->uniform1f("magnification", magnification); + } + + S32 channel = shader->enableTexture(LLViewerShaderMgr::DEFERRED_DIFFUSE, LLTexUnit::TT_RECT_TEXTURE); + if (channel > -1) + { + mScreen.bindTexture(0, channel); + gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR); + } + //channel = shader->enableTexture(LLViewerShaderMgr::DEFERRED_DEPTH, LLTexUnit::TT_RECT_TEXTURE); + //if (channel > -1) + //{ + //gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR); + //} + + gGL.begin(LLRender::TRIANGLE_STRIP); + gGL.texCoord2f(tc1.mV[0], tc1.mV[1]); + gGL.vertex2f(-1,-1); + + gGL.texCoord2f(tc1.mV[0], tc2.mV[1]); + gGL.vertex2f(-1,3); + + gGL.texCoord2f(tc2.mV[0], tc1.mV[1]); + gGL.vertex2f(3,-1); + + gGL.end(); + + unbindDeferredShader(*shader); + } + else + { if (res_mod > 1) { @@ -5576,14 +6324,16 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield, b gGL.getTexUnit(0)->bind(&mGlow[1]); gGL.getTexUnit(1)->activate(); gGL.getTexUnit(1)->enable(LLTexUnit::TT_RECT_TEXTURE); - + + //tex unit 1 gGL.getTexUnit(1)->setTextureColorBlend(LLTexUnit::TBO_ADD, LLTexUnit::TBS_TEX_COLOR, LLTexUnit::TBS_PREV_COLOR); gGL.getTexUnit(1)->bind(&mScreen); gGL.getTexUnit(1)->activate(); - LLGLEnable multisample(GL_MULTISAMPLE_ARB); + static const LLCachedControl fsaa_samples("RenderFSAASamples",0); + LLGLEnable multisample(fsaa_samples > 0 ? GL_MULTISAMPLE_ARB : 0); buff->setBuffer(mask); buff->drawArrays(LLRender::TRIANGLE_STRIP, 0, 3); @@ -5593,15 +6343,12 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield, b gGL.getTexUnit(0)->activate(); gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); + } - //TO-DO: - //V2 requires this for hover text and such since they have been pulled out of geom render. - //Do this when multisample z-buffer issues are figured out - if (LLRenderTarget::sUseFBO) - { //copy depth buffer from mScreen to framebuffer - LLRenderTarget::copyContentsToFramebuffer(mScreen, 0, 0, mScreen.getWidth(), mScreen.getHeight(), - 0, 0, mScreen.getWidth(), mScreen.getHeight(), GL_DEPTH_BUFFER_BIT, GL_NEAREST); - } + if (LLRenderTarget::sUseFBO) + { //copy depth buffer from mScreen to framebuffer + LLRenderTarget::copyContentsToFramebuffer(mScreen, 0, 0, mScreen.getWidth(), mScreen.getHeight(), + 0, 0, mScreen.getWidth(), mScreen.getHeight(), GL_DEPTH_BUFFER_BIT, GL_NEAREST); } @@ -5618,8 +6365,17 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield, b } -void LLPipeline::bindDeferredShader(LLGLSLShader& shader, U32 light_index) +void LLPipeline::bindDeferredShader(LLGLSLShader& shader, U32 light_index, LLRenderTarget* gi_source, LLRenderTarget* last_gi_post, U32 noise_map) { + LLFastTimer t(LLFastTimer::FTM_BIND_DEFERRED); + + if (noise_map == 0xFFFFFFFF) + { + noise_map = mNoiseMap; + } + + LLGLState::checkTextureChannels(); + shader.bind(); S32 channel = 0; channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_DIFFUSE, LLTexUnit::TT_RECT_TEXTURE); @@ -5627,7 +6383,6 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, U32 light_index) { mDeferredScreen.bindTexture(0,channel); gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT); - //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); } channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_SPECULAR, LLTexUnit::TT_RECT_TEXTURE); @@ -5644,26 +6399,172 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, U32 light_index) gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT); } - channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_POSITION, LLTexUnit::TT_RECT_TEXTURE); + if (gi_source) + { + BOOL has_gi = FALSE; + channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_GI_DIFFUSE); + if (channel > -1) + { + has_gi = TRUE; + gi_source->bindTexture(0, channel); + gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR); + } + + channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_GI_SPECULAR); + if (channel > -1) + { + has_gi = TRUE; + gi_source->bindTexture(1, channel); + gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR); + } + + channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_GI_NORMAL); + if (channel > -1) + { + has_gi = TRUE; + gi_source->bindTexture(2, channel); + gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR); + } + + channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_GI_MIN_POS); + if (channel > -1) + { + has_gi = TRUE; + gi_source->bindTexture(1, channel); + gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR); + } + + channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_GI_MAX_POS); + if (channel > -1) + { + has_gi = TRUE; + gi_source->bindTexture(3, channel); + gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR); + } + + channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_GI_LAST_DIFFUSE); + if (channel > -1) + { + has_gi = TRUE; + last_gi_post->bindTexture(0, channel); + gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR); + } + + channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_GI_LAST_NORMAL); + if (channel > -1) + { + has_gi = TRUE; + last_gi_post->bindTexture(2, channel); + gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR); + } + + channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_GI_LAST_MAX_POS); + if (channel > -1) + { + has_gi = TRUE; + last_gi_post->bindTexture(1, channel); + gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR); + } + + channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_GI_LAST_MIN_POS); + if (channel > -1) + { + has_gi = TRUE; + last_gi_post->bindTexture(3, channel); + gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR); + } + + channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_GI_LIGHT, LLTexUnit::TT_RECT_TEXTURE); + if (channel > -1) + { + has_gi = TRUE; + gi_source->bindTexture(0, channel); + gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT); + } + + channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_GI_DEPTH); + if (channel > -1) + { + has_gi = TRUE; + gGL.getTexUnit(channel)->bind(gi_source, TRUE); + gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT); + stop_glerror(); + + glTexParameteri(LLTexUnit::getInternalType(mGIMap.getUsage()), GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE); + glTexParameteri(LLTexUnit::getInternalType(mGIMap.getUsage()), GL_DEPTH_TEXTURE_MODE_ARB, GL_ALPHA); + + stop_glerror(); + } + + if (has_gi) + { + F32 range_x = llmin(mGIRange.mV[0], 1.f); + F32 range_y = llmin(mGIRange.mV[1], 1.f); + + LLVector2 scale(range_x,range_y); + + LLVector2 kern[25]; + + for (S32 i = 0; i < 5; ++i) + { + for (S32 j = 0; j < 5; ++j) + { + S32 idx = i*5+j; + kern[idx].mV[0] = (i-2)*0.5f; + kern[idx].mV[1] = (j-2)*0.5f; + kern[idx].scaleVec(scale); + } + } + + shader.uniform2fv("gi_kern", 25, (F32*) kern); + shader.uniformMatrix4fv("gi_mat", 1, FALSE, mGIMatrix.m); + shader.uniformMatrix4fv("gi_mat_proj", 1, FALSE, mGIMatrixProj.m); + shader.uniformMatrix4fv("gi_inv_proj", 1, FALSE, mGIInvProj.m); + shader.uniformMatrix4fv("gi_norm_mat", 1, FALSE, mGINormalMatrix.m); + } + } + + /*channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_POSITION, LLTexUnit::TT_RECT_TEXTURE); if (channel > -1) { mDeferredScreen.bindTexture(3, channel); - } + }*/ channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_DEPTH, LLTexUnit::TT_RECT_TEXTURE); if (channel > -1) { - gGL.getTexUnit(channel)->bind(&mDeferredScreen, TRUE); + gGL.getTexUnit(channel)->bind(&mDeferredDepth, TRUE); gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT); + stop_glerror(); + + glTexParameteri(LLTexUnit::getInternalType(mDeferredDepth.getUsage()), GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE); + glTexParameteri(LLTexUnit::getInternalType(mDeferredDepth.getUsage()), GL_DEPTH_TEXTURE_MODE_ARB, GL_ALPHA); + + stop_glerror(); + + glh::matrix4f projection = glh_get_current_projection(); + glh::matrix4f inv_proj = projection.inverse(); + + shader.uniformMatrix4fv("inv_proj", 1, FALSE, inv_proj.m); + shader.uniform4f("viewport", (F32) gGLViewport[0], + (F32) gGLViewport[1], + (F32) gGLViewport[2], + (F32) gGLViewport[3]); } channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_NOISE); if (channel > -1) { - gGL.getTexUnit(channel)->bindManual(LLTexUnit::TT_TEXTURE, mNoiseMap); + gGL.getTexUnit(channel)->bindManual(LLTexUnit::TT_TEXTURE, noise_map); gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT); } + channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_LIGHTFUNC); + if (channel > -1) + { + gGL.getTexUnit(channel)->bindManual(LLTexUnit::TT_TEXTURE, mLightFunc); + } + stop_glerror(); channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_LIGHT, LLTexUnit::TT_RECT_TEXTURE); @@ -5673,16 +6574,69 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, U32 light_index) gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT); } + channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_LUMINANCE); + if (channel > -1) + { + gGL.getTexUnit(channel)->bindManual(LLTexUnit::TT_TEXTURE, mLuminanceMap.getTexture(), true); + gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_TRILINEAR); + } + + channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_BLOOM); + if (channel > -1) + { + mGlow[1].bindTexture(0, channel); + } + + channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_EDGE, LLTexUnit::TT_RECT_TEXTURE); + if (channel > -1) + { + mEdgeMap.bindTexture(0, channel); + gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT); + } + + channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_SUN_LIGHT, LLTexUnit::TT_RECT_TEXTURE); + if (channel > -1) + { + mDeferredLight[1].bindTexture(0, channel); + gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT); + } + + channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_LOCAL_LIGHT, LLTexUnit::TT_RECT_TEXTURE); + if (channel > -1) + { + mDeferredLight[2].bindTexture(0, channel); + gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT); + } + + stop_glerror(); for (U32 i = 0; i < 4; i++) + { + channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_SHADOW0+i, LLTexUnit::TT_RECT_TEXTURE); + stop_glerror(); + if (channel > -1) + { + stop_glerror(); + gGL.getTexUnit(channel)->bind(&mShadow[i], TRUE); + gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR); + gGL.getTexUnit(channel)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); + stop_glerror(); + + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB); + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL); + stop_glerror(); + } + } + + for (U32 i = 4; i < 6; i++) { channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_SHADOW0+i); stop_glerror(); if (channel > -1) { stop_glerror(); - gGL.getTexUnit(channel)->bind(&mSunShadow[i], TRUE); + gGL.getTexUnit(channel)->bind(&mShadow[i], TRUE); gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR); gGL.getTexUnit(channel)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); stop_glerror(); @@ -5695,17 +6649,19 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, U32 light_index) stop_glerror(); - F32 mat[64]; + F32 mat[16*6]; for (U32 i = 0; i < 16; i++) { mat[i] = mSunShadowMatrix[0].m[i]; mat[i+16] = mSunShadowMatrix[1].m[i]; mat[i+32] = mSunShadowMatrix[2].m[i]; mat[i+48] = mSunShadowMatrix[3].m[i]; + mat[i+64] = mSunShadowMatrix[4].m[i]; + mat[i+80] = mSunShadowMatrix[5].m[i]; } - shader.uniformMatrix4fv("shadow_matrix[0]", 4, FALSE, mat); - shader.uniformMatrix4fv("shadow_matrix", 4, FALSE, mat); + shader.uniformMatrix4fv("shadow_matrix[0]", 6, FALSE, mat); + shader.uniformMatrix4fv("shadow_matrix", 6, FALSE, mat); stop_glerror(); @@ -5734,11 +6690,33 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, U32 light_index) static const LLCachedControl render_shadow_noise("RenderShadowNoise",-.0001f); static const LLCachedControl render_shadow_blur_size("RenderShadowBlurSize",.7f); static const LLCachedControl render_ssao_scale("RenderSSAOScale",500); - static const LLCachedControl render_ssao_max_scale("RenderSSAOMaxScale",60); + static const LLCachedControl render_ssao_max_scale("RenderSSAOMaxScale",200); static const LLCachedControl render_ssao_factor("RenderSSAOFactor",.3f); - static const LLCachedControl render_ssao_effect("RenderSSAOEffect",LLVector3(.4f,1,0)); + static const LLCachedControl render_ssao_effect("RenderSSAOEffect",LLVector3(.4f,1.f,0.f)); static const LLCachedControl render_deferred_alpha_soft("RenderDeferredAlphaSoften",.75f); - + static const LLCachedControl render_shadow_offset_error("RenderShadowOffsetError",0.f); + static const LLCachedControl render_shadow_bias_error("RenderShadowBiasError",0.f); + static const LLCachedControl render_shadow_offset("RenderShadowOffset",.1f); + static const LLCachedControl render_shadow_bias("RenderShadowBias",0.f); + static const LLCachedControl render_spot_shadow_offset("RenderSpotShadowOffset",.4f); + static const LLCachedControl render_spot_shadow_bias("RenderSpotShadowBias",0.f); + + static const LLCachedControl render_luminance_scale("RenderLuminanceScale",1.f); + static const LLCachedControl render_sun_luminance_scale("RenderSunLuminanceScale",1.f); + static const LLCachedControl render_sun_luminance_offset("RenderSunLuminanceOffset",0.f); + static const LLCachedControl render_luminance_detail("RenderLuminanceDetail",16.f); + static const LLCachedControl render_gi_range("RenderGIRange",96.f); + static const LLCachedControl render_gi_brightness("RenderGIBrightness",.3f); + static const LLCachedControl render_gi_luminance("RenderGILuminance",.075f); + static const LLCachedControl render_gi_blur_edge_weight("RenderGIBlurEdgeWeight",.8f); + static const LLCachedControl render_gi_blur_brightness("RenderGIBlurBrightness",1.025f); + static const LLCachedControl render_gi_render_gi_noise("RenderGINoise",.7); + static const LLCachedControl render_gi_attenuation("RenderGIAttenuation",.1f); + static const LLCachedControl render_gi_ambiance("RenderGIAmbiance",.5f); + static const LLCachedControl render_edge_depth_cutoff("RenderEdgeDepthCutoff",.01f); + static const LLCachedControl render_edge_norm_cutoff("RenderEdgeNormCutoff",.25f); + + shader.uniform1f("sun_wash", render_deferred_sun_wash); shader.uniform1f("shadow_noise", render_shadow_noise); shader.uniform1f("blur_size", render_shadow_blur_size); @@ -5760,9 +6738,34 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, U32 light_index) matrix_nondiag, matrix_nondiag, matrix_diag}; shader.uniformMatrix3fv("ssao_effect_mat", 1, GL_FALSE, ssao_effect_mat); + F32 shadow_offset_error = 1.f + render_shadow_offset_error * fabsf(LLViewerCamera::getInstance()->getOrigin().mV[2]); + F32 shadow_bias_error = 1.f + render_shadow_bias_error * fabsf(LLViewerCamera::getInstance()->getOrigin().mV[2]); + shader.uniform2f("screen_res", mDeferredScreen.getWidth(), mDeferredScreen.getHeight()); shader.uniform1f("near_clip", LLViewerCamera::getInstance()->getNear()*2.f); - shader.uniform1f("alpha_soften", render_deferred_alpha_soft); + shader.uniform1f ("shadow_offset", render_shadow_offset*shadow_offset_error); + shader.uniform1f("shadow_bias", render_shadow_bias*shadow_bias_error); + shader.uniform1f ("spot_shadow_offset", render_spot_shadow_offset); + shader.uniform1f("spot_shadow_bias", render_spot_shadow_bias); + + shader.uniform1f("lum_scale", render_luminance_scale); + shader.uniform1f("sun_lum_scale", render_sun_luminance_scale); + shader.uniform1f("sun_lum_offset", render_sun_luminance_offset); + shader.uniform1f("lum_lod", render_luminance_detail); + shader.uniform1f("gi_range", render_gi_range); + shader.uniform1f("gi_brightness", render_gi_brightness); + shader.uniform1f("gi_luminance", render_gi_luminance); + shader.uniform1f("gi_edge_weight", render_gi_blur_edge_weight); + shader.uniform1f("gi_blur_brightness", render_gi_blur_brightness); + shader.uniform1f("gi_sample_width", mGILightRadius); + shader.uniform1f("gi_noise", render_gi_render_gi_noise); + shader.uniform1f("gi_attenuation", render_gi_attenuation); + shader.uniform1f("gi_ambiance", render_gi_ambiance); + shader.uniform2f("shadow_res", mShadow[0].getWidth(), mShadow[0].getHeight()); + shader.uniform2f("proj_shadow_res", mShadow[4].getWidth(), mShadow[4].getHeight()); + shader.uniform1f("depth_cutoff", render_edge_depth_cutoff); + shader.uniform1f("norm_cutoff", render_edge_norm_cutoff); + if (shader.getUniformLocation("norm_mat") >= 0) { glh::matrix4f norm_mat = glh_get_current_modelview().inverse().transpose(); @@ -5777,188 +6780,295 @@ void LLPipeline::renderDeferredLighting() return; } - LLViewerCamera* camera = LLViewerCamera::getInstance(); - /*{ + { + LLFastTimer ftm(LLFastTimer::FTM_RENDER_DEFERRED); + + LLViewerCamera* camera = LLViewerCamera::getInstance(); + { LLGLDepthTest depth(GL_TRUE); mDeferredDepth.copyContents(mDeferredScreen, 0, 0, mDeferredScreen.getWidth(), mDeferredScreen.getHeight(), 0, 0, mDeferredDepth.getWidth(), mDeferredDepth.getHeight(), GL_DEPTH_BUFFER_BIT, GL_NEAREST); - }*/ + } - LLGLEnable multisample(GL_MULTISAMPLE_ARB); + static const LLCachedControl fsaa_samples("RenderFSAASamples",0); + LLGLEnable multisample(fsaa_samples > 0 ? GL_MULTISAMPLE_ARB : 0); - if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD)) - { - gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_HUD); - } - - //ati doesn't seem to love actually using the stencil buffer on FBO's - LLGLEnable stencil(GL_STENCIL_TEST); - glStencilFunc(GL_EQUAL, 1, 0xFFFFFFFF); - glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); - - gGL.setColorMask(true, true); - - //mDeferredLight[0].copyContents(mDeferredScreen, 0, 0, mDeferredScreen.getWidth(), mDeferredScreen.getHeight(), - // 0, 0, mDeferredLight[0].getWidth(), mDeferredLight[0].getHeight(), GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST); - - //draw a cube around every light - LLVertexBuffer::unbind(); - - //glBlendFunc(GL_ONE, GL_ONE); - LLGLEnable cull(GL_CULL_FACE); - LLGLEnable blend(GL_BLEND); - - glh::matrix4f mat = glh_copy_matrix(gGLModelView); - - F32 vert[] = - { - -1,1, - -1,-3, - 3,1, - }; - glVertexPointer(2, GL_FLOAT, 0, vert); - glColor3f(1,1,1); - - { - setupHWLights(NULL); //to set mSunDir; - LLVector4 dir(mSunDir, 0.f); - glh::vec4f tc(dir.mV); - mat.mult_matrix_vec(tc); - glTexCoord4f(tc.v[0], tc.v[1], tc.v[2], 0); - } - - glPushMatrix(); - glLoadIdentity(); - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glLoadIdentity(); - - mDeferredLight[0].bindTarget(); - - //Sun shadows. - { - bindDeferredShader(gDeferredSunProgram); - - glClearColor(1,1,1,1); - mDeferredLight[0].clear(GL_COLOR_BUFFER_BIT); - glClearColor(0,0,0,0); - - glh::matrix4f inv_trans = glh_get_current_modelview().inverse().transpose(); - - const U32 slice = 32; - F32 offset[slice*3]; - for (U32 i = 0; i < 4; i++) + if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD)) { - for (U32 j = 0; j < 8; j++) + gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_HUD); + } + + //ati doesn't seem to love actually using the stencil buffer on FBO's + LLGLEnable stencil(GL_STENCIL_TEST); + glStencilFunc(GL_EQUAL, 1, 0xFFFFFFFF); + glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); + + gGL.setColorMask(true, true); + + //draw a cube around every light + LLVertexBuffer::unbind(); + + LLGLEnable cull(GL_CULL_FACE); + LLGLEnable blend(GL_BLEND); + + glh::matrix4f mat = glh_copy_matrix(gGLModelView); + + F32 vert[] = + { + -1,1, + -1,-3, + 3,1, + }; + glVertexPointer(2, GL_FLOAT, 0, vert); + glColor3f(1,1,1); + + { + setupHWLights(NULL); //to set mSunDir; + LLVector4 dir(mSunDir, 0.f); + glh::vec4f tc(dir.mV); + mat.mult_matrix_vec(tc); + glTexCoord4f(tc.v[0], tc.v[1], tc.v[2], 0); + } + + glPushMatrix(); + glLoadIdentity(); + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + + static const LLCachedControl render_deferred_ssao("RenderDeferredSSAO",false); + static const LLCachedControl render_shadow_detail("RenderShadowDetail",0); + if (render_deferred_ssao || render_shadow_detail > 0) + { + mDeferredLight[0].bindTarget(); + { //paint shadow/SSAO light map (direct lighting lightmap) + LLFastTimer ftm(LLFastTimer::FTM_SUN_SHADOW); + bindDeferredShader(gDeferredSunProgram, 0); + + glClearColor(1,1,1,1); + mDeferredLight[0].clear(GL_COLOR_BUFFER_BIT); + glClearColor(0,0,0,0); + + glh::matrix4f inv_trans = glh_get_current_modelview().inverse().transpose(); + + const U32 slice = 32; + F32 offset[slice*3]; + for (U32 i = 0; i < 4; i++) + { + for (U32 j = 0; j < 8; j++) + { + glh::vec3f v; + v.set_value(sinf(6.284f/8*j), cosf(6.284f/8*j), -(F32) i); + v.normalize(); + inv_trans.mult_matrix_vec(v); + v.normalize(); + offset[(i*8+j)*3+0] = v.v[0]; + offset[(i*8+j)*3+1] = v.v[2]; + offset[(i*8+j)*3+2] = v.v[1]; + } + } + + gDeferredSunProgram.uniform3fv("offset", slice, offset); + gDeferredSunProgram.uniform2f("screenRes", mDeferredLight[0].getWidth(), mDeferredLight[0].getHeight()); + + { + LLGLDisable blend(GL_BLEND); + LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_ALWAYS); + stop_glerror(); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 3); + stop_glerror(); + } + + unbindDeferredShader(gDeferredSunProgram); + } + mDeferredLight[0].flush(); + } + + static const LLCachedControl render_deferred_blur_light("RenderDeferredBlurLight",false); + static const LLCachedControl render_shadow_gi("RenderDeferredGI",false); + { //global illumination specific block (still experimental) + if (render_deferred_blur_light && + render_shadow_gi) { - glh::vec3f v; - v.set_value(sinf(6.284f/8*j), cosf(6.284f/8*j), -(F32) i); - v.normalize(); - inv_trans.mult_matrix_vec(v); - v.normalize(); - offset[(i*8+j)*3+0] = v.v[0]; - offset[(i*8+j)*3+1] = v.v[2]; - offset[(i*8+j)*3+2] = v.v[1]; + LLFastTimer ftm(LLFastTimer::FTM_EDGE_DETECTION); + //generate edge map + LLGLDisable blend(GL_BLEND); + LLGLDisable test(GL_ALPHA_TEST); + LLGLDepthTest depth(GL_FALSE); + LLGLDisable stencil(GL_STENCIL_TEST); + + { + gDeferredEdgeProgram.bind(); + mEdgeMap.bindTarget(); + bindDeferredShader(gDeferredEdgeProgram); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 3); + unbindDeferredShader(gDeferredEdgeProgram); + mEdgeMap.flush(); + } + } + + if (LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_DEFERRED) > 2) + { + { //get luminance map from previous frame's light map + LLGLEnable blend(GL_BLEND); + LLGLDisable test(GL_ALPHA_TEST); + LLGLDepthTest depth(GL_FALSE); + LLGLDisable stencil(GL_STENCIL_TEST); + + //static F32 fade = 1.f; + + { + gGL.setSceneBlendType(LLRender::BT_ALPHA); + gLuminanceGatherProgram.bind(); + gLuminanceGatherProgram.uniform2f("screen_res", mDeferredLight[0].getWidth(), mDeferredLight[0].getHeight()); + mLuminanceMap.bindTarget(); + bindDeferredShader(gLuminanceGatherProgram); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 3); + unbindDeferredShader(gLuminanceGatherProgram); + mLuminanceMap.flush(); + gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mLuminanceMap.getTexture(), true); + gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_TRILINEAR); + glGenerateMipmapEXT(GL_TEXTURE_2D); + } + } + + { //paint noisy GI map (bounce lighting lightmap) + LLFastTimer ftm(LLFastTimer::FTM_GI_TRACE); + LLGLDisable blend(GL_BLEND); + LLGLDepthTest depth(GL_FALSE); + LLGLDisable test(GL_ALPHA_TEST); + + mGIMapPost[0].bindTarget(); + + bindDeferredShader(gDeferredGIProgram, 0, &mGIMap, 0, mTrueNoiseMap); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 3); + unbindDeferredShader(gDeferredGIProgram); + mGIMapPost[0].flush(); + } + + U32 pass_count = 0; + if (render_deferred_blur_light) + { + static const LLCachedControl render_gui_blur_passes("RenderGIBlurPasses",(U32)1); + pass_count = llclamp(render_gui_blur_passes.get(), (U32) 1, (U32) 128); + } + + static const LLCachedControl render_gui_blur_size("RenderGIBlurSize",4.f); + static const LLCachedControl render_gui_blur_increment("RenderGIBlurIncrement",.8f); + static const LLCachedControl render_gui_blur_brightness("RenderGIBlurBrightness",1.025f); + for (U32 i = 0; i < pass_count; ++i) + { //gather/soften indirect lighting map + LLFastTimer ftm(LLFastTimer::FTM_GI_GATHER); + bindDeferredShader(gDeferredPostGIProgram, 0, &mGIMapPost[0], NULL, mTrueNoiseMap); + F32 blur_size = render_gui_blur_size/((F32) i * render_gui_blur_increment+1.f); + gDeferredPostGIProgram.uniform2f("delta", 1.f, 0.f); + gDeferredPostGIProgram.uniform1f("kern_scale", blur_size); + gDeferredPostGIProgram.uniform1f("gi_blur_brightness", render_gui_blur_brightness); + + mGIMapPost[1].bindTarget(); + { + LLGLDisable blend(GL_BLEND); + LLGLDepthTest depth(GL_FALSE); + stop_glerror(); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 3); + stop_glerror(); + } + + mGIMapPost[1].flush(); + unbindDeferredShader(gDeferredPostGIProgram); + bindDeferredShader(gDeferredPostGIProgram, 0, &mGIMapPost[1], NULL, mTrueNoiseMap); + mGIMapPost[0].bindTarget(); + + gDeferredPostGIProgram.uniform2f("delta", 0.f, 1.f); + + { + LLGLDisable blend(GL_BLEND); + LLGLDepthTest depth(GL_FALSE); + stop_glerror(); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + stop_glerror(); + } + mGIMapPost[0].flush(); + unbindDeferredShader(gDeferredPostGIProgram); + } } } - gDeferredSunProgram.uniform3fv("offset", slice, offset); - gDeferredSunProgram.uniform2f("screenRes", mDeferredLight[0].getWidth(), mDeferredLight[0].getHeight()); + //if (gSavedSettings.getBOOL("RenderDeferredSSAO")) + //Make sure to blur normal shadows, even if ssao isn't enabled... + if(mDeferredLight[0].getTexture(0)) + { + LLFastTimer ftm(LLFastTimer::FTM_SOFTEN_SHADOW); + //blur lightmap + if(mDeferredLight[1].getTexture(0)) + { + mDeferredLight[1].bindTarget(); - { - LLGLDisable blend(GL_BLEND); - //TO-DO: - //V2 changed to LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_ALWAYS); - //Do this when multisample z-buffer issues are figured out - //LLGLDepthTest depth(GL_FALSE); - LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_ALWAYS); - stop_glerror(); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 3); - stop_glerror(); - } - - unbindDeferredShader(gDeferredSunProgram); - } + glClearColor(1,1,1,1); + mDeferredLight[1].clear(GL_COLOR_BUFFER_BIT); + glClearColor(0,0,0,0); + } + else + mDeferredLight[0].bindTarget(); - mDeferredLight[0].flush(); + bindDeferredShader(gDeferredBlurLightProgram); - //SSAO - { - //blur lightmap - mDeferredLight[1].bindTarget(); + static const LLCachedControl go("RenderShadowGaussian",LLVector3(3.f,2.f,0.f)); + const U32 kern_length = 4; + static const LLCachedControl blur_size("RenderShadowBlurSize",1.4f); + static const LLCachedControl shadow_blur_dist_factor("RenderShadowBlurDistFactor",.1f); - //mDeferredLight[1].copyContents(mDeferredScreen, 0, 0, mDeferredScreen.getWidth(), mDeferredScreen.getHeight(), - // 0, 0, mDeferredLight[0].getWidth(), mDeferredLight[0].getHeight(), GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST); - glClearColor(1,1,1,1); - mDeferredLight[1].clear(GL_COLOR_BUFFER_BIT); - glClearColor(0,0,0,0); + // sample symmetrically with the middle sample falling exactly on 0.0 + F32 x = 0.f; - bindDeferredShader(gDeferredBlurLightProgram); + LLVector3 gauss[32]; // xweight, yweight, offset - static const LLCachedControl go("RenderShadowGaussian",LLVector3(2.f,2.f,0.f)); - static const LLCachedControl blur_size("RenderShadowBlurSize",.7f); - static const LLCachedControl blur_samples("RenderShadowBlurSamples",(U32)5); - U32 kern_length = llclamp(blur_samples.get(), (U32) 1, (U32) 16)*2 - 1; + for (U32 i = 0; i < kern_length; i++) + { + gauss[i].mV[0] = llgaussian(x, go.get().mV[0]); + gauss[i].mV[1] = llgaussian(x, go.get().mV[1]); + gauss[i].mV[2] = x; + x += 1.f; + } - // sample symmetrically with the middle sample falling exactly on 0.0 - F32 x = -(kern_length/2.0f) + 0.5f; + gDeferredBlurLightProgram.uniform2f("delta", 1.f, 0.f); + gDeferredBlurLightProgram.uniform1f("dist_factor", shadow_blur_dist_factor); + gDeferredBlurLightProgram.uniform3fv("kern", kern_length, gauss[0].mV); + gDeferredBlurLightProgram.uniform1f("kern_scale", blur_size * (kern_length/2.f - 0.5f)); + + { + LLGLDisable blend(GL_BLEND); + LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_ALWAYS); + stop_glerror(); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 3); + stop_glerror(); + } + + if(mDeferredLight[1].getTexture(0)) + { + mDeferredLight[1].flush(); + unbindDeferredShader(gDeferredBlurLightProgram); - LLVector3 gauss[32]; // xweight, yweight, offset + bindDeferredShader(gDeferredBlurLightProgram, 1); + } + else + { + mDeferredLight[0].flush(); + } + + mDeferredLight[0].bindTarget(); - for (U32 i = 0; i < kern_length; i++) - { - gauss[i].mV[0] = llgaussian(x, go.get().mV[0]); - gauss[i].mV[1] = llgaussian(x, go.get().mV[1]); - gauss[i].mV[2] = x; - x += 1.f; - } - /* swap the x=0 position to the start of gauss[] so we can - treat it specially as an optimization. */ - LLVector3 swap; - swap = gauss[kern_length/2]; - gauss[kern_length/2] = gauss[0]; - gauss[0] = swap; - llassert(gauss[0].mV[2] == 0.0f); + gDeferredBlurLightProgram.uniform2f("delta", 0.f, 1.f); - gDeferredBlurLightProgram.uniform2f("delta", 1.f, 0.f); - gDeferredBlurLightProgram.uniform3fv("kern[0]", kern_length, gauss[0].mV); - gDeferredBlurLightProgram.uniform3fv("kern", kern_length, gauss[0].mV); - gDeferredBlurLightProgram.uniform1i("kern_length", kern_length); - gDeferredBlurLightProgram.uniform1f("kern_scale", blur_size * (kern_length/2.f - 0.5f)); - - { - LLGLDisable blend(GL_BLEND); - //TO-DO: - //V2 changed to LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_ALWAYS); - //Do this when multisample z-buffer issues are figured out - //LLGLDepthTest depth(GL_FALSE); - LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_ALWAYS); - stop_glerror(); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 3); - stop_glerror(); - } - - mDeferredLight[1].flush(); - unbindDeferredShader(gDeferredBlurLightProgram); - - bindDeferredShader(gDeferredBlurLightProgram, 1); - mDeferredLight[0].bindTarget(); - - gDeferredBlurLightProgram.uniform2f("delta", 0.f, 1.f); - - { - LLGLDisable blend(GL_BLEND); - //TO-DO: - //V2 changed to LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_ALWAYS); - //Do this when multisample z-buffer issues are figured out - //LLGLDepthTest depth(GL_FALSE); - LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_ALWAYS); - stop_glerror(); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - stop_glerror(); - } - mDeferredLight[0].flush(); - unbindDeferredShader(gDeferredBlurLightProgram); + { + LLGLDisable blend(GL_BLEND); + LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_ALWAYS); + stop_glerror(); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 3); + stop_glerror(); + } + mDeferredLight[0].flush(); + unbindDeferredShader(gDeferredBlurLightProgram); } stop_glerror(); @@ -5973,35 +7083,49 @@ void LLPipeline::renderDeferredLighting() //mScreen.copyContents(mDeferredScreen, 0, 0, mDeferredScreen.getWidth(), mDeferredScreen.getHeight(), // 0, 0, mScreen.getWidth(), mScreen.getHeight(), GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST); - mScreen.bindTarget(); - // clear color buffer here - zeroing alpha (glow) is important or it will accumulate against sky - glClearColor(0,0,0,0); - mScreen.clear(GL_COLOR_BUFFER_BIT); - - bindDeferredShader(gDeferredSoftenProgram); + if (LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_DEFERRED) > 2) { - LLGLDepthTest depth(GL_FALSE); - LLGLDisable blend(GL_BLEND); - LLGLDisable test(GL_ALPHA_TEST); - - //full screen blit - glPushMatrix(); - glLoadIdentity(); - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glLoadIdentity(); - - glVertexPointer(2, GL_FLOAT, 0, vert); - - glDrawArrays(GL_TRIANGLE_STRIP, 0, 3); - - glPopMatrix(); - glMatrixMode(GL_MODELVIEW); - glPopMatrix(); + mDeferredLight[1].bindTarget(); + // clear color buffer here (GI) - zeroing alpha (glow) is important or it will accumulate against sky + glClearColor(0,0,0,0); + mScreen.clear(GL_COLOR_BUFFER_BIT); + } + else + { + mScreen.bindTarget(); + // clear color buffer here - zeroing alpha (glow) is important or it will accumulate against sky + glClearColor(0,0,0,0); + mScreen.clear(GL_COLOR_BUFFER_BIT); } - unbindDeferredShader(gDeferredSoftenProgram); + static const LLCachedControl render_deferred_atmospheric("RenderDeferredAtmospheric",false); + if (render_deferred_atmospheric) + { //apply sunlight contribution + LLFastTimer ftm(LLFastTimer::FTM_ATMOSPHERICS); + bindDeferredShader(gDeferredSoftenProgram, 0, &mGIMapPost[0]); + { + LLGLDepthTest depth(GL_FALSE); + LLGLDisable blend(GL_BLEND); + LLGLDisable test(GL_ALPHA_TEST); + //full screen blit + glPushMatrix(); + glLoadIdentity(); + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + + glVertexPointer(2, GL_FLOAT, 0, vert); + + glDrawArrays(GL_TRIANGLE_STRIP, 0, 3); + + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); + } + + unbindDeferredShader(gDeferredSoftenProgram); + } { //render sky LLGLDisable blend(GL_BLEND); @@ -6009,7 +7133,7 @@ void LLPipeline::renderDeferredLighting() gGL.setSceneBlendType(LLRender::BT_ALPHA); gPipeline.pushRenderTypeMask(); - + gPipeline.andRenderTypeMask(LLPipeline::RENDER_TYPE_SKY, LLPipeline::RENDER_TYPE_WL_CLOUDS, LLPipeline::RENDER_TYPE_WL_SKY, @@ -6020,17 +7144,39 @@ void LLPipeline::renderDeferredLighting() gPipeline.popRenderTypeMask(); } - gGL.setSceneBlendType(LLRender::BT_ADD); - std::list fullscreen_lights; - std::list light_colors; + static const LLCachedControl render_local("RenderLocalLights",false); - F32 v[24]; - glVertexPointer(3, GL_FLOAT, 0, v); + if (LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_DEFERRED) > 2) { - bindDeferredShader(gDeferredLightProgram); - LLGLDepthTest depth(GL_TRUE, GL_FALSE); - for (LLDrawable::drawable_set_t::iterator iter = mLights.begin(); iter != mLights.end(); ++iter) + mDeferredLight[1].flush(); + mDeferredLight[2].bindTarget(); + mDeferredLight[2].clear(GL_COLOR_BUFFER_BIT); + } + + if (render_local) + { + gGL.setSceneBlendType(LLRender::BT_ADD); + std::list fullscreen_lights; + LLDrawable::drawable_list_t spot_lights; + LLDrawable::drawable_list_t fullscreen_spot_lights; + + for (U32 i = 0; i < 2; i++) { + mTargetShadowSpotLight[i] = NULL; + } + + std::list light_colors; + + LLVertexBuffer::unbind(); + + F32 v[24]; + glVertexPointer(3, GL_FLOAT, 0, v); + + { + bindDeferredShader(gDeferredLightProgram); + LLGLDepthTest depth(GL_TRUE, GL_FALSE); + for (LLDrawable::drawable_set_t::iterator iter = mLights.begin(); iter != mLights.end(); ++iter) + { LLDrawable* drawablep = *iter; LLVOVolume* volume = drawablep->getVOVolume(); @@ -6074,7 +7220,7 @@ void LLPipeline::renderDeferredLighting() glh::vec3f tc(c); mat.mult_matrix_vec(tc); - + //vertex positions are encoded so the 3 bits of their vertex index //correspond to their axis facing, with bit position 3,2,1 matching //axis facing x,y,z, bit set meaning positive facing, bit clear @@ -6083,7 +7229,7 @@ void LLPipeline::renderDeferredLighting() v[3] = c[0]-s; v[4] = c[1]-s; v[5] = c[2]+s; // 1 - 0001 v[6] = c[0]-s; v[7] = c[1]+s; v[8] = c[2]-s; // 2 - 0010 v[9] = c[0]-s; v[10] = c[1]+s; v[11] = c[2]+s; // 3 - 0011 - + v[12] = c[0]+s; v[13] = c[1]-s; v[14] = c[2]-s; // 4 - 0100 v[15] = c[0]+s; v[16] = c[1]-s; v[17] = c[2]+s; // 5 - 0101 v[18] = c[0]+s; v[19] = c[1]+s; v[20] = c[2]-s; // 6 - 0110 @@ -6096,25 +7242,92 @@ void LLPipeline::renderDeferredLighting() camera->getOrigin().mV[2] > c[2] + s + 0.2f || camera->getOrigin().mV[2] < c[2] - s - 0.2f) { //draw box if camera is outside box - glTexCoord4f(tc.v[0], tc.v[1], tc.v[2], s*s); - glColor4f(col.mV[0], col.mV[1], col.mV[2], volume->getLightFalloff()*0.5f); - glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8, - GL_UNSIGNED_BYTE, get_box_fan_indices(camera, center)); + if (render_local) + { + if (volume->isLightSpotlight()) + { + drawablep->getVOVolume()->updateSpotLightPriority(); + spot_lights.push_back(drawablep); + continue; + } + + LLFastTimer ftm(LLFastTimer::FTM_LOCAL_LIGHTS); + glTexCoord4f(tc.v[0], tc.v[1], tc.v[2], s*s); + glColor4f(col.mV[0], col.mV[1], col.mV[2], volume->getLightFalloff()*0.5f); + glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8, + GL_UNSIGNED_BYTE, get_box_fan_indices(camera, center)); + } } else { + if (volume->isLightSpotlight()) + { + drawablep->getVOVolume()->updateSpotLightPriority(); + fullscreen_spot_lights.push_back(drawablep); + continue; + } + fullscreen_lights.push_back(LLVector4(tc.v[0], tc.v[1], tc.v[2], s*s)); light_colors.push_back(LLVector4(col.mV[0], col.mV[1], col.mV[2], volume->getLightFalloff()*0.5f)); } } unbindDeferredShader(gDeferredLightProgram); - } + } + if (!spot_lights.empty()) + { + LLGLDepthTest depth(GL_TRUE, GL_FALSE); + bindDeferredShader(gDeferredSpotLightProgram); + gDeferredSpotLightProgram.enableTexture(LLViewerShaderMgr::DEFERRED_PROJECTION); + + for (LLDrawable::drawable_list_t::iterator iter = spot_lights.begin(); iter != spot_lights.end(); ++iter) + { + LLFastTimer ftm(LLFastTimer::FTM_PROJECTORS); + LLDrawable* drawablep = *iter; + + LLVOVolume* volume = drawablep->getVOVolume(); + + LLVector3 center = drawablep->getPositionAgent(); + F32* c = center.mV; + F32 s = volume->getLightRadius()*1.5f; + + sVisibleLightCount++; + + glh::vec3f tc(c); + mat.mult_matrix_vec(tc); + + setupSpotLight(gDeferredSpotLightProgram, drawablep); + + LLColor3 col = volume->getLightColor(); + col *= volume->getLightIntensity(); + + //vertex positions are encoded so the 3 bits of their vertex index + //correspond to their axis facing, with bit position 3,2,1 matching + //axis facing x,y,z, bit set meaning positive facing, bit clear + //meaning negative facing + v[0] = c[0]-s; v[1] = c[1]-s; v[2] = c[2]-s; // 0 - 0000 + v[3] = c[0]-s; v[4] = c[1]-s; v[5] = c[2]+s; // 1 - 0001 + v[6] = c[0]-s; v[7] = c[1]+s; v[8] = c[2]-s; // 2 - 0010 + v[9] = c[0]-s; v[10] = c[1]+s; v[11] = c[2]+s; // 3 - 0011 + + v[12] = c[0]+s; v[13] = c[1]-s; v[14] = c[2]-s; // 4 - 0100 + v[15] = c[0]+s; v[16] = c[1]-s; v[17] = c[2]+s; // 5 - 0101 + v[18] = c[0]+s; v[19] = c[1]+s; v[20] = c[2]-s; // 6 - 0110 + v[21] = c[0]+s; v[22] = c[1]+s; v[23] = c[2]+s; // 7 - 0111 + + glTexCoord4f(tc.v[0], tc.v[1], tc.v[2], s*s); + glColor4f(col.mV[0], col.mV[1], col.mV[2], volume->getLightFalloff()*0.5f); + glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8, + GL_UNSIGNED_BYTE, get_box_fan_indices(camera, center)); + } + gDeferredSpotLightProgram.disableTexture(LLViewerShaderMgr::DEFERRED_PROJECTION); + unbindDeferredShader(gDeferredSpotLightProgram); + } + + { + bindDeferredShader(gDeferredMultiLightProgram); - if (!fullscreen_lights.empty()) - { - bindDeferredShader(gDeferredMultiLightProgram); LLGLDepthTest depth(GL_FALSE); //full screen blit @@ -6126,41 +7339,123 @@ void LLPipeline::renderDeferredLighting() U32 count = 0; - const U32 max_count = 16; - LLVector4 light[max_count]; - LLVector4 col[max_count]; + const U32 max_count = 8; + LLVector4 light[max_count]; + LLVector4 col[max_count]; glVertexPointer(2, GL_FLOAT, 0, vert); + F32 far_z = 0.f; + while (!fullscreen_lights.empty()) { + LLFastTimer ftm(LLFastTimer::FTM_FULLSCREEN_LIGHTS); light[count] = fullscreen_lights.front(); fullscreen_lights.pop_front(); col[count] = light_colors.front(); light_colors.pop_front(); - count++; + far_z = llmin(light[count].mV[2]-sqrtf(light[count].mV[3]), far_z); + + count++; if (count == max_count || fullscreen_lights.empty()) { gDeferredMultiLightProgram.uniform1i("light_count", count); - gDeferredMultiLightProgram.uniform4fv("light[0]", count, (GLfloat*) light); gDeferredMultiLightProgram.uniform4fv("light", count, (GLfloat*) light); - gDeferredMultiLightProgram.uniform4fv("light_col[0]", count, (GLfloat*) col); gDeferredMultiLightProgram.uniform4fv("light_col", count, (GLfloat*) col); + gDeferredMultiLightProgram.uniform1f("far_z", far_z); + far_z = 0.f; count = 0; - glDrawArrays(GL_TRIANGLE_STRIP, 0, 3); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 3); + } + } + + unbindDeferredShader(gDeferredMultiLightProgram); + + bindDeferredShader(gDeferredMultiSpotLightProgram); + + gDeferredMultiSpotLightProgram.enableTexture(LLViewerShaderMgr::DEFERRED_PROJECTION); + + for (LLDrawable::drawable_list_t::iterator iter = fullscreen_spot_lights.begin(); iter != fullscreen_spot_lights.end(); ++iter) + { + LLFastTimer ftm(LLFastTimer::FTM_PROJECTORS); + LLDrawable* drawablep = *iter; + + LLVOVolume* volume = drawablep->getVOVolume(); + + LLVector3 center = drawablep->getPositionAgent(); + F32* c = center.mV; + F32 s = volume->getLightRadius()*1.5f; + + sVisibleLightCount++; + + glh::vec3f tc(c); + mat.mult_matrix_vec(tc); + + setupSpotLight(gDeferredMultiSpotLightProgram, drawablep); + + LLColor3 col = volume->getLightColor(); + col *= volume->getLightIntensity(); + + glTexCoord4f(tc.v[0], tc.v[1], tc.v[2], s*s); + glColor4f(col.mV[0], col.mV[1], col.mV[2], volume->getLightFalloff()*0.5f); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 3); + } + + gDeferredMultiSpotLightProgram.disableTexture(LLViewerShaderMgr::DEFERRED_PROJECTION); + unbindDeferredShader(gDeferredMultiSpotLightProgram); + + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); } } + + gGL.setColorMask(true, true); + + if (LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_DEFERRED) > 2) + { + mDeferredLight[2].flush(); + + mScreen.bindTarget(); + mScreen.clear(GL_COLOR_BUFFER_BIT); - glPopMatrix(); - glMatrixMode(GL_MODELVIEW); - glPopMatrix(); + gGL.setSceneBlendType(LLRender::BT_ALPHA); - unbindDeferredShader(gDeferredMultiLightProgram); + { //mix various light maps (local, sun, gi) + LLFastTimer ftm(LLFastTimer::FTM_POST); + LLGLDisable blend(GL_BLEND); + LLGLDisable test(GL_ALPHA_TEST); + LLGLDepthTest depth(GL_FALSE); + LLGLDisable stencil(GL_STENCIL_TEST); + + bindDeferredShader(gDeferredPostProgram, 0, &mGIMapPost[0]); + + gDeferredPostProgram.bind(); + + LLVertexBuffer::unbind(); + + glVertexPointer(2, GL_FLOAT, 0, vert); + glColor3f(1,1,1); + + glPushMatrix(); + glLoadIdentity(); + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + + glDrawArrays(GL_TRIANGLES, 0, 3); + + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); + + unbindDeferredShader(gDeferredPostProgram); + } + } } - //glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - { //render non-deferred geometry + { //render non-deferred geometry (alpha, fullbright, glow) LLGLDisable blend(GL_BLEND); LLGLDisable stencil(GL_STENCIL_TEST); @@ -6190,9 +7485,6 @@ void LLPipeline::renderDeferredLighting() popRenderTypeMask(); } - //TO-DO: - //V2 moved block from LLPipeline::renderGeomPostDeferred - //Migrate once multisample z-buffer issues are figured out on ati cards. { //render highlights, etc. renderHighlights(); @@ -6214,6 +7506,136 @@ void LLPipeline::renderDeferredLighting() } +void LLPipeline::setupSpotLight(LLGLSLShader& shader, LLDrawable* drawablep) +{ + //construct frustum + LLVOVolume* volume = drawablep->getVOVolume(); + LLVector3 params = volume->getSpotLightParams(); + + F32 fov = params.mV[0]; + F32 focus = params.mV[1]; + + LLVector3 pos = drawablep->getPositionAgent(); + LLQuaternion quat = volume->getRenderRotation(); + LLVector3 scale = volume->getScale(); + + //get near clip plane + LLVector3 at_axis(0,0,-scale.mV[2]*0.5f); + at_axis *= quat; + + LLVector3 np = pos+at_axis; + at_axis.normVec(); + + //get origin that has given fov for plane np, at_axis, and given scale + F32 dist = (scale.mV[1]*0.5f)/tanf(fov*0.5f); + + LLVector3 origin = np - at_axis*dist; + + //matrix from volume space to agent space + LLMatrix4 light_mat(quat, LLVector4(origin,1.f)); + + glh::matrix4f light_to_agent((F32*) light_mat.mMatrix); + glh::matrix4f light_to_screen = glh_get_current_modelview() * light_to_agent; + + glh::matrix4f screen_to_light = light_to_screen.inverse(); + + F32 s = volume->getLightRadius()*1.5f; + F32 near_clip = dist; + F32 width = scale.mV[VX]; + F32 height = scale.mV[VY]; + F32 far_clip = s+dist-scale.mV[VZ]; + + F32 fovy = fov * RAD_TO_DEG; + F32 aspect = width/height; + + glh::matrix4f trans(0.5f, 0.f, 0.f, 0.5f, + 0.f, 0.5f, 0.f, 0.5f, + 0.f, 0.f, 0.5f, 0.5f, + 0.f, 0.f, 0.f, 1.f); + + glh::vec3f p1(0, 0, -(near_clip+0.01f)); + glh::vec3f p2(0, 0, -(near_clip+1.f)); + + glh::vec3f screen_origin(0, 0, 0); + + light_to_screen.mult_matrix_vec(p1); + light_to_screen.mult_matrix_vec(p2); + light_to_screen.mult_matrix_vec(screen_origin); + + glh::vec3f n = p2-p1; + n.normalize(); + + F32 proj_range = far_clip - near_clip; + glh::matrix4f light_proj = gl_perspective(fovy, aspect, near_clip, far_clip); + screen_to_light = trans * light_proj * screen_to_light; + shader.uniformMatrix4fv("proj_mat", 1, FALSE, screen_to_light.m); + shader.uniform1f("proj_near", near_clip); + shader.uniform3fv("proj_p", 1, p1.v); + shader.uniform3fv("proj_n", 1, n.v); + shader.uniform3fv("proj_origin", 1, screen_origin.v); + shader.uniform1f("proj_range", proj_range); + shader.uniform1f("proj_ambiance", params.mV[2]); + S32 s_idx = -1; + + for (U32 i = 0; i < 2; i++) + { + if (mShadowSpotLight[i] == drawablep) + { + s_idx = i; + } + } + + shader.uniform1i("proj_shadow_idx", s_idx); + + if (s_idx >= 0) + { + shader.uniform1f("shadow_fade", 1.f-mSpotLightFade[s_idx]); + } + else + { + shader.uniform1f("shadow_fade", 1.f); + } + + { + LLDrawable* potential = drawablep; + //determine if this is a good light for casting shadows + F32 m_pri = volume->getSpotLightPriority(); + + for (U32 i = 0; i < 2; i++) + { + F32 pri = 0.f; + + if (mTargetShadowSpotLight[i].notNull()) + { + pri = mTargetShadowSpotLight[i]->getVOVolume()->getSpotLightPriority(); + } + + if (m_pri > pri) + { + LLDrawable* temp = mTargetShadowSpotLight[i]; + mTargetShadowSpotLight[i] = potential; + potential = temp; + m_pri = pri; + } + } + } + + LLViewerTexture* img = volume->getLightTexture(); + + S32 channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_PROJECTION); + + if (channel > -1 && img) + { + gGL.getTexUnit(channel)->bind(img); + + F32 lod_range = logf(img->getWidth())/logf(2.f); + + shader.uniform1f("proj_focus", focus); + shader.uniform1f("proj_lod", lod_range); + shader.uniform1f("proj_ambient_lod", llclamp((proj_range-focus)/proj_range*lod_range, 0.f, 1.f)); + } +} + void LLPipeline::unbindDeferredShader(LLGLSLShader &shader) { stop_glerror(); @@ -6223,14 +7645,43 @@ void LLPipeline::unbindDeferredShader(LLGLSLShader &shader) shader.disableTexture(LLViewerShaderMgr::DEFERRED_SPECULAR, LLTexUnit::TT_RECT_TEXTURE); shader.disableTexture(LLViewerShaderMgr::DEFERRED_DEPTH, LLTexUnit::TT_RECT_TEXTURE); shader.disableTexture(LLViewerShaderMgr::DEFERRED_LIGHT, LLTexUnit::TT_RECT_TEXTURE); + shader.disableTexture(LLViewerShaderMgr::DEFERRED_GI_LIGHT, LLTexUnit::TT_RECT_TEXTURE); + shader.disableTexture(LLViewerShaderMgr::DEFERRED_EDGE, LLTexUnit::TT_RECT_TEXTURE); + shader.disableTexture(LLViewerShaderMgr::DEFERRED_SUN_LIGHT, LLTexUnit::TT_RECT_TEXTURE); + shader.disableTexture(LLViewerShaderMgr::DEFERRED_LOCAL_LIGHT, LLTexUnit::TT_RECT_TEXTURE); + shader.disableTexture(LLViewerShaderMgr::DEFERRED_LUMINANCE); + shader.disableTexture(LLViewerShaderMgr::DIFFUSE_MAP); + shader.disableTexture(LLViewerShaderMgr::DEFERRED_GI_MIP); + shader.disableTexture(LLViewerShaderMgr::DEFERRED_BLOOM); + shader.disableTexture(LLViewerShaderMgr::DEFERRED_GI_NORMAL); + shader.disableTexture(LLViewerShaderMgr::DEFERRED_GI_DIFFUSE); + shader.disableTexture(LLViewerShaderMgr::DEFERRED_GI_SPECULAR); + shader.disableTexture(LLViewerShaderMgr::DEFERRED_GI_DEPTH); + shader.disableTexture(LLViewerShaderMgr::DEFERRED_GI_MIN_POS); + shader.disableTexture(LLViewerShaderMgr::DEFERRED_GI_MAX_POS); + shader.disableTexture(LLViewerShaderMgr::DEFERRED_GI_LAST_NORMAL); + shader.disableTexture(LLViewerShaderMgr::DEFERRED_GI_LAST_DIFFUSE); + shader.disableTexture(LLViewerShaderMgr::DEFERRED_GI_LAST_MIN_POS); + shader.disableTexture(LLViewerShaderMgr::DEFERRED_GI_LAST_MAX_POS); + for (U32 i = 0; i < 4; i++) + { + if (shader.disableTexture(LLViewerShaderMgr::DEFERRED_SHADOW0+i, LLTexUnit::TT_RECT_TEXTURE) > -1) + { + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE); + } + } + + for (U32 i = 4; i < 6; i++) { if (shader.disableTexture(LLViewerShaderMgr::DEFERRED_SHADOW0+i) > -1) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE); } } + shader.disableTexture(LLViewerShaderMgr::DEFERRED_NOISE); + shader.disableTexture(LLViewerShaderMgr::DEFERRED_LIGHTFUNC); S32 channel = shader.disableTexture(LLViewerShaderMgr::ENVIRONMENT_MAP, LLTexUnit::TT_CUBE_MAP); if (channel > -1) @@ -6244,6 +7695,8 @@ void LLPipeline::unbindDeferredShader(LLGLSLShader &shader) gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); gGL.getTexUnit(0)->activate(); shader.unbind(); + + LLGLState::checkTextureChannels(); } inline float sgn(float a) @@ -6258,7 +7711,7 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in) if (LLPipeline::sWaterReflections && assertInitialized() && LLDrawPoolWater::sNeedsReflectionUpdate) { LLVOAvatar* agent = gAgent.getAvatarObject(); - if (gAgent.getCameraAnimating() || gAgent.getCameraMode() != CAMERA_MODE_MOUSELOOK) + if (!isAgentAvatarValid() || gAgent.getCameraAnimating() || gAgent.getCameraMode() != CAMERA_MODE_MOUSELOOK) { agent = NULL; } @@ -6276,11 +7729,6 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in) LLCamera camera = camera_in; camera.setFar(camera.getFar()*0.87654321f); LLPipeline::sReflectionRender = TRUE; - S32 occlusion = LLPipeline::sUseOcclusion; - - LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD; - - LLPipeline::sUseOcclusion = llmin(occlusion, 1); gPipeline.pushRenderTypeMask(); @@ -6316,9 +7764,14 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in) if (!LLViewerCamera::getInstance()->cameraUnderWater()) { //generate planar reflection map + + //disable occlusion culling for reflection map for now + S32 occlusion = LLPipeline::sUseOcclusion; + LLPipeline::sUseOcclusion = 0; gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); glClearColor(0,0,0,0); mWaterRef.bindTarget(); + LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WATER0; gGL.setColorMask(true, true); mWaterRef.clear(); gGL.setColorMask(true, false); @@ -6373,54 +7826,47 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in) gPipeline.popRenderTypeMask(); } - - static const LLCachedControl water_reflections("RenderWaterReflections",false); - if (water_reflections) + static const LLCachedControl detail("RenderReflectionDetail",0); + if (detail > 0) { //mask out selected geometry based on reflection detail - static const LLCachedControl detail("RenderReflectionDetail",0); - //if (detail > 0) - { //mask out selected geometry based on reflection detail + gPipeline.pushRenderTypeMask(); + if (detail < 4) + { + clearRenderTypeMask(LLPipeline::RENDER_TYPE_PARTICLES, END_RENDER_TYPES); + if (detail < 3) { - gPipeline.pushRenderTypeMask(); - if (detail < 3) + clearRenderTypeMask(LLPipeline::RENDER_TYPE_AVATAR, END_RENDER_TYPES); + if (detail < 2) { - clearRenderTypeMask(LLPipeline::RENDER_TYPE_PARTICLES, END_RENDER_TYPES); - if (detail < 2) - { - clearRenderTypeMask(LLPipeline::RENDER_TYPE_AVATAR, END_RENDER_TYPES); - if (detail < 1) - { - clearRenderTypeMask(LLPipeline::RENDER_TYPE_VOLUME, END_RENDER_TYPES); - } - } + clearRenderTypeMask(LLPipeline::RENDER_TYPE_VOLUME, END_RENDER_TYPES); } - - clearRenderTypeMask(LLPipeline::RENDER_TYPE_WATER, - LLPipeline::RENDER_TYPE_VOIDWATER, - LLPipeline::RENDER_TYPE_GROUND, - LLPipeline::RENDER_TYPE_SKY, - LLPipeline::RENDER_TYPE_CLASSIC_CLOUDS, - LLPipeline::RENDER_TYPE_WL_CLOUDS, - LLPipeline::END_RENDER_TYPES); - static const LLCachedControl skip_distortion_updates("SkipReflectOcclusionUpdates",false); - LLPipeline::sSkipUpdate = skip_distortion_updates; - LLGLUserClipPlane clip_plane(plane, mat, projection); - LLGLDisable cull(GL_CULL_FACE); - updateCull(camera, ref_result, 1); - stateSort(camera, ref_result); - gPipeline.grabReferences(ref_result); - renderGeom(camera); - LLPipeline::sSkipUpdate = FALSE; - gPipeline.popRenderTypeMask(); } - } + } + + clearRenderTypeMask(LLPipeline::RENDER_TYPE_WATER, + LLPipeline::RENDER_TYPE_VOIDWATER, + LLPipeline::RENDER_TYPE_GROUND, + LLPipeline::RENDER_TYPE_SKY, + LLPipeline::RENDER_TYPE_CLASSIC_CLOUDS, + LLPipeline::RENDER_TYPE_WL_CLOUDS, + LLPipeline::END_RENDER_TYPES); + static const LLCachedControl skip_distortion_updates("SkipReflectOcclusionUpdates",false); + LLPipeline::sSkipUpdate = skip_distortion_updates; + LLGLUserClipPlane clip_plane(plane, mat, projection); + LLGLDisable cull(GL_CULL_FACE); + updateCull(camera, ref_result, -water_clip, &plane); + stateSort(camera, ref_result); + gPipeline.grabReferences(ref_result); + renderGeom(camera); + LLPipeline::sSkipUpdate = FALSE; + gPipeline.popRenderTypeMask(); } - } + } glCullFace(GL_BACK); glPopMatrix(); mWaterRef.flush(); - glh_set_current_modelview(current); + LLPipeline::sUseOcclusion = occlusion; } camera.setOrigin(camera_in.getOrigin()); @@ -6452,15 +7898,18 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in) LLColor4& col = LLDrawPoolWater::sWaterFogColor; glClearColor(col.mV[0], col.mV[1], col.mV[2], 0.f); mWaterDis.bindTarget(); + LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WATER1; mWaterDis.getViewport(gGLViewport); if (!LLPipeline::sUnderWaterRender || LLDrawPoolWater::sNeedsReflectionUpdate) { //clip out geometry on the same side of water as the camera mat = glh_get_current_modelview(); - LLGLUserClipPlane clip_plane(LLPlane(-pnorm, -(pd+pad)), mat, projection); + LLPlane plane(-pnorm, -(pd+pad)); + + LLGLUserClipPlane clip_plane(plane, mat, projection); static LLCullResult result; - updateCull(camera, result, water_clip); + updateCull(camera, result, water_clip, &plane); stateSort(camera, result); gGL.setColorMask(true, true); @@ -6490,7 +7939,6 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in) LLDrawPoolWater::sNeedsReflectionUpdate = FALSE; LLDrawPoolWater::sNeedsDistortionUpdate = FALSE; LLViewerCamera::getInstance()->setUserClipPlane(LLPlane(-pnorm, -pd)); - LLPipeline::sUseOcclusion = occlusion; LLGLState::checkStates(); LLGLState::checkTextureChannels(); @@ -6500,6 +7948,8 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in) { agent->updateAttachmentVisibility(gAgent.getCameraMode()); } + + LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD; } } @@ -6570,31 +8020,480 @@ glh::matrix4f scale_translate_to_fit(const LLVector3 min, const LLVector3 max) return ret; } -void LLPipeline::generateSunShadow(LLCamera& camera) +void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera& shadow_cam, LLCullResult &result, BOOL use_shader, BOOL use_occlusion) { - if (!sRenderDeferred) + LLFastTimer t(LLFastTimer::FTM_SHADOW_RENDER); + + //clip out geometry on the same side of water as the camera + S32 occlude = LLPipeline::sUseOcclusion; + if (!use_occlusion) + { + LLPipeline::sUseOcclusion = 0; + } + LLPipeline::sShadowRender = TRUE; + + U32 types[] = { LLRenderPass::PASS_SIMPLE, LLRenderPass::PASS_FULLBRIGHT, LLRenderPass::PASS_SHINY, LLRenderPass::PASS_BUMP, LLRenderPass::PASS_FULLBRIGHT_SHINY }; + LLGLEnable cull(GL_CULL_FACE); + + if (use_shader) + { + gDeferredShadowProgram.bind(); + } + + updateCull(shadow_cam, result); + stateSort(shadow_cam, result); + + //generate shadow map + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadMatrixf(proj.m); + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadMatrixd(gGLModelView); + + stop_glerror(); + gGLLastMatrix = NULL; + + { + //LLGLDepthTest depth(GL_TRUE); + //glClear(GL_DEPTH_BUFFER_BIT); + } + + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + + glColor4f(1,1,1,1); + + stop_glerror(); + + gGL.setColorMask(false, false); + + //glCullFace(GL_FRONT); + + LLVertexBuffer::unbind(); + + { + LLFastTimer ftm(LLFastTimer::FTM_SHADOW_SIMPLE); + LLGLDisable test(GL_ALPHA_TEST); + gGL.getTexUnit(0)->disable(); + for (U32 i = 0; i < sizeof(types)/sizeof(U32); ++i) + { + renderObjects(types[i], LLVertexBuffer::MAP_VERTEX, FALSE); + } + gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE); + } + + if (use_shader) + { + gDeferredShadowProgram.unbind(); + renderGeomShadow(shadow_cam); + gDeferredShadowProgram.bind(); + } + else + { + renderGeomShadow(shadow_cam); + } + + { + LLFastTimer ftm(LLFastTimer::FTM_SHADOW_ALPHA); + LLGLEnable test(GL_ALPHA_TEST); + gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.6f); + renderObjects(LLRenderPass::PASS_ALPHA_SHADOW, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_COLOR, TRUE); + glColor4f(1,1,1,1); + renderObjects(LLRenderPass::PASS_GRASS, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, TRUE); + gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); + } + + //glCullFace(GL_BACK); + + gGLLastMatrix = NULL; + glLoadMatrixd(gGLModelView); + doOcclusion(shadow_cam); + + if (use_shader) + { + gDeferredShadowProgram.unbind(); + } + + gGL.setColorMask(true, true); + + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); + gGLLastMatrix = NULL; + + LLPipeline::sUseOcclusion = occlude; + LLPipeline::sShadowRender = FALSE; +} + +BOOL LLPipeline::getVisiblePointCloud(LLCamera& camera, LLVector3& min, LLVector3& max, std::vector& fp, LLVector3 light_dir) +{ + LLFastTimer t(LLFastTimer::FTM_VISIBLE_CLOUD); + //get point cloud of intersection of frust and min, max + + if (getVisibleExtents(camera, min, max)) + { + return FALSE; + } + + //get set of planes on bounding box + LLPlane bp[] = { + LLPlane(min, LLVector3(-1,0,0)), + LLPlane(min, LLVector3(0,-1,0)), + LLPlane(min, LLVector3(0,0,-1)), + LLPlane(max, LLVector3(1,0,0)), + LLPlane(max, LLVector3(0,1,0)), + LLPlane(max, LLVector3(0,0,1))}; + + //potential points + std::vector pp; + + //add corners of AABB + pp.push_back(LLVector3(min.mV[0], min.mV[1], min.mV[2])); + pp.push_back(LLVector3(max.mV[0], min.mV[1], min.mV[2])); + pp.push_back(LLVector3(min.mV[0], max.mV[1], min.mV[2])); + pp.push_back(LLVector3(max.mV[0], max.mV[1], min.mV[2])); + pp.push_back(LLVector3(min.mV[0], min.mV[1], max.mV[2])); + pp.push_back(LLVector3(max.mV[0], min.mV[1], max.mV[2])); + pp.push_back(LLVector3(min.mV[0], max.mV[1], max.mV[2])); + pp.push_back(LLVector3(max.mV[0], max.mV[1], max.mV[2])); + + //add corners of camera frustum + for (U32 i = 0; i < 8; i++) + { + pp.push_back(camera.mAgentFrustum[i]); + } + + + //bounding box line segments + U32 bs[] = + { + 0,1, + 1,3, + 3,2, + 2,0, + + 4,5, + 5,7, + 7,6, + 6,4, + + 0,4, + 1,5, + 3,7, + 2,6 + }; + + for (U32 i = 0; i < 12; i++) + { //for each line segment in bounding box + for (U32 j = 0; j < 6; j++) + { //for each plane in camera frustum + const LLPlane& cp = camera.getAgentPlane(j); + const LLVector3& v1 = pp[bs[i*2+0]]; + const LLVector3& v2 = pp[bs[i*2+1]]; + const LLVector3 n(cp.mV); + + LLVector3 line = v1-v2; + + F32 d1 = line*n; + F32 d2 = -cp.dist(v2); + + F32 t = d2/d1; + + if (t > 0.f && t < 1.f) + { + LLVector3 intersect = v2+line*t; + pp.push_back(intersect); + } + } + } + + //camera frustum line segments + const U32 fs[] = + { + 0,1, + 1,2, + 2,3, + 3,0, + + 4,5, + 5,6, + 6,7, + 7,4, + + 0,4, + 1,5, + 2,6, + 3,7 + }; + + LLVector3 center = (max+min)*0.5f; + LLVector3 size = (max-min)*0.5f; + + for (U32 i = 0; i < 12; i++) + { + for (U32 j = 0; j < 6; ++j) + { + const LLVector3& v1 = pp[fs[i*2+0]+8]; + const LLVector3& v2 = pp[fs[i*2+1]+8]; + const LLPlane& cp = bp[j]; + const LLVector3 n(cp.mV); + + LLVector3 line = v1-v2; + + F32 d1 = line*n; + F32 d2 = -cp.dist(v2); + + F32 t = d2/d1; + + if (t > 0.f && t < 1.f) + { + LLVector3 intersect = v2+line*t; + pp.push_back(intersect); + } + } + } + + LLVector3 ext[] = { min-LLVector3(0.05f,0.05f,0.05f), + max+LLVector3(0.05f,0.05f,0.05f) }; + + for (U32 i = 0; i < pp.size(); ++i) + { + bool found = true; + + const F32* p = pp[i].mV; + + for (U32 j = 0; j < 3; ++j) + { + if (p[j] < ext[0].mV[j] || + p[j] > ext[1].mV[j]) + { + found = false; + break; + } + } + + for (U32 j = 0; j < 6; ++j) + { + const LLPlane& cp = camera.getAgentPlane(j); + F32 dist = cp.dist(pp[i]); + if (dist > 0.05f) //point is above some plane, not contained + { + found = false; + break; + } + } + + if (found) + { + fp.push_back(pp[i]); + } + } + + if (fp.empty()) + { + return FALSE; + } + + return TRUE; +} + +void LLPipeline::generateGI(LLCamera& camera, LLVector3& lightDir, std::vector& vpc) +{ + if (LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_DEFERRED) < 3) { return; } - //temporary hack to disable shadows but keep local lights - static BOOL clear = TRUE; - static const LLCachedControl gen_shadow("RenderDeferredSunShadow",false); - if (!gen_shadow) + LLVector3 up; + + //LLGLEnable depth_clamp(GL_DEPTH_CLAMP_NV); + + if (lightDir.mV[2] > 0.5f) + { + up = LLVector3(1,0,0); + } + else + { + up = LLVector3(0, 0, 1); + } + + + static const LLCachedControl gi_range("RenderGIRange",96.f); + + U32 res = mGIMap.getWidth(); + + static const LLCachedControl render_gi_attenuation("RenderGIAttenuation",.1f); + F32 atten = llmax(render_gi_attenuation.get(), 0.001f); + + //set radius to range at which distance attenuation of incoming photons is near 0 + + F32 lrad = sqrtf(1.f/(atten*0.01f)); + + F32 lrange = lrad+gi_range*0.5f; + + LLVector3 pad(lrange,lrange,lrange); + + glh::matrix4f view = look(LLVector3(128.f,128.f,128.f), lightDir, up); + + LLVector3 cp = camera.getOrigin()+camera.getAtAxis()*(gi_range*0.5f); + + glh::vec3f scp(cp.mV); + view.mult_matrix_vec(scp); + cp.setVec(scp.v); + + F32 pix_width = lrange/(res*0.5f); + + //move cp to the nearest pix_width + for (U32 i = 0; i < 3; i++) + { + cp.mV[i] = llround(cp.mV[i], pix_width); + } + + LLVector3 min = cp-pad; + LLVector3 max = cp+pad; + + //set mGIRange to range in tc space[0,1] that covers texture block of intersecting lights around a point + mGIRange.mV[0] = (max.mV[0]-min.mV[0])/res; + mGIRange.mV[1] = (max.mV[1]-min.mV[1])/res; + mGILightRadius = lrad/lrange*0.5f; + + glh::matrix4f proj = gl_ortho(min.mV[0], max.mV[0], + min.mV[1], max.mV[1], + -max.mV[2], -min.mV[2]); + + LLCamera sun_cam = camera; + + glh::matrix4f eye_view = glh_get_current_modelview(); + + //get eye space to camera space matrix + mGIMatrix = view*eye_view.inverse(); + mGINormalMatrix = mGIMatrix.inverse().transpose(); + mGIInvProj = proj.inverse(); + mGIMatrixProj = proj*mGIMatrix; + + //translate and scale to [0,1] + glh::matrix4f trans(.5f, 0.f, 0.f, .5f, + 0.f, 0.5f, 0.f, 0.5f, + 0.f, 0.f, 0.5f, 0.5f, + 0.f, 0.f, 0.f, 1.f); + + mGIMatrixProj = trans*mGIMatrixProj; + + glh_set_current_modelview(view); + glh_set_current_projection(proj); + + LLViewerCamera::updateFrustumPlanes(sun_cam, TRUE, FALSE, TRUE); + + sun_cam.ignoreAgentFrustumPlane(LLCamera::AGENT_PLANE_NEAR); + static LLCullResult result; + + pushRenderTypeMask(); + + andRenderTypeMask(LLPipeline::RENDER_TYPE_SIMPLE, + LLPipeline::RENDER_TYPE_FULLBRIGHT, + LLPipeline::RENDER_TYPE_BUMP, + LLPipeline::RENDER_TYPE_VOLUME, + LLPipeline::RENDER_TYPE_TREE, + LLPipeline::RENDER_TYPE_TERRAIN, + LLPipeline::RENDER_TYPE_WATER, + LLPipeline::RENDER_TYPE_VOIDWATER, + LLPipeline::RENDER_TYPE_PASS_ALPHA_SHADOW, + LLPipeline::RENDER_TYPE_AVATAR, + LLPipeline::RENDER_TYPE_PASS_SIMPLE, + LLPipeline::RENDER_TYPE_PASS_BUMP, + LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT, + LLPipeline::RENDER_TYPE_PASS_SHINY, + END_RENDER_TYPES); + + + + S32 occlude = LLPipeline::sUseOcclusion; + //LLPipeline::sUseOcclusion = 0; + LLPipeline::sShadowRender = TRUE; + + //only render large objects into GI map + static const LLCachedControl render_gi_min_render_size("RenderGIMinRenderSize",.5f); + sMinRenderSize = render_gi_min_render_size; + + LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_GI_SOURCE; + mGIMap.bindTarget(); + + F64 last_modelview[16]; + F64 last_projection[16]; + for (U32 i = 0; i < 16; i++) + { + last_modelview[i] = gGLLastModelView[i]; + last_projection[i] = gGLLastProjection[i]; + gGLLastModelView[i] = mGIModelview.m[i]; + gGLLastProjection[i] = mGIProjection.m[i]; + } + + sun_cam.setOrigin(0.f, 0.f, 0.f); + updateCull(sun_cam, result); + stateSort(sun_cam, result); + + for (U32 i = 0; i < 16; i++) + { + gGLLastModelView[i] = last_modelview[i]; + gGLLastProjection[i] = last_projection[i]; + } + + mGIProjection = proj; + mGIModelview = view; + + LLGLEnable cull(GL_CULL_FACE); + + //generate GI map + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadMatrixf(proj.m); + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadMatrixf(view.m); + + stop_glerror(); + gGLLastMatrix = NULL; + + mGIMap.clear(); + + { + //LLGLEnable enable(GL_DEPTH_CLAMP_NV); + renderGeomDeferred(camera); + } + + mGIMap.flush(); + + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); + gGLLastMatrix = NULL; + + LLPipeline::sUseOcclusion = occlude; + LLPipeline::sShadowRender = FALSE; + sMinRenderSize = 0.f; + + popRenderTypeMask(); + +} + +void LLPipeline::generateSunShadow(LLCamera& camera) +{ + static const LLCachedControl shadow_detial("RenderShadowDetail",0); + if (!sRenderDeferred || shadow_detial <= 0) { - if (clear) - { - clear = FALSE; - for (U32 i = 0; i < 4; i++) - { - mSunShadow[i].bindTarget(); - mSunShadow[i].clear(); - mSunShadow[i].flush(); - } - } return; } - clear = TRUE; + + F64 last_modelview[16]; + F64 last_projection[16]; + for (U32 i = 0; i < 16; i++) + { //store last_modelview of world camera + last_modelview[i] = gGLLastModelView[i]; + last_projection[i] = gGLLastProjection[i]; + } + pushRenderTypeMask(); andRenderTypeMask(LLPipeline::RENDER_TYPE_SIMPLE, LLPipeline::RENDER_TYPE_ALPHA, @@ -6619,40 +8518,145 @@ void LLPipeline::generateSunShadow(LLCamera& camera) //get sun view matrix - F32 range = 128.f; - //store current projection/modelview matrix glh::matrix4f saved_proj = glh_get_current_projection(); glh::matrix4f saved_view = glh_get_current_modelview(); glh::matrix4f inv_view = saved_view.inverse(); - glh::matrix4f view[4]; - glh::matrix4f proj[4]; - LLVector3 up; - + glh::matrix4f view[6]; + glh::matrix4f proj[6]; + //clip contains parallel split distances for 3 splits - static const LLCachedControl clip("RenderShadowClipPlanes",LLVector3(4.f,8.f,24.f)); - - //far clip on last split is minimum of camera view distance and 128 - mSunClipPlanes = LLVector4(clip, clip.get().mV[2] * clip.get().mV[2]/clip.get().mV[1]); - - const LLPickInfo& pick_info = gViewerWindow->getLastPick(); - - if (!pick_info.mPosGlobal.isExactlyZero()) - { //squish nearest frustum based on alt-zoom (tighten up nearest frustum when focusing on tiny object - F32 focus_dist = (F32) (pick_info.mPosGlobal + LLVector3d(pick_info.mObjectOffset) - gAgent.getPosGlobalFromAgent(LLViewerCamera::getInstance()->getOrigin())).magVec(); - mSunClipPlanes.mV[0] = llclamp(focus_dist*focus_dist, 2.f, mSunClipPlanes.mV[0]); - } + static const LLCachedControl normal_clip_planes("RenderShadowClipPlanes",LLVector3(1.f,12.f,32.f)); + static const LLCachedControl ortho_clip_planes("RenderShadowOrthoClipPlanes",LLVector3(4.f,8.f,24.f)); + const LLVector3 &sun_clip = normal_clip_planes.get(); + const LLVector3 &ortho_clip = ortho_clip_planes.get(); - // convenience array of 4 near clip plane distances - F32 dist[] = { 0.1f, mSunClipPlanes.mV[0], mSunClipPlanes.mV[1], mSunClipPlanes.mV[2], mSunClipPlanes.mV[3] }; + //far clip on last split is minimum of camera view distance and 128 + mSunClipPlanes = LLVector4(sun_clip, sun_clip.mV[2] * sun_clip.mV[2]/sun_clip.mV[1]); + + mSunOrthoClipPlanes = LLVector4(ortho_clip, ortho_clip.mV[2]*ortho_clip.mV[2]/ortho_clip.mV[1]); //currently used for amount to extrude frusta corners for constructing shadow frusta - static const LLCachedControl n("RenderShadowNearDist",LLVector3(256,256,256)); - F32 nearDist[] = { n.get().mV[0], n.get().mV[1], n.get().mV[2], n.get().mV[2] }; + //staic const LLCachedControl shadow_near_dist("RenderShadowNearDist"); + //LLVector3 &n = shadow_near_dist.get(); + //F32 nearDist[] = { n.mV[0], n.mV[1], n.mV[2], n.mV[2] }; + + //put together a universal "near clip" plane for shadow frusta + /*LLPlane shadow_near_clip; + { + LLVector3 p = gAgent.getCameraPositionAgent();//gAgent.getPositionAgent(); + p += mSunDir * gSavedSettings.getF32("RenderFarClip")*2.f; + shadow_near_clip.setVec(p, mSunDir); + }*/ + + LLVector3 lightDir = -mSunDir; + lightDir.normVec(); + + glh::vec3f light_dir(lightDir.mV); + + //create light space camera matrix + + LLVector3 at = lightDir; + + LLVector3 up = camera.getAtAxis(); + + if (fabsf(up*lightDir) > 0.75f) + { + up = camera.getUpAxis(); + } + + /*LLVector3 left = up%at; + up = at%left;*/ + + up.normVec(); + at.normVec(); + + + LLCamera main_camera = camera; + + F32 near_clip = 0.f; + { + //get visible point cloud + std::vector fp; + + main_camera.calcAgentFrustumPlanes(main_camera.mAgentFrustum); + + LLVector3 min,max; + getVisiblePointCloud(main_camera,min,max,fp); + + if (fp.empty()) + { + if (!hasRenderDebugMask(RENDER_DEBUG_SHADOW_FRUSTA)) + { + mShadowCamera[0] = main_camera; + mShadowExtents[0][0] = min; + mShadowExtents[0][1] = max; + + mShadowFrustPoints[0].clear(); + mShadowFrustPoints[1].clear(); + mShadowFrustPoints[2].clear(); + mShadowFrustPoints[3].clear(); + } + popRenderTypeMask(); + return; + } + + generateGI(camera, lightDir, fp); + + //get good split distances for frustum + for (U32 i = 0; i < fp.size(); ++i) + { + glh::vec3f v(fp[i].mV); + saved_view.mult_matrix_vec(v); + fp[i].setVec(v.v); + } + + min = fp[0]; + max = fp[0]; + + //get camera space bounding box + for (U32 i = 1; i < fp.size(); ++i) + { + update_min_max(min, max, fp[i]); + } + + near_clip = -max.mV[2]; + F32 far_clip = -min.mV[2]*2.f; + + far_clip = llmin(far_clip, 128.f); + far_clip = llmin(far_clip, camera.getFar()); + + F32 range = far_clip-near_clip; + + static const LLCachedControl shadow_split_exponent("RenderShadowSplitExponent",LLVector3(3.f,3.f,2.f)); + const LLVector3 &split_exp = shadow_split_exponent.get(); + + F32 da = 1.f-llmax( fabsf(lightDir*up), fabsf(lightDir*camera.getLeftAxis()) ); + + da = powf(da, split_exp.mV[2]); + + + F32 sxp = split_exp.mV[1] + (split_exp.mV[0]-split_exp.mV[1])*da; + + + for (U32 i = 0; i < 4; ++i) + { + F32 x = (F32)(i+1)/4.f; + x = powf(x, sxp); + mSunClipPlanes.mV[i] = near_clip+range*x; + } + } + + // convenience array of 4 near clip plane distances + F32 dist[] = { near_clip, mSunClipPlanes.mV[0], mSunClipPlanes.mV[1], mSunClipPlanes.mV[2], mSunClipPlanes.mV[3] }; for (S32 j = 0; j < 4; j++) { + if (!hasRenderDebugMask(RENDER_DEBUG_SHADOW_FRUSTA)) + { + mShadowFrustPoints[j].clear(); + } LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_SHADOW0+j; @@ -6660,83 +8664,45 @@ void LLPipeline::generateSunShadow(LLCamera& camera) glh_set_current_modelview(saved_view); glh_set_current_projection(saved_proj); - //get center of far clip plane (for point of interest later) - LLVector3 center = camera.getOrigin() + camera.getAtAxis() * range; - LLVector3 eye = camera.getOrigin(); //camera used for shadow cull/render LLCamera shadow_cam; - // perspective shadow map - glh::vec3f p[16]; //point cloud to be contained by shadow projection (light camera space) - glh::vec3f wp[16]; //point cloud to be contained by shadow projection (world space) - - LLVector3 lightDir = -mSunDir; - glh::vec3f light_dir(lightDir.mV); - - //create light space camera matrix - LLVector3 at; - F32 dl = camera.getLeftAxis() * lightDir; - F32 du = camera.getUpAxis() * lightDir; - - //choose an at axis such that up will be most aligned with lightDir - if (dl*dl < du*du) - { - at = lightDir%camera.getLeftAxis(); - } - else - { - at = lightDir%camera.getUpAxis(); - } - - if (at * camera.getAtAxis() < 0) - { - at = -at; - } - - - LLVector3 left = lightDir%at; - up = left%lightDir; - up.normVec(); - //create world space camera frustum for this split shadow_cam = camera; shadow_cam.setFar(16.f); - LLViewerCamera::updateFrustumPlanes(shadow_cam); + LLViewerCamera::updateFrustumPlanes(shadow_cam, FALSE, FALSE, TRUE); LLVector3* frust = shadow_cam.mAgentFrustum; LLVector3 pn = shadow_cam.getAtAxis(); - LLVector3 frust_center; - LLVector3 min, max; //construct 8 corners of split frustum section for (U32 i = 0; i < 4; i++) { LLVector3 delta = frust[i+4]-eye; + delta += (frust[i+4]-frust[(i+2)%4+4])*0.05f; delta.normVec(); F32 dp = delta*pn; - frust[i] = eye + (delta*dist[j])/dp; - frust[i+4] = eye + (delta*dist[j+1])/dp; - frust_center += frust[i] + frust[i+4]; + frust[i] = eye + (delta*dist[j]*0.95f)/dp; + frust[i+4] = eye + (delta*dist[j+1]*1.05f)/dp; } - - //get frustum center - frust_center /= 8.f; shadow_cam.calcAgentFrustumPlanes(frust); - + shadow_cam.mFrustumCornerDist = 0.f; if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA)) { mShadowCamera[j] = shadow_cam; } - if (gPipeline.getVisibleExtents(shadow_cam, min, max)) + std::vector fp; + + if (!gPipeline.getVisiblePointCloud(shadow_cam, min, max, fp, lightDir)) { //no possible shadow receivers if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA)) @@ -6746,6 +8712,16 @@ void LLPipeline::generateSunShadow(LLCamera& camera) mShadowCamera[j+4] = shadow_cam; } + mShadow[j].bindTarget(); + { + LLGLDepthTest depth(GL_TRUE); + mShadow[j].clear(); + } + mShadow[j].flush(); + + mShadowError.mV[j] = 0.f; + mShadowFOV.mV[j] = 0.f; + continue; } @@ -6753,53 +8729,266 @@ void LLPipeline::generateSunShadow(LLCamera& camera) { mShadowExtents[j][0] = min; mShadowExtents[j][1] = max; + mShadowFrustPoints[j] = fp; } - view[j] = look(frust_center-lightDir*nearDist[j], lightDir, up); - F32 shadow_dist = nearDist[j]; - for (U32 i = 0; i < 8; i++) + //find a good origin for shadow projection + LLVector3 origin; + + //get a temporary view projection + view[j] = look(camera.getOrigin(), lightDir, -up); + + std::vector wpf; + + for (U32 i = 0; i < fp.size(); i++) { - //points in worldspace (wp) and light camera space (p) - //that must be included in shadow generation - wp[i] = glh::vec3f(frust[i].mV); - wp[i+8] = wp[i] - light_dir*shadow_dist; - view[j].mult_matrix_vec(wp[i], p[i]); - view[j].mult_matrix_vec(wp[i+8], p[i+8]); + glh::vec3f p = glh::vec3f(fp[i].mV); + view[j].mult_matrix_vec(p); + wpf.push_back(LLVector3(p.v)); } - - min = LLVector3(p[0].v); - max = LLVector3(p[0].v); - LLVector3 fmin = min; - LLVector3 fmax = max; + min = wpf[0]; + max = wpf[0]; - for (U32 i = 1; i < 16; i++) - { //find camera space AABB of frustum in light camera space - update_min_max(min, max, LLVector3(p[i].v)); - if (i < 8) + for (U32 i = 0; i < fp.size(); ++i) + { //get AABB in camera space + update_min_max(min, max, wpf[i]); + } + + // Construct a perspective transform with perspective along y-axis that contains + // points in wpf + //Known: + // - far clip plane + // - near clip plane + // - points in frustum + //Find: + // - origin + + //get some "interesting" points of reference + LLVector3 center = (min+max)*0.5f; + LLVector3 size = (max-min)*0.5f; + LLVector3 near_center = center; + near_center.mV[1] += size.mV[1]*2.f; + + + //put all points in wpf in quadrant 0, reletive to center of min/max + //get the best fit line using least squares + F32 bfm = 0.f; + F32 bfb = 0.f; + + for (U32 i = 0; i < wpf.size(); ++i) + { + wpf[i] -= center; + wpf[i].mV[0] = fabsf(wpf[i].mV[0]); + wpf[i].mV[2] = fabsf(wpf[i].mV[2]); + } + + if (!wpf.empty()) + { + F32 sx = 0.f; + F32 sx2 = 0.f; + F32 sy = 0.f; + F32 sxy = 0.f; + + for (U32 i = 0; i < wpf.size(); ++i) + { + sx += wpf[i].mV[0]; + sx2 += wpf[i].mV[0]*wpf[i].mV[0]; + sy += wpf[i].mV[1]; + sxy += wpf[i].mV[0]*wpf[i].mV[1]; + } + + bfm = (sy*sx-wpf.size()*sxy)/(sx*sx-wpf.size()*sx2); + bfb = (sx*sxy-sy*sx2)/(sx*sx-bfm*sx2); + } + + { + // best fit line is y=bfm*x+bfb + + //find point that is furthest to the right of line + F32 off_x = -1.f; + LLVector3 lp; + + for (U32 i = 0; i < wpf.size(); ++i) { - update_min_max(fmin, fmax, LLVector3(p[i].v)); + //y = bfm*x+bfb + //x = (y-bfb)/bfm + F32 lx = (wpf[i].mV[1]-bfb)/bfm; + + lx = wpf[i].mV[0]-lx; + + if (off_x < lx) + { + off_x = lx; + lp = wpf[i]; + } + } + + //get line with slope bfm through lp + // bfb = y-bfm*x + bfb = lp.mV[1]-bfm*lp.mV[0]; + + //calculate error + mShadowError.mV[j] = 0.f; + + for (U32 i = 0; i < wpf.size(); ++i) + { + F32 lx = (wpf[i].mV[1]-bfb)/bfm; + mShadowError.mV[j] += fabsf(wpf[i].mV[0]-lx); + } + + mShadowError.mV[j] /= wpf.size(); + mShadowError.mV[j] /= size.mV[0]; + + static const LLCachedControl render_shadow_error_cutoff("RenderShadowErrorCutoff",5.f); + if (mShadowError.mV[j] > render_shadow_error_cutoff) + { //just use ortho projection + mShadowFOV.mV[j] = -1.f; + origin.clearVec(); + proj[j] = gl_ortho(min.mV[0], max.mV[0], + min.mV[1], max.mV[1], + -max.mV[2], -min.mV[2]); + } + else + { + //origin is where line x = 0; + origin.setVec(0,bfb,0); + + F32 fovz = 1.f; + F32 fovx = 1.f; + + LLVector3 zp; + LLVector3 xp; + + for (U32 i = 0; i < wpf.size(); ++i) + { + LLVector3 atz = wpf[i]-origin; + atz.mV[0] = 0.f; + atz.normVec(); + if (fovz > -atz.mV[1]) + { + zp = wpf[i]; + fovz = -atz.mV[1]; + } + + LLVector3 atx = wpf[i]-origin; + atx.mV[2] = 0.f; + atx.normVec(); + if (fovx > -atx.mV[1]) + { + fovx = -atx.mV[1]; + xp = wpf[i]; + } + } + + fovx = acos(fovx); + fovz = acos(fovz); + + static const LLCachedControl render_shadow_fov_cutoff("RenderShadowFOVCutoff",1.1f); + F32 cutoff = llmin(render_shadow_fov_cutoff.get(), 1.4f); + + mShadowFOV.mV[j] = fovx; + + if (fovx < cutoff && fovz > cutoff) + { + //x is a good fit, but z is too big, move away from zp enough so that fovz matches cutoff + F32 d = zp.mV[2]/tan(cutoff); + F32 ny = zp.mV[1] + fabsf(d); + + origin.mV[1] = ny; + + fovz = 1.f; + fovx = 1.f; + + for (U32 i = 0; i < wpf.size(); ++i) + { + LLVector3 atz = wpf[i]-origin; + atz.mV[0] = 0.f; + atz.normVec(); + fovz = llmin(fovz, -atz.mV[1]); + + LLVector3 atx = wpf[i]-origin; + atx.mV[2] = 0.f; + atx.normVec(); + fovx = llmin(fovx, -atx.mV[1]); + } + + fovx = acos(fovx); + fovz = acos(fovz); + + if (fovx > cutoff || llround(fovz, 0.01f) > cutoff) + { + // llerrs << "WTF?" << llendl; + } + + mShadowFOV.mV[j] = cutoff; + } + + + origin += center; + + F32 ynear = -(max.mV[1]-origin.mV[1]); + F32 yfar = -(min.mV[1]-origin.mV[1]); + + if (ynear < 0.1f) //keep a sensible near clip plane + { + F32 diff = 0.1f-ynear; + origin.mV[1] += diff; + ynear += diff; + yfar += diff; + } + + if (fovx > cutoff) + { //just use ortho projection + origin.clearVec(); + mShadowError.mV[j] = -1.f; + proj[j] = gl_ortho(min.mV[0], max.mV[0], + min.mV[1], max.mV[1], + -max.mV[2], -min.mV[2]); + } + else + { + //get perspective projection + view[j] = view[j].inverse(); + + glh::vec3f origin_agent(origin.mV); + + //translate view to origin + view[j].mult_matrix_vec(origin_agent); + + eye = LLVector3(origin_agent.v); + + if (!hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA)) + { + mShadowFrustOrigin[j] = eye; + } + + view[j] = look(LLVector3(origin_agent.v), lightDir, -up); + + F32 fx = 1.f/tanf(fovx); + F32 fz = 1.f/tanf(fovz); + + proj[j] = glh::matrix4f(-fx, 0, 0, 0, + 0, (yfar+ynear)/(ynear-yfar), 0, (2.f*yfar*ynear)/(ynear-yfar), + 0, 0, -fz, 0, + 0, -1.f, 0, 0); + } } } - //generate perspective matrix that contains frustum - //proj[j] = matrix_perspective(min, max); - proj[j] = gl_ortho(min.mV[0], max.mV[0], - min.mV[1], max.mV[1], - -max.mV[2], -min.mV[2]); - - shadow_cam.setFar(128.f); + //shadow_cam.setFar(128.f); shadow_cam.setOriginAndLookAt(eye, up, center); + shadow_cam.setOrigin(0,0,0); + glh_set_current_modelview(view[j]); glh_set_current_projection(proj[j]); LLViewerCamera::updateFrustumPlanes(shadow_cam, FALSE, FALSE, TRUE); - proj[j] = gl_ortho(fmin.mV[0], fmax.mV[0], - fmin.mV[1], fmax.mV[1], - -fmax.mV[2], -fmin.mV[2]); + shadow_cam.ignoreAgentFrustumPlane(LLCamera::AGENT_PLANE_NEAR); + //shadow_cam.getAgentPlane(LLCamera::AGENT_PLANE_NEAR).set(shadow_near_clip); //translate and scale to from [-1, 1] to [0, 1] glh::matrix4f trans(0.5f, 0.f, 0.f, 0.5f, @@ -6810,101 +8999,174 @@ void LLPipeline::generateSunShadow(LLCamera& camera) glh_set_current_modelview(view[j]); glh_set_current_projection(proj[j]); + for (U32 i = 0; i < 16; i++) + { + gGLLastModelView[i] = mShadowModelview[j].m[i]; + gGLLastProjection[i] = mShadowProjection[j].m[i]; + } + + mShadowModelview[j] = view[j]; + mShadowProjection[j] = proj[j]; + + mSunShadowMatrix[j] = trans*proj[j]*view[j]*inv_view; + stop_glerror(); - //clip out geometry on the same side of water as the camera - static LLCullResult result; - S32 occlude = LLPipeline::sUseOcclusion; - LLPipeline::sUseOcclusion = 1; - LLPipeline::sShadowRender = TRUE; - //hack to prevent LOD updates from using sun camera origin - shadow_cam.setOrigin(camera.getOrigin()); - updateCull(shadow_cam, result); - stateSort(shadow_cam, result); + mShadow[j].bindTarget(); + mShadow[j].getViewport(gGLViewport); + mShadow[j].clear(); + { + static LLCullResult result[4]; + + //LLGLEnable enable(GL_DEPTH_CLAMP_NV); + renderShadow(view[j], proj[j], shadow_cam, result[j], TRUE); + } + + mShadow[j].flush(); + if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA)) { LLViewerCamera::updateFrustumPlanes(shadow_cam, FALSE, FALSE, TRUE); mShadowCamera[j+4] = shadow_cam; } + } - LLFastTimer t(LLFastTimer::FTM_SHADOW_RENDER); + + //hack to disable projector shadows + static const LLCachedControl gen_shadow("RenderShadowDetail",0); - stop_glerror(); + if (gen_shadow > 1) + { + F32 fade_amt = gFrameIntervalSeconds * llmax(LLViewerCamera::getInstance()->getVelocityStat()->getCurrentPerSec(), 1.f); - mSunShadow[j].bindTarget(); - mSunShadow[j].getViewport(gGLViewport); + //update shadow targets + for (U32 i = 0; i < 2; i++) + { //for each current shadow + LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_SHADOW4+i; - { - LLGLDepthTest depth(GL_TRUE); - mSunShadow[j].clear(); + if (mShadowSpotLight[i].notNull() && + (mShadowSpotLight[i] == mTargetShadowSpotLight[0] || + mShadowSpotLight[i] == mTargetShadowSpotLight[1])) + { //keep this spotlight + mSpotLightFade[i] = llmin(mSpotLightFade[i]+fade_amt, 1.f); } - - U32 types[] = { LLRenderPass::PASS_SIMPLE, LLRenderPass::PASS_FULLBRIGHT, LLRenderPass::PASS_SHINY, LLRenderPass::PASS_BUMP }; - LLGLEnable cull(GL_CULL_FACE); - - //generate sun shadow map - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glLoadMatrixf(proj[j].m); - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glLoadMatrixf(view[j].m); - - stop_glerror(); - gGLLastMatrix = NULL; - - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - - glColor4f(1,1,1,1); - - glCullFace(GL_FRONT); - - stop_glerror(); - - gGL.setColorMask(false, false); - - gDeferredShadowProgram.bind(); - { - LLFastTimer ftm(LLFastTimer::FTM_SHADOW_SIMPLE); - LLGLDisable test(GL_ALPHA_TEST); - gGL.getTexUnit(0)->disable(); - for (U32 i = 0; i < sizeof(types)/sizeof(U32); ++i) - { - renderObjects(types[i], LLVertexBuffer::MAP_VERTEX, FALSE); + else + { //fade out this light + mSpotLightFade[i] = llmax(mSpotLightFade[i]-fade_amt, 0.f); + + if (mSpotLightFade[i] == 0.f || mShadowSpotLight[i].isNull()) + { //faded out, grab one of the pending spots (whichever one isn't already taken) + if (mTargetShadowSpotLight[0] != mShadowSpotLight[(i+1)%2]) + { + mShadowSpotLight[i] = mTargetShadowSpotLight[0]; + } + else + { + mShadowSpotLight[i] = mTargetShadowSpotLight[1]; + } } - gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE); } - + } + + for (S32 i = 0; i < 2; i++) + { + glh_set_current_modelview(saved_view); + glh_set_current_projection(saved_proj); + + if (mShadowSpotLight[i].isNull()) { - LLFastTimer ftm(LLFastTimer::FTM_SHADOW_ALPHA); - LLGLEnable test(GL_ALPHA_TEST); - gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.6f); - renderObjects(LLRenderPass::PASS_ALPHA_SHADOW, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_COLOR, TRUE); - glColor4f(1,1,1,1); - renderObjects(LLRenderPass::PASS_GRASS, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, TRUE); - gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); + continue; } + + LLVOVolume* volume = mShadowSpotLight[i]->getVOVolume(); + + if (!volume) + { + mShadowSpotLight[i] = NULL; + continue; + } + + LLDrawable* drawable = mShadowSpotLight[i]; + + LLVector3 params = volume->getSpotLightParams(); + F32 fov = params.mV[0]; + + //get agent->light space matrix (modelview) + LLVector3 center = drawable->getPositionAgent(); + LLQuaternion quat = volume->getRenderRotation(); + + //get near clip plane + LLVector3 scale = volume->getScale(); + LLVector3 at_axis(0,0,-scale.mV[2]*0.5f); + at_axis *= quat; + + LLVector3 np = center+at_axis; + at_axis.normVec(); + + //get origin that has given fov for plane np, at_axis, and given scale + F32 dist = (scale.mV[1]*0.5f)/tanf(fov*0.5f); + + LLVector3 origin = np - at_axis*dist; + + LLMatrix4 mat(quat, LLVector4(origin, 1.f)); + + view[i+4] = glh::matrix4f((F32*) mat.mMatrix); + + view[i+4] = view[i+4].inverse(); + + //get perspective matrix + F32 near_clip = dist+0.01f; + F32 width = scale.mV[VX]; + F32 height = scale.mV[VY]; + F32 far_clip = dist+volume->getLightRadius()*1.5f; + + F32 fovy = fov * RAD_TO_DEG; + F32 aspect = width/height; - gDeferredShadowProgram.unbind(); + proj[i+4] = gl_perspective(fovy, aspect, near_clip, far_clip); - renderGeomShadow(shadow_cam); + //translate and scale to from [-1, 1] to [0, 1] + glh::matrix4f trans(0.5f, 0.f, 0.f, 0.5f, + 0.f, 0.5f, 0.f, 0.5f, + 0.f, 0.f, 0.5f, 0.5f, + 0.f, 0.f, 0.f, 1.f); - gGL.setColorMask(true, true); + glh_set_current_modelview(view[i+4]); + glh_set_current_projection(proj[i+4]); - glCullFace(GL_BACK); - LLPipeline::sUseOcclusion = occlude; - LLPipeline::sShadowRender = FALSE; + mSunShadowMatrix[i+4] = trans*proj[i+4]*view[i+4]*inv_view; - glMatrixMode(GL_PROJECTION); - glPopMatrix(); - glMatrixMode(GL_MODELVIEW); - glPopMatrix(); - gGLLastMatrix = NULL; + for (U32 j = 0; j < 16; j++) + { + gGLLastModelView[j] = mShadowModelview[i+4].m[j]; + gGLLastProjection[j] = mShadowProjection[i+4].m[j]; + } - sMinRenderSize = 0.f; - mSunShadow[j].flush(); + mShadowModelview[i+4] = view[i+4]; + mShadowProjection[i+4] = proj[i+4]; + + LLCamera shadow_cam = camera; + shadow_cam.setFar(far_clip); + shadow_cam.setOrigin(origin); + + LLViewerCamera::updateFrustumPlanes(shadow_cam, FALSE, FALSE, TRUE); + + stop_glerror(); + + mShadow[i+4].bindTarget(); + mShadow[i+4].getViewport(gGLViewport); + mShadow[i+4].clear(); + + static LLCullResult result[2]; + + LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_SHADOW0+i+4; + + renderShadow(view[i+4], proj[i+4], shadow_cam, result[i], FALSE, FALSE); + + mShadow[i+4].flush(); + } } static const LLCachedControl camera_offset("CameraOffset",false); @@ -6923,6 +9185,13 @@ void LLPipeline::generateSunShadow(LLCamera& camera) glMatrixMode(GL_MODELVIEW); } gGL.setColorMask(true, false); + + for (U32 i = 0; i < 16; i++) + { + gGLLastModelView[i] = last_modelview[i]; + gGLLastProjection[i] = last_projection[i]; + } + popRenderTypeMask(); } @@ -7076,7 +9345,9 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar) { if (LLPipeline::sRenderDeferred) { - avatar->mImpostor.allocate(resX,resY,GL_RGBA16F_ARB,TRUE,TRUE); + static const LLCachedControl shadow_precision("DeferredHighPrecision",true); + const GLuint format = shadow_precision ? GL_RGBA : GL_RGBA16F_ARB; //TO-DO: Profile 16bit format later + avatar->mImpostor.allocate(resX,resY,format,TRUE,TRUE); addDeferredAttachments(avatar->mImpostor); } else @@ -7092,6 +9363,7 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar) glStencilMask(0xFFFFFFFF); glStencilFunc(GL_ALWAYS, 1, 0xFFFFFFFF); glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); + { LLGLEnable scissor(GL_SCISSOR_TEST); glScissor(0, 0, resX, resY); diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index 436d73726..56720d027 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -185,7 +185,7 @@ public: BOOL visibleObjectsInFrustum(LLCamera& camera); BOOL getVisibleExtents(LLCamera& camera, LLVector3 &min, LLVector3& max); BOOL getVisiblePointCloud(LLCamera& camera, LLVector3 &min, LLVector3& max, std::vector& fp, LLVector3 light_dir = LLVector3(0,0,0)); - void updateCull(LLCamera& camera, LLCullResult& result, S32 water_clip = 0); //if water_clip is 0, ignore water plane, 1, cull to above plane, -1, cull to below plane + void updateCull(LLCamera& camera, LLCullResult& result, S32 water_clip = 0, LLPlane* plane = NULL); //if water_clip is 0, ignore water plane, 1, cull to above plane, -1, cull to below plane void createObjects(F32 max_dtime); void createObject(LLViewerObject* vobj); void updateGeom(F32 max_dtime); @@ -207,17 +207,30 @@ public: void renderGroups(LLRenderPass* pass, U32 type, U32 mask, BOOL texture); void grabReferences(LLCullResult& result); + void clearReferences(); + + //check references will assert that there are no references in sCullResult to the provided data + void checkReferences(LLFace* face); + void checkReferences(LLDrawable* drawable); + void checkReferences(LLDrawInfo* draw_info); + void checkReferences(LLSpatialGroup* group); void renderGeom(LLCamera& camera, BOOL forceVBOUpdate = FALSE); void renderGeomDeferred(LLCamera& camera); void renderGeomPostDeferred(LLCamera& camera); void renderGeomShadow(LLCamera& camera); - void bindDeferredShader(LLGLSLShader& shader, U32 light_index = 0); + void bindDeferredShader(LLGLSLShader& shader, U32 light_index = 0, LLRenderTarget* gi_source = NULL, LLRenderTarget* last_gi_post = NULL, U32 noise_map = 0xFFFFFFFF); + void setupSpotLight(LLGLSLShader& shader, LLDrawable* drawablep); + void unbindDeferredShader(LLGLSLShader& shader); void renderDeferredLighting(); void generateWaterReflection(LLCamera& camera); void generateSunShadow(LLCamera& camera); + + + void renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera& camera, LLCullResult& result, BOOL use_shader = TRUE, BOOL use_occlusion = TRUE); + void generateGI(LLCamera& camera, LLVector3& lightDir, std::vector& vpc); void renderHighlights(); void renderDebug(); @@ -254,6 +267,9 @@ public: BOOL hasRenderDebugFeatureMask(const U32 mask) const { return (mRenderDebugFeatureMask & mask) ? TRUE : FALSE; } BOOL hasRenderDebugMask(const U32 mask) const { return (mRenderDebugMask & mask) ? TRUE : FALSE; } + + + BOOL hasRenderType(const U32 type) const; BOOL hasAnyRenderType(const U32 type, ...) const; @@ -454,22 +470,47 @@ public: static BOOL sRenderAttachedLights; static BOOL sRenderAttachedParticles; static BOOL sRenderDeferred; - static BOOL sAllowRebuildPriorityGroup; static S32 sVisibleLightCount; static F32 sMinRenderSize; //screen texture + LLRenderTarget mScreen; LLRenderTarget mDeferredScreen; - LLRenderTarget mDeferredLight[2]; + LLRenderTarget mEdgeMap; + LLRenderTarget mDeferredDepth; + LLRenderTarget mDeferredLight[3]; LLMultisampleBuffer mSampleBuffer; + LLRenderTarget mGIMap; + LLRenderTarget mGIMapPost[2]; + LLRenderTarget mLuminanceMap; //sun shadow map - LLRenderTarget mSunShadow[4]; + LLRenderTarget mShadow[6]; + std::vector mShadowFrustPoints[4]; + LLVector4 mShadowError; + LLVector4 mShadowFOV; + LLVector3 mShadowFrustOrigin[4]; LLCamera mShadowCamera[8]; LLVector3 mShadowExtents[4][2]; - glh::matrix4f mSunShadowMatrix[4]; + glh::matrix4f mSunShadowMatrix[6]; + glh::matrix4f mShadowModelview[6]; + glh::matrix4f mShadowProjection[6]; + glh::matrix4f mGIMatrix; + glh::matrix4f mGIMatrixProj; + glh::matrix4f mGIModelview; + glh::matrix4f mGIProjection; + glh::matrix4f mGINormalMatrix; + glh::matrix4f mGIInvProj; + LLVector2 mGIRange; + F32 mGILightRadius; + + LLPointer mShadowSpotLight[2]; + F32 mSpotLightFade[2]; + LLPointer mTargetShadowSpotLight[2]; + LLVector4 mSunClipPlanes; + LLVector4 mSunOrthoClipPlanes; LLVector2 mScreenScale; @@ -484,6 +525,8 @@ public: //noise map U32 mNoiseMap; + U32 mTrueNoiseMap; + U32 mLightFunc; LLColor4 mSunDiffuse; LLVector3 mSunDir; @@ -548,6 +591,9 @@ protected: LLDrawable::drawable_list_t mBuildQ2; // non-priority LLSpatialGroup::sg_vector_t mGroupQ1; //priority LLSpatialGroup::sg_vector_t mGroupQ2; // non-priority + bool mGroupQ2Locked; + bool mGroupQ1Locked; + LLViewerObject::vobj_list_t mCreateQ; LLDrawable::drawable_set_t mRetexturedList; @@ -618,6 +664,9 @@ protected: public: static BOOL sRenderBeacons; static BOOL sRenderHighlight; + + //debug use + static U32 sCurRenderPoolType ; }; void render_bbox(const LLVector3 &min, const LLVector3 &max); diff --git a/indra/newview/rlvhandler.cpp b/indra/newview/rlvhandler.cpp index 94b88fb0c..16c415f5c 100644 --- a/indra/newview/rlvhandler.cpp +++ b/indra/newview/rlvhandler.cpp @@ -1430,7 +1430,7 @@ ERlvCmdRet RlvHandler::processForceCommand(const RlvCommand& rlvCmd) const { VERIFY_OPTION(rlvCmd.getOption().empty()); LLVOAvatar* pAvatar = gAgent.getAvatarObject(); - if ( (pAvatar) && (pAvatar->mIsSitting) && (!hasBehaviourExcept(RLV_BHVR_UNSIT, rlvCmd.getObjectID())) ) + if ( (pAvatar) && (pAvatar->isSitting()) && (!hasBehaviourExcept(RLV_BHVR_UNSIT, rlvCmd.getObjectID())) ) { gAgent.setControlFlags(AGENT_CONTROL_STAND_UP); send_agent_update(TRUE, TRUE); // See behaviour notes on why we have to force an agent update here @@ -1577,7 +1577,7 @@ ERlvCmdRet RlvHandler::onForceSit(const RlvCommand& rlvCmd) const return RLV_RET_FAILED_LOCK; else if ( (hasBehaviour(RLV_BHVR_STANDTP)) && (gAgent.getAvatarObject()) ) { - if (gAgent.getAvatarObject()->mIsSitting) + if (gAgent.getAvatarObject()->isSitting()) return RLV_RET_FAILED_LOCK; m_posSitSource = gAgent.getPositionGlobal(); } @@ -1692,7 +1692,7 @@ ERlvCmdRet RlvHandler::processReplyCommand(const RlvCommand& rlvCmd) const { // NOTE: RLV 1.16.1 returns a NULL UUID if we're not sitting LLVOAvatar* pAvatar = gAgent.getAvatarObject(); LLUUID idSitObj; - if ( (pAvatar) && (pAvatar->mIsSitting) ) + if ( (pAvatar) && (pAvatar->isSitting()) ) { // LLVOAvatar inherits from 2 classes so make sure we get the right vfptr LLViewerObject* pAvatarObj = dynamic_cast(pAvatar), *pParent; diff --git a/indra/newview/rlvhandler.h b/indra/newview/rlvhandler.h index 62f577cc3..69f8ad703 100644 --- a/indra/newview/rlvhandler.h +++ b/indra/newview/rlvhandler.h @@ -22,6 +22,7 @@ #include "llstartup.h" #include "llviewerjointattachment.h" #include "llviewerobject.h" +#include "lleventtimer.h" #include "rlvcommon.h" #include "rlvhelper.h" @@ -243,7 +244,7 @@ inline bool RlvHandler::canSit(LLViewerObject* pObj, const LLVector3& posOffset ( (pObj) && (LL_PCODE_VOLUME == pObj->getPCode()) ) && (!hasBehaviour(RLV_BHVR_SIT)) && ( ((!hasBehaviour(RLV_BHVR_UNSIT)) && (!hasBehaviour(RLV_BHVR_STANDTP))) || - ((gAgent.getAvatarObject()) && (!gAgent.getAvatarObject()->mIsSitting)) ) && + ((gAgent.getAvatarObject()) && (!gAgent.getAvatarObject()->isSitting())) ) && ( ((NULL == getCurrentCommand() || (RLV_BHVR_SIT != getCurrentCommand()->getBehaviourType())) ? ((!hasBehaviour(RLV_BHVR_SITTP)) && (!hasBehaviour(RLV_BHVR_FARTOUCH))) // [regular sit] : (!hasBehaviourExcept(RLV_BHVR_SITTP, getCurrentObject()))) || // [force sit] @@ -254,7 +255,7 @@ inline bool RlvHandler::canSit(LLViewerObject* pObj, const LLVector3& posOffset inline bool RlvHandler::canStand() const { // NOTE: return FALSE only if we're @unsit=n restricted and the avie is currently sitting on something and TRUE for everything else - return (!hasBehaviour(RLV_BHVR_UNSIT)) || ((gAgent.getAvatarObject()) && (!gAgent.getAvatarObject()->mIsSitting)); + return (!hasBehaviour(RLV_BHVR_UNSIT)) || ((gAgent.getAvatarObject()) && (!gAgent.getAvatarObject()->isSitting())); } // Checked: 2010-12-11 (RLVa-1.2.2c) | Added: RLVa-1.2.2c diff --git a/indra/newview/rlvhelper.h b/indra/newview/rlvhelper.h index 165797b92..74b527f70 100644 --- a/indra/newview/rlvhelper.h +++ b/indra/newview/rlvhelper.h @@ -24,6 +24,7 @@ #include "llviewerinventory.h" #include "llvoavatar.h" #include "llwlparamset.h" +#include "lleventtimer.h" #include "rlvdefines.h" #include "rlvcommon.h" diff --git a/indra/newview/rlvlocks.h b/indra/newview/rlvlocks.h index e54caa30a..c4139b135 100644 --- a/indra/newview/rlvlocks.h +++ b/indra/newview/rlvlocks.h @@ -28,6 +28,7 @@ #include "llviewerjointattachment.h" #include "llviewerobject.h" #include "llvoavatar.h" +#include "lleventtimer.h" #include "rlvdefines.h" diff --git a/indra/newview/skins/default/xui/en-us/floater_beacons.xml b/indra/newview/skins/default/xui/en-us/floater_beacons.xml index 361d04601..ff9ed0b0a 100644 --- a/indra/newview/skins/default/xui/en-us/floater_beacons.xml +++ b/indra/newview/skins/default/xui/en-us/floater_beacons.xml @@ -1,24 +1,25 @@ - - + rect_control="FloaterBeaconsRect" control_name="ShowBeaconsFloater"> + + + - + Beacon Width: diff --git a/indra/newview/skins/default/xui/en-us/floater_dickdongs.xml b/indra/newview/skins/default/xui/en-us/floater_dickdongs.xml deleted file mode 100644 index a1afa5798..000000000 --- a/indra/newview/skins/default/xui/en-us/floater_dickdongs.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - AMOUNT OF AWESOME: - - - - diff --git a/indra/newview/skins/default/xui/en-us/floater_snapshot.xml b/indra/newview/skins/default/xui/en-us/floater_snapshot.xml index 65e7d0fae..5b86ce319 100644 --- a/indra/newview/skins/default/xui/en-us/floater_snapshot.xml +++ b/indra/newview/skins/default/xui/en-us/floater_snapshot.xml @@ -32,6 +32,7 @@ list_position="below" mouse_opaque="true" name="save_btn" tool_tip="Save image to a file" width="105"> Save + Save As...