diff options
Diffstat (limited to 'indra')
61 files changed, 3310 insertions, 1600 deletions
diff --git a/indra/llcommon/llapr.cpp b/indra/llcommon/llapr.cpp index 66ec5bad2c..7330b00bcf 100644 --- a/indra/llcommon/llapr.cpp +++ b/indra/llcommon/llapr.cpp @@ -4,25 +4,31 @@ * @date 2004-11-28 * @brief Helper functions for using the apache portable runtime library. * - * $LicenseInfo:firstyear=2004&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. + * $LicenseInfo:firstyear=2004&license=viewergpl$ + * + * Copyright (c) 2004-2009, 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. + * 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 * - * 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. + * 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 * - * 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 + * 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. * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * 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$ */ @@ -411,11 +417,7 @@ apr_pool_t* LLAPRFile::getAPRFilePool(apr_pool_t* pool) // File I/O S32 LLAPRFile::read(void *buf, S32 nbytes) { - if(!mFile) - { - llwarns << "apr mFile is removed by somebody else. Can not read." << llendl ; - return 0; - } + llassert_always(mFile) ; apr_size_t sz = nbytes; apr_status_t s = apr_file_read(mFile, buf, &sz); @@ -433,11 +435,7 @@ S32 LLAPRFile::read(void *buf, S32 nbytes) S32 LLAPRFile::write(const void *buf, S32 nbytes) { - if(!mFile) - { - llwarns << "apr mFile is removed by somebody else. Can not write." << llendl ; - return 0; - } + llassert_always(mFile) ; apr_size_t sz = nbytes; apr_status_t s = apr_file_write(mFile, buf, &sz); diff --git a/indra/llcommon/llapr.h b/indra/llcommon/llapr.h index 4930270af8..08cf11e593 100644 --- a/indra/llcommon/llapr.h +++ b/indra/llcommon/llapr.h @@ -4,25 +4,31 @@ * @date 2004-11-28 * @brief Helper functions for using the apache portable runtime library. * - * $LicenseInfo:firstyear=2004&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. + * $LicenseInfo:firstyear=2004&license=viewergpl$ + * + * Copyright (c) 2004-2009, 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. + * 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 * - * 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. + * 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 * - * 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 + * 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. * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * 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$ */ diff --git a/indra/llcommon/llfasttimer.h b/indra/llcommon/llfasttimer.h index 4ff93a553c..840d09d970 100644 --- a/indra/llcommon/llfasttimer.h +++ b/indra/llcommon/llfasttimer.h @@ -2,25 +2,31 @@ * @file llfasttimer.h * @brief Inline implementations of fast timers. * - * $LicenseInfo:firstyear=2004&license=viewerlgpl$ + * $LicenseInfo:firstyear=2004&license=viewergpl$ + * + * Copyright (c) 2004-2009, Linden Research, Inc. + * * 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 + * 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$ */ diff --git a/indra/llcommon/llfasttimer_class.cpp b/indra/llcommon/llfasttimer_class.cpp index bc1ae37c2b..f39a4e6619 100644 --- a/indra/llcommon/llfasttimer_class.cpp +++ b/indra/llcommon/llfasttimer_class.cpp @@ -2,25 +2,30 @@ * @file llfasttimer_class.cpp * @brief Implementation of the fast timer. * - * $LicenseInfo:firstyear=2004&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. + * $LicenseInfo:firstyear=2004&license=viewergpl$ + * + * Copyright (c) 2004-2007, 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. + * 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 * - * 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. + * 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 * - * 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 + * 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. * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * 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" @@ -233,8 +238,7 @@ U64 LLFastTimer::countsPerSecond() // counts per second for the *32-bit* timer #else // windows or x86-mac or x86-linux or x86-solaris U64 LLFastTimer::countsPerSecond() // counts per second for the *32-bit* timer { - //getCPUFrequency returns MHz and sCPUClockFrequency wants to be in Hz - static U64 sCPUClockFrequency = U64(LLProcessorInfo().getCPUFrequency()*1000000.0); + static U64 sCPUClockFrequency = U64(CProcessor().GetCPUFrequency(50)); // we drop the low-order byte in our timers, so report a lower frequency return sCPUClockFrequency >> 8; diff --git a/indra/llcommon/llprocessor.cpp b/indra/llcommon/llprocessor.cpp index fd8f603d21..f6ab55a6b5 100644 --- a/indra/llcommon/llprocessor.cpp +++ b/indra/llcommon/llprocessor.cpp @@ -2,411 +2,167 @@ * @file llprocessor.cpp * @brief Code to figure out the processor. Originally by Benjamin Jurke. * - * $LicenseInfo:firstyear=2002&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. + * $LicenseInfo:firstyear=2002&license=viewergpl$ + * + * Copyright (c) 2002-2009, 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. + * 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 * - * 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. + * 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 * - * 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 + * 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. * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * 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$ */ +// 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 "llerror.h" +#include "processor.h" -//#include <memory> +#include <memory> #if LL_WINDOWS # define WIN32_LEAN_AND_MEAN # include <winsock2.h> # include <windows.h> -# define _interlockedbittestandset _renamed_interlockedbittestandset -# define _interlockedbittestandreset _renamed_interlockedbittestandreset -# include <intrin.h> -# undef _interlockedbittestandset -# undef _interlockedbittestandreset #endif -#include "llsd.h" - -#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; - -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); - } +#if LL_LINUX +#include "llsys.h" +#endif // LL_LINUX - 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); - } +#if !LL_DARWIN && !LL_SOLARIS -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 PROCESSOR_FREQUENCY_MEASURE_AVAILABLE +// We need the QueryPerformanceCounter and Sleep functions +#define FORCEINLINE __forceinline +#else +#define FORCEINLINE +#endif -#ifdef LL_MSVC -// LL_MSVC and not LLWINDOWS because some of the following code -// uses the MSVC compiler intrinsics __cpuid() and __rdtsc(). +// Some macros we often need +//////////////////////////// +#define CheckBit(var, bit) ((var & (1 << bit)) ? true : false) +#ifdef PROCESSOR_FREQUENCY_MEASURE_AVAILABLE // Delays for the specified amount of milliseconds -static void _Delay(unsigned int ms) +static void _Delay(unsigned int ms) { - LARGE_INTEGER freq, c1, c2; - __int64 x; + LARGE_INTEGER freq, c1, c2; + __int64 x; - // Get High-Res Timer frequency + // Get High-Res Timer frequency if (!QueryPerformanceFrequency(&freq)) return; - + // Convert ms to High-Res Timer value x = freq.QuadPart/1000*ms; - // Get first snapshot of High-Res Timer value + // Get first snapshot of High-Res Timer value QueryPerformanceCounter(&c1); do { - // Get second snapshot - QueryPerformanceCounter(&c2); + // Get second snapshot + QueryPerformanceCounter(&c2); }while(c2.QuadPart-c1.QuadPart < x); // Loop while (second-first < x) } +#endif + +// CProcessor::CProcessor +// ====================== +// Class constructor: +///////////////////////// +CProcessor::CProcessor() +{ + uqwFrequency = 0; + strCPUName[0] = 0; + memset(&CPUInfo, 0, sizeof(CPUInfo)); +} -static F64 calculate_cpu_frequency(U32 measure_msecs) +// unsigned __int64 CProcessor::GetCPUFrequency(unsigned int uiMeasureMSecs) +// ========================================================================= +// Function to measure the current CPU frequency +//////////////////////////////////////////////////////////////////////////// +F64 CProcessor::GetCPUFrequency(unsigned int uiMeasureMSecs) { - if(measure_msecs == 0) +#if LL_LINUX + // use the shinier LLCPUInfo interface + return 1000000.0F * gSysCPU.getMHz(); +#endif + +#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 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. - unsigned __int64 starttime, endtime, timedif, freq, start, end, dif; + // If there's no high-res timer, we exit. + __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 @@ -422,27 +178,35 @@ static F64 calculate_cpu_frequency(U32 measure_msecs) 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 - int cpu_info[4] = {-1}; - __cpuid(cpu_info, 0); + // Now we call a CPUID to ensure, that all other prior called functions are + // completed now (serialization) + __asm cpuid // We ask the high-res timer for the start time QueryPerformanceCounter((LARGE_INTEGER *) &starttime); // Then we get the current cpu clock and store it - start = __rdtsc(); + __asm + { + rdtsc + mov dword ptr [start+4], edx + mov dword ptr [start], eax + } // Now we wart for some msecs - _Delay(measure_msecs); - // Sleep(uiMeasureMSecs); + _Delay(uiMeasureMSecs); +// Sleep(uiMeasureMSecs); // We ask for the end time QueryPerformanceCounter((LARGE_INTEGER *) &endtime); // And also for the end cpu clock - end = __rdtsc(); + __asm + { + rdtsc + mov dword ptr [end+4], edx + mov dword ptr [end], eax + } // Now we can restore the default process and thread priorities SetProcessAffinityMask(hProcess, dwProcessMask); @@ -455,433 +219,2075 @@ static F64 calculate_cpu_frequency(U32 measure_msecs) // And finally the frequency is the clock difference divided by the time // difference. - F64 frequency = (F64)dif / (((F64)timedif) / freq); + uqwFrequency = (F64)dif / (((F64)timedif) / freq); // At last we just return the frequency that is also stored in the call - // member var uqwFrequency - converted to MHz - return frequency / (F64)1000000; + // member var uqwFrequency + return uqwFrequency; +#endif } -// Windows implementation -class LLProcessorInfoWindowsImpl : public LLProcessorInfoImpl +// bool CProcessor::AnalyzeIntelProcessor() +// ======================================== +// Private class function for analyzing an Intel processor +////////////////////////////////////////////////////////// +bool CProcessor::AnalyzeIntelProcessor() { -public: - LLProcessorInfoWindowsImpl() +#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 { - getCPUIDInfo(); - setInfo(eFrequency, calculate_cpu_frequency(50)); + mov eax, 1 + cpuid + mov eaxreg, eax + mov ebxreg, ebx + mov edxreg, edx } - -private: - void getCPUIDInfo() + + // 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[] = { - // http://msdn.microsoft.com/en-us/library/hskdteyh(VS.80).aspx - - // __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); + /* 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", + }; - 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); + // 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) ) + { + strncpy(CPUInfo.strBrandID, INTEL_BRAND[CPUInfo.uiBrandID], sizeof(CPUInfo.strBrandID)-1); + CPUInfo.strBrandID[sizeof(CPUInfo.strBrandID)-1]='\0'; - // Get the information associated with each valid Id - for(unsigned int i=0; i<=ids; ++i) + if (CPUInfo.uiBrandID == 3 && CPUInfo.uiModel == 6) { - __cpuid(cpu_info, i); + strcpy(CPUInfo.strBrandID, "0.18 micron Intel Pentium III Xeon"); + } + } - // Interpret CPU feature information. - if (i == 1) + // 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) + { + 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; + } + + // 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) + { + 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; + } + 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) { - 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); - - 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 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 { - setExtension(cpu_feature_names[index]); + 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; } + 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"); + } - // 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); + // Now we get the standard processor extensions + GetStandardProcessorExtensions(); - char cpu_brand_string[0x40]; - memset(cpu_brand_string, 0, sizeof(cpu_brand_string)); + // And finally the processor configuration (caches, TLBs, ...) and translate + // the data to readable strings + GetStandardProcessorConfiguration(); + TranslateProcessorConfiguration(); - // Get the information associated with each extended ID. - for(unsigned int i=0x80000000; i<=ext_ids; ++i) + // 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 { - __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) + 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) { - memcpy(cpu_brand_string + 32, cpu_info, sizeof(cpu_info)); - setInfo(eBrandName, cpu_brand_string); + 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; } - else if (i == 0x80000006) + break; + case 5: // Family = 5: K5 or K6 processor family + switch (CPUInfo.uiModel) { - setConfig(eCacheLineSize, cpu_info[2] & 0xff); - setConfig(eL2Associativity, (cpu_info[2] >> 12) & 0xf); - setConfig(eCacheSizeK, (cpu_info[2] >> 16) & 0xffff); + 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; } -}; -#elif LL_DARWIN - -#include <mach/machine.h> -#include <sys/sysctl.h> - -class LLProcessorInfoDarwinImpl : public LLProcessorInfoImpl -{ -public: - LLProcessorInfoDarwinImpl() - { - getCPUIDInfo(); - uint64_t frequency = getSysctlInt64("hw.cpufrequency"); - setInfo(eFrequency, (F64)frequency / (F64)1000000); - } - - virtual ~LLProcessorInfoDarwinImpl() {} - -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 + // 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) { - LL_WARNS("Unknown type returned from sysctl!") << LL_ENDL; + 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 } - - return result == -1 ? 0 : value; - } - - void getCPUIDInfo() + + // 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) { - size_t len = 0; + // 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 + } - 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); + // 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; - setConfig(eFeatureBits, feature_infos[0]); + // 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 + } - for(unsigned int index = 0, bit = 1; index < eSSE3_Features; ++index, bit <<= 1) + // 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) { - if(feature_info & bit) + CPUInfo._L2.bPresent = true; + snprintf(CPUInfo._L2.strSize, sizeof(CPUInfo._L2.strSize), "%d KB", ecxreg >> 16); /* Flawfinder: ignore */ + switch ((ecxreg >> 12) & 0xF) { - setExtension(cpu_feature_names[index]); + 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(); - // *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 + // 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; - uint64_t ext_feature_info = getSysctlInt64("machdep.cpu.extfeature_bits"); - S32 *ext_feature_infos = (S32*)(&ext_feature_info); - setConfig(eExtFeatureBits, ext_feature_infos[0]); + // 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*/ -#elif LL_LINUX -const char CPUINFO_FILE[] = "/proc/cpuinfo"; + strcpy(CPUInfo.strProcessorSerial, "Unknown / Not supported"); /*Flawfinder: ignore*/ -class LLProcessorInfoLinuxImpl : public LLProcessorInfoImpl + // 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() { -public: - LLProcessorInfoLinuxImpl() +#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 { - get_proc_cpuinfo(); + pushfd + pop eax + mov ebx, eax + xor eax, 0x00200000 + push eax + popfd + pushfd + pop eax + xor eax,ebx + mov BitChanged, eax } - virtual ~LLProcessorInfoLinuxImpl() {} -private: + 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 */ - void get_proc_cpuinfo() + // 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 { - std::map< std::string, std::string > cpuinfo; - LLFILE* cpuinfo_fp = LLFile::fopen(CPUINFO_FILE, "rb"); - if(cpuinfo_fp) + // 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++) { - char line[MAX_STRING]; - memset(line, 0, MAX_STRING); - while(fgets(line, MAX_STRING, cpuinfo_fp)) + __asm { - // /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; + 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); } - 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)); } + } +#endif +} - LLPI_SET_INFO_STRING(eBrandName, "model name"); - LLPI_SET_INFO_STRING(eVendor, "vendor_id"); +// void CProcessor::GetStandardProcessorExtensions() +// ================================================= +// Private class function to read the standard processor extensions +/////////////////////////////////////////////////////////////////// +void CProcessor::GetStandardProcessorExtensions() +{ +#if LL_WINDOWS + unsigned long ebxreg, edxreg; - LLPI_SET_INFO_INT(eStepping, "stepping"); - LLPI_SET_INFO_INT(eModel, "model"); + // 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 +} - - S32 family; - if (!cpuinfo["cpu family"].empty() - && LLStringUtil::convertToS32(cpuinfo["cpu family"], family)) - { - setInfo(eFamily, family); - } +// 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; - setInfo(eFamilyName, compute_CPUFamilyName(cpuinfo["vendor_id"].c_str(), family)); + // First of all we check if the CPUID command is available + if (!CheckCPUIDPresence()) + return NULL; - // setInfo(eExtendedModel, getSysctlInt("machdep.cpu.extmodel")); - // setInfo(eBrandID, getSysctlInt("machdep.cpu.brand")); - // setInfo(eType, 0); // ? where to find this? + // 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; - //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); + // 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); +} - if( flags.find( " sse " ) != std::string::npos ) - { - setExtension(cpu_feature_names[eSSE_Ext]); - } +#elif LL_SOLARIS +#include <kstat.h> - if( flags.find( " sse2 " ) != std::string::npos ) - { - setExtension(cpu_feature_names[eSSE2_Ext]); - } +#if defined(__i386) +#include <sys/auxv.h> +#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++; + } -# endif // LL_X86 + if(ncpus < 1){ + llwarns << "No cpus found in kstats!" << llendl; + return (&CPUInfo); } - std::string getCPUFeatureDescription() const - { - std::ostringstream s; + 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; + } + } - // *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; + 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; } - else - { - s << "Unable to collect processor information" << std::endl; + + 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; } - return s.str(); + +#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); -#endif // LL_MSVC elif LL_DARWIN elif LL_LINUX +#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); +} -////////////////////////////////////////////////////// -// 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 +// LL_DARWIN + +#include <mach/machine.h> +#include <sys/sysctl.h> + +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; } +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 */ -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(); } + // 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); +} + +// 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/llsys.cpp b/indra/llcommon/llsys.cpp index 00c94404d4..52b1b63209 100644 --- a/indra/llcommon/llsys.cpp +++ b/indra/llcommon/llsys.cpp @@ -2,25 +2,31 @@ * @file llsys.cpp * @brief Impelementation of the basic system query functions. * - * $LicenseInfo:firstyear=2002&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. + * $LicenseInfo:firstyear=2002&license=viewergpl$ + * + * Copyright (c) 2002-2009, 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. + * 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 * - * 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. + * 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 * - * 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 + * 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. * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * 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$ */ @@ -52,6 +58,7 @@ # include <unistd.h> # include <sys/sysinfo.h> const char MEMINFO_FILE[] = "/proc/meminfo"; +const char CPUINFO_FILE[] = "/proc/cpuinfo"; #elif LL_SOLARIS # include <stdio.h> # include <unistd.h> @@ -506,21 +513,71 @@ U32 LLOSInfo::getProcessResidentSizeKB() LLCPUInfo::LLCPUInfo() { std::ostringstream out; - LLProcessorInfo proc; + CProcessor proc; + const ProcessorInfo* info = proc.GetCPUInfo(); // proc.WriteInfoTextFile("procInfo.txt"); - mHasSSE = proc.hasSSE(); - mHasSSE2 = proc.hasSSE2(); - mHasAltivec = proc.hasAltivec(); - mCPUMHz = (F64)proc.getCPUFrequency(); - mFamily = proc.getCPUFamilyName(); + mHasSSE = info->_Ext.SSE_StreamingSIMD_Extensions; + mHasSSE2 = info->_Ext.SSE2_StreamingSIMD2_Extensions; + mHasAltivec = info->_Ext.Altivec_Extensions; + mCPUMHz = (F64)(proc.GetCPUFrequency(50)/1000000.0F); + mFamily.assign( info->strFamily ); mCPUString = "Unknown"; - out << proc.getCPUBrandName(); +#if LL_WINDOWS || LL_DARWIN || LL_SOLARIS + out << proc.strCPUName; 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)(mhz); + } + if (!cpuinfo["model name"].empty()) + mCPUString = cpuinfo["model name"]; +# endif // LL_X86 +#endif // LL_LINUX } bool LLCPUInfo::hasAltivec() const @@ -550,9 +607,38 @@ std::string LLCPUInfo::getCPUString() const void LLCPUInfo::stream(std::ostream& s) const { +#if LL_WINDOWS || LL_DARWIN || LL_SOLARIS // gather machine information. - s << LLProcessorInfo().getCPUFeatureDescription(); - + 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 // 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 39af74e5c8..0b34951149 100644 --- a/indra/llcommon/llsys.h +++ b/indra/llcommon/llsys.h @@ -2,25 +2,31 @@ * @file llsys.h * @brief System information debugging classes. * - * $LicenseInfo:firstyear=2001&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. + * $LicenseInfo:firstyear=2001&license=viewergpl$ + * + * Copyright (c) 2001-2009, 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. + * 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 * - * 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. + * 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 * - * 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 + * 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. * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * 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$ */ diff --git a/indra/llcommon/lltimer.cpp b/indra/llcommon/lltimer.cpp index 38054b636e..6111db2bfa 100644 --- a/indra/llcommon/lltimer.cpp +++ b/indra/llcommon/lltimer.cpp @@ -2,25 +2,31 @@ * @file lltimer.cpp * @brief Cross-platform objects for doing timing * - * $LicenseInfo:firstyear=2000&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. + * $LicenseInfo:firstyear=2000&license=viewergpl$ + * + * Copyright (c) 2000-2009, 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. + * 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 * - * 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. + * 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 * - * 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 + * 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. * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * 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$ */ diff --git a/indra/llmath/v2math.h b/indra/llmath/v2math.h index f50a5e6633..65f3714313 100644 --- a/indra/llmath/v2math.h +++ b/indra/llmath/v2math.h @@ -2,25 +2,31 @@ * @file v2math.h * @brief LLVector2 class header file. * - * $LicenseInfo:firstyear=2000&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. + * $LicenseInfo:firstyear=2000&license=viewergpl$ + * + * Copyright (c) 2000-2009, 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. + * 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 * - * 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. + * 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 * - * 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 + * 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. * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * 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$ */ diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index dae759ca5f..00f0fd5b9a 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -1778,8 +1778,18 @@ BOOL LLImageGL::getMask(const LLVector2 &tc) if (mPickMask) { - F32 u = tc.mV[0] - floorf(tc.mV[0]); - F32 v = tc.mV[1] - floorf(tc.mV[1]); + F32 u,v; + if (LL_LIKELY(tc.isFinite())) + { + u = tc.mV[0] - floorf(tc.mV[0]); + v = tc.mV[1] - floorf(tc.mV[1]); + } + else + { + LL_WARNS_ONCE("render") << "Ugh, non-finite u/v in mask pick" << LL_ENDL; + u = v = 0.f; + llassert(false); + } if (LL_UNLIKELY(u < 0.f || u > 1.f || v < 0.f || v > 1.f)) diff --git a/indra/llui/llflatlistview.cpp b/indra/llui/llflatlistview.cpp index 35f5a6bbb9..82f054c4b7 100644 --- a/indra/llui/llflatlistview.cpp +++ b/indra/llui/llflatlistview.cpp @@ -504,7 +504,68 @@ void LLFlatListView::onItemMouseClick(item_pair_t* item_pair, MASK mask) //*TODO find a better place for that enforcing stuff if (mKeepOneItemSelected && numSelected() == 1 && !select_item) return; - + + if ( (mask & MASK_SHIFT) && !(mask & MASK_CONTROL) + && mMultipleSelection && !mSelectedItemPairs.empty() ) + { + item_pair_t* last_selected_pair = mSelectedItemPairs.back(); + + // If item_pair is already selected - do nothing + if (last_selected_pair == item_pair) + return; + + bool grab_items = false; + pairs_list_t pairs_to_select; + + // Pick out items from list between last selected and current clicked item_pair. + for (pairs_iterator_t + iter = mItemPairs.begin(), + iter_end = mItemPairs.end(); + iter != iter_end; ++iter) + { + item_pair_t* cur = *iter; + if (cur == last_selected_pair || cur == item_pair) + { + grab_items = !grab_items; + // Skip last selected and current clicked item pairs. + continue; + } + if (!cur->first->getVisible()) + { + // Skip invisible item pairs. + continue; + } + if (grab_items) + { + pairs_to_select.push_back(cur); + } + } + + if (select_item) + { + pairs_to_select.push_back(item_pair); + } + + for (pairs_iterator_t + iter = pairs_to_select.begin(), + iter_end = pairs_to_select.end(); + iter != iter_end; ++iter) + { + item_pair_t* pair_to_select = *iter; + selectItemPair(pair_to_select, true); + } + + if (!select_item) + { + // Item was already selected but there is a need to update last selected item and its border. + // Do it here to prevent extra mCommitOnSelectionChange in selectItemPair(). + mSelectedItemPairs.remove(item_pair); + mSelectedItemPairs.push_back(item_pair); + mSelectedItemsBorder->setRect(getLastSelectedItemRect().stretch(-1)); + } + return; + } + if (!(mask & MASK_CONTROL) || !mMultipleSelection) resetSelection(); selectItemPair(item_pair, select_item); } diff --git a/indra/llui/llsliderctrl.cpp b/indra/llui/llsliderctrl.cpp index 904c458e85..04958075db 100644 --- a/indra/llui/llsliderctrl.cpp +++ b/indra/llui/llsliderctrl.cpp @@ -2,25 +2,31 @@ * @file llsliderctrl.cpp * @brief LLSliderCtrl base class * - * $LicenseInfo:firstyear=2002&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. + * $LicenseInfo:firstyear=2002&license=viewergpl$ + * + * Copyright (c) 2002-2009, 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. + * 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 * - * 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. + * 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 * - * 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 + * 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. * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * 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$ */ diff --git a/indra/llui/llsliderctrl.h b/indra/llui/llsliderctrl.h index 5153e33f49..482c81a0f4 100644 --- a/indra/llui/llsliderctrl.h +++ b/indra/llui/llsliderctrl.h @@ -2,25 +2,31 @@ * @file llsliderctrl.h * @brief Decorated wrapper for a LLSlider. * - * $LicenseInfo:firstyear=2002&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. + * $LicenseInfo:firstyear=2002&license=viewergpl$ + * + * Copyright (c) 2002-2009, 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. + * 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 * - * 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. + * 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 * - * 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 + * 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. * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * 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$ */ diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp index a1cae4bb98..4fd62045e8 100644 --- a/indra/llui/lltexteditor.cpp +++ b/indra/llui/lltexteditor.cpp @@ -713,7 +713,8 @@ BOOL LLTextEditor::handleRightMouseDown(S32 x, S32 y, MASK mask) { setFocus(TRUE); } - if (!LLTextBase::handleRightMouseDown(x, y, mask)) + // Prefer editor menu if it has selection. See EXT-6806. + if (hasSelection() || !LLTextBase::handleRightMouseDown(x, y, mask)) { if(getShowContextMenu()) { diff --git a/indra/llvfs/lldir.cpp b/indra/llvfs/lldir.cpp index da4abde451..29b6f490c8 100644 --- a/indra/llvfs/lldir.cpp +++ b/indra/llvfs/lldir.cpp @@ -91,15 +91,16 @@ S32 LLDir::deleteFilesInDir(const std::string &dirname, const std::string &mask) S32 result; while (getNextFileInDir(dirname, mask, filename, FALSE)) { - if ((filename == ".") || (filename == "..")) + fullpath = dirname; + fullpath += getDirDelimiter(); + fullpath += filename; + + if(LLFile::isdir(fullpath)) { // skipping directory traversal filenames count++; continue; } - fullpath = dirname; - fullpath += getDirDelimiter(); - fullpath += filename; S32 retry_count = 0; while (retry_count < 5) diff --git a/indra/llvfs/lllfsthread.cpp b/indra/llvfs/lllfsthread.cpp index 3d3ed9f6d4..49c198a82d 100644 --- a/indra/llvfs/lllfsthread.cpp +++ b/indra/llvfs/lllfsthread.cpp @@ -2,25 +2,31 @@ * @file lllfsthread.cpp * @brief LLLFSThread base class * - * $LicenseInfo:firstyear=2001&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. + * $LicenseInfo:firstyear=2001&license=viewergpl$ + * + * Copyright (c) 2001-2009, 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. + * 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 * - * 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. + * 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 * - * 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 + * 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. * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * 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$ */ diff --git a/indra/media_plugins/webkit/CMakeLists.txt b/indra/media_plugins/webkit/CMakeLists.txt index 4f183cddeb..1a559ed39c 100644 --- a/indra/media_plugins/webkit/CMakeLists.txt +++ b/indra/media_plugins/webkit/CMakeLists.txt @@ -36,6 +36,10 @@ set(media_plugin_webkit_SOURCE_FILES media_plugin_webkit.cpp ) +set(media_plugin_webkit_HEADER_FILES + volume_catcher.h + ) + set(media_plugin_webkit_LINK_LIBRARIES ${LLPLUGIN_LIBRARIES} ${MEDIA_PLUGIN_BASE_LIBRARIES} @@ -59,11 +63,18 @@ elseif (DARWIN) ${CORESERVICES_LIBRARY} # for Component Manager calls ${AUDIOUNIT_LIBRARY} # for AudioUnit calls ) +elseif (WINDOWS) + list(APPEND media_plugin_webkit_SOURCE_FILES windows_volume_catcher.cpp) else (LINUX AND PULSEAUDIO) # All other platforms use the dummy volume catcher for now. list(APPEND media_plugin_webkit_SOURCE_FILES dummy_volume_catcher.cpp) endif (LINUX AND PULSEAUDIO) +set_source_files_properties(${media_plugin_webkit_HEADER_FILES} + PROPERTIES HEADER_FILE_ONLY TRUE) + +list(APPEND media_plugin_webkit_SOURCE_FILES ${media_plugin_webkit_HEADER_FILES}) + add_library(media_plugin_webkit SHARED ${media_plugin_webkit_SOURCE_FILES} diff --git a/indra/media_plugins/webkit/windows_volume_catcher.cpp b/indra/media_plugins/webkit/windows_volume_catcher.cpp index 5fb84756ee..1c1ef0b42f 100644 --- a/indra/media_plugins/webkit/windows_volume_catcher.cpp +++ b/indra/media_plugins/webkit/windows_volume_catcher.cpp @@ -3,83 +3,283 @@ * @brief A Windows implementation of volume level control of all audio channels opened by a process. * * @cond - * $LicenseInfo:firstyear=2010&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. + * $LicenseInfo:firstyear=2010&license=viewergpl$ + * + * 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. + * 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 * - * 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. + * 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 * - * 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 + * 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. * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * 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 "volume_catcher.h" #include <windows.h> -#include "llsingleton.h" -class VolumeCatcherImpl : public LLSingleton<VolumeCatcherImpl> + +// +// Abstracts a Win32 mixer line and associated state +// for muting and changing volume on a given output +// +class Mixer +{ +public: + static Mixer* create(U32 index); + ~Mixer(); + + void setMute(bool mute); + void setVolume(F32 volume_left, F32 volume_right); + +private: + // use create(index) to create a Mixer + Mixer(HMIXER handle, U32 mute_control_id, U32 volume_control_id, U32 min_volume, U32 max_volume); + + HMIXER mHandle; + U32 mMuteControlID; // handle to mixer controller for muting + U32 mVolumeControlID; // handle to mixer controller for changing volume + U32 mMinVolume; // value that specifies minimum volume as reported by mixer + U32 mMaxVolume; // value that specifies maximum volume as reported by mixer +}; + +// factory function that attempts to create a Mixer object associated with a given mixer line index +// returns NULL if creation failed +// static +Mixer* Mixer::create(U32 index) +{ + // get handle to mixer object + HMIXER mixer_handle; + MMRESULT result = mixerOpen( &mixer_handle, + index, + 0, // HWND to call when state changes - not used + 0, // user data for callback - not used + MIXER_OBJECTF_MIXER ); + + if (result == MMSYSERR_NOERROR) + { + MIXERLINE mixer_line; + mixer_line.cbStruct = sizeof( MIXERLINE ); + + // try speakers first + mixer_line.dwComponentType = MIXERLINE_COMPONENTTYPE_DST_SPEAKERS; + + MMRESULT result = mixerGetLineInfo( reinterpret_cast< HMIXEROBJ >( mixer_handle ), + &mixer_line, + MIXER_OBJECTF_HMIXER | MIXER_GETLINEINFOF_COMPONENTTYPE ); + if (result != MMSYSERR_NOERROR) + { // failed - try headphones next + mixer_line.dwComponentType = MIXERLINE_COMPONENTTYPE_DST_HEADPHONES; + result = mixerGetLineInfo( reinterpret_cast< HMIXEROBJ >( mixer_handle ), + &mixer_line, + MIXER_OBJECTF_HMIXER | MIXER_GETLINEINFOF_COMPONENTTYPE ); + } + + if (result == MMSYSERR_NOERROR) + { // successfully found mixer line object, now use it to get volume and mute controls + + // reuse these objects to query for both volume and mute controls + MIXERCONTROL mixer_control; + MIXERLINECONTROLS mixer_line_controls; + mixer_line_controls.cbStruct = sizeof( MIXERLINECONTROLS ); + mixer_line_controls.dwLineID = mixer_line.dwLineID; + mixer_line_controls.cControls = 1; + mixer_line_controls.cbmxctrl = sizeof( MIXERCONTROL ); + mixer_line_controls.pamxctrl = &mixer_control; + + // first, query for mute + mixer_line_controls.dwControlType = MIXERCONTROL_CONTROLTYPE_MUTE; + + // get control id for mute controls + result = mixerGetLineControls( reinterpret_cast< HMIXEROBJ >( mixer_handle ), + &mixer_line_controls, + MIXER_OBJECTF_HMIXER | MIXER_GETLINECONTROLSF_ONEBYTYPE ); + if (result == MMSYSERR_NOERROR ) + { // we have a mute controls. Remember the mute control id and then query for + // volume controls using the same struct, but different dwControlType + + U32 mute_control_id = mixer_control.dwControlID; + mixer_line_controls.dwControlType = MIXERCONTROL_CONTROLTYPE_VOLUME; + result = mixerGetLineControls( reinterpret_cast< HMIXEROBJ >( mixer_handle ), + &mixer_line_controls, + MIXER_OBJECTF_HMIXER | MIXER_GETLINECONTROLSF_ONEBYTYPE ); + + if (result == MMSYSERR_NOERROR) + { // we have both mute and volume controls for this mixer, so we're keeping it + return new Mixer(mixer_handle, + mute_control_id, + mixer_control.dwControlID, + mixer_control.Bounds.dwMinimum, + mixer_control.Bounds.dwMaximum); + } + } + } + } + + // if we got here, we didn't successfully create a Mixer object + mixerClose(mixer_handle); + return NULL; +} + +Mixer::Mixer(HMIXER handle, U32 mute_control_id, U32 volume_control_id, U32 min_volume, U32 max_volume) +: mHandle(handle), + mMuteControlID(mute_control_id), + mVolumeControlID(volume_control_id), + mMinVolume(min_volume), + mMaxVolume(max_volume) +{} + +Mixer::~Mixer() +{} + +// toggle mute for this mixer +// if mute is set, then volume level will be ignored +void Mixer::setMute(bool mute) +{ + MIXERCONTROLDETAILS_BOOLEAN mixer_control_details_bool = { mute }; + MIXERCONTROLDETAILS mixer_control_details; + mixer_control_details.cbStruct = sizeof( MIXERCONTROLDETAILS ); + mixer_control_details.dwControlID = mMuteControlID; + mixer_control_details.cChannels = 1; + mixer_control_details.cMultipleItems = 0; + mixer_control_details.cbDetails = sizeof( MIXERCONTROLDETAILS_BOOLEAN ); + mixer_control_details.paDetails = &mixer_control_details_bool; + + mixerSetControlDetails( reinterpret_cast< HMIXEROBJ >( mHandle ), + &mixer_control_details, + MIXER_OBJECTF_HMIXER | MIXER_SETCONTROLDETAILSF_VALUE ); +} + +// set individual volume levels for left and right channels +// if mute is set, then these values will apply once mute is unset +void Mixer::setVolume(F32 volume_left, F32 volume_right) +{ + // assuming pan is in range [-1, 1] set volume levels accordingly + // if pan == -1 then volume_left_mixer = volume_left && volume_right_mixer = 0 + // if pan == 0 then volume_left_mixer = volume_left && volume_right_mixer = volume_right + // if pan == 1 then volume_left_mixer = 0 && volume_right_mixer = volume_right + U32 volume_left_mixer = (U32) + ((F32)mMinVolume + + (volume_left * ((F32)mMaxVolume - (F32)mMinVolume))); + U32 volume_right_mixer = (U32) + ((F32)mMinVolume + + (volume_right * ((F32)mMaxVolume - (F32)mMinVolume))); + + // pass volume levels on to mixer + MIXERCONTROLDETAILS_UNSIGNED mixer_control_details_unsigned[ 2 ] = { volume_left_mixer, volume_right_mixer }; + MIXERCONTROLDETAILS mixer_control_details; + mixer_control_details.cbStruct = sizeof( MIXERCONTROLDETAILS ); + mixer_control_details.dwControlID = mVolumeControlID; + mixer_control_details.cChannels = 2; + mixer_control_details.cMultipleItems = 0; + mixer_control_details.cbDetails = sizeof( MIXERCONTROLDETAILS_UNSIGNED ); + mixer_control_details.paDetails = &mixer_control_details_unsigned; + + mixerSetControlDetails( reinterpret_cast< HMIXEROBJ >( mHandle ), + &mixer_control_details, + MIXER_OBJECTF_HMIXER | MIXER_SETCONTROLDETAILSF_VALUE ); +} + +class VolumeCatcherImpl { -friend LLSingleton<VolumeCatcherImpl>; public: void setVolume(F32 volume); void setPan(F32 pan); + static VolumeCatcherImpl *getInstance(); private: // This is a singleton class -- both callers and the component implementation should use getInstance() to find the instance. VolumeCatcherImpl(); ~VolumeCatcherImpl(); - typedef void (WINAPI *set_volume_func_t)(F32); - typedef void (WINAPI *set_mute_func_t)(bool); - - set_volume_func_t mSetVolumeFunc; - set_mute_func_t mSetMuteFunc; - + static VolumeCatcherImpl *sInstance; + F32 mVolume; F32 mPan; + typedef std::vector<Mixer*> mixer_vector_t; + mixer_vector_t mMixers; }; + +VolumeCatcherImpl *VolumeCatcherImpl::sInstance = NULL; + +VolumeCatcherImpl *VolumeCatcherImpl::getInstance() +{ + if(!sInstance) + { + sInstance = new VolumeCatcherImpl; + } + + return sInstance; +} + VolumeCatcherImpl::VolumeCatcherImpl() : mVolume(1.0f), // default volume is max mPan(0.f) // default pan is centered { - HMODULE handle = ::LoadLibrary(L"winmm.dll"); - if(handle) + // for each reported mixer "device", create a proxy object and add to list + U32 num_mixers = mixerGetNumDevs(); + for (U32 mixer_index = 0; mixer_index < num_mixers; ++mixer_index) { - mSetVolumeFunc = (set_volume_func_t)::GetProcAddress(handle, "setPluginVolume"); - mSetMuteFunc = (set_mute_func_t)::GetProcAddress(handle, "setPluginMute"); + Mixer* mixerp = Mixer::create(mixer_index); + if (mixerp) + { + mMixers.push_back(mixerp); + } } } VolumeCatcherImpl::~VolumeCatcherImpl() { + for(mixer_vector_t::iterator it = mMixers.begin(), end_it = mMixers.end(); + it != end_it; + ++it) + { + delete *it; + *it = NULL; + } } void VolumeCatcherImpl::setVolume(F32 volume) { - mVolume = volume; + F32 left_volume = volume * min(1.f, 1.f - mPan); + F32 right_volume = volume * max(0.f, 1.f + mPan); + + for(mixer_vector_t::iterator it = mMixers.begin(), end_it = mMixers.end(); + it != end_it; + ++it) + { // set volume levels and mute for each mixer + // note that a muted mixer will ignore this volume level + + (*it)->setVolume(left_volume, right_volume); + + if (volume == 0.f && mVolume != 0.f) + { + (*it)->setMute(true); + } + else if (mVolume == 0.f && volume != 0.f) + { + (*it)->setMute(false); + } - if (mSetMuteFunc) - { - mSetMuteFunc(volume == 0.f); - } - if (mSetVolumeFunc) - { - mSetVolumeFunc(mVolume); } + mVolume = volume; } void VolumeCatcherImpl::setPan(F32 pan) @@ -114,4 +314,3 @@ void VolumeCatcher::pump() // No periodic tasks are necessary for this implementation. } - diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index ec465358fa..8bcf680876 100644 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -1295,6 +1295,8 @@ void LLAgent::stopAutoPilot(BOOL user_cancel) { resetAxes(mAutoPilotTargetFacing); } + // Restore previous flying state before invoking mAutoPilotFinishedCallback to allow + // callback function to change the flying state (like in near_sit_down_point()). // If the user cancelled, don't change the fly state if (!user_cancel) { diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index c8e8b9a221..21c07b97c5 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -862,7 +862,7 @@ bool LLAppViewer::init() minSpecs += "\n"; unsupported = true; } - if(gSysCPU.getMhz() < minCPU) + if(gSysCPU.getMHz() < minCPU) { minSpecs += LLNotifications::instance().getGlobalString("UnsupportedCPU"); minSpecs += "\n"; @@ -2539,7 +2539,7 @@ void LLAppViewer::writeSystemInfo() gDebugInfo["CPUInfo"]["CPUString"] = gSysCPU.getCPUString(); gDebugInfo["CPUInfo"]["CPUFamily"] = gSysCPU.getFamily(); - gDebugInfo["CPUInfo"]["CPUMhz"] = gSysCPU.getMhz(); + gDebugInfo["CPUInfo"]["CPUMhz"] = (S32)gSysCPU.getMHz(); gDebugInfo["CPUInfo"]["CPUAltivec"] = gSysCPU.hasAltivec(); gDebugInfo["CPUInfo"]["CPUSSE"] = gSysCPU.hasSSE(); gDebugInfo["CPUInfo"]["CPUSSE2"] = gSysCPU.hasSSE2(); @@ -2552,7 +2552,7 @@ void LLAppViewer::writeSystemInfo() // which may have been the intended grid. This can b gDebugInfo["GridName"] = LLViewerLogin::getInstance()->getGridLabel(); - // *FIX:Mani - move this ddown in llappviewerwin32 + // *FIX:Mani - move this down in llappviewerwin32 #ifdef LL_WINDOWS DWORD thread_id = GetCurrentThreadId(); gDebugInfo["MainloopThreadID"] = (S32)thread_id; diff --git a/indra/newview/llfavoritesbar.cpp b/indra/newview/llfavoritesbar.cpp index ba92c33d59..4c1e3461a5 100644 --- a/indra/newview/llfavoritesbar.cpp +++ b/indra/newview/llfavoritesbar.cpp @@ -75,7 +75,9 @@ public: mPosY(0), mPosZ(0), mLoaded(false) - {} + { + mHandle.bind(this); + } void setLandmarkID(const LLUUID& id) { mLandmarkID = id; } const LLUUID& getLandmarkId() const { return mLandmarkID; } @@ -122,17 +124,21 @@ private: if(LLLandmarkActions::getLandmarkGlobalPos(mLandmarkID, g_pos)) { LLLandmarkActions::getRegionNameAndCoordsFromPosGlobal(g_pos, - boost::bind(&LLLandmarkInfoGetter::landmarkNameCallback, this, _1, _2, _3, _4)); + boost::bind(&LLLandmarkInfoGetter::landmarkNameCallback, static_cast<LLHandle<LLLandmarkInfoGetter> >(mHandle), _1, _2, _3, _4)); } } - void landmarkNameCallback(const std::string& name, S32 x, S32 y, S32 z) + static void landmarkNameCallback(LLHandle<LLLandmarkInfoGetter> handle, const std::string& name, S32 x, S32 y, S32 z) { - mPosX = x; - mPosY = y; - mPosZ = z; - mName = name; - mLoaded = true; + LLLandmarkInfoGetter* getter = handle.get(); + if (getter) + { + getter->mPosX = x; + getter->mPosY = y; + getter->mPosZ = z; + getter->mName = name; + getter->mLoaded = true; + } } LLUUID mLandmarkID; @@ -141,6 +147,7 @@ private: S32 mPosY; S32 mPosZ; bool mLoaded; + LLRootHandle<LLLandmarkInfoGetter> mHandle; }; /** diff --git a/indra/newview/llfeaturemanager.cpp b/indra/newview/llfeaturemanager.cpp index 03cfc6764a..50b08f782a 100644 --- a/indra/newview/llfeaturemanager.cpp +++ b/indra/newview/llfeaturemanager.cpp @@ -2,25 +2,31 @@ * @file llfeaturemanager.cpp * @brief LLFeatureManager class implementation * - * $LicenseInfo:firstyear=2003&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. + * $LicenseInfo:firstyear=2003&license=viewergpl$ + * + * Copyright (c) 2003-2009, 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. + * 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 * - * 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. + * 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 * - * 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 + * 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. * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * 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$ */ @@ -39,13 +45,10 @@ #include "llsecondlifeurls.h" #include "llappviewer.h" -#include "llhttpclient.h" -#include "llnotificationsutil.h" #include "llviewercontrol.h" #include "llworld.h" #include "lldrawpoolterrain.h" #include "llviewertexturelist.h" -#include "llversioninfo.h" #include "llwindow.h" #include "llui.h" #include "llcontrol.h" @@ -59,20 +62,15 @@ #if LL_DARWIN const char FEATURE_TABLE_FILENAME[] = "featuretable_mac.txt"; -const char FEATURE_TABLE_VER_FILENAME[] = "featuretable_mac.%s.txt"; #elif LL_LINUX const char FEATURE_TABLE_FILENAME[] = "featuretable_linux.txt"; -const char FEATURE_TABLE_VER_FILENAME[] = "featuretable_linux.%s.txt"; #elif LL_SOLARIS const char FEATURE_TABLE_FILENAME[] = "featuretable_solaris.txt"; -const char FEATURE_TABLE_VER_FILENAME[] = "featuretable_solaris.%s.txt"; #else const char FEATURE_TABLE_FILENAME[] = "featuretable.txt"; -const char FEATURE_TABLE_VER_FILENAME[] = "featuretable.%s.txt"; #endif const char GPU_TABLE_FILENAME[] = "gpu_table.txt"; -const char GPU_TABLE_VER_FILENAME[] = "gpu_table.%s.txt"; LLFeatureInfo::LLFeatureInfo(const std::string& name, const BOOL available, const F32 level) : mValid(TRUE), mName(name), mAvailable(available), mRecommendedLevel(level) @@ -217,44 +215,22 @@ BOOL LLFeatureManager::loadFeatureTables() mSkippedFeatures.insert("RenderVBOEnable"); mSkippedFeatures.insert("RenderFogRatio"); - // first table is install with app - std::string app_path = gDirUtilp->getAppRODataDir(); - app_path += gDirUtilp->getDirDelimiter(); - app_path += FEATURE_TABLE_FILENAME; + std::string data_path = gDirUtilp->getAppRODataDir(); - // second table is downloaded with HTTP - std::string http_filename = llformat(FEATURE_TABLE_VER_FILENAME, LLVersionInfo::getVersion().c_str()); - std::string http_path = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, http_filename); + data_path += gDirUtilp->getDirDelimiter(); - // use HTTP table if it exists - std::string path; - if (gDirUtilp->fileExists(http_path)) - { - path = http_path; - } - else - { - path = app_path; - } - - - return parseFeatureTable(path); -} - - -BOOL LLFeatureManager::parseFeatureTable(std::string filename) -{ - llinfos << "Looking for feature table in " << filename << llendl; + data_path += FEATURE_TABLE_FILENAME; + lldebugs << "Looking for feature table in " << data_path << llendl; llifstream file; std::string name; U32 version; - file.open(filename); /*Flawfinder: ignore*/ + file.open(data_path); /*Flawfinder: ignore*/ if (!file) { - LL_WARNS("RenderInit") << "Unable to open feature table " << filename << LL_ENDL; + LL_WARNS("RenderInit") << "Unable to open feature table!" << LL_ENDL; return FALSE; } @@ -263,7 +239,7 @@ BOOL LLFeatureManager::parseFeatureTable(std::string filename) file >> version; if (name != "version") { - LL_WARNS("RenderInit") << filename << " does not appear to be a valid feature table!" << LL_ENDL; + LL_WARNS("RenderInit") << data_path << " does not appear to be a valid feature table!" << LL_ENDL; return FALSE; } @@ -326,44 +302,24 @@ BOOL LLFeatureManager::parseFeatureTable(std::string filename) 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; - - // second table is downloaded with HTTP - std::string http_filename = llformat(GPU_TABLE_VER_FILENAME, LLVersionInfo::getVersion().c_str()); - std::string http_path = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, http_filename); - - // use HTTP table if it exists - std::string path; - if (gDirUtilp->fileExists(http_path)) - { - path = http_path; - } - else - { - path = app_path; - } - - parseGPUTable(path); -} - - -void LLFeatureManager::parseGPUTable(std::string filename) -{ llifstream file; - file.open(filename); + file.open(data_path); /*Flawfinder: ignore*/ if (!file) { - LL_WARNS("RenderInit") << "Unable to open GPU table: " << filename << "!" << LL_ENDL; + LL_WARNS("RenderInit") << "Unable to open GPU table: " << data_path << "!" << LL_ENDL; return; } @@ -447,70 +403,6 @@ void LLFeatureManager::parseGPUTable(std::string filename) LL_WARNS("RenderInit") << "Couldn't match GPU to a class: " << gGLManager.getRawGLString() << LL_ENDL; } -// responder saves table into file -class LLHTTPFeatureTableResponder : public LLHTTPClient::Responder -{ -public: - - LLHTTPFeatureTableResponder(std::string filename) : - mFilename(filename) - { - } - - - virtual void completedRaw(U32 status, const std::string& reason, - const LLChannelDescriptors& channels, - const LLIOPipe::buffer_ptr_t& buffer) - { - if (isGoodStatus(status)) - { - // write to file - - llinfos << "writing feature table to " << mFilename << llendl; - - S32 file_size = buffer->countAfter(channels.in(), NULL); - if (file_size > 0) - { - // read from buffer - U8* copy_buffer = new U8[file_size]; - buffer->readAfter(channels.in(), NULL, copy_buffer, file_size); - - // write to file - LLAPRFile out(mFilename, LL_APR_WB); - out.write(copy_buffer, file_size); - out.close(); - } - } - - } - -private: - std::string mFilename; -}; - -void fetch_table(std::string table) -{ - const std::string base = gSavedSettings.getString("FeatureManagerHTTPTable"); - - const std::string filename = llformat(table.c_str(), LLVersionInfo::getVersion().c_str()); - - const std::string url = base + "/" + filename; - - const std::string path = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, filename); - - llinfos << "LLFeatureManager fetching " << url << " into " << path << llendl; - - LLHTTPClient::get(url, new LLHTTPFeatureTableResponder(path)); -} - -// fetch table(s) from a website (S3) -void LLFeatureManager::fetchHTTPTables() -{ - fetch_table(FEATURE_TABLE_VER_FILENAME); - fetch_table(GPU_TABLE_VER_FILENAME); -} - - void LLFeatureManager::cleanupFeatureTables() { std::for_each(mMaskList.begin(), mMaskList.end(), DeletePairedPointer()); diff --git a/indra/newview/llfloaterscriptdebug.cpp b/indra/newview/llfloaterscriptdebug.cpp index 118dea2c74..d6732a9d5c 100644 --- a/indra/newview/llfloaterscriptdebug.cpp +++ b/indra/newview/llfloaterscriptdebug.cpp @@ -2,25 +2,31 @@ * @file llfloaterscriptdebug.cpp * @brief Chat window for showing script errors and warnings * - * $LicenseInfo:firstyear=2006&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. + * $LicenseInfo:firstyear=2006&license=viewergpl$ + * + * Copyright (c) 2006-2009, 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. + * 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 * - * 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. + * 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 * - * 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 + * 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. * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * 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$ */ @@ -57,8 +63,6 @@ LLFloaterScriptDebug::LLFloaterScriptDebug(const LLSD& key) // avoid resizing of the window to match // the initial size of the tabbed-childs, whenever a tab is opened or closed mAutoResize = FALSE; - // enabled autocous blocks controling focus via LLFloaterReg::showInstance - setAutoFocus(FALSE); } LLFloaterScriptDebug::~LLFloaterScriptDebug() @@ -89,8 +93,7 @@ LLFloater* LLFloaterScriptDebug::addOutputWindow(const LLUUID &object_id) return NULL; LLFloater::setFloaterHost(host); - // prevent stealing focus, see EXT-8040 - LLFloater* floaterp = LLFloaterReg::showInstance("script_debug_output", object_id, FALSE); + LLFloater* floaterp = LLFloaterReg::showInstance("script_debug_output", object_id); LLFloater::setFloaterHost(NULL); return floaterp; @@ -142,9 +145,6 @@ LLFloaterScriptDebugOutput::LLFloaterScriptDebugOutput(const LLSD& object_id) mObjectID(object_id.asUUID()) { //LLUICtrlFactory::getInstance()->buildFloater(this, "floater_script_debug_panel.xml"); - - // enabled autocous blocks controling focus via LLFloaterReg::showInstance - setAutoFocus(FALSE); } BOOL LLFloaterScriptDebugOutput::postBuild() diff --git a/indra/newview/llfolderview.cpp b/indra/newview/llfolderview.cpp index 8d4d6a178a..c492bfcef1 100644 --- a/indra/newview/llfolderview.cpp +++ b/indra/newview/llfolderview.cpp @@ -1416,8 +1416,8 @@ void LLFolderView::startRenamingSelectedItem( void ) mRenamer->setVisible( TRUE ); // set focus will fail unless item is visible mRenamer->setFocus( TRUE ); - mRenamer->setTopLostCallback(boost::bind(onRenamerLost, _1)); - mRenamer->setFocusLostCallback(boost::bind(onRenamerLost, _1)); + mRenamer->setTopLostCallback(boost::bind(&LLFolderView::onRenamerLost, this, _1)); + mRenamer->setFocusLostCallback(boost::bind(&LLFolderView::onRenamerLost, this, _1)); gViewerWindow->addPopup(mRenamer); } } @@ -2386,9 +2386,9 @@ S32 LLFolderView::notify(const LLSD& info) /// Local function definitions ///---------------------------------------------------------------------------- -//static void LLFolderView::onRenamerLost( LLFocusableElement* renamer) { + mRenameItem = NULL; LLUICtrl* uictrl = dynamic_cast<LLUICtrl*>(renamer); if (uictrl) { diff --git a/indra/newview/llfolderview.h b/indra/newview/llfolderview.h index 9be83ba852..874723bb1a 100644 --- a/indra/newview/llfolderview.h +++ b/indra/newview/llfolderview.h @@ -2,25 +2,31 @@ * @file llfolderview.h * @brief Definition of the folder view collection of classes. * - * $LicenseInfo:firstyear=2001&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. + * $LicenseInfo:firstyear=2001&license=viewergpl$ + * + * Copyright (c) 2001-2009, 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. + * 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 * - * 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. + * 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 * - * 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 + * 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. * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * 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$ */ @@ -90,7 +96,6 @@ public: Mandatory<LLPanel*> parent_panel; Optional<LLUUID> task_id; Optional<std::string> title; - Optional<bool> use_label_suffix; }; LLFolderView(const Params&); virtual ~LLFolderView( void ); @@ -159,7 +164,7 @@ public: virtual S32 extendSelection(LLFolderViewItem* selection, LLFolderViewItem* last_selected, LLDynamicArray<LLFolderViewItem*>& items); - virtual std::set<LLUUID> getSelectionList() const; + virtual BOOL getSelectionList(std::set<LLUUID> &selection) const; // make sure if ancestor is selected, descendents are not void sanitizeSelection(); @@ -225,7 +230,6 @@ public: EAcceptance* accept, std::string& tooltip_msg); /*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); - /*virtual*/ void onMouseLeave(S32 x, S32 y, MASK mask) { setShowSelectionContext(FALSE); } virtual void draw(); virtual void deleteAllChildren(); @@ -256,8 +260,6 @@ public: BOOL needsAutoSelect() { return mNeedsAutoSelect && !mAutoSelectOverride; } BOOL needsAutoRename() { return mNeedsAutoRename; } void setNeedsAutoRename(BOOL val) { mNeedsAutoRename = val; } - void setPinningSelectedItem(BOOL val) { mPinningSelectedItem = val; } - void setAutoSelectOverride(BOOL val) { mAutoSelectOverride = val; } void setCallbackRegistrar(LLUICtrl::CommitCallbackRegistry::ScopedRegistrar* registrar) { mCallbackRegistrar = registrar; } @@ -270,7 +272,6 @@ public: virtual S32 notify(const LLSD& info) ; void setEnableScroll(bool enable_scroll) { mEnableScroll = enable_scroll; } - bool useLabelSuffix() { return mUseLabelSuffix; } private: void updateRenamerPosition(); @@ -286,8 +287,6 @@ protected: bool selectFirstItem(); bool selectLastItem(); - BOOL addNoOptions(LLMenuGL* menu) const; - protected: LLHandle<LLView> mPopupMenuHandle; @@ -309,7 +308,6 @@ protected: BOOL mNeedsAutoSelect; BOOL mAutoSelectOverride; BOOL mNeedsAutoRename; - bool mUseLabelSuffix; BOOL mDebugFilters; U32 mSortOrder; diff --git a/indra/newview/llhudrender.cpp b/indra/newview/llhudrender.cpp index 1156e764a1..5b653638f2 100644 --- a/indra/newview/llhudrender.cpp +++ b/indra/newview/llhudrender.cpp @@ -2,25 +2,31 @@ * @file llhudrender.cpp * @brief LLHUDRender class implementation * - * $LicenseInfo:firstyear=2002&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. + * $LicenseInfo:firstyear=2002&license=viewergpl$ + * + * Copyright (c) 2002-2009, 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. + * 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 * - * 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. + * 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 * - * 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 + * 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. * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * 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$ */ @@ -72,8 +78,8 @@ void hud_render_text(const LLWString &wstr, const LLVector3 &pos_agent, LLVector3 up_axis; if (orthographic) { - right_axis.setVec(0.f, -1.f / gViewerWindow->getWorldViewHeightScaled(), 0.f); - up_axis.setVec(0.f, 0.f, 1.f / gViewerWindow->getWorldViewHeightScaled()); + right_axis.setVec(0.f, -1.f / gViewerWindow->getWorldViewHeightRaw(), 0.f); + up_axis.setVec(0.f, 0.f, 1.f / gViewerWindow->getWorldViewHeightRaw()); } else { diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 10146ee9d3..4357c7d426 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -1459,7 +1459,13 @@ void LLCallDialogManager::onVoiceChannelChanged(const LLUUID &session_id) } sSession = session; - sSession->mVoiceChannel->setStateChangedCallback(boost::bind(LLCallDialogManager::onVoiceChannelStateChanged, _1, _2, _3, _4)); + + static boost::signals2::connection prev_channel_state_changed_connection; + // disconnect previously connected callback to avoid have invalid sSession in onVoiceChannelStateChanged() + prev_channel_state_changed_connection.disconnect(); + prev_channel_state_changed_connection = + sSession->mVoiceChannel->setStateChangedCallback(boost::bind(LLCallDialogManager::onVoiceChannelStateChanged, _1, _2, _3, _4)); + if(sCurrentSessionlName != session->mName) { sPreviousSessionlName = sCurrentSessionlName; diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 3071ef3b71..b85bf0d518 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -2680,6 +2680,13 @@ void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags) { // This is the lost+found folder. mItems.push_back(std::string("Empty Lost And Found")); + + mDisabledItems.push_back(std::string("New Folder")); + mDisabledItems.push_back(std::string("New Script")); + mDisabledItems.push_back(std::string("New Note")); + mDisabledItems.push_back(std::string("New Gesture")); + mDisabledItems.push_back(std::string("New Clothes")); + mDisabledItems.push_back(std::string("New Body Parts")); } if(trash_id == mUUID) diff --git a/indra/newview/llmoveview.cpp b/indra/newview/llmoveview.cpp index 4ccf5e1c7b..7df5a33313 100644 --- a/indra/newview/llmoveview.cpp +++ b/indra/newview/llmoveview.cpp @@ -200,7 +200,11 @@ void LLFloaterMove::setFlyingMode(BOOL fly) if (instance) { instance->setFlyingModeImpl(fly); - BOOL is_sitting = isAgentAvatarValid() && gAgentAvatarp->isSitting(); + LLVOAvatarSelf* avatar_object = gAgent.getAvatarObject(); + bool is_sitting = avatar_object + && (avatar_object->getRegion() != NULL) + && (!avatar_object->isDead()) + && avatar_object->isSitting(); instance->showModeButtons(!fly && !is_sitting); } if (fly) @@ -697,6 +701,7 @@ void LLPanelStandStopFlying::onStandButtonClick() gAgent.setControlFlags(AGENT_CONTROL_STAND_UP); setFocus(FALSE); // EXT-482 + mStandButton->setVisible(FALSE); // force visibility changing to avoid seeing Stand & Move buttons at once. } void LLPanelStandStopFlying::onStopFlyingButtonClick() diff --git a/indra/newview/llpanelnearbymedia.cpp b/indra/newview/llpanelnearbymedia.cpp index 93ebae334f..79786c06d9 100644 --- a/indra/newview/llpanelnearbymedia.cpp +++ b/indra/newview/llpanelnearbymedia.cpp @@ -1010,7 +1010,7 @@ void LLPanelNearByMedia::updateControls() if (NULL == impl) { // Just means it hasn't started yet - showBasicControls(false, false, false); + showBasicControls(false, false, false, false, 0); } else if (impl->isMediaTimeBased()) { @@ -1022,7 +1022,11 @@ void LLPanelNearByMedia::updateControls() } else { // non-time-based parcel media - showBasicControls(LLViewerMedia::isParcelMediaPlaying(), false, false); + showBasicControls(LLViewerMedia::isParcelMediaPlaying(), + false, + false, + impl->getVolume() == 0.0, + impl->getVolume()); } } } @@ -1045,19 +1049,28 @@ void LLPanelNearByMedia::updateControls() else { showBasicControls(!impl->isMediaDisabled(), ! impl->isParcelMedia(), // include_zoom - LLViewerMediaFocus::getInstance()->isZoomed()); + LLViewerMediaFocus::getInstance()->isZoomed(), + impl->getVolume() == 0.0, + impl->getVolume()); } } } } -void LLPanelNearByMedia::showBasicControls(bool playing, bool include_zoom, bool is_zoomed) +void LLPanelNearByMedia::showBasicControls(bool playing, bool include_zoom, bool is_zoomed, bool muted, F32 volume) { mStopCtrl->setVisible(playing); mPlayCtrl->setVisible(!playing); mPauseCtrl->setVisible(false); - mMuteCtrl->setVisible(false); +#ifdef PER_MEDIA_VOLUME + mVolumeSliderCtrl->setVisible(true); + mMuteCtrl->setVisible(true); + mMuteBtn->setValue(muted); + mVolumeSlider->setValue(volume); +#else mVolumeSliderCtrl->setVisible(false); + mMuteCtrl->setVisible(false); +#endif mZoomCtrl->setVisible(include_zoom && !is_zoomed); mUnzoomCtrl->setVisible(include_zoom && is_zoomed); mStopCtrl->setEnabled(true); @@ -1156,7 +1169,7 @@ void LLPanelNearByMedia::onClickSelectedMediaMute() else { LLViewerMediaImpl* impl = (selected_media_id == PARCEL_MEDIA_LIST_ITEM_UUID) ? ((LLViewerMediaImpl*)LLViewerParcelMedia::getParcelMedia()) : LLViewerMedia::getMediaImplFromTextureID(selected_media_id); - if (NULL != impl && impl->isMediaTimeBased()) + if (NULL != impl) { F32 volume = impl->getVolume(); if(volume > 0.0) @@ -1187,7 +1200,7 @@ void LLPanelNearByMedia::onCommitSelectedMediaVolume() else { LLViewerMediaImpl* impl = (selected_media_id == PARCEL_MEDIA_LIST_ITEM_UUID) ? ((LLViewerMediaImpl*)LLViewerParcelMedia::getParcelMedia()) : LLViewerMedia::getMediaImplFromTextureID(selected_media_id); - if (NULL != impl && impl->isMediaTimeBased()) + if (NULL != impl) { impl->setVolume(mVolumeSlider->getValueF32()); } diff --git a/indra/newview/llpanelnearbymedia.h b/indra/newview/llpanelnearbymedia.h index 7c07867df3..3cecf8e40c 100644 --- a/indra/newview/llpanelnearbymedia.h +++ b/indra/newview/llpanelnearbymedia.h @@ -140,7 +140,7 @@ private: bool shouldShow(LLViewerMediaImpl* impl); - void showBasicControls(bool playing, bool include_zoom, bool is_zoomed); + void showBasicControls(bool playing, bool include_zoom, bool is_zoomed, bool muted, F32 volume); void showTimeBasedControls(bool playing, bool include_zoom, bool is_zoomed, bool muted, F32 volume); void showDisabledControls(); void updateControls(); diff --git a/indra/newview/llpaneloutfitedit.cpp b/indra/newview/llpaneloutfitedit.cpp index d78a448acb..ba6473839a 100644 --- a/indra/newview/llpaneloutfitedit.cpp +++ b/indra/newview/llpaneloutfitedit.cpp @@ -133,10 +133,6 @@ mRemoveFromOutfitBtn(NULL), mLookObserver(NULL) mLookItemTypes.push_back(LLLookItemType()); } - // TODO: make these strings translatable - mLookItemTypes[LIT_ALL] = LLLookItemType("All Items", ALL_ITEMS_MASK); - mLookItemTypes[LIT_WEARABLE] = LLLookItemType("Shape & Clothing", WEARABLE_MASK); - mLookItemTypes[LIT_ATTACHMENT] = LLLookItemType("Attachments", ATTACHMENT_MASK); } @@ -159,10 +155,15 @@ LLPanelOutfitEdit::~LLPanelOutfitEdit() BOOL LLPanelOutfitEdit::postBuild() { // gInventory.isInventoryUsable() no longer needs to be tested per Richard's fix for race conditions between inventory and panels - + + mLookItemTypes[LIT_ALL] = LLLookItemType(getString("Filter.All"), ALL_ITEMS_MASK); + mLookItemTypes[LIT_WEARABLE] = LLLookItemType(getString("Filter.Clothes/Body"), WEARABLE_MASK); + mLookItemTypes[LIT_ATTACHMENT] = LLLookItemType(getString("Filter.Objects"), ATTACHMENT_MASK); + mCurrentOutfitName = getChild<LLTextBox>("curr_outfit_name"); childSetCommitCallback("add_btn", boost::bind(&LLPanelOutfitEdit::showAddWearablesPanel, this), NULL); + childSetCommitCallback("filter_button", boost::bind(&LLPanelOutfitEdit::showWearablesFilter, this), NULL); mLookContents = getChild<LLScrollListCtrl>("look_items_list"); mLookContents->sortByColumn("look_item_sort", TRUE); @@ -174,7 +175,7 @@ BOOL LLPanelOutfitEdit::postBuild() mInventoryItemsPanel->setSelectCallback(boost::bind(&LLPanelOutfitEdit::onInventorySelectionChange, this, _1, _2)); mInventoryItemsPanel->getRootFolder()->setReshapeCallback(boost::bind(&LLPanelOutfitEdit::onInventorySelectionChange, this, _1, _2)); - LLComboBox* type_filter = getChild<LLComboBox>("inventory_filter"); + LLComboBox* type_filter = getChild<LLComboBox>("filter_wearables_combobox"); type_filter->setCommitCallback(boost::bind(&LLPanelOutfitEdit::onTypeFilterChanged, this, _1)); type_filter->removeall(); for (U32 i = 0; i < mLookItemTypes.size(); ++i) @@ -236,6 +237,11 @@ void LLPanelOutfitEdit::showAddWearablesPanel() childSetVisible("add_wearables_panel", childGetValue("add_btn")); } +void LLPanelOutfitEdit::showWearablesFilter() +{ + childSetVisible("filter_combobox_panel", childGetValue("filter_button")); +} + void LLPanelOutfitEdit::saveOutfit(bool as_new) { if (!as_new && LLAppearanceMgr::getInstance()->updateBaseOutfit()) @@ -457,20 +463,18 @@ void LLPanelOutfitEdit::onInventorySelectionChange(const std::deque<LLFolderView void LLPanelOutfitEdit::onOutfitItemSelectionChange(void) { - S32 left_offset = -4; - S32 top_offset = -10; LLScrollListItem* item = mLookContents->getLastSelectedItem(); if (!item) return; - LLRect rect = item->getRect(); - LLRect btn_rect( - left_offset + rect.mRight - 50, - top_offset + rect.mTop, - left_offset + rect.mRight - 30, - top_offset + rect.mBottom); + LLRect item_rect; + mLookContents->localRectToOtherView(item->getRect(), &item_rect, getChild<LLUICtrl>("outfit_wearables_panel")); + + // TODO button(and item list) should be removed (when new widget is ready) + LLRect btn_rect = mEditWearableBtn->getRect(); + btn_rect.set(item_rect.mRight - btn_rect.getWidth(), item_rect.mTop, item_rect.mRight, item_rect.mBottom); - mEditWearableBtn->setRect(btn_rect); + mEditWearableBtn->setShape(btn_rect); mEditWearableBtn->setEnabled(TRUE); if (!mEditWearableBtn->getVisible()) diff --git a/indra/newview/llpaneloutfitedit.h b/indra/newview/llpaneloutfitedit.h index fa92d4c314..69e8016534 100644 --- a/indra/newview/llpaneloutfitedit.h +++ b/indra/newview/llpaneloutfitedit.h @@ -87,6 +87,7 @@ public: // only update the location if there is none already available. void showAddWearablesPanel(); + void showWearablesFilter(); void saveOutfit(bool as_new = false); void showSaveMenu(); diff --git a/indra/newview/llpanelprimmediacontrols.cpp b/indra/newview/llpanelprimmediacontrols.cpp index 83244edb8e..5209d50755 100644 --- a/indra/newview/llpanelprimmediacontrols.cpp +++ b/indra/newview/llpanelprimmediacontrols.cpp @@ -66,10 +66,6 @@ #include "llwindow.h" #include "llfloatertools.h" // to enable hide if build tools are up -#if defined(LL_DARWIN) || (defined(LL_WINDOW) && (! defined(LL_RELEASE_FOR_DOWNLOAD)) ) -#define PER_MEDIA_VOLUME -#endif - // Functions pulled from pipeline.cpp glh::matrix4f glh_get_current_modelview(); glh::matrix4f glh_get_current_projection(); @@ -467,10 +463,21 @@ void LLPanelPrimMediaControls::updateShape() mSkipBackCtrl->setEnabled(FALSE); #ifdef PER_MEDIA_VOLUME + // these should be pulled up above the pluginSupportsMediaTime + // if check once we always have PER_MEDIA_VOLUME turned on mVolumeCtrl->setVisible(has_focus); mVolumeCtrl->setEnabled(has_focus); mVolumeSliderCtrl->setEnabled(has_focus && shouldVolumeSliderBeVisible()); mVolumeSliderCtrl->setVisible(has_focus && shouldVolumeSliderBeVisible()); + + if(media_impl->getVolume() <= 0.0) + { + mMuteBtn->setToggleState(true); + } + else + { + mMuteBtn->setToggleState(false); + } #else mVolumeCtrl->setVisible(FALSE); mVolumeSliderCtrl->setVisible(FALSE); diff --git a/indra/newview/llspeakers.cpp b/indra/newview/llspeakers.cpp index 4573520647..ba6a44dff4 100644 --- a/indra/newview/llspeakers.cpp +++ b/indra/newview/llspeakers.cpp @@ -84,7 +84,7 @@ void LLSpeaker::onAvatarNameLookup(const LLUUID& id, const std::string& first, c bool LLSpeaker::isInVoiceChannel() { - return mStatus == LLSpeaker::STATUS_VOICE_ACTIVE || mStatus == LLSpeaker::STATUS_MUTED; + return mStatus <= LLSpeaker::STATUS_VOICE_ACTIVE || mStatus == LLSpeaker::STATUS_MUTED; } LLSpeakerUpdateModeratorEvent::LLSpeakerUpdateModeratorEvent(LLSpeaker* source) diff --git a/indra/newview/lltoolpie.cpp b/indra/newview/lltoolpie.cpp index a9bbee784d..ae244cd8a1 100644 --- a/indra/newview/lltoolpie.cpp +++ b/indra/newview/lltoolpie.cpp @@ -1267,6 +1267,7 @@ bool LLToolPie::handleMediaClick(const LLPickInfo& pick) if (!parcel || objectp.isNull() || + objectp->isHUDAttachment() || pick.mObjectFace < 0 || pick.mObjectFace >= objectp->getNumTEs()) { diff --git a/indra/newview/llviewerjoystick.cpp b/indra/newview/llviewerjoystick.cpp index e1dd72dddc..240a539f2e 100644 --- a/indra/newview/llviewerjoystick.cpp +++ b/indra/newview/llviewerjoystick.cpp @@ -2,25 +2,31 @@ * @file llviewerjoystick.cpp * @brief Joystick / NDOF device functionality. * - * $LicenseInfo:firstyear=2002&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. + * $LicenseInfo:firstyear=2002&license=viewergpl$ + * + * Copyright (c) 2002-2009, 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. + * 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 * - * 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. + * 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 * - * 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 + * 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. * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * 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$ */ @@ -51,6 +57,9 @@ #define RY_I 5 #define RZ_I 3 +// flycam translations in build mode should be reduced +const F32 BUILDMODE_FLYCAM_T_SCALE = 3.f; + // minimum time after setting away state before coming back const F32 MIN_AFK_TIME = 2.f; @@ -915,15 +924,14 @@ void LLViewerJoystick::moveFlycam(bool reset) cur_delta[i] = llmin(cur_delta[i]+dead_zone[i], 0.f); } - // We may want to scale camera movements up or down in build mode. + // we need smaller camera movements in build mode // NOTE: this needs to remain after the deadzone calculation, otherwise // we have issues with flycam "jumping" when the build dialog is opened/closed -Nyx if (in_build_mode) { if (i == X_I || i == Y_I || i == Z_I) { - static LLCachedControl<F32> build_mode_scale(gSavedSettings,"FlycamBuildModeScale"); - cur_delta[i] *= build_mode_scale; + cur_delta[i] /= BUILDMODE_FLYCAM_T_SCALE; } } diff --git a/indra/newview/llviewermedia.h b/indra/newview/llviewermedia.h index e829d7a5b4..bc6716697e 100644 --- a/indra/newview/llviewermedia.h +++ b/indra/newview/llviewermedia.h @@ -46,6 +46,12 @@ #include "llurl.h" + +#if defined(LL_DARWIN) || (LL_WINDOWS && !LL_RELEASE_FOR_DOWNLOAD ) +#define PER_MEDIA_VOLUME +#endif + + class LLViewerMediaImpl; class LLUUID; class LLViewerMediaTexture; diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 0cd69d892f..1fcbbd7fd4 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -116,6 +116,11 @@ #include "llnotificationmanager.h" // +#if LL_MSVC +// disable boost::lexical_cast warning +#pragma warning (disable:4702) +#endif + // // Constants // @@ -1631,6 +1636,18 @@ bool LLOfferInfo::inventory_task_offer_callback(const LLSD& notification, const return false; } +class LLPostponedOfferNotification: public LLPostponedNotification +{ +protected: + /* virtual */ + void modifyNotificationParams() + { + LLSD substitutions = mParams.substitutions; + substitutions["NAME"] = mName; + mParams.substitutions = substitutions; + } +}; + void inventory_offer_handler(LLOfferInfo* info) { //Until throttling is implmented, busy mode should reject inventory instead of silently @@ -1780,7 +1797,10 @@ void inventory_offer_handler(LLOfferInfo* info) // Inform user that there is a script floater via toast system { payload["give_inventory_notification"] = TRUE; - LLNotificationPtr notification = LLNotifications::instance().add(p.payload(payload)); + LLNotification::Params params(p.name); + params.substitutions = p.substitutions; + params.payload = p.payload; + LLPostponedNotification::add<LLPostponedOfferNotification>( params, info->mFromID, false); } } } @@ -2552,7 +2572,11 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) payload["from_id"] = from_id; payload["lure_id"] = session_id; payload["godlike"] = FALSE; - LLNotificationsUtil::add("TeleportOffered", args, payload); + + LLNotification::Params params("TeleportOffered"); + params.substitutions = args; + params.payload = payload; + LLPostponedNotification::add<LLPostponedOfferNotification>( params, from_id, false); } } break; @@ -2621,7 +2645,10 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) else { args["[MESSAGE]"] = message; - LLNotificationsUtil::add("OfferFriendship", args, payload); + LLNotification::Params params("OfferFriendship"); + params.substitutions = args; + params.payload = payload; + LLPostponedNotification::add<LLPostponedOfferNotification>( params, from_id, false); } } } @@ -4403,6 +4430,9 @@ void process_avatar_sit_response(LLMessageSystem *mesgsys, void **user_data) } gAgentCamera.setForceMouselook(force_mouselook); + // Forcing turning off flying here to prevent flying after pressing "Stand" + // to stand up from an object. See EXT-1655. + gAgent.setFlying(FALSE); LLViewerObject* object = gObjectList.findObject(sitObjectID); if (object) diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index af833db9c3..5100f4e59a 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -66,6 +66,7 @@ #include "llkeyframewalkmotion.h" #include "llmutelist.h" #include "llmoveview.h" +#include "llnotificationsutil.h" #include "llquantize.h" #include "llregionhandle.h" #include "llresmgr.h" @@ -101,6 +102,8 @@ #include <boost/lexical_cast.hpp> +#define DISPLAY_AVATAR_LOAD_TIMES + using namespace LLVOAvatarDefines; //----------------------------------------------------------------------------- @@ -656,6 +659,7 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id, mNameMute(FALSE), mRenderGroupTitles(sRenderGroupTitles), mNameAppearance(FALSE), + mNameCloud(FALSE), mFirstTEMessageReceived( FALSE ), mFirstAppearanceMessageReceived( FALSE ), mCulled( FALSE ), @@ -2764,25 +2768,20 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last) if (mNameText.notNull() && firstname && lastname) { - BOOL is_away = mSignaledAnimations.find(ANIM_AGENT_AWAY) != mSignaledAnimations.end(); - BOOL is_busy = mSignaledAnimations.find(ANIM_AGENT_BUSY) != mSignaledAnimations.end(); - BOOL is_appearance = mSignaledAnimations.find(ANIM_AGENT_CUSTOMIZE) != mSignaledAnimations.end(); - BOOL is_muted; - if (isSelf()) - { - is_muted = FALSE; - } - else - { - is_muted = LLMuteList::getInstance()->isMuted(getID()); - } + const BOOL is_away = mSignaledAnimations.find(ANIM_AGENT_AWAY) != mSignaledAnimations.end(); + const BOOL is_busy = mSignaledAnimations.find(ANIM_AGENT_BUSY) != mSignaledAnimations.end(); + const BOOL is_appearance = mSignaledAnimations.find(ANIM_AGENT_CUSTOMIZE) != mSignaledAnimations.end(); + const BOOL is_muted = isSelf() ? FALSE : LLMuteList::getInstance()->isMuted(getID()); + const BOOL is_cloud = getIsCloud(); if (mNameString.empty() || new_name || (!title && !mTitle.empty()) || (title && mTitle != title->getString()) || (is_away != mNameAway || is_busy != mNameBusy || is_muted != mNameMute) - || is_appearance != mNameAppearance) + || is_appearance != mNameAppearance + || is_cloud != mNameCloud + ) { std::string line; if (!sRenderGroupTitles) @@ -2836,7 +2835,12 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last) } line += ")"; } - if (is_appearance) + if (is_cloud) + { + line += "\n"; + line += "(" + LLTrans::getString("LoadingData") + ")"; + } + else if (is_appearance) { line += "\n"; line += LLTrans::getString("AvatarEditingAppearance"); @@ -2845,6 +2849,7 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last) mNameBusy = is_busy; mNameMute = is_muted; mNameAppearance = is_appearance; + mNameCloud = is_cloud; mTitle = title ? title->getString() : ""; LLStringFn::replace_ascii_controlchars(mTitle,LL_UNKNOWN_CHAR); mNameString = utf8str_to_wstring(line); @@ -5607,8 +5612,6 @@ void LLVOAvatar::sitDown(BOOL bSitting) //----------------------------------------------------------------------------- void LLVOAvatar::sitOnObject(LLViewerObject *sit_object) { - sitDown(TRUE); - if (isSelf()) { // Might be first sit @@ -5641,6 +5644,9 @@ void LLVOAvatar::sitOnObject(LLViewerObject *sit_object) mDrawable->mXform.setRotation(mDrawable->getWorldRotation() * inv_obj_rot); gPipeline.markMoved(mDrawable, TRUE); + // Notice that removing sitDown() from here causes avatars sitting on + // objects to be not rendered for new arrivals. See EXT-6835 and EXT-1655. + sitDown(TRUE); mRoot.getXform()->setParent(&sit_object->mDrawable->mXform); // LLVOAvatar::sitOnObject mRoot.setPosition(getPosition()); mRoot.updateWorldMatrixChildren(); @@ -5812,27 +5818,29 @@ BOOL LLVOAvatar::isVisible() const && (mDrawable->isVisible() || mIsDummy); } -// call periodically to keep isFullyLoaded up to date. -// returns true if the value has changed. -BOOL LLVOAvatar::updateIsFullyLoaded() +// Determine if we have enough avatar data to render +BOOL LLVOAvatar::getIsCloud() { - // a "heuristic" to determine if we have enough avatar data to render - // (to avoid rendering a "Ruth" - DEV-3168) - BOOL loading = FALSE; - - // do we have a shape? + // Do we have a shape? if (visualParamWeightsAreDefault()) { - loading = TRUE; + return TRUE; } if (!isTextureDefined(TEX_LOWER_BAKED) || !isTextureDefined(TEX_UPPER_BAKED) || !isTextureDefined(TEX_HEAD_BAKED)) { - loading = TRUE; + return TRUE; } - + return FALSE; +} + +// call periodically to keep isFullyLoaded up to date. +// returns true if the value has changed. +BOOL LLVOAvatar::updateIsFullyLoaded() +{ + const BOOL loading = getIsCloud(); updateRuthTimer(loading); return processFullyLoadedChange(loading); } @@ -5847,6 +5855,7 @@ void LLVOAvatar::updateRuthTimer(bool loading) if (mPreviousFullyLoaded) { mRuthTimer.reset(); + mRuthDebugTimer.reset(); } const F32 LOADING_TIMEOUT = 120.f; @@ -5875,7 +5884,17 @@ BOOL LLVOAvatar::processFullyLoadedChange(bool loading) mFullyLoaded = (mFullyLoadedTimer.getElapsedTimeF32() > PAUSE); - +#ifdef DISPLAY_AVATAR_LOAD_TIMES + if (!mPreviousFullyLoaded && !loading && mFullyLoaded) + { + llinfos << "Avatar '" << getFullname() << "' resolved in " << mRuthDebugTimer.getElapsedTimeF32() << " seconds." << llendl; + LLSD args; + args["TIME"] = llformat("%d",(U32)mRuthDebugTimer.getElapsedTimeF32()); + args["NAME"] = getFullname(); + LLNotificationsUtil::add("AvatarRezNotification",args); + } +#endif + // did our loading state "change" from last call? const S32 UPDATE_RATE = 30; BOOL changed = diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index 0934f5df36..8da4c226ed 100644 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -1,27 +1,33 @@ /** * @file llvoavatar.h - * @brief Declaration of LLVOAvatar class which is a derivation of + * @brief Declaration of LLVOAvatar class which is a derivation fo * LLViewerObject * - * $LicenseInfo:firstyear=2001&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. + * $LicenseInfo:firstyear=2001&license=viewergpl$ + * + * Copyright (c) 2001-2009, 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. + * 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 * - * 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. + * 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 * - * 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 + * 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. * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * 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$ */ @@ -65,10 +71,9 @@ class LLTexGlobalColor; class LLVOAvatarBoneInfo; class LLVOAvatarSkeletonInfo; -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//------------------------------------------------------------------------ // LLVOAvatar -// -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//------------------------------------------------------------------------ class LLVOAvatar : public LLViewerObject, public LLCharacter @@ -133,13 +138,13 @@ public: virtual void updateSpatialExtents(LLVector3& newMin, LLVector3 &newMax); virtual 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 + 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 @@ -152,14 +157,12 @@ public: virtual LLJoint* getCharacterJoint(U32 num); virtual BOOL allocateCharacterJoints(U32 num); - virtual 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(); - void dumpAnimationState(); virtual LLJoint* getJoint(const std::string &name); virtual LLJoint* getRootJoint() { return &mRoot; } @@ -217,8 +220,8 @@ public: public: static S32 sRenderName; static BOOL sRenderGroupTitles; - static U32 sMaxVisible; //(affected by control "RenderAvatarMaxVisible") - static F32 sRenderDistance; //distance at which avatars will render. + static S32 sMaxVisible; + static F32 sRenderDistance; //distance at which avatars will render (affected by control "RenderAvatarMaxVisible") 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 @@ -243,7 +246,6 @@ public: //-------------------------------------------------------------------- public: BOOL isFullyLoaded() const; - bool visualParamWeightsAreDefault(); protected: virtual BOOL getIsCloud(); BOOL updateIsFullyLoaded(); @@ -257,8 +259,7 @@ private: S32 mFullyLoadedFrameCounter; LLFrameTimer mFullyLoadedTimer; LLFrameTimer mRuthTimer; -protected: - LLFrameTimer mInvisibleTimer; + LLFrameTimer mRuthDebugTimer; // For tracking how long it takes for av to rez /** State ** ** @@ -461,9 +462,7 @@ public: //-------------------------------------------------------------------- public: virtual BOOL isTextureDefined(LLVOAvatarDefines::ETextureIndex type, U32 index = 0) const; - virtual BOOL isTextureVisible(LLVOAvatarDefines::ETextureIndex type, U32 index = 0) const; - virtual BOOL isTextureVisible(LLVOAvatarDefines::ETextureIndex type, LLWearable *wearable) const; - + BOOL isTextureVisible(LLVOAvatarDefines::ETextureIndex index) const; protected: BOOL isFullyBaked(); static BOOL areAllNearbyInstancesBaked(S32& grey_avatars); @@ -495,8 +494,7 @@ protected: }; typedef std::vector<BakedTextureData> bakedtexturedata_vec_t; bakedtexturedata_vec_t mBakedTextureDatas; - LLLoadedCallbackEntry::source_callback_list_t mCallbackTextureList ; - BOOL mLoadedCallbacksPaused; + //-------------------------------------------------------------------- // Local Textures //-------------------------------------------------------------------- @@ -516,7 +514,7 @@ private: virtual const LLTextureEntry* getTexEntry(const U8 te_num) const; virtual void setTexEntry(const U8 index, const LLTextureEntry &te); - void checkTextureLoading() ; + //-------------------------------------------------------------------- // Layers //-------------------------------------------------------------------- @@ -605,9 +603,8 @@ public: // Appearance morphing //-------------------------------------------------------------------- public: - BOOL getIsAppearanceAnimating() const { return mAppearanceAnimating; } -private: BOOL mAppearanceAnimating; +private: LLFrameTimer mAppearanceMorphTimer; F32 mLastAppearanceBlendTime; @@ -649,7 +646,7 @@ public: **/ public: - virtual BOOL isWearingWearableType(LLWearableType::EType type ) const; + virtual BOOL isWearingWearableType(EWearableType type ) const; //-------------------------------------------------------------------- // Attachments @@ -863,7 +860,7 @@ private: 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<LLVoiceVisualizer> mVoiceVisualizer; + LLVoiceVisualizer* mVoiceVisualizer; int mCurrentGesticulationLevel; //-------------------------------------------------------------------- @@ -895,9 +892,6 @@ private: ** DIAGNOSTICS **/ - //-------------------------------------------------------------------- - // General - //-------------------------------------------------------------------- public: static void dumpArchetypeXML(void*); static void dumpBakedStatus(); @@ -917,16 +911,6 @@ private: F32 mAdjustedPixelArea; std::string mDebugText; - - //-------------------------------------------------------------------- - // Avatar Rez Metrics - //-------------------------------------------------------------------- -public: - F32 debugGetExistenceTimeElapsedF32() const { return mDebugExistenceTimer.getElapsedTimeF32(); } -protected: - LLFrameTimer mRuthDebugTimer; // For tracking how long it takes for av to rez - LLFrameTimer mDebugExistenceTimer; // Debugging for how long the avatar has been in memory. - /** Diagnostics ** ** *******************************************************************************/ @@ -1043,7 +1027,15 @@ protected: // Shared with LLVOAvatarSelf *******************************************************************************/ }; // LLVOAvatar -extern const S32 MAX_TEXTURE_VIRTURE_SIZE_RESET_INTERVAL; -extern const F32 SELF_ADDITIONAL_PRI; + +//------------------------------------------------------------------------ +// Inlines +//------------------------------------------------------------------------ +inline BOOL LLVOAvatar::isTextureVisible(LLVOAvatarDefines::ETextureIndex te) const +{ + return ((isTextureDefined(te) || isSelf()) + && (getTEImage(te)->getID() != IMG_INVISIBLE + || LLDrawPoolAlpha::sShowDebugAlpha)); +} #endif // LL_VO_AVATAR_H diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp index 8b87254f81..7473adda1f 100644 --- a/indra/newview/llvoavatarself.cpp +++ b/indra/newview/llvoavatarself.cpp @@ -1697,22 +1697,20 @@ void LLVOAvatarSelf::dumpTotalLocalTextureByteCount() llinfos << "Total Avatar LocTex GL:" << (gl_bytes/1024) << "KB" << llendl; } -BOOL LLVOAvatarSelf::updateIsFullyLoaded() +BOOL LLVOAvatarSelf::getIsCloud() { - BOOL loading = FALSE; - // do we have our body parts? if (gAgentWearables.getWearableCount(WT_SHAPE) == 0 || gAgentWearables.getWearableCount(WT_HAIR) == 0 || gAgentWearables.getWearableCount(WT_EYES) == 0 || gAgentWearables.getWearableCount(WT_SKIN) == 0) { - loading = TRUE; + return TRUE; } if (!isTextureDefined(TEX_HAIR, 0)) { - loading = TRUE; + return TRUE; } if (!mPreviousFullyLoaded) @@ -1720,13 +1718,13 @@ BOOL LLVOAvatarSelf::updateIsFullyLoaded() if (!isLocalTextureDataAvailable(mBakedTextureDatas[BAKED_LOWER].mTexLayerSet) && (!isTextureDefined(TEX_LOWER_BAKED, 0))) { - loading = TRUE; + return TRUE; } if (!isLocalTextureDataAvailable(mBakedTextureDatas[BAKED_UPPER].mTexLayerSet) && (!isTextureDefined(TEX_UPPER_BAKED, 0))) { - loading = TRUE; + return TRUE; } for (U32 i = 0; i < mBakedTextureDatas.size(); i++) @@ -1734,23 +1732,23 @@ BOOL LLVOAvatarSelf::updateIsFullyLoaded() if (i == BAKED_SKIRT && !isWearingWearableType(WT_SKIRT)) continue; - BakedTextureData& texture_data = mBakedTextureDatas[i]; + const BakedTextureData& texture_data = mBakedTextureDatas[i]; if (!isTextureDefined(texture_data.mTextureIndex, 0)) continue; // Check for the case that texture is defined but not sufficiently loaded to display anything. - LLViewerTexture* baked_img = getImage( texture_data.mTextureIndex, 0 ); + const LLViewerTexture* baked_img = getImage( texture_data.mTextureIndex, 0 ); if (!baked_img || !baked_img->hasGLTexture()) { - loading = TRUE; + return TRUE; } - } } - return processFullyLoadedChange(loading); + return FALSE; } + const LLUUID& LLVOAvatarSelf::grabLocalTexture(ETextureIndex type, U32 index) const { if (canGrabLocalTexture(type, index)) diff --git a/indra/newview/llvoavatarself.h b/indra/newview/llvoavatarself.h index 4856e82275..337d445eac 100644 --- a/indra/newview/llvoavatarself.h +++ b/indra/newview/llvoavatarself.h @@ -122,7 +122,7 @@ public: // Loading state //-------------------------------------------------------------------- public: - /*virtual*/ BOOL updateIsFullyLoaded(); + /*virtual*/ BOOL getIsCloud(); private: //-------------------------------------------------------------------- diff --git a/indra/newview/skins/default/xui/da/panel_status_bar.xml b/indra/newview/skins/default/xui/da/panel_status_bar.xml index 8633f12d24..08ffafd5a6 100644 --- a/indra/newview/skins/default/xui/da/panel_status_bar.xml +++ b/indra/newview/skins/default/xui/da/panel_status_bar.xml @@ -21,10 +21,8 @@ <panel.string name="buycurrencylabel"> L$ [AMT] </panel.string> - <panel name="balance_bg"> - <text name="balance" tool_tip="Min status" value="L$20"/> - <button label="KØB L$" name="buyL" tool_tip="Klik for at købe flere L$"/> - </panel> + <button label="" label_selected="" name="buycurrency" tool_tip="Min balance"/> + <button label="Køb L$" name="buyL" tool_tip="Klik for at købe flere L$"/> <text name="TimeText" tool_tip="Nuværende tid (Pacific)"> 24:00 PST </text> diff --git a/indra/newview/skins/default/xui/de/notifications.xml b/indra/newview/skins/default/xui/de/notifications.xml index e5baf0f98f..97387e9e87 100644 --- a/indra/newview/skins/default/xui/de/notifications.xml +++ b/indra/newview/skins/default/xui/de/notifications.xml @@ -333,9 +333,6 @@ Sie benötigen ein Benutzerkonto, um [SECOND_LIFE] betreten zu können. Möchten </url> <usetemplate name="okcancelbuttons" notext="Erneut versuchen" yestext="Neues Benutzerkonto anlegen"/> </notification> - <notification name="InvalidCredentialFormat"> - Sie müssen den Vor- und Nachnamen Ihres Avatars in das Feld Benutzername eingeben, und sich dann erneut anmelden. - </notification> <notification name="AddClassified"> Anzeigen werden im Suchverzeichnis im Abschnitt „Anzeigen" und auf [http://secondlife.com/community/classifieds secondlife.com] für eine Woche angezeigt. Füllen Sie Ihre Anzeige aus und klicken Sie auf 'Veröffentlichen...', um sie zum Verzeichnis hinzuzufügen. @@ -362,11 +359,7 @@ Sind Sie sicher, dass Sie fortfahren wollen? <usetemplate name="okbutton" yestext="OK"/> </notification> <notification name="DeleteAvatarPick"> - Auswahl <nolink>[PICK]</nolink> löschen? - <usetemplate name="okcancelbuttons" notext="Abbrechen" yestext="OK"/> - </notification> - <notification name="DeleteOutfits"> - Das/Die ausgewählte(n) Outfit(s) löschen? + Auswahl [PICK] löschen? <usetemplate name="okcancelbuttons" notext="Abbrechen" yestext="OK"/> </notification> <notification name="PromptGoToEventsPage"> @@ -486,9 +479,7 @@ Sie können die Grafikqualität unter Einstellungen > Grafik wieder erhöhen. Die Region [REGION] erlaubt kein Terraforming. </notification> <notification name="CannotCopyWarning"> - Sie sind nicht berechtigt, die folgenden Objekte zu kopieren: -[ITEMS] -Wenn Sie diese weitergeben, werden sie aus Ihrem Inventar entfernt. Möchten Sie diese Objekte wirklich weggeben? + Sie sind nicht berechtigt, dieses Objekt zu kopieren und verlieren es aus Ihrem Inventar, wenn Sie es weggeben. Möchten Sie dieses Objekt anbieten? <usetemplate name="okcancelbuttons" notext="Nein" yestext="Ja"/> </notification> <notification name="CannotGiveItem"> @@ -625,10 +616,6 @@ Erwartet wurde [VALIDS] <notification name="CannotEncodeFile"> Datei konnte nicht kodiert werden: [FILE] </notification> - <notification name="CorruptedProtectedDataStore"> - Wir können Ihren Benutzernamen und Ihr Kennwort nicht automatisch ausfüllen. Dies kann passieren, wenn Sie die Netzwerkeinstellungen ändern. - <usetemplate name="okbutton" yestext="OK"/> - </notification> <notification name="CorruptResourceFile"> Ressourcendatei beschädigt: [FILE] </notification> @@ -950,36 +937,6 @@ Sie sind nicht berechtigt, Land für die aktive Gruppe zu kaufen. <button name="Cancel" text="Abbrechen"/> </form> </notification> - <notification label="Outfit speichern" name="SaveOutfitAs"> - Mein aktuelles Outfit als neues Outfit speichern: - <form name="form"> - <input name="message"> - [DESC] (neu) - </input> - <button name="Offer" text="OK"/> - <button name="Cancel" text="Abbrechen"/> - </form> - </notification> - <notification label="Kleidungstyp speichern" name="SaveWearableAs"> - Objekt in meinem Inventar speichern als: - <form name="form"> - <input name="message"> - [DESC] (neu) - </input> - <button name="Offer" text="OK"/> - <button name="Cancel" text="Abbrechen"/> - </form> - </notification> - <notification label="Outfit neu benennen" name="RenameOutfit"> - Neuer Outfit-Name: - <form name="form"> - <input name="new_name"> - [NAME] - </input> - <button name="Offer" text="OK"/> - <button name="Cancel" text="Abbrechen"/> - </form> - </notification> <notification name="RemoveFromFriends"> Möchten Sie [FIRST_NAME] [LAST_NAME] aus Ihrer Freundesliste entfernen? <usetemplate name="okcancelbuttons" notext="Abbrechen" yestext="OK"/> @@ -1014,12 +971,6 @@ auf ALLEN LÄNDERN in diesem Sim LÖSCHEN? Geben sie einen höheren Betrag ein. </notification> - <notification name="ConfirmItemDeleteHasLinks"> - Mindestens eines Ihrer ausgewählten Objekte verfügt über verknüpfte Objekte. Wenn Sie dieses Objekt löschen, funktionieren die Verknüpfungen nicht mehr. Wir empfehlen Ihnen daher, diese Verknüpfungen zuerst zu löschen. - -Möchten Sie diese Objekte wirklich löschen? - <usetemplate name="okcancelbuttons" notext="Abbrechen" yestext="OK"/> - </notification> <notification name="ConfirmObjectDeleteLock"> Mindestens ein ausgewähltes Objekt ist gesperrt. @@ -1170,42 +1121,6 @@ Bitte wählen Sie einen männlichen oder weiblichen Avatar. Sie können sich später noch umentscheiden. <usetemplate name="okcancelbuttons" notext="Weiblich" yestext="Männlich"/> </notification> - <notification name="CantTeleportToGrid"> - Konnte nicht zu [SLURL] teleportieren, da dieser Standort sich auf einem anderen Grid ([GRID]) befindet. Sie befinden sich im Moment auf dem Grid ([CURRENT_GRID]). Bitte schließen Sie Ihren Viewer und versuchen Sie es erneut. - <usetemplate name="okbutton" yestext="OK"/> - </notification> - <notification name="GeneralCertificateError"> - Eine Verbindung zum Server konnte nicht hergestellt werden. -[REASON] - -SubjektName: [SUBJECT_NAME_STRING] -Herausgeber: [ISSUER_NAME_STRING] -Gültig ab: [VALID_FROM] -Gültig bis: [VALID_TO] -MD5 Fingerabdruck: [SHA1_DIGEST] -SHA1 Fingerabdruck: [MD5_DIGEST] -Verwendung: [KEYUSAGE] -Erweiterte Verwendung: [EXTENDEDKEYUSAGE] -Identifikation: [SUBJECTKEYIDENTIFIER] - <usetemplate name="okbutton" yestext="OK"/> - </notification> - <notification name="TrustCertificateError"> - Die Zertifizierungsautorität für diesen Server ist unbekannt. - -Zertifikatsinformation: -SubjektName: [SUBJECT_NAME_STRING] -Herausgeber: [ISSUER_NAME_STRING] -Gültig ab: [VALID_FROM] -Gültig bis: [VALID_TO] -MD5 Fingerabdruck: [SHA1_DIGEST] -SHA1 Fingerabdruck: [MD5_DIGEST] -Verwendung: [KEYUSAGE] -Erweiterte Verwendung: [EXTENDEDKEYUSAGE] -Identifikation: [SUBJECTKEYIDENTIFIER] - -Möchten Sie dieser Autorität vertrauen? - <usetemplate name="okcancelbuttons" notext="Abbrechen" yestext="Vertrauen"/> - </notification> <notification name="NotEnoughCurrency"> [NAME] [PRICE] L$ Sie haben nicht genügend L$, um diese Aktion auszuführen. </notification> @@ -1511,10 +1426,6 @@ Chat und Instant Messages werden ausgeblendet. Instant Messages (Sofortnachricht Zu [CLASSIFIED] teleportieren? <usetemplate ignoretext="Bestätigen, dass ich zu einer Position in Anzeigen teleportieren möchte." name="okcancelignore" notext="Abbrechen" yestext="Teleportieren"/> </notification> - <notification name="TeleportToHistoryEntry"> - Nach [HISTORY_ENTRY] teleportieren? - <usetemplate ignoretext="Bestätigen, dass ich zu einem Standort aus der Teleportliste teleportieren möchte" name="okcancelignore" notext="Abbrechen" yestext="Teleportieren"/> - </notification> <notification label="Nachricht an alle auf diesem Grundbesitz" name="MessageEstate"> Geben Sie eine kurze Nachricht ein, die an jede Person auf Ihrem Grundbesitz gesendet wird. <form name="form"> @@ -1597,18 +1508,15 @@ Möchten Sie unsere Knowledgebase besuchen, um mehr Informationen über Alterein Aufgrund Ihrer Alterseinstufung dürfen Sie diese Region nicht betreten. </notification> <notification name="RegionEntryAccessBlocked_Change"> - Sie dürfen diese Region aufgrund der Einstellung Ihrer Inhaltseinstufung nicht betreten. + Sie dürfen diese Region aufgrund der Einstellung Ihrer Alterseinstufung nicht betreten. -Bitte ändern Sie Ihre Einstellungen bezüglich der Inhaltseinstufung, um die gewünschte Region zu betreten. Danach können Sie nach [REGIONMATURITY]-Inhalt suchen und auf diesen zugreifen. Um die Veränderungen rückgängig zu machen, gehen Sie zu Ich > Einstellungen > Allgemein. +Klicken Sie auf „Einstellung ändern“, um Ihre Einstellung für Altereinstufung sofort zu ändern und Zugang zu erhalten. Sie können ab sofort [REGIONMATURITY]-Inhalt suchen und auf diesen zugreifen. Falls Sie diese Einstellung später rückgängig machen möchten, gehen Sie zu Bearbeiten > Einstellungen > Allgemein. <form name="form"> <button name="OK" text="Einstellung ändern"/> <button name="Cancel" text="Schließen"/> <ignore name="ignore" text="Meine Alterseinstufung lässt nicht zu, dass ich eine Region betrete."/> </form> </notification> - <notification name="PreferredMaturityChanged"> - Ihre Inhaltseinstufung ist jetzt [RATING]. - </notification> <notification name="LandClaimAccessBlocked"> Sie haben aufgrund Ihrer Alterseinstufung keinen Anspruch auf dieses Land. Der Grund hierfür ist möglicherweise, dass Sie nicht altersüberprüft sind. @@ -2024,9 +1932,6 @@ Von einer Webseite zu diesem Formular linken, um anderen leichten Zugang zu dies <notification name="SystemMessageTip"> [MESSAGE] </notification> - <notification name="IMSystemMessageTip"> - [MESSAGE] - </notification> <notification name="Cancelled"> Abgebrochen </notification> @@ -2367,6 +2272,15 @@ Versuchen Sie es in einigen Minuten erneut. <button name="Mute" text="Ignorieren"/> </form> </notification> + <notification name="ObjectGiveItemUnknownUser"> + Ein Objekt namens [OBJECTFROMNAME] von (einem unbekannten Einwohner) hat Ihnen folgendes übergeben [OBJECTTYPE]: +[ITEM_SLURL] + <form name="form"> + <button name="Keep" text="Behalten"/> + <button name="Discard" text="Verwerfen"/> + <button name="Mute" text="Ignorieren"/> + </form> + </notification> <notification name="UserGiveItem"> [NAME_SLURL] hat Ihnen folgendes [OBJECTTYPE] übergeben: [ITEM_SLURL] @@ -2390,9 +2304,9 @@ Versuchen Sie es in einigen Minuten erneut. </form> </notification> <notification name="TeleportOffered"> - [NAME_SLURL] hat Ihnen einen Teleport an seine/ihre Position angeboten: + [NAME] hat Ihnen einen Teleport an seine/ihre Position angeboten: -[MESSAGE] - [MATURITY_STR] <icon>[MATURITY_ICON]</icon> +[MESSAGE] <form name="form"> <button name="Teleport" text="Teleportieren"/> <button name="Cancel" text="Abbrechen"/> @@ -2410,11 +2324,11 @@ Versuchen Sie es in einigen Minuten erneut. </form> </notification> <notification name="OfferFriendship"> - [NAME_SLURL] bietet Ihnen die Freundschaft an. + [NAME] bietet Ihnen die Freundschaft an. [MESSAGE] -(Standardmäßig können Sie gegenseitig ihren Online-Status sehen.) +(Standardmäßig werden Sie gegenseitig ihren Online-Status sehen können.) <form name="form"> <button name="Accept" text="Akzeptieren"/> <button name="Decline" text="Ablehnen"/> @@ -2518,6 +2432,14 @@ Anfrage gestatten? <button name="Ignore" text="Ignorieren"/> </form> </notification> + <notification name="ScriptToast"> + [FIRST] [LAST]s '[TITLE]' fordert Eingaben vom Benutzer an. + <form name="form"> + <button name="Open" text="Dialog öffnen"/> + <button name="Ignore" text="Ignorieren"/> + <button name="Block" text="Ignorieren"/> + </form> + </notification> <notification name="BuyLindenDollarSuccess"> Vielen Dank für Ihre Zahlung. @@ -2609,21 +2531,6 @@ Klicken Sie auf 'Akzeptieren ', um dem Chat beizutreten, oder auf &a <notification name="VoiceLoginRetry"> Wir erstellen einen Voice-Kanal für Sie. Bitte warten Sie einen Moment. </notification> - <notification name="VoiceEffectsExpired"> - Ein oder mehrere Ihrer Voice-Morph-Abos ist/sind abgelaufen. -[[URL] Hier klicken], um Ihr Abo zu erneuern. - </notification> - <notification name="VoiceEffectsExpiredInUse"> - Das aktive Voice-Morph-Abo ist abgelaufen. Ihre normalen Voice-Einstellungen werden angewendet. -[[URL] Hier klicken], um Ihr Abo zu erneuern. - </notification> - <notification name="VoiceEffectsWillExpire"> - Ein oder mehrere Ihrer Voice-Morph-Abos werden in weniger als [INTERVAL] Tagen ablaufen. -[[URL] Hier klicken], um Ihr Abo zu erneuern. - </notification> - <notification name="VoiceEffectsNew"> - Neue Voice-Morph-Effekte sind erhältlich! - </notification> <notification name="Cannot enter parcel: not a group member"> Nur Mitglieder einer bestimmten Gruppe dürfen diesen Bereich betreten. </notification> @@ -2689,96 +2596,6 @@ Diese werden für ein paar Sekunden sicherheitshalber gesperrt. Die ausgewählte Schaltfläche kann zur Zeit nicht angezeigt werden. Die Schaltfläche wird angezeigt, wenn genügend Platz vorhanden ist. </notification> - <notification name="ShareNotification"> - Wählen Sie Einwohner aus, für die Sie das Objekt freigeben möchten. - </notification> - <notification name="ShareItemsConfirmation"> - Möchten Sie diese Objekte wirklich für andere freigeben: - -[ITEMS] - -Für folgende Einwohner: - -[RESIDENTS] - <usetemplate name="okcancelbuttons" notext="Abbrechen" yestext="OK"/> - </notification> - <notification name="ItemsShared"> - Objekte wurden erfolgreich freigegeben. - </notification> - <notification name="DeedToGroupFail"> - Übertragung an Gruppe ist fehlgeschlagen. - </notification> - <notification name="AvatarRezNotification"> - (Seit [EXISTENCE] Sekunden inworld ) -Avatar '[NAME]' wurde in [TIME] Sekunden gerezzt. - </notification> - <notification name="AvatarRezSelfBakedDoneNotification"> - (Seit [EXISTENCE] Sekunden inworld ) -Ihr Outfit wurde in [TIME] Sekunden gebacken. - </notification> - <notification name="AvatarRezSelfBakedUpdateNotification"> - (Seit [EXISTENCE] Sekunden inworld ) -Nach [TIME] Sekunden wurde eine Aktualisierung Ihres Aussehens gesendet. -[STATUS] - </notification> - <notification name="AvatarRezCloudNotification"> - (Seit [EXISTENCE] Sekunden inworld ) -Avatar '[NAME]' wird als Wolke angezeigt. - </notification> - <notification name="AvatarRezArrivedNotification"> - (Seit [EXISTENCE] Sekunden inworld ) -Avatar '[NAME]' wird angezeigt. - </notification> - <notification name="AvatarRezLeftCloudNotification"> - (Seit [EXISTENCE] Sekunden inworld ) -Avatar '[NAME]' hat nach [TIME] Sekunden als Wolke die Welt verlassen. - </notification> - <notification name="AvatarRezEnteredAppearanceNotification"> - (Seit [EXISTENCE] Sekunden inworld ) -Avatar '[NAME]' befindet sich im Modus „Aussehen bearbeiten". - </notification> - <notification name="AvatarRezLeftAppearanceNotification"> - (Seit [EXISTENCE] Sekunden inworld ) -Avatar '[NAME]' hat Modus „Aussehen bearbeiten" verlassen. - </notification> - <notification name="NoConnect"> - Es gibt Probleme mit der Verbindung mit [PROTOCOL] [HOSTID]. -Bitte überprüfen Sie Ihre Netzwerk- und Firewalleinstellungen. - <form name="form"> - <button name="OK" text="OK"/> - </form> - </notification> - <notification name="NoVoiceConnect"> - Verbindung mit Voice-Server ist leider nicht möglich: - -[HOSTID] - -Voice-Kommunikation ist leider nicht verfügbar. -Bitte überprüfen Sie Ihr Netzwerk- und Firewall-Setup. - <form name="form"> - <button name="OK" text="OK"/> - </form> - </notification> - <notification name="AvatarRezLeftNotification"> - (Seit [EXISTENCE] Sekunden inworld ) -Avatar '[NAME]' hat als vollständig gerezzter Avatar die Welt verlassen. - </notification> - <notification name="AvatarRezSelfBakeNotification"> - (Seit [EXISTENCE] Sekunden inworld ) -Die [RESOLUTION]-gebakene Textur für '[BODYREGION]' wurde in [TIME] Sekunden [ACTION]. - </notification> - <notification name="ConfirmLeaveCall"> - Möchten Sie dieses Gespräch wirklich verlassen ? - <usetemplate ignoretext="Bestätigen, bevor ich den Anruf verlasse." name="okcancelignore" notext="Nein" yestext="Ja"/> - </notification> - <notification name="ConfirmMuteAll"> - Die von Ihnen ausgewählten Einstellungen werden alle Teilnehmer eines Gruppengespräches stummschalten. -Dies bedeutet, dass alle Einwohner, die später dem Gespräch beitreten, -auch dann stummgeschaltet werden, wenn Sie den Anruf verlassen haben. - -Alle stummschalten? - <usetemplate ignoretext="Bestätigen, bevor alle Teilnehmer in einem Gruppengespräch stummgeschaltet werden." name="okcancelignore" notext="Abbrechen" yestext="OK"/> - </notification> <global name="UnsupportedCPU"> - Ihre CPU-Geschwindigkeit entspricht nicht den Mindestanforderungen. </global> @@ -2803,7 +2620,4 @@ Sollte das Problem fortbestehen, finden Sie weitere Hilfestellung unter [SUPPORT Wenn Sie ein Stück Land besitzen, können Sie dies als Ihr Zuhause festlegen. Ansonsten können Sie auf der Karte nachsehen und dort Ort suchen, die als „Infohub“ gekennzeichnet sind. </global> - <global name="You died and have been teleported to your home location"> - Sie sind gestorben und wurden zu Ihrem Zuhause teleportiert. - </global> </notifications> diff --git a/indra/newview/skins/default/xui/de/panel_status_bar.xml b/indra/newview/skins/default/xui/de/panel_status_bar.xml index 803bd1b5ab..3dc6997320 100644 --- a/indra/newview/skins/default/xui/de/panel_status_bar.xml +++ b/indra/newview/skins/default/xui/de/panel_status_bar.xml @@ -22,7 +22,7 @@ [AMT] L$ </panel.string> <button label="" label_selected="" name="buycurrency" tool_tip="Mein Kontostand"/> - <button label=" " name="buyL" tool_tip="Hier klicken, um mehr L$ zu kaufen"/> + <button label="L$ kaufen" name="buyL" tool_tip="Hier klicken, um mehr L$ zu kaufen"/> <text name="TimeText" tool_tip="Aktuelle Zeit (Pazifik)"> 24:00 H PST </text> diff --git a/indra/newview/skins/default/xui/en/floater_script_debug_panel.xml b/indra/newview/skins/default/xui/en/floater_script_debug_panel.xml index d1db5c17ba..e94af2c8d5 100644 --- a/indra/newview/skins/default/xui/en/floater_script_debug_panel.xml +++ b/indra/newview/skins/default/xui/en/floater_script_debug_panel.xml @@ -18,7 +18,6 @@ max_length="2147483647" name="Chat History Editor" parse_highlights="true" - read_only="true" width="420" word_wrap="true" /> </floater> diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 6c9564c8cf..ca922bf724 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -5968,6 +5968,12 @@ The button will be shown when there is enough space for it. Drag items from inventory onto a person in the resident picker </notification> + <notification + icon="notifytip.tga" + name="AvatarRezNotification" + type="notifytip"> +Avatar '[NAME]' rezzed in [TIME] seconds. + </notification> <global name="UnsupportedCPU"> - Your CPU speed does not meet the minimum requirements. diff --git a/indra/newview/skins/default/xui/en/panel_outfit_edit.xml b/indra/newview/skins/default/xui/en/panel_outfit_edit.xml index 9ece4aead8..bc37af0319 100644 --- a/indra/newview/skins/default/xui/en/panel_outfit_edit.xml +++ b/indra/newview/skins/default/xui/en/panel_outfit_edit.xml @@ -25,6 +25,10 @@ (unknown) </panel.string> + <!-- Wearables filtering strings --> + <string name="Filter.All" value="All"/> + <string name="Filter.Clothes/Body" value="Clothes/Body"/> + <string name="Filter.Objects" value="Objects"/> <button follows="top|left" @@ -154,6 +158,16 @@ sort_column="look_item_sort" name="look_item_sort" /> </scroll_list> + <!-- TODO remove this button. Added it temporary for QA to be able to test new edit wearable panel (see EXT-6564)--> + <button + follows="left|top|right" + height="20" + label="edit" + left="0" + top="0" + layout="topleft" + name="edit_wearable_btn" + width="40" /> <panel background_visible="true" @@ -222,29 +236,18 @@ <layout_panel auto_resize="true" default_tab_group="3" - height="250" - min_height="120" + height="210" + min_height="210" name="add_wearables_panel" width="300" tab_group="2" user_resize="true" visible="false"> - <text - follows="top|left|right" - font="SansSerifBold" - height="13" - layout="topleft" - left="5" - name="status" - text_color="LtGray" - top="5" - value="Add Wearables" - use_ellipses="true" - width="275" /> - + <!-- *NOTE is not used, invisible and disabled --> <filter_editor background_image="TextField_Search_Off" + enabled="false" follows="left|top|right" font="SansSerif" label="Filter" @@ -254,13 +257,79 @@ height="20" name="look_item_filter" text_color="black" - text_pad_left="25" /> + text_pad_left="25" + visible="false"/> + + <layout_stack + animate="true" + follows="all" + height="25" + width="300" + layout="topleft" + orientation="horizontal" + name="filter_panels" + top="0" + left="0"> + <layout_panel + layout="topleft" + follows="left|top|right" + height="25" + label="IM Control Panel" + name="filter_button_panel" + width="150" + auto_resize="true" + user_resize="false"> + <text + follows="top|left|right" + font="SansSerifBold" + height="13" + layout="topleft" + left="5" + name="add_to_outfit_label" + text_color="LtGray" + top="3" + value="Add to Outfit:" + use_ellipses="true" + width="270" /> + <button + follows="top|right" + height="20" + image_hover_unselected="Toolbar_Middle_Over" + image_overlay="" + image_selected="Toolbar_Middle_Selected" + image_unselected="Toolbar_Middle_Off" + is_toggle="true" + label="O" + layout="topleft" + right="-1" + name="filter_button" + top="3" + width="20" /> + </layout_panel> + <layout_panel + auto_resize="true" + height="25" + min_width="130" + name="filter_combobox_panel" + width="150" + user_resize="false" + visible="false"> + <combo_box + follows="top|left|right" + height="20" + layout="topleft" + right="-5" + name="filter_wearables_combobox" + top="0" + width="130"/> + </layout_panel> + </layout_stack> <inventory_panel allow_multi_select="false" border="false" follows="left|top|right|bottom" - height="176" + height="155" layout="topleft" left="0" mouse_opaque="false" diff --git a/indra/newview/skins/default/xui/en/panel_people.xml b/indra/newview/skins/default/xui/en/panel_people.xml index 233137a76b..8131b75b70 100644 --- a/indra/newview/skins/default/xui/en/panel_people.xml +++ b/indra/newview/skins/default/xui/en/panel_people.xml @@ -477,7 +477,7 @@ If you're looking for people to hang out with, [secondlife:///app/worldmap try t label="Share" layout="topleft" name="share_btn" - width="85" /> + width="62" /> <button follows="bottom|left" left_pad="3" diff --git a/indra/newview/skins/default/xui/en/panel_scrolling_param.xml b/indra/newview/skins/default/xui/en/panel_scrolling_param.xml index 8042563900..19eb4bb0d6 100644 --- a/indra/newview/skins/default/xui/en/panel_scrolling_param.xml +++ b/indra/newview/skins/default/xui/en/panel_scrolling_param.xml @@ -110,7 +110,6 @@ increment="1" initial_value="0" label="[DESC]" - label_width="100" layout="bottom|left" left="6" max_val="100" diff --git a/indra/newview/skins/default/xui/en/panel_status_bar.xml b/indra/newview/skins/default/xui/en/panel_status_bar.xml index c2624ce0d0..690d2971ee 100644 --- a/indra/newview/skins/default/xui/en/panel_status_bar.xml +++ b/indra/newview/skins/default/xui/en/panel_status_bar.xml @@ -99,7 +99,7 @@ image_pressed="Pause_Press" image_pressed_selected="Play_Press" is_toggle="true" - left_pad="20" + left_pad="15" top="1" name="media_toggle_btn" tool_tip="Start/Stop All Media (Music, Video, Web pages)" @@ -112,12 +112,12 @@ image_pressed="Audio_Press" image_unselected="Audio_Off" is_toggle="true" - left_pad="10" + left_pad="5" top="2" name="volume_btn" tool_tip="Global Volume Control" width="16" /> - <!-- <text + <text follows="right|top" halign="center" height="12" @@ -125,5 +125,5 @@ left_delta="0" name="stat_btn" top_delta="0" - width="20"/>--> + width="20"/> </panel> diff --git a/indra/newview/skins/default/xui/es/floater_about_land.xml b/indra/newview/skins/default/xui/es/floater_about_land.xml index 49bf2a7442..6118a63872 100644 --- a/indra/newview/skins/default/xui/es/floater_about_land.xml +++ b/indra/newview/skins/default/xui/es/floater_about_land.xml @@ -264,7 +264,7 @@ Vaya al menú Mundo > Acerca del terreno o seleccione otra parcela para ver s [COUNT] </text> <text left="4" name="Autoreturn" width="412"> - Devolución automática de objetos de otros (en min., 0 para desactivarla): + Devolución automát. de objetos de otros (en min., 0 la desactiva): </text> <line_editor name="clean other time" right="-20"/> <text name="Object Owners:" width="150"> @@ -275,7 +275,7 @@ Vaya al menú Mundo > Acerca del terreno o seleccione otra parcela para ver s <name_list name="owner list"> <name_list.columns label="Tipo" name="type"/> <name_list.columns label="Nombre" name="name"/> - <name_list.columns label="Número" name="count"/> + <name_list.columns label="Núm." name="count"/> <name_list.columns label="Más recientes" name="mostrecent"/> </name_list> </panel> diff --git a/indra/newview/skins/default/xui/es/panel_status_bar.xml b/indra/newview/skins/default/xui/es/panel_status_bar.xml index 13ed1acf0b..d4404fd9b5 100644 --- a/indra/newview/skins/default/xui/es/panel_status_bar.xml +++ b/indra/newview/skins/default/xui/es/panel_status_bar.xml @@ -21,10 +21,8 @@ <panel.string name="buycurrencylabel"> [AMT] L$ </panel.string> - <panel name="balance_bg"> - <text name="balance" tool_tip="Mi saldo" value="20 L$"/> - <button label="COMPRAR L$" name="buyL" tool_tip="Pulsa para comprar más L$"/> - </panel> + <button label="" label_selected="" name="buycurrency" tool_tip="Mi saldo"/> + <button label="Comprar L$" name="buyL" tool_tip="Pulsa para comprar más L$"/> <text name="TimeText" tool_tip="Hora actual (Pacífico)"> 24:00 AM PST </text> diff --git a/indra/newview/skins/default/xui/fr/panel_status_bar.xml b/indra/newview/skins/default/xui/fr/panel_status_bar.xml index 85429a18c7..dffb1d4238 100644 --- a/indra/newview/skins/default/xui/fr/panel_status_bar.xml +++ b/indra/newview/skins/default/xui/fr/panel_status_bar.xml @@ -16,15 +16,13 @@ [hour12, datetime, slt]:[min, datetime, slt] [ampm, datetime, slt] [timezone,datetime, slt] </panel.string> <panel.string name="timeTooltip"> - [weekday, datetime, slt] [sday, datetime, slt] [month, datetime, slt] [year, datetime, slt] + [weekday, datetime, slt], [day, datetime, slt] [month, datetime, slt] [year, datetime, slt] </panel.string> <panel.string name="buycurrencylabel"> [AMT] L$ </panel.string> - <panel name="balance_bg"> - <text name="balance" tool_tip="Mon solde" value="20 L$"/> - <button label="ACHETER L$" name="buyL" tool_tip="Cliquer pour acheter plus de L$"/> - </panel> + <button label="" label_selected="" name="buycurrency" tool_tip="Mon solde"/> + <button label="Acheter L$" name="buyL" tool_tip="Cliquez pour acheter plus de L$"/> <text name="TimeText" tool_tip="Heure actuelle (Pacifique)"> 00h00 PST </text> diff --git a/indra/newview/skins/default/xui/it/panel_group_roles.xml b/indra/newview/skins/default/xui/it/panel_group_roles.xml index 478b35e628..1769ef748d 100644 --- a/indra/newview/skins/default/xui/it/panel_group_roles.xml +++ b/indra/newview/skins/default/xui/it/panel_group_roles.xml @@ -13,9 +13,6 @@ Seleziona più membri tenendo premuto il tasto Ctrl e cliccando sui loro nomi. </panel.string> - <panel.string name="donation_area"> - [AREA] m² - </panel.string> <filter_editor label="Filtra Membri" name="filter_input"/> <name_list name="member_list"> <name_list.columns label="Socio" name="name"/> @@ -69,15 +66,21 @@ in questo gruppo. C'è una vasta gamma di abilità. <text name="static"> Nome del ruolo </text> - <line_editor name="role_name"/> + <line_editor name="role_name"> + Addetti + </line_editor> <text name="static3"> Titolo del ruolo </text> - <line_editor name="role_title"/> + <line_editor name="role_title"> + (attendi) + </line_editor> <text name="static2"> Descrizione </text> - <text_editor name="role_description"/> + <text_editor name="role_description"> + (attendi) + </text_editor> <text name="static4"> Ruoli assegnati </text> @@ -88,6 +91,9 @@ in questo gruppo. C'è una vasta gamma di abilità. <scroll_list name="role_allowed_actions" tool_tip="Per i dettagli di ogni abilità consentita vedi la scheda abilità."/> </panel> <panel name="actions_footer"> + <text name="static"> + Descrizione abilità + </text> <text_editor name="action_description"> Questa abilità è 'Espelli i membri dal gruppo'. Solo un Capogruppo puo espellere un'altro Capogruppo. </text_editor> diff --git a/indra/newview/skins/default/xui/it/panel_status_bar.xml b/indra/newview/skins/default/xui/it/panel_status_bar.xml index 584ac5e4b4..4c860ff479 100644 --- a/indra/newview/skins/default/xui/it/panel_status_bar.xml +++ b/indra/newview/skins/default/xui/it/panel_status_bar.xml @@ -22,7 +22,7 @@ L$ [AMT] </panel.string> <button label="" label_selected="" name="buycurrency" tool_tip="Il mio saldo"/> - <button label="Acquista" name="buyL" tool_tip="Clicca per comprare più L$"/> + <button label="Acquista L$" name="buyL" tool_tip="Clicca per comprare più L$"/> <text name="TimeText" tool_tip="Orario attuale (Pacifico)"> 24:00, ora del Pacifico </text> diff --git a/indra/newview/skins/default/xui/ja/panel_status_bar.xml b/indra/newview/skins/default/xui/ja/panel_status_bar.xml index c3a5127981..8a848f496d 100644 --- a/indra/newview/skins/default/xui/ja/panel_status_bar.xml +++ b/indra/newview/skins/default/xui/ja/panel_status_bar.xml @@ -21,10 +21,8 @@ <panel.string name="buycurrencylabel"> L$ [AMT] </panel.string> - <panel name="balance_bg"> - <text name="balance" tool_tip="残高" value="L$20"/> - <button label="L$ の購入" name="buyL" tool_tip="クリックして L$ を購入します"/> - </panel> + <button label="" label_selected="" name="buycurrency" tool_tip="所持金"/> + <button label="L$ の購入" name="buyL" tool_tip="クリックして L$ を購入します"/> <text name="TimeText" tool_tip="現在時刻(太平洋)"> 24:00 AM PST </text> diff --git a/indra/newview/skins/default/xui/pl/panel_people.xml b/indra/newview/skins/default/xui/pl/panel_people.xml index 5ea5356c60..09958c84d6 100644 --- a/indra/newview/skins/default/xui/pl/panel_people.xml +++ b/indra/newview/skins/default/xui/pl/panel_people.xml @@ -47,13 +47,13 @@ Jeżeli szukasz ludzi, z którymi można się spotkać, kliknij tutaj [secondlif </panel> </tab_container> <panel name="button_bar"> - <button label="Profil" name="view_profile_btn" tool_tip="Pokaż zdjęcie, grupy i inne informacje o Rezydencie"/> - <button label="IM" name="im_btn" tool_tip="Rozpocznij rozmowę prywatną (IM)"/> - <button label="Zadzwoń" name="call_btn" tool_tip="Zadzwoń do tego Rezydenta"/> - <button label="Podziel się" name="share_btn"/> - <button label="Teleportuj" name="teleport_btn" tool_tip="Zaproponuj teleportację"/> - <button label="Profil grupy" name="group_info_btn" tool_tip="Pokaż informacje o grupie"/> - <button label="Konferencja Grupowa" name="chat_btn" tool_tip="Rozpocznij konferencę"/> - <button label="Rozmowa Głosowa" name="group_call_btn" tool_tip="Rozmowa Głosowa w tej Grupie"/> + <button width="55" label="Profil" name="view_profile_btn" tool_tip="Pokaż zdjęcie, grupy i inne informacje o Rezydencie"/> + <button width="35" label="IM" name="im_btn" tool_tip="Rozpocznij rozmowę prywatną (IM)"/> + <button width="62" label="Zadzwoń" name="call_btn" tool_tip="Zadzwoń do tego Rezydenta"/> + <button width="72" label="Podziel się" name="share_btn"/> + <button width="70" label="Teleportuj" name="teleport_btn" tool_tip="Zaproponuj teleportację"/> + <button width="69" label="Profil grupy" name="group_info_btn" tool_tip="Pokaż informacje o grupie"/> + <button width="124" label="Konferencja Grupowa" name="chat_btn" tool_tip="Rozpocznij konferencę"/> + <button width="108" label="Rozmowa Głosowa" name="group_call_btn" tool_tip="Rozmowa Głosowa w tej Grupie"/> </panel> </panel> diff --git a/indra/newview/skins/default/xui/pl/panel_status_bar.xml b/indra/newview/skins/default/xui/pl/panel_status_bar.xml index cd2ae14f6c..313c2732ff 100644 --- a/indra/newview/skins/default/xui/pl/panel_status_bar.xml +++ b/indra/newview/skins/default/xui/pl/panel_status_bar.xml @@ -22,7 +22,7 @@ L$ [AMT] </panel.string> <button label="" label_selected="" name="buycurrency" tool_tip="Bilans"/> - <button label="Kup" name="buyL" tool_tip="Kliknij aby kupić L$"/> + <button label="Kup L$" name="buyL" tool_tip="Kliknij aby kupić L$"/> <text name="TimeText" tool_tip="Obecny Czas (Pacyficzny)"> 24:00 AM PST </text> diff --git a/indra/newview/skins/default/xui/pt/panel_status_bar.xml b/indra/newview/skins/default/xui/pt/panel_status_bar.xml index fbbcf0d1be..a320d9d56d 100644 --- a/indra/newview/skins/default/xui/pt/panel_status_bar.xml +++ b/indra/newview/skins/default/xui/pt/panel_status_bar.xml @@ -21,10 +21,8 @@ <panel.string name="buycurrencylabel"> L$ [AMT] </panel.string> - <panel name="balance_bg"> - <text name="balance" tool_tip="Meu saldo" value="L$20"/> - <button label="Comprar L$" name="buyL" tool_tip="Comprar mais L$"/> - </panel> + <button label="" label_selected="" name="buycurrency" tool_tip="Meu saldo"/> + <button label="Comprar L$" name="buyL" tool_tip="Comprar mais L$"/> <text name="TimeText" tool_tip="Hora atual (Pacífico)"> 24:00 AM PST </text> |