STORM-151 : merge kdu static linking, add indra/llkdu implementation. Doesn't build yet.
commit
94f44437d7
|
|
@ -60,22 +60,6 @@ if(WINDOWS)
|
|||
set(release_files ${release_files} fmod.dll)
|
||||
endif (FMOD)
|
||||
|
||||
#*******************************
|
||||
# LLKDU
|
||||
set(internal_llkdu_path "${CMAKE_SOURCE_DIR}/llkdu")
|
||||
if(NOT EXISTS ${internal_llkdu_path})
|
||||
if (EXISTS "${debug_src_dir}/llkdu.dll")
|
||||
set(debug_llkdu_src "${debug_src_dir}/llkdu.dll")
|
||||
set(debug_llkdu_dst "${SHARED_LIB_STAGING_DIR_DEBUG}/llkdu.dll")
|
||||
endif (EXISTS "${debug_src_dir}/llkdu.dll")
|
||||
|
||||
if (EXISTS "${release_src_dir}/llkdu.dll")
|
||||
set(release_llkdu_src "${release_src_dir}/llkdu.dll")
|
||||
set(release_llkdu_dst "${SHARED_LIB_STAGING_DIR_RELEASE}/llkdu.dll")
|
||||
set(relwithdebinfo_llkdu_dst "${SHARED_LIB_STAGING_DIR_RELWITHDEBINFO}/llkdu.dll")
|
||||
endif (EXISTS "${release_src_dir}/llkdu.dll")
|
||||
endif (NOT EXISTS ${internal_llkdu_path})
|
||||
|
||||
#*******************************
|
||||
# Copy MS C runtime dlls, required for packaging.
|
||||
# *TODO - Adapt this to support VC9
|
||||
|
|
@ -174,21 +158,6 @@ elseif(DARWIN)
|
|||
# fmod is statically linked on darwin
|
||||
set(fmod_files "")
|
||||
|
||||
#*******************************
|
||||
# LLKDU
|
||||
set(internal_llkdu_path "${CMAKE_SOURCE_DIR}/llkdu")
|
||||
if(NOT EXISTS ${internal_llkdu_path})
|
||||
if (EXISTS "${debug_src_dir}/libllkdu.dylib")
|
||||
set(debug_llkdu_src "${debug_src_dir}/libllkdu.dylib")
|
||||
set(debug_llkdu_dst "${SHARED_LIB_STAGING_DIR_DEBUG}/libllkdu.dylib")
|
||||
endif (EXISTS "${debug_src_dir}/libllkdu.dylib")
|
||||
|
||||
if (EXISTS "${release_src_dir}/libllkdu.dylib")
|
||||
set(release_llkdu_src "${release_src_dir}/libllkdu.dylib")
|
||||
set(release_llkdu_dst "${SHARED_LIB_STAGING_DIR_RELEASE}/libllkdu.dylib")
|
||||
set(relwithdebinfo_llkdu_dst "${SHARED_LIB_STAGING_DIR_RELWITHDEBINFO}/libllkdu.dylib")
|
||||
endif (EXISTS "${release_src_dir}/libllkdu.dylib")
|
||||
endif (NOT EXISTS ${internal_llkdu_path})
|
||||
elseif(LINUX)
|
||||
# linux is weird, multiple side by side configurations aren't supported
|
||||
# and we don't seem to have any debug shared libs built yet anyways...
|
||||
|
|
@ -242,21 +211,6 @@ elseif(LINUX)
|
|||
set(release_files ${release_files} "libfmod-3.75.so")
|
||||
endif (FMOD)
|
||||
|
||||
#*******************************
|
||||
# LLKDU
|
||||
set(internal_llkdu_path "${CMAKE_SOURCE_DIR}/llkdu")
|
||||
if(NOT EXISTS ${internal_llkdu_path})
|
||||
if (EXISTS "${debug_src_dir}/libllkdu.so")
|
||||
set(debug_llkdu_src "${debug_src_dir}/libllkdu.so")
|
||||
set(debug_llkdu_dst "${SHARED_LIB_STAGING_DIR_DEBUG}/libllkdu.so")
|
||||
endif (EXISTS "${debug_src_dir}/libllkdu.so")
|
||||
|
||||
if (EXISTS "${release_src_dir}/libllkdu.so")
|
||||
set(release_llkdu_src "${release_src_dir}/libllkdu.so")
|
||||
set(release_llkdu_dst "${SHARED_LIB_STAGING_DIR_RELEASE}/libllkdu.so")
|
||||
set(relwithdebinfo_llkdu_dst "${SHARED_LIB_STAGING_DIR_RELWITHDEBINFO}/libllkdu.so")
|
||||
endif (EXISTS "${release_src_dir}/libllkdu.so")
|
||||
endif(NOT EXISTS ${internal_llkdu_path})
|
||||
else(WINDOWS)
|
||||
message(STATUS "WARNING: unrecognized platform for staging 3rd party libs, skipping...")
|
||||
set(vivox_src_dir "${CMAKE_SOURCE_DIR}/newview/vivox-runtime/i686-linux")
|
||||
|
|
@ -334,40 +288,29 @@ copy_if_different(
|
|||
)
|
||||
set(third_party_targets ${third_party_targets} ${out_targets})
|
||||
|
||||
#*******************************
|
||||
# LLKDU
|
||||
set(internal_llkdu_path "${CMAKE_SOURCE_DIR}/llkdu")
|
||||
if(NOT EXISTS ${internal_llkdu_path})
|
||||
if (EXISTS "${debug_llkdu_src}")
|
||||
ADD_CUSTOM_COMMAND(
|
||||
OUTPUT ${debug_llkdu_dst}
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${debug_llkdu_src} ${debug_llkdu_dst}
|
||||
DEPENDS ${debug_llkdu_src}
|
||||
COMMENT "Copying llkdu.dll ${SHARED_LIB_STAGING_DIR_DEBUG}"
|
||||
)
|
||||
set(third_party_targets ${third_party_targets} $} ${debug_llkdu_dst})
|
||||
endif (EXISTS "${debug_llkdu_src}")
|
||||
|
||||
if (EXISTS "${release_llkdu_src}")
|
||||
ADD_CUSTOM_COMMAND(
|
||||
OUTPUT ${release_llkdu_dst}
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${release_llkdu_src} ${release_llkdu_dst}
|
||||
DEPENDS ${release_llkdu_src}
|
||||
COMMENT "Copying llkdu.dll ${SHARED_LIB_STAGING_DIR_RELEASE}"
|
||||
)
|
||||
set(third_party_targets ${third_party_targets} ${release_llkdu_dst})
|
||||
|
||||
ADD_CUSTOM_COMMAND(
|
||||
OUTPUT ${relwithdebinfo_llkdu_dst}
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${release_llkdu_src} ${relwithdebinfo_llkdu_dst}
|
||||
DEPENDS ${release_llkdu_src}
|
||||
COMMENT "Copying llkdu.dll ${SHARED_LIB_STAGING_DIR_RELWITHDEBINFO}"
|
||||
)
|
||||
set(third_party_targets ${third_party_targets} ${relwithdebinfo_llkdu_dst})
|
||||
endif (EXISTS "${release_llkdu_src}")
|
||||
|
||||
endif (NOT EXISTS ${internal_llkdu_path})
|
||||
|
||||
if (FMOD_SDK_DIR)
|
||||
copy_if_different(
|
||||
${FMOD_SDK_DIR}
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/Debug"
|
||||
out_targets
|
||||
${fmod_files}
|
||||
)
|
||||
set(all_targets ${all_targets} ${out_targets})
|
||||
copy_if_different(
|
||||
${FMOD_SDK_DIR}
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/Release"
|
||||
out_targets
|
||||
${fmod_files}
|
||||
)
|
||||
set(all_targets ${all_targets} ${out_targets})
|
||||
copy_if_different(
|
||||
${FMOD_SDK_DIR}
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/RelWithDbgInfo"
|
||||
out_targets
|
||||
${fmod_files}
|
||||
)
|
||||
set(all_targets ${all_targets} ${out_targets})
|
||||
endif (FMOD_SDK_DIR)
|
||||
|
||||
if(NOT STANDALONE)
|
||||
add_custom_target(
|
||||
|
|
|
|||
|
|
@ -1,7 +1,24 @@
|
|||
# -*- cmake -*-
|
||||
include(Prebuilt)
|
||||
|
||||
# USE_KDU can be set when launching cmake or develop.py as an option using the argument -DUSE_KDU:BOOL=ON
|
||||
# When building using proprietary binaries though (i.e. having access to LL private servers), we always build with KDU
|
||||
if (INSTALL_PROPRIETARY AND NOT STANDALONE)
|
||||
use_prebuilt_binary(kdu)
|
||||
set(LLKDU_LIBRARY llkdu)
|
||||
set(USE_KDU ON)
|
||||
endif (INSTALL_PROPRIETARY AND NOT STANDALONE)
|
||||
|
||||
if (USE_KDU)
|
||||
use_prebuilt_binary(kdu)
|
||||
if (WINDOWS)
|
||||
set(KDU_LIBRARY debug kdu_cored optimized kdu_core)
|
||||
else (WINDOWS)
|
||||
set(KDU_LIBRARY kdu)
|
||||
endif (WINDOWS)
|
||||
|
||||
set(KDU_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include)
|
||||
|
||||
set(LLKDU_LIBRARY llkdu)
|
||||
set(LLKDU_STATIC_LIBRARY llkdu_static)
|
||||
set(LLKDU_LIBRARIES ${LLKDU_LIBRARY})
|
||||
set(LLKDU_STATIC_LIBRARIES ${LLKDU_STATIC_LIBRARY})
|
||||
endif (USE_KDU)
|
||||
|
|
|
|||
|
|
@ -71,6 +71,8 @@ endif (DARWIN)
|
|||
target_link_libraries(llui_libtest
|
||||
llui
|
||||
llmessage
|
||||
${LLIMAGE_LIBRARIES}
|
||||
${LLIMAGEJ2COJ_LIBRARIES}
|
||||
${OS_LIBRARIES}
|
||||
${GOOGLE_PERFTOOLS_LIBRARIES}
|
||||
)
|
||||
|
|
|
|||
|
|
@ -70,6 +70,7 @@ set(llcommon_SOURCE_FILES
|
|||
llmemorystream.cpp
|
||||
llmemtype.cpp
|
||||
llmetrics.cpp
|
||||
llmetricperformancetester.cpp
|
||||
llmortician.cpp
|
||||
lloptioninterface.cpp
|
||||
llptrto.cpp
|
||||
|
|
@ -186,6 +187,7 @@ set(llcommon_HEADER_FILES
|
|||
llmemorystream.h
|
||||
llmemtype.h
|
||||
llmetrics.h
|
||||
llmetricperformancetester.h
|
||||
llmortician.h
|
||||
llnametable.h
|
||||
lloptioninterface.h
|
||||
|
|
|
|||
|
|
@ -56,6 +56,7 @@ bool LLFastTimer::sPauseHistory = 0;
|
|||
bool LLFastTimer::sResetHistory = 0;
|
||||
LLFastTimer::CurTimerData LLFastTimer::sCurTimerData;
|
||||
BOOL LLFastTimer::sLog = FALSE;
|
||||
std::string LLFastTimer::sLogName = "";
|
||||
BOOL LLFastTimer::sMetricLog = FALSE;
|
||||
LLMutex* LLFastTimer::sLogLock = NULL;
|
||||
std::queue<LLSD> LLFastTimer::sLogQueue;
|
||||
|
|
|
|||
|
|
@ -211,6 +211,7 @@ public:
|
|||
static std::queue<LLSD> sLogQueue;
|
||||
static BOOL sLog;
|
||||
static BOOL sMetricLog;
|
||||
static std::string sLogName;
|
||||
static bool sPauseHistory;
|
||||
static bool sResetHistory;
|
||||
static U64 sTimerCycles;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,254 @@
|
|||
/**
|
||||
* @file llmetricperformancetester.cpp
|
||||
* @brief LLMetricPerformanceTesterBasic and LLMetricPerformanceTesterWithSession classes implementation
|
||||
*
|
||||
* $LicenseInfo:firstyear=2004&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#include "linden_common.h"
|
||||
|
||||
#include "indra_constants.h"
|
||||
#include "llerror.h"
|
||||
#include "llsdserialize.h"
|
||||
#include "llstat.h"
|
||||
#include "lltreeiterators.h"
|
||||
#include "llmetricperformancetester.h"
|
||||
|
||||
//----------------------------------------------------------------------------------------------
|
||||
// LLMetricPerformanceTesterBasic : static methods and testers management
|
||||
//----------------------------------------------------------------------------------------------
|
||||
|
||||
LLMetricPerformanceTesterBasic::name_tester_map_t LLMetricPerformanceTesterBasic::sTesterMap ;
|
||||
|
||||
/*static*/
|
||||
void LLMetricPerformanceTesterBasic::cleanClass()
|
||||
{
|
||||
for (name_tester_map_t::iterator iter = sTesterMap.begin() ; iter != sTesterMap.end() ; ++iter)
|
||||
{
|
||||
delete iter->second ;
|
||||
}
|
||||
sTesterMap.clear() ;
|
||||
}
|
||||
|
||||
/*static*/
|
||||
BOOL LLMetricPerformanceTesterBasic::addTester(LLMetricPerformanceTesterBasic* tester)
|
||||
{
|
||||
llassert_always(tester != NULL);
|
||||
std::string name = tester->getTesterName() ;
|
||||
if (getTester(name))
|
||||
{
|
||||
llerrs << "Tester name is already used by some other tester : " << name << llendl ;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
sTesterMap.insert(std::make_pair(name, tester));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*static*/
|
||||
LLMetricPerformanceTesterBasic* LLMetricPerformanceTesterBasic::getTester(std::string name)
|
||||
{
|
||||
// Check for the requested metric name
|
||||
name_tester_map_t::iterator found_it = sTesterMap.find(name) ;
|
||||
if (found_it != sTesterMap.end())
|
||||
{
|
||||
return found_it->second ;
|
||||
}
|
||||
return NULL ;
|
||||
}
|
||||
|
||||
/*static*/
|
||||
// Return TRUE if this metric is requested or if the general default "catch all" metric is requested
|
||||
BOOL LLMetricPerformanceTesterBasic::isMetricLogRequested(std::string name)
|
||||
{
|
||||
return (LLFastTimer::sMetricLog && ((LLFastTimer::sLogName == name) || (LLFastTimer::sLogName == DEFAULT_METRIC_NAME)));
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------------------------
|
||||
// LLMetricPerformanceTesterBasic : Tester instance methods
|
||||
//----------------------------------------------------------------------------------------------
|
||||
|
||||
LLMetricPerformanceTesterBasic::LLMetricPerformanceTesterBasic(std::string name) :
|
||||
mName(name),
|
||||
mCount(0)
|
||||
{
|
||||
if (mName == std::string())
|
||||
{
|
||||
llerrs << "LLMetricPerformanceTesterBasic construction invalid : Empty name passed to constructor" << llendl ;
|
||||
}
|
||||
|
||||
mValidInstance = LLMetricPerformanceTesterBasic::addTester(this) ;
|
||||
}
|
||||
|
||||
LLMetricPerformanceTesterBasic::~LLMetricPerformanceTesterBasic()
|
||||
{
|
||||
}
|
||||
|
||||
void LLMetricPerformanceTesterBasic::preOutputTestResults(LLSD* sd)
|
||||
{
|
||||
incrementCurrentCount() ;
|
||||
(*sd)[getCurrentLabelName()]["Name"] = mName ;
|
||||
}
|
||||
|
||||
void LLMetricPerformanceTesterBasic::postOutputTestResults(LLSD* sd)
|
||||
{
|
||||
LLMutexLock lock(LLFastTimer::sLogLock);
|
||||
LLFastTimer::sLogQueue.push((*sd));
|
||||
}
|
||||
|
||||
void LLMetricPerformanceTesterBasic::outputTestResults()
|
||||
{
|
||||
LLSD sd;
|
||||
|
||||
preOutputTestResults(&sd) ;
|
||||
outputTestRecord(&sd) ;
|
||||
postOutputTestResults(&sd) ;
|
||||
}
|
||||
|
||||
void LLMetricPerformanceTesterBasic::addMetric(std::string str)
|
||||
{
|
||||
mMetricStrings.push_back(str) ;
|
||||
}
|
||||
|
||||
/*virtual*/
|
||||
void LLMetricPerformanceTesterBasic::analyzePerformance(std::ofstream* os, LLSD* base, LLSD* current)
|
||||
{
|
||||
resetCurrentCount() ;
|
||||
|
||||
std::string current_label = getCurrentLabelName();
|
||||
BOOL in_base = (*base).has(current_label) ;
|
||||
BOOL in_current = (*current).has(current_label) ;
|
||||
|
||||
while(in_base || in_current)
|
||||
{
|
||||
LLSD::String label = current_label ;
|
||||
|
||||
if(in_base && in_current)
|
||||
{
|
||||
*os << llformat("%s\n", label.c_str()) ;
|
||||
|
||||
for(U32 index = 0 ; index < mMetricStrings.size() ; index++)
|
||||
{
|
||||
switch((*current)[label][ mMetricStrings[index] ].type())
|
||||
{
|
||||
case LLSD::TypeInteger:
|
||||
compareTestResults(os, mMetricStrings[index],
|
||||
(S32)((*base)[label][ mMetricStrings[index] ].asInteger()), (S32)((*current)[label][ mMetricStrings[index] ].asInteger())) ;
|
||||
break ;
|
||||
case LLSD::TypeReal:
|
||||
compareTestResults(os, mMetricStrings[index],
|
||||
(F32)((*base)[label][ mMetricStrings[index] ].asReal()), (F32)((*current)[label][ mMetricStrings[index] ].asReal())) ;
|
||||
break;
|
||||
default:
|
||||
llerrs << "unsupported metric " << mMetricStrings[index] << " LLSD type: " << (S32)(*current)[label][ mMetricStrings[index] ].type() << llendl ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
incrementCurrentCount();
|
||||
current_label = getCurrentLabelName();
|
||||
in_base = (*base).has(current_label) ;
|
||||
in_current = (*current).has(current_label) ;
|
||||
}
|
||||
}
|
||||
|
||||
/*virtual*/
|
||||
void LLMetricPerformanceTesterBasic::compareTestResults(std::ofstream* os, std::string metric_string, S32 v_base, S32 v_current)
|
||||
{
|
||||
*os << llformat(" ,%s, %d, %d, %d, %.4f\n", metric_string.c_str(), v_base, v_current,
|
||||
v_current - v_base, (v_base != 0) ? 100.f * v_current / v_base : 0) ;
|
||||
}
|
||||
|
||||
/*virtual*/
|
||||
void LLMetricPerformanceTesterBasic::compareTestResults(std::ofstream* os, std::string metric_string, F32 v_base, F32 v_current)
|
||||
{
|
||||
*os << llformat(" ,%s, %.4f, %.4f, %.4f, %.4f\n", metric_string.c_str(), v_base, v_current,
|
||||
v_current - v_base, (fabs(v_base) > 0.0001f) ? 100.f * v_current / v_base : 0.f ) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------
|
||||
// LLMetricPerformanceTesterWithSession
|
||||
//----------------------------------------------------------------------------------------------
|
||||
|
||||
LLMetricPerformanceTesterWithSession::LLMetricPerformanceTesterWithSession(std::string name) :
|
||||
LLMetricPerformanceTesterBasic(name),
|
||||
mBaseSessionp(NULL),
|
||||
mCurrentSessionp(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
LLMetricPerformanceTesterWithSession::~LLMetricPerformanceTesterWithSession()
|
||||
{
|
||||
if (mBaseSessionp)
|
||||
{
|
||||
delete mBaseSessionp ;
|
||||
mBaseSessionp = NULL ;
|
||||
}
|
||||
if (mCurrentSessionp)
|
||||
{
|
||||
delete mCurrentSessionp ;
|
||||
mCurrentSessionp = NULL ;
|
||||
}
|
||||
}
|
||||
|
||||
/*virtual*/
|
||||
void LLMetricPerformanceTesterWithSession::analyzePerformance(std::ofstream* os, LLSD* base, LLSD* current)
|
||||
{
|
||||
// Load the base session
|
||||
resetCurrentCount() ;
|
||||
mBaseSessionp = loadTestSession(base) ;
|
||||
|
||||
// Load the current session
|
||||
resetCurrentCount() ;
|
||||
mCurrentSessionp = loadTestSession(current) ;
|
||||
|
||||
if (!mBaseSessionp || !mCurrentSessionp)
|
||||
{
|
||||
llerrs << "Error loading test sessions." << llendl ;
|
||||
}
|
||||
|
||||
// Compare
|
||||
compareTestSessions(os) ;
|
||||
|
||||
// Release memory
|
||||
if (mBaseSessionp)
|
||||
{
|
||||
delete mBaseSessionp ;
|
||||
mBaseSessionp = NULL ;
|
||||
}
|
||||
if (mCurrentSessionp)
|
||||
{
|
||||
delete mCurrentSessionp ;
|
||||
mCurrentSessionp = NULL ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------------------------
|
||||
// LLTestSession
|
||||
//----------------------------------------------------------------------------------------------
|
||||
|
||||
LLMetricPerformanceTesterWithSession::LLTestSession::~LLTestSession()
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,206 @@
|
|||
/**
|
||||
* @file llmetricperformancetester.h
|
||||
* @brief LLMetricPerformanceTesterBasic and LLMetricPerformanceTesterWithSession classes definition
|
||||
*
|
||||
* $LicenseInfo:firstyear=2004&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#ifndef LL_METRICPERFORMANCETESTER_H
|
||||
#define LL_METRICPERFORMANCETESTER_H
|
||||
|
||||
const std::string DEFAULT_METRIC_NAME("metric");
|
||||
|
||||
/**
|
||||
* @class LLMetricPerformanceTesterBasic
|
||||
* @brief Performance Metric Base Class
|
||||
*/
|
||||
class LL_COMMON_API LLMetricPerformanceTesterBasic
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Creates a basic tester instance.
|
||||
* @param[in] name - Unique string identifying this tester instance.
|
||||
*/
|
||||
LLMetricPerformanceTesterBasic(std::string name);
|
||||
virtual ~LLMetricPerformanceTesterBasic();
|
||||
|
||||
/**
|
||||
* @return Returns true if the instance has been added to the tester map.
|
||||
* Need to be tested after creation of a tester instance so to know if the tester is correctly handled.
|
||||
* A tester might not be added to the map if another tester with the same name already exists.
|
||||
*/
|
||||
BOOL isValid() const { return mValidInstance; }
|
||||
|
||||
/**
|
||||
* @brief Write a set of test results to the log LLSD.
|
||||
*/
|
||||
void outputTestResults() ;
|
||||
|
||||
/**
|
||||
* @brief Compare the test results.
|
||||
* By default, compares the test results against the baseline one by one, item by item,
|
||||
* in the increasing order of the LLSD record counter, starting from the first one.
|
||||
*/
|
||||
virtual void analyzePerformance(std::ofstream* os, LLSD* base, LLSD* current) ;
|
||||
|
||||
/**
|
||||
* @return Returns the number of the test metrics in this tester instance.
|
||||
*/
|
||||
S32 getNumberOfMetrics() const { return mMetricStrings.size() ;}
|
||||
/**
|
||||
* @return Returns the metric name at index
|
||||
* @param[in] index - Index on the list of metrics managed by this tester instance.
|
||||
*/
|
||||
std::string getMetricName(S32 index) const { return mMetricStrings[index] ;}
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @return Returns the name of this tester instance.
|
||||
*/
|
||||
std::string getTesterName() const { return mName ;}
|
||||
|
||||
/**
|
||||
* @brief Insert a new metric to be managed by this tester instance.
|
||||
* @param[in] str - Unique string identifying the new metric.
|
||||
*/
|
||||
void addMetric(std::string str) ;
|
||||
|
||||
/**
|
||||
* @brief Compare test results, provided in 2 flavors: compare integers and compare floats.
|
||||
* @param[out] os - Formatted output string holding the compared values.
|
||||
* @param[in] metric_string - Name of the metric.
|
||||
* @param[in] v_base - Base value of the metric.
|
||||
* @param[in] v_current - Current value of the metric.
|
||||
*/
|
||||
virtual void compareTestResults(std::ofstream* os, std::string metric_string, S32 v_base, S32 v_current) ;
|
||||
virtual void compareTestResults(std::ofstream* os, std::string metric_string, F32 v_base, F32 v_current) ;
|
||||
|
||||
/**
|
||||
* @brief Reset internal record count. Count starts with 1.
|
||||
*/
|
||||
void resetCurrentCount() { mCount = 1; }
|
||||
/**
|
||||
* @brief Increment internal record count.
|
||||
*/
|
||||
void incrementCurrentCount() { mCount++; }
|
||||
/**
|
||||
* @return Returns the label to be used for the current count. It's "TesterName"-"Count".
|
||||
*/
|
||||
std::string getCurrentLabelName() const { return llformat("%s-%d", mName.c_str(), mCount) ;}
|
||||
|
||||
/**
|
||||
* @brief Write a test record to the LLSD. Implementers need to overload this method.
|
||||
* @param[out] sd - The LLSD record to store metric data into.
|
||||
*/
|
||||
virtual void outputTestRecord(LLSD* sd) = 0 ;
|
||||
|
||||
private:
|
||||
void preOutputTestResults(LLSD* sd) ;
|
||||
void postOutputTestResults(LLSD* sd) ;
|
||||
|
||||
std::string mName ; // Name of this tester instance
|
||||
S32 mCount ; // Current record count
|
||||
BOOL mValidInstance; // TRUE if the instance is managed by the map
|
||||
std::vector< std::string > mMetricStrings ; // Metrics strings
|
||||
|
||||
// Static members managing the collection of testers
|
||||
public:
|
||||
// Map of all the tester instances in use
|
||||
typedef std::map< std::string, LLMetricPerformanceTesterBasic* > name_tester_map_t;
|
||||
static name_tester_map_t sTesterMap ;
|
||||
|
||||
/**
|
||||
* @return Returns a pointer to the tester
|
||||
* @param[in] name - Name of the tester instance queried.
|
||||
*/
|
||||
static LLMetricPerformanceTesterBasic* getTester(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.
|
||||
*/
|
||||
static BOOL isMetricLogRequested(std::string name);
|
||||
|
||||
/**
|
||||
* @return Returns TRUE if there's a tester defined, FALSE otherwise.
|
||||
*/
|
||||
static BOOL hasMetricPerformanceTesters() { return !sTesterMap.empty() ;}
|
||||
/**
|
||||
* @brief Delete all testers and reset the tester map
|
||||
*/
|
||||
static void cleanClass() ;
|
||||
|
||||
private:
|
||||
// Add a tester to the map. Returns false if adding fails.
|
||||
static BOOL addTester(LLMetricPerformanceTesterBasic* tester) ;
|
||||
};
|
||||
|
||||
/**
|
||||
* @class LLMetricPerformanceTesterWithSession
|
||||
* @brief Performance Metric Class with custom session
|
||||
*/
|
||||
class LL_COMMON_API LLMetricPerformanceTesterWithSession : public LLMetricPerformanceTesterBasic
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @param[in] name - Unique string identifying this tester instance.
|
||||
*/
|
||||
LLMetricPerformanceTesterWithSession(std::string name);
|
||||
virtual ~LLMetricPerformanceTesterWithSession();
|
||||
|
||||
/**
|
||||
* @brief Compare the test results.
|
||||
* This will be loading the base and current sessions and compare them using the virtual
|
||||
* abstract methods loadTestSession() and compareTestSessions()
|
||||
*/
|
||||
virtual void analyzePerformance(std::ofstream* os, LLSD* base, LLSD* current) ;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @class LLMetricPerformanceTesterWithSession::LLTestSession
|
||||
* @brief Defines an interface for the two abstract virtual functions loadTestSession() and compareTestSessions()
|
||||
*/
|
||||
class LL_COMMON_API LLTestSession
|
||||
{
|
||||
public:
|
||||
virtual ~LLTestSession() ;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Convert an LLSD log into a test session.
|
||||
* @param[in] log - The LLSD record
|
||||
* @return Returns the record as a test session
|
||||
*/
|
||||
virtual LLMetricPerformanceTesterWithSession::LLTestSession* loadTestSession(LLSD* log) = 0;
|
||||
|
||||
/**
|
||||
* @brief Compare the base session and the target session. Assumes base and current sessions have been loaded.
|
||||
* @param[out] os - The comparison result as a standard stream
|
||||
*/
|
||||
virtual void compareTestSessions(std::ofstream* os) = 0;
|
||||
|
||||
LLTestSession* mBaseSessionp;
|
||||
LLTestSession* mCurrentSessionp;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -57,7 +57,6 @@ add_library (llimage ${llimage_SOURCE_FILES})
|
|||
# Sort by high-level to low-level
|
||||
target_link_libraries(llimage
|
||||
llcommon
|
||||
llimagej2coj # *HACK: In theory a noop for KDU builds?
|
||||
${JPEG_LIBRARIES}
|
||||
${PNG_LIBRARIES}
|
||||
${ZLIB_LIBRARIES}
|
||||
|
|
|
|||
|
|
@ -52,13 +52,11 @@ LLMutex* LLImage::sMutex = NULL;
|
|||
void LLImage::initClass()
|
||||
{
|
||||
sMutex = new LLMutex(NULL);
|
||||
LLImageJ2C::openDSO();
|
||||
}
|
||||
|
||||
//static
|
||||
void LLImage::cleanupClass()
|
||||
{
|
||||
LLImageJ2C::closeDSO();
|
||||
delete sMutex;
|
||||
sMutex = NULL;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,148 +24,32 @@
|
|||
*/
|
||||
#include "linden_common.h"
|
||||
|
||||
#include "apr_pools.h"
|
||||
#include "apr_dso.h"
|
||||
|
||||
#include "lldir.h"
|
||||
#include "llimagej2c.h"
|
||||
#include "llmemtype.h"
|
||||
#include "lltimer.h"
|
||||
#include "llmath.h"
|
||||
|
||||
typedef LLImageJ2CImpl* (*CreateLLImageJ2CFunction)();
|
||||
typedef void (*DestroyLLImageJ2CFunction)(LLImageJ2CImpl*);
|
||||
typedef const char* (*EngineInfoLLImageJ2CFunction)();
|
||||
|
||||
//some "private static" variables so we only attempt to load
|
||||
//dynamic libaries once
|
||||
CreateLLImageJ2CFunction j2cimpl_create_func;
|
||||
DestroyLLImageJ2CFunction j2cimpl_destroy_func;
|
||||
EngineInfoLLImageJ2CFunction j2cimpl_engineinfo_func;
|
||||
apr_pool_t *j2cimpl_dso_memory_pool;
|
||||
apr_dso_handle_t *j2cimpl_dso_handle;
|
||||
|
||||
//Declare the prototype for theses functions here, their functionality
|
||||
//will be implemented in other files which define a derived LLImageJ2CImpl
|
||||
//but only ONE static library which has the implementation for this
|
||||
//function should ever be included
|
||||
// Declare the prototype for theses functions here. Their functionality
|
||||
// will be implemented in other files which define a derived LLImageJ2CImpl
|
||||
// but only ONE static library which has the implementation for these
|
||||
// functions should ever be included.
|
||||
LLImageJ2CImpl* fallbackCreateLLImageJ2CImpl();
|
||||
void fallbackDestroyLLImageJ2CImpl(LLImageJ2CImpl* impl);
|
||||
const char* fallbackEngineInfoLLImageJ2CImpl();
|
||||
|
||||
//static
|
||||
//Loads the required "create", "destroy" and "engineinfo" functions needed
|
||||
void LLImageJ2C::openDSO()
|
||||
{
|
||||
//attempt to load a DSO and get some functions from it
|
||||
std::string dso_name;
|
||||
std::string dso_path;
|
||||
|
||||
bool all_functions_loaded = false;
|
||||
apr_status_t rv;
|
||||
|
||||
#if LL_WINDOWS
|
||||
dso_name = "llkdu.dll";
|
||||
#elif LL_DARWIN
|
||||
dso_name = "libllkdu.dylib";
|
||||
#else
|
||||
dso_name = "libllkdu.so";
|
||||
#endif
|
||||
|
||||
dso_path = gDirUtilp->findFile(dso_name,
|
||||
gDirUtilp->getAppRODataDir(),
|
||||
gDirUtilp->getExecutableDir());
|
||||
|
||||
j2cimpl_dso_handle = NULL;
|
||||
j2cimpl_dso_memory_pool = NULL;
|
||||
|
||||
//attempt to load the shared library
|
||||
apr_pool_create(&j2cimpl_dso_memory_pool, NULL);
|
||||
rv = apr_dso_load(&j2cimpl_dso_handle,
|
||||
dso_path.c_str(),
|
||||
j2cimpl_dso_memory_pool);
|
||||
|
||||
//now, check for success
|
||||
if ( rv == APR_SUCCESS )
|
||||
{
|
||||
//found the dynamic library
|
||||
//now we want to load the functions we're interested in
|
||||
CreateLLImageJ2CFunction create_func = NULL;
|
||||
DestroyLLImageJ2CFunction dest_func = NULL;
|
||||
EngineInfoLLImageJ2CFunction engineinfo_func = NULL;
|
||||
|
||||
rv = apr_dso_sym((apr_dso_handle_sym_t*)&create_func,
|
||||
j2cimpl_dso_handle,
|
||||
"createLLImageJ2CKDU");
|
||||
if ( rv == APR_SUCCESS )
|
||||
{
|
||||
//we've loaded the create function ok
|
||||
//we need to delete via the DSO too
|
||||
//so lets check for a destruction function
|
||||
rv = apr_dso_sym((apr_dso_handle_sym_t*)&dest_func,
|
||||
j2cimpl_dso_handle,
|
||||
"destroyLLImageJ2CKDU");
|
||||
if ( rv == APR_SUCCESS )
|
||||
{
|
||||
//we've loaded the destroy function ok
|
||||
rv = apr_dso_sym((apr_dso_handle_sym_t*)&engineinfo_func,
|
||||
j2cimpl_dso_handle,
|
||||
"engineInfoLLImageJ2CKDU");
|
||||
if ( rv == APR_SUCCESS )
|
||||
{
|
||||
//ok, everything is loaded alright
|
||||
j2cimpl_create_func = create_func;
|
||||
j2cimpl_destroy_func = dest_func;
|
||||
j2cimpl_engineinfo_func = engineinfo_func;
|
||||
all_functions_loaded = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( !all_functions_loaded )
|
||||
{
|
||||
//something went wrong with the DSO or function loading..
|
||||
//fall back onto our satefy impl creation function
|
||||
|
||||
#if 0
|
||||
// precious verbose debugging, sadly we can't use our
|
||||
// 'llinfos' stream etc. this early in the initialisation seq.
|
||||
char errbuf[256];
|
||||
fprintf(stderr, "failed to load syms from DSO %s (%s)\n",
|
||||
dso_name.c_str(), dso_path.c_str());
|
||||
apr_strerror(rv, errbuf, sizeof(errbuf));
|
||||
fprintf(stderr, "error: %d, %s\n", rv, errbuf);
|
||||
apr_dso_error(j2cimpl_dso_handle, errbuf, sizeof(errbuf));
|
||||
fprintf(stderr, "dso-error: %d, %s\n", rv, errbuf);
|
||||
#endif
|
||||
|
||||
if ( j2cimpl_dso_handle )
|
||||
{
|
||||
apr_dso_unload(j2cimpl_dso_handle);
|
||||
j2cimpl_dso_handle = NULL;
|
||||
}
|
||||
|
||||
if ( j2cimpl_dso_memory_pool )
|
||||
{
|
||||
apr_pool_destroy(j2cimpl_dso_memory_pool);
|
||||
j2cimpl_dso_memory_pool = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//static
|
||||
void LLImageJ2C::closeDSO()
|
||||
{
|
||||
if ( j2cimpl_dso_handle ) apr_dso_unload(j2cimpl_dso_handle);
|
||||
if (j2cimpl_dso_memory_pool) apr_pool_destroy(j2cimpl_dso_memory_pool);
|
||||
}
|
||||
// Test data gathering handle
|
||||
LLImageCompressionTester* LLImageJ2C::sTesterp = NULL ;
|
||||
const std::string sTesterName("ImageCompressionTester");
|
||||
|
||||
//static
|
||||
std::string LLImageJ2C::getEngineInfo()
|
||||
{
|
||||
if (!j2cimpl_engineinfo_func)
|
||||
j2cimpl_engineinfo_func = fallbackEngineInfoLLImageJ2CImpl;
|
||||
|
||||
return j2cimpl_engineinfo_func();
|
||||
return fallbackEngineInfoLLImageJ2CImpl();
|
||||
}
|
||||
|
||||
LLImageJ2C::LLImageJ2C() : LLImageFormatted(IMG_CODEC_J2C),
|
||||
|
|
@ -175,47 +59,32 @@ LLImageJ2C::LLImageJ2C() : LLImageFormatted(IMG_CODEC_J2C),
|
|||
mReversible(FALSE),
|
||||
mAreaUsedForDataSizeCalcs(0)
|
||||
{
|
||||
//We assume here that if we wanted to create via
|
||||
//a dynamic library that the approriate open calls were made
|
||||
//before any calls to this constructor.
|
||||
|
||||
//Therefore, a NULL creation function pointer here means
|
||||
//we either did not want to create using functions from the dynamic
|
||||
//library or there were issues loading it, either way
|
||||
//use our fall back
|
||||
if ( !j2cimpl_create_func )
|
||||
{
|
||||
j2cimpl_create_func = fallbackCreateLLImageJ2CImpl;
|
||||
}
|
||||
|
||||
mImpl = j2cimpl_create_func();
|
||||
mImpl = fallbackCreateLLImageJ2CImpl();
|
||||
|
||||
// Clear data size table
|
||||
for( S32 i = 0; i <= MAX_DISCARD_LEVEL; i++)
|
||||
{ // Array size is MAX_DISCARD_LEVEL+1
|
||||
mDataSizes[i] = 0;
|
||||
}
|
||||
|
||||
// If that test log has ben requested but not yet created, create it
|
||||
if (LLMetricPerformanceTesterBasic::isMetricLogRequested(sTesterName) && !LLMetricPerformanceTesterBasic::getTester(sTesterName))
|
||||
{
|
||||
sTesterp = new LLImageCompressionTester() ;
|
||||
if (!sTesterp->isValid())
|
||||
{
|
||||
delete sTesterp;
|
||||
sTesterp = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// virtual
|
||||
LLImageJ2C::~LLImageJ2C()
|
||||
{
|
||||
//We assume here that if we wanted to destroy via
|
||||
//a dynamic library that the approriate open calls were made
|
||||
//before any calls to this destructor.
|
||||
|
||||
//Therefore, a NULL creation function pointer here means
|
||||
//we either did not want to destroy using functions from the dynamic
|
||||
//library or there were issues loading it, either way
|
||||
//use our fall back
|
||||
if ( !j2cimpl_destroy_func )
|
||||
{
|
||||
j2cimpl_destroy_func = fallbackDestroyLLImageJ2CImpl;
|
||||
}
|
||||
|
||||
if ( mImpl )
|
||||
{
|
||||
j2cimpl_destroy_func(mImpl);
|
||||
fallbackDestroyLLImageJ2CImpl(mImpl);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -280,6 +149,7 @@ BOOL LLImageJ2C::decode(LLImageRaw *raw_imagep, F32 decode_time)
|
|||
// Returns TRUE to mean done, whether successful or not.
|
||||
BOOL LLImageJ2C::decodeChannels(LLImageRaw *raw_imagep, F32 decode_time, S32 first_channel, S32 max_channel_count )
|
||||
{
|
||||
LLTimer elapsed;
|
||||
LLMemType mt1(mMemType);
|
||||
|
||||
BOOL res = TRUE;
|
||||
|
|
@ -318,6 +188,21 @@ BOOL LLImageJ2C::decodeChannels(LLImageRaw *raw_imagep, F32 decode_time, S32 fir
|
|||
LLImage::setLastError(mLastError);
|
||||
}
|
||||
|
||||
LLImageCompressionTester* tester = (LLImageCompressionTester*)LLMetricPerformanceTesterBasic::getTester(sTesterName);
|
||||
if (tester)
|
||||
{
|
||||
// Decompression stat gathering
|
||||
// Note that we *do not* take into account the decompression failures data so we might overestimate the time spent processing
|
||||
|
||||
// Always add the decompression time to the stat
|
||||
tester->updateDecompressionStats(elapsed.getElapsedTimeF32()) ;
|
||||
if (res)
|
||||
{
|
||||
// The whole data stream is finally decompressed when res is returned as TRUE
|
||||
tester->updateDecompressionStats(this->getDataSize(), raw_imagep->getDataSize()) ;
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
@ -330,6 +215,7 @@ BOOL LLImageJ2C::encode(const LLImageRaw *raw_imagep, F32 encode_time)
|
|||
|
||||
BOOL LLImageJ2C::encode(const LLImageRaw *raw_imagep, const char* comment_text, F32 encode_time)
|
||||
{
|
||||
LLTimer elapsed;
|
||||
LLMemType mt1(mMemType);
|
||||
resetLastError();
|
||||
BOOL res = mImpl->encodeImpl(*this, *raw_imagep, comment_text, encode_time, mReversible);
|
||||
|
|
@ -337,6 +223,22 @@ BOOL LLImageJ2C::encode(const LLImageRaw *raw_imagep, const char* comment_text,
|
|||
{
|
||||
LLImage::setLastError(mLastError);
|
||||
}
|
||||
|
||||
LLImageCompressionTester* tester = (LLImageCompressionTester*)LLMetricPerformanceTesterBasic::getTester(sTesterName);
|
||||
if (tester)
|
||||
{
|
||||
// Compression stat gathering
|
||||
// Note that we *do not* take into account the compression failures cases so we night overestimate the time spent processing
|
||||
|
||||
// Always add the compression time to the stat
|
||||
tester->updateCompressionStats(elapsed.getElapsedTimeF32()) ;
|
||||
if (res)
|
||||
{
|
||||
// The whole data stream is finally compressed when res is returned as TRUE
|
||||
tester->updateCompressionStats(this->getDataSize(), raw_imagep->getDataSize()) ;
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
@ -540,3 +442,125 @@ void LLImageJ2C::updateRawDiscardLevel()
|
|||
LLImageJ2CImpl::~LLImageJ2CImpl()
|
||||
{
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------
|
||||
// Start of LLImageCompressionTester
|
||||
//----------------------------------------------------------------------------------------------
|
||||
LLImageCompressionTester::LLImageCompressionTester() : LLMetricPerformanceTesterBasic(sTesterName)
|
||||
{
|
||||
addMetric("Time Decompression (s)");
|
||||
addMetric("Volume In Decompression (kB)");
|
||||
addMetric("Volume Out Decompression (kB)");
|
||||
addMetric("Decompression Ratio (x:1)");
|
||||
addMetric("Perf Decompression (kB/s)");
|
||||
|
||||
addMetric("Time Compression (s)");
|
||||
addMetric("Volume In Compression (kB)");
|
||||
addMetric("Volume Out Compression (kB)");
|
||||
addMetric("Compression Ratio (x:1)");
|
||||
addMetric("Perf Compression (kB/s)");
|
||||
|
||||
mRunBytesInDecompression = 0;
|
||||
mRunBytesInCompression = 0;
|
||||
|
||||
mTotalBytesInDecompression = 0;
|
||||
mTotalBytesOutDecompression = 0;
|
||||
mTotalBytesInCompression = 0;
|
||||
mTotalBytesOutCompression = 0;
|
||||
|
||||
mTotalTimeDecompression = 0.0f;
|
||||
mTotalTimeCompression = 0.0f;
|
||||
}
|
||||
|
||||
LLImageCompressionTester::~LLImageCompressionTester()
|
||||
{
|
||||
LLImageJ2C::sTesterp = NULL;
|
||||
}
|
||||
|
||||
//virtual
|
||||
void LLImageCompressionTester::outputTestRecord(LLSD *sd)
|
||||
{
|
||||
std::string currentLabel = getCurrentLabelName();
|
||||
|
||||
F32 decompressionPerf = 0.0f;
|
||||
F32 compressionPerf = 0.0f;
|
||||
F32 decompressionRate = 0.0f;
|
||||
F32 compressionRate = 0.0f;
|
||||
|
||||
F32 totalkBInDecompression = (F32)(mTotalBytesInDecompression) / 1000.0;
|
||||
F32 totalkBOutDecompression = (F32)(mTotalBytesOutDecompression) / 1000.0;
|
||||
F32 totalkBInCompression = (F32)(mTotalBytesInCompression) / 1000.0;
|
||||
F32 totalkBOutCompression = (F32)(mTotalBytesOutCompression) / 1000.0;
|
||||
|
||||
if (!is_approx_zero(mTotalTimeDecompression))
|
||||
{
|
||||
decompressionPerf = totalkBInDecompression / mTotalTimeDecompression;
|
||||
}
|
||||
if (!is_approx_zero(totalkBInDecompression))
|
||||
{
|
||||
decompressionRate = totalkBOutDecompression / totalkBInDecompression;
|
||||
}
|
||||
if (!is_approx_zero(mTotalTimeCompression))
|
||||
{
|
||||
compressionPerf = totalkBInCompression / mTotalTimeCompression;
|
||||
}
|
||||
if (!is_approx_zero(totalkBOutCompression))
|
||||
{
|
||||
compressionRate = totalkBInCompression / totalkBOutCompression;
|
||||
}
|
||||
|
||||
(*sd)[currentLabel]["Time Decompression (s)"] = (LLSD::Real)mTotalTimeDecompression;
|
||||
(*sd)[currentLabel]["Volume In Decompression (kB)"] = (LLSD::Real)totalkBInDecompression;
|
||||
(*sd)[currentLabel]["Volume Out Decompression (kB)"]= (LLSD::Real)totalkBOutDecompression;
|
||||
(*sd)[currentLabel]["Decompression Ratio (x:1)"] = (LLSD::Real)decompressionRate;
|
||||
(*sd)[currentLabel]["Perf Decompression (kB/s)"] = (LLSD::Real)decompressionPerf;
|
||||
|
||||
(*sd)[currentLabel]["Time Compression (s)"] = (LLSD::Real)mTotalTimeCompression;
|
||||
(*sd)[currentLabel]["Volume In Compression (kB)"] = (LLSD::Real)totalkBInCompression;
|
||||
(*sd)[currentLabel]["Volume Out Compression (kB)"] = (LLSD::Real)totalkBOutCompression;
|
||||
(*sd)[currentLabel]["Compression Ratio (x:1)"] = (LLSD::Real)compressionRate;
|
||||
(*sd)[currentLabel]["Perf Compression (kB/s)"] = (LLSD::Real)compressionPerf;
|
||||
}
|
||||
|
||||
void LLImageCompressionTester::updateCompressionStats(const F32 deltaTime)
|
||||
{
|
||||
mTotalTimeCompression += deltaTime;
|
||||
}
|
||||
|
||||
void LLImageCompressionTester::updateCompressionStats(const S32 bytesCompress, const S32 bytesRaw)
|
||||
{
|
||||
mTotalBytesInCompression += bytesRaw;
|
||||
mRunBytesInCompression += bytesRaw;
|
||||
mTotalBytesOutCompression += bytesCompress;
|
||||
if (mRunBytesInCompression > (1000000))
|
||||
{
|
||||
// Output everything
|
||||
outputTestResults();
|
||||
// Reset the compression data of the run
|
||||
mRunBytesInCompression = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void LLImageCompressionTester::updateDecompressionStats(const F32 deltaTime)
|
||||
{
|
||||
mTotalTimeDecompression += deltaTime;
|
||||
}
|
||||
|
||||
void LLImageCompressionTester::updateDecompressionStats(const S32 bytesIn, const S32 bytesOut)
|
||||
{
|
||||
mTotalBytesInDecompression += bytesIn;
|
||||
mRunBytesInDecompression += bytesIn;
|
||||
mTotalBytesOutDecompression += bytesOut;
|
||||
if (mRunBytesInDecompression > (1000000))
|
||||
{
|
||||
// Output everything
|
||||
outputTestResults();
|
||||
// Reset the decompression data of the run
|
||||
mRunBytesInDecompression = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------
|
||||
// End of LLTexturePipelineTester
|
||||
//----------------------------------------------------------------------------------------------
|
||||
|
||||
|
|
|
|||
|
|
@ -29,8 +29,11 @@
|
|||
|
||||
#include "llimage.h"
|
||||
#include "llassettype.h"
|
||||
#include "llmetricperformancetester.h"
|
||||
|
||||
class LLImageJ2CImpl;
|
||||
class LLImageCompressionTester ;
|
||||
|
||||
class LLImageJ2C : public LLImageFormatted
|
||||
{
|
||||
protected:
|
||||
|
|
@ -69,14 +72,13 @@ public:
|
|||
static S32 calcHeaderSizeJ2C();
|
||||
static S32 calcDataSizeJ2C(S32 w, S32 h, S32 comp, S32 discard_level, F32 rate = 0.f);
|
||||
|
||||
static void openDSO();
|
||||
static void closeDSO();
|
||||
static std::string getEngineInfo();
|
||||
|
||||
|
||||
protected:
|
||||
friend class LLImageJ2CImpl;
|
||||
friend class LLImageJ2COJ;
|
||||
friend class LLImageJ2CKDU;
|
||||
friend class LLImageCompressionTester;
|
||||
void decodeFailed();
|
||||
void updateRawDiscardLevel();
|
||||
|
||||
|
|
@ -90,6 +92,9 @@ protected:
|
|||
BOOL mReversible;
|
||||
LLImageJ2CImpl *mImpl;
|
||||
std::string mLastError;
|
||||
|
||||
// Image compression/decompression tester
|
||||
static LLImageCompressionTester* sTesterp;
|
||||
};
|
||||
|
||||
// Derive from this class to implement JPEG2000 decoding
|
||||
|
|
@ -118,4 +123,40 @@ protected:
|
|||
|
||||
#define LINDEN_J2C_COMMENT_PREFIX "LL_"
|
||||
|
||||
//
|
||||
// This class is used for performance data gathering only.
|
||||
// Tracks the image compression / decompression data,
|
||||
// records and outputs them to the log file.
|
||||
//
|
||||
class LLImageCompressionTester : public LLMetricPerformanceTesterBasic
|
||||
{
|
||||
public:
|
||||
LLImageCompressionTester();
|
||||
~LLImageCompressionTester();
|
||||
|
||||
void updateDecompressionStats(const F32 deltaTime) ;
|
||||
void updateDecompressionStats(const S32 bytesIn, const S32 bytesOut) ;
|
||||
void updateCompressionStats(const F32 deltaTime) ;
|
||||
void updateCompressionStats(const S32 bytesIn, const S32 bytesOut) ;
|
||||
|
||||
protected:
|
||||
/*virtual*/ void outputTestRecord(LLSD* sd);
|
||||
|
||||
private:
|
||||
//
|
||||
// Data size
|
||||
//
|
||||
U32 mTotalBytesInDecompression; // Total bytes fed to decompressor
|
||||
U32 mTotalBytesOutDecompression; // Total bytes produced by decompressor
|
||||
U32 mTotalBytesInCompression; // Total bytes fed to compressor
|
||||
U32 mTotalBytesOutCompression; // Total bytes produced by compressor
|
||||
U32 mRunBytesInDecompression; // Bytes fed to decompressor in this run
|
||||
U32 mRunBytesInCompression; // Bytes fed to compressor in this run
|
||||
//
|
||||
// Time
|
||||
//
|
||||
F32 mTotalTimeDecompression; // Total time spent in computing decompression
|
||||
F32 mTotalTimeCompression; // Total time spent in computing compression
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -0,0 +1,85 @@
|
|||
# -*- cmake -*-
|
||||
|
||||
project(llkdu)
|
||||
|
||||
# Visual Studio 2005 has a dumb bug that causes it to fail compilation
|
||||
# of KDU if building with both optimisation and /WS (treat warnings as
|
||||
# errors), even when the specific warnings that make it croak are
|
||||
# disabled.
|
||||
|
||||
set(VS_DISABLE_FATAL_WARNINGS ON)
|
||||
|
||||
include(00-Common)
|
||||
include(LLCommon)
|
||||
include(LLImage)
|
||||
include(LLKDU)
|
||||
include(LLMath)
|
||||
#include(LLVFS)
|
||||
#include(Linking)
|
||||
|
||||
include_directories(
|
||||
${LLCOMMON_INCLUDE_DIRS}
|
||||
${LLIMAGE_INCLUDE_DIRS}
|
||||
${KDU_INCLUDE_DIR}
|
||||
${LLMATH_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
set(llkdu_SOURCE_FILES
|
||||
kdc_flow_control.cpp
|
||||
kde_flow_control.cpp
|
||||
kdu_image.cpp
|
||||
llblockdata.cpp
|
||||
llblockdecoder.cpp
|
||||
llblockencoder.cpp
|
||||
llimagej2ckdu.cpp
|
||||
llkdumem.cpp
|
||||
)
|
||||
|
||||
set(llkdu_HEADER_FILES
|
||||
CMakeLists.txt
|
||||
|
||||
kdc_flow_control.h
|
||||
kde_flow_control.h
|
||||
kdu_image.h
|
||||
kdu_image_local.h
|
||||
llblockdata.h
|
||||
llblockdecoder.h
|
||||
llblockencoder.h
|
||||
llimagej2ckdu.h
|
||||
llkdumem.h
|
||||
)
|
||||
|
||||
set_source_files_properties(${llkdu_HEADER_FILES}
|
||||
PROPERTIES HEADER_FILE_ONLY TRUE)
|
||||
|
||||
list(APPEND llkdu_SOURCE_FILES ${llkdu_HEADER_FILES})
|
||||
|
||||
if (WINDOWS)
|
||||
# This turns off the warning about flow control ending in a destructor.
|
||||
set_source_files_properties(
|
||||
kdu_image.cpp llkdumem.cpp
|
||||
PROPERTIES
|
||||
COMPILE_FLAGS "/wd4702 /wd4722"
|
||||
)
|
||||
|
||||
# This turns off the warning about sprintf in the following 2 files.
|
||||
set_source_files_properties(
|
||||
kde_flow_control.cpp kdc_flow_control.cpp
|
||||
PROPERTIES
|
||||
COMPILE_FLAGS /D_CRT_SECURE_NO_DEPRECATE
|
||||
)
|
||||
endif (WINDOWS)
|
||||
|
||||
if (LLKDU_LIBRARY)
|
||||
add_library (${LLKDU_STATIC_LIBRARY} ${llkdu_SOURCE_FILES})
|
||||
|
||||
target_link_libraries(
|
||||
${LLKDU_STATIC_LIBRARY}
|
||||
# ${LLIMAGE_LIBRARIES}
|
||||
# ${LLVFS_LIBRARIES}
|
||||
${LLMATH_LIBRARIES}
|
||||
# ${LLCOMMON_LIBRARIES}
|
||||
${KDU_LIBRARY}
|
||||
# ${WINDOWS_LIBRARIES}
|
||||
)
|
||||
endif (LLKDU_LIBRARY)
|
||||
|
|
@ -0,0 +1,162 @@
|
|||
/**
|
||||
* @file llblockdata.cpp
|
||||
* @brief Image block structure
|
||||
*
|
||||
* $LicenseInfo:firstyear=2010&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#include "linden_common.h"
|
||||
|
||||
#include "llblockdata.h"
|
||||
#include "llmath.h"
|
||||
|
||||
LLBlockData::LLBlockData(const U32 type)
|
||||
{
|
||||
mType = type;
|
||||
mWidth = 0;
|
||||
mHeight = 0;
|
||||
mRowStride = 0;
|
||||
mData = NULL;
|
||||
}
|
||||
|
||||
void LLBlockData::setData(U8 *data, const U32 width, const U32 height, const U32 row_stride)
|
||||
{
|
||||
mData = data;
|
||||
mWidth = width;
|
||||
mHeight = height;
|
||||
if (row_stride)
|
||||
{
|
||||
mRowStride = row_stride;
|
||||
}
|
||||
else
|
||||
{
|
||||
mRowStride = width * 4;
|
||||
}
|
||||
}
|
||||
|
||||
U32 LLBlockData::getType() const
|
||||
{
|
||||
return mType;
|
||||
}
|
||||
|
||||
|
||||
U8 *LLBlockData::getData() const
|
||||
{
|
||||
return mData;
|
||||
}
|
||||
|
||||
U32 LLBlockData::getSize() const
|
||||
{
|
||||
return mWidth*mHeight;
|
||||
}
|
||||
|
||||
U32 LLBlockData::getWidth() const
|
||||
{
|
||||
return mWidth;
|
||||
}
|
||||
U32 LLBlockData::getHeight() const
|
||||
{
|
||||
return mHeight;
|
||||
}
|
||||
|
||||
U32 LLBlockData::getRowStride() const
|
||||
{
|
||||
return mRowStride;
|
||||
}
|
||||
|
||||
LLBlockDataU32::LLBlockDataU32() : LLBlockData(BLOCK_TYPE_U32)
|
||||
{
|
||||
mPrecision = 32;
|
||||
}
|
||||
|
||||
void LLBlockDataU32::setData(U32 *data, const U32 width, const U32 height, const U32 row_stride)
|
||||
{
|
||||
LLBlockData::setData((U8 *)data, width, height, row_stride);
|
||||
}
|
||||
|
||||
U32 LLBlockDataU32::getSize() const
|
||||
{
|
||||
return mWidth*mHeight*4;
|
||||
}
|
||||
|
||||
void LLBlockDataU32::setPrecision(const U32 bits)
|
||||
{
|
||||
mPrecision = bits;
|
||||
}
|
||||
|
||||
U32 LLBlockDataU32::getPrecision() const
|
||||
{
|
||||
return mPrecision;
|
||||
}
|
||||
|
||||
void LLBlockDataF32::setPrecision(const U32 bits)
|
||||
{
|
||||
mPrecision = bits;
|
||||
}
|
||||
|
||||
U32 LLBlockDataF32::getPrecision() const
|
||||
{
|
||||
return mPrecision;
|
||||
}
|
||||
|
||||
void LLBlockDataF32::setData(F32 *data, const U32 width, const U32 height, const U32 row_stride)
|
||||
{
|
||||
LLBlockData::setData((U8 *)data, width, height, row_stride);
|
||||
}
|
||||
|
||||
void LLBlockDataF32::setMin(const F32 min)
|
||||
{
|
||||
mMin = min;
|
||||
}
|
||||
|
||||
void LLBlockDataF32::setMax(const F32 max)
|
||||
{
|
||||
mMax = max;
|
||||
}
|
||||
|
||||
void LLBlockDataF32::calcMinMax()
|
||||
{
|
||||
U32 x, y;
|
||||
|
||||
mMin = *(F32*)mData;
|
||||
mMax = mMin;
|
||||
|
||||
for (y = 0; y < mHeight; y++)
|
||||
{
|
||||
for (x = 0; x < mWidth; x++)
|
||||
{
|
||||
F32 data = *(F32*)(mData + y*mRowStride + x*4);
|
||||
mMin = llmin(data, mMin);
|
||||
mMax = llmax(data, mMax);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
F32 LLBlockDataF32::getMin() const
|
||||
{
|
||||
return mMin;
|
||||
}
|
||||
|
||||
F32 LLBlockDataF32::getMax() const
|
||||
{
|
||||
return mMax;
|
||||
}
|
||||
|
|
@ -0,0 +1,107 @@
|
|||
/**
|
||||
* @file llblockdata.h
|
||||
* @brief Image block structure
|
||||
*
|
||||
* $LicenseInfo:firstyear=2010&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#ifndef LL_LLBLOCKDATA_H
|
||||
#define LL_LLBLOCKDATA_H
|
||||
|
||||
#include "stdtypes.h"
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
//
|
||||
// This class stores all of the information about
|
||||
// a single channel of raw data, either integer
|
||||
// or floating point.
|
||||
//
|
||||
class LLBlockData
|
||||
{
|
||||
protected:
|
||||
U32 mType;
|
||||
U32 mWidth;
|
||||
U32 mHeight;
|
||||
U32 mRowStride;
|
||||
U8 *mData;
|
||||
public:
|
||||
enum
|
||||
{
|
||||
BLOCK_TYPE_U32 = 1,
|
||||
BLOCK_TYPE_F32 = 2
|
||||
};
|
||||
|
||||
LLBlockData(const U32 type);
|
||||
virtual ~LLBlockData() {}
|
||||
|
||||
void setData(U8 *data, const U32 width, const U32 height, const U32 row_stride = 0);
|
||||
|
||||
U32 getType() const;
|
||||
U8 *getData() const;
|
||||
virtual U32 getSize() const;
|
||||
U32 getWidth() const;
|
||||
U32 getHeight() const;
|
||||
U32 getRowStride() const;
|
||||
};
|
||||
|
||||
class LLBlockDataU32 : public LLBlockData
|
||||
{
|
||||
protected:
|
||||
U32 mPrecision;
|
||||
public:
|
||||
LLBlockDataU32();
|
||||
|
||||
void setData(U32 *data, const U32 width, const U32 height, const U32 row_stride = 0);
|
||||
void setPrecision(const U32 bits);
|
||||
|
||||
/*virtual*/ U32 getSize() const;
|
||||
U32 getPrecision() const;
|
||||
};
|
||||
|
||||
class LLBlockDataF32 : public LLBlockData
|
||||
{
|
||||
protected:
|
||||
U32 mPrecision;
|
||||
F32 mMin;
|
||||
F32 mMax;
|
||||
public:
|
||||
LLBlockDataF32()
|
||||
: LLBlockData(LLBlockData::BLOCK_TYPE_F32),
|
||||
mPrecision(0),
|
||||
mMin(0.f),
|
||||
mMax(0.f)
|
||||
{};
|
||||
|
||||
void setData(F32 *data, const U32 width, const U32 height, const U32 row_stride = 0);
|
||||
|
||||
void setPrecision(const U32 bits);
|
||||
void setMin(const F32 min);
|
||||
void setMax(const F32 max);
|
||||
|
||||
void calcMinMax();
|
||||
|
||||
U32 getPrecision() const;
|
||||
F32 getMin() const;
|
||||
F32 getMax() const;
|
||||
};
|
||||
|
||||
#endif // LL_LLBLOCKDATA_H
|
||||
|
|
@ -0,0 +1,273 @@
|
|||
/**
|
||||
* @file llblockdecoder.cpp
|
||||
* @brief Image block decompression
|
||||
*
|
||||
* $LicenseInfo:firstyear=2010&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#include "linden_common.h"
|
||||
|
||||
#include "llblockdecoder.h"
|
||||
|
||||
// KDU core header files
|
||||
#include "kdu/kdu_elementary.h"
|
||||
#include "kdu/kdu_messaging.h"
|
||||
#include "kdu/kdu_params.h"
|
||||
#include "kdu/kdu_compressed.h"
|
||||
#include "kdu/kdu_sample_processing.h"
|
||||
|
||||
// KDU utility functions.
|
||||
#include "kde_flow_control.h"
|
||||
|
||||
#include "llkdumem.h"
|
||||
|
||||
#include "llblockdata.h"
|
||||
#include "llerror.h"
|
||||
|
||||
|
||||
BOOL LLBlockDecoder::decodeU32(LLBlockDataU32 &block_data, U8 *source_data, const U32 source_size) const
|
||||
{
|
||||
U32 width, height;
|
||||
|
||||
llassert(source_data);
|
||||
|
||||
LLKDUMemSource source(source_data, source_size);
|
||||
|
||||
source.reset();
|
||||
|
||||
kdu_codestream codestream;
|
||||
|
||||
codestream.create(&source);
|
||||
codestream.set_fast();
|
||||
|
||||
kdu_dims dims;
|
||||
codestream.get_dims(0,dims);
|
||||
llassert(codestream.get_num_components() == 1);
|
||||
|
||||
width = dims.size.x;
|
||||
height = dims.size.y;
|
||||
|
||||
// Assumes U32 data.
|
||||
U8 *output = block_data.getData();
|
||||
|
||||
kdu_dims tile_indices;
|
||||
codestream.get_valid_tiles(tile_indices);
|
||||
|
||||
kdu_coords tpos;
|
||||
tpos.x = 0;
|
||||
tpos.y = 0;
|
||||
|
||||
// Now we are ready to walk through the tiles processing them one-by-one.
|
||||
while (tpos.y < tile_indices.size.y)
|
||||
{
|
||||
while (tpos.x < tile_indices.size.x)
|
||||
{
|
||||
kdu_tile tile = codestream.open_tile(tpos+tile_indices.pos);
|
||||
|
||||
kdu_resolution res = tile.access_component(0).access_resolution();
|
||||
kdu_dims tile_dims;
|
||||
res.get_dims(tile_dims);
|
||||
kdu_coords offset = tile_dims.pos - dims.pos;
|
||||
int row_gap = block_data.getRowStride(); // inter-row separation
|
||||
kdu_byte *buf = output + offset.y*row_gap + offset.x*4;
|
||||
|
||||
kdu_tile_comp tile_comp = tile.access_component(0);
|
||||
bool reversible = tile_comp.get_reversible();
|
||||
U32 precision = tile_comp.get_bit_depth();
|
||||
U32 precision_scale = 1 << precision;
|
||||
llassert(precision >= 8); // Else would have used 16 bit representation
|
||||
|
||||
kdu_resolution comp_res = tile_comp.access_resolution(); // Get top resolution
|
||||
kdu_dims comp_dims;
|
||||
comp_res.get_dims(comp_dims);
|
||||
|
||||
bool use_shorts = (tile_comp.get_bit_depth(true) <= 16);
|
||||
|
||||
kdu_line_buf line;
|
||||
kdu_sample_allocator allocator;
|
||||
kdu_pull_ifc engine;
|
||||
|
||||
line.pre_create(&allocator, comp_dims.size.x, reversible, use_shorts);
|
||||
if (res.which() == 0) // No DWT levels used
|
||||
{
|
||||
engine = kdu_decoder(res.access_subband(LL_BAND), &allocator, use_shorts);
|
||||
}
|
||||
else
|
||||
{
|
||||
engine = kdu_synthesis(res, &allocator, use_shorts);
|
||||
}
|
||||
allocator.finalize(); // Actually creates buffering resources
|
||||
|
||||
line.create(); // Grabs resources from the allocator.
|
||||
|
||||
// Do the actual processing
|
||||
while (tile_dims.size.y--)
|
||||
{
|
||||
engine.pull(line, true);
|
||||
int width = line.get_width();
|
||||
|
||||
llassert(line.get_buf32());
|
||||
llassert(!line.is_absolute());
|
||||
// Decompressed samples have a 32-bit representation (integer or float)
|
||||
kdu_sample32 *sp = line.get_buf32();
|
||||
// Transferring normalized floating point data.
|
||||
U32 *dest_u32 = (U32 *)buf;
|
||||
for (; width > 0; width--, sp++, dest_u32++)
|
||||
{
|
||||
if (sp->fval < -0.5f)
|
||||
{
|
||||
*dest_u32 = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
*dest_u32 = (U32)((sp->fval + 0.5f)*precision_scale);
|
||||
}
|
||||
}
|
||||
buf += row_gap;
|
||||
}
|
||||
engine.destroy();
|
||||
tile.close();
|
||||
tpos.x++;
|
||||
}
|
||||
tpos.y++;
|
||||
tpos.x = 0;
|
||||
}
|
||||
codestream.destroy();
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL LLBlockDecoder::decodeF32(LLBlockDataF32 &block_data, U8 *source_data, const U32 source_size, const F32 min, const F32 max) const
|
||||
{
|
||||
U32 width, height;
|
||||
F32 range, range_inv, float_offset;
|
||||
bool use_shorts = false;
|
||||
|
||||
range = max - min;
|
||||
range_inv = 1.f / range;
|
||||
float_offset = 0.5f*(max + min);
|
||||
|
||||
llassert(source_data);
|
||||
|
||||
LLKDUMemSource source(source_data, source_size);
|
||||
|
||||
source.reset();
|
||||
|
||||
kdu_codestream codestream;
|
||||
|
||||
codestream.create(&source);
|
||||
codestream.set_fast();
|
||||
|
||||
kdu_dims dims;
|
||||
codestream.get_dims(0,dims);
|
||||
llassert(codestream.get_num_components() == 1);
|
||||
|
||||
width = dims.size.x;
|
||||
height = dims.size.y;
|
||||
|
||||
// Assumes F32 data.
|
||||
U8 *output = block_data.getData();
|
||||
|
||||
kdu_dims tile_indices;
|
||||
codestream.get_valid_tiles(tile_indices);
|
||||
|
||||
kdu_coords tpos;
|
||||
tpos.x = 0;
|
||||
tpos.y = 0;
|
||||
|
||||
// Now we are ready to walk through the tiles processing them one-by-one.
|
||||
while (tpos.y < tile_indices.size.y)
|
||||
{
|
||||
while (tpos.x < tile_indices.size.x)
|
||||
{
|
||||
kdu_tile tile = codestream.open_tile(tpos+tile_indices.pos);
|
||||
|
||||
kdu_resolution res = tile.access_component(0).access_resolution();
|
||||
kdu_dims tile_dims;
|
||||
res.get_dims(tile_dims);
|
||||
kdu_coords offset = tile_dims.pos - dims.pos;
|
||||
int row_gap = block_data.getRowStride(); // inter-row separation
|
||||
kdu_byte *buf = output + offset.y*row_gap + offset.x*4;
|
||||
|
||||
kdu_tile_comp tile_comp = tile.access_component(0);
|
||||
bool reversible = tile_comp.get_reversible();
|
||||
|
||||
kdu_resolution comp_res = tile_comp.access_resolution(); // Get top resolution
|
||||
kdu_dims comp_dims;
|
||||
comp_res.get_dims(comp_dims);
|
||||
|
||||
kdu_line_buf line;
|
||||
kdu_sample_allocator allocator;
|
||||
kdu_pull_ifc engine;
|
||||
|
||||
line.pre_create(&allocator, comp_dims.size.x, reversible, use_shorts);
|
||||
if (res.which() == 0) // No DWT levels used
|
||||
{
|
||||
engine = kdu_decoder(res.access_subband(LL_BAND), &allocator, use_shorts);
|
||||
}
|
||||
else
|
||||
{
|
||||
engine = kdu_synthesis(res, &allocator, use_shorts);
|
||||
}
|
||||
allocator.finalize(); // Actually creates buffering resources
|
||||
|
||||
line.create(); // Grabs resources from the allocator.
|
||||
|
||||
// Do the actual processing
|
||||
while (tile_dims.size.y--)
|
||||
{
|
||||
engine.pull(line, true);
|
||||
int width = line.get_width();
|
||||
|
||||
llassert(line.get_buf32());
|
||||
llassert(!line.is_absolute());
|
||||
// Decompressed samples have a 32-bit representation (integer or float)
|
||||
kdu_sample32 *sp = line.get_buf32();
|
||||
// Transferring normalized floating point data.
|
||||
F32 *dest_f32 = (F32 *)buf;
|
||||
for (; width > 0; width--, sp++, dest_f32++)
|
||||
{
|
||||
if (sp->fval < -0.5f)
|
||||
{
|
||||
*dest_f32 = min;
|
||||
}
|
||||
else if (sp->fval > 0.5f)
|
||||
{
|
||||
*dest_f32 = max;
|
||||
}
|
||||
else
|
||||
{
|
||||
*dest_f32 = (sp->fval) * range + float_offset;
|
||||
}
|
||||
}
|
||||
buf += row_gap;
|
||||
}
|
||||
engine.destroy();
|
||||
tile.close();
|
||||
tpos.x++;
|
||||
}
|
||||
tpos.y++;
|
||||
tpos.x = 0;
|
||||
}
|
||||
codestream.destroy();
|
||||
return TRUE;
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
/**
|
||||
* @file llblockdecoder.h
|
||||
* @brief Image block decompression
|
||||
*
|
||||
* $LicenseInfo:firstyear=2010&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#ifndef LL_LLBLOCKDECODER_H
|
||||
#define LL_LLBLOCKDECODER_H
|
||||
|
||||
#include "stdtypes.h"
|
||||
|
||||
class LLBlockDataU32;
|
||||
class LLBlockDataF32;
|
||||
|
||||
class LLBlockDecoder
|
||||
{
|
||||
public:
|
||||
BOOL decodeU32(LLBlockDataU32 &block_data, U8 *source_data, const U32 source_size) const;
|
||||
BOOL decodeF32(LLBlockDataF32 &block_data, U8 *source_data, const U32 source_size, const F32 min, const F32 max) const;
|
||||
};
|
||||
|
||||
#endif // LL_LLBLOCKDECODER_H
|
||||
|
|
@ -0,0 +1,343 @@
|
|||
/**
|
||||
* @file llblockencoder.cpp
|
||||
* @brief Image block compression
|
||||
*
|
||||
* $LicenseInfo:firstyear=2010&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#include "linden_common.h"
|
||||
|
||||
#include "llblockencoder.h"
|
||||
|
||||
// KDU core header files
|
||||
#include "kdu/kdu_elementary.h"
|
||||
#include "kdu/kdu_messaging.h"
|
||||
#include "kdu/kdu_params.h"
|
||||
#include "kdu/kdu_compressed.h"
|
||||
#include "kdu/kdu_sample_processing.h"
|
||||
|
||||
// KDU utility functions.
|
||||
#include "kdc_flow_control.h"
|
||||
|
||||
#include "llkdumem.h"
|
||||
|
||||
#include "llblockdata.h"
|
||||
#include "llerror.h"
|
||||
|
||||
LLBlockEncoder::LLBlockEncoder()
|
||||
{
|
||||
mBPP = 0.f;
|
||||
}
|
||||
|
||||
U8 *LLBlockEncoder::encode(const LLBlockData &block_data, U32 &output_size) const
|
||||
{
|
||||
switch (block_data.getType())
|
||||
{
|
||||
case LLBlockData::BLOCK_TYPE_U32:
|
||||
{
|
||||
LLBlockDataU32 &bd_u32 = (LLBlockDataU32 &)block_data;
|
||||
return encodeU32(bd_u32, output_size);
|
||||
}
|
||||
case LLBlockData::BLOCK_TYPE_F32:
|
||||
{
|
||||
LLBlockDataF32 &bd_f32 = (LLBlockDataF32 &)block_data;
|
||||
return encodeF32(bd_f32, output_size);
|
||||
}
|
||||
default:
|
||||
llerrs << "Unsupported block type!" << llendl;
|
||||
output_size = 0;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
U8 *LLBlockEncoder::encodeU32(const LLBlockDataU32 &block_data, U32 &output_size) const
|
||||
{
|
||||
// OK, for now, just use the standard KDU encoder, with a single channel
|
||||
// integer channel.
|
||||
|
||||
// Collect simple arguments.
|
||||
bool allow_rate_prediction, allow_shorts, mem, quiet, no_weights;
|
||||
|
||||
allow_rate_prediction = true;
|
||||
allow_shorts = false;
|
||||
no_weights = false;
|
||||
bool use_absolute = false;
|
||||
mem = false;
|
||||
quiet = false;
|
||||
|
||||
// Set codestream options
|
||||
siz_params siz;
|
||||
S16 precision = block_data.getPrecision();
|
||||
|
||||
siz.set(Sdims,0,0,(U16)block_data.getHeight());
|
||||
siz.set(Sdims,0,1,(U16)block_data.getWidth());
|
||||
siz.set(Ssigned,0,0,false);
|
||||
siz.set(Scomponents,0,0,1);
|
||||
siz.set(Sprecision,0,0, precision);
|
||||
|
||||
// Construct the `kdu_codestream' object and parse all remaining arguments.
|
||||
output_size = block_data.getSize();
|
||||
if (output_size < 1000)
|
||||
{
|
||||
output_size = 1000;
|
||||
}
|
||||
|
||||
U8 *output_buffer = new U8[output_size];
|
||||
|
||||
LLKDUMemTarget output(output_buffer, output_size, block_data.getSize());
|
||||
|
||||
kdu_codestream codestream;
|
||||
codestream.create(&siz,&output);
|
||||
|
||||
codestream.access_siz()->parse_string("Clayers=1");
|
||||
codestream.access_siz()->finalize_all();
|
||||
|
||||
kdu_tile tile = codestream.open_tile(kdu_coords(0,0));
|
||||
|
||||
// Open tile-components and create processing engines and resources
|
||||
kdu_dims dims;
|
||||
kdu_sample_allocator allocator;
|
||||
kdu_tile_comp tile_comp;
|
||||
kdu_line_buf line;
|
||||
kdu_push_ifc engine;
|
||||
|
||||
tile_comp = tile.access_component(0);
|
||||
kdu_resolution res = tile_comp.access_resolution(); // Get top resolution
|
||||
|
||||
res.get_dims(dims);
|
||||
|
||||
line.pre_create(&allocator,dims.size.x, use_absolute, allow_shorts);
|
||||
|
||||
if (res.which() == 0) // No DWT levels (should not occur in this example)
|
||||
{
|
||||
engine = kdu_encoder(res.access_subband(LL_BAND),&allocator, use_absolute);
|
||||
}
|
||||
else
|
||||
{
|
||||
engine = kdu_analysis(res,&allocator, use_absolute);
|
||||
}
|
||||
|
||||
allocator.finalize(); // Actually creates buffering resources
|
||||
line.create(); // Grabs resources from the allocator.
|
||||
|
||||
// Now walk through the lines of the buffer, pushing them into the
|
||||
// relevant tile-component processing engines.
|
||||
|
||||
U32 *source_u32 = NULL;
|
||||
F32 scale_inv = 1.f / (1 << precision);
|
||||
|
||||
S32 y;
|
||||
for (y = 0; y < dims.size.y; y++)
|
||||
{
|
||||
source_u32 = (U32*)(block_data.getData() + y * block_data.getRowStride());
|
||||
kdu_sample32 *dest = line.get_buf32();
|
||||
for (S32 n=dims.size.x; n > 0; n--, dest++, source_u32++)
|
||||
{
|
||||
// Just pack it in, for now.
|
||||
dest->fval = (F32)(*source_u32) * scale_inv - 0.5f;// - 0.5f;
|
||||
}
|
||||
engine.push(line, true);
|
||||
}
|
||||
|
||||
// Cleanup
|
||||
engine.destroy(); // engines are interfaces; no default destructors
|
||||
|
||||
// Produce the final compressed output.
|
||||
kdu_long layer_bytes[1] = {0};
|
||||
|
||||
layer_bytes[0] = (kdu_long) (mBPP*block_data.getWidth()*block_data.getHeight());
|
||||
// Here we are not requesting specific sizes for any of the 12
|
||||
// quality layers. As explained in the description of
|
||||
// "kdu_codestream::flush" (see "kdu_compressed.h"), the rate allocator
|
||||
// will then assign the layers in such a way as to achieve roughly
|
||||
// two quality layers per octave change in bit-rate, with the final
|
||||
// layer reaching true lossless quality.
|
||||
|
||||
codestream.flush(layer_bytes,1);
|
||||
// You can see how many bytes were assigned
|
||||
// to each quality layer by looking at the entries of `layer_bytes' here.
|
||||
// The flush function can do a lot of interesting things which you may
|
||||
// want to spend some time looking into. In addition to targeting
|
||||
// specific bit-rates for each quality layer, it can be configured to
|
||||
// use rate-distortion slope thresholds of your choosing and to return
|
||||
// the thresholds which it finds to be best for any particular set of
|
||||
// target layer sizes. This opens the door to feedback-oriented rate
|
||||
// control for video. You should also look into the
|
||||
// "kdu_codestream::set_max_bytes" and
|
||||
// "kdu_codestream::set_min_slope_threshold" functions which can be
|
||||
// used to significantly speed up compression.
|
||||
codestream.destroy(); // All done: simple as that.
|
||||
|
||||
// Now that we're done encoding, create the new data buffer for the compressed
|
||||
// image and stick it there.
|
||||
|
||||
U8 *output_data = new U8[output_size];
|
||||
|
||||
memcpy(output_data, output_buffer, output_size);
|
||||
|
||||
output.close(); // Not really necessary here.
|
||||
|
||||
return output_data;
|
||||
}
|
||||
|
||||
U8 *LLBlockEncoder::encodeF32(const LLBlockDataF32 &block_data, U32 &output_size) const
|
||||
{
|
||||
// OK, for now, just use the standard KDU encoder, with a single channel
|
||||
// integer channel.
|
||||
|
||||
// Collect simple arguments.
|
||||
bool allow_rate_prediction, allow_shorts, mem, quiet, no_weights;
|
||||
|
||||
allow_rate_prediction = true;
|
||||
allow_shorts = false;
|
||||
no_weights = false;
|
||||
bool use_absolute = false;
|
||||
mem = false;
|
||||
quiet = false;
|
||||
|
||||
F32 min, max, range, range_inv, offset;
|
||||
min = block_data.getMin();
|
||||
max = block_data.getMax();
|
||||
range = max - min;
|
||||
range_inv = 1.f / range;
|
||||
offset = 0.5f*(max + min);
|
||||
|
||||
// Set codestream options
|
||||
siz_params siz;
|
||||
S16 precision = block_data.getPrecision(); // Assume precision is always 32 bits for floating point.
|
||||
|
||||
siz.set(Sdims,0,0,(U16)block_data.getHeight());
|
||||
siz.set(Sdims,0,1,(U16)block_data.getWidth());
|
||||
siz.set(Ssigned,0,0,false);
|
||||
siz.set(Scomponents,0,0,1);
|
||||
siz.set(Sprecision,0,0, precision);
|
||||
|
||||
// Construct the `kdu_codestream' object and parse all remaining arguments.
|
||||
output_size = block_data.getSize();
|
||||
if (output_size < 1000)
|
||||
{
|
||||
output_size = 1000;
|
||||
}
|
||||
|
||||
U8 *output_buffer = new U8[output_size*2];
|
||||
|
||||
LLKDUMemTarget output(output_buffer, output_size, block_data.getSize());
|
||||
|
||||
kdu_codestream codestream;
|
||||
codestream.create(&siz,&output);
|
||||
|
||||
codestream.access_siz()->parse_string("Clayers=1");
|
||||
codestream.access_siz()->finalize_all();
|
||||
|
||||
kdu_tile tile = codestream.open_tile(kdu_coords(0,0));
|
||||
|
||||
// Open tile-components and create processing engines and resources
|
||||
kdu_dims dims;
|
||||
kdu_sample_allocator allocator;
|
||||
kdu_tile_comp tile_comp;
|
||||
kdu_line_buf line;
|
||||
kdu_push_ifc engine;
|
||||
|
||||
tile_comp = tile.access_component(0);
|
||||
kdu_resolution res = tile_comp.access_resolution(); // Get top resolution
|
||||
|
||||
res.get_dims(dims);
|
||||
|
||||
line.pre_create(&allocator,dims.size.x, use_absolute, allow_shorts);
|
||||
|
||||
if (res.which() == 0) // No DWT levels (should not occur in this example)
|
||||
{
|
||||
engine = kdu_encoder(res.access_subband(LL_BAND),&allocator, use_absolute);
|
||||
}
|
||||
else
|
||||
{
|
||||
engine = kdu_analysis(res,&allocator, use_absolute);
|
||||
}
|
||||
|
||||
allocator.finalize(); // Actually creates buffering resources
|
||||
line.create(); // Grabs resources from the allocator.
|
||||
|
||||
// Now walk through the lines of the buffer, pushing them into the
|
||||
// relevant tile-component processing engines.
|
||||
|
||||
F32 *source_f32 = NULL;
|
||||
|
||||
S32 y;
|
||||
for (y = 0; y < dims.size.y; y++)
|
||||
{
|
||||
source_f32 = (F32*)(block_data.getData() + y * block_data.getRowStride());
|
||||
kdu_sample32 *dest = line.get_buf32();
|
||||
for (S32 n=dims.size.x; n > 0; n--, dest++, source_f32++)
|
||||
{
|
||||
dest->fval = ((*source_f32) - offset) * range_inv;
|
||||
}
|
||||
engine.push(line, true);
|
||||
}
|
||||
|
||||
// Cleanup
|
||||
engine.destroy(); // engines are interfaces; no default destructors
|
||||
|
||||
// Produce the final compressed output.
|
||||
kdu_long layer_bytes[1] = {0};
|
||||
|
||||
layer_bytes[0] = (kdu_long) (mBPP*block_data.getWidth()*block_data.getHeight());
|
||||
// Here we are not requesting specific sizes for any of the 12
|
||||
// quality layers. As explained in the description of
|
||||
// "kdu_codestream::flush" (see "kdu_compressed.h"), the rate allocator
|
||||
// will then assign the layers in such a way as to achieve roughly
|
||||
// two quality layers per octave change in bit-rate, with the final
|
||||
// layer reaching true lossless quality.
|
||||
|
||||
codestream.flush(layer_bytes,1);
|
||||
// You can see how many bytes were assigned
|
||||
// to each quality layer by looking at the entries of `layer_bytes' here.
|
||||
// The flush function can do a lot of interesting things which you may
|
||||
// want to spend some time looking into. In addition to targeting
|
||||
// specific bit-rates for each quality layer, it can be configured to
|
||||
// use rate-distortion slope thresholds of your choosing and to return
|
||||
// the thresholds which it finds to be best for any particular set of
|
||||
// target layer sizes. This opens the door to feedback-oriented rate
|
||||
// control for video. You should also look into the
|
||||
// "kdu_codestream::set_max_bytes" and
|
||||
// "kdu_codestream::set_min_slope_threshold" functions which can be
|
||||
// used to significantly speed up compression.
|
||||
codestream.destroy(); // All done: simple as that.
|
||||
|
||||
// Now that we're done encoding, create the new data buffer for the compressed
|
||||
// image and stick it there.
|
||||
|
||||
U8 *output_data = new U8[output_size];
|
||||
|
||||
memcpy(output_data, output_buffer, output_size);
|
||||
|
||||
output.close(); // Not really necessary here.
|
||||
|
||||
delete[] output_buffer;
|
||||
|
||||
return output_data;
|
||||
}
|
||||
|
||||
|
||||
void LLBlockEncoder::setBPP(const F32 bpp)
|
||||
{
|
||||
mBPP = bpp;
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
/**
|
||||
* @file llblockencoder.h
|
||||
* @brief Image block compression
|
||||
*
|
||||
* $LicenseInfo:firstyear=2010&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#ifndef LL_LLBLOCKENCODER_H
|
||||
#define LL_LLBLOCKENCODER_H
|
||||
|
||||
#include "stdtypes.h"
|
||||
|
||||
class LLBlockData;
|
||||
class LLBlockDataU32;
|
||||
class LLBlockDataF32;
|
||||
|
||||
class LLBlockEncoder
|
||||
{
|
||||
F32 mBPP; // bits per point
|
||||
public:
|
||||
LLBlockEncoder();
|
||||
U8 *encode(const LLBlockData &block_data, U32 &output_size) const;
|
||||
U8 *encodeU32(const LLBlockDataU32 &block_data, U32 &output_size) const;
|
||||
U8 *encodeF32(const LLBlockDataF32 &block_data, U32 &output_size) const;
|
||||
|
||||
void setBPP(const F32 bpp);
|
||||
};
|
||||
|
||||
#endif // LL_LLBLOCKENCODER_H
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,92 @@
|
|||
/**
|
||||
* @file llimagej2ckdu.h
|
||||
* @brief This is an implementation of JPEG2000 encode/decode using Kakadu
|
||||
*
|
||||
* $LicenseInfo:firstyear=2010&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#ifndef LL_LLIMAGEJ2CKDU_H
|
||||
#define LL_LLIMAGEJ2CKDU_H
|
||||
|
||||
#include "llimagej2c.h"
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
// KDU core header files
|
||||
#include "kdu/kdu_elementary.h"
|
||||
#include "kdu/kdu_messaging.h"
|
||||
#include "kdu/kdu_params.h"
|
||||
#include "kdu/kdu_compressed.h"
|
||||
#include "kdu/kdu_sample_processing.h"
|
||||
|
||||
class LLKDUDecodeState;
|
||||
class LLKDUMemSource;
|
||||
|
||||
class LLImageJ2CKDU : public LLImageJ2CImpl
|
||||
{
|
||||
public:
|
||||
enum ECodeStreamMode
|
||||
{
|
||||
MODE_FAST = 0,
|
||||
MODE_RESILIENT = 1,
|
||||
MODE_FUSSY = 2
|
||||
};
|
||||
|
||||
public:
|
||||
LLImageJ2CKDU();
|
||||
virtual ~LLImageJ2CKDU();
|
||||
|
||||
protected:
|
||||
/*virtual*/ BOOL getMetadata(LLImageJ2C &base);
|
||||
/*virtual*/ BOOL decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decode_time, S32 first_channel, S32 max_channel_count);
|
||||
/*virtual*/ BOOL encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, const char* comment_text, F32 encode_time=0.0,
|
||||
BOOL reversible=FALSE);
|
||||
|
||||
void setupCodeStream(LLImageJ2C &base, BOOL keep_codestream, ECodeStreamMode mode);
|
||||
void cleanupCodeStream();
|
||||
BOOL initDecode(LLImageJ2C &base, LLImageRaw &raw_image, F32 decode_time, ECodeStreamMode mode, S32 first_channel, S32 max_channel_count );
|
||||
|
||||
// Encode variable
|
||||
LLKDUMemSource *mInputp;
|
||||
kdu_codestream *mCodeStreamp;
|
||||
kdu_coords *mTPosp; // tile position
|
||||
kdu_dims *mTileIndicesp;
|
||||
|
||||
// Temporary variables for in-progress decodes...
|
||||
LLImageRaw *mRawImagep;
|
||||
LLKDUDecodeState *mDecodeState;
|
||||
};
|
||||
|
||||
#if LL_WINDOWS
|
||||
# define LLSYMEXPORT __declspec(dllexport)
|
||||
#elif LL_LINUX
|
||||
# define LLSYMEXPORT __attribute__ ((visibility("default")))
|
||||
#else
|
||||
# define LLSYMEXPORT /**/
|
||||
#endif
|
||||
|
||||
extern "C" LLSYMEXPORT const char* engineInfoLLImageJ2CKDU();
|
||||
extern "C" LLSYMEXPORT LLImageJ2CKDU* createLLImageJ2CKDU();
|
||||
extern "C" LLSYMEXPORT void destroyLLImageJ2CKDU(LLImageJ2CKDU* kdu);
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,392 @@
|
|||
/**
|
||||
* @file llkdumem.cpp
|
||||
* @brief Helper class for kdu memory management
|
||||
*
|
||||
* $LicenseInfo:firstyear=2010&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#include "linden_common.h"
|
||||
|
||||
#include "llkdumem.h"
|
||||
|
||||
// Various image utility functions from kdu
|
||||
#include "llerror.h"
|
||||
|
||||
#if defined(LL_WINDOWS)
|
||||
# pragma warning(disable: 4702) // unreachable code
|
||||
#endif
|
||||
|
||||
LLKDUMemIn::LLKDUMemIn(const U8 *data,
|
||||
const U32 size,
|
||||
const U16 width,
|
||||
const U16 height,
|
||||
const U8 in_num_components,
|
||||
siz_params *siz)
|
||||
{
|
||||
U8 n;
|
||||
|
||||
first_comp_idx = 0;
|
||||
rows = height;
|
||||
cols = width;
|
||||
num_components = in_num_components;
|
||||
alignment_bytes = 0;
|
||||
|
||||
for (n=0; n<3; ++n)
|
||||
{
|
||||
precision[n] = 0;
|
||||
}
|
||||
|
||||
for (n=0; n < num_components; ++n)
|
||||
{
|
||||
siz->set(Sdims,n,0,rows);
|
||||
siz->set(Sdims,n,1,cols);
|
||||
siz->set(Ssigned,n,0,false);
|
||||
siz->set(Sprecision,n,0,8);
|
||||
}
|
||||
incomplete_lines = NULL;
|
||||
free_lines = NULL;
|
||||
num_unread_rows = rows;
|
||||
|
||||
mData = data;
|
||||
mDataSize = size;
|
||||
mCurPos = 0;
|
||||
}
|
||||
|
||||
|
||||
LLKDUMemIn::~LLKDUMemIn()
|
||||
{
|
||||
if ((num_unread_rows > 0) || (incomplete_lines != NULL))
|
||||
{ kdu_warning w;
|
||||
w << "Not all rows of image components "
|
||||
<< first_comp_idx << " through "
|
||||
<< first_comp_idx+num_components-1
|
||||
<< " were consumed!";
|
||||
}
|
||||
image_line_buf *tmp;
|
||||
while ((tmp=incomplete_lines) != NULL)
|
||||
{
|
||||
incomplete_lines = tmp->next;
|
||||
delete tmp;
|
||||
}
|
||||
while ((tmp=free_lines) != NULL)
|
||||
{
|
||||
free_lines = tmp->next;
|
||||
delete tmp;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool LLKDUMemIn::get(int comp_idx, kdu_line_buf &line, int x_tnum)
|
||||
{
|
||||
int idx = comp_idx - this->first_comp_idx;
|
||||
assert((idx >= 0) && (idx < num_components));
|
||||
x_tnum = x_tnum*num_components+idx;
|
||||
image_line_buf *scan, *prev=NULL;
|
||||
for (scan=incomplete_lines; scan != NULL; prev=scan, scan=scan->next)
|
||||
{
|
||||
assert(scan->next_x_tnum >= x_tnum);
|
||||
if (scan->next_x_tnum == x_tnum)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (scan == NULL)
|
||||
{ // Need to read a new image line.
|
||||
assert(x_tnum == 0); // Must consume in very specific order.
|
||||
if (num_unread_rows == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if ((scan = free_lines) == NULL)
|
||||
{
|
||||
scan = new image_line_buf(cols+3,num_components);
|
||||
}
|
||||
free_lines = scan->next;
|
||||
if (prev == NULL)
|
||||
{
|
||||
incomplete_lines = scan;
|
||||
}
|
||||
else
|
||||
{
|
||||
prev->next = scan;
|
||||
}
|
||||
|
||||
// Copy from image buffer into scan.
|
||||
memcpy(scan->buf, mData+mCurPos, cols*num_components);
|
||||
mCurPos += cols*num_components;
|
||||
|
||||
num_unread_rows--;
|
||||
scan->accessed_samples = 0;
|
||||
scan->next_x_tnum = 0;
|
||||
}
|
||||
|
||||
assert((cols-scan->accessed_samples) >= line.get_width());
|
||||
|
||||
int comp_offset = idx;
|
||||
kdu_byte *sp = scan->buf+num_components*scan->accessed_samples + comp_offset;
|
||||
int n=line.get_width();
|
||||
|
||||
if (line.get_buf32() != NULL)
|
||||
{
|
||||
kdu_sample32 *dp = line.get_buf32();
|
||||
if (line.is_absolute())
|
||||
{ // 32-bit absolute integers
|
||||
for (; n > 0; n--, sp+=num_components, dp++)
|
||||
{
|
||||
dp->ival = ((kdu_int32)(*sp)) - 128;
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // true 32-bit floats
|
||||
for (; n > 0; n--, sp+=num_components, dp++)
|
||||
{
|
||||
dp->fval = (((float)(*sp)) / 256.0F) - 0.5F;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
kdu_sample16 *dp = line.get_buf16();
|
||||
if (line.is_absolute())
|
||||
{ // 16-bit absolute integers
|
||||
for (; n > 0; n--, sp+=num_components, dp++)
|
||||
{
|
||||
dp->ival = ((kdu_int16)(*sp)) - 128;
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // 16-bit normalized representation.
|
||||
for (; n > 0; n--, sp+=num_components, dp++)
|
||||
{
|
||||
dp->ival = (((kdu_int16)(*sp)) - 128) << (KDU_FIX_POINT-8);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
scan->next_x_tnum++;
|
||||
if (idx == (num_components-1))
|
||||
{
|
||||
scan->accessed_samples += line.get_width();
|
||||
}
|
||||
if (scan->accessed_samples == cols)
|
||||
{ // Send empty line to free list.
|
||||
assert(scan == incomplete_lines);
|
||||
incomplete_lines = scan->next;
|
||||
scan->next = free_lines;
|
||||
free_lines = scan;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
LLKDUMemOut::LLKDUMemOut(U8 *data, siz_params *siz, U8 in_num_components)
|
||||
{
|
||||
int is_signed = 0;
|
||||
int n;
|
||||
|
||||
// Allocate memory segment
|
||||
|
||||
first_comp_idx = 0;
|
||||
if (!(siz->get(Scomponents,0,0,num_components) &&
|
||||
siz->get(Sdims,first_comp_idx,0,rows) &&
|
||||
siz->get(Sdims,first_comp_idx,1,cols) &&
|
||||
siz->get(Ssigned,first_comp_idx,0,is_signed)))
|
||||
{
|
||||
kdu_error e; e << "Attempting to create output image files before "
|
||||
"all information is available concerning the image component "
|
||||
"dimensions, bit-depth and signed/unsigned characteristics.";
|
||||
}
|
||||
num_components -= first_comp_idx;
|
||||
|
||||
for (n=0; n < 3; n++)
|
||||
{
|
||||
precision[n] = 0;
|
||||
}
|
||||
|
||||
for (n=0; n < num_components; n++)
|
||||
{
|
||||
int prec;
|
||||
|
||||
if (!(siz->compare(Sdims,first_comp_idx+n,0,rows) &&
|
||||
siz->compare(Sdims,first_comp_idx+n,1,cols) &&
|
||||
siz->compare(Ssigned,first_comp_idx+n,0,is_signed)))
|
||||
{
|
||||
assert(n > 0);
|
||||
num_components = 1;
|
||||
break;
|
||||
}
|
||||
if (!siz->get(Sprecision,first_comp_idx+n,0,prec))
|
||||
{
|
||||
kdu_error e; e << "Attempting to create output image data before "
|
||||
"all information is available concerning the image component "
|
||||
"dimensions, bit-depth and signed/unsigned characteristics.";
|
||||
}
|
||||
llassert(n < 3);
|
||||
precision[n] = prec;
|
||||
}
|
||||
if (is_signed)
|
||||
{
|
||||
kdu_warning w;
|
||||
w << "Signed sample values will be written to the "
|
||||
"BMP file as unsigned 8-bit quantities, centered about 128.";
|
||||
}
|
||||
|
||||
mCurPos = 0;
|
||||
mData = data;
|
||||
mDataSize = rows*cols*num_components;
|
||||
|
||||
incomplete_lines = NULL;
|
||||
free_lines = NULL;
|
||||
num_unwritten_rows = rows;
|
||||
}
|
||||
|
||||
LLKDUMemOut::~LLKDUMemOut()
|
||||
{
|
||||
if ((num_unwritten_rows > 0) || (incomplete_lines != NULL))
|
||||
{
|
||||
kdu_warning w;
|
||||
w << "Not all rows of image components "
|
||||
<< first_comp_idx << " through "
|
||||
<< first_comp_idx+num_components-1
|
||||
<< " were completed!";
|
||||
}
|
||||
image_line_buf *tmp;
|
||||
|
||||
while ((tmp=incomplete_lines) != NULL)
|
||||
{
|
||||
incomplete_lines = tmp->next;
|
||||
delete tmp;
|
||||
}
|
||||
|
||||
while ((tmp=free_lines) != NULL)
|
||||
{
|
||||
free_lines = tmp->next;
|
||||
delete tmp;
|
||||
}
|
||||
|
||||
// Should either clean up or leave alone the data buffer...
|
||||
// cout << "Done Destroying" << endl;
|
||||
}
|
||||
|
||||
void LLKDUMemOut::put(int comp_idx, kdu_line_buf &line, int x_tnum)
|
||||
{
|
||||
int idx = 0;
|
||||
|
||||
idx = comp_idx - this->first_comp_idx;
|
||||
|
||||
assert((idx >= 0) && (idx < num_components));
|
||||
x_tnum = x_tnum*num_components+idx;
|
||||
image_line_buf *scan, *prev=NULL;
|
||||
for (scan=incomplete_lines; scan != NULL; prev=scan, scan=scan->next)
|
||||
{
|
||||
assert(scan->next_x_tnum >= x_tnum);
|
||||
if (scan->next_x_tnum == x_tnum)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (scan == NULL)
|
||||
{ // Need to open a new line buffer
|
||||
assert(x_tnum == 0); // Must consume in very specific order.
|
||||
if ((scan = free_lines) == NULL)
|
||||
{
|
||||
scan = new image_line_buf(cols+3,num_components);
|
||||
}
|
||||
free_lines = scan->next;
|
||||
if (prev == NULL)
|
||||
{
|
||||
incomplete_lines = scan;
|
||||
}
|
||||
else
|
||||
{
|
||||
prev->next = scan;
|
||||
}
|
||||
scan->accessed_samples = 0;
|
||||
scan->next_x_tnum = 0;
|
||||
}
|
||||
|
||||
assert((cols-scan->accessed_samples) >= line.get_width());
|
||||
|
||||
int comp_offset = idx;
|
||||
|
||||
if (line.get_buf32() != NULL)
|
||||
{
|
||||
if (line.is_absolute())
|
||||
{
|
||||
convert_ints_to_bytes(line.get_buf32(),
|
||||
scan->buf+num_components*scan->accessed_samples+comp_offset,
|
||||
line.get_width(),precision[idx],num_components);
|
||||
}
|
||||
else
|
||||
{
|
||||
convert_floats_to_bytes(line.get_buf32(),
|
||||
scan->buf+num_components*scan->accessed_samples+comp_offset,
|
||||
line.get_width(),precision[idx],num_components);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (line.is_absolute())
|
||||
{
|
||||
convert_shorts_to_bytes(line.get_buf16(),
|
||||
scan->buf+num_components*scan->accessed_samples+comp_offset,
|
||||
line.get_width(),precision[idx],num_components);
|
||||
}
|
||||
else
|
||||
{
|
||||
convert_fixpoint_to_bytes(line.get_buf16(),
|
||||
scan->buf+num_components*scan->accessed_samples+comp_offset,
|
||||
line.get_width(),precision[idx],num_components);
|
||||
}
|
||||
}
|
||||
|
||||
scan->next_x_tnum++;
|
||||
if (idx == (num_components-1))
|
||||
{
|
||||
scan->accessed_samples += line.get_width();
|
||||
}
|
||||
if (scan->accessed_samples == cols)
|
||||
{
|
||||
// Write completed line and send it to the free list.
|
||||
if (num_unwritten_rows == 0)
|
||||
{
|
||||
kdu_error e; e << "Attempting to write too many lines to image "
|
||||
"file for components " << first_comp_idx << " through "
|
||||
<< first_comp_idx+num_components-1 << ".";
|
||||
}
|
||||
if ((mCurPos + cols*num_components) > mDataSize)
|
||||
{
|
||||
llerrs << "LLKDUMemOut::put() too much data" << llendl;
|
||||
}
|
||||
// Write the data to the output buffer.
|
||||
memcpy(mData+mCurPos, scan->buf, cols*num_components);
|
||||
mCurPos += cols*num_components;
|
||||
|
||||
num_unwritten_rows--;
|
||||
assert(scan == incomplete_lines);
|
||||
incomplete_lines = scan->next;
|
||||
scan->next = free_lines;
|
||||
free_lines = scan;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,167 @@
|
|||
/**
|
||||
* @file llkdumem.h
|
||||
* @brief Helper class for kdu memory management
|
||||
*
|
||||
* $LicenseInfo:firstyear=2010&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#ifndef LL_LLKDUMEM_H
|
||||
#define LL_LLKDUMEM_H
|
||||
|
||||
// Support classes for reading and writing from memory buffers
|
||||
// for KDU
|
||||
#include "kdu_image.h"
|
||||
#include "kdu/kdu_elementary.h"
|
||||
#include "kdu/kdu_messaging.h"
|
||||
#include "kdu/kdu_params.h"
|
||||
#include "kdu/kdu_compressed.h"
|
||||
#include "kdu/kdu_sample_processing.h"
|
||||
#include "kdu_image_local.h"
|
||||
#include "stdtypes.h"
|
||||
|
||||
class LLKDUMemSource: public kdu_compressed_source
|
||||
{
|
||||
public: // Member functions
|
||||
LLKDUMemSource(U8 *input_buffer, U32 size)
|
||||
{
|
||||
mData = input_buffer;
|
||||
mSize = size;
|
||||
mCurPos = 0;
|
||||
}
|
||||
|
||||
~LLKDUMemSource()
|
||||
{
|
||||
}
|
||||
|
||||
int read(kdu_byte *buf, int num_bytes)
|
||||
{
|
||||
U32 num_out;
|
||||
num_out = num_bytes;
|
||||
|
||||
if ((mSize - mCurPos) < (U32)num_bytes)
|
||||
{
|
||||
num_out = mSize -mCurPos;
|
||||
}
|
||||
memcpy(buf, mData + mCurPos, num_out);
|
||||
mCurPos += num_out;
|
||||
return num_out;
|
||||
}
|
||||
|
||||
void reset()
|
||||
{
|
||||
mCurPos = 0;
|
||||
}
|
||||
private: // Data
|
||||
U8 *mData;
|
||||
U32 mSize;
|
||||
U32 mCurPos;
|
||||
};
|
||||
|
||||
class LLKDUMemTarget: public kdu_compressed_target
|
||||
{
|
||||
public: // Member functions
|
||||
LLKDUMemTarget(U8 *output_buffer, U32 &output_size, const U32 buffer_size)
|
||||
{
|
||||
mData = output_buffer;
|
||||
mSize = buffer_size;
|
||||
mCurPos = 0;
|
||||
mOutputSize = &output_size;
|
||||
}
|
||||
|
||||
~LLKDUMemTarget()
|
||||
{
|
||||
}
|
||||
|
||||
bool write(const kdu_byte *buf, int num_bytes)
|
||||
{
|
||||
U32 num_out;
|
||||
num_out = num_bytes;
|
||||
|
||||
if ((mSize - mCurPos) < (U32)num_bytes)
|
||||
{
|
||||
num_out = mSize - mCurPos;
|
||||
memcpy(mData + mCurPos, buf, num_out);
|
||||
return false;
|
||||
}
|
||||
memcpy(mData + mCurPos, buf, num_out);
|
||||
mCurPos += num_out;
|
||||
*mOutputSize = mCurPos;
|
||||
return true;
|
||||
}
|
||||
private: // Data
|
||||
U8 *mData;
|
||||
U32 mSize;
|
||||
U32 mCurPos;
|
||||
U32 *mOutputSize;
|
||||
};
|
||||
|
||||
|
||||
class LLKDUMemIn : public kdu_image_in_base
|
||||
{
|
||||
public: // Member functions
|
||||
LLKDUMemIn(const U8 *data,
|
||||
const U32 size,
|
||||
const U16 rows,
|
||||
const U16 cols,
|
||||
U8 in_num_components,
|
||||
siz_params *siz);
|
||||
~LLKDUMemIn();
|
||||
bool get(int comp_idx, kdu_line_buf &line, int x_tnum);
|
||||
|
||||
const U8 *mData;
|
||||
private: // Data
|
||||
int first_comp_idx;
|
||||
int num_components;
|
||||
int rows, cols;
|
||||
int alignment_bytes; // Number of 0's at end of each line.
|
||||
int precision[3];
|
||||
image_line_buf *incomplete_lines; // Each "sample" represents a full pixel
|
||||
image_line_buf *free_lines;
|
||||
int num_unread_rows;
|
||||
|
||||
U32 mCurPos;
|
||||
U32 mDataSize;
|
||||
};
|
||||
|
||||
class LLKDUMemOut : public kdu_image_out_base
|
||||
{
|
||||
public: // Member functions
|
||||
LLKDUMemOut(U8 *data, siz_params *siz, U8 in_num_components);
|
||||
LLKDUMemOut(siz_params *siz, U8 in_num_components);
|
||||
~LLKDUMemOut();
|
||||
void put(int comp_idx, kdu_line_buf &line, int x_tnum);
|
||||
|
||||
U8 *mData;
|
||||
private: // Data
|
||||
int first_comp_idx;
|
||||
int num_components;
|
||||
int rows, cols;
|
||||
int precision[3];
|
||||
image_line_buf *incomplete_lines; // Each "sample" represents a full pixel
|
||||
image_line_buf *free_lines;
|
||||
int num_unwritten_rows;
|
||||
|
||||
U32 mCurPos;
|
||||
U32 mDataSize;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -290,7 +290,6 @@ set(viewer_SOURCE_FILES
|
|||
llmediadataclient.cpp
|
||||
llmemoryview.cpp
|
||||
llmenucommands.cpp
|
||||
llmetricperformancetester.cpp
|
||||
llmimetypes.cpp
|
||||
llmorphview.cpp
|
||||
llmoveview.cpp
|
||||
|
|
@ -822,7 +821,6 @@ set(viewer_HEADER_FILES
|
|||
llmediadataclient.h
|
||||
llmemoryview.h
|
||||
llmenucommands.h
|
||||
llmetricperformancetester.h
|
||||
llmimetypes.h
|
||||
llmorphview.h
|
||||
llmoveview.h
|
||||
|
|
@ -1446,11 +1444,6 @@ if (WINDOWS)
|
|||
# In the meantime, if you have any ideas on how to easily maintain one list, either here or in viewer_manifest.py
|
||||
# and have the build deps get tracked *please* tell me about it.
|
||||
|
||||
if(LLKDU_LIBRARY)
|
||||
# Configure a var for llkdu which may not exist for all builds.
|
||||
set(LLKDU_DLL_SOURCE ${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/llkdu.dll)
|
||||
endif(LLKDU_LIBRARY)
|
||||
|
||||
if(USE_GOOGLE_PERFTOOLS)
|
||||
# Configure a var for tcmalloc location, if used.
|
||||
# Note the need to specify multiple names explicitly.
|
||||
|
|
@ -1467,7 +1460,6 @@ if (WINDOWS)
|
|||
#${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/libtcmalloc_minimal.dll => None ... Skipping libtcmalloc_minimal.dll
|
||||
${CMAKE_SOURCE_DIR}/../etc/message.xml
|
||||
${CMAKE_SOURCE_DIR}/../scripts/messages/message_template.msg
|
||||
${LLKDU_DLL_SOURCE}
|
||||
${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/llcommon.dll
|
||||
${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/libapr-1.dll
|
||||
${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/libaprutil-1.dll
|
||||
|
|
@ -1646,7 +1638,6 @@ target_link_libraries(${VIEWER_BINARY_NAME}
|
|||
${LLAUDIO_LIBRARIES}
|
||||
${LLCHARACTER_LIBRARIES}
|
||||
${LLIMAGE_LIBRARIES}
|
||||
${LLIMAGEJ2COJ_LIBRARIES}
|
||||
${LLINVENTORY_LIBRARIES}
|
||||
${LLMESSAGE_LIBRARIES}
|
||||
${LLPLUGIN_LIBRARIES}
|
||||
|
|
@ -1682,6 +1673,17 @@ target_link_libraries(${VIEWER_BINARY_NAME}
|
|||
${GOOGLE_PERFTOOLS_LIBRARIES}
|
||||
)
|
||||
|
||||
if (LLKDU_LIBRARY)
|
||||
target_link_libraries(${VIEWER_BINARY_NAME}
|
||||
${LLKDU_STATIC_LIBRARIES}
|
||||
${KDU_LIBRARY}
|
||||
)
|
||||
else (LLKDU_LIBRARY)
|
||||
target_link_libraries(${VIEWER_BINARY_NAME}
|
||||
${LLIMAGEJ2COJ_LIBRARIES}
|
||||
)
|
||||
endif (LLKDU_LIBRARY)
|
||||
|
||||
build_version(viewer)
|
||||
|
||||
set(ARTWORK_DIR ${CMAKE_CURRENT_SOURCE_DIR} CACHE PATH
|
||||
|
|
|
|||
|
|
@ -118,6 +118,8 @@
|
|||
<map>
|
||||
<key>desc</key>
|
||||
<string>Log metrics for benchmarking</string>
|
||||
<key>count</key>
|
||||
<integer>1</integer>
|
||||
<key>map-to</key>
|
||||
<string>LogMetrics</string>
|
||||
</map>
|
||||
|
|
|
|||
|
|
@ -510,16 +510,10 @@ class LLFastTimerLogThread : public LLThread
|
|||
public:
|
||||
std::string mFile;
|
||||
|
||||
LLFastTimerLogThread() : LLThread("fast timer log")
|
||||
LLFastTimerLogThread(std::string& test_name) : LLThread("fast timer log")
|
||||
{
|
||||
if(LLFastTimer::sLog)
|
||||
{
|
||||
mFile = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "performance.slp");
|
||||
}
|
||||
if(LLFastTimer::sMetricLog)
|
||||
{
|
||||
mFile = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "metric.slp");
|
||||
}
|
||||
std::string file_name = test_name + std::string(".slp");
|
||||
mFile = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, file_name);
|
||||
}
|
||||
|
||||
void run()
|
||||
|
|
@ -535,6 +529,7 @@ public:
|
|||
|
||||
os.close();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
//virtual
|
||||
|
|
@ -1643,22 +1638,16 @@ bool LLAppViewer::cleanup()
|
|||
{
|
||||
llinfos << "Analyzing performance" << llendl;
|
||||
|
||||
if(LLFastTimer::sLog)
|
||||
{
|
||||
LLFastTimerView::doAnalysis(
|
||||
gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "performance_baseline.slp"),
|
||||
gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "performance.slp"),
|
||||
gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "performance_report.csv"));
|
||||
}
|
||||
if(LLFastTimer::sMetricLog)
|
||||
{
|
||||
LLFastTimerView::doAnalysis(
|
||||
gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "metric_baseline.slp"),
|
||||
gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "metric.slp"),
|
||||
gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "metric_report.csv"));
|
||||
}
|
||||
std::string baseline_name = LLFastTimer::sLogName + "_baseline.slp";
|
||||
std::string current_name = LLFastTimer::sLogName + ".slp";
|
||||
std::string report_name = LLFastTimer::sLogName + "_report.csv";
|
||||
|
||||
LLFastTimerView::doAnalysis(
|
||||
gDirUtilp->getExpandedFilename(LL_PATH_LOGS, baseline_name),
|
||||
gDirUtilp->getExpandedFilename(LL_PATH_LOGS, current_name),
|
||||
gDirUtilp->getExpandedFilename(LL_PATH_LOGS, report_name));
|
||||
}
|
||||
LLMetricPerformanceTester::cleanClass() ;
|
||||
LLMetricPerformanceTesterBasic::cleanClass() ;
|
||||
|
||||
llinfos << "Cleaning up Media and Textures" << llendflush;
|
||||
|
||||
|
|
@ -1765,7 +1754,7 @@ bool LLAppViewer::initThreads()
|
|||
if (LLFastTimer::sLog || LLFastTimer::sMetricLog)
|
||||
{
|
||||
LLFastTimer::sLogLock = new LLMutex(NULL);
|
||||
mFastTimerLogThread = new LLFastTimerLogThread();
|
||||
mFastTimerLogThread = new LLFastTimerLogThread(LLFastTimer::sLogName);
|
||||
mFastTimerLogThread->start();
|
||||
}
|
||||
|
||||
|
|
@ -2116,11 +2105,25 @@ bool LLAppViewer::initConfiguration()
|
|||
if (clp.hasOption("logperformance"))
|
||||
{
|
||||
LLFastTimer::sLog = TRUE;
|
||||
LLFastTimer::sLogName = std::string("performance");
|
||||
}
|
||||
|
||||
if(clp.hasOption("logmetrics"))
|
||||
if (clp.hasOption("logmetrics"))
|
||||
{
|
||||
LLFastTimer::sMetricLog = TRUE ;
|
||||
// '--logmetrics' can be specified with a named test metric argument so the data gathering is done only on that test
|
||||
// In the absence of argument, every metric is gathered (makes for a rather slow run and hard to decipher report...)
|
||||
std::string test_name = clp.getOption("logmetrics")[0];
|
||||
llinfos << "'--logmetrics' argument : " << test_name << llendl;
|
||||
if (test_name == "")
|
||||
{
|
||||
llwarns << "No '--logmetrics' argument given, will output all metrics to " << DEFAULT_METRIC_NAME << llendl;
|
||||
LLFastTimer::sLogName = DEFAULT_METRIC_NAME;
|
||||
}
|
||||
else
|
||||
{
|
||||
LLFastTimer::sLogName = test_name;
|
||||
}
|
||||
}
|
||||
|
||||
if (clp.hasOption("graphicslevel"))
|
||||
|
|
|
|||
|
|
@ -251,7 +251,9 @@ private:
|
|||
|
||||
LLWatchdogTimeout* mMainloopTimeout;
|
||||
|
||||
// For performance and metric gathering
|
||||
LLThread* mFastTimerLogThread;
|
||||
|
||||
// for tracking viewer<->region circuit death
|
||||
bool mAgentRegionLastAlive;
|
||||
LLUUID mAgentRegionLastID;
|
||||
|
|
|
|||
|
|
@ -1086,14 +1086,22 @@ LLSD LLFastTimerView::analyzePerformanceLogDefault(std::istream& is)
|
|||
//static
|
||||
void LLFastTimerView::doAnalysisDefault(std::string baseline, std::string target, std::string output)
|
||||
{
|
||||
// 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
|
||||
std::ifstream base_is(baseline.c_str());
|
||||
LLSD base = analyzePerformanceLogDefault(base_is);
|
||||
base_is.close();
|
||||
|
||||
//analyze current
|
||||
std::ifstream target_is(target.c_str());
|
||||
LLSD current = analyzePerformanceLogDefault(target_is);
|
||||
target_is.close();
|
||||
|
||||
|
|
@ -1154,15 +1162,15 @@ LLSD LLFastTimerView::analyzeMetricPerformanceLog(std::istream& is)
|
|||
{
|
||||
std::string label = iter->first;
|
||||
|
||||
LLMetricPerformanceTester* tester = LLMetricPerformanceTester::getTester(iter->second["Name"].asString()) ;
|
||||
LLMetricPerformanceTesterBasic* tester = LLMetricPerformanceTesterBasic::getTester(iter->second["Name"].asString()) ;
|
||||
if(tester)
|
||||
{
|
||||
ret[label]["Name"] = iter->second["Name"] ;
|
||||
|
||||
S32 num_of_strings = tester->getNumOfMetricStrings() ;
|
||||
for(S32 index = 0 ; index < num_of_strings ; index++)
|
||||
S32 num_of_metrics = tester->getNumberOfMetrics() ;
|
||||
for(S32 index = 0 ; index < num_of_metrics ; index++)
|
||||
{
|
||||
ret[label][ tester->getMetricString(index) ] = iter->second[ tester->getMetricString(index) ] ;
|
||||
ret[label][ tester->getMetricName(index) ] = iter->second[ tester->getMetricName(index) ] ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1171,21 +1179,44 @@ LLSD LLFastTimerView::analyzeMetricPerformanceLog(std::istream& is)
|
|||
return ret;
|
||||
}
|
||||
|
||||
//static
|
||||
void LLFastTimerView::outputAllMetrics()
|
||||
{
|
||||
if (LLMetricPerformanceTesterBasic::hasMetricPerformanceTesters())
|
||||
{
|
||||
for (LLMetricPerformanceTesterBasic::name_tester_map_t::iterator iter = LLMetricPerformanceTesterBasic::sTesterMap.begin();
|
||||
iter != LLMetricPerformanceTesterBasic::sTesterMap.end(); ++iter)
|
||||
{
|
||||
LLMetricPerformanceTesterBasic* tester = ((LLMetricPerformanceTesterBasic*)iter->second);
|
||||
tester->outputTestResults();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//static
|
||||
void LLFastTimerView::doAnalysisMetrics(std::string baseline, std::string target, std::string output)
|
||||
{
|
||||
if(!LLMetricPerformanceTester::hasMetricPerformanceTesters())
|
||||
if(!LLMetricPerformanceTesterBasic::hasMetricPerformanceTesters())
|
||||
{
|
||||
return ;
|
||||
}
|
||||
|
||||
//analyze baseline
|
||||
// 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
|
||||
std::ifstream target_is(target.c_str());
|
||||
LLSD current = analyzeMetricPerformanceLog(target_is);
|
||||
target_is.close();
|
||||
|
||||
|
|
@ -1193,10 +1224,10 @@ void LLFastTimerView::doAnalysisMetrics(std::string baseline, std::string target
|
|||
std::ofstream os(output.c_str());
|
||||
|
||||
os << "Label, Metric, Base(B), Target(T), Diff(T-B), Percentage(100*T/B)\n";
|
||||
for(LLMetricPerformanceTester::name_tester_map_t::iterator iter = LLMetricPerformanceTester::sTesterMap.begin() ;
|
||||
iter != LLMetricPerformanceTester::sTesterMap.end() ; ++iter)
|
||||
for(LLMetricPerformanceTesterBasic::name_tester_map_t::iterator iter = LLMetricPerformanceTesterBasic::sTesterMap.begin() ;
|
||||
iter != LLMetricPerformanceTesterBasic::sTesterMap.end() ; ++iter)
|
||||
{
|
||||
LLMetricPerformanceTester* tester = ((LLMetricPerformanceTester*)iter->second) ;
|
||||
LLMetricPerformanceTesterBasic* tester = ((LLMetricPerformanceTesterBasic*)iter->second) ;
|
||||
tester->analyzePerformance(&os, &base, ¤t) ;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ public:
|
|||
|
||||
static BOOL sAnalyzePerformance;
|
||||
|
||||
static void outputAllMetrics();
|
||||
static void doAnalysis(std::string baseline, std::string target, std::string output);
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -1,252 +0,0 @@
|
|||
/**
|
||||
* @file llmetricperformancetester.cpp
|
||||
* @brief LLMetricPerformanceTester class implementation
|
||||
*
|
||||
* $LicenseInfo:firstyear=2004&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#include "llviewerprecompiledheaders.h"
|
||||
|
||||
#include "indra_constants.h"
|
||||
#include "llerror.h"
|
||||
#include "llmath.h"
|
||||
#include "llfontgl.h"
|
||||
#include "llsdserialize.h"
|
||||
#include "llstat.h"
|
||||
#include "lltreeiterators.h"
|
||||
#include "llmetricperformancetester.h"
|
||||
|
||||
LLMetricPerformanceTester::name_tester_map_t LLMetricPerformanceTester::sTesterMap ;
|
||||
|
||||
//static
|
||||
void LLMetricPerformanceTester::initClass()
|
||||
{
|
||||
}
|
||||
//static
|
||||
void LLMetricPerformanceTester::cleanClass()
|
||||
{
|
||||
for(name_tester_map_t::iterator iter = sTesterMap.begin() ; iter != sTesterMap.end() ; ++iter)
|
||||
{
|
||||
delete iter->second ;
|
||||
}
|
||||
sTesterMap.clear() ;
|
||||
}
|
||||
|
||||
//static
|
||||
void LLMetricPerformanceTester::addTester(LLMetricPerformanceTester* tester)
|
||||
{
|
||||
if(!tester)
|
||||
{
|
||||
llerrs << "invalid tester!" << llendl ;
|
||||
return ;
|
||||
}
|
||||
|
||||
std::string name = tester->getName() ;
|
||||
if(getTester(name))
|
||||
{
|
||||
llerrs << "Tester name is used by some other tester: " << name << llendl ;
|
||||
return ;
|
||||
}
|
||||
|
||||
sTesterMap.insert(std::make_pair(name, tester));
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
//static
|
||||
LLMetricPerformanceTester* LLMetricPerformanceTester::getTester(std::string label)
|
||||
{
|
||||
name_tester_map_t::iterator found_it = sTesterMap.find(label) ;
|
||||
if(found_it != sTesterMap.end())
|
||||
{
|
||||
return found_it->second ;
|
||||
}
|
||||
|
||||
return NULL ;
|
||||
}
|
||||
|
||||
LLMetricPerformanceTester::LLMetricPerformanceTester(std::string name, BOOL use_default_performance_analysis)
|
||||
: mName(name),
|
||||
mBaseSessionp(NULL),
|
||||
mCurrentSessionp(NULL),
|
||||
mCount(0),
|
||||
mUseDefaultPerformanceAnalysis(use_default_performance_analysis)
|
||||
{
|
||||
if(mName == std::string())
|
||||
{
|
||||
llerrs << "invalid name." << llendl ;
|
||||
}
|
||||
|
||||
LLMetricPerformanceTester::addTester(this) ;
|
||||
}
|
||||
|
||||
/*virtual*/
|
||||
LLMetricPerformanceTester::~LLMetricPerformanceTester()
|
||||
{
|
||||
if(mBaseSessionp)
|
||||
{
|
||||
delete mBaseSessionp ;
|
||||
mBaseSessionp = NULL ;
|
||||
}
|
||||
if(mCurrentSessionp)
|
||||
{
|
||||
delete mCurrentSessionp ;
|
||||
mCurrentSessionp = NULL ;
|
||||
}
|
||||
}
|
||||
|
||||
void LLMetricPerformanceTester::incLabel()
|
||||
{
|
||||
mCurLabel = llformat("%s-%d", mName.c_str(), mCount++) ;
|
||||
}
|
||||
void LLMetricPerformanceTester::preOutputTestResults(LLSD* sd)
|
||||
{
|
||||
incLabel() ;
|
||||
(*sd)[mCurLabel]["Name"] = mName ;
|
||||
}
|
||||
void LLMetricPerformanceTester::postOutputTestResults(LLSD* sd)
|
||||
{
|
||||
LLMutexLock lock(LLFastTimer::sLogLock);
|
||||
LLFastTimer::sLogQueue.push((*sd));
|
||||
}
|
||||
|
||||
void LLMetricPerformanceTester::outputTestResults()
|
||||
{
|
||||
LLSD sd ;
|
||||
preOutputTestResults(&sd) ;
|
||||
|
||||
outputTestRecord(&sd) ;
|
||||
|
||||
postOutputTestResults(&sd) ;
|
||||
}
|
||||
|
||||
void LLMetricPerformanceTester::addMetricString(std::string str)
|
||||
{
|
||||
mMetricStrings.push_back(str) ;
|
||||
}
|
||||
|
||||
const std::string& LLMetricPerformanceTester::getMetricString(U32 index) const
|
||||
{
|
||||
return mMetricStrings[index] ;
|
||||
}
|
||||
|
||||
void LLMetricPerformanceTester::prePerformanceAnalysis()
|
||||
{
|
||||
mCount = 0 ;
|
||||
incLabel() ;
|
||||
}
|
||||
|
||||
//
|
||||
//default analyzing the performance
|
||||
//
|
||||
/*virtual*/
|
||||
void LLMetricPerformanceTester::analyzePerformance(std::ofstream* os, LLSD* base, LLSD* current)
|
||||
{
|
||||
if(mUseDefaultPerformanceAnalysis)//use default performance analysis
|
||||
{
|
||||
prePerformanceAnalysis() ;
|
||||
|
||||
BOOL in_base = (*base).has(mCurLabel) ;
|
||||
BOOL in_current = (*current).has(mCurLabel) ;
|
||||
|
||||
while(in_base || in_current)
|
||||
{
|
||||
LLSD::String label = mCurLabel ;
|
||||
|
||||
if(in_base && in_current)
|
||||
{
|
||||
*os << llformat("%s\n", label.c_str()) ;
|
||||
|
||||
for(U32 index = 0 ; index < mMetricStrings.size() ; index++)
|
||||
{
|
||||
switch((*current)[label][ mMetricStrings[index] ].type())
|
||||
{
|
||||
case LLSD::TypeInteger:
|
||||
compareTestResults(os, mMetricStrings[index],
|
||||
(S32)((*base)[label][ mMetricStrings[index] ].asInteger()), (S32)((*current)[label][ mMetricStrings[index] ].asInteger())) ;
|
||||
break ;
|
||||
case LLSD::TypeReal:
|
||||
compareTestResults(os, mMetricStrings[index],
|
||||
(F32)((*base)[label][ mMetricStrings[index] ].asReal()), (F32)((*current)[label][ mMetricStrings[index] ].asReal())) ;
|
||||
break;
|
||||
default:
|
||||
llerrs << "unsupported metric " << mMetricStrings[index] << " LLSD type: " << (S32)(*current)[label][ mMetricStrings[index] ].type() << llendl ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
incLabel() ;
|
||||
in_base = (*base).has(mCurLabel) ;
|
||||
in_current = (*current).has(mCurLabel) ;
|
||||
}
|
||||
}//end of default
|
||||
else
|
||||
{
|
||||
//load the base session
|
||||
prePerformanceAnalysis() ;
|
||||
mBaseSessionp = loadTestSession(base) ;
|
||||
|
||||
//load the current session
|
||||
prePerformanceAnalysis() ;
|
||||
mCurrentSessionp = loadTestSession(current) ;
|
||||
|
||||
if(!mBaseSessionp || !mCurrentSessionp)
|
||||
{
|
||||
llerrs << "memory error during loading test sessions." << llendl ;
|
||||
}
|
||||
|
||||
//compare
|
||||
compareTestSessions(os) ;
|
||||
|
||||
//release memory
|
||||
if(mBaseSessionp)
|
||||
{
|
||||
delete mBaseSessionp ;
|
||||
mBaseSessionp = NULL ;
|
||||
}
|
||||
if(mCurrentSessionp)
|
||||
{
|
||||
delete mCurrentSessionp ;
|
||||
mCurrentSessionp = NULL ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//virtual
|
||||
void LLMetricPerformanceTester::compareTestResults(std::ofstream* os, std::string metric_string, S32 v_base, S32 v_current)
|
||||
{
|
||||
*os << llformat(" ,%s, %d, %d, %d, %.4f\n", metric_string.c_str(), v_base, v_current,
|
||||
v_current - v_base, (v_base != 0) ? 100.f * v_current / v_base : 0) ;
|
||||
}
|
||||
|
||||
//virtual
|
||||
void LLMetricPerformanceTester::compareTestResults(std::ofstream* os, std::string metric_string, F32 v_base, F32 v_current)
|
||||
{
|
||||
*os << llformat(" ,%s, %.4f, %.4f, %.4f, %.4f\n", metric_string.c_str(), v_base, v_current,
|
||||
v_current - v_base, (fabs(v_base) > 0.0001f) ? 100.f * v_current / v_base : 0.f ) ;
|
||||
}
|
||||
|
||||
//virtual
|
||||
LLMetricPerformanceTester::LLTestSession::~LLTestSession()
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -1,153 +0,0 @@
|
|||
/**
|
||||
* @file LLMetricPerformanceTester.h
|
||||
* @brief LLMetricPerformanceTester class definition
|
||||
*
|
||||
* $LicenseInfo:firstyear=2004&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#ifndef LL_METRICPERFORMANCETESTER_H
|
||||
#define LL_METRICPERFORMANCETESTER_H
|
||||
|
||||
class LLMetricPerformanceTester
|
||||
{
|
||||
public:
|
||||
//
|
||||
//name passed to the constructor is a unique string for each tester.
|
||||
//an error is reported if the name is already used by some other tester.
|
||||
//
|
||||
LLMetricPerformanceTester(std::string name, BOOL use_default_performance_analysis) ;
|
||||
virtual ~LLMetricPerformanceTester();
|
||||
|
||||
//
|
||||
//return the name of the tester
|
||||
//
|
||||
std::string getName() const { return mName ;}
|
||||
//
|
||||
//return the number of the test metrics in this tester
|
||||
//
|
||||
S32 getNumOfMetricStrings() const { return mMetricStrings.size() ;}
|
||||
//
|
||||
//return the metric string at the index
|
||||
//
|
||||
const std::string& getMetricString(U32 index) const ;
|
||||
|
||||
//
|
||||
//this function to compare the test results.
|
||||
//by default, it compares the test results against the baseline one by one, item by item,
|
||||
//in the increasing order of the LLSD label counter, starting from the first one.
|
||||
//you can define your own way to analyze performance by passing FALSE to "use_default_performance_analysis",
|
||||
//and implement two abstract virtual functions below: loadTestSession(...) and compareTestSessions(...).
|
||||
//
|
||||
void analyzePerformance(std::ofstream* os, LLSD* base, LLSD* current) ;
|
||||
|
||||
protected:
|
||||
//
|
||||
//insert metric strings used in the tester.
|
||||
//
|
||||
void addMetricString(std::string str) ;
|
||||
|
||||
//
|
||||
//increase LLSD label by 1
|
||||
//
|
||||
void incLabel() ;
|
||||
|
||||
//
|
||||
//the function to write a set of test results to the log LLSD.
|
||||
//
|
||||
void outputTestResults() ;
|
||||
|
||||
//
|
||||
//compare the test results.
|
||||
//you can write your own to overwrite the default one.
|
||||
//
|
||||
virtual void compareTestResults(std::ofstream* os, std::string metric_string, S32 v_base, S32 v_current) ;
|
||||
virtual void compareTestResults(std::ofstream* os, std::string metric_string, F32 v_base, F32 v_current) ;
|
||||
|
||||
//
|
||||
//for performance analysis use
|
||||
//it defines an interface for the two abstract virtual functions loadTestSession(...) and compareTestSessions(...).
|
||||
//please make your own test session class derived from it.
|
||||
//
|
||||
class LLTestSession
|
||||
{
|
||||
public:
|
||||
virtual ~LLTestSession() ;
|
||||
};
|
||||
|
||||
//
|
||||
//load a test session for log LLSD
|
||||
//you need to implement it only when you define your own way to analyze performance.
|
||||
//otherwise leave it empty.
|
||||
//
|
||||
virtual LLMetricPerformanceTester::LLTestSession* loadTestSession(LLSD* log) = 0 ;
|
||||
//
|
||||
//compare the base session and the target session
|
||||
//you need to implement it only when you define your own way to analyze performance.
|
||||
//otherwise leave it empty.
|
||||
//
|
||||
virtual void compareTestSessions(std::ofstream* os) = 0 ;
|
||||
//
|
||||
//the function to write a set of test results to the log LLSD.
|
||||
//you have to write you own version of this function.
|
||||
//
|
||||
virtual void outputTestRecord(LLSD* sd) = 0 ;
|
||||
|
||||
private:
|
||||
void preOutputTestResults(LLSD* sd) ;
|
||||
void postOutputTestResults(LLSD* sd) ;
|
||||
void prePerformanceAnalysis() ;
|
||||
|
||||
protected:
|
||||
//
|
||||
//the unique name string of the tester
|
||||
//
|
||||
std::string mName ;
|
||||
//
|
||||
//the current label counter for the log LLSD
|
||||
//
|
||||
std::string mCurLabel ;
|
||||
S32 mCount ;
|
||||
|
||||
BOOL mUseDefaultPerformanceAnalysis ;
|
||||
LLTestSession* mBaseSessionp ;
|
||||
LLTestSession* mCurrentSessionp ;
|
||||
|
||||
//metrics strings
|
||||
std::vector< std::string > mMetricStrings ;
|
||||
|
||||
//static members
|
||||
private:
|
||||
static void addTester(LLMetricPerformanceTester* tester) ;
|
||||
|
||||
public:
|
||||
typedef std::map< std::string, LLMetricPerformanceTester* > name_tester_map_t;
|
||||
static name_tester_map_t sTesterMap ;
|
||||
|
||||
static LLMetricPerformanceTester* getTester(std::string label) ;
|
||||
static BOOL hasMetricPerformanceTesters() {return !sTesterMap.empty() ;}
|
||||
|
||||
static void initClass() ;
|
||||
static void cleanClass() ;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -1574,7 +1574,6 @@ bool LLTextureFetch::createRequest(const std::string& url, const LLUUID& id, con
|
|||
if (!url.empty() && (!exten.empty() && LLImageBase::getCodecFromExtension(exten) != IMG_CODEC_J2C))
|
||||
{
|
||||
// Only do partial requests for J2C at the moment
|
||||
//llinfos << "Merov : LLTextureFetch::createRequest(), blocking fetch on " << url << llendl;
|
||||
desired_size = MAX_IMAGE_DATA_SIZE;
|
||||
desired_discard = 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -72,6 +72,7 @@ LLPointer<LLViewerFetchedTexture> LLViewerFetchedTexture::sDefaultImagep = NULL;
|
|||
LLPointer<LLViewerFetchedTexture> LLViewerFetchedTexture::sSmokeImagep = NULL;
|
||||
LLViewerMediaTexture::media_map_t LLViewerMediaTexture::sMediaMap ;
|
||||
LLTexturePipelineTester* LLViewerTextureManager::sTesterp = NULL ;
|
||||
const std::string sTesterName("TextureTester");
|
||||
|
||||
S32 LLViewerTexture::sImageCount = 0;
|
||||
S32 LLViewerTexture::sRawCount = 0;
|
||||
|
|
@ -341,9 +342,14 @@ void LLViewerTextureManager::init()
|
|||
|
||||
LLViewerTexture::initClass() ;
|
||||
|
||||
if(LLFastTimer::sMetricLog)
|
||||
if (LLMetricPerformanceTesterBasic::isMetricLogRequested(sTesterName) && !LLMetricPerformanceTesterBasic::getTester(sTesterName))
|
||||
{
|
||||
LLViewerTextureManager::sTesterp = new LLTexturePipelineTester() ;
|
||||
sTesterp = new LLTexturePipelineTester() ;
|
||||
if (!sTesterp->isValid())
|
||||
{
|
||||
delete sTesterp;
|
||||
sTesterp = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -408,9 +414,10 @@ void LLViewerTexture::updateClass(const F32 velocity, const F32 angular_velocity
|
|||
{
|
||||
sCurrentTime = gFrameTimeSeconds ;
|
||||
|
||||
if(LLViewerTextureManager::sTesterp)
|
||||
LLTexturePipelineTester* tester = (LLTexturePipelineTester*)LLMetricPerformanceTesterBasic::getTester(sTesterName);
|
||||
if (tester)
|
||||
{
|
||||
LLViewerTextureManager::sTesterp->update() ;
|
||||
tester->update() ;
|
||||
}
|
||||
LLViewerMediaTexture::updateClass() ;
|
||||
|
||||
|
|
@ -603,9 +610,10 @@ bool LLViewerTexture::bindDefaultImage(S32 stage)
|
|||
//check if there is cached raw image and switch to it if possible
|
||||
switchToCachedImage() ;
|
||||
|
||||
if(LLViewerTextureManager::sTesterp)
|
||||
LLTexturePipelineTester* tester = (LLTexturePipelineTester*)LLMetricPerformanceTesterBasic::getTester(sTesterName);
|
||||
if (tester)
|
||||
{
|
||||
LLViewerTextureManager::sTesterp->updateGrayTextureBinding() ;
|
||||
tester->updateGrayTextureBinding() ;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
|
@ -1066,9 +1074,10 @@ BOOL LLViewerTexture::isLargeImage()
|
|||
//virtual
|
||||
void LLViewerTexture::updateBindStatsForTester()
|
||||
{
|
||||
if(LLViewerTextureManager::sTesterp)
|
||||
LLTexturePipelineTester* tester = (LLTexturePipelineTester*)LLMetricPerformanceTesterBasic::getTester(sTesterName);
|
||||
if (tester)
|
||||
{
|
||||
LLViewerTextureManager::sTesterp->updateTextureBindingStats(this) ;
|
||||
tester->updateTextureBindingStats(this) ;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1849,10 +1858,11 @@ bool LLViewerFetchedTexture::updateFetch()
|
|||
// We may have data ready regardless of whether or not we are finished (e.g. waiting on write)
|
||||
if (mRawImage.notNull())
|
||||
{
|
||||
if(LLViewerTextureManager::sTesterp)
|
||||
LLTexturePipelineTester* tester = (LLTexturePipelineTester*)LLMetricPerformanceTesterBasic::getTester(sTesterName);
|
||||
if (tester)
|
||||
{
|
||||
mIsFetched = TRUE ;
|
||||
LLViewerTextureManager::sTesterp->updateTextureLoadingStats(this, mRawImage, LLAppViewer::getTextureFetch()->isFromLocalCache(mID)) ;
|
||||
tester->updateTextureLoadingStats(this, mRawImage, LLAppViewer::getTextureFetch()->isFromLocalCache(mID)) ;
|
||||
}
|
||||
mRawDiscardLevel = fetch_discard;
|
||||
if ((mRawImage->getDataSize() > 0 && mRawDiscardLevel >= 0) &&
|
||||
|
|
@ -3076,9 +3086,10 @@ void LLViewerLODTexture::scaleDown()
|
|||
{
|
||||
switchToCachedImage() ;
|
||||
|
||||
if(LLViewerTextureManager::sTesterp)
|
||||
LLTexturePipelineTester* tester = (LLTexturePipelineTester*)LLMetricPerformanceTesterBasic::getTester(sTesterName);
|
||||
if (tester)
|
||||
{
|
||||
LLViewerTextureManager::sTesterp->setStablizingTime() ;
|
||||
tester->setStablizingTime() ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3588,23 +3599,22 @@ F32 LLViewerMediaTexture::getMaxVirtualSize()
|
|||
//----------------------------------------------------------------------------------------------
|
||||
//start of LLTexturePipelineTester
|
||||
//----------------------------------------------------------------------------------------------
|
||||
LLTexturePipelineTester::LLTexturePipelineTester() :
|
||||
LLMetricPerformanceTester("TextureTester", FALSE)
|
||||
LLTexturePipelineTester::LLTexturePipelineTester() : LLMetricPerformanceTesterWithSession(sTesterName)
|
||||
{
|
||||
addMetricString("TotalBytesLoaded") ;
|
||||
addMetricString("TotalBytesLoadedFromCache") ;
|
||||
addMetricString("TotalBytesLoadedForLargeImage") ;
|
||||
addMetricString("TotalBytesLoadedForSculpties") ;
|
||||
addMetricString("StartFetchingTime") ;
|
||||
addMetricString("TotalGrayTime") ;
|
||||
addMetricString("TotalStablizingTime") ;
|
||||
addMetricString("StartTimeLoadingSculpties") ;
|
||||
addMetricString("EndTimeLoadingSculpties") ;
|
||||
addMetric("TotalBytesLoaded") ;
|
||||
addMetric("TotalBytesLoadedFromCache") ;
|
||||
addMetric("TotalBytesLoadedForLargeImage") ;
|
||||
addMetric("TotalBytesLoadedForSculpties") ;
|
||||
addMetric("StartFetchingTime") ;
|
||||
addMetric("TotalGrayTime") ;
|
||||
addMetric("TotalStablizingTime") ;
|
||||
addMetric("StartTimeLoadingSculpties") ;
|
||||
addMetric("EndTimeLoadingSculpties") ;
|
||||
|
||||
addMetricString("Time") ;
|
||||
addMetricString("TotalBytesBound") ;
|
||||
addMetricString("TotalBytesBoundForLargeImage") ;
|
||||
addMetricString("PercentageBytesBound") ;
|
||||
addMetric("Time") ;
|
||||
addMetric("TotalBytesBound") ;
|
||||
addMetric("TotalBytesBoundForLargeImage") ;
|
||||
addMetric("PercentageBytesBound") ;
|
||||
|
||||
mTotalBytesLoaded = 0 ;
|
||||
mTotalBytesLoadedFromCache = 0 ;
|
||||
|
|
@ -3616,7 +3626,7 @@ LLTexturePipelineTester::LLTexturePipelineTester() :
|
|||
|
||||
LLTexturePipelineTester::~LLTexturePipelineTester()
|
||||
{
|
||||
LLViewerTextureManager::sTesterp = NULL ;
|
||||
LLViewerTextureManager::sTesterp = NULL;
|
||||
}
|
||||
|
||||
void LLTexturePipelineTester::update()
|
||||
|
|
@ -3682,22 +3692,23 @@ void LLTexturePipelineTester::reset()
|
|||
//virtual
|
||||
void LLTexturePipelineTester::outputTestRecord(LLSD *sd)
|
||||
{
|
||||
(*sd)[mCurLabel]["TotalBytesLoaded"] = (LLSD::Integer)mTotalBytesLoaded ;
|
||||
(*sd)[mCurLabel]["TotalBytesLoadedFromCache"] = (LLSD::Integer)mTotalBytesLoadedFromCache ;
|
||||
(*sd)[mCurLabel]["TotalBytesLoadedForLargeImage"] = (LLSD::Integer)mTotalBytesLoadedForLargeImage ;
|
||||
(*sd)[mCurLabel]["TotalBytesLoadedForSculpties"] = (LLSD::Integer)mTotalBytesLoadedForSculpties ;
|
||||
std::string currentLabel = getCurrentLabelName();
|
||||
(*sd)[currentLabel]["TotalBytesLoaded"] = (LLSD::Integer)mTotalBytesLoaded ;
|
||||
(*sd)[currentLabel]["TotalBytesLoadedFromCache"] = (LLSD::Integer)mTotalBytesLoadedFromCache ;
|
||||
(*sd)[currentLabel]["TotalBytesLoadedForLargeImage"] = (LLSD::Integer)mTotalBytesLoadedForLargeImage ;
|
||||
(*sd)[currentLabel]["TotalBytesLoadedForSculpties"] = (LLSD::Integer)mTotalBytesLoadedForSculpties ;
|
||||
|
||||
(*sd)[mCurLabel]["StartFetchingTime"] = (LLSD::Real)mStartFetchingTime ;
|
||||
(*sd)[mCurLabel]["TotalGrayTime"] = (LLSD::Real)mTotalGrayTime ;
|
||||
(*sd)[mCurLabel]["TotalStablizingTime"] = (LLSD::Real)mTotalStablizingTime ;
|
||||
(*sd)[currentLabel]["StartFetchingTime"] = (LLSD::Real)mStartFetchingTime ;
|
||||
(*sd)[currentLabel]["TotalGrayTime"] = (LLSD::Real)mTotalGrayTime ;
|
||||
(*sd)[currentLabel]["TotalStablizingTime"] = (LLSD::Real)mTotalStablizingTime ;
|
||||
|
||||
(*sd)[mCurLabel]["StartTimeLoadingSculpties"] = (LLSD::Real)mStartTimeLoadingSculpties ;
|
||||
(*sd)[mCurLabel]["EndTimeLoadingSculpties"] = (LLSD::Real)mEndTimeLoadingSculpties ;
|
||||
(*sd)[currentLabel]["StartTimeLoadingSculpties"] = (LLSD::Real)mStartTimeLoadingSculpties ;
|
||||
(*sd)[currentLabel]["EndTimeLoadingSculpties"] = (LLSD::Real)mEndTimeLoadingSculpties ;
|
||||
|
||||
(*sd)[mCurLabel]["Time"] = LLImageGL::sLastFrameTime ;
|
||||
(*sd)[mCurLabel]["TotalBytesBound"] = (LLSD::Integer)mLastTotalBytesUsed ;
|
||||
(*sd)[mCurLabel]["TotalBytesBoundForLargeImage"] = (LLSD::Integer)mLastTotalBytesUsedForLargeImage ;
|
||||
(*sd)[mCurLabel]["PercentageBytesBound"] = (LLSD::Real)(100.f * mLastTotalBytesUsed / mTotalBytesLoaded) ;
|
||||
(*sd)[currentLabel]["Time"] = LLImageGL::sLastFrameTime ;
|
||||
(*sd)[currentLabel]["TotalBytesBound"] = (LLSD::Integer)mLastTotalBytesUsed ;
|
||||
(*sd)[currentLabel]["TotalBytesBoundForLargeImage"] = (LLSD::Integer)mLastTotalBytesUsedForLargeImage ;
|
||||
(*sd)[currentLabel]["PercentageBytesBound"] = (LLSD::Real)(100.f * mLastTotalBytesUsed / mTotalBytesLoaded) ;
|
||||
}
|
||||
|
||||
void LLTexturePipelineTester::updateTextureBindingStats(const LLViewerTexture* imagep)
|
||||
|
|
@ -3786,7 +3797,7 @@ void LLTexturePipelineTester::compareTestSessions(std::ofstream* os)
|
|||
}
|
||||
|
||||
//compare and output the comparison
|
||||
*os << llformat("%s\n", mName.c_str()) ;
|
||||
*os << llformat("%s\n", getTesterName().c_str()) ;
|
||||
*os << llformat("AggregateResults\n") ;
|
||||
|
||||
compareTestResults(os, "TotalFetchingTime", base_sessionp->mTotalFetchingTime, current_sessionp->mTotalFetchingTime) ;
|
||||
|
|
@ -3841,7 +3852,7 @@ void LLTexturePipelineTester::compareTestSessions(std::ofstream* os)
|
|||
}
|
||||
|
||||
//virtual
|
||||
LLMetricPerformanceTester::LLTestSession* LLTexturePipelineTester::loadTestSession(LLSD* log)
|
||||
LLMetricPerformanceTesterWithSession::LLTestSession* LLTexturePipelineTester::loadTestSession(LLSD* log)
|
||||
{
|
||||
LLTexturePipelineTester::LLTextureTestSession* sessionp = new LLTexturePipelineTester::LLTextureTestSession() ;
|
||||
if(!sessionp)
|
||||
|
|
@ -3868,12 +3879,11 @@ LLMetricPerformanceTester::LLTestSession* LLTexturePipelineTester::loadTestSessi
|
|||
sessionp->mInstantPerformanceList[sessionp->mInstantPerformanceListCounter].mTime = 0.f ;
|
||||
|
||||
//load a session
|
||||
BOOL in_log = (*log).has(mCurLabel) ;
|
||||
while(in_log)
|
||||
std::string currentLabel = getCurrentLabelName();
|
||||
BOOL in_log = (*log).has(currentLabel) ;
|
||||
while (in_log)
|
||||
{
|
||||
LLSD::String label = mCurLabel ;
|
||||
incLabel() ;
|
||||
in_log = (*log).has(mCurLabel) ;
|
||||
LLSD::String label = currentLabel ;
|
||||
|
||||
if(sessionp->mInstantPerformanceListCounter >= (S32)sessionp->mInstantPerformanceList.size())
|
||||
{
|
||||
|
|
@ -3939,7 +3949,11 @@ LLMetricPerformanceTester::LLTestSession* LLTexturePipelineTester::loadTestSessi
|
|||
sessionp->mInstantPerformanceList[sessionp->mInstantPerformanceListCounter].mAverageBytesUsedForLargeImagePerSecond = 0 ;
|
||||
sessionp->mInstantPerformanceList[sessionp->mInstantPerformanceListCounter].mAveragePercentageBytesUsedPerSecond = 0.f ;
|
||||
sessionp->mInstantPerformanceList[sessionp->mInstantPerformanceListCounter].mTime = 0.f ;
|
||||
}
|
||||
}
|
||||
// Next label
|
||||
incrementCurrentCount() ;
|
||||
currentLabel = getCurrentLabelName();
|
||||
in_log = (*log).has(currentLabel) ;
|
||||
}
|
||||
|
||||
sessionp->mTotalFetchingTime += total_fetching_time ;
|
||||
|
|
|
|||
|
|
@ -735,7 +735,7 @@ public:
|
|||
//it tracks the activities of the texture pipeline
|
||||
//records them, and outputs them to log files
|
||||
//
|
||||
class LLTexturePipelineTester : public LLMetricPerformanceTester
|
||||
class LLTexturePipelineTester : public LLMetricPerformanceTesterWithSession
|
||||
{
|
||||
enum
|
||||
{
|
||||
|
|
@ -751,8 +751,6 @@ public:
|
|||
void updateGrayTextureBinding() ;
|
||||
void setStablizingTime() ;
|
||||
|
||||
/*virtual*/ void analyzePerformance(std::ofstream* os, LLSD* base, LLSD* current) ;
|
||||
|
||||
private:
|
||||
void reset() ;
|
||||
void updateStablizingTime() ;
|
||||
|
|
@ -823,7 +821,7 @@ private:
|
|||
S32 mInstantPerformanceListCounter ;
|
||||
};
|
||||
|
||||
/*virtual*/ LLMetricPerformanceTester::LLTestSession* loadTestSession(LLSD* log) ;
|
||||
/*virtual*/ LLMetricPerformanceTesterWithSession::LLTestSession* loadTestSession(LLSD* log) ;
|
||||
/*virtual*/ void compareTestSessions(std::ofstream* os) ;
|
||||
};
|
||||
|
||||
|
|
|
|||
19
install.xml
19
install.xml
|
|
@ -830,23 +830,30 @@
|
|||
<key>darwin</key>
|
||||
<map>
|
||||
<key>md5sum</key>
|
||||
<string>ae18dd120807a46ac961b881a631ad94</string>
|
||||
<string>3b40e7170dea82c1443e8d90cd44a13d</string>
|
||||
<key>url</key>
|
||||
<uri>scp:install-packages.lindenlab.com:/local/www/install-packages/doc/indra_private-2.1.1-darwin-20100820.tar.bz2</uri>
|
||||
<uri>scp:install-packages.lindenlab.com:/local/www/install-packages/doc/kdu-4.2.1-darwin-20080926.tar.bz2</uri>
|
||||
</map>
|
||||
<key>linux</key>
|
||||
<map>
|
||||
<key>md5sum</key>
|
||||
<string>b1f15bbabb68445e55ce23a2aeaca598</string>
|
||||
<string>a6d2f0995c25d7f53bd12b8ec0d6b462</string>
|
||||
<key>url</key>
|
||||
<uri>scp:install-packages.lindenlab.com:/local/www/install-packages/doc/indra_private-2.1.1-linux-20100826.tar.bz2</uri>
|
||||
<uri>scp:install-packages.lindenlab.com:/local/www/install-packages/doc/kdu-4.2.1-linux-20080930.tar.bz2</uri>
|
||||
</map>
|
||||
<key>linux64</key>
|
||||
<map>
|
||||
<key>md5sum</key>
|
||||
<string>f4e2e2b3440594527729a8c85119e508</string>
|
||||
<key>url</key>
|
||||
<uri>scp:install-packages.lindenlab.com:/local/www/install-packages/doc/kdu-5.2.1-linux64-20080926.tar.bz2</uri>
|
||||
</map>
|
||||
<key>windows</key>
|
||||
<map>
|
||||
<key>md5sum</key>
|
||||
<string>0e2fe621ce99085eba00d86d9a3bc130</string>
|
||||
<string>1b9f61140f8b599cdae5e00d21dbb177</string>
|
||||
<key>url</key>
|
||||
<uri>scp:install-packages.lindenlab.com:/local/www/install-packages/doc/indra_private-2.1.1-windows-20100820.tar.bz2</uri>
|
||||
<uri>scp:install-packages.lindenlab.com:/local/www/install-packages/doc/kdu-4.2.1-windows-20080926.tar.bz2</uri>
|
||||
</map>
|
||||
</map>
|
||||
</map>
|
||||
|
|
|
|||
Loading…
Reference in New Issue