merge up from viewer-autobuild2010 through the start of 2.6.3
commit
77cd2e283a
1
.hgtags
1
.hgtags
|
|
@ -84,3 +84,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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1149,36 +1149,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()
|
||||
{
|
||||
|
|
@ -1193,48 +1163,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)
|
||||
{
|
||||
|
|
@ -1246,7 +1174,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) ;
|
||||
|
||||
public:
|
||||
|
|
|
|||
Loading…
Reference in New Issue