Automated merge up from viewer-development into mesh-development
commit
690105630e
1
.hgtags
1
.hgtags
|
|
@ -86,3 +86,4 @@ f1827b441e05bf37c68e2c15ebc6d09e9b03f527 2.6.0-start
|
|||
c5bdef3aaa2744626aef3c217ce29e1900d357b3 2.6.1-start
|
||||
9e4641f4a7870c0f565a25a2971368d5a29516a1 DRTVWR-41_2.6.0-beta2
|
||||
9e4641f4a7870c0f565a25a2971368d5a29516a1 2.6.0-beta2
|
||||
56b2778c743c2a964d82e1caf11084d76a87de2c 2.6.2-start
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
# -*- cmake -*-
|
||||
|
||||
add_subdirectory(llui_libtest)
|
||||
add_subdirectory(llimage_libtest)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,131 @@
|
|||
# -*- cmake -*-
|
||||
|
||||
# Integration tests of the llimage library (JPEG2000, PNG, jpeg, etc... images reading and writing)
|
||||
|
||||
project (llimage_libtest)
|
||||
|
||||
include(00-Common)
|
||||
include(LLCommon)
|
||||
include(Linking)
|
||||
include(LLSharedLibs)
|
||||
include(LLImage)
|
||||
include(LLImageJ2COJ)
|
||||
include(LLKDU)
|
||||
include(LLMath)
|
||||
include(LLVFS)
|
||||
|
||||
include_directories(
|
||||
${LLCOMMON_INCLUDE_DIRS}
|
||||
${LLVFS_INCLUDE_DIRS}
|
||||
${LLIMAGE_INCLUDE_DIRS}
|
||||
${LLMATH_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
set(llimage_libtest_SOURCE_FILES
|
||||
llimage_libtest.cpp
|
||||
)
|
||||
|
||||
set(llimage_libtest_HEADER_FILES
|
||||
CMakeLists.txt
|
||||
llimage_libtest.h
|
||||
)
|
||||
|
||||
set_source_files_properties(${llimage_libtest_HEADER_FILES}
|
||||
PROPERTIES HEADER_FILE_ONLY TRUE)
|
||||
|
||||
list(APPEND llimage_libtest_SOURCE_FILES ${llimage_libtest_HEADER_FILES})
|
||||
|
||||
add_executable(llimage_libtest
|
||||
WIN32
|
||||
MACOSX_BUNDLE
|
||||
${llimage_libtest_SOURCE_FILES}
|
||||
)
|
||||
|
||||
set_target_properties(llimage_libtest
|
||||
PROPERTIES
|
||||
WIN32_EXECUTABLE
|
||||
FALSE
|
||||
)
|
||||
|
||||
# OS-specific libraries
|
||||
if (DARWIN)
|
||||
include(CMakeFindFrameworks)
|
||||
find_library(COREFOUNDATION_LIBRARY CoreFoundation)
|
||||
set(OS_LIBRARIES ${COREFOUNDATION_LIBRARY})
|
||||
elseif (WINDOWS)
|
||||
# set(OS_LIBRARIES)
|
||||
elseif (LINUX)
|
||||
# set(OS_LIBRARIES)
|
||||
else (DARWIN)
|
||||
message(FATAL_ERROR "Unknown platform")
|
||||
endif (DARWIN)
|
||||
|
||||
# Libraries on which this application depends on
|
||||
# Sort by high-level to low-level
|
||||
target_link_libraries(llimage_libtest
|
||||
${LLCOMMON_LIBRARIES}
|
||||
${LLVFS_LIBRARIES}
|
||||
${LLIMAGE_LIBRARIES}
|
||||
${LLKDU_LIBRARIES}
|
||||
${KDU_LIBRARY}
|
||||
${LLIMAGEJ2COJ_LIBRARIES}
|
||||
${OS_LIBRARIES}
|
||||
)
|
||||
|
||||
if (DARWIN)
|
||||
# Path inside the app bundle where we'll need to copy libraries
|
||||
set(LLIMAGE_LIBTEST_DESTINATION_DIR
|
||||
${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/llimage_libtest.app/Contents/Resources
|
||||
)
|
||||
# Create the Contents/Resources directory
|
||||
add_custom_command(
|
||||
TARGET llimage_libtest POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND}
|
||||
ARGS
|
||||
-E
|
||||
make_directory
|
||||
${LLIMAGE_LIBTEST_DESTINATION_DIR}
|
||||
COMMENT "Creating Resources directory in app bundle."
|
||||
)
|
||||
else (DARWIN)
|
||||
set(LLIMAGE_LIBTEST_DESTINATION_DIR
|
||||
${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/
|
||||
)
|
||||
endif (DARWIN)
|
||||
|
||||
get_target_property(BUILT_LLCOMMON llcommon LOCATION)
|
||||
add_custom_command(TARGET llimage_libtest POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${BUILT_LLCOMMON} ${LLIMAGE_LIBTEST_DESTINATION_DIR}
|
||||
DEPENDS ${BUILT_LLCOMMON}
|
||||
)
|
||||
|
||||
if (DARWIN)
|
||||
# Copy the required libraries to the package app
|
||||
add_custom_command(TARGET llimage_libtest POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/../libraries/universal-darwin/lib_release/libapr-1.0.3.7.dylib ${LLIMAGE_LIBTEST_DESTINATION_DIR}
|
||||
DEPENDS ${CMAKE_SOURCE_DIR}/../libraries/universal-darwin/lib_release/libapr-1.0.3.7.dylib
|
||||
)
|
||||
add_custom_command(TARGET llimage_libtest POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/../libraries/universal-darwin/lib_release/libaprutil-1.0.3.8.dylib ${LLIMAGE_LIBTEST_DESTINATION_DIR}
|
||||
DEPENDS ${CMAKE_SOURCE_DIR}/../libraries/universal-darwin/lib_release/libaprutil-1.0.3.8.dylib
|
||||
)
|
||||
add_custom_command(TARGET llimage_libtest POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/../libraries/universal-darwin/lib_release/libexception_handler.dylib ${LLIMAGE_LIBTEST_DESTINATION_DIR}
|
||||
DEPENDS ${CMAKE_SOURCE_DIR}/../libraries/universal-darwin/lib_release/libexception_handler.dylib
|
||||
)
|
||||
add_custom_command(TARGET llimage_libtest POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/../libraries/universal-darwin/lib_release/libexpat.0.5.0.dylib ${LLIMAGE_LIBTEST_DESTINATION_DIR}
|
||||
DEPENDS ${CMAKE_SOURCE_DIR}/../libraries/universal-darwin/lib_release/libexpat.0.5.0.dylib
|
||||
)
|
||||
endif (DARWIN)
|
||||
|
||||
if (WINDOWS)
|
||||
# Check indra/test_apps/llplugintest/CMakeLists.txt for an example of what to copy over for Windows and how
|
||||
endif (WINDOWS)
|
||||
|
||||
# Ensure people working on the viewer don't break this library
|
||||
# *NOTE: This could be removed, or only built by TeamCity, if the build
|
||||
# and link times become too long.
|
||||
add_dependencies(viewer llimage_libtest)
|
||||
|
||||
ll_deploy_sharedlibs_command(llimage_libtest)
|
||||
|
|
@ -0,0 +1,437 @@
|
|||
/**
|
||||
* @file llimage_libtest.cpp
|
||||
* @author Merov Linden
|
||||
* @brief Integration test for the llimage library
|
||||
*
|
||||
* $LicenseInfo:firstyear=2011&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2011, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
#include "linden_common.h"
|
||||
#include "llpointer.h"
|
||||
#include "lltimer.h"
|
||||
|
||||
#include "llimage_libtest.h"
|
||||
|
||||
// Linden library includes
|
||||
#include "llimage.h"
|
||||
#include "llimagejpeg.h"
|
||||
#include "llimagepng.h"
|
||||
#include "llimagebmp.h"
|
||||
#include "llimagetga.h"
|
||||
#include "llimagej2c.h"
|
||||
#include "lldir.h"
|
||||
|
||||
// system libraries
|
||||
#include <iostream>
|
||||
|
||||
// doc string provided when invoking the program with --help
|
||||
static const char USAGE[] = "\n"
|
||||
"usage:\tllimage_libtest [options]\n"
|
||||
"\n"
|
||||
" -h, --help\n"
|
||||
" Print this help\n"
|
||||
" -i, --input <file1 .. file2>\n"
|
||||
" List of image files to load and convert. Patterns with wild cards can be used.\n"
|
||||
" -o, --output <file1 .. file2> OR <type>\n"
|
||||
" List of image files to create (assumes same order as for input files)\n"
|
||||
" OR 3 letters file type extension to convert each input file into.\n"
|
||||
" -log, --logmetrics <metric>\n"
|
||||
" Log performance data for <metric>. Results in <metric>.slp\n"
|
||||
" Note: so far, only ImageCompressionTester has been tested.\n"
|
||||
" -r, --analyzeperformance\n"
|
||||
" Create a report comparing <metric>_baseline.slp with current <metric>.slp\n"
|
||||
" Results in <metric>_report.csv"
|
||||
" -s, --image-stats\n"
|
||||
" Output stats for each input and output image.\n"
|
||||
"\n";
|
||||
|
||||
// true when all image loading is done. Used by metric logging thread to know when to stop the thread.
|
||||
static bool sAllDone = false;
|
||||
|
||||
// Create an empty formatted image instance of the correct type from the filename
|
||||
LLPointer<LLImageFormatted> create_image(const std::string &filename)
|
||||
{
|
||||
std::string exten = gDirUtilp->getExtension(filename);
|
||||
U32 codec = LLImageBase::getCodecFromExtension(exten);
|
||||
|
||||
LLPointer<LLImageFormatted> image;
|
||||
switch (codec)
|
||||
{
|
||||
case IMG_CODEC_BMP:
|
||||
image = new LLImageBMP();
|
||||
break;
|
||||
case IMG_CODEC_TGA:
|
||||
image = new LLImageTGA();
|
||||
break;
|
||||
case IMG_CODEC_JPEG:
|
||||
image = new LLImageJPEG();
|
||||
break;
|
||||
case IMG_CODEC_J2C:
|
||||
image = new LLImageJ2C();
|
||||
break;
|
||||
case IMG_CODEC_PNG:
|
||||
image = new LLImagePNG();
|
||||
break;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
void output_image_stats(LLPointer<LLImageFormatted> image, const std::string &filename)
|
||||
{
|
||||
// Print out some statistical data on the image
|
||||
std::cout << "Image stats for : " << filename << ", extension : " << image->getExtension() << std::endl;
|
||||
|
||||
std::cout << " with : " << (int)(image->getWidth()) << ", height : " << (int)(image->getHeight()) << std::endl;
|
||||
std::cout << " comp : " << (int)(image->getComponents()) << ", levels : " << (int)(image->getDiscardLevel()) << std::endl;
|
||||
std::cout << " head : " << (int)(image->calcHeaderSize()) << ", data : " << (int)(image->getDataSize()) << std::endl;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Load an image from file and return a raw (decompressed) instance of its data
|
||||
LLPointer<LLImageRaw> load_image(const std::string &src_filename, bool output_stats)
|
||||
{
|
||||
LLPointer<LLImageFormatted> image = create_image(src_filename);
|
||||
|
||||
if (!image->load(src_filename))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if( (image->getComponents() != 3) && (image->getComponents() != 4) )
|
||||
{
|
||||
std::cout << "Image files with less than 3 or more than 4 components are not supported\n";
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (output_stats)
|
||||
{
|
||||
output_image_stats(image, src_filename);
|
||||
}
|
||||
|
||||
LLPointer<LLImageRaw> raw_image = new LLImageRaw;
|
||||
if (!image->decode(raw_image, 0.0f))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return raw_image;
|
||||
}
|
||||
|
||||
// Save a raw image instance into a file
|
||||
bool save_image(const std::string &dest_filename, LLPointer<LLImageRaw> raw_image, bool output_stats)
|
||||
{
|
||||
LLPointer<LLImageFormatted> image = create_image(dest_filename);
|
||||
|
||||
if (!image->encode(raw_image, 0.0f))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (output_stats)
|
||||
{
|
||||
output_image_stats(image, dest_filename);
|
||||
}
|
||||
|
||||
return image->save(dest_filename);
|
||||
}
|
||||
|
||||
void store_input_file(std::list<std::string> &input_filenames, const std::string &path)
|
||||
{
|
||||
// Break the incoming path in its components
|
||||
std::string dir = gDirUtilp->getDirName(path);
|
||||
std::string name = gDirUtilp->getBaseFileName(path);
|
||||
std::string exten = gDirUtilp->getExtension(path);
|
||||
|
||||
// std::cout << "store_input_file : " << path << ", dir : " << dir << ", name : " << name << ", exten : " << exten << std::endl;
|
||||
|
||||
// If extension is not an image type or "*", exit
|
||||
// Note: we don't support complex patterns for the extension like "j??"
|
||||
// Note: on most shells, the pattern expansion is done by the shell so that pattern matching limitation is actually not a problem
|
||||
if ((exten.compare("*") != 0) && (LLImageBase::getCodecFromExtension(exten) == IMG_CODEC_INVALID))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ((name.find('*') != -1) || ((name.find('?') != -1)))
|
||||
{
|
||||
// If file name is a pattern, iterate to get each file name and store
|
||||
std::string next_name;
|
||||
while (gDirUtilp->getNextFileInDir(dir,name,next_name))
|
||||
{
|
||||
std::string file_name = dir + gDirUtilp->getDirDelimiter() + next_name;
|
||||
input_filenames.push_back(file_name);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Verify that the file does exist before storing
|
||||
if (gDirUtilp->fileExists(path))
|
||||
{
|
||||
input_filenames.push_back(path);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "store_input_file : the file " << path << " could not be found" << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void store_output_file(std::list<std::string> &output_filenames, std::list<std::string> &input_filenames, const std::string &path)
|
||||
{
|
||||
// Break the incoming path in its components
|
||||
std::string dir = gDirUtilp->getDirName(path);
|
||||
std::string name = gDirUtilp->getBaseFileName(path);
|
||||
std::string exten = gDirUtilp->getExtension(path);
|
||||
|
||||
// std::cout << "store_output_file : " << path << ", dir : " << dir << ", name : " << name << ", exten : " << exten << std::endl;
|
||||
|
||||
if (dir.empty() && exten.empty())
|
||||
{
|
||||
// If dir and exten are empty, we interpret the name as a file extension type name and will iterate through input list to populate the output list
|
||||
exten = name;
|
||||
// Make sure the extension is an image type
|
||||
if (LLImageBase::getCodecFromExtension(exten) == IMG_CODEC_INVALID)
|
||||
{
|
||||
return;
|
||||
}
|
||||
std::string delim = gDirUtilp->getDirDelimiter();
|
||||
std::list<std::string>::iterator in_file = input_filenames.begin();
|
||||
std::list<std::string>::iterator end = input_filenames.end();
|
||||
for (; in_file != end; ++in_file)
|
||||
{
|
||||
dir = gDirUtilp->getDirName(*in_file);
|
||||
name = gDirUtilp->getBaseFileName(*in_file,true);
|
||||
std::string file_name;
|
||||
if (!dir.empty())
|
||||
{
|
||||
file_name = dir + delim + name + "." + exten;
|
||||
}
|
||||
else
|
||||
{
|
||||
file_name = name + "." + exten;
|
||||
}
|
||||
output_filenames.push_back(file_name);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Make sure the extension is an image type
|
||||
if (LLImageBase::getCodecFromExtension(exten) == IMG_CODEC_INVALID)
|
||||
{
|
||||
return;
|
||||
}
|
||||
// Store the path
|
||||
output_filenames.push_back(path);
|
||||
}
|
||||
}
|
||||
|
||||
// Holds the metric gathering output in a thread safe way
|
||||
class LogThread : public LLThread
|
||||
{
|
||||
public:
|
||||
std::string mFile;
|
||||
|
||||
LogThread(std::string& test_name) : LLThread("llimage_libtest log")
|
||||
{
|
||||
std::string file_name = test_name + std::string(".slp");
|
||||
mFile = file_name;
|
||||
}
|
||||
|
||||
void run()
|
||||
{
|
||||
std::ofstream os(mFile.c_str());
|
||||
|
||||
while (!sAllDone)
|
||||
{
|
||||
LLFastTimer::writeLog(os);
|
||||
os.flush();
|
||||
ms_sleep(32);
|
||||
}
|
||||
LLFastTimer::writeLog(os);
|
||||
os.flush();
|
||||
os.close();
|
||||
}
|
||||
};
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
// List of input and output files
|
||||
std::list<std::string> input_filenames;
|
||||
std::list<std::string> output_filenames;
|
||||
bool analyze_performance = false;
|
||||
bool image_stats = false;
|
||||
|
||||
// Init whatever is necessary
|
||||
ll_init_apr();
|
||||
LLImage::initClass();
|
||||
LogThread* fast_timer_log_thread = NULL; // For performance and metric gathering
|
||||
|
||||
// Analyze command line arguments
|
||||
for (int arg = 1; arg < argc; ++arg)
|
||||
{
|
||||
if (!strcmp(argv[arg], "--help") || !strcmp(argv[arg], "-h"))
|
||||
{
|
||||
// Send the usage to standard out
|
||||
std::cout << USAGE << std::endl;
|
||||
return 0;
|
||||
}
|
||||
else if ((!strcmp(argv[arg], "--input") || !strcmp(argv[arg], "-i")) && arg < argc-1)
|
||||
{
|
||||
std::string file_name = argv[arg+1];
|
||||
while (file_name[0] != '-') // if arg starts with '-', we consider it's not a file name but some other argument
|
||||
{
|
||||
// std::cout << "input file name : " << file_name << std::endl;
|
||||
store_input_file(input_filenames, file_name);
|
||||
arg += 1; // Skip that arg now we know it's a file name
|
||||
if ((arg + 1) == argc) // Break out of the loop if we reach the end of the arg list
|
||||
break;
|
||||
file_name = argv[arg+1]; // Next argument and loop over
|
||||
}
|
||||
}
|
||||
else if ((!strcmp(argv[arg], "--output") || !strcmp(argv[arg], "-o")) && arg < argc-1)
|
||||
{
|
||||
std::string file_name = argv[arg+1];
|
||||
while (file_name[0] != '-') // if arg starts with '-', we consider it's not a file name but some other argument
|
||||
{
|
||||
// std::cout << "output file name : " << file_name << std::endl;
|
||||
store_output_file(output_filenames, input_filenames, file_name);
|
||||
arg += 1; // Skip that arg now we know it's a file name
|
||||
if ((arg + 1) == argc) // Break out of the loop if we reach the end of the arg list
|
||||
break;
|
||||
file_name = argv[arg+1]; // Next argument and loop over
|
||||
}
|
||||
}
|
||||
else if (!strcmp(argv[arg], "--logmetrics") || !strcmp(argv[arg], "-log"))
|
||||
{
|
||||
// '--logmetrics' needs to be specified with a named test metric argument
|
||||
// Note: for the moment, only ImageCompressionTester has been tested
|
||||
std::string test_name;
|
||||
if ((arg + 1) < argc)
|
||||
{
|
||||
test_name = argv[arg+1];
|
||||
}
|
||||
if (((arg + 1) >= argc) || (test_name[0] == '-'))
|
||||
{
|
||||
// We don't have an argument left in the arg list or the next argument is another option
|
||||
std::cout << "No --logmetrics argument given, no perf data will be gathered" << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
LLFastTimer::sMetricLog = TRUE;
|
||||
LLFastTimer::sLogName = test_name;
|
||||
arg += 1; // Skip that arg now we know it's a valid test name
|
||||
if ((arg + 1) == argc) // Break out of the loop if we reach the end of the arg list
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (!strcmp(argv[arg], "--analyzeperformance") || !strcmp(argv[arg], "-r"))
|
||||
{
|
||||
analyze_performance = true;
|
||||
}
|
||||
else if (!strcmp(argv[arg], "--image-stats") || !strcmp(argv[arg], "-s"))
|
||||
{
|
||||
image_stats = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Check arguments consistency. Exit with proper message if inconsistent.
|
||||
if (input_filenames.size() == 0)
|
||||
{
|
||||
std::cout << "No input file, nothing to do -> exit" << std::endl;
|
||||
return 0;
|
||||
}
|
||||
if (analyze_performance && !LLFastTimer::sMetricLog)
|
||||
{
|
||||
std::cout << "Cannot create perf report if no perf gathered (i.e. use argument -log <perf> with -r) -> exit" << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// Create the logging thread if required
|
||||
if (LLFastTimer::sMetricLog)
|
||||
{
|
||||
LLFastTimer::sLogLock = new LLMutex(NULL);
|
||||
fast_timer_log_thread = new LogThread(LLFastTimer::sLogName);
|
||||
fast_timer_log_thread->start();
|
||||
}
|
||||
|
||||
// Perform action on each input file
|
||||
std::list<std::string>::iterator in_file = input_filenames.begin();
|
||||
std::list<std::string>::iterator out_file = output_filenames.begin();
|
||||
std::list<std::string>::iterator in_end = input_filenames.end();
|
||||
std::list<std::string>::iterator out_end = output_filenames.end();
|
||||
for (; in_file != in_end; ++in_file)
|
||||
{
|
||||
// Load file
|
||||
LLPointer<LLImageRaw> raw_image = load_image(*in_file, image_stats);
|
||||
if (!raw_image)
|
||||
{
|
||||
std::cout << "Error: Image " << *in_file << " could not be loaded" << std::endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Save file
|
||||
if (out_file != out_end)
|
||||
{
|
||||
if (!save_image(*out_file, raw_image, image_stats))
|
||||
{
|
||||
std::cout << "Error: Image " << *out_file << " could not be saved" << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << *in_file << " -> " << *out_file << std::endl;
|
||||
}
|
||||
++out_file;
|
||||
}
|
||||
}
|
||||
|
||||
// Stop the perf gathering system if needed
|
||||
if (LLFastTimer::sMetricLog)
|
||||
{
|
||||
LLMetricPerformanceTesterBasic::deleteTester(LLFastTimer::sLogName);
|
||||
sAllDone = true;
|
||||
}
|
||||
|
||||
// Output perf data if requested by user
|
||||
if (analyze_performance)
|
||||
{
|
||||
std::cout << "Analyzing performance" << std::endl;
|
||||
|
||||
std::string baseline_name = LLFastTimer::sLogName + "_baseline.slp";
|
||||
std::string current_name = LLFastTimer::sLogName + ".slp";
|
||||
std::string report_name = LLFastTimer::sLogName + "_report.csv";
|
||||
|
||||
LLMetricPerformanceTesterBasic::doAnalysisMetrics(baseline_name, current_name, report_name);
|
||||
}
|
||||
|
||||
// Cleanup and exit
|
||||
LLImage::cleanupClass();
|
||||
if (fast_timer_log_thread)
|
||||
{
|
||||
fast_timer_log_thread->shutdown();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
/**
|
||||
* @file llimage_libtest.h
|
||||
*
|
||||
* $LicenseInfo:firstyear=2011&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2011, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
#ifndef LLIMAGE_LIBTEST_H
|
||||
#define LLIMAGE_LIBTEST_H
|
||||
|
||||
|
||||
#endif
|
||||
|
|
@ -63,7 +63,18 @@ BOOL LLMetricPerformanceTesterBasic::addTester(LLMetricPerformanceTesterBasic* t
|
|||
sTesterMap.insert(std::make_pair(name, tester));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/*static*/
|
||||
void LLMetricPerformanceTesterBasic::deleteTester(std::string name)
|
||||
{
|
||||
name_tester_map_t::iterator tester = sTesterMap.find(name);
|
||||
if (tester != sTesterMap.end())
|
||||
{
|
||||
delete tester->second;
|
||||
sTesterMap.erase(tester);
|
||||
}
|
||||
}
|
||||
|
||||
/*static*/
|
||||
LLMetricPerformanceTesterBasic* LLMetricPerformanceTesterBasic::getTester(std::string name)
|
||||
{
|
||||
|
|
@ -83,7 +94,78 @@ BOOL LLMetricPerformanceTesterBasic::isMetricLogRequested(std::string name)
|
|||
return (LLFastTimer::sMetricLog && ((LLFastTimer::sLogName == name) || (LLFastTimer::sLogName == DEFAULT_METRIC_NAME)));
|
||||
}
|
||||
|
||||
/*static*/
|
||||
LLSD LLMetricPerformanceTesterBasic::analyzeMetricPerformanceLog(std::istream& is)
|
||||
{
|
||||
LLSD ret;
|
||||
LLSD cur;
|
||||
|
||||
while (!is.eof() && LLSDSerialize::fromXML(cur, is))
|
||||
{
|
||||
for (LLSD::map_iterator iter = cur.beginMap(); iter != cur.endMap(); ++iter)
|
||||
{
|
||||
std::string label = iter->first;
|
||||
|
||||
LLMetricPerformanceTesterBasic* tester = LLMetricPerformanceTesterBasic::getTester(iter->second["Name"].asString()) ;
|
||||
if(tester)
|
||||
{
|
||||
ret[label]["Name"] = iter->second["Name"] ;
|
||||
|
||||
S32 num_of_metrics = tester->getNumberOfMetrics() ;
|
||||
for(S32 index = 0 ; index < num_of_metrics ; index++)
|
||||
{
|
||||
ret[label][ tester->getMetricName(index) ] = iter->second[ tester->getMetricName(index) ] ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*static*/
|
||||
void LLMetricPerformanceTesterBasic::doAnalysisMetrics(std::string baseline, std::string target, std::string output)
|
||||
{
|
||||
if(!LLMetricPerformanceTesterBasic::hasMetricPerformanceTesters())
|
||||
{
|
||||
return ;
|
||||
}
|
||||
|
||||
// Open baseline and current target, exit if one is inexistent
|
||||
std::ifstream base_is(baseline.c_str());
|
||||
std::ifstream target_is(target.c_str());
|
||||
if (!base_is.is_open() || !target_is.is_open())
|
||||
{
|
||||
llwarns << "'-analyzeperformance' error : baseline or current target file inexistent" << llendl;
|
||||
base_is.close();
|
||||
target_is.close();
|
||||
return;
|
||||
}
|
||||
|
||||
//analyze baseline
|
||||
LLSD base = analyzeMetricPerformanceLog(base_is);
|
||||
base_is.close();
|
||||
|
||||
//analyze current
|
||||
LLSD current = analyzeMetricPerformanceLog(target_is);
|
||||
target_is.close();
|
||||
|
||||
//output comparision
|
||||
std::ofstream os(output.c_str());
|
||||
|
||||
os << "Label, Metric, Base(B), Target(T), Diff(T-B), Percentage(100*T/B)\n";
|
||||
for(LLMetricPerformanceTesterBasic::name_tester_map_t::iterator iter = LLMetricPerformanceTesterBasic::sTesterMap.begin() ;
|
||||
iter != LLMetricPerformanceTesterBasic::sTesterMap.end() ; ++iter)
|
||||
{
|
||||
LLMetricPerformanceTesterBasic* tester = ((LLMetricPerformanceTesterBasic*)iter->second) ;
|
||||
tester->analyzePerformance(&os, &base, ¤t) ;
|
||||
}
|
||||
|
||||
os.flush();
|
||||
os.close();
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------------------------
|
||||
// LLMetricPerformanceTesterBasic : Tester instance methods
|
||||
//----------------------------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -62,6 +62,8 @@ public:
|
|||
*/
|
||||
virtual void analyzePerformance(std::ofstream* os, LLSD* base, LLSD* current) ;
|
||||
|
||||
static void doAnalysisMetrics(std::string baseline, std::string target, std::string output) ;
|
||||
|
||||
/**
|
||||
* @return Returns the number of the test metrics in this tester instance.
|
||||
*/
|
||||
|
|
@ -116,6 +118,7 @@ protected:
|
|||
private:
|
||||
void preOutputTestResults(LLSD* sd) ;
|
||||
void postOutputTestResults(LLSD* sd) ;
|
||||
static LLSD analyzeMetricPerformanceLog(std::istream& is) ;
|
||||
|
||||
std::string mName ; // Name of this tester instance
|
||||
S32 mCount ; // Current record count
|
||||
|
|
@ -134,6 +137,12 @@ public:
|
|||
*/
|
||||
static LLMetricPerformanceTesterBasic* getTester(std::string name) ;
|
||||
|
||||
/**
|
||||
* @return Delete the named tester from the list
|
||||
* @param[in] name - Name of the tester instance to delete.
|
||||
*/
|
||||
static void deleteTester(std::string name);
|
||||
|
||||
/**
|
||||
* @return Returns TRUE if that metric *or* the default catch all metric has been requested to be logged
|
||||
* @param[in] name - Name of the tester queried.
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@
|
|||
|
||||
const S32 LL_VERSION_MAJOR = 2;
|
||||
const S32 LL_VERSION_MINOR = 6;
|
||||
const S32 LL_VERSION_PATCH = 2;
|
||||
const S32 LL_VERSION_PATCH = 3;
|
||||
const S32 LL_VERSION_BUILD = 0;
|
||||
|
||||
const char * const LL_CHANNEL = "Second Life Developer";
|
||||
|
|
|
|||
|
|
@ -266,13 +266,13 @@ public:
|
|||
// subclasses must return a prefered file extension (lowercase without a leading dot)
|
||||
virtual std::string getExtension() = 0;
|
||||
// calcHeaderSize() returns the maximum size of header;
|
||||
// 0 indicates we don't know have a header and have to lead the entire file
|
||||
// 0 indicates we don't have a header and have to read the entire file
|
||||
virtual S32 calcHeaderSize() { return 0; };
|
||||
// calcDataSize() returns how many bytes to read to load discard_level (including header)
|
||||
virtual S32 calcDataSize(S32 discard_level);
|
||||
// calcDiscardLevelBytes() returns the smallest valid discard level based on the number of input bytes
|
||||
virtual S32 calcDiscardLevelBytes(S32 bytes);
|
||||
// getRawDiscardLevel()by default returns mDiscardLevel, but may be overridden (LLImageJ2C)
|
||||
// getRawDiscardLevel() by default returns mDiscardLevel, but may be overridden (LLImageJ2C)
|
||||
virtual S8 getRawDiscardLevel() { return mDiscardLevel; }
|
||||
|
||||
BOOL load(const std::string& filename);
|
||||
|
|
|
|||
|
|
@ -474,6 +474,7 @@ LLImageCompressionTester::LLImageCompressionTester() : LLMetricPerformanceTester
|
|||
|
||||
LLImageCompressionTester::~LLImageCompressionTester()
|
||||
{
|
||||
outputTestResults();
|
||||
LLImageJ2C::sTesterp = NULL;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -793,21 +793,7 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL
|
|||
if ( chat.mSourceType == CHAT_SOURCE_OBJECT && chat.mFromID.notNull())
|
||||
{
|
||||
// for object IMs, create a secondlife:///app/objectim SLapp
|
||||
std::string url = LLSLURL("objectim", chat.mFromID, "").getSLURLString();
|
||||
url += "?name=" + chat.mFromName;
|
||||
url += "&owner=" + chat.mOwnerID.asString();
|
||||
|
||||
std::string slurl = args["slurl"].asString();
|
||||
if (slurl.empty())
|
||||
{
|
||||
LLViewerRegion *region = LLWorld::getInstance()->getRegionFromPosAgent(chat.mPosAgent);
|
||||
if(region)
|
||||
{
|
||||
LLSLURL region_slurl(region->getName(), chat.mPosAgent);
|
||||
slurl = region_slurl.getLocationString();
|
||||
}
|
||||
}
|
||||
url += "&slurl=" + LLURI::escape(slurl);
|
||||
std::string url = LLViewerChat::getSenderSLURL(chat, args);
|
||||
|
||||
// set the link for the object name to be the objectim SLapp
|
||||
// (don't let object names with hyperlinks override our objectim Url)
|
||||
|
|
|
|||
|
|
@ -213,17 +213,6 @@ void LLNearbyChatToastPanel::init(LLSD& notification)
|
|||
{
|
||||
LLStyle::Params style_params_name;
|
||||
|
||||
std::string href;
|
||||
|
||||
if (mSourceType == CHAT_SOURCE_AGENT)
|
||||
{
|
||||
href = LLSLURL("agent", mFromID, "about").getSLURLString();
|
||||
}
|
||||
else
|
||||
{
|
||||
href = LLSLURL("object", mFromID, "inspect").getSLURLString();
|
||||
}
|
||||
|
||||
LLColor4 user_name_color = LLUIColorTable::instance().getColor("HTMLLinkColor");
|
||||
style_params_name.color(user_name_color);
|
||||
|
||||
|
|
@ -232,7 +221,7 @@ void LLNearbyChatToastPanel::init(LLSD& notification)
|
|||
style_params_name.font.name(font_name);
|
||||
style_params_name.font.size(font_style_size);
|
||||
|
||||
style_params_name.link_href = href;
|
||||
style_params_name.link_href = notification["sender_slurl"].asString();
|
||||
style_params_name.is_link = true;
|
||||
|
||||
msg_text->appendText(str_sender, FALSE, style_params_name);
|
||||
|
|
|
|||
|
|
@ -1538,36 +1538,6 @@ void LLFastTimerView::doAnalysisDefault(std::string baseline, std::string target
|
|||
os.close();
|
||||
}
|
||||
|
||||
//-------------------------
|
||||
//static
|
||||
LLSD LLFastTimerView::analyzeMetricPerformanceLog(std::istream& is)
|
||||
{
|
||||
LLSD ret;
|
||||
LLSD cur;
|
||||
|
||||
while (!is.eof() && LLSDSerialize::fromXML(cur, is))
|
||||
{
|
||||
for (LLSD::map_iterator iter = cur.beginMap(); iter != cur.endMap(); ++iter)
|
||||
{
|
||||
std::string label = iter->first;
|
||||
|
||||
LLMetricPerformanceTesterBasic* tester = LLMetricPerformanceTesterBasic::getTester(iter->second["Name"].asString()) ;
|
||||
if(tester)
|
||||
{
|
||||
ret[label]["Name"] = iter->second["Name"] ;
|
||||
|
||||
S32 num_of_metrics = tester->getNumberOfMetrics() ;
|
||||
for(S32 index = 0 ; index < num_of_metrics ; index++)
|
||||
{
|
||||
ret[label][ tester->getMetricName(index) ] = iter->second[ tester->getMetricName(index) ] ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
//static
|
||||
void LLFastTimerView::outputAllMetrics()
|
||||
{
|
||||
|
|
@ -1582,48 +1552,6 @@ void LLFastTimerView::outputAllMetrics()
|
|||
}
|
||||
}
|
||||
|
||||
//static
|
||||
void LLFastTimerView::doAnalysisMetrics(std::string baseline, std::string target, std::string output)
|
||||
{
|
||||
if(!LLMetricPerformanceTesterBasic::hasMetricPerformanceTesters())
|
||||
{
|
||||
return ;
|
||||
}
|
||||
|
||||
// Open baseline and current target, exit if one is inexistent
|
||||
std::ifstream base_is(baseline.c_str());
|
||||
std::ifstream target_is(target.c_str());
|
||||
if (!base_is.is_open() || !target_is.is_open())
|
||||
{
|
||||
llwarns << "'-analyzeperformance' error : baseline or current target file inexistent" << llendl;
|
||||
base_is.close();
|
||||
target_is.close();
|
||||
return;
|
||||
}
|
||||
|
||||
//analyze baseline
|
||||
LLSD base = analyzeMetricPerformanceLog(base_is);
|
||||
base_is.close();
|
||||
|
||||
//analyze current
|
||||
LLSD current = analyzeMetricPerformanceLog(target_is);
|
||||
target_is.close();
|
||||
|
||||
//output comparision
|
||||
std::ofstream os(output.c_str());
|
||||
|
||||
os << "Label, Metric, Base(B), Target(T), Diff(T-B), Percentage(100*T/B)\n";
|
||||
for(LLMetricPerformanceTesterBasic::name_tester_map_t::iterator iter = LLMetricPerformanceTesterBasic::sTesterMap.begin() ;
|
||||
iter != LLMetricPerformanceTesterBasic::sTesterMap.end() ; ++iter)
|
||||
{
|
||||
LLMetricPerformanceTesterBasic* tester = ((LLMetricPerformanceTesterBasic*)iter->second) ;
|
||||
tester->analyzePerformance(&os, &base, ¤t) ;
|
||||
}
|
||||
|
||||
os.flush();
|
||||
os.close();
|
||||
}
|
||||
|
||||
//static
|
||||
void LLFastTimerView::doAnalysis(std::string baseline, std::string target, std::string output)
|
||||
{
|
||||
|
|
@ -1635,7 +1563,7 @@ void LLFastTimerView::doAnalysis(std::string baseline, std::string target, std::
|
|||
|
||||
if(LLFastTimer::sMetricLog)
|
||||
{
|
||||
doAnalysisMetrics(baseline, target, output) ;
|
||||
LLMetricPerformanceTesterBasic::doAnalysisMetrics(baseline, target, output) ;
|
||||
return ;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,8 +42,6 @@ public:
|
|||
|
||||
private:
|
||||
static void doAnalysisDefault(std::string baseline, std::string target, std::string output) ;
|
||||
static void doAnalysisMetrics(std::string baseline, std::string target, std::string output) ;
|
||||
static LLSD analyzeMetricPerformanceLog(std::istream& is) ;
|
||||
static LLSD analyzePerformanceLogDefault(std::istream& is) ;
|
||||
static void exportCharts(const std::string& base, const std::string& target);
|
||||
|
||||
|
|
|
|||
|
|
@ -558,6 +558,7 @@ void LLNearbyChatHandler::processChat(const LLChat& chat_msg, const LLSD &args)
|
|||
}
|
||||
*/
|
||||
|
||||
// Add a nearby chat toast.
|
||||
LLUUID id;
|
||||
id.generate();
|
||||
|
||||
|
|
@ -583,6 +584,10 @@ void LLNearbyChatHandler::processChat(const LLChat& chat_msg, const LLSD &args)
|
|||
notification["text_color"] = r_color_name;
|
||||
notification["color_alpha"] = r_color_alpha;
|
||||
notification["font_size"] = (S32)LLViewerChat::getChatFontSize() ;
|
||||
|
||||
// Pass sender info so that it can be rendered properly (STORM-1021).
|
||||
notification["sender_slurl"] = LLViewerChat::getSenderSLURL(chat_msg, args);
|
||||
|
||||
channel->addNotification(notification);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -31,6 +31,8 @@
|
|||
#include "llagent.h" // gAgent
|
||||
#include "lluicolortable.h"
|
||||
#include "llviewercontrol.h" // gSavedSettings
|
||||
#include "llviewerregion.h"
|
||||
#include "llworld.h"
|
||||
#include "llinstantmessage.h" //SYSTEM_FROM
|
||||
|
||||
// LLViewerChat
|
||||
|
|
@ -214,3 +216,43 @@ void LLViewerChat::formatChatMsg(const LLChat& chat, std::string& formated_msg)
|
|||
|
||||
}
|
||||
|
||||
//static
|
||||
std::string LLViewerChat::getSenderSLURL(const LLChat& chat, const LLSD& args)
|
||||
{
|
||||
switch (chat.mSourceType)
|
||||
{
|
||||
case CHAT_SOURCE_AGENT:
|
||||
return LLSLURL("agent", chat.mFromID, "about").getSLURLString();
|
||||
|
||||
case CHAT_SOURCE_OBJECT:
|
||||
return getObjectImSLURL(chat, args);
|
||||
|
||||
default:
|
||||
llwarns << "Getting SLURL for an unsupported sender type: " << chat.mSourceType << llendl;
|
||||
}
|
||||
|
||||
return LLStringUtil::null;
|
||||
}
|
||||
|
||||
//static
|
||||
std::string LLViewerChat::getObjectImSLURL(const LLChat& chat, const LLSD& args)
|
||||
{
|
||||
std::string url = LLSLURL("objectim", chat.mFromID, "").getSLURLString();
|
||||
url += "?name=" + chat.mFromName;
|
||||
url += "&owner=" + chat.mOwnerID.asString();
|
||||
|
||||
std::string slurl = args["slurl"].asString();
|
||||
if (slurl.empty())
|
||||
{
|
||||
LLViewerRegion *region = LLWorld::getInstance()->getRegionFromPosAgent(chat.mPosAgent);
|
||||
if(region)
|
||||
{
|
||||
LLSLURL region_slurl(region->getName(), chat.mPosAgent);
|
||||
slurl = region_slurl.getLocationString();
|
||||
}
|
||||
}
|
||||
|
||||
url += "&slurl=" + LLURI::escape(slurl);
|
||||
|
||||
return url;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,6 +40,10 @@ public:
|
|||
static LLFontGL* getChatFont();
|
||||
static S32 getChatFontSize();
|
||||
static void formatChatMsg(const LLChat& chat, std::string& formated_msg);
|
||||
static std::string getSenderSLURL(const LLChat& chat, const LLSD& args);
|
||||
|
||||
private:
|
||||
static std::string getObjectImSLURL(const LLChat& chat, const LLSD& args);
|
||||
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ name="Stand Up">
|
|||
function="Self.EnableStandUp" />
|
||||
</menu_item_call>
|
||||
<menu_item_call
|
||||
label="Change Outfit"
|
||||
label="My Appearance"
|
||||
name="Change Outfit">
|
||||
<menu_item_call.on_click
|
||||
function="CustomizeAvatar" />
|
||||
|
|
|
|||
|
|
@ -193,7 +193,7 @@
|
|||
</menu_item_call>
|
||||
</context_menu>
|
||||
<menu_item_call
|
||||
label="Change Outfit"
|
||||
label="My Appearance"
|
||||
layout="topleft"
|
||||
name="Chenge Outfit">
|
||||
<menu_item_call.on_click
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@
|
|||
parameter="agent" />
|
||||
</menu_item_call>
|
||||
<menu_item_call
|
||||
label="Change Outfit"
|
||||
label="My Appearance"
|
||||
name="ChangeOutfit">
|
||||
<menu_item_call.on_click
|
||||
function="CustomizeAvatar" />
|
||||
|
|
|
|||
|
|
@ -819,22 +819,6 @@ You need to enter either the Username or both the First and Last name of your av
|
|||
</notification>
|
||||
|
||||
|
||||
<notification
|
||||
icon="alertmodal.tga"
|
||||
name="AddClassified"
|
||||
type="alertmodal">
|
||||
Classified ads appear in the 'Classified' section of the Search directory and on [http://secondlife.com/community/classifieds secondlife.com] for one week.
|
||||
Fill out your ad, then click 'Publish...' to add it to the directory.
|
||||
You'll be asked for a price to pay when clicking Publish.
|
||||
Paying more makes your ad appear higher in the list, and also appear higher when people search for keywords.
|
||||
<tag>confirm</tag>
|
||||
<usetemplate
|
||||
ignoretext="How to create a new Classified ad"
|
||||
name="okcancelignore"
|
||||
notext="Cancel"
|
||||
yestext="OK"/>
|
||||
</notification>
|
||||
|
||||
<notification
|
||||
icon="alertmodal.tga"
|
||||
name="DeleteClassified"
|
||||
|
|
|
|||
Loading…
Reference in New Issue