merge changes for 4.1.1-release
commit
8e30a2f06d
3
.hgtags
3
.hgtags
|
|
@ -517,3 +517,6 @@ e9d350764dfbf5a46229e627547ef5c1b1eeef00 4.0.2-release
|
|||
0a5de9ec2cb868f367501024d8d6958c20869053 4.0.4-release
|
||||
450de775fff66a011be1a001acd117cc623c445d 4.0.5-release
|
||||
4070611edd95eb3a683d1cd97c4c07fe67793812 4.0.6-release
|
||||
33981d8130f031597b4c7f4c981b18359afb61a0 4.0.7-release
|
||||
45eaee56883df7a439ed3300c44d3126f7e3a41e 4.0.8-release
|
||||
b280a1c797a3891e68dbc237e73de9cf19f426e9 4.1.1-release
|
||||
|
|
|
|||
|
|
@ -90,4 +90,3 @@ EDU_viewer_channel_suffix = "edu"
|
|||
# environment variable 'email' to a space-separated list of email addresses
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1454,9 +1454,9 @@
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>faa1e5b7cf70c143caabe190fa5588ce</string>
|
||||
<string>fddd634dec5ec03924d62cc774f7f8ea</string>
|
||||
<key>url</key>
|
||||
<string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/llappearance_viewer-update-llappearance-utility/rev/304432/arch/Linux/installer/llappearance_utility-0.0.1-linux-304432.tar.bz2</string>
|
||||
<string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/p64_viewer-llappearance-utility/rev/317266/arch/Linux/installer/llappearance_utility-0.0.1-linux-317266.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>linux</string>
|
||||
|
|
@ -1512,11 +1512,11 @@
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>29a1f64df46094eda0d681821a98d17e</string>
|
||||
<string>db992d58c46c80df7d4d31f8a4784b98</string>
|
||||
<key>hash_algorithm</key>
|
||||
<string>md5</string>
|
||||
<key>url</key>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-llceflib_3p-llceflib/rev/311349/arch/Darwin/installer/llceflib-1.5.3.311349-darwin-311349.tar.bz2</string>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-llceflib_3p-llceflib/rev/317959/arch/Darwin/installer/llceflib-1.5.3.317959-darwin-317959.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>darwin</string>
|
||||
|
|
@ -1526,18 +1526,18 @@
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>827b7c339a2cd401d9d23f9ee02cb83f</string>
|
||||
<string>bb3818628131a99cd789febfad9dc2c2</string>
|
||||
<key>hash_algorithm</key>
|
||||
<string>md5</string>
|
||||
<key>url</key>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-llceflib_3p-llceflib/rev/311349/arch/CYGWIN/installer/llceflib-1.5.3.311349-windows-311349.tar.bz2</string>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-llceflib_3p-llceflib/rev/317959/arch/CYGWIN/installer/llceflib-1.5.3.317959-windows-317959.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>windows</string>
|
||||
</map>
|
||||
</map>
|
||||
<key>version</key>
|
||||
<string>1.5.3.311349</string>
|
||||
<string>1.5.3.317959</string>
|
||||
</map>
|
||||
<key>llphysicsextensions_source</key>
|
||||
<map>
|
||||
|
|
@ -2163,6 +2163,46 @@
|
|||
<key>version</key>
|
||||
<string>0.8.0.1</string>
|
||||
</map>
|
||||
<key>vlc-bin</key>
|
||||
<map>
|
||||
<key>copyright</key>
|
||||
<string>Copyright (C) 1998-2016 VLC authors and VideoLAN</string>
|
||||
<key>license</key>
|
||||
<string>GPL2</string>
|
||||
<key>license_file</key>
|
||||
<string>LICENSES/vlc.txt</string>
|
||||
<key>name</key>
|
||||
<string>vlc-bin</string>
|
||||
<key>platforms</key>
|
||||
<map>
|
||||
<key>linux</key>
|
||||
<map>
|
||||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>2f410640df3f9812d1abff02a414cfa8</string>
|
||||
<key>url</key>
|
||||
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-vlc-bin/rev/315283/arch/Linux/vlc_bin-2.2.3-linux-201606011750-r10.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>linux</string>
|
||||
</map>
|
||||
<key>windows</key>
|
||||
<map>
|
||||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>04cff37070a5f65f3652b4ddcec7183f</string>
|
||||
<key>url</key>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-vlc-bin/rev/317935/arch/CYGWIN/installer/vlc_bin-2.2.4.317935-windows-317935.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>windows</string>
|
||||
</map>
|
||||
</map>
|
||||
<key>version</key>
|
||||
<string>2.2.4.317935</string>
|
||||
</map>
|
||||
<key>xmlrpc-epi</key>
|
||||
<map>
|
||||
<key>copyright</key>
|
||||
|
|
|
|||
|
|
@ -190,6 +190,9 @@ Ansariel Hiller
|
|||
STORM-2094
|
||||
MAINT-5756
|
||||
MAINT-4677
|
||||
MAINT-6432
|
||||
STORM-2133
|
||||
MAINT-6511
|
||||
Aralara Rajal
|
||||
Arare Chantilly
|
||||
CHUIBUG-191
|
||||
|
|
|
|||
|
|
@ -24,7 +24,6 @@ set(cmake_SOURCE_FILES
|
|||
DirectX.cmake
|
||||
DragDrop.cmake
|
||||
EXPAT.cmake
|
||||
## ExamplePlugin.cmake
|
||||
FindAPR.cmake
|
||||
FindAutobuild.cmake
|
||||
FindBerkeleyDB.cmake
|
||||
|
|
@ -100,6 +99,7 @@ set(cmake_SOURCE_FILES
|
|||
Variables.cmake
|
||||
ViewerMiscLibs.cmake
|
||||
VisualLeakDetector.cmake
|
||||
LibVLCPlugin.cmake
|
||||
XmlRpcEpi.cmake
|
||||
ZLIB.cmake
|
||||
)
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ else (USESYSTEMLIBS)
|
|||
use_prebuilt_binary(SDL)
|
||||
set (SDL_FOUND TRUE)
|
||||
set (SDL_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/i686-linux)
|
||||
set (SDL_LIBRARY SDL directfb fusion direct)
|
||||
set (SDL_LIBRARY SDL directfb fusion direct X11)
|
||||
endif (LINUX)
|
||||
endif (USESYSTEMLIBS)
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,27 @@
|
|||
# -*- cmake -*-
|
||||
include(Linking)
|
||||
include(Prebuilt)
|
||||
|
||||
if (USESYSTEMLIBS)
|
||||
set(LIBVLCPLUGIN OFF CACHE BOOL
|
||||
"LIBVLCPLUGIN support for the llplugin/llmedia test apps.")
|
||||
else (USESYSTEMLIBS)
|
||||
use_prebuilt_binary(vlc-bin)
|
||||
set(LIBVLCPLUGIN ON CACHE BOOL
|
||||
"LIBVLCPLUGIN support for the llplugin/llmedia test apps.")
|
||||
set(VLC_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include/vlc)
|
||||
endif (USESYSTEMLIBS)
|
||||
|
||||
if (WINDOWS)
|
||||
set(VLC_PLUGIN_LIBRARIES
|
||||
libvlc.lib
|
||||
libvlccore.lib
|
||||
)
|
||||
elseif (DARWIN)
|
||||
elseif (LINUX)
|
||||
# Specify a full path to make sure we get a static link
|
||||
set(VLC_PLUGIN_LIBRARIES
|
||||
${LIBS_PREBUILT_DIR}/lib/libvlc.a
|
||||
${LIBS_PREBUILT_DIR}/lib/libvlccore.a
|
||||
)
|
||||
endif (WINDOWS)
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
2014-02-25 10:34
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ int main(int argc, char **argv)
|
|||
return 1;
|
||||
}
|
||||
|
||||
app.mainLoop();
|
||||
app.frame();
|
||||
app.cleanup();
|
||||
LL_INFOS() << "Crash reporter finished normally." << LL_ENDL;
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -114,7 +114,7 @@ void LLCrashLoggerLinux::gatherPlatformSpecificFiles()
|
|||
{
|
||||
}
|
||||
|
||||
bool LLCrashLoggerLinux::mainLoop()
|
||||
bool LLCrashLoggerLinux::frame()
|
||||
{
|
||||
bool send_logs = true;
|
||||
if(CRASH_BEHAVIOR_ASK == getCrashBehavior())
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ class LLCrashLoggerLinux : public LLCrashLogger
|
|||
public:
|
||||
LLCrashLoggerLinux(void);
|
||||
~LLCrashLoggerLinux(void);
|
||||
virtual bool mainLoop();
|
||||
virtual bool frame();
|
||||
virtual void updateApplication(const std::string& = LLStringUtil::null);
|
||||
virtual void gatherPlatformSpecificFiles();
|
||||
virtual bool cleanup();
|
||||
|
|
|
|||
|
|
@ -58,6 +58,7 @@ set(llcommon_SOURCE_FILES
|
|||
lleventfilter.cpp
|
||||
llevents.cpp
|
||||
lleventtimer.cpp
|
||||
llexception.cpp
|
||||
llfasttimer.cpp
|
||||
llfile.cpp
|
||||
llfindlocale.cpp
|
||||
|
|
@ -157,6 +158,7 @@ set(llcommon_HEADER_FILES
|
|||
lleventfilter.h
|
||||
llevents.h
|
||||
lleventemitter.h
|
||||
llexception.h
|
||||
llfasttimer.h
|
||||
llfile.h
|
||||
llfindlocale.h
|
||||
|
|
@ -315,7 +317,7 @@ if (LL_TESTS)
|
|||
LL_ADD_INTEGRATION_TEST(llprocinfo "" "${test_libs}")
|
||||
LL_ADD_INTEGRATION_TEST(llrand "" "${test_libs}")
|
||||
LL_ADD_INTEGRATION_TEST(llsdserialize "" "${test_libs}")
|
||||
LL_ADD_INTEGRATION_TEST(llsingleton "" "${test_libs}")
|
||||
LL_ADD_INTEGRATION_TEST(llsingleton "" "${test_libs}")
|
||||
LL_ADD_INTEGRATION_TEST(llstring "" "${test_libs}")
|
||||
LL_ADD_INTEGRATION_TEST(lltrace "" "${test_libs}")
|
||||
LL_ADD_INTEGRATION_TEST(lltreeiterators "" "${test_libs}")
|
||||
|
|
@ -328,6 +330,11 @@ if (LL_TESTS)
|
|||
LL_ADD_INTEGRATION_TEST(llleap "" "${test_libs}")
|
||||
LL_ADD_INTEGRATION_TEST(llstreamqueue "" "${test_libs}")
|
||||
|
||||
## llexception_test.cpp isn't a regression test, and doesn't need to be run
|
||||
## every build. It's to help a developer make implementation choices about
|
||||
## throwing and catching exceptions.
|
||||
##LL_ADD_INTEGRATION_TEST(llexception "" "${test_libs}")
|
||||
|
||||
# *TODO - reenable these once tcmalloc libs no longer break the build.
|
||||
#ADD_BUILD_TEST(llallocator llcommon)
|
||||
#ADD_BUILD_TEST(llallocator_heap_profile llcommon)
|
||||
|
|
|
|||
|
|
@ -60,6 +60,10 @@ const LLUUID IMG_SMOKE_POOF ("1e63e323-5fe0-452e-92f8-b98bd0f764e3"); // On d
|
|||
const LLUUID IMG_BIG_EXPLOSION_1 ("5e47a0dc-97bf-44e0-8b40-de06718cee9d"); // On dataserver
|
||||
const LLUUID IMG_BIG_EXPLOSION_2 ("9c8eca51-53d5-42a7-bb58-cef070395db8"); // On dataserver
|
||||
|
||||
const LLUUID IMG_ALPHA_GRAD ("e97cf410-8e61-7005-ec06-629eba4cd1fb"); // VIEWER
|
||||
const LLUUID IMG_ALPHA_GRAD_2D ("38b86f85-2575-52a9-a531-23108d8da837"); // VIEWER
|
||||
const LLUUID IMG_TRANSPARENT ("8dcd4a48-2d37-4909-9f78-f7a9eb4ef903"); // VIEWER
|
||||
|
||||
const LLUUID IMG_BLOOM1 ("3c59f7fe-9dc8-47f9-8aaf-a9dd1fbc3bef"); // VIEWER
|
||||
const LLUUID TERRAIN_DIRT_DETAIL ("0bc58228-74a0-7e83-89bc-5c23464bcec5"); // VIEWER
|
||||
const LLUUID TERRAIN_GRASS_DETAIL ("63338ede-0037-c4fd-855b-015d77112fc8"); // VIEWER
|
||||
|
|
|
|||
|
|
@ -197,6 +197,10 @@ LL_COMMON_API extern const LLUUID IMG_SMOKE_POOF;
|
|||
LL_COMMON_API extern const LLUUID IMG_BIG_EXPLOSION_1;
|
||||
LL_COMMON_API extern const LLUUID IMG_BIG_EXPLOSION_2;
|
||||
|
||||
LL_COMMON_API extern const LLUUID IMG_ALPHA_GRAD;
|
||||
LL_COMMON_API extern const LLUUID IMG_ALPHA_GRAD_2D;
|
||||
LL_COMMON_API extern const LLUUID IMG_TRANSPARENT;
|
||||
|
||||
LL_COMMON_API extern const LLUUID IMG_BLOOM1;
|
||||
LL_COMMON_API extern const LLUUID TERRAIN_DIRT_DETAIL;
|
||||
LL_COMMON_API extern const LLUUID TERRAIN_GRASS_DETAIL;
|
||||
|
|
|
|||
|
|
@ -172,12 +172,12 @@ public:
|
|||
virtual bool cleanup() = 0; // Override to do application cleanup
|
||||
|
||||
//
|
||||
// mainLoop()
|
||||
// frame()
|
||||
//
|
||||
// Runs the application main loop. It's assumed that when you exit
|
||||
// this method, the application is in one of the cleanup states, either QUITTING or ERROR
|
||||
// Pass control to the application for a single frame. Returns 'done'
|
||||
// flag: if frame() returns false, it expects to be called again.
|
||||
//
|
||||
virtual bool mainLoop() = 0; // Override for the application main loop. Needs to at least gracefully notice the QUITTING state and exit.
|
||||
virtual bool frame() = 0; // Override for application body logic
|
||||
|
||||
//
|
||||
// Crash logging
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@
|
|||
#include "llevents.h"
|
||||
#include "llerror.h"
|
||||
#include "stringize.h"
|
||||
#include "llexception.h"
|
||||
|
||||
// do nothing, when we need nothing done
|
||||
void LLCoros::no_cleanup(CoroData*) {}
|
||||
|
|
@ -131,9 +132,9 @@ bool LLCoros::cleanup(const LLSD&)
|
|||
if ((previousCount < 5) || !(previousCount % 50))
|
||||
{
|
||||
if (previousCount < 5)
|
||||
LL_INFOS("LLCoros") << "LLCoros: cleaning up coroutine " << mi->first << LL_ENDL;
|
||||
LL_DEBUGS("LLCoros") << "LLCoros: cleaning up coroutine " << mi->first << LL_ENDL;
|
||||
else
|
||||
LL_INFOS("LLCoros") << "LLCoros: cleaning up coroutine " << mi->first << "("<< previousCount << ")" << LL_ENDL;
|
||||
LL_DEBUGS("LLCoros") << "LLCoros: cleaning up coroutine " << mi->first << "("<< previousCount << ")" << LL_ENDL;
|
||||
|
||||
}
|
||||
// The erase() call will invalidate its passed iterator value --
|
||||
|
|
@ -185,9 +186,9 @@ std::string LLCoros::generateDistinctName(const std::string& prefix) const
|
|||
if ((previousCount < 5) || !(previousCount % 50))
|
||||
{
|
||||
if (previousCount < 5)
|
||||
LL_INFOS("LLCoros") << "LLCoros: launching coroutine " << name << LL_ENDL;
|
||||
LL_DEBUGS("LLCoros") << "LLCoros: launching coroutine " << name << LL_ENDL;
|
||||
else
|
||||
LL_INFOS("LLCoros") << "LLCoros: launching coroutine " << name << "(" << previousCount << ")" << LL_ENDL;
|
||||
LL_DEBUGS("LLCoros") << "LLCoros: launching coroutine " << name << "(" << previousCount << ")" << LL_ENDL;
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -223,7 +224,7 @@ std::string LLCoros::getName() const
|
|||
|
||||
void LLCoros::setStackSize(S32 stacksize)
|
||||
{
|
||||
LL_INFOS("LLCoros") << "Setting coroutine stack size to " << stacksize << LL_ENDL;
|
||||
LL_DEBUGS("LLCoros") << "Setting coroutine stack size to " << stacksize << LL_ENDL;
|
||||
mStackSize = stacksize;
|
||||
}
|
||||
|
||||
|
|
@ -235,7 +236,23 @@ void LLCoros::toplevel(coro::self& self, CoroData* data, const callable_t& calla
|
|||
// capture the 'self' param in CoroData
|
||||
data->mSelf = &self;
|
||||
// run the code the caller actually wants in the coroutine
|
||||
callable();
|
||||
try
|
||||
{
|
||||
callable();
|
||||
}
|
||||
catch (const LLContinueError&)
|
||||
{
|
||||
// Any uncaught exception derived from LLContinueError will be caught
|
||||
// here and logged. This coroutine will terminate but the rest of the
|
||||
// viewer will carry on.
|
||||
LOG_UNHANDLED_EXCEPTION(STRINGIZE("coroutine " << data->mName));
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
// Any OTHER kind of uncaught exception will cause the viewer to
|
||||
// crash, hopefully informatively.
|
||||
CRASH_ON_UNHANDLED_EXCEPTION(STRINGIZE("coroutine " << data->mName));
|
||||
}
|
||||
// This cleanup isn't perfectly symmetrical with the way we initially set
|
||||
// data->mPrev, but this is our last chance to reset mCurrentCoro.
|
||||
sCurrentCoro.reset(data->mPrev);
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@
|
|||
#include <boost/graph/topological_sort.hpp>
|
||||
#include <boost/graph/exception.hpp>
|
||||
// other Linden headers
|
||||
#include "llexception.h"
|
||||
|
||||
LLDependenciesBase::VertexList LLDependenciesBase::topo_sort(int vertices, const EdgeList& edges) const
|
||||
{
|
||||
|
|
@ -76,7 +77,7 @@ LLDependenciesBase::VertexList LLDependenciesBase::topo_sort(int vertices, const
|
|||
// Omit independent nodes: display only those that might contribute to
|
||||
// the cycle.
|
||||
describe(out, false);
|
||||
throw Cycle(out.str());
|
||||
LLTHROW(Cycle(out.str()));
|
||||
}
|
||||
// A peculiarity of boost::topological_sort() is that it emits results in
|
||||
// REVERSE topological order: to get the result you want, you must
|
||||
|
|
|
|||
|
|
@ -34,13 +34,13 @@
|
|||
#include <vector>
|
||||
#include <set>
|
||||
#include <map>
|
||||
#include <stdexcept>
|
||||
#include <iosfwd>
|
||||
#include <boost/iterator/transform_iterator.hpp>
|
||||
#include <boost/iterator/indirect_iterator.hpp>
|
||||
#include <boost/range/iterator_range.hpp>
|
||||
#include <boost/function.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
#include "llexception.h"
|
||||
|
||||
/*****************************************************************************
|
||||
* Utilities
|
||||
|
|
@ -106,9 +106,9 @@ public:
|
|||
/**
|
||||
* Exception thrown by sort() if there's a cycle
|
||||
*/
|
||||
struct Cycle: public std::runtime_error
|
||||
struct Cycle: public LLException
|
||||
{
|
||||
Cycle(const std::string& what): std::runtime_error(what) {}
|
||||
Cycle(const std::string& what): LLException(what) {}
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -174,7 +174,8 @@ namespace LLError
|
|||
// not really a level
|
||||
// used to indicate that no messages should be logged
|
||||
};
|
||||
|
||||
// If you change ELevel, please update llvlog() macro below.
|
||||
|
||||
/* Macro support
|
||||
The classes CallSite and Log are used by the logging macros below.
|
||||
They are not intended for general use.
|
||||
|
|
@ -305,24 +306,38 @@ typedef LLError::NoClassInfo _LL_CLASS_TO_LOG;
|
|||
|
||||
/////////////////////////////////
|
||||
// Error Logging Macros
|
||||
// See top of file for common usage.
|
||||
// See top of file for common usage.
|
||||
/////////////////////////////////
|
||||
|
||||
// this macro uses a one-shot do statement to avoid parsing errors when writing control flow statements
|
||||
// without braces:
|
||||
// if (condition) LL_INFOS() << "True" << LL_ENDL; else LL_INFOS()() << "False" << LL_ENDL
|
||||
// Instead of using LL_DEBUGS(), LL_INFOS() et al., it may be tempting to
|
||||
// directly code the lllog() macro so you can pass in the LLError::ELevel as a
|
||||
// variable. DON'T DO IT! The reason is that the first time control passes
|
||||
// through lllog(), it initializes a local static LLError::CallSite with that
|
||||
// *first* ELevel value. All subsequent visits will decide whether or not to
|
||||
// emit output based on the *first* ELevel value bound into that static
|
||||
// CallSite instance. Use LL_VLOGS() instead. lllog() assumes its ELevel
|
||||
// argument never varies.
|
||||
|
||||
#define lllog(level, once, ...) \
|
||||
do { \
|
||||
const char* tags[] = {"", ##__VA_ARGS__}; \
|
||||
::size_t tag_count = LL_ARRAY_SIZE(tags) - 1; \
|
||||
static LLError::CallSite _site( \
|
||||
level, __FILE__, __LINE__, typeid(_LL_CLASS_TO_LOG), __FUNCTION__, once, &tags[1], tag_count);\
|
||||
if (LL_UNLIKELY(_site.shouldLog())) \
|
||||
{ \
|
||||
std::ostringstream* _out = LLError::Log::out(); \
|
||||
// this macro uses a one-shot do statement to avoid parsing errors when
|
||||
// writing control flow statements without braces:
|
||||
// if (condition) LL_INFOS() << "True" << LL_ENDL; else LL_INFOS()() << "False" << LL_ENDL;
|
||||
|
||||
#define lllog(level, once, ...) \
|
||||
do { \
|
||||
const char* tags[] = {"", ##__VA_ARGS__}; \
|
||||
static LLError::CallSite _site(lllog_site_args_(level, once, tags)); \
|
||||
lllog_test_()
|
||||
|
||||
#define lllog_test_() \
|
||||
if (LL_UNLIKELY(_site.shouldLog())) \
|
||||
{ \
|
||||
std::ostringstream* _out = LLError::Log::out(); \
|
||||
(*_out)
|
||||
|
||||
#define lllog_site_args_(level, once, tags) \
|
||||
level, __FILE__, __LINE__, typeid(_LL_CLASS_TO_LOG), \
|
||||
__FUNCTION__, once, &tags[1], LL_ARRAY_SIZE(tags)-1
|
||||
|
||||
//Use this construct if you need to do computation in the middle of a
|
||||
//message:
|
||||
//
|
||||
|
|
@ -363,4 +378,46 @@ typedef LLError::NoClassInfo _LL_CLASS_TO_LOG;
|
|||
#define LL_INFOS_ONCE(...) lllog(LLError::LEVEL_INFO, true, ##__VA_ARGS__)
|
||||
#define LL_WARNS_ONCE(...) lllog(LLError::LEVEL_WARN, true, ##__VA_ARGS__)
|
||||
|
||||
// Use this if you need to pass LLError::ELevel as a variable.
|
||||
#define LL_VLOGS(level, ...) llvlog(level, false, ##__VA_ARGS__)
|
||||
#define LL_VLOGS_ONCE(level, ...) llvlog(level, true, ##__VA_ARGS__)
|
||||
|
||||
// The problem with using lllog() with a variable level is that the first time
|
||||
// through, it initializes a static CallSite instance with whatever level you
|
||||
// pass. That first level is bound into the CallSite; the level parameter is
|
||||
// never again examined. One approach to variable level would be to
|
||||
// dynamically construct a CallSite instance every call -- which could get
|
||||
// expensive, depending on context. So instead, initialize a static CallSite
|
||||
// for each level value we support, then dynamically select the CallSite
|
||||
// instance for the passed level value.
|
||||
// Compare implementation to lllog() above.
|
||||
#define llvlog(level, once, ...) \
|
||||
do { \
|
||||
const char* tags[] = {"", ##__VA_ARGS__}; \
|
||||
/* Need a static CallSite instance per expected ELevel value. */ \
|
||||
/* Since we intend to index this array with the ELevel, */ \
|
||||
/* _sites[0] should be ELevel(0), and so on -- avoid using */ \
|
||||
/* ELevel symbolic names when initializing -- except for */ \
|
||||
/* the last entry, which handles anything beyond the end. */ \
|
||||
/* (Commented ELevel value names are from 2016-09-01.) */ \
|
||||
/* Passing an ELevel past the end of this array is itself */ \
|
||||
/* a fatal error, so ensure the last is LEVEL_ERROR. */ \
|
||||
static LLError::CallSite _sites[] = \
|
||||
{ \
|
||||
/* LEVEL_DEBUG */ \
|
||||
LLError::CallSite(lllog_site_args_(LLError::ELevel(0), once, tags)), \
|
||||
/* LEVEL_INFO */ \
|
||||
LLError::CallSite(lllog_site_args_(LLError::ELevel(1), once, tags)), \
|
||||
/* LEVEL_WARN */ \
|
||||
LLError::CallSite(lllog_site_args_(LLError::ELevel(2), once, tags)), \
|
||||
/* LEVEL_ERROR */ \
|
||||
LLError::CallSite(lllog_site_args_(LLError::LEVEL_ERROR, once, tags)) \
|
||||
}; \
|
||||
/* Clamp the passed 'level' to at most last entry */ \
|
||||
std::size_t which((std::size_t(level) >= LL_ARRAY_SIZE(_sites)) ? \
|
||||
(LL_ARRAY_SIZE(_sites) - 1) : std::size_t(level)); \
|
||||
/* selected CallSite *must* be named _site for LL_ENDL */ \
|
||||
LLError::CallSite& _site(_sites[which]); \
|
||||
lllog_test_()
|
||||
|
||||
#endif // LL_LLERROR_H
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@
|
|||
#include "llerror.h"
|
||||
#include "llcoros.h"
|
||||
#include "llmake.h"
|
||||
#include "llexception.h"
|
||||
|
||||
#include "lleventfilter.h"
|
||||
|
||||
|
|
@ -351,7 +352,7 @@ LLSD errorException(const LLEventWithID& result, const std::string& desc)
|
|||
// returning it, deliver it via exception.
|
||||
if (result.second)
|
||||
{
|
||||
throw LLErrorEvent(desc, result.first);
|
||||
LLTHROW(LLErrorEvent(desc, result.first));
|
||||
}
|
||||
// That way, our caller knows a simple return must be from the reply
|
||||
// pump (pump 0).
|
||||
|
|
|
|||
|
|
@ -31,10 +31,10 @@
|
|||
|
||||
#include <boost/optional.hpp>
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#include <utility> // std::pair
|
||||
#include "llevents.h"
|
||||
#include "llerror.h"
|
||||
#include "llexception.h"
|
||||
|
||||
/**
|
||||
* Like LLListenerOrPumpName, this is a class intended for parameter lists:
|
||||
|
|
@ -234,11 +234,11 @@ LLSD errorException(const LLEventWithID& result, const std::string& desc);
|
|||
* because it's not an error in event processing: rather, this exception
|
||||
* announces an event that bears error information (for some other API).
|
||||
*/
|
||||
class LL_COMMON_API LLErrorEvent: public std::runtime_error
|
||||
class LL_COMMON_API LLErrorEvent: public LLException
|
||||
{
|
||||
public:
|
||||
LLErrorEvent(const std::string& what, const LLSD& data):
|
||||
std::runtime_error(what),
|
||||
LLException(what),
|
||||
mData(data)
|
||||
{}
|
||||
virtual ~LLErrorEvent() throw() {}
|
||||
|
|
|
|||
|
|
@ -57,6 +57,7 @@
|
|||
#include "stringize.h"
|
||||
#include "llerror.h"
|
||||
#include "llsdutil.h"
|
||||
#include "llexception.h"
|
||||
#if LL_MSVC
|
||||
#pragma warning (disable : 4702)
|
||||
#endif
|
||||
|
|
@ -174,7 +175,7 @@ std::string LLEventPumps::registerNew(const LLEventPump& pump, const std::string
|
|||
// Unless we're permitted to tweak it, that's Bad.
|
||||
if (! tweak)
|
||||
{
|
||||
throw LLEventPump::DupPumpName(std::string("Duplicate LLEventPump name '") + name + "'");
|
||||
LLTHROW(LLEventPump::DupPumpName("Duplicate LLEventPump name '" + name + "'"));
|
||||
}
|
||||
// The passed name isn't unique, but we're permitted to tweak it. Find the
|
||||
// first decimal-integer suffix not already taken. The insert() attempt
|
||||
|
|
@ -326,8 +327,8 @@ LLBoundListener LLEventPump::listen_impl(const std::string& name, const LLEventL
|
|||
// is only when the existing connection object is still connected.
|
||||
if (found != mConnections.end() && found->second.connected())
|
||||
{
|
||||
throw DupListenerName(std::string("Attempt to register duplicate listener name '") + name +
|
||||
"' on " + typeid(*this).name() + " '" + getName() + "'");
|
||||
LLTHROW(DupListenerName("Attempt to register duplicate listener name '" + name +
|
||||
"' on " + typeid(*this).name() + " '" + getName() + "'"));
|
||||
}
|
||||
// Okay, name is unique, try to reconcile its dependencies. Specify a new
|
||||
// "node" value that we never use for an mSignal placement; we'll fix it
|
||||
|
|
@ -353,8 +354,8 @@ LLBoundListener LLEventPump::listen_impl(const std::string& name, const LLEventL
|
|||
// unsortable. If we leave the new node in mDeps, it will continue
|
||||
// to screw up all future attempts to sort()! Pull it out.
|
||||
mDeps.remove(name);
|
||||
throw Cycle(std::string("New listener '") + name + "' on " + typeid(*this).name() +
|
||||
" '" + getName() + "' would cause cycle: " + e.what());
|
||||
LLTHROW(Cycle("New listener '" + name + "' on " + typeid(*this).name() +
|
||||
" '" + getName() + "' would cause cycle: " + e.what()));
|
||||
}
|
||||
// Walk the list to verify that we haven't changed the order.
|
||||
float previous = 0.0, myprev = 0.0;
|
||||
|
|
@ -418,7 +419,7 @@ LLBoundListener LLEventPump::listen_impl(const std::string& name, const LLEventL
|
|||
// NOW remove the offending listener node.
|
||||
mDeps.remove(name);
|
||||
// Having constructed a description of the order change, inform caller.
|
||||
throw OrderChange(out.str());
|
||||
LLTHROW(OrderChange(out.str()));
|
||||
}
|
||||
// This node becomes the previous one.
|
||||
previous = dmi->second;
|
||||
|
|
@ -608,7 +609,7 @@ bool LLListenerOrPumpName::operator()(const LLSD& event) const
|
|||
{
|
||||
if (! mListener)
|
||||
{
|
||||
throw Empty("attempting to call uninitialized");
|
||||
LLTHROW(Empty("attempting to call uninitialized"));
|
||||
}
|
||||
return (*mListener)(event);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,7 +37,6 @@
|
|||
#include <set>
|
||||
#include <vector>
|
||||
#include <deque>
|
||||
#include <stdexcept>
|
||||
#if LL_WINDOWS
|
||||
#pragma warning (push)
|
||||
#pragma warning (disable : 4263) // boost::signals2::expired_slot::what() has const mismatch
|
||||
|
|
@ -62,6 +61,7 @@
|
|||
#include "llsingleton.h"
|
||||
#include "lldependencies.h"
|
||||
#include "llstl.h"
|
||||
#include "llexception.h"
|
||||
|
||||
/*==========================================================================*|
|
||||
// override this to allow binding free functions with more parameters
|
||||
|
|
@ -95,12 +95,32 @@ struct LLStopWhenHandled
|
|||
result_type operator()(InputIterator first, InputIterator last) const
|
||||
{
|
||||
for (InputIterator si = first; si != last; ++si)
|
||||
{
|
||||
if (*si)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
{
|
||||
try
|
||||
{
|
||||
if (*si)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch (const LLContinueError&)
|
||||
{
|
||||
// We catch LLContinueError here because an LLContinueError-
|
||||
// based exception means the viewer as a whole should carry on
|
||||
// to the best of our ability. Therefore subsequent listeners
|
||||
// on the same LLEventPump should still receive this event.
|
||||
|
||||
// The iterator passed to a boost::signals2 Combiner is very
|
||||
// clever, but provides no contextual information. We would
|
||||
// very much like to be able to log the name of the LLEventPump
|
||||
// plus the name of this particular listener, but alas.
|
||||
LOG_UNHANDLED_EXCEPTION("LLEventPump");
|
||||
}
|
||||
// We do NOT catch (...) here because we might as well let it
|
||||
// propagate out to the generic handler. If we were able to log
|
||||
// context information here, that would be great, but we can't, so
|
||||
// there's no point.
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
|
@ -188,10 +208,10 @@ public:
|
|||
bool operator()(const LLSD& event) const;
|
||||
|
||||
/// exception if you try to call when empty
|
||||
struct Empty: public std::runtime_error
|
||||
struct Empty: public LLException
|
||||
{
|
||||
Empty(const std::string& what):
|
||||
std::runtime_error(std::string("LLListenerOrPumpName::Empty: ") + what) {}
|
||||
LLException(std::string("LLListenerOrPumpName::Empty: ") + what) {}
|
||||
};
|
||||
|
||||
private:
|
||||
|
|
@ -371,10 +391,10 @@ public:
|
|||
* you didn't pass <tt>tweak=true</tt> to permit it to generate a unique
|
||||
* variant.
|
||||
*/
|
||||
struct DupPumpName: public std::runtime_error
|
||||
struct DupPumpName: public LLException
|
||||
{
|
||||
DupPumpName(const std::string& what):
|
||||
std::runtime_error(std::string("DupPumpName: ") + what) {}
|
||||
LLException(std::string("DupPumpName: ") + what) {}
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -399,9 +419,9 @@ public:
|
|||
/// group exceptions thrown by listen(). We use exceptions because these
|
||||
/// particular errors are likely to be coding errors, found and fixed by
|
||||
/// the developer even before preliminary checkin.
|
||||
struct ListenError: public std::runtime_error
|
||||
struct ListenError: public LLException
|
||||
{
|
||||
ListenError(const std::string& what): std::runtime_error(what) {}
|
||||
ListenError(const std::string& what): LLException(what) {}
|
||||
};
|
||||
/**
|
||||
* exception thrown by listen(). You are attempting to register a
|
||||
|
|
|
|||
|
|
@ -0,0 +1,55 @@
|
|||
/**
|
||||
* @file llexception.cpp
|
||||
* @author Nat Goodspeed
|
||||
* @date 2016-08-12
|
||||
* @brief Implementation for llexception.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2016&license=viewerlgpl$
|
||||
* Copyright (c) 2016, Linden Research, Inc.
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
// Precompiled header
|
||||
#include "linden_common.h"
|
||||
// associated header
|
||||
#include "llexception.h"
|
||||
// STL headers
|
||||
// std headers
|
||||
#include <typeinfo>
|
||||
// external library headers
|
||||
#include <boost/exception/diagnostic_information.hpp>
|
||||
// other Linden headers
|
||||
#include "llerror.h"
|
||||
#include "llerrorcontrol.h"
|
||||
|
||||
namespace {
|
||||
// used by crash_on_unhandled_exception_() and log_unhandled_exception_()
|
||||
void log_unhandled_exception_(LLError::ELevel level,
|
||||
const char* file, int line, const char* pretty_function,
|
||||
const std::string& context)
|
||||
{
|
||||
// log same message but allow caller-specified severity level
|
||||
LL_VLOGS(level, "LLException") << LLError::abbreviateFile(file)
|
||||
<< "(" << line << "): Unhandled exception caught in " << pretty_function;
|
||||
if (! context.empty())
|
||||
{
|
||||
LL_CONT << ": " << context;
|
||||
}
|
||||
LL_CONT << ":\n" << boost::current_exception_diagnostic_information() << LL_ENDL;
|
||||
}
|
||||
}
|
||||
|
||||
void crash_on_unhandled_exception_(const char* file, int line, const char* pretty_function,
|
||||
const std::string& context)
|
||||
{
|
||||
// LL_ERRS() terminates and propagates message into crash dump.
|
||||
log_unhandled_exception_(LLError::LEVEL_ERROR, file, line, pretty_function, context);
|
||||
}
|
||||
|
||||
void log_unhandled_exception_(const char* file, int line, const char* pretty_function,
|
||||
const std::string& context)
|
||||
{
|
||||
// Use LL_WARNS() because we seriously do not expect this to happen
|
||||
// routinely, but we DO expect to return from this function.
|
||||
log_unhandled_exception_(LLError::LEVEL_WARN, file, line, pretty_function, context);
|
||||
}
|
||||
|
|
@ -0,0 +1,85 @@
|
|||
/**
|
||||
* @file llexception.h
|
||||
* @author Nat Goodspeed
|
||||
* @date 2016-06-29
|
||||
* @brief Types needed for generic exception handling
|
||||
*
|
||||
* $LicenseInfo:firstyear=2016&license=viewerlgpl$
|
||||
* Copyright (c) 2016, Linden Research, Inc.
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#if ! defined(LL_LLEXCEPTION_H)
|
||||
#define LL_LLEXCEPTION_H
|
||||
|
||||
#include <stdexcept>
|
||||
#include <boost/exception/exception.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include <boost/current_function.hpp>
|
||||
|
||||
// "Found someone who can comfort me
|
||||
// But there are always exceptions..."
|
||||
// - Empty Pages, Traffic, from John Barleycorn (1970)
|
||||
// https://www.youtube.com/watch?v=dRH0CGVK7ic
|
||||
|
||||
/**
|
||||
* LLException is intended as the common base class from which all
|
||||
* viewer-specific exceptions are derived. Rationale for why it's derived from
|
||||
* both std::exception and boost::exception is explained in
|
||||
* tests/llexception_test.cpp.
|
||||
*
|
||||
* boost::current_exception_diagnostic_information() is quite wonderful: if
|
||||
* all we need to do with an exception is log it, in most places we should
|
||||
* catch (...) and log boost::current_exception_diagnostic_information().
|
||||
* See CRASH_ON_UNHANDLED_EXCEPTION() and LOG_UNHANDLED_EXCEPTION() below.
|
||||
*
|
||||
* There may be circumstances in which it would be valuable to distinguish an
|
||||
* exception explicitly thrown by viewer code from an exception thrown by
|
||||
* (say) a third-party library. Catching (const LLException&) supports such
|
||||
* usage. However, most of the value of this base class is in the
|
||||
* diagnostic_information() available via Boost.Exception.
|
||||
*/
|
||||
struct LLException:
|
||||
public std::runtime_error,
|
||||
public boost::exception
|
||||
{
|
||||
LLException(const std::string& what):
|
||||
std::runtime_error(what)
|
||||
{}
|
||||
};
|
||||
|
||||
/**
|
||||
* The point of LLContinueError is to distinguish exceptions that need not
|
||||
* terminate the whole viewer session. In general, an uncaught exception will
|
||||
* be logged and will crash the viewer. However, though an uncaught exception
|
||||
* derived from LLContinueError will still be logged, the viewer will attempt
|
||||
* to continue processing.
|
||||
*/
|
||||
struct LLContinueError: public LLException
|
||||
{
|
||||
LLContinueError(const std::string& what):
|
||||
LLException(what)
|
||||
{}
|
||||
};
|
||||
|
||||
/**
|
||||
* Please use LLTHROW() to throw viewer exceptions whenever possible. This
|
||||
* enriches the exception's diagnostic_information() with the source file,
|
||||
* line and containing function of the LLTHROW() macro.
|
||||
*/
|
||||
// Currently we implement that using BOOST_THROW_EXCEPTION(). Wrap it in
|
||||
// LLTHROW() in case we ever want to revisit that implementation decision.
|
||||
#define LLTHROW(x) BOOST_THROW_EXCEPTION(x)
|
||||
|
||||
/// Call this macro from a catch (...) clause
|
||||
#define CRASH_ON_UNHANDLED_EXCEPTION(CONTEXT) \
|
||||
crash_on_unhandled_exception_(__FILE__, __LINE__, BOOST_CURRENT_FUNCTION, CONTEXT)
|
||||
void crash_on_unhandled_exception_(const char*, int, const char*, const std::string&);
|
||||
|
||||
/// Call this from a catch (const LLContinueError&) clause, or from a catch
|
||||
/// (...) clause in which you do NOT want the viewer to crash.
|
||||
#define LOG_UNHANDLED_EXCEPTION(CONTEXT) \
|
||||
log_unhandled_exception_(__FILE__, __LINE__, BOOST_CURRENT_FUNCTION, CONTEXT)
|
||||
void log_unhandled_exception_(const char*, int, const char*, const std::string&);
|
||||
|
||||
#endif /* ! defined(LL_LLEXCEPTION_H) */
|
||||
|
|
@ -296,7 +296,16 @@ LL_FORCE_INLINE BlockTimer::BlockTimer(BlockTimerStatHandle& timer)
|
|||
{
|
||||
#if LL_FAST_TIMER_ON
|
||||
BlockTimerStackRecord* cur_timer_data = LLThreadLocalSingletonPointer<BlockTimerStackRecord>::getInstance();
|
||||
if (!cur_timer_data) return;
|
||||
if (!cur_timer_data)
|
||||
{
|
||||
// How likely is it that
|
||||
// LLThreadLocalSingletonPointer<T>::getInstance() will return NULL?
|
||||
// Even without researching, what we can say is that if we exit
|
||||
// without setting mStartTime at all, gcc 4.7 produces (fatal)
|
||||
// warnings about a possibly-uninitialized data member.
|
||||
mStartTime = 0;
|
||||
return;
|
||||
}
|
||||
TimeBlockAccumulator& accumulator = timer.getCurrentAccumulator();
|
||||
accumulator.mActiveCount++;
|
||||
// keep current parent as long as it is active when we are
|
||||
|
|
|
|||
|
|
@ -28,8 +28,11 @@
|
|||
#define LLHANDLE_H
|
||||
|
||||
#include "llpointer.h"
|
||||
#include "llexception.h"
|
||||
#include <stdexcept>
|
||||
#include <boost/type_traits/is_convertible.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
|
||||
/**
|
||||
* Helper object for LLHandle. Don't instantiate these directly, used
|
||||
|
|
@ -213,4 +216,82 @@ private:
|
|||
mutable LLRootHandle<T> mHandle;
|
||||
};
|
||||
|
||||
|
||||
|
||||
class LLCheckedHandleBase
|
||||
{
|
||||
public:
|
||||
class Stale : public LLException
|
||||
{
|
||||
public:
|
||||
Stale() :
|
||||
LLException("Attempt to access stale handle.")
|
||||
{}
|
||||
};
|
||||
|
||||
protected:
|
||||
LLCheckedHandleBase() { }
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* This is a simple wrapper for Handles, allowing direct calls to the underlying
|
||||
* pointer. The checked handle will throw a Stale if an attempt
|
||||
* is made to access the object referenced by the handle and that object has
|
||||
* been destroyed.
|
||||
**/
|
||||
template <typename T>
|
||||
class LLCheckedHandle: public LLCheckedHandleBase
|
||||
{
|
||||
public:
|
||||
|
||||
LLCheckedHandle(LLHandle<T> handle):
|
||||
mHandle(handle)
|
||||
{ }
|
||||
|
||||
/**
|
||||
* Test the underlying handle. If it is no longer valid, throw a Stale exception.
|
||||
*/
|
||||
void check() const
|
||||
{
|
||||
T* ptr = mHandle.get();
|
||||
if (!ptr)
|
||||
BOOST_THROW_EXCEPTION(Stale());
|
||||
}
|
||||
|
||||
/**
|
||||
* Cast back to an appropriate handle
|
||||
*/
|
||||
operator LLHandle<T>() const
|
||||
{
|
||||
return mHandle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the LLCheckedHandle to a bool. Allows for if (chkdHandle) {}
|
||||
* Does not throw.
|
||||
*/
|
||||
/*explicit*/ operator bool() const // explicit conversion operator not available with Linux compiler
|
||||
{
|
||||
return (mHandle.get() != NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to call a method or access a member in the structure referenced
|
||||
* by the handle. If the handle no longer points to a valid structure
|
||||
* throw a Stale.
|
||||
*/
|
||||
T* operator ->() const
|
||||
{
|
||||
T* ptr = mHandle.get();
|
||||
if (!ptr)
|
||||
BOOST_THROW_EXCEPTION(Stale());
|
||||
return ptr;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
LLHandle<T> mHandle;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@
|
|||
#include "lltimer.h"
|
||||
#include "lluuid.h"
|
||||
#include "llleaplistener.h"
|
||||
#include "llexception.h"
|
||||
|
||||
#if LL_MSVC
|
||||
#pragma warning (disable : 4355) // 'this' used in initializer list: yes, intentionally
|
||||
|
|
@ -69,7 +70,7 @@ public:
|
|||
// Rule out empty vector
|
||||
if (plugin.empty())
|
||||
{
|
||||
throw Error("no plugin command");
|
||||
LLTHROW(Error("no plugin command"));
|
||||
}
|
||||
|
||||
// Don't leave desc empty either, but in this case, if we weren't
|
||||
|
|
@ -112,7 +113,7 @@ public:
|
|||
// If that didn't work, no point in keeping this LLLeap object.
|
||||
if (! mChild)
|
||||
{
|
||||
throw Error(STRINGIZE("failed to run " << mDesc));
|
||||
LLTHROW(Error(STRINGIZE("failed to run " << mDesc)));
|
||||
}
|
||||
|
||||
// Okay, launch apparently worked. Change our mDonePump listener.
|
||||
|
|
|
|||
|
|
@ -13,9 +13,9 @@
|
|||
#define LL_LLLEAP_H
|
||||
|
||||
#include "llinstancetracker.h"
|
||||
#include "llexception.h"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <stdexcept>
|
||||
|
||||
/**
|
||||
* LLSD Event API Plugin class. Because instances are managed by
|
||||
|
|
@ -67,9 +67,9 @@ public:
|
|||
* string(s) passed to create() might come from an external source. This
|
||||
* way the caller can catch LLLeap::Error and try to recover.
|
||||
*/
|
||||
struct Error: public std::runtime_error
|
||||
struct Error: public LLException
|
||||
{
|
||||
Error(const std::string& what): std::runtime_error(what) {}
|
||||
Error(const std::string& what): LLException(what) {}
|
||||
};
|
||||
|
||||
virtual ~LLLeap();
|
||||
|
|
|
|||
|
|
@ -110,11 +110,15 @@ template <typename T> T* LL_NEXT_ALIGNED_ADDRESS_64(T* address)
|
|||
#if defined(LL_WINDOWS)
|
||||
return _aligned_malloc(size, align);
|
||||
#else
|
||||
char* aligned = NULL;
|
||||
void* mem = malloc( size + (align - 1) + sizeof(void*) );
|
||||
char* aligned = ((char*)mem) + sizeof(void*);
|
||||
aligned += align - ((uintptr_t)aligned & (align - 1));
|
||||
if (mem)
|
||||
{
|
||||
aligned = ((char*)mem) + sizeof(void*);
|
||||
aligned += align - ((uintptr_t)aligned & (align - 1));
|
||||
|
||||
((void**)aligned)[-1] = mem;
|
||||
((void**)aligned)[-1] = mem;
|
||||
}
|
||||
return aligned;
|
||||
#endif
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@
|
|||
#include "llapr.h"
|
||||
#include "apr_signal.h"
|
||||
#include "llevents.h"
|
||||
#include "llexception.h"
|
||||
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
|
|
@ -472,9 +473,9 @@ private:
|
|||
*****************************************************************************/
|
||||
/// Need an exception to avoid constructing an invalid LLProcess object, but
|
||||
/// internal use only
|
||||
struct LLProcessError: public std::runtime_error
|
||||
struct LLProcessError: public LLException
|
||||
{
|
||||
LLProcessError(const std::string& msg): std::runtime_error(msg) {}
|
||||
LLProcessError(const std::string& msg): LLException(msg) {}
|
||||
};
|
||||
|
||||
LLProcessPtr LLProcess::create(const LLSDOrParams& params)
|
||||
|
|
@ -530,8 +531,8 @@ LLProcess::LLProcess(const LLSDOrParams& params):
|
|||
|
||||
if (! params.validateBlock(true))
|
||||
{
|
||||
throw LLProcessError(STRINGIZE("not launched: failed parameter validation\n"
|
||||
<< LLSDNotationStreamer(params)));
|
||||
LLTHROW(LLProcessError(STRINGIZE("not launched: failed parameter validation\n"
|
||||
<< LLSDNotationStreamer(params))));
|
||||
}
|
||||
|
||||
mPostend = params.postend;
|
||||
|
|
@ -596,10 +597,10 @@ LLProcess::LLProcess(const LLSDOrParams& params):
|
|||
}
|
||||
else
|
||||
{
|
||||
throw LLProcessError(STRINGIZE("For " << params.executable()
|
||||
<< ": unsupported FileParam for " << which
|
||||
<< ": type='" << fparam.type()
|
||||
<< "', name='" << fparam.name() << "'"));
|
||||
LLTHROW(LLProcessError(STRINGIZE("For " << params.executable()
|
||||
<< ": unsupported FileParam for " << which
|
||||
<< ": type='" << fparam.type()
|
||||
<< "', name='" << fparam.name() << "'")));
|
||||
}
|
||||
}
|
||||
// By default, pass APR_NO_PIPE for unspecified slots.
|
||||
|
|
@ -678,7 +679,7 @@ LLProcess::LLProcess(const LLSDOrParams& params):
|
|||
if (ll_apr_warn_status(apr_proc_create(&mProcess, argv[0], &argv[0], NULL, procattr,
|
||||
gAPRPoolp)))
|
||||
{
|
||||
throw LLProcessError(STRINGIZE(params << " failed"));
|
||||
LLTHROW(LLProcessError(STRINGIZE(params << " failed")));
|
||||
}
|
||||
|
||||
// arrange to call status_callback()
|
||||
|
|
@ -1063,7 +1064,7 @@ PIPETYPE& LLProcess::getPipe(FILESLOT slot)
|
|||
PIPETYPE* wp = getPipePtr<PIPETYPE>(error, slot);
|
||||
if (! wp)
|
||||
{
|
||||
throw NoPipe(error);
|
||||
LLTHROW(NoPipe(error));
|
||||
}
|
||||
return *wp;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,13 +30,13 @@
|
|||
#include "llinitparam.h"
|
||||
#include "llsdparam.h"
|
||||
#include "llwin32headerslean.h"
|
||||
#include "llexception.h"
|
||||
#include "apr_thread_proc.h"
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/ptr_container/ptr_vector.hpp>
|
||||
#include <boost/optional.hpp>
|
||||
#include <boost/noncopyable.hpp>
|
||||
#include <iosfwd> // std::ostream
|
||||
#include <stdexcept>
|
||||
|
||||
#if LL_WINDOWS
|
||||
#include "llwin32headerslean.h" // for HANDLE
|
||||
|
|
@ -479,9 +479,9 @@ public:
|
|||
|
||||
/// Exception thrown by getWritePipe(), getReadPipe() if you didn't ask to
|
||||
/// create a pipe at the corresponding FILESLOT.
|
||||
struct NoPipe: public std::runtime_error
|
||||
struct NoPipe: public LLException
|
||||
{
|
||||
NoPipe(const std::string& what): std::runtime_error(what) {}
|
||||
NoPipe(const std::string& what): LLException(what) {}
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -576,6 +576,33 @@ std::string utf8str_truncate(const std::string& utf8str, const S32 max_len)
|
|||
}
|
||||
}
|
||||
|
||||
std::string utf8str_symbol_truncate(const std::string& utf8str, const S32 symbol_len)
|
||||
{
|
||||
if (0 == symbol_len)
|
||||
{
|
||||
return std::string();
|
||||
}
|
||||
if ((S32)utf8str.length() <= symbol_len)
|
||||
{
|
||||
return utf8str;
|
||||
}
|
||||
else
|
||||
{
|
||||
int len = 0, byteIndex = 0;
|
||||
const char* aStr = utf8str.c_str();
|
||||
size_t origSize = utf8str.size();
|
||||
|
||||
for (byteIndex = 0; len < symbol_len && byteIndex < origSize; byteIndex++)
|
||||
{
|
||||
if ((aStr[byteIndex] & 0xc0) != 0x80)
|
||||
{
|
||||
len += 1;
|
||||
}
|
||||
}
|
||||
return utf8str.substr(0, byteIndex);
|
||||
}
|
||||
}
|
||||
|
||||
std::string utf8str_substChar(
|
||||
const std::string& utf8str,
|
||||
const llwchar target_char,
|
||||
|
|
|
|||
|
|
@ -563,6 +563,17 @@ LL_COMMON_API S32 utf8str_compare_insensitive(
|
|||
const std::string& lhs,
|
||||
const std::string& rhs);
|
||||
|
||||
/**
|
||||
* @brief Properly truncate a utf8 string to a maximum character count.
|
||||
*
|
||||
* If symbol_len is longer than the string passed in, the return
|
||||
* value == utf8str.
|
||||
* @param utf8str A valid utf8 string to truncate.
|
||||
* @param symbol_len The maximum number of symbols in the return value.
|
||||
* @return Returns a valid utf8 string with symbol count <= max_len.
|
||||
*/
|
||||
LL_COMMON_API std::string utf8str_symbol_truncate(const std::string& utf8str, const S32 symbol_len);
|
||||
|
||||
/**
|
||||
* @brief Replace all occurences of target_char with replace_char
|
||||
*
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
#include <apr_pools.h>
|
||||
#include <apr_queue.h>
|
||||
#include "llthreadsafequeue.h"
|
||||
#include "llexception.h"
|
||||
|
||||
|
||||
|
||||
|
|
@ -41,13 +42,13 @@ LLThreadSafeQueueImplementation::LLThreadSafeQueueImplementation(apr_pool_t * po
|
|||
{
|
||||
if(mOwnsPool) {
|
||||
apr_status_t status = apr_pool_create(&mPool, 0);
|
||||
if(status != APR_SUCCESS) throw LLThreadSafeQueueError("failed to allocate pool");
|
||||
if(status != APR_SUCCESS) LLTHROW(LLThreadSafeQueueError("failed to allocate pool"));
|
||||
} else {
|
||||
; // No op.
|
||||
}
|
||||
|
||||
apr_status_t status = apr_queue_create(&mQueue, capacity, mPool);
|
||||
if(status != APR_SUCCESS) throw LLThreadSafeQueueError("failed to allocate queue");
|
||||
if(status != APR_SUCCESS) LLTHROW(LLThreadSafeQueueError("failed to allocate queue"));
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -68,9 +69,9 @@ void LLThreadSafeQueueImplementation::pushFront(void * element)
|
|||
apr_status_t status = apr_queue_push(mQueue, element);
|
||||
|
||||
if(status == APR_EINTR) {
|
||||
throw LLThreadSafeQueueInterrupt();
|
||||
LLTHROW(LLThreadSafeQueueInterrupt());
|
||||
} else if(status != APR_SUCCESS) {
|
||||
throw LLThreadSafeQueueError("push failed");
|
||||
LLTHROW(LLThreadSafeQueueError("push failed"));
|
||||
} else {
|
||||
; // Success.
|
||||
}
|
||||
|
|
@ -88,9 +89,9 @@ void * LLThreadSafeQueueImplementation::popBack(void)
|
|||
apr_status_t status = apr_queue_pop(mQueue, &element);
|
||||
|
||||
if(status == APR_EINTR) {
|
||||
throw LLThreadSafeQueueInterrupt();
|
||||
LLTHROW(LLThreadSafeQueueInterrupt());
|
||||
} else if(status != APR_SUCCESS) {
|
||||
throw LLThreadSafeQueueError("pop failed");
|
||||
LLTHROW(LLThreadSafeQueueError("pop failed"));
|
||||
} else {
|
||||
return element;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,9 +27,8 @@
|
|||
#ifndef LL_LLTHREADSAFEQUEUE_H
|
||||
#define LL_LLTHREADSAFEQUEUE_H
|
||||
|
||||
|
||||
#include "llexception.h"
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
|
||||
|
||||
struct apr_pool_t; // From apr_pools.h
|
||||
|
|
@ -40,11 +39,11 @@ class LLThreadSafeQueueImplementation; // See below.
|
|||
// A general queue exception.
|
||||
//
|
||||
class LL_COMMON_API LLThreadSafeQueueError:
|
||||
public std::runtime_error
|
||||
public LLException
|
||||
{
|
||||
public:
|
||||
LLThreadSafeQueueError(std::string const & message):
|
||||
std::runtime_error(message)
|
||||
LLException(message)
|
||||
{
|
||||
; // No op.
|
||||
}
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ unsigned int decode( char const * fiveChars ) throw( bad_input_data )
|
|||
unsigned int ret = 0;
|
||||
for( int ix = 0; ix < 5; ++ix ) {
|
||||
char * s = strchr( encodeTable, fiveChars[ ix ] );
|
||||
if( s == 0 ) throw bad_input_data();
|
||||
if( s == 0 ) LLTHROW(bad_input_data());
|
||||
ret = ret * 85 + (s-encodeTable);
|
||||
}
|
||||
return ret;
|
||||
|
|
|
|||
|
|
@ -237,8 +237,21 @@ namespace tut
|
|||
void ErrorTestObject::test<4>()
|
||||
// file abbreviation
|
||||
{
|
||||
std::string thisFile = __FILE__;
|
||||
std::string abbreviateFile = LLError::abbreviateFile(thisFile);
|
||||
std::string prev, abbreviateFile = __FILE__;
|
||||
do
|
||||
{
|
||||
prev = abbreviateFile;
|
||||
abbreviateFile = LLError::abbreviateFile(abbreviateFile);
|
||||
// __FILE__ is assumed to end with
|
||||
// indra/llcommon/tests/llerror_test.cpp. This test used to call
|
||||
// abbreviateFile() exactly once, then check below whether it
|
||||
// still contained the string 'indra'. That fails if the FIRST
|
||||
// part of the pathname also contains indra! Certain developer
|
||||
// machine images put local directory trees under
|
||||
// /ngi-persist/indra, which is where we observe the problem. So
|
||||
// now, keep calling abbreviateFile() until it returns its
|
||||
// argument unchanged, THEN check.
|
||||
} while (abbreviateFile != prev);
|
||||
|
||||
ensure_ends_with("file name abbreviation",
|
||||
abbreviateFile,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,308 @@
|
|||
/**
|
||||
* @file llexception_test.cpp
|
||||
* @author Nat Goodspeed
|
||||
* @date 2016-08-12
|
||||
* @brief Tests for throwing exceptions.
|
||||
*
|
||||
* This isn't a regression test: it doesn't need to be run every build, which
|
||||
* is why the corresponding line in llcommon/CMakeLists.txt is commented out.
|
||||
* Rather it's a head-to-head test of what kind of exception information we
|
||||
* can collect from various combinations of exception base classes, type of
|
||||
* throw verb and sequences of catch clauses.
|
||||
*
|
||||
* This "test" makes no ensure() calls: its output goes to stdout for human
|
||||
* examination.
|
||||
*
|
||||
* As of 2016-08-12 with Boost 1.57, we come to the following conclusions.
|
||||
* These should probably be re-examined from time to time as we update Boost.
|
||||
*
|
||||
* - It is indisputably beneficial to use BOOST_THROW_EXCEPTION() rather than
|
||||
* plain throw. The macro annotates the exception object with the filename,
|
||||
* line number and function name from which the exception was thrown.
|
||||
*
|
||||
* - That being the case, deriving only from boost::exception isn't an option.
|
||||
* Every exception object passed to BOOST_THROW_EXCEPTION() must be derived
|
||||
* directly or indirectly from std::exception. The only question is whether
|
||||
* to also derive from boost::exception. We decided to derive LLException
|
||||
* from both, as it makes message output slightly cleaner, but this is a
|
||||
* trivial reason: if a strong reason emerges to prefer single inheritance,
|
||||
* dropping the boost::exception base class shouldn't be a problem.
|
||||
*
|
||||
* - (As you will have guessed, ridiculous things like a char* or int or a
|
||||
* class derived from neither boost::exception nor std::exception can only
|
||||
* be caught by that specific type or (...), and
|
||||
* boost::current_exception_diagnostic_information() simply throws up its
|
||||
* hands and confesses utter ignorance. Stay away from such nonsense.)
|
||||
*
|
||||
* - But if you derive from std::exception, to nat's surprise,
|
||||
* boost::current_exception_diagnostic_information() gives as much
|
||||
* information about exceptions in a catch (...) clause as you can get from
|
||||
* a specific catch (const std::exception&) clause, notably the concrete
|
||||
* exception class and the what() string. So instead of a sequence like
|
||||
*
|
||||
* try { ... }
|
||||
* catch (const boost::exception& e) { ... boost-flavored logging ... }
|
||||
* catch (const std::exception& e) { ... std::exception logging ... }
|
||||
* catch (...) { ... generic logging ... }
|
||||
*
|
||||
* we should be able to get away with only a catch (...) clause that logs
|
||||
* boost::current_exception_diagnostic_information().
|
||||
*
|
||||
* - Going further: boost::current_exception_diagnostic_information() provides
|
||||
* just as much information even within a std::set_terminate() handler. So
|
||||
* it might not even be strictly necessary to include a catch (...) clause
|
||||
* since the viewer does use std::set_terminate().
|
||||
*
|
||||
* - (We might consider adding a catch (int) clause because Kakadu internally
|
||||
* throws ints, and who knows if one of those might leak out. If it does,
|
||||
* boost::current_exception_diagnostic_information() can do nothing with it.
|
||||
* A catch (int) clause could at least log the value and rethrow.)
|
||||
*
|
||||
* $LicenseInfo:firstyear=2016&license=viewerlgpl$
|
||||
* Copyright (c) 2016, Linden Research, Inc.
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
// Precompiled header
|
||||
#include "linden_common.h"
|
||||
// associated header
|
||||
#include "llexception.h"
|
||||
// STL headers
|
||||
// std headers
|
||||
#include <typeinfo>
|
||||
// external library headers
|
||||
#include <boost/throw_exception.hpp>
|
||||
// other Linden headers
|
||||
#include "../test/lltut.h"
|
||||
|
||||
// helper for display output
|
||||
// usage: std::cout << center(some string value, fill char, width) << std::endl;
|
||||
// (assumes it's the only thing on that particular line)
|
||||
struct center
|
||||
{
|
||||
center(const std::string& label, char fill, std::size_t width):
|
||||
mLabel(label),
|
||||
mFill(fill),
|
||||
mWidth(width)
|
||||
{}
|
||||
|
||||
// Use friend declaration not because we need to grant access, but because
|
||||
// it lets us declare a free operator like a member function.
|
||||
friend std::ostream& operator<<(std::ostream& out, const center& ctr)
|
||||
{
|
||||
std::size_t padded = ctr.mLabel.length() + 2;
|
||||
std::size_t left = (ctr.mWidth - padded) / 2;
|
||||
std::size_t right = ctr.mWidth - left - padded;
|
||||
return out << std::string(left, ctr.mFill) << ' ' << ctr.mLabel << ' '
|
||||
<< std::string(right, ctr.mFill);
|
||||
}
|
||||
|
||||
std::string mLabel;
|
||||
char mFill;
|
||||
std::size_t mWidth;
|
||||
};
|
||||
|
||||
/*****************************************************************************
|
||||
* Four kinds of exceptions: derived from boost::exception, from
|
||||
* std::exception, from both, from neither
|
||||
*****************************************************************************/
|
||||
// Interestingly, we can't use this variant with BOOST_THROW_EXCEPTION()
|
||||
// (which we want) -- we reach a failure topped by this comment:
|
||||
// //All boost exceptions are required to derive from std::exception,
|
||||
// //to ensure compatibility with BOOST_NO_EXCEPTIONS.
|
||||
struct FromBoost: public boost::exception
|
||||
{
|
||||
FromBoost(const std::string& what): mWhat(what) {}
|
||||
~FromBoost() throw() {}
|
||||
std::string what() const { return mWhat; }
|
||||
std::string mWhat;
|
||||
};
|
||||
|
||||
struct FromStd: public std::runtime_error
|
||||
{
|
||||
FromStd(const std::string& what): std::runtime_error(what) {}
|
||||
};
|
||||
|
||||
struct FromBoth: public boost::exception, public std::runtime_error
|
||||
{
|
||||
FromBoth(const std::string& what): std::runtime_error(what) {}
|
||||
};
|
||||
|
||||
// Same deal with FromNeither: can't use with BOOST_THROW_EXCEPTION().
|
||||
struct FromNeither
|
||||
{
|
||||
FromNeither(const std::string& what): mWhat(what) {}
|
||||
std::string what() const { return mWhat; }
|
||||
std::string mWhat;
|
||||
};
|
||||
|
||||
/*****************************************************************************
|
||||
* Two kinds of throws: plain throw and BOOST_THROW_EXCEPTION()
|
||||
*****************************************************************************/
|
||||
template <typename EXC>
|
||||
void plain_throw(const std::string& what)
|
||||
{
|
||||
throw EXC(what);
|
||||
}
|
||||
|
||||
template <typename EXC>
|
||||
void boost_throw(const std::string& what)
|
||||
{
|
||||
BOOST_THROW_EXCEPTION(EXC(what));
|
||||
}
|
||||
|
||||
// Okay, for completeness, functions that throw non-class values. We wouldn't
|
||||
// even deign to consider these if we hadn't found examples in our own source
|
||||
// code! (Note that Kakadu's internal exception support is still based on
|
||||
// throwing ints.)
|
||||
void throw_char_ptr(const std::string& what)
|
||||
{
|
||||
throw what.c_str(); // umm...
|
||||
}
|
||||
|
||||
void throw_int(const std::string& what)
|
||||
{
|
||||
throw int(what.length());
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Three sequences of catch clauses:
|
||||
* boost::exception then ...,
|
||||
* std::exception then ...,
|
||||
* or just ...
|
||||
*****************************************************************************/
|
||||
void catch_boost_dotdotdot(void (*thrower)(const std::string&), const std::string& what)
|
||||
{
|
||||
try
|
||||
{
|
||||
thrower(what);
|
||||
}
|
||||
catch (const boost::exception& e)
|
||||
{
|
||||
std::cout << "catch (const boost::exception& e)" << std::endl;
|
||||
std::cout << "e is " << typeid(e).name() << std::endl;
|
||||
std::cout << "boost::diagnostic_information(e):\n'"
|
||||
<< boost::diagnostic_information(e) << "'" << std::endl;
|
||||
// no way to report e.what()
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
std::cout << "catch (...)" << std::endl;
|
||||
std::cout << "boost::current_exception_diagnostic_information():\n'"
|
||||
<< boost::current_exception_diagnostic_information() << "'"
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
void catch_std_dotdotdot(void (*thrower)(const std::string&), const std::string& what)
|
||||
{
|
||||
try
|
||||
{
|
||||
thrower(what);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
std::cout << "catch (const std::exception& e)" << std::endl;
|
||||
std::cout << "e is " << typeid(e).name() << std::endl;
|
||||
std::cout << "boost::diagnostic_information(e):\n'"
|
||||
<< boost::diagnostic_information(e) << "'" << std::endl;
|
||||
std::cout << "e.what: '"
|
||||
<< e.what() << "'" << std::endl;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
std::cout << "catch (...)" << std::endl;
|
||||
std::cout << "boost::current_exception_diagnostic_information():\n'"
|
||||
<< boost::current_exception_diagnostic_information() << "'"
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
void catch_dotdotdot(void (*thrower)(const std::string&), const std::string& what)
|
||||
{
|
||||
try
|
||||
{
|
||||
thrower(what);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
std::cout << "catch (...)" << std::endl;
|
||||
std::cout << "boost::current_exception_diagnostic_information():\n'"
|
||||
<< boost::current_exception_diagnostic_information() << "'"
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Try a particular kind of throw against each of three catch sequences
|
||||
*****************************************************************************/
|
||||
void catch_several(void (*thrower)(const std::string&), const std::string& what)
|
||||
{
|
||||
std::cout << std::string(20, '-') << "catch_boost_dotdotdot(" << what << ")" << std::endl;
|
||||
catch_boost_dotdotdot(thrower, "catch_boost_dotdotdot(" + what + ")");
|
||||
|
||||
std::cout << std::string(20, '-') << "catch_std_dotdotdot(" << what << ")" << std::endl;
|
||||
catch_std_dotdotdot(thrower, "catch_std_dotdotdot(" + what + ")");
|
||||
|
||||
std::cout << std::string(20, '-') << "catch_dotdotdot(" << what << ")" << std::endl;
|
||||
catch_dotdotdot(thrower, "catch_dotdotdot(" + what + ")");
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* For a particular kind of exception, try both kinds of throw against all
|
||||
* three catch sequences
|
||||
*****************************************************************************/
|
||||
template <typename EXC>
|
||||
void catch_both_several(const std::string& what)
|
||||
{
|
||||
std::cout << std::string(20, '*') << "plain_throw<" << what << ">" << std::endl;
|
||||
catch_several(plain_throw<EXC>, "plain_throw<" + what + ">");
|
||||
|
||||
std::cout << std::string(20, '*') << "boost_throw<" << what << ">" << std::endl;
|
||||
catch_several(boost_throw<EXC>, "boost_throw<" + what + ">");
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* TUT
|
||||
*****************************************************************************/
|
||||
namespace tut
|
||||
{
|
||||
struct llexception_data
|
||||
{
|
||||
};
|
||||
typedef test_group<llexception_data> llexception_group;
|
||||
typedef llexception_group::object object;
|
||||
llexception_group llexceptiongrp("llexception");
|
||||
|
||||
template<> template<>
|
||||
void object::test<1>()
|
||||
{
|
||||
set_test_name("throwing exceptions");
|
||||
|
||||
// For each kind of exception, try both kinds of throw against all
|
||||
// three catch sequences
|
||||
std::size_t margin = 72;
|
||||
std::cout << center("FromStd", '=', margin) << std::endl;
|
||||
catch_both_several<FromStd>("FromStd");
|
||||
|
||||
std::cout << center("FromBoth", '=', margin) << std::endl;
|
||||
catch_both_several<FromBoth>("FromBoth");
|
||||
|
||||
std::cout << center("FromBoost", '=', margin) << std::endl;
|
||||
// can't throw with BOOST_THROW_EXCEPTION(), just use catch_several()
|
||||
catch_several(plain_throw<FromBoost>, "plain_throw<FromBoost>");
|
||||
|
||||
std::cout << center("FromNeither", '=', margin) << std::endl;
|
||||
// can't throw this with BOOST_THROW_EXCEPTION() either
|
||||
catch_several(plain_throw<FromNeither>, "plain_throw<FromNeither>");
|
||||
|
||||
std::cout << center("const char*", '=', margin) << std::endl;
|
||||
// We don't expect BOOST_THROW_EXCEPTION() to throw anything so daft
|
||||
// as a const char* or an int, so don't bother with
|
||||
// catch_both_several() -- just catch_several().
|
||||
catch_several(throw_char_ptr, "throw_char_ptr");
|
||||
|
||||
std::cout << center("int", '=', margin) << std::endl;
|
||||
catch_several(throw_int, "throw_int");
|
||||
}
|
||||
} // namespace tut
|
||||
|
|
@ -35,13 +35,13 @@
|
|||
|
||||
#include <tut/tut.hpp>
|
||||
#include "llerrorcontrol.h"
|
||||
#include "llexception.h"
|
||||
#include "stringize.h"
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/noncopyable.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <list>
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
|
||||
// statically reference the function in test.cpp... it's short, we could
|
||||
// replicate, but better to reuse
|
||||
|
|
@ -67,9 +67,9 @@ struct WrapLLErrs
|
|||
LLError::restoreSettings(mPriorErrorSettings);
|
||||
}
|
||||
|
||||
struct FatalException: public std::runtime_error
|
||||
struct FatalException: public LLException
|
||||
{
|
||||
FatalException(const std::string& what): std::runtime_error(what) {}
|
||||
FatalException(const std::string& what): LLException(what) {}
|
||||
};
|
||||
|
||||
void operator()(const std::string& message)
|
||||
|
|
@ -78,7 +78,7 @@ struct WrapLLErrs
|
|||
error = message;
|
||||
// Also throw an appropriate exception since calling code is likely to
|
||||
// assume that control won't continue beyond LL_ERRS.
|
||||
throw FatalException(message);
|
||||
LLTHROW(FatalException(message));
|
||||
}
|
||||
|
||||
std::string error;
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ public:
|
|||
LLSD constructPostData();
|
||||
virtual void updateApplication(const std::string& message = LLStringUtil::null);
|
||||
virtual bool init();
|
||||
virtual bool mainLoop() = 0;
|
||||
virtual bool frame() = 0;
|
||||
virtual bool cleanup() = 0;
|
||||
void commonCleanup();
|
||||
void setUserText(const std::string& text) { mCrashInfo["UserNotes"] = text; }
|
||||
|
|
|
|||
|
|
@ -773,7 +773,8 @@ const U8* LLImageBase::getData() const
|
|||
{
|
||||
if(mBadBufferAllocation)
|
||||
{
|
||||
LL_ERRS() << "Bad memory allocation for the image buffer!" << LL_ENDL ;
|
||||
LL_WARNS() << "Bad memory allocation for the image buffer!" << LL_ENDL ;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return mData;
|
||||
|
|
@ -783,7 +784,8 @@ U8* LLImageBase::getData()
|
|||
{
|
||||
if(mBadBufferAllocation)
|
||||
{
|
||||
LL_ERRS() << "Bad memory allocation for the image buffer!" << LL_ENDL ;
|
||||
LL_WARNS() << "Bad memory allocation for the image buffer!" << LL_ENDL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return mData;
|
||||
|
|
@ -895,30 +897,30 @@ void LLImageRaw::setDataAndSize(U8 *data, S32 width, S32 height, S8 components)
|
|||
sGlobalRawMemory += getDataSize();
|
||||
}
|
||||
|
||||
BOOL LLImageRaw::resize(U16 width, U16 height, S8 components)
|
||||
bool LLImageRaw::resize(U16 width, U16 height, S8 components)
|
||||
{
|
||||
if ((getWidth() == width) && (getHeight() == height) && (getComponents() == components))
|
||||
{
|
||||
return TRUE;
|
||||
return true;
|
||||
}
|
||||
// Reallocate the data buffer.
|
||||
deleteData();
|
||||
|
||||
allocateDataSize(width,height,components);
|
||||
|
||||
return TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
BOOL LLImageRaw::setSubImage(U32 x_pos, U32 y_pos, U32 width, U32 height,
|
||||
const U8 *data, U32 stride, BOOL reverse_y)
|
||||
bool LLImageRaw::setSubImage(U32 x_pos, U32 y_pos, U32 width, U32 height,
|
||||
const U8 *data, U32 stride, bool reverse_y)
|
||||
{
|
||||
if (!getData())
|
||||
{
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
if (!data)
|
||||
{
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Should do some simple bounds checking
|
||||
|
|
@ -933,13 +935,19 @@ BOOL LLImageRaw::setSubImage(U32 x_pos, U32 y_pos, U32 width, U32 height,
|
|||
data + from_offset, getComponents()*width);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
void LLImageRaw::clear(U8 r, U8 g, U8 b, U8 a)
|
||||
{
|
||||
llassert( getComponents() <= 4 );
|
||||
// This is fairly bogus, but it'll do for now.
|
||||
if (isBufferInvalid())
|
||||
{
|
||||
LL_WARNS() << "Invalid image buffer" << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
|
||||
U8 *pos = getData();
|
||||
U32 x, y;
|
||||
for (x = 0; x < getWidth(); x++)
|
||||
|
|
@ -988,7 +996,7 @@ void LLImageRaw::verticalFlip()
|
|||
}
|
||||
|
||||
|
||||
void LLImageRaw::expandToPowerOfTwo(S32 max_dim, BOOL scale_image)
|
||||
void LLImageRaw::expandToPowerOfTwo(S32 max_dim, bool scale_image)
|
||||
{
|
||||
// Find new sizes
|
||||
S32 new_width = expandDimToPowerOfTwo(getWidth(), max_dim);
|
||||
|
|
@ -997,7 +1005,7 @@ void LLImageRaw::expandToPowerOfTwo(S32 max_dim, BOOL scale_image)
|
|||
scale( new_width, new_height, scale_image );
|
||||
}
|
||||
|
||||
void LLImageRaw::contractToPowerOfTwo(S32 max_dim, BOOL scale_image)
|
||||
void LLImageRaw::contractToPowerOfTwo(S32 max_dim, bool scale_image)
|
||||
{
|
||||
// Find new sizes
|
||||
S32 new_width = contractDimToPowerOfTwo(getWidth(), MIN_IMAGE_SIZE);
|
||||
|
|
@ -1067,6 +1075,11 @@ void LLImageRaw::composite( LLImageRaw* src )
|
|||
{
|
||||
LLImageRaw* dst = this; // Just for clarity.
|
||||
|
||||
if (!validateSrcAndDst("LLImageRaw::composite", src, dst))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
llassert(3 == src->getComponents());
|
||||
llassert(3 == dst->getComponents());
|
||||
|
||||
|
|
@ -1134,7 +1147,6 @@ void LLImageRaw::compositeUnscaled4onto3( LLImageRaw* src )
|
|||
llassert( (3 == src->getComponents()) || (4 == src->getComponents()) );
|
||||
llassert( (src->getWidth() == dst->getWidth()) && (src->getHeight() == dst->getHeight()) );
|
||||
|
||||
|
||||
U8* src_data = src->getData();
|
||||
U8* dst_data = dst->getData();
|
||||
S32 pixels = getWidth() * getHeight();
|
||||
|
|
@ -1169,6 +1181,11 @@ void LLImageRaw::copyUnscaledAlphaMask( LLImageRaw* src, const LLColor4U& fill)
|
|||
{
|
||||
LLImageRaw* dst = this; // Just for clarity.
|
||||
|
||||
if (!validateSrcAndDst("LLImageRaw::copyUnscaledAlphaMask", src, dst))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
llassert( 1 == src->getComponents() );
|
||||
llassert( 4 == dst->getComponents() );
|
||||
llassert( (src->getWidth() == dst->getWidth()) && (src->getHeight() == dst->getHeight()) );
|
||||
|
|
@ -1191,6 +1208,12 @@ void LLImageRaw::copyUnscaledAlphaMask( LLImageRaw* src, const LLColor4U& fill)
|
|||
// Fill the buffer with a constant color
|
||||
void LLImageRaw::fill( const LLColor4U& color )
|
||||
{
|
||||
if (isBufferInvalid())
|
||||
{
|
||||
LL_WARNS() << "Invalid image buffer" << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
|
||||
S32 pixels = getWidth() * getHeight();
|
||||
if( 4 == getComponents() )
|
||||
{
|
||||
|
|
@ -1229,14 +1252,13 @@ LLPointer<LLImageRaw> LLImageRaw::duplicate()
|
|||
// Src and dst can be any size. Src and dst can each have 3 or 4 components.
|
||||
void LLImageRaw::copy(LLImageRaw* src)
|
||||
{
|
||||
if (!src)
|
||||
LLImageRaw* dst = this; // Just for clarity.
|
||||
|
||||
if (!validateSrcAndDst("LLImageRaw::copy", src, dst))
|
||||
{
|
||||
LL_WARNS() << "LLImageRaw::copy called with a null src pointer" << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
|
||||
LLImageRaw* dst = this; // Just for clarity.
|
||||
|
||||
if( (src->getWidth() == dst->getWidth()) && (src->getHeight() == dst->getHeight()) )
|
||||
{
|
||||
// No scaling needed
|
||||
|
|
@ -1363,6 +1385,11 @@ void LLImageRaw::copyScaled( LLImageRaw* src )
|
|||
{
|
||||
LLImageRaw* dst = this; // Just for clarity.
|
||||
|
||||
if (!validateSrcAndDst("LLImageRaw::copyScaled", src, dst))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
llassert_always( (1 == src->getComponents()) || (3 == src->getComponents()) || (4 == src->getComponents()) );
|
||||
llassert_always( src->getComponents() == dst->getComponents() );
|
||||
|
||||
|
|
@ -1397,86 +1424,83 @@ void LLImageRaw::copyScaled( LLImageRaw* src )
|
|||
}
|
||||
|
||||
|
||||
BOOL LLImageRaw::scale( S32 new_width, S32 new_height, BOOL scale_image_data )
|
||||
bool LLImageRaw::scale( S32 new_width, S32 new_height, bool scale_image_data )
|
||||
{
|
||||
llassert((1 == getComponents()) || (3 == getComponents()) || (4 == getComponents()) );
|
||||
S32 components = getComponents();
|
||||
if (! ((1 == components) || (3 == components) || (4 == components) ))
|
||||
{
|
||||
LL_WARNS() << "Invalid getComponents value (" << components << ")" << LL_ENDL;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isBufferInvalid())
|
||||
{
|
||||
LL_WARNS() << "Invalid image buffer" << LL_ENDL;
|
||||
return false;
|
||||
}
|
||||
|
||||
S32 old_width = getWidth();
|
||||
S32 old_height = getHeight();
|
||||
|
||||
if( (old_width == new_width) && (old_height == new_height) )
|
||||
{
|
||||
return TRUE; // Nothing to do.
|
||||
return true; // Nothing to do.
|
||||
}
|
||||
|
||||
// Reallocate the data buffer.
|
||||
|
||||
if (scale_image_data)
|
||||
{
|
||||
/*
|
||||
S32 temp_data_size = old_width * new_height * getComponents();
|
||||
llassert_always(temp_data_size > 0);
|
||||
std::vector<U8> temp_buffer(temp_data_size);
|
||||
S32 new_data_size = new_width * new_height * components;
|
||||
|
||||
// Vertical
|
||||
for( S32 col = 0; col < old_width; col++ )
|
||||
{
|
||||
copyLineScaled( getData() + (getComponents() * col), &temp_buffer[0] + (getComponents() * col), old_height, new_height, old_width, old_width );
|
||||
if (new_data_size > 0)
|
||||
{
|
||||
U8 *new_data = (U8*)ALLOCATE_MEM(LLImageBase::getPrivatePool(), new_data_size);
|
||||
if(NULL == new_data)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bilinear_scale(getData(), old_width, old_height, components, old_width*components, new_data, new_width, new_height, components, new_width*components);
|
||||
setDataAndSize(new_data, new_width, new_height, components);
|
||||
}
|
||||
|
||||
deleteData();
|
||||
|
||||
U8* new_buffer = allocateDataSize(new_width, new_height, getComponents());
|
||||
|
||||
// Horizontal
|
||||
for( S32 row = 0; row < new_height; row++ )
|
||||
{
|
||||
copyLineScaled( &temp_buffer[0] + (getComponents() * old_width * row), new_buffer + (getComponents() * new_width * row), old_width, new_width, 1, 1 );
|
||||
}
|
||||
*/
|
||||
|
||||
S32 new_data_size = new_width * new_height * getComponents();
|
||||
llassert_always(new_data_size > 0);
|
||||
|
||||
U8 *new_data = (U8*)ALLOCATE_MEM(LLImageBase::getPrivatePool(), new_data_size);
|
||||
if(NULL == new_data)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
bilinear_scale(getData(), old_width, old_height, getComponents(), old_width*getComponents(), new_data, new_width, new_height, getComponents(), new_width*getComponents());
|
||||
setDataAndSize(new_data, new_width, new_height, getComponents());
|
||||
}
|
||||
else
|
||||
{
|
||||
// copy out existing image data
|
||||
S32 temp_data_size = old_width * old_height * getComponents();
|
||||
S32 temp_data_size = old_width * old_height * components;
|
||||
std::vector<U8> temp_buffer(temp_data_size);
|
||||
memcpy(&temp_buffer[0], getData(), temp_data_size);
|
||||
|
||||
// allocate new image data, will delete old data
|
||||
U8* new_buffer = allocateDataSize(new_width, new_height, getComponents());
|
||||
U8* new_buffer = allocateDataSize(new_width, new_height, components);
|
||||
|
||||
for( S32 row = 0; row < new_height; row++ )
|
||||
{
|
||||
if (row < old_height)
|
||||
{
|
||||
memcpy(new_buffer + (new_width * row * getComponents()), &temp_buffer[0] + (old_width * row * getComponents()), getComponents() * llmin(old_width, new_width));
|
||||
if (old_width < new_width)
|
||||
{
|
||||
// pad out rest of row with black
|
||||
memset(new_buffer + (getComponents() * ((new_width * row) + old_width)), 0, getComponents() * (new_width - old_width));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// pad remaining rows with black
|
||||
memset(new_buffer + (new_width * row * getComponents()), 0, new_width * getComponents());
|
||||
}
|
||||
}
|
||||
if (!new_buffer)
|
||||
{
|
||||
LL_WARNS() << "Failed to allocate new image data buffer" << LL_ENDL;
|
||||
return false;
|
||||
}
|
||||
|
||||
for( S32 row = 0; row < new_height; row++ )
|
||||
{
|
||||
if (row < old_height)
|
||||
{
|
||||
memcpy(new_buffer + (new_width * row * components), &temp_buffer[0] + (old_width * row * components), components * llmin(old_width, new_width));
|
||||
if (old_width < new_width)
|
||||
{
|
||||
// pad out rest of row with black
|
||||
memset(new_buffer + (components * ((new_width * row) + old_width)), 0, components * (new_width - old_width));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// pad remaining rows with black
|
||||
memset(new_buffer + (new_width * row * components), 0, new_width * components);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
void LLImageRaw::copyLineScaled( U8* in, U8* out, S32 in_pixel_len, S32 out_pixel_len, S32 in_pixel_step, S32 out_pixel_step )
|
||||
|
|
@ -1690,6 +1714,25 @@ void LLImageRaw::compositeRowScaled4onto3( U8* in, U8* out, S32 in_pixel_len, S3
|
|||
}
|
||||
}
|
||||
|
||||
bool LLImageRaw::validateSrcAndDst(std::string func, LLImageRaw* src, LLImageRaw* dst)
|
||||
{
|
||||
if (!src || !dst || src->isBufferInvalid() || dst->isBufferInvalid())
|
||||
{
|
||||
LL_WARNS() << func << ": Source: ";
|
||||
if (!src) LL_CONT << "Null pointer";
|
||||
else if (src->isBufferInvalid()) LL_CONT << "Invalid buffer";
|
||||
else LL_CONT << "OK";
|
||||
|
||||
LL_CONT << "; Destination: ";
|
||||
if (!dst) LL_CONT << "Null pointer";
|
||||
else if (dst->isBufferInvalid()) LL_CONT << "Invalid buffer";
|
||||
else LL_CONT << "OK";
|
||||
LL_CONT << "." << LL_ENDL;
|
||||
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
|
|
@ -1795,7 +1838,7 @@ bool LLImageRaw::createFromFile(const std::string &filename, bool j2c_lowest_mip
|
|||
ifs.read ((char*)buffer, length);
|
||||
ifs.close();
|
||||
|
||||
BOOL success;
|
||||
bool success;
|
||||
|
||||
success = image->updateData();
|
||||
if (success)
|
||||
|
|
@ -1971,7 +2014,7 @@ S32 LLImageFormatted::calcDiscardLevelBytes(S32 bytes)
|
|||
//----------------------------------------------------------------------------
|
||||
|
||||
// Subclasses that can handle more than 4 channels should override this function.
|
||||
BOOL LLImageFormatted::decodeChannels(LLImageRaw* raw_image,F32 decode_time, S32 first_channel, S32 max_channel)
|
||||
bool LLImageFormatted::decodeChannels(LLImageRaw* raw_image,F32 decode_time, S32 first_channel, S32 max_channel)
|
||||
{
|
||||
llassert( (first_channel == 0) && (max_channel == 4) );
|
||||
return decode( raw_image, decode_time ); // Loads first 4 channels by default.
|
||||
|
|
@ -2022,7 +2065,7 @@ void LLImageFormatted::sanityCheck()
|
|||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
BOOL LLImageFormatted::copyData(U8 *data, S32 size)
|
||||
bool LLImageFormatted::copyData(U8 *data, S32 size)
|
||||
{
|
||||
if ( data && ((data != getData()) || (size != getDataSize())) )
|
||||
{
|
||||
|
|
@ -2030,7 +2073,7 @@ BOOL LLImageFormatted::copyData(U8 *data, S32 size)
|
|||
allocateData(size);
|
||||
memcpy(getData(), data, size); /* Flawfinder: ignore */
|
||||
}
|
||||
return TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
// LLImageFormatted becomes the owner of data
|
||||
|
|
@ -2066,7 +2109,7 @@ void LLImageFormatted::appendData(U8 *data, S32 size)
|
|||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
BOOL LLImageFormatted::load(const std::string &filename, int load_size)
|
||||
bool LLImageFormatted::load(const std::string &filename, int load_size)
|
||||
{
|
||||
resetLastError();
|
||||
|
||||
|
|
@ -2077,12 +2120,12 @@ BOOL LLImageFormatted::load(const std::string &filename, int load_size)
|
|||
if (!apr_file)
|
||||
{
|
||||
setLastError("Unable to open file for reading", filename);
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
if (file_size == 0)
|
||||
{
|
||||
setLastError("File is empty",filename);
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Constrain the load size to acceptable values
|
||||
|
|
@ -2090,7 +2133,7 @@ BOOL LLImageFormatted::load(const std::string &filename, int load_size)
|
|||
{
|
||||
load_size = file_size;
|
||||
}
|
||||
BOOL res;
|
||||
bool res;
|
||||
U8 *data = allocateData(load_size);
|
||||
apr_size_t bytes_read = load_size;
|
||||
apr_status_t s = apr_file_read(apr_file, data, &bytes_read); // modifies bytes_read
|
||||
|
|
@ -2098,7 +2141,7 @@ BOOL LLImageFormatted::load(const std::string &filename, int load_size)
|
|||
{
|
||||
deleteData();
|
||||
setLastError("Unable to read file",filename);
|
||||
res = FALSE;
|
||||
res = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -2108,7 +2151,7 @@ BOOL LLImageFormatted::load(const std::string &filename, int load_size)
|
|||
return res;
|
||||
}
|
||||
|
||||
BOOL LLImageFormatted::save(const std::string &filename)
|
||||
bool LLImageFormatted::save(const std::string &filename)
|
||||
{
|
||||
resetLastError();
|
||||
|
||||
|
|
@ -2117,15 +2160,15 @@ BOOL LLImageFormatted::save(const std::string &filename)
|
|||
if (!outfile.getFileHandle())
|
||||
{
|
||||
setLastError("Unable to open file for writing", filename);
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
outfile.write(getData(), getDataSize());
|
||||
outfile.close() ;
|
||||
return TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
// BOOL LLImageFormatted::save(LLVFS *vfs, const LLUUID &uuid, LLAssetType::EType type)
|
||||
// bool LLImageFormatted::save(LLVFS *vfs, const LLUUID &uuid, LLAssetType::EType type)
|
||||
// Depricated to remove VFS dependency.
|
||||
// Use:
|
||||
// LLVFile::writeFile(image->getData(), image->getDataSize(), vfs, uuid, type);
|
||||
|
|
|
|||
|
|
@ -199,11 +199,11 @@ public:
|
|||
/*virtual*/ U8* allocateData(S32 size = -1);
|
||||
/*virtual*/ U8* reallocateData(S32 size);
|
||||
|
||||
BOOL resize(U16 width, U16 height, S8 components);
|
||||
bool resize(U16 width, U16 height, S8 components);
|
||||
|
||||
//U8 * getSubImage(U32 x_pos, U32 y_pos, U32 width, U32 height) const;
|
||||
BOOL setSubImage(U32 x_pos, U32 y_pos, U32 width, U32 height,
|
||||
const U8 *data, U32 stride = 0, BOOL reverse_y = FALSE);
|
||||
bool setSubImage(U32 x_pos, U32 y_pos, U32 width, U32 height,
|
||||
const U8 *data, U32 stride = 0, bool reverse_y = false);
|
||||
|
||||
void clear(U8 r=0, U8 g=0, U8 b=0, U8 a=255);
|
||||
|
||||
|
|
@ -212,10 +212,10 @@ public:
|
|||
static S32 biasedDimToPowerOfTwo(S32 curr_dim, S32 max_dim = MAX_IMAGE_SIZE);
|
||||
static S32 expandDimToPowerOfTwo(S32 curr_dim, S32 max_dim = MAX_IMAGE_SIZE);
|
||||
static S32 contractDimToPowerOfTwo(S32 curr_dim, S32 min_dim = MIN_IMAGE_SIZE);
|
||||
void expandToPowerOfTwo(S32 max_dim = MAX_IMAGE_SIZE, BOOL scale_image = TRUE);
|
||||
void contractToPowerOfTwo(S32 max_dim = MAX_IMAGE_SIZE, BOOL scale_image = TRUE);
|
||||
void expandToPowerOfTwo(S32 max_dim = MAX_IMAGE_SIZE, bool scale_image = true);
|
||||
void contractToPowerOfTwo(S32 max_dim = MAX_IMAGE_SIZE, bool scale_image = true);
|
||||
void biasedScaleToPowerOfTwo(S32 max_dim = MAX_IMAGE_SIZE);
|
||||
BOOL scale( S32 new_width, S32 new_height, BOOL scale_image = TRUE );
|
||||
bool scale( S32 new_width, S32 new_height, bool scale_image = true );
|
||||
|
||||
// Fill the buffer with a constant color
|
||||
void fill( const LLColor4U& color );
|
||||
|
|
@ -277,6 +277,9 @@ protected:
|
|||
public:
|
||||
static S32 sGlobalRawMemory;
|
||||
static S32 sRawImageCount;
|
||||
|
||||
private:
|
||||
bool validateSrcAndDst(std::string func, LLImageRaw* src, LLImageRaw* dst);
|
||||
};
|
||||
|
||||
// Compressed representation of image.
|
||||
|
|
@ -314,23 +317,23 @@ public:
|
|||
// getRawDiscardLevel() by default returns mDiscardLevel, but may be overridden (LLImageJ2C)
|
||||
virtual S8 getRawDiscardLevel() { return mDiscardLevel; }
|
||||
|
||||
BOOL load(const std::string& filename, int load_size = 0);
|
||||
BOOL save(const std::string& filename);
|
||||
bool load(const std::string& filename, int load_size = 0);
|
||||
bool save(const std::string& filename);
|
||||
|
||||
virtual BOOL updateData() = 0; // pure virtual
|
||||
virtual bool updateData() = 0; // pure virtual
|
||||
void setData(U8 *data, S32 size);
|
||||
void appendData(U8 *data, S32 size);
|
||||
|
||||
// Loads first 4 channels.
|
||||
virtual BOOL decode(LLImageRaw* raw_image, F32 decode_time) = 0;
|
||||
virtual bool decode(LLImageRaw* raw_image, F32 decode_time) = 0;
|
||||
// Subclasses that can handle more than 4 channels should override this function.
|
||||
virtual BOOL decodeChannels(LLImageRaw* raw_image, F32 decode_time, S32 first_channel, S32 max_channel);
|
||||
virtual bool decodeChannels(LLImageRaw* raw_image, F32 decode_time, S32 first_channel, S32 max_channel);
|
||||
|
||||
virtual BOOL encode(const LLImageRaw* raw_image, F32 encode_time) = 0;
|
||||
virtual bool encode(const LLImageRaw* raw_image, F32 encode_time) = 0;
|
||||
|
||||
S8 getCodec() const;
|
||||
BOOL isDecoding() const { return mDecoding ? TRUE : FALSE; }
|
||||
BOOL isDecoded() const { return mDecoded ? TRUE : FALSE; }
|
||||
bool isDecoding() const { return mDecoding; }
|
||||
bool isDecoded() const { return mDecoded; }
|
||||
void setDiscardLevel(S8 discard_level) { mDiscardLevel = discard_level; }
|
||||
S8 getDiscardLevel() const { return mDiscardLevel; }
|
||||
S8 getLevels() const { return mLevels; }
|
||||
|
|
@ -341,7 +344,7 @@ public:
|
|||
virtual void setLastError(const std::string& message, const std::string& filename = std::string());
|
||||
|
||||
protected:
|
||||
BOOL copyData(U8 *data, S32 size); // calls updateData()
|
||||
bool copyData(U8 *data, S32 size); // calls updateData()
|
||||
|
||||
protected:
|
||||
S8 mCodec;
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ LLImageBMP::LLImageBMP()
|
|||
mColorPalette( NULL ),
|
||||
mBitmapOffset( 0 ),
|
||||
mBitsPerPixel( 0 ),
|
||||
mOriginAtTop( FALSE )
|
||||
mOriginAtTop( false )
|
||||
{
|
||||
mBitfieldMask[0] = 0;
|
||||
mBitfieldMask[1] = 0;
|
||||
|
|
@ -92,7 +92,7 @@ LLImageBMP::~LLImageBMP()
|
|||
}
|
||||
|
||||
|
||||
BOOL LLImageBMP::updateData()
|
||||
bool LLImageBMP::updateData()
|
||||
{
|
||||
resetLastError();
|
||||
|
||||
|
|
@ -101,7 +101,7 @@ BOOL LLImageBMP::updateData()
|
|||
if (!mdata || (0 == getDataSize()))
|
||||
{
|
||||
setLastError("Uninitialized instance of LLImageBMP");
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Read the bitmap headers in order to get all the useful info
|
||||
|
|
@ -120,12 +120,12 @@ BOOL LLImageBMP::updateData()
|
|||
if ((mdata[0] != 'B') || (mdata[1] != 'A'))
|
||||
{
|
||||
setLastError("OS/2 bitmap array BMP files are not supported");
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
setLastError("Does not appear to be a bitmap file");
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -160,12 +160,12 @@ BOOL LLImageBMP::updateData()
|
|||
llendianswizzleone(header.mNumColors);
|
||||
llendianswizzleone(header.mNumColorsImportant);
|
||||
|
||||
BOOL windows_nt_version = FALSE;
|
||||
BOOL windows_95_version = FALSE;
|
||||
bool windows_nt_version = false;
|
||||
bool windows_95_version = false;
|
||||
if( 12 == header.mSize )
|
||||
{
|
||||
setLastError("Windows 2.x and OS/2 1.x BMP files are not supported");
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
else
|
||||
if( 40 == header.mSize )
|
||||
|
|
@ -173,7 +173,7 @@ BOOL LLImageBMP::updateData()
|
|||
if( 3 == header.mCompression )
|
||||
{
|
||||
// Windows NT
|
||||
windows_nt_version = TRUE;
|
||||
windows_nt_version = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -184,32 +184,32 @@ BOOL LLImageBMP::updateData()
|
|||
if( 12 <= header.mSize && 64 <= header.mSize )
|
||||
{
|
||||
setLastError("OS/2 2.x BMP files are not supported");
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
else
|
||||
if( 108 == header.mSize )
|
||||
{
|
||||
// BITMAPV4HEADER
|
||||
windows_95_version = TRUE;
|
||||
windows_95_version = true;
|
||||
}
|
||||
else
|
||||
if( 108 < header.mSize )
|
||||
{
|
||||
// BITMAPV5HEADER or greater
|
||||
// Should work as long at Microsoft maintained backwards compatibility (which they did in V4 and V5)
|
||||
windows_95_version = TRUE;
|
||||
windows_95_version = true;
|
||||
}
|
||||
|
||||
S32 width = header.mWidth;
|
||||
S32 height = header.mHeight;
|
||||
if (height < 0)
|
||||
{
|
||||
mOriginAtTop = TRUE;
|
||||
mOriginAtTop = true;
|
||||
height = -height;
|
||||
}
|
||||
else
|
||||
{
|
||||
mOriginAtTop = FALSE;
|
||||
mOriginAtTop = false;
|
||||
}
|
||||
|
||||
mBitsPerPixel = header.mBitsPerPixel;
|
||||
|
|
@ -228,10 +228,10 @@ BOOL LLImageBMP::updateData()
|
|||
case 16: // Started work on 16, but doesn't work yet
|
||||
// These are legal, but we don't support them yet.
|
||||
setLastError("Unsupported bit depth");
|
||||
return FALSE;
|
||||
return false;
|
||||
default:
|
||||
setLastError("Unrecognized bit depth");
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
setSize(width, height, components);
|
||||
|
|
@ -244,11 +244,11 @@ BOOL LLImageBMP::updateData()
|
|||
|
||||
case 1:
|
||||
setLastError("8 bit RLE compression not supported.");
|
||||
return FALSE;
|
||||
return false;
|
||||
|
||||
case 2:
|
||||
setLastError("4 bit RLE compression not supported.");
|
||||
return FALSE;
|
||||
return false;
|
||||
|
||||
case 3:
|
||||
// Windows NT or Windows 95
|
||||
|
|
@ -256,7 +256,7 @@ BOOL LLImageBMP::updateData()
|
|||
|
||||
default:
|
||||
setLastError("Unsupported compression format.");
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -267,13 +267,13 @@ BOOL LLImageBMP::updateData()
|
|||
if( (16 != header.mBitsPerPixel) && (32 != header.mBitsPerPixel) )
|
||||
{
|
||||
setLastError("Bitfield encoding requires 16 or 32 bits per pixel.");
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
if( 0 != header.mNumColors )
|
||||
{
|
||||
setLastError("Bitfield encoding is not compatible with a color table.");
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -322,15 +322,15 @@ BOOL LLImageBMP::updateData()
|
|||
if (!mColorPalette)
|
||||
{
|
||||
LL_ERRS() << "Out of memory in LLImageBMP::updateData()" << LL_ENDL;
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
memcpy( mColorPalette, mdata + FILE_HEADER_SIZE + BITMAP_HEADER_SIZE + extension_size, color_palette_size ); /* Flawfinder: ignore */
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
BOOL LLImageBMP::decode(LLImageRaw* raw_image, F32 decode_time)
|
||||
bool LLImageBMP::decode(LLImageRaw* raw_image, F32 decode_time)
|
||||
{
|
||||
llassert_always(raw_image);
|
||||
|
||||
|
|
@ -341,7 +341,7 @@ BOOL LLImageBMP::decode(LLImageRaw* raw_image, F32 decode_time)
|
|||
if (!mdata || (0 == getDataSize()))
|
||||
{
|
||||
setLastError("llimagebmp trying to decode an image with no data!");
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
raw_image->resize(getWidth(), getHeight(), 3);
|
||||
|
|
@ -349,7 +349,7 @@ BOOL LLImageBMP::decode(LLImageRaw* raw_image, F32 decode_time)
|
|||
U8* src = mdata + mBitmapOffset;
|
||||
U8* dst = raw_image->getData();
|
||||
|
||||
BOOL success = FALSE;
|
||||
bool success = false;
|
||||
|
||||
switch( mBitsPerPixel )
|
||||
{
|
||||
|
|
@ -393,7 +393,7 @@ U32 LLImageBMP::countTrailingZeros( U32 m )
|
|||
}
|
||||
|
||||
|
||||
BOOL LLImageBMP::decodeColorMask16( U8* dst, U8* src )
|
||||
bool LLImageBMP::decodeColorMask16( U8* dst, U8* src )
|
||||
{
|
||||
llassert( 16 == mBitsPerPixel );
|
||||
|
||||
|
|
@ -426,10 +426,10 @@ BOOL LLImageBMP::decodeColorMask16( U8* dst, U8* src )
|
|||
src += alignment_bytes;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
BOOL LLImageBMP::decodeColorMask32( U8* dst, U8* src )
|
||||
bool LLImageBMP::decodeColorMask32( U8* dst, U8* src )
|
||||
{
|
||||
// Note: alpha is not supported
|
||||
|
||||
|
|
@ -445,7 +445,7 @@ BOOL LLImageBMP::decodeColorMask32( U8* dst, U8* src )
|
|||
|
||||
if (getWidth() * getHeight() * 4 > getDataSize() - mBitmapOffset)
|
||||
{ //here we have situation when data size in src less than actually needed
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
S32 src_row_span = getWidth() * 4;
|
||||
|
|
@ -469,11 +469,11 @@ BOOL LLImageBMP::decodeColorMask32( U8* dst, U8* src )
|
|||
src += alignment_bytes;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
BOOL LLImageBMP::decodeColorTable8( U8* dst, U8* src )
|
||||
bool LLImageBMP::decodeColorTable8( U8* dst, U8* src )
|
||||
{
|
||||
llassert( (8 == mBitsPerPixel) && (mColorPaletteColors >= 256) );
|
||||
|
||||
|
|
@ -482,7 +482,7 @@ BOOL LLImageBMP::decodeColorTable8( U8* dst, U8* src )
|
|||
|
||||
if ((getWidth() * getHeight()) + getHeight() * alignment_bytes > getDataSize() - mBitmapOffset)
|
||||
{ //here we have situation when data size in src less than actually needed
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
for( S32 row = 0; row < getHeight(); row++ )
|
||||
|
|
@ -499,11 +499,11 @@ BOOL LLImageBMP::decodeColorTable8( U8* dst, U8* src )
|
|||
src += alignment_bytes;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
BOOL LLImageBMP::decodeTruecolor24( U8* dst, U8* src )
|
||||
bool LLImageBMP::decodeTruecolor24( U8* dst, U8* src )
|
||||
{
|
||||
llassert( 24 == mBitsPerPixel );
|
||||
llassert( 3 == getComponents() );
|
||||
|
|
@ -512,7 +512,7 @@ BOOL LLImageBMP::decodeTruecolor24( U8* dst, U8* src )
|
|||
|
||||
if ((getWidth() * getHeight() * 3) + getHeight() * alignment_bytes > getDataSize() - mBitmapOffset)
|
||||
{ //here we have situation when data size in src less than actually needed
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
for( S32 row = 0; row < getHeight(); row++ )
|
||||
|
|
@ -528,10 +528,10 @@ BOOL LLImageBMP::decodeTruecolor24( U8* dst, U8* src )
|
|||
src += alignment_bytes;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
BOOL LLImageBMP::encode(const LLImageRaw* raw_image, F32 encode_time)
|
||||
bool LLImageBMP::encode(const LLImageRaw* raw_image, F32 encode_time)
|
||||
{
|
||||
llassert_always(raw_image);
|
||||
|
||||
|
|
@ -563,7 +563,7 @@ BOOL LLImageBMP::encode(const LLImageRaw* raw_image, F32 encode_time)
|
|||
// Allocate the new buffer for the data.
|
||||
if(!allocateData(file_bytes)) //memory allocation failed
|
||||
{
|
||||
return FALSE ;
|
||||
return false ;
|
||||
}
|
||||
|
||||
magic[0] = 'B'; magic[1] = 'M';
|
||||
|
|
@ -663,5 +663,5 @@ BOOL LLImageBMP::encode(const LLImageRaw* raw_image, F32 encode_time)
|
|||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,15 +40,15 @@ public:
|
|||
LLImageBMP();
|
||||
|
||||
/*virtual*/ std::string getExtension() { return std::string("bmp"); }
|
||||
/*virtual*/ BOOL updateData();
|
||||
/*virtual*/ BOOL decode(LLImageRaw* raw_image, F32 decode_time);
|
||||
/*virtual*/ BOOL encode(const LLImageRaw* raw_image, F32 encode_time);
|
||||
/*virtual*/ bool updateData();
|
||||
/*virtual*/ bool decode(LLImageRaw* raw_image, F32 decode_time);
|
||||
/*virtual*/ bool encode(const LLImageRaw* raw_image, F32 encode_time);
|
||||
|
||||
protected:
|
||||
BOOL decodeColorTable8( U8* dst, U8* src );
|
||||
BOOL decodeColorMask16( U8* dst, U8* src );
|
||||
BOOL decodeTruecolor24( U8* dst, U8* src );
|
||||
BOOL decodeColorMask32( U8* dst, U8* src );
|
||||
bool decodeColorTable8( U8* dst, U8* src );
|
||||
bool decodeColorMask16( U8* dst, U8* src );
|
||||
bool decodeTruecolor24( U8* dst, U8* src );
|
||||
bool decodeColorMask32( U8* dst, U8* src );
|
||||
|
||||
U32 countTrailingZeros( U32 m );
|
||||
|
||||
|
|
@ -58,7 +58,7 @@ protected:
|
|||
S32 mBitmapOffset;
|
||||
S32 mBitsPerPixel;
|
||||
U32 mBitfieldMask[4]; // rgba
|
||||
BOOL mOriginAtTop;
|
||||
bool mOriginAtTop;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -201,7 +201,7 @@ bool LLImageDimensionsInfo::getImageDimensionsJpeg()
|
|||
cinfo.out_color_space = JCS_RGB;
|
||||
jpeg_start_decompress (&cinfo);
|
||||
|
||||
mHeight = cinfo.output_width;
|
||||
mWidth = cinfo.output_width;
|
||||
mHeight = cinfo.output_height;
|
||||
|
||||
jpeg_destroy_decompress(&cinfo);
|
||||
|
|
|
|||
|
|
@ -172,7 +172,7 @@ LLImageDXT::~LLImageDXT()
|
|||
}
|
||||
|
||||
// virtual
|
||||
BOOL LLImageDXT::updateData()
|
||||
bool LLImageDXT::updateData()
|
||||
{
|
||||
resetLastError();
|
||||
|
||||
|
|
@ -182,7 +182,7 @@ BOOL LLImageDXT::updateData()
|
|||
if (!data || !data_size)
|
||||
{
|
||||
setLastError("LLImageDXT uninitialized");
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
S32 width, height, miplevelmax;
|
||||
|
|
@ -216,7 +216,7 @@ BOOL LLImageDXT::updateData()
|
|||
discard = llmin(discard, miplevelmax);
|
||||
setDiscardLevel(discard);
|
||||
|
||||
return TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
// discard: 0 = largest (last) mip
|
||||
|
|
@ -257,7 +257,7 @@ void LLImageDXT::setFormat()
|
|||
}
|
||||
|
||||
// virtual
|
||||
BOOL LLImageDXT::decode(LLImageRaw* raw_image, F32 time)
|
||||
bool LLImageDXT::decode(LLImageRaw* raw_image, F32 time)
|
||||
{
|
||||
// *TODO: Test! This has been tweaked since its intial inception,
|
||||
// but we don't use it any more!
|
||||
|
|
@ -266,7 +266,7 @@ BOOL LLImageDXT::decode(LLImageRaw* raw_image, F32 time)
|
|||
if (mFileFormat >= FORMAT_DXT1 && mFileFormat <= FORMAT_DXR5)
|
||||
{
|
||||
LL_WARNS() << "Attempt to decode compressed LLImageDXT to Raw (unsupported)" << LL_ENDL;
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
S32 width = getWidth(), height = getHeight();
|
||||
|
|
@ -286,16 +286,16 @@ BOOL LLImageDXT::decode(LLImageRaw* raw_image, F32 time)
|
|||
if ((!getData()) || (data + image_size > getData() + getDataSize()))
|
||||
{
|
||||
setLastError("LLImageDXT trying to decode an image with not enough data!");
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
raw_image->resize(width, height, ncomponents);
|
||||
memcpy(raw_image->getData(), data, image_size); /* Flawfinder: ignore */
|
||||
|
||||
return TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
BOOL LLImageDXT::getMipData(LLPointer<LLImageRaw>& raw, S32 discard)
|
||||
bool LLImageDXT::getMipData(LLPointer<LLImageRaw>& raw, S32 discard)
|
||||
{
|
||||
if (discard < 0)
|
||||
{
|
||||
|
|
@ -310,10 +310,10 @@ BOOL LLImageDXT::getMipData(LLPointer<LLImageRaw>& raw, S32 discard)
|
|||
S32 height = 0;
|
||||
calcDiscardWidthHeight(discard, mFileFormat, width, height);
|
||||
raw = new LLImageRaw(data, width, height, getComponents());
|
||||
return TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
BOOL LLImageDXT::encodeDXT(const LLImageRaw* raw_image, F32 time, bool explicit_mips)
|
||||
bool LLImageDXT::encodeDXT(const LLImageRaw* raw_image, F32 time, bool explicit_mips)
|
||||
{
|
||||
llassert_always(raw_image);
|
||||
|
||||
|
|
@ -395,11 +395,11 @@ BOOL LLImageDXT::encodeDXT(const LLImageRaw* raw_image, F32 time, bool explicit_
|
|||
prev_mipdata = mipdata;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
// virtual
|
||||
BOOL LLImageDXT::encode(const LLImageRaw* raw_image, F32 time)
|
||||
bool LLImageDXT::encode(const LLImageRaw* raw_image, F32 time)
|
||||
{
|
||||
return encodeDXT(raw_image, time, false);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -93,21 +93,21 @@ protected:
|
|||
/*virtual*/ ~LLImageDXT();
|
||||
|
||||
private:
|
||||
BOOL encodeDXT(const LLImageRaw* raw_image, F32 decode_time, bool explicit_mips);
|
||||
bool encodeDXT(const LLImageRaw* raw_image, F32 decode_time, bool explicit_mips);
|
||||
|
||||
public:
|
||||
LLImageDXT();
|
||||
|
||||
/*virtual*/ std::string getExtension() { return std::string("dxt"); }
|
||||
/*virtual*/ BOOL updateData();
|
||||
/*virtual*/ bool updateData();
|
||||
|
||||
/*virtual*/ BOOL decode(LLImageRaw* raw_image, F32 decode_time);
|
||||
/*virtual*/ BOOL encode(const LLImageRaw* raw_image, F32 encode_time);
|
||||
/*virtual*/ bool decode(LLImageRaw* raw_image, F32 decode_time);
|
||||
/*virtual*/ bool encode(const LLImageRaw* raw_image, F32 encode_time);
|
||||
|
||||
/*virtual*/ S32 calcHeaderSize();
|
||||
/*virtual*/ S32 calcDataSize(S32 discard_level = 0);
|
||||
|
||||
BOOL getMipData(LLPointer<LLImageRaw>& raw, S32 discard=-1);
|
||||
bool getMipData(LLPointer<LLImageRaw>& raw, S32 discard=-1);
|
||||
|
||||
void setFormat();
|
||||
S32 getMipOffset(S32 discard);
|
||||
|
|
|
|||
|
|
@ -31,18 +31,13 @@
|
|||
#include "llmath.h"
|
||||
#include "llmemory.h"
|
||||
#include "llsd.h"
|
||||
#include <boost/scoped_ptr.hpp>
|
||||
|
||||
typedef LLImageJ2CImpl* (*CreateLLImageJ2CFunction)();
|
||||
typedef void (*DestroyLLImageJ2CFunction)(LLImageJ2CImpl*);
|
||||
typedef const char* (*EngineInfoLLImageJ2CFunction)();
|
||||
|
||||
// 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.
|
||||
// Declare the prototype for this factory function here. It is implemented in
|
||||
// other files which define a LLImageJ2CImpl subclass, but only ONE static
|
||||
// library which has the implementation for this function should ever be
|
||||
// linked.
|
||||
LLImageJ2CImpl* fallbackCreateLLImageJ2CImpl();
|
||||
void fallbackDestroyLLImageJ2CImpl(LLImageJ2CImpl* impl);
|
||||
const char* fallbackEngineInfoLLImageJ2CImpl();
|
||||
|
||||
// Test data gathering handle
|
||||
LLImageCompressionTester* LLImageJ2C::sTesterp = NULL ;
|
||||
|
|
@ -51,17 +46,20 @@ const std::string sTesterName("ImageCompressionTester");
|
|||
//static
|
||||
std::string LLImageJ2C::getEngineInfo()
|
||||
{
|
||||
return fallbackEngineInfoLLImageJ2CImpl();
|
||||
// All known LLImageJ2CImpl implementation subclasses are cheap to
|
||||
// construct.
|
||||
boost::scoped_ptr<LLImageJ2CImpl> impl(fallbackCreateLLImageJ2CImpl());
|
||||
return impl->getEngineInfo();
|
||||
}
|
||||
|
||||
LLImageJ2C::LLImageJ2C() : LLImageFormatted(IMG_CODEC_J2C),
|
||||
mMaxBytes(0),
|
||||
mRawDiscardLevel(-1),
|
||||
mRate(DEFAULT_COMPRESSION_RATE),
|
||||
mReversible(FALSE),
|
||||
mReversible(false),
|
||||
mAreaUsedForDataSizeCalcs(0)
|
||||
{
|
||||
mImpl = fallbackCreateLLImageJ2CImpl();
|
||||
mImpl.reset(fallbackCreateLLImageJ2CImpl());
|
||||
claimMem(mImpl);
|
||||
|
||||
// Clear data size table
|
||||
|
|
@ -83,13 +81,7 @@ LLImageJ2C::LLImageJ2C() : LLImageFormatted(IMG_CODEC_J2C),
|
|||
}
|
||||
|
||||
// virtual
|
||||
LLImageJ2C::~LLImageJ2C()
|
||||
{
|
||||
if ( mImpl )
|
||||
{
|
||||
fallbackDestroyLLImageJ2CImpl(mImpl);
|
||||
}
|
||||
}
|
||||
LLImageJ2C::~LLImageJ2C() {}
|
||||
|
||||
// virtual
|
||||
void LLImageJ2C::resetLastError()
|
||||
|
|
@ -111,16 +103,16 @@ S8 LLImageJ2C::getRawDiscardLevel()
|
|||
return mRawDiscardLevel;
|
||||
}
|
||||
|
||||
BOOL LLImageJ2C::updateData()
|
||||
bool LLImageJ2C::updateData()
|
||||
{
|
||||
BOOL res = TRUE;
|
||||
bool res = true;
|
||||
resetLastError();
|
||||
|
||||
// Check to make sure that this instance has been initialized with data
|
||||
if (!getData() || (getDataSize() < 16))
|
||||
{
|
||||
setLastError("LLImageJ2C uninitialized");
|
||||
res = FALSE;
|
||||
res = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -142,29 +134,29 @@ BOOL LLImageJ2C::updateData()
|
|||
return res;
|
||||
}
|
||||
|
||||
BOOL LLImageJ2C::initDecode(LLImageRaw &raw_image, int discard_level, int* region)
|
||||
bool LLImageJ2C::initDecode(LLImageRaw &raw_image, int discard_level, int* region)
|
||||
{
|
||||
setDiscardLevel(discard_level != -1 ? discard_level : 0);
|
||||
return mImpl->initDecode(*this,raw_image,discard_level,region);
|
||||
}
|
||||
|
||||
BOOL LLImageJ2C::initEncode(LLImageRaw &raw_image, int blocks_size, int precincts_size, int levels)
|
||||
bool LLImageJ2C::initEncode(LLImageRaw &raw_image, int blocks_size, int precincts_size, int levels)
|
||||
{
|
||||
return mImpl->initEncode(*this,raw_image,blocks_size,precincts_size,levels);
|
||||
}
|
||||
|
||||
BOOL LLImageJ2C::decode(LLImageRaw *raw_imagep, F32 decode_time)
|
||||
bool LLImageJ2C::decode(LLImageRaw *raw_imagep, F32 decode_time)
|
||||
{
|
||||
return decodeChannels(raw_imagep, decode_time, 0, 4);
|
||||
}
|
||||
|
||||
|
||||
// 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 )
|
||||
// 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;
|
||||
|
||||
BOOL res = TRUE;
|
||||
bool res = true;
|
||||
|
||||
resetLastError();
|
||||
|
||||
|
|
@ -172,13 +164,13 @@ BOOL LLImageJ2C::decodeChannels(LLImageRaw *raw_imagep, F32 decode_time, S32 fir
|
|||
if (!getData() || (getDataSize() < 16))
|
||||
{
|
||||
setLastError("LLImageJ2C uninitialized");
|
||||
res = TRUE; // done
|
||||
res = true; // done
|
||||
}
|
||||
else
|
||||
{
|
||||
// Update the raw discard level
|
||||
updateRawDiscardLevel();
|
||||
mDecoding = TRUE;
|
||||
mDecoding = true;
|
||||
res = mImpl->decodeImpl(*this, *raw_imagep, decode_time, first_channel, max_channel_count);
|
||||
}
|
||||
|
||||
|
|
@ -191,7 +183,7 @@ BOOL LLImageJ2C::decodeChannels(LLImageRaw *raw_imagep, F32 decode_time, S32 fir
|
|||
}
|
||||
else
|
||||
{
|
||||
mDecoding = FALSE;
|
||||
mDecoding = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -210,7 +202,7 @@ BOOL LLImageJ2C::decodeChannels(LLImageRaw *raw_imagep, F32 decode_time, S32 fir
|
|||
tester->updateDecompressionStats(elapsed.getElapsedTimeF32()) ;
|
||||
if (res)
|
||||
{
|
||||
// The whole data stream is finally decompressed when res is returned as TRUE
|
||||
// The whole data stream is finally decompressed when res is returned as true
|
||||
tester->updateDecompressionStats(this->getDataSize(), raw_imagep->getDataSize()) ;
|
||||
}
|
||||
}
|
||||
|
|
@ -219,17 +211,17 @@ BOOL LLImageJ2C::decodeChannels(LLImageRaw *raw_imagep, F32 decode_time, S32 fir
|
|||
}
|
||||
|
||||
|
||||
BOOL LLImageJ2C::encode(const LLImageRaw *raw_imagep, F32 encode_time)
|
||||
bool LLImageJ2C::encode(const LLImageRaw *raw_imagep, F32 encode_time)
|
||||
{
|
||||
return encode(raw_imagep, NULL, encode_time);
|
||||
}
|
||||
|
||||
|
||||
BOOL LLImageJ2C::encode(const LLImageRaw *raw_imagep, const char* comment_text, F32 encode_time)
|
||||
bool LLImageJ2C::encode(const LLImageRaw *raw_imagep, const char* comment_text, F32 encode_time)
|
||||
{
|
||||
LLTimer elapsed;
|
||||
resetLastError();
|
||||
BOOL res = mImpl->encodeImpl(*this, *raw_imagep, comment_text, encode_time, mReversible);
|
||||
bool res = mImpl->encodeImpl(*this, *raw_imagep, comment_text, encode_time, mReversible);
|
||||
if (!mLastError.empty())
|
||||
{
|
||||
LLImage::setLastError(mLastError);
|
||||
|
|
@ -245,7 +237,7 @@ BOOL LLImageJ2C::encode(const LLImageRaw *raw_imagep, const char* comment_text,
|
|||
tester->updateCompressionStats(elapsed.getElapsedTimeF32()) ;
|
||||
if (res)
|
||||
{
|
||||
// The whole data stream is finally compressed when res is returned as TRUE
|
||||
// The whole data stream is finally compressed when res is returned as true
|
||||
tester->updateCompressionStats(this->getDataSize(), raw_imagep->getDataSize()) ;
|
||||
}
|
||||
}
|
||||
|
|
@ -348,15 +340,15 @@ void LLImageJ2C::setMaxBytes(S32 max_bytes)
|
|||
mMaxBytes = max_bytes;
|
||||
}
|
||||
|
||||
void LLImageJ2C::setReversible(const BOOL reversible)
|
||||
void LLImageJ2C::setReversible(const bool reversible)
|
||||
{
|
||||
mReversible = reversible;
|
||||
}
|
||||
|
||||
|
||||
BOOL LLImageJ2C::loadAndValidate(const std::string &filename)
|
||||
bool LLImageJ2C::loadAndValidate(const std::string &filename)
|
||||
{
|
||||
BOOL res = TRUE;
|
||||
bool res = true;
|
||||
|
||||
resetLastError();
|
||||
|
||||
|
|
@ -367,12 +359,12 @@ BOOL LLImageJ2C::loadAndValidate(const std::string &filename)
|
|||
if (!apr_file)
|
||||
{
|
||||
setLastError("Unable to open file for reading", filename);
|
||||
res = FALSE;
|
||||
res = false;
|
||||
}
|
||||
else if (file_size == 0)
|
||||
{
|
||||
setLastError("File is empty",filename);
|
||||
res = FALSE;
|
||||
res = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -385,7 +377,7 @@ BOOL LLImageJ2C::loadAndValidate(const std::string &filename)
|
|||
{
|
||||
FREE_MEM(LLImageBase::getPrivatePool(), data);
|
||||
setLastError("Unable to read entire file");
|
||||
res = FALSE;
|
||||
res = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -402,21 +394,21 @@ BOOL LLImageJ2C::loadAndValidate(const std::string &filename)
|
|||
}
|
||||
|
||||
|
||||
BOOL LLImageJ2C::validate(U8 *data, U32 file_size)
|
||||
bool LLImageJ2C::validate(U8 *data, U32 file_size)
|
||||
{
|
||||
|
||||
resetLastError();
|
||||
|
||||
setData(data, file_size);
|
||||
|
||||
BOOL res = updateData();
|
||||
bool res = updateData();
|
||||
if ( res )
|
||||
{
|
||||
// Check to make sure that this instance has been initialized with data
|
||||
if (!getData() || (0 == getDataSize()))
|
||||
{
|
||||
setLastError("LLImageJ2C uninitialized");
|
||||
res = FALSE;
|
||||
res = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -433,7 +425,7 @@ BOOL LLImageJ2C::validate(U8 *data, U32 file_size)
|
|||
|
||||
void LLImageJ2C::decodeFailed()
|
||||
{
|
||||
mDecoding = FALSE;
|
||||
mDecoding = false;
|
||||
}
|
||||
|
||||
void LLImageJ2C::updateRawDiscardLevel()
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
#include "llimage.h"
|
||||
#include "llassettype.h"
|
||||
#include "llmetricperformancetester.h"
|
||||
#include <boost/scoped_ptr.hpp>
|
||||
|
||||
// JPEG2000 : compression rate used in j2c conversion.
|
||||
const F32 DEFAULT_COMPRESSION_RATE = 1.f/8.f;
|
||||
|
|
@ -47,10 +48,10 @@ public:
|
|||
|
||||
// Base class overrides
|
||||
/*virtual*/ std::string getExtension() { return std::string("j2c"); }
|
||||
/*virtual*/ BOOL updateData();
|
||||
/*virtual*/ BOOL decode(LLImageRaw *raw_imagep, F32 decode_time);
|
||||
/*virtual*/ BOOL decodeChannels(LLImageRaw *raw_imagep, F32 decode_time, S32 first_channel, S32 max_channel_count);
|
||||
/*virtual*/ BOOL encode(const LLImageRaw *raw_imagep, F32 encode_time);
|
||||
/*virtual*/ bool updateData();
|
||||
/*virtual*/ bool decode(LLImageRaw *raw_imagep, F32 decode_time);
|
||||
/*virtual*/ bool decodeChannels(LLImageRaw *raw_imagep, F32 decode_time, S32 first_channel, S32 max_channel_count);
|
||||
/*virtual*/ bool encode(const LLImageRaw *raw_imagep, F32 encode_time);
|
||||
/*virtual*/ S32 calcHeaderSize();
|
||||
/*virtual*/ S32 calcDataSize(S32 discard_level = 0);
|
||||
/*virtual*/ S32 calcDiscardLevelBytes(S32 bytes);
|
||||
|
|
@ -59,17 +60,17 @@ public:
|
|||
/*virtual*/ void resetLastError();
|
||||
/*virtual*/ void setLastError(const std::string& message, const std::string& filename = std::string());
|
||||
|
||||
BOOL initDecode(LLImageRaw &raw_image, int discard_level, int* region);
|
||||
BOOL initEncode(LLImageRaw &raw_image, int blocks_size, int precincts_size, int levels);
|
||||
bool initDecode(LLImageRaw &raw_image, int discard_level, int* region);
|
||||
bool initEncode(LLImageRaw &raw_image, int blocks_size, int precincts_size, int levels);
|
||||
|
||||
// Encode with comment text
|
||||
BOOL encode(const LLImageRaw *raw_imagep, const char* comment_text, F32 encode_time=0.0);
|
||||
bool encode(const LLImageRaw *raw_imagep, const char* comment_text, F32 encode_time=0.0);
|
||||
|
||||
BOOL validate(U8 *data, U32 file_size);
|
||||
BOOL loadAndValidate(const std::string &filename);
|
||||
bool validate(U8 *data, U32 file_size);
|
||||
bool loadAndValidate(const std::string &filename);
|
||||
|
||||
// Encode accessors
|
||||
void setReversible(const BOOL reversible); // Use non-lossy?
|
||||
void setReversible(const bool reversible); // Use non-lossy?
|
||||
void setMaxBytes(S32 max_bytes);
|
||||
S32 getMaxBytes() const { return mMaxBytes; }
|
||||
|
||||
|
|
@ -93,8 +94,8 @@ protected:
|
|||
|
||||
S8 mRawDiscardLevel;
|
||||
F32 mRate;
|
||||
BOOL mReversible;
|
||||
LLImageJ2CImpl *mImpl;
|
||||
bool mReversible;
|
||||
boost::scoped_ptr<LLImageJ2CImpl> mImpl;
|
||||
std::string mLastError;
|
||||
|
||||
// Image compression/decompression tester
|
||||
|
|
@ -111,23 +112,25 @@ protected:
|
|||
// Return value:
|
||||
// true: image size and number of channels was determined
|
||||
// false: error on decode
|
||||
virtual BOOL getMetadata(LLImageJ2C &base) = 0;
|
||||
virtual bool getMetadata(LLImageJ2C &base) = 0;
|
||||
// Decode the raw image optionally aborting (to continue later) after
|
||||
// decode_time seconds. Decode at most max_channel_count and start
|
||||
// decoding channel first_channel.
|
||||
// Return value:
|
||||
// true: decoding complete (even if it failed)
|
||||
// false: time expired while decoding
|
||||
virtual BOOL decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decode_time, S32 first_channel, S32 max_channel_count) = 0;
|
||||
virtual BOOL encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, const char* comment_text, F32 encode_time=0.0,
|
||||
BOOL reversible=FALSE) = 0;
|
||||
virtual BOOL initDecode(LLImageJ2C &base, LLImageRaw &raw_image, int discard_level = -1, int* region = NULL) = 0;
|
||||
virtual BOOL initEncode(LLImageJ2C &base, LLImageRaw &raw_image, int blocks_size = -1, int precincts_size = -1, int levels = 0) = 0;
|
||||
virtual bool decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decode_time, S32 first_channel, S32 max_channel_count) = 0;
|
||||
virtual bool encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, const char* comment_text, F32 encode_time=0.0,
|
||||
bool reversible=false) = 0;
|
||||
virtual bool initDecode(LLImageJ2C &base, LLImageRaw &raw_image, int discard_level = -1, int* region = NULL) = 0;
|
||||
virtual bool initEncode(LLImageJ2C &base, LLImageRaw &raw_image, int blocks_size = -1, int precincts_size = -1, int levels = 0) = 0;
|
||||
|
||||
virtual std::string getEngineInfo() const = 0;
|
||||
|
||||
friend class LLImageJ2C;
|
||||
};
|
||||
|
||||
#define LINDEN_J2C_COMMENT_PREFIX "LL_"
|
||||
#define LINDEN_J2C_COMMENT_PREFIX "LL_" // Used by LLAppearanceUtility
|
||||
|
||||
//
|
||||
// This class is used for performance data gathering only.
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ LLImageJPEG::~LLImageJPEG()
|
|||
delete[] mOutputBuffer;
|
||||
}
|
||||
|
||||
BOOL LLImageJPEG::updateData()
|
||||
bool LLImageJPEG::updateData()
|
||||
{
|
||||
resetLastError();
|
||||
|
||||
|
|
@ -53,7 +53,7 @@ BOOL LLImageJPEG::updateData()
|
|||
if (!getData() || (0 == getDataSize()))
|
||||
{
|
||||
setLastError("Uninitialized instance of LLImageJPEG");
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////
|
||||
|
|
@ -79,7 +79,7 @@ BOOL LLImageJPEG::updateData()
|
|||
if(setjmp(sSetjmpBuffer))
|
||||
{
|
||||
jpeg_destroy_decompress(&cinfo);
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
try
|
||||
{
|
||||
|
|
@ -106,7 +106,7 @@ BOOL LLImageJPEG::updateData()
|
|||
|
||||
////////////////////////////////////////
|
||||
// Step 3: read file parameters with jpeg_read_header()
|
||||
jpeg_read_header( &cinfo, TRUE );
|
||||
jpeg_read_header( &cinfo, true );
|
||||
|
||||
// Data set by jpeg_read_header
|
||||
setSize(cinfo.image_width, cinfo.image_height, 3); // Force to 3 components (RGB)
|
||||
|
|
@ -115,13 +115,13 @@ BOOL LLImageJPEG::updateData()
|
|||
// More data set by jpeg_read_header
|
||||
cinfo.num_components;
|
||||
cinfo.jpeg_color_space; // Colorspace of image
|
||||
cinfo.saw_JFIF_marker; // TRUE if a JFIF APP0 marker was seen
|
||||
cinfo.saw_JFIF_marker; // true if a JFIF APP0 marker was seen
|
||||
cinfo.JFIF_major_version; // Version information from JFIF marker
|
||||
cinfo.JFIF_minor_version; //
|
||||
cinfo.density_unit; // Resolution data from JFIF marker
|
||||
cinfo.X_density;
|
||||
cinfo.Y_density;
|
||||
cinfo.saw_Adobe_marker; // TRUE if an Adobe APP14 marker was seen
|
||||
cinfo.saw_Adobe_marker; // true if an Adobe APP14 marker was seen
|
||||
cinfo.Adobe_transform; // Color transform code from Adobe marker
|
||||
*/
|
||||
}
|
||||
|
|
@ -129,13 +129,13 @@ BOOL LLImageJPEG::updateData()
|
|||
{
|
||||
jpeg_destroy_decompress(&cinfo);
|
||||
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
////////////////////////////////////////
|
||||
// Step 4: Release JPEG decompression object
|
||||
jpeg_destroy_decompress(&cinfo);
|
||||
|
||||
return TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Initialize source --- called by jpeg_read_header
|
||||
|
|
@ -154,7 +154,7 @@ boolean LLImageJPEG::decodeFillInputBuffer( j_decompress_ptr cinfo )
|
|||
// Should never get here, since we provide the entire buffer up front.
|
||||
ERREXIT(cinfo, JERR_INPUT_EMPTY);
|
||||
|
||||
return TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Skip data --- used to skip over a potentially large amount of
|
||||
|
|
@ -182,7 +182,7 @@ void LLImageJPEG::decodeTermSource (j_decompress_ptr cinfo)
|
|||
|
||||
|
||||
// Returns true when done, whether or not decode was successful.
|
||||
BOOL LLImageJPEG::decode(LLImageRaw* raw_image, F32 decode_time)
|
||||
bool LLImageJPEG::decode(LLImageRaw* raw_image, F32 decode_time)
|
||||
{
|
||||
llassert_always(raw_image);
|
||||
|
||||
|
|
@ -192,7 +192,7 @@ BOOL LLImageJPEG::decode(LLImageRaw* raw_image, F32 decode_time)
|
|||
if (!getData() || (0 == getDataSize()))
|
||||
{
|
||||
setLastError("LLImageJPEG trying to decode an image with no data!");
|
||||
return TRUE; // done
|
||||
return true; // done
|
||||
}
|
||||
|
||||
S32 row_stride = 0;
|
||||
|
|
@ -220,7 +220,7 @@ BOOL LLImageJPEG::decode(LLImageRaw* raw_image, F32 decode_time)
|
|||
if(setjmp(sSetjmpBuffer))
|
||||
{
|
||||
jpeg_destroy_decompress(&cinfo);
|
||||
return TRUE; // done
|
||||
return true; // done
|
||||
}
|
||||
try
|
||||
{
|
||||
|
|
@ -247,11 +247,11 @@ BOOL LLImageJPEG::decode(LLImageRaw* raw_image, F32 decode_time)
|
|||
////////////////////////////////////////
|
||||
// Step 3: read file parameters with jpeg_read_header()
|
||||
|
||||
jpeg_read_header(&cinfo, TRUE);
|
||||
jpeg_read_header(&cinfo, true);
|
||||
|
||||
// We can ignore the return value from jpeg_read_header since
|
||||
// (a) suspension is not possible with our data source, and
|
||||
// (b) we passed TRUE to reject a tables-only JPEG file as an error.
|
||||
// (b) we passed true to reject a tables-only JPEG file as an error.
|
||||
// See libjpeg.doc for more info.
|
||||
|
||||
setSize(cinfo.image_width, cinfo.image_height, 3); // Force to 3 components (RGB)
|
||||
|
|
@ -314,7 +314,7 @@ BOOL LLImageJPEG::decode(LLImageRaw* raw_image, F32 decode_time)
|
|||
catch (int)
|
||||
{
|
||||
jpeg_destroy_decompress(&cinfo);
|
||||
return TRUE; // done
|
||||
return true; // done
|
||||
}
|
||||
|
||||
// Check to see whether any corrupt-data warnings occurred
|
||||
|
|
@ -322,10 +322,10 @@ BOOL LLImageJPEG::decode(LLImageRaw* raw_image, F32 decode_time)
|
|||
{
|
||||
// TODO: extract the warning to find out what went wrong.
|
||||
setLastError( "Unable to decode JPEG image.");
|
||||
return TRUE; // done
|
||||
return true; // done
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -344,11 +344,11 @@ void LLImageJPEG::encodeInitDestination ( j_compress_ptr cinfo )
|
|||
//
|
||||
// In typical applications, this should write the entire output buffer
|
||||
// (ignoring the current state of next_output_byte & free_in_buffer),
|
||||
// reset the pointer & count to the start of the buffer, and return TRUE
|
||||
// reset the pointer & count to the start of the buffer, and return true
|
||||
// indicating that the buffer has been dumped.
|
||||
//
|
||||
// In applications that need to be able to suspend compression due to output
|
||||
// overrun, a FALSE return indicates that the buffer cannot be emptied now.
|
||||
// overrun, a false return indicates that the buffer cannot be emptied now.
|
||||
// In this situation, the compressor will return to its caller (possibly with
|
||||
// an indication that it has not accepted all the supplied scanlines). The
|
||||
// application should resume compression after it has made more room in the
|
||||
|
|
@ -357,7 +357,7 @@ void LLImageJPEG::encodeInitDestination ( j_compress_ptr cinfo )
|
|||
//
|
||||
// When suspending, the compressor will back up to a convenient restart point
|
||||
// (typically the start of the current MCU). next_output_byte & free_in_buffer
|
||||
// indicate where the restart point will be if the current call returns FALSE.
|
||||
// indicate where the restart point will be if the current call returns false.
|
||||
// Data beyond this point will be regenerated after resumption, so do not
|
||||
// write it out when emptying the buffer externally.
|
||||
|
||||
|
|
@ -374,7 +374,7 @@ boolean LLImageJPEG::encodeEmptyOutputBuffer( j_compress_ptr cinfo )
|
|||
if (!new_buffer)
|
||||
{
|
||||
LL_ERRS() << "Out of memory in LLImageJPEG::encodeEmptyOutputBuffer( j_compress_ptr cinfo )" << LL_ENDL;
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
memcpy( new_buffer, self->mOutputBuffer, self->mOutputBufferSize ); /* Flawfinder: ignore */
|
||||
delete[] self->mOutputBuffer;
|
||||
|
|
@ -386,7 +386,7 @@ boolean LLImageJPEG::encodeEmptyOutputBuffer( j_compress_ptr cinfo )
|
|||
self->mOutputBufferSize = new_buffer_size;
|
||||
self->claimMem(new_buffer_size);
|
||||
|
||||
return TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Terminate destination --- called by jpeg_finish_compress
|
||||
|
|
@ -465,11 +465,11 @@ void LLImageJPEG::errorOutputMessage( j_common_ptr cinfo )
|
|||
std::string error = buffer ;
|
||||
LLImage::setLastError(error);
|
||||
|
||||
BOOL is_decode = (cinfo->is_decompressor != 0);
|
||||
bool is_decode = (cinfo->is_decompressor != 0);
|
||||
LL_WARNS() << "LLImageJPEG " << (is_decode ? "decode " : "encode ") << " failed: " << buffer << LL_ENDL;
|
||||
}
|
||||
|
||||
BOOL LLImageJPEG::encode( const LLImageRaw* raw_image, F32 encode_time )
|
||||
bool LLImageJPEG::encode( const LLImageRaw* raw_image, F32 encode_time )
|
||||
{
|
||||
llassert_always(raw_image);
|
||||
|
||||
|
|
@ -482,7 +482,7 @@ BOOL LLImageJPEG::encode( const LLImageRaw* raw_image, F32 encode_time )
|
|||
break;
|
||||
default:
|
||||
setLastError("Unable to encode a JPEG image that doesn't have 1 or 3 components.");
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
setSize(raw_image->getWidth(), raw_image->getHeight(), raw_image->getComponents());
|
||||
|
|
@ -531,7 +531,7 @@ BOOL LLImageJPEG::encode( const LLImageRaw* raw_image, F32 encode_time )
|
|||
mOutputBuffer = NULL;
|
||||
disclaimMem(mOutputBufferSize);
|
||||
mOutputBufferSize = 0;
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
try
|
||||
|
|
@ -576,7 +576,7 @@ BOOL LLImageJPEG::encode( const LLImageRaw* raw_image, F32 encode_time )
|
|||
break;
|
||||
default:
|
||||
setLastError("Unable to encode a JPEG image that doesn't have 1 or 3 components.");
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Now use the library's routine to set default compression parameters.
|
||||
|
|
@ -585,15 +585,15 @@ BOOL LLImageJPEG::encode( const LLImageRaw* raw_image, F32 encode_time )
|
|||
jpeg_set_defaults(&cinfo);
|
||||
|
||||
// Now you can set any non-default parameters you wish to.
|
||||
jpeg_set_quality(&cinfo, mEncodeQuality, TRUE ); // limit to baseline-JPEG values
|
||||
jpeg_set_quality(&cinfo, mEncodeQuality, true ); // limit to baseline-JPEG values
|
||||
|
||||
////////////////////////////////////////
|
||||
// Step 4: Start compressor
|
||||
//
|
||||
// TRUE ensures that we will write a complete interchange-JPEG file.
|
||||
// Pass TRUE unless you are very sure of what you're doing.
|
||||
// true ensures that we will write a complete interchange-JPEG file.
|
||||
// Pass true unless you are very sure of what you're doing.
|
||||
|
||||
jpeg_start_compress(&cinfo, TRUE);
|
||||
jpeg_start_compress(&cinfo, true);
|
||||
|
||||
////////////////////////////////////////
|
||||
// Step 5: while (scan lines remain to be written)
|
||||
|
|
@ -647,8 +647,8 @@ BOOL LLImageJPEG::encode( const LLImageRaw* raw_image, F32 encode_time )
|
|||
mOutputBuffer = NULL;
|
||||
disclaimMem(mOutputBufferSize);
|
||||
mOutputBufferSize = 0;
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,9 +51,9 @@ public:
|
|||
LLImageJPEG(S32 quality = 75);
|
||||
|
||||
/*virtual*/ std::string getExtension() { return std::string("jpg"); }
|
||||
/*virtual*/ BOOL updateData();
|
||||
/*virtual*/ BOOL decode(LLImageRaw* raw_image, F32 decode_time);
|
||||
/*virtual*/ BOOL encode(const LLImageRaw* raw_image, F32 encode_time);
|
||||
/*virtual*/ bool updateData();
|
||||
/*virtual*/ bool decode(LLImageRaw* raw_image, F32 decode_time);
|
||||
/*virtual*/ bool encode(const LLImageRaw* raw_image, F32 encode_time);
|
||||
|
||||
void setEncodeQuality( S32 q ) { mEncodeQuality = q; } // on a scale from 1 to 100
|
||||
S32 getEncodeQuality() { return mEncodeQuality; }
|
||||
|
|
@ -73,7 +73,7 @@ public:
|
|||
static void errorEmitMessage(j_common_ptr cinfo, int msg_level);
|
||||
static void errorOutputMessage(j_common_ptr cinfo);
|
||||
|
||||
static BOOL decompress(LLImageJPEG* imagep);
|
||||
static bool decompress(LLImageJPEG* imagep);
|
||||
|
||||
protected:
|
||||
U8* mOutputBuffer; // temp buffer used during encoding
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ LLImagePNG::~LLImagePNG()
|
|||
// Virtual
|
||||
// Parse PNG image information and set the appropriate
|
||||
// width, height and component (channel) information.
|
||||
BOOL LLImagePNG::updateData()
|
||||
bool LLImagePNG::updateData()
|
||||
{
|
||||
resetLastError();
|
||||
|
||||
|
|
@ -55,7 +55,7 @@ BOOL LLImagePNG::updateData()
|
|||
if (!getData() || (0 == getDataSize()))
|
||||
{
|
||||
setLastError("Uninitialized instance of LLImagePNG");
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Decode the PNG data and extract sizing information
|
||||
|
|
@ -63,25 +63,25 @@ BOOL LLImagePNG::updateData()
|
|||
if (!pngWrapper.isValidPng(getData()))
|
||||
{
|
||||
setLastError("LLImagePNG data does not have a valid PNG header!");
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
LLPngWrapper::ImageInfo infop;
|
||||
if (! pngWrapper.readPng(getData(), getDataSize(), NULL, &infop))
|
||||
{
|
||||
setLastError(pngWrapper.getErrorMessage());
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
setSize(infop.mWidth, infop.mHeight, infop.mComponents);
|
||||
|
||||
return TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Virtual
|
||||
// Decode an in-memory PNG image into the raw RGB or RGBA format
|
||||
// used within SecondLife.
|
||||
BOOL LLImagePNG::decode(LLImageRaw* raw_image, F32 decode_time)
|
||||
bool LLImagePNG::decode(LLImageRaw* raw_image, F32 decode_time)
|
||||
{
|
||||
llassert_always(raw_image);
|
||||
|
||||
|
|
@ -91,7 +91,7 @@ BOOL LLImagePNG::decode(LLImageRaw* raw_image, F32 decode_time)
|
|||
if (!getData() || (0 == getDataSize()))
|
||||
{
|
||||
setLastError("LLImagePNG trying to decode an image with no data!");
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Decode the PNG data into the raw image
|
||||
|
|
@ -99,21 +99,21 @@ BOOL LLImagePNG::decode(LLImageRaw* raw_image, F32 decode_time)
|
|||
if (!pngWrapper.isValidPng(getData()))
|
||||
{
|
||||
setLastError("LLImagePNG data does not have a valid PNG header!");
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (! pngWrapper.readPng(getData(), getDataSize(), raw_image))
|
||||
{
|
||||
setLastError(pngWrapper.getErrorMessage());
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Virtual
|
||||
// Encode the in memory RGB image into PNG format.
|
||||
BOOL LLImagePNG::encode(const LLImageRaw* raw_image, F32 encode_time)
|
||||
bool LLImagePNG::encode(const LLImageRaw* raw_image, F32 encode_time)
|
||||
{
|
||||
llassert_always(raw_image);
|
||||
|
||||
|
|
@ -133,7 +133,7 @@ BOOL LLImagePNG::encode(const LLImageRaw* raw_image, F32 encode_time)
|
|||
{
|
||||
setLastError(pngWrapper.getErrorMessage());
|
||||
delete[] tmpWriteBuffer;
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Resize internal buffer and copy from temp
|
||||
|
|
@ -143,6 +143,6 @@ BOOL LLImagePNG::encode(const LLImageRaw* raw_image, F32 encode_time)
|
|||
|
||||
delete[] tmpWriteBuffer;
|
||||
|
||||
return TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -38,9 +38,9 @@ public:
|
|||
LLImagePNG();
|
||||
|
||||
/*virtual*/ std::string getExtension() { return std::string("png"); }
|
||||
/*virtual*/ BOOL updateData();
|
||||
/*virtual*/ BOOL decode(LLImageRaw* raw_image, F32 decode_time);
|
||||
/*virtual*/ BOOL encode(const LLImageRaw* raw_image, F32 encode_time);
|
||||
/*virtual*/ bool updateData();
|
||||
/*virtual*/ bool decode(LLImageRaw* raw_image, F32 decode_time);
|
||||
/*virtual*/ bool encode(const LLImageRaw* raw_image, F32 encode_time);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ LLImageTGA::LLImageTGA()
|
|||
mColorMapStart( 0 ),
|
||||
mColorMapLength( 0 ),
|
||||
mColorMapBytesPerEntry( 0 ),
|
||||
mIs15Bit( FALSE ),
|
||||
mIs15Bit( false ),
|
||||
|
||||
mAttributeBits(0),
|
||||
mColorMapDepth(0),
|
||||
|
|
@ -94,7 +94,7 @@ LLImageTGA::LLImageTGA(const std::string& file_name)
|
|||
mColorMapStart( 0 ),
|
||||
mColorMapLength( 0 ),
|
||||
mColorMapBytesPerEntry( 0 ),
|
||||
mIs15Bit( FALSE )
|
||||
mIs15Bit( false )
|
||||
{
|
||||
loadFile(file_name);
|
||||
}
|
||||
|
|
@ -104,7 +104,7 @@ LLImageTGA::~LLImageTGA()
|
|||
delete [] mColorMap;
|
||||
}
|
||||
|
||||
BOOL LLImageTGA::updateData()
|
||||
bool LLImageTGA::updateData()
|
||||
{
|
||||
resetLastError();
|
||||
|
||||
|
|
@ -112,7 +112,7 @@ BOOL LLImageTGA::updateData()
|
|||
if (!getData() || (0 == getDataSize()))
|
||||
{
|
||||
setLastError("LLImageTGA uninitialized");
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Pull image information from the header...
|
||||
|
|
@ -185,13 +185,13 @@ BOOL LLImageTGA::updateData()
|
|||
case 0:
|
||||
// No image data included in file
|
||||
setLastError("Unable to load file. TGA file contains no image data.");
|
||||
return FALSE;
|
||||
return false;
|
||||
case 1:
|
||||
// Colormapped uncompressed
|
||||
if( 8 != mPixelSize )
|
||||
{
|
||||
setLastError("Unable to load file. Colormapped images must have 8 bits per pixel.");
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
|
|
@ -202,7 +202,7 @@ BOOL LLImageTGA::updateData()
|
|||
if( 8 != mPixelSize )
|
||||
{
|
||||
setLastError("Unable to load file. Monochrome images must have 8 bits per pixel.");
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case 9:
|
||||
|
|
@ -216,12 +216,12 @@ BOOL LLImageTGA::updateData()
|
|||
if( 8 != mPixelSize )
|
||||
{
|
||||
setLastError("Unable to load file. Monochrome images must have 8 bits per pixel.");
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
setLastError("Unable to load file. Unrecoginzed TGA image type.");
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
// discard the ID field, if any
|
||||
|
|
@ -266,8 +266,8 @@ BOOL LLImageTGA::updateData()
|
|||
mColorMap = new U8[ color_map_bytes ];
|
||||
if (!mColorMap)
|
||||
{
|
||||
LL_ERRS() << "Out of Memory in BOOL LLImageTGA::updateData()" << LL_ENDL;
|
||||
return FALSE;
|
||||
LL_ERRS() << "Out of Memory in bool LLImageTGA::updateData()" << LL_ENDL;
|
||||
return false;
|
||||
}
|
||||
memcpy( mColorMap, getData() + mDataOffset, color_map_bytes ); /* Flawfinder: ignore */
|
||||
}
|
||||
|
|
@ -302,28 +302,28 @@ BOOL LLImageTGA::updateData()
|
|||
// if( mAttributeBits != 8 )
|
||||
// {
|
||||
// setLastError("Unable to load file. 32 bit TGA image does not have 8 bits of alpha.");
|
||||
// return FALSE;
|
||||
// return false;
|
||||
// }
|
||||
mAttributeBits = 8;
|
||||
break;
|
||||
case 15:
|
||||
case 16:
|
||||
components = 3;
|
||||
mIs15Bit = TRUE; // 16th bit is used for Targa hardware interupts and is ignored.
|
||||
mIs15Bit = true; // 16th bit is used for Targa hardware interupts and is ignored.
|
||||
break;
|
||||
case 8:
|
||||
components = 1;
|
||||
break;
|
||||
default:
|
||||
setLastError("Unable to load file. Unknown pixel size.");
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
setSize(width, height, components);
|
||||
|
||||
return TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
BOOL LLImageTGA::decode(LLImageRaw* raw_image, F32 decode_time)
|
||||
bool LLImageTGA::decode(LLImageRaw* raw_image, F32 decode_time)
|
||||
{
|
||||
llassert_always(raw_image);
|
||||
|
||||
|
|
@ -331,7 +331,7 @@ BOOL LLImageTGA::decode(LLImageRaw* raw_image, F32 decode_time)
|
|||
if (!getData() || (0 == getDataSize()))
|
||||
{
|
||||
setLastError("LLImageTGA trying to decode an image with no data!");
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Copy everything after the header.
|
||||
|
|
@ -343,18 +343,18 @@ BOOL LLImageTGA::decode(LLImageRaw* raw_image, F32 decode_time)
|
|||
(getComponents() != 4) )
|
||||
{
|
||||
setLastError("TGA images with a number of components other than 1, 3, and 4 are not supported.");
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if( mOriginRightBit )
|
||||
{
|
||||
setLastError("TGA images with origin on right side are not supported.");
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
BOOL flipped = (mOriginTopBit != 0);
|
||||
BOOL rle_compressed = ((mImageType & 0x08) != 0);
|
||||
bool flipped = (mOriginTopBit != 0);
|
||||
bool rle_compressed = ((mImageType & 0x08) != 0);
|
||||
|
||||
if( mColorMap )
|
||||
{
|
||||
|
|
@ -366,10 +366,10 @@ BOOL LLImageTGA::decode(LLImageRaw* raw_image, F32 decode_time)
|
|||
}
|
||||
}
|
||||
|
||||
BOOL LLImageTGA::decodeTruecolor( LLImageRaw* raw_image, BOOL rle, BOOL flipped )
|
||||
bool LLImageTGA::decodeTruecolor( LLImageRaw* raw_image, bool rle, bool flipped )
|
||||
{
|
||||
BOOL success = FALSE;
|
||||
BOOL alpha_opaque = FALSE;
|
||||
bool success = false;
|
||||
bool alpha_opaque = false;
|
||||
if( rle )
|
||||
{
|
||||
|
||||
|
|
@ -404,7 +404,7 @@ BOOL LLImageTGA::decodeTruecolor( LLImageRaw* raw_image, BOOL rle, BOOL flipped
|
|||
}
|
||||
else
|
||||
{
|
||||
BOOL alpha_opaque;
|
||||
bool alpha_opaque;
|
||||
success = decodeTruecolorNonRle( raw_image, alpha_opaque );
|
||||
if (alpha_opaque && raw_image->getComponents() == 4)
|
||||
{
|
||||
|
|
@ -430,9 +430,9 @@ BOOL LLImageTGA::decodeTruecolor( LLImageRaw* raw_image, BOOL rle, BOOL flipped
|
|||
}
|
||||
|
||||
|
||||
BOOL LLImageTGA::decodeTruecolorNonRle( LLImageRaw* raw_image, BOOL &alpha_opaque )
|
||||
bool LLImageTGA::decodeTruecolorNonRle( LLImageRaw* raw_image, bool &alpha_opaque )
|
||||
{
|
||||
alpha_opaque = TRUE;
|
||||
alpha_opaque = true;
|
||||
|
||||
// Origin is the bottom left
|
||||
U8* dst = raw_image->getData();
|
||||
|
|
@ -442,7 +442,7 @@ BOOL LLImageTGA::decodeTruecolorNonRle( LLImageRaw* raw_image, BOOL &alpha_opaqu
|
|||
|
||||
if (pixels * (mIs15Bit ? 2 : getComponents()) > getDataSize() - mDataOffset)
|
||||
{ //here we have situation when data size in src less than actually needed
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (getComponents() == 4)
|
||||
|
|
@ -456,7 +456,7 @@ BOOL LLImageTGA::decodeTruecolorNonRle( LLImageRaw* raw_image, BOOL &alpha_opaqu
|
|||
dst[3] = src[3]; // Alpha
|
||||
if (dst[3] != 255)
|
||||
{
|
||||
alpha_opaque = FALSE;
|
||||
alpha_opaque = false;
|
||||
}
|
||||
dst += 4;
|
||||
src += 4;
|
||||
|
|
@ -490,7 +490,7 @@ BOOL LLImageTGA::decodeTruecolorNonRle( LLImageRaw* raw_image, BOOL &alpha_opaqu
|
|||
memcpy(dst, src, pixels); /* Flawfinder: ignore */
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
void LLImageTGA::decodeColorMapPixel8( U8* dst, const U8* src )
|
||||
|
|
@ -523,14 +523,14 @@ void LLImageTGA::decodeColorMapPixel32( U8* dst, const U8* src )
|
|||
}
|
||||
|
||||
|
||||
BOOL LLImageTGA::decodeColorMap( LLImageRaw* raw_image, BOOL rle, BOOL flipped )
|
||||
bool LLImageTGA::decodeColorMap( LLImageRaw* raw_image, bool rle, bool flipped )
|
||||
{
|
||||
// If flipped, origin is the top left. Need to reverse the order of the rows.
|
||||
// Otherwise the origin is the bottom left.
|
||||
|
||||
if( 8 != mPixelSize )
|
||||
{
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
U8* src = getData() + mDataOffset;
|
||||
|
|
@ -544,7 +544,7 @@ BOOL LLImageTGA::decodeColorMap( LLImageRaw* raw_image, BOOL rle, BOOL flipped )
|
|||
case 2: pixel_decoder = &LLImageTGA::decodeColorMapPixel15; break;
|
||||
case 3: pixel_decoder = &LLImageTGA::decodeColorMapPixel24; break;
|
||||
case 4: pixel_decoder = &LLImageTGA::decodeColorMapPixel32; break;
|
||||
default: llassert(0); return FALSE;
|
||||
default: llassert(0); return false;
|
||||
}
|
||||
|
||||
if( rle )
|
||||
|
|
@ -613,12 +613,12 @@ BOOL LLImageTGA::decodeColorMap( LLImageRaw* raw_image, BOOL rle, BOOL flipped )
|
|||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
BOOL LLImageTGA::encode(const LLImageRaw* raw_image, F32 encode_time)
|
||||
bool LLImageTGA::encode(const LLImageRaw* raw_image, F32 encode_time)
|
||||
{
|
||||
llassert_always(raw_image);
|
||||
|
||||
|
|
@ -642,7 +642,7 @@ BOOL LLImageTGA::encode(const LLImageRaw* raw_image, F32 encode_time)
|
|||
mImageType = 2;
|
||||
break;
|
||||
default:
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Color map stuff (unsupported)
|
||||
|
|
@ -678,7 +678,7 @@ BOOL LLImageTGA::encode(const LLImageRaw* raw_image, F32 encode_time)
|
|||
bytes_per_pixel = 4;
|
||||
break;
|
||||
default:
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
mPixelSize = U8(bytes_per_pixel * 8); // 8, 16, 24, 32 bits per pixel
|
||||
|
||||
|
|
@ -765,13 +765,13 @@ BOOL LLImageTGA::encode(const LLImageRaw* raw_image, F32 encode_time)
|
|||
break;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
BOOL LLImageTGA::decodeTruecolorRle32( LLImageRaw* raw_image, BOOL &alpha_opaque )
|
||||
bool LLImageTGA::decodeTruecolorRle32( LLImageRaw* raw_image, bool &alpha_opaque )
|
||||
{
|
||||
llassert( getComponents() == 4 );
|
||||
alpha_opaque = TRUE;
|
||||
alpha_opaque = true;
|
||||
|
||||
U8* dst = raw_image->getData();
|
||||
U32* dst_pixels = (U32*) dst;
|
||||
|
|
@ -788,7 +788,7 @@ BOOL LLImageTGA::decodeTruecolorRle32( LLImageRaw* raw_image, BOOL &alpha_opaque
|
|||
// Read RLE block header
|
||||
|
||||
if (src >= last_src)
|
||||
return FALSE;
|
||||
return false;
|
||||
|
||||
U8 block_header_byte = *src;
|
||||
src++;
|
||||
|
|
@ -799,7 +799,7 @@ BOOL LLImageTGA::decodeTruecolorRle32( LLImageRaw* raw_image, BOOL &alpha_opaque
|
|||
// Encoded (duplicate-pixel) block
|
||||
|
||||
if (src + 3 >= last_src)
|
||||
return FALSE;
|
||||
return false;
|
||||
|
||||
rgba_byte_p[0] = src[2];
|
||||
rgba_byte_p[1] = src[1];
|
||||
|
|
@ -807,7 +807,7 @@ BOOL LLImageTGA::decodeTruecolorRle32( LLImageRaw* raw_image, BOOL &alpha_opaque
|
|||
rgba_byte_p[3] = src[3];
|
||||
if (rgba_byte_p[3] != 255)
|
||||
{
|
||||
alpha_opaque = FALSE;
|
||||
alpha_opaque = false;
|
||||
}
|
||||
|
||||
src += 4;
|
||||
|
|
@ -826,7 +826,7 @@ BOOL LLImageTGA::decodeTruecolorRle32( LLImageRaw* raw_image, BOOL &alpha_opaque
|
|||
do
|
||||
{
|
||||
if (src + 3 >= last_src)
|
||||
return FALSE;
|
||||
return false;
|
||||
|
||||
((U8*)dst_pixels)[0] = src[2];
|
||||
((U8*)dst_pixels)[1] = src[1];
|
||||
|
|
@ -834,7 +834,7 @@ BOOL LLImageTGA::decodeTruecolorRle32( LLImageRaw* raw_image, BOOL &alpha_opaque
|
|||
((U8*)dst_pixels)[3] = src[3];
|
||||
if (src[3] != 255)
|
||||
{
|
||||
alpha_opaque = FALSE;
|
||||
alpha_opaque = false;
|
||||
}
|
||||
src += 4;
|
||||
dst_pixels++;
|
||||
|
|
@ -844,10 +844,10 @@ BOOL LLImageTGA::decodeTruecolorRle32( LLImageRaw* raw_image, BOOL &alpha_opaque
|
|||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
BOOL LLImageTGA::decodeTruecolorRle15( LLImageRaw* raw_image )
|
||||
bool LLImageTGA::decodeTruecolorRle15( LLImageRaw* raw_image )
|
||||
{
|
||||
llassert( getComponents() == 3 );
|
||||
llassert( mIs15Bit );
|
||||
|
|
@ -863,7 +863,7 @@ BOOL LLImageTGA::decodeTruecolorRle15( LLImageRaw* raw_image )
|
|||
// Read RLE block header
|
||||
|
||||
if (src >= last_src)
|
||||
return FALSE;
|
||||
return false;
|
||||
|
||||
U8 block_header_byte = *src;
|
||||
src++;
|
||||
|
|
@ -875,7 +875,7 @@ BOOL LLImageTGA::decodeTruecolorRle15( LLImageRaw* raw_image )
|
|||
do
|
||||
{
|
||||
if (src + 2 >= last_src)
|
||||
return FALSE;
|
||||
return false;
|
||||
|
||||
decodeTruecolorPixel15( dst, src ); // slow
|
||||
dst += 3;
|
||||
|
|
@ -890,7 +890,7 @@ BOOL LLImageTGA::decodeTruecolorRle15( LLImageRaw* raw_image )
|
|||
do
|
||||
{
|
||||
if (src + 2 >= last_src)
|
||||
return FALSE;
|
||||
return false;
|
||||
|
||||
decodeTruecolorPixel15( dst, src );
|
||||
dst += 3;
|
||||
|
|
@ -901,12 +901,12 @@ BOOL LLImageTGA::decodeTruecolorRle15( LLImageRaw* raw_image )
|
|||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
BOOL LLImageTGA::decodeTruecolorRle24( LLImageRaw* raw_image )
|
||||
bool LLImageTGA::decodeTruecolorRle24( LLImageRaw* raw_image )
|
||||
{
|
||||
llassert( getComponents() == 3 );
|
||||
|
||||
|
|
@ -921,7 +921,7 @@ BOOL LLImageTGA::decodeTruecolorRle24( LLImageRaw* raw_image )
|
|||
// Read RLE block header
|
||||
|
||||
if (src >= last_src)
|
||||
return FALSE;
|
||||
return false;
|
||||
|
||||
U8 block_header_byte = *src;
|
||||
src++;
|
||||
|
|
@ -933,7 +933,7 @@ BOOL LLImageTGA::decodeTruecolorRle24( LLImageRaw* raw_image )
|
|||
do
|
||||
{
|
||||
if (src + 2 >= last_src)
|
||||
return FALSE;
|
||||
return false;
|
||||
dst[0] = src[2];
|
||||
dst[1] = src[1];
|
||||
dst[2] = src[0];
|
||||
|
|
@ -949,7 +949,7 @@ BOOL LLImageTGA::decodeTruecolorRle24( LLImageRaw* raw_image )
|
|||
do
|
||||
{
|
||||
if (src + 2 >= last_src)
|
||||
return FALSE;
|
||||
return false;
|
||||
|
||||
dst[0] = src[2];
|
||||
dst[1] = src[1];
|
||||
|
|
@ -962,11 +962,11 @@ BOOL LLImageTGA::decodeTruecolorRle24( LLImageRaw* raw_image )
|
|||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
BOOL LLImageTGA::decodeTruecolorRle8( LLImageRaw* raw_image )
|
||||
bool LLImageTGA::decodeTruecolorRle8( LLImageRaw* raw_image )
|
||||
{
|
||||
llassert( getComponents() == 1 );
|
||||
|
||||
|
|
@ -981,7 +981,7 @@ BOOL LLImageTGA::decodeTruecolorRle8( LLImageRaw* raw_image )
|
|||
// Read RLE block header
|
||||
|
||||
if (src >= last_src)
|
||||
return FALSE;
|
||||
return false;
|
||||
|
||||
U8 block_header_byte = *src;
|
||||
src++;
|
||||
|
|
@ -990,7 +990,7 @@ BOOL LLImageTGA::decodeTruecolorRle8( LLImageRaw* raw_image )
|
|||
if( block_header_byte & 0x80 )
|
||||
{
|
||||
if (src >= last_src)
|
||||
return FALSE;
|
||||
return false;
|
||||
|
||||
// Encoded (duplicate-pixel) block
|
||||
memset( dst, *src, block_pixel_count );
|
||||
|
|
@ -1003,7 +1003,7 @@ BOOL LLImageTGA::decodeTruecolorRle8( LLImageRaw* raw_image )
|
|||
do
|
||||
{
|
||||
if (src >= last_src)
|
||||
return FALSE;
|
||||
return false;
|
||||
|
||||
*dst = *src;
|
||||
dst++;
|
||||
|
|
@ -1014,13 +1014,13 @@ BOOL LLImageTGA::decodeTruecolorRle8( LLImageRaw* raw_image )
|
|||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// Decoded and process the image for use in avatar gradient masks.
|
||||
// Processing happens during the decode for speed.
|
||||
BOOL LLImageTGA::decodeAndProcess( LLImageRaw* raw_image, F32 domain, F32 weight )
|
||||
bool LLImageTGA::decodeAndProcess( LLImageRaw* raw_image, F32 domain, F32 weight )
|
||||
{
|
||||
llassert_always(raw_image);
|
||||
|
||||
|
|
@ -1043,14 +1043,14 @@ BOOL LLImageTGA::decodeAndProcess( LLImageRaw* raw_image, F32 domain, F32 weight
|
|||
if (!getData() || (0 == getDataSize()))
|
||||
{
|
||||
setLastError("LLImageTGA trying to decode an image with no data!");
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Only works for unflipped monochrome RLE images
|
||||
if( (getComponents() != 1) || (mImageType != 11) || mOriginTopBit || mOriginRightBit )
|
||||
{
|
||||
LL_ERRS() << "LLImageTGA trying to alpha-gradient process an image that's not a standard RLE, one component image" << LL_ENDL;
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
raw_image->resize(getWidth(), getHeight(), getComponents());
|
||||
|
|
@ -1136,7 +1136,7 @@ BOOL LLImageTGA::decodeAndProcess( LLImageRaw* raw_image, F32 domain, F32 weight
|
|||
}
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Reads a .tga file and creates an LLImageTGA with its data.
|
||||
|
|
|
|||
|
|
@ -41,25 +41,25 @@ public:
|
|||
LLImageTGA(const std::string& file_name);
|
||||
|
||||
/*virtual*/ std::string getExtension() { return std::string("tga"); }
|
||||
/*virtual*/ BOOL updateData();
|
||||
/*virtual*/ BOOL decode(LLImageRaw* raw_image, F32 decode_time=0.0);
|
||||
/*virtual*/ BOOL encode(const LLImageRaw* raw_image, F32 encode_time=0.0);
|
||||
/*virtual*/ bool updateData();
|
||||
/*virtual*/ bool decode(LLImageRaw* raw_image, F32 decode_time=0.0);
|
||||
/*virtual*/ bool encode(const LLImageRaw* raw_image, F32 encode_time=0.0);
|
||||
|
||||
BOOL decodeAndProcess(LLImageRaw* raw_image, F32 domain, F32 weight);
|
||||
bool decodeAndProcess(LLImageRaw* raw_image, F32 domain, F32 weight);
|
||||
|
||||
private:
|
||||
BOOL decodeTruecolor( LLImageRaw* raw_image, BOOL rle, BOOL flipped );
|
||||
bool decodeTruecolor( LLImageRaw* raw_image, bool rle, bool flipped );
|
||||
|
||||
BOOL decodeTruecolorRle8( LLImageRaw* raw_image );
|
||||
BOOL decodeTruecolorRle15( LLImageRaw* raw_image );
|
||||
BOOL decodeTruecolorRle24( LLImageRaw* raw_image );
|
||||
BOOL decodeTruecolorRle32( LLImageRaw* raw_image, BOOL &alpha_opaque );
|
||||
bool decodeTruecolorRle8( LLImageRaw* raw_image );
|
||||
bool decodeTruecolorRle15( LLImageRaw* raw_image );
|
||||
bool decodeTruecolorRle24( LLImageRaw* raw_image );
|
||||
bool decodeTruecolorRle32( LLImageRaw* raw_image, bool &alpha_opaque );
|
||||
|
||||
void decodeTruecolorPixel15( U8* dst, const U8* src );
|
||||
|
||||
BOOL decodeTruecolorNonRle( LLImageRaw* raw_image, BOOL &alpha_opaque );
|
||||
bool decodeTruecolorNonRle( LLImageRaw* raw_image, bool &alpha_opaque );
|
||||
|
||||
BOOL decodeColorMap( LLImageRaw* raw_image, BOOL rle, BOOL flipped );
|
||||
bool decodeColorMap( LLImageRaw* raw_image, bool rle, bool flipped );
|
||||
|
||||
void decodeColorMapPixel8(U8* dst, const U8* src);
|
||||
void decodeColorMapPixel15(U8* dst, const U8* src);
|
||||
|
|
@ -100,7 +100,7 @@ private:
|
|||
S32 mColorMapLength;
|
||||
S32 mColorMapBytesPerEntry;
|
||||
|
||||
BOOL mIs15Bit;
|
||||
bool mIs15Bit;
|
||||
|
||||
static const U8 s5to8bits[32];
|
||||
};
|
||||
|
|
|
|||
|
|
@ -31,6 +31,16 @@
|
|||
#include "llimage.h"
|
||||
#include "llpngwrapper.h"
|
||||
|
||||
#include "llexception.h"
|
||||
|
||||
namespace {
|
||||
// Failure to load an image shouldn't crash the whole viewer.
|
||||
struct PngError: public LLContinueError
|
||||
{
|
||||
PngError(png_const_charp msg): LLContinueError(msg) {}
|
||||
};
|
||||
} // anonymous namespace
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// LLPngWrapper
|
||||
// ---------------------------------------------------------------------------
|
||||
|
|
@ -75,11 +85,10 @@ BOOL LLPngWrapper::isValidPng(U8* src)
|
|||
}
|
||||
|
||||
// Called by the libpng library when a fatal encoding or decoding error
|
||||
// occurs. We simply throw the error message and let our try/catch
|
||||
// block clean up.
|
||||
// occurs. We throw PngError and let our try/catch block clean up.
|
||||
void LLPngWrapper::errorHandler(png_structp png_ptr, png_const_charp msg)
|
||||
{
|
||||
throw msg;
|
||||
LLTHROW(PngError(msg));
|
||||
}
|
||||
|
||||
// Called by the libpng library when reading (decoding) the PNG file. We
|
||||
|
|
@ -129,7 +138,7 @@ BOOL LLPngWrapper::readPng(U8* src, S32 dataSize, LLImageRaw* rawImage, ImageInf
|
|||
this, &errorHandler, NULL);
|
||||
if (mReadPngPtr == NULL)
|
||||
{
|
||||
throw "Problem creating png read structure";
|
||||
LLTHROW(PngError("Problem creating png read structure"));
|
||||
}
|
||||
|
||||
// Allocate/initialize the memory for image information.
|
||||
|
|
@ -187,9 +196,9 @@ BOOL LLPngWrapper::readPng(U8* src, S32 dataSize, LLImageRaw* rawImage, ImageInf
|
|||
|
||||
mFinalSize = dataPtr.mOffset;
|
||||
}
|
||||
catch (png_const_charp msg)
|
||||
catch (const PngError& msg)
|
||||
{
|
||||
mErrorMessage = msg;
|
||||
mErrorMessage = msg.what();
|
||||
releaseResources();
|
||||
return (FALSE);
|
||||
}
|
||||
|
|
@ -288,14 +297,14 @@ BOOL LLPngWrapper::writePng(const LLImageRaw* rawImage, U8* dest)
|
|||
|
||||
if (mColorType == -1)
|
||||
{
|
||||
throw "Unsupported image: unexpected number of channels";
|
||||
LLTHROW(PngError("Unsupported image: unexpected number of channels"));
|
||||
}
|
||||
|
||||
mWritePngPtr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
|
||||
NULL, &errorHandler, NULL);
|
||||
if (!mWritePngPtr)
|
||||
{
|
||||
throw "Problem creating png write structure";
|
||||
LLTHROW(PngError("Problem creating png write structure"));
|
||||
}
|
||||
|
||||
mWriteInfoPtr = png_create_info_struct(mWritePngPtr);
|
||||
|
|
@ -339,9 +348,9 @@ BOOL LLPngWrapper::writePng(const LLImageRaw* rawImage, U8* dest)
|
|||
png_write_end(mWritePngPtr, mWriteInfoPtr);
|
||||
mFinalSize = dataPtr.mOffset;
|
||||
}
|
||||
catch (png_const_charp msg)
|
||||
catch (const PngError& msg)
|
||||
{
|
||||
mErrorMessage = msg;
|
||||
mErrorMessage = msg.what();
|
||||
releaseResources();
|
||||
return (FALSE);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,23 +33,16 @@
|
|||
#include "lltimer.h"
|
||||
//#include "llmemory.h"
|
||||
|
||||
const char* fallbackEngineInfoLLImageJ2CImpl()
|
||||
{
|
||||
static std::string version_string =
|
||||
std::string("OpenJPEG: " OPENJPEG_VERSION ", Runtime: ")
|
||||
+ opj_version();
|
||||
return version_string.c_str();
|
||||
}
|
||||
|
||||
// Factory function: see declaration in llimagej2c.cpp
|
||||
LLImageJ2CImpl* fallbackCreateLLImageJ2CImpl()
|
||||
{
|
||||
return new LLImageJ2COJ();
|
||||
}
|
||||
|
||||
void fallbackDestroyLLImageJ2CImpl(LLImageJ2CImpl* impl)
|
||||
std::string LLImageJ2COJ::getEngineInfo() const
|
||||
{
|
||||
delete impl;
|
||||
impl = NULL;
|
||||
return std::string("OpenJPEG: " OPENJPEG_VERSION ", Runtime: ")
|
||||
+ opj_version();
|
||||
}
|
||||
|
||||
// Return string from message, eliminating final \n if present
|
||||
|
|
@ -107,19 +100,19 @@ LLImageJ2COJ::~LLImageJ2COJ()
|
|||
{
|
||||
}
|
||||
|
||||
BOOL LLImageJ2COJ::initDecode(LLImageJ2C &base, LLImageRaw &raw_image, int discard_level, int* region)
|
||||
bool LLImageJ2COJ::initDecode(LLImageJ2C &base, LLImageRaw &raw_image, int discard_level, int* region)
|
||||
{
|
||||
// No specific implementation for this method in the OpenJpeg case
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
BOOL LLImageJ2COJ::initEncode(LLImageJ2C &base, LLImageRaw &raw_image, int blocks_size, int precincts_size, int levels)
|
||||
bool LLImageJ2COJ::initEncode(LLImageJ2C &base, LLImageRaw &raw_image, int blocks_size, int precincts_size, int levels)
|
||||
{
|
||||
// No specific implementation for this method in the OpenJpeg case
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
BOOL LLImageJ2COJ::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decode_time, S32 first_channel, S32 max_channel_count)
|
||||
bool LLImageJ2COJ::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decode_time, S32 first_channel, S32 max_channel_count)
|
||||
{
|
||||
//
|
||||
// FIXME: Get the comment field out of the texture
|
||||
|
|
@ -186,7 +179,7 @@ BOOL LLImageJ2COJ::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decod
|
|||
opj_image_destroy(image);
|
||||
}
|
||||
|
||||
return TRUE; // done
|
||||
return true; // done
|
||||
}
|
||||
|
||||
// sometimes we get bad data out of the cache - check to see if the decode succeeded
|
||||
|
|
@ -196,8 +189,8 @@ BOOL LLImageJ2COJ::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decod
|
|||
{
|
||||
// if we didn't get the discard level we're expecting, fail
|
||||
opj_image_destroy(image);
|
||||
base.mDecoding = FALSE;
|
||||
return TRUE;
|
||||
base.mDecoding = false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -209,7 +202,7 @@ BOOL LLImageJ2COJ::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decod
|
|||
opj_image_destroy(image);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Copy image data into our raw image format (instead of the separate channel format
|
||||
|
|
@ -256,18 +249,18 @@ BOOL LLImageJ2COJ::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decod
|
|||
LL_DEBUGS("Texture") << "ERROR -> decodeImpl: failed to decode image! (NULL comp data - OpenJPEG bug)" << LL_ENDL;
|
||||
opj_image_destroy(image);
|
||||
|
||||
return TRUE; // done
|
||||
return true; // done
|
||||
}
|
||||
}
|
||||
|
||||
/* free image data structure */
|
||||
opj_image_destroy(image);
|
||||
|
||||
return TRUE; // done
|
||||
return true; // done
|
||||
}
|
||||
|
||||
|
||||
BOOL LLImageJ2COJ::encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, const char* comment_text, F32 encode_time, BOOL reversible)
|
||||
bool LLImageJ2COJ::encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, const char* comment_text, F32 encode_time, bool reversible)
|
||||
{
|
||||
const S32 MAX_COMPS = 5;
|
||||
opj_cparameters_t parameters; /* compression parameters */
|
||||
|
|
@ -388,7 +381,7 @@ BOOL LLImageJ2COJ::encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, con
|
|||
{
|
||||
opj_cio_close(cio);
|
||||
LL_DEBUGS("Texture") << "Failed to encode image." << LL_ENDL;
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
codestream_length = cio_tell(cio);
|
||||
|
||||
|
|
@ -407,10 +400,10 @@ BOOL LLImageJ2COJ::encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, con
|
|||
|
||||
/* free image data */
|
||||
opj_image_destroy(image);
|
||||
return TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
BOOL LLImageJ2COJ::getMetadata(LLImageJ2C &base)
|
||||
bool LLImageJ2COJ::getMetadata(LLImageJ2C &base)
|
||||
{
|
||||
//
|
||||
// FIXME: We get metadata by decoding the ENTIRE image.
|
||||
|
|
@ -473,7 +466,7 @@ BOOL LLImageJ2COJ::getMetadata(LLImageJ2C &base)
|
|||
if(!image)
|
||||
{
|
||||
LL_WARNS() << "ERROR -> getMetadata: failed to decode image!" << LL_ENDL;
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Copy image data into our raw image format (instead of the separate channel format
|
||||
|
|
@ -487,5 +480,5 @@ BOOL LLImageJ2COJ::getMetadata(LLImageJ2C &base)
|
|||
|
||||
/* free image data structure */
|
||||
opj_image_destroy(image);
|
||||
return TRUE;
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,12 +35,13 @@ public:
|
|||
LLImageJ2COJ();
|
||||
virtual ~LLImageJ2COJ();
|
||||
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);
|
||||
/*virtual*/ BOOL initDecode(LLImageJ2C &base, LLImageRaw &raw_image, int discard_level = -1, int* region = NULL);
|
||||
/*virtual*/ BOOL initEncode(LLImageJ2C &base, LLImageRaw &raw_image, int blocks_size = -1, int precincts_size = -1, int levels = 0);
|
||||
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);
|
||||
virtual bool initDecode(LLImageJ2C &base, LLImageRaw &raw_image, int discard_level = -1, int* region = NULL);
|
||||
virtual bool initEncode(LLImageJ2C &base, LLImageRaw &raw_image, int blocks_size = -1, int precincts_size = -1, int levels = 0);
|
||||
virtual std::string getEngineInfo() const;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
/**
|
||||
/**
|
||||
* @file llimagej2ckdu.cpp
|
||||
* @brief This is an implementation of JPEG2000 encode/decode using Kakadu
|
||||
*
|
||||
|
|
@ -31,9 +31,66 @@
|
|||
#include "llpointer.h"
|
||||
#include "llmath.h"
|
||||
#include "llkdumem.h"
|
||||
#include "stringize.h"
|
||||
|
||||
#include "kdu_block_coding.h"
|
||||
|
||||
#include "llexception.h"
|
||||
#include <boost/exception/diagnostic_information.hpp>
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
|
||||
namespace {
|
||||
// Failure to load an image shouldn't crash the whole viewer.
|
||||
struct KDUError: public LLContinueError
|
||||
{
|
||||
KDUError(const std::string& msg): LLContinueError(msg) {}
|
||||
};
|
||||
|
||||
// KDU defines int error codes as hex values, so we should log them in hex
|
||||
// so we can grep KDU headers for the hex. However those hex values
|
||||
// generally "happen" to encode big-endian multibyte character sequences,
|
||||
// e.g. KDU_ERROR_EXCEPTION is 0x6b647545: 'kduE'
|
||||
// But beware because KDU_NULL_EXCEPTION is simply 0 -- which doesn't
|
||||
// preclude somebody from throwing it.
|
||||
std::string report_kdu_exception(kdu_exception mb)
|
||||
{
|
||||
std::ostringstream out;
|
||||
// always report mb in hex
|
||||
out << "kdu_exception " << std::hex << mb;
|
||||
|
||||
// Also display as many chars as are encoded in the kdu_exception
|
||||
// value. Make a char array; reserve 1 extra byte for nul terminator.
|
||||
char bytes[sizeof(kdu_exception) + 1];
|
||||
// Back up through 'bytes'
|
||||
char *bptr = bytes + sizeof(bytes);
|
||||
*(--bptr) = '\0';
|
||||
while (mb)
|
||||
{
|
||||
// store low-order byte of mb in next-left char
|
||||
*(--bptr) = char(mb & 0xFF);
|
||||
// then shift mb right by one byte
|
||||
mb >>= 8;
|
||||
}
|
||||
// did that produce any characters?
|
||||
if (*bptr)
|
||||
{
|
||||
out << " (" << bptr << ')';
|
||||
}
|
||||
|
||||
return out.str();
|
||||
}
|
||||
} // anonymous namespace
|
||||
|
||||
// stream kdu_dims to std::ostream
|
||||
// Turns out this must NOT be in the anonymous namespace!
|
||||
inline
|
||||
std::ostream& operator<<(std::ostream& out, const kdu_dims& dims)
|
||||
{
|
||||
return out << "(" << dims.pos.x << "," << dims.pos.y << "),"
|
||||
"[" << dims.size.x << "x" << dims.size.y << "]";
|
||||
}
|
||||
|
||||
class kdc_flow_control {
|
||||
|
||||
public:
|
||||
|
|
@ -72,37 +129,15 @@ private:
|
|||
//
|
||||
void set_default_colour_weights(kdu_params *siz);
|
||||
|
||||
const char* engineInfoLLImageJ2CKDU()
|
||||
{
|
||||
static std::string version = llformat("KDU %s", KDU_CORE_VERSION);
|
||||
return version.c_str();
|
||||
}
|
||||
|
||||
LLImageJ2CKDU* createLLImageJ2CKDU()
|
||||
{
|
||||
return new LLImageJ2CKDU();
|
||||
}
|
||||
|
||||
void destroyLLImageJ2CKDU(LLImageJ2CKDU* kdu)
|
||||
{
|
||||
delete kdu;
|
||||
kdu = NULL;
|
||||
}
|
||||
|
||||
// Factory function: see declaration in llimagej2c.cpp
|
||||
LLImageJ2CImpl* fallbackCreateLLImageJ2CImpl()
|
||||
{
|
||||
return new LLImageJ2CKDU();
|
||||
}
|
||||
|
||||
void fallbackDestroyLLImageJ2CImpl(LLImageJ2CImpl* impl)
|
||||
std::string LLImageJ2CKDU::getEngineInfo() const
|
||||
{
|
||||
delete impl;
|
||||
impl = NULL;
|
||||
}
|
||||
|
||||
const char* fallbackEngineInfoLLImageJ2CImpl()
|
||||
{
|
||||
return engineInfoLLImageJ2CKDU();
|
||||
return llformat("KDU %s", KDU_CORE_VERSION);
|
||||
}
|
||||
|
||||
class LLKDUDecodeState
|
||||
|
|
@ -110,11 +145,11 @@ class LLKDUDecodeState
|
|||
public:
|
||||
LLKDUDecodeState(kdu_tile tile, kdu_byte *buf, S32 row_gap);
|
||||
~LLKDUDecodeState();
|
||||
BOOL processTileDecode(F32 decode_time, BOOL limit_time = TRUE);
|
||||
bool processTileDecode(F32 decode_time, bool limit_time = true);
|
||||
|
||||
private:
|
||||
S32 mNumComponents;
|
||||
BOOL mUseYCC;
|
||||
bool mUseYCC;
|
||||
kdu_dims mDims;
|
||||
kdu_sample_allocator mAllocator;
|
||||
kdu_tile_comp mComps[4];
|
||||
|
|
@ -128,74 +163,91 @@ private:
|
|||
S32 mRowGap;
|
||||
};
|
||||
|
||||
void ll_kdu_error( void )
|
||||
{
|
||||
// *FIX: This exception is bad, bad, bad. It gets thrown from a
|
||||
// destructor which can lead to immediate program termination!
|
||||
throw "ll_kdu_error() throwing an exception";
|
||||
}
|
||||
|
||||
// Stuff for new kdu error handling
|
||||
class LLKDUMessageWarning : public kdu_message
|
||||
class LLKDUMessage: public kdu_message
|
||||
{
|
||||
public:
|
||||
/*virtual*/ void put_text(const char *s);
|
||||
/*virtual*/ void put_text(const kdu_uint16 *s);
|
||||
LLKDUMessage(const std::string& type):
|
||||
mType(type)
|
||||
{}
|
||||
|
||||
static LLKDUMessageWarning sDefaultMessage;
|
||||
};
|
||||
|
||||
class LLKDUMessageError : public kdu_message
|
||||
{
|
||||
public:
|
||||
/*virtual*/ void put_text(const char *s);
|
||||
/*virtual*/ void put_text(const kdu_uint16 *s);
|
||||
/*virtual*/ void flush(bool end_of_message = false);
|
||||
static LLKDUMessageError sDefaultMessage;
|
||||
};
|
||||
|
||||
void LLKDUMessageWarning::put_text(const char *s)
|
||||
{
|
||||
LL_INFOS() << "KDU Warning: " << s << LL_ENDL;
|
||||
}
|
||||
|
||||
void LLKDUMessageWarning::put_text(const kdu_uint16 *s)
|
||||
{
|
||||
LL_INFOS() << "KDU Warning: " << s << LL_ENDL;
|
||||
}
|
||||
|
||||
void LLKDUMessageError::put_text(const char *s)
|
||||
{
|
||||
LL_INFOS() << "KDU Error: " << s << LL_ENDL;
|
||||
}
|
||||
|
||||
void LLKDUMessageError::put_text(const kdu_uint16 *s)
|
||||
{
|
||||
LL_INFOS() << "KDU Error: " << s << LL_ENDL;
|
||||
}
|
||||
|
||||
void LLKDUMessageError::flush(bool end_of_message)
|
||||
{
|
||||
if (end_of_message)
|
||||
virtual void put_text(const char *s)
|
||||
{
|
||||
throw "KDU throwing an exception";
|
||||
LL_INFOS() << "KDU " << mType << ": " << s << LL_ENDL;
|
||||
}
|
||||
}
|
||||
|
||||
LLKDUMessageWarning LLKDUMessageWarning::sDefaultMessage;
|
||||
LLKDUMessageError LLKDUMessageError::sDefaultMessage;
|
||||
static bool kdu_message_initialized = false;
|
||||
virtual void put_text(const kdu_uint16 *s)
|
||||
{
|
||||
// The previous implementation simply streamed 's' to the log. So
|
||||
// either this put_text() override was never called -- or it produced
|
||||
// some baffling log messages -- because I assert that streaming a
|
||||
// const kdu_uint16* to a std::ostream will display only the hex value
|
||||
// of the pointer.
|
||||
LL_INFOS() << "KDU " << mType << ": "
|
||||
<< utf16str_to_utf8str(llutf16string(s)) << LL_ENDL;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string mType;
|
||||
};
|
||||
|
||||
struct LLKDUMessageWarning : public LLKDUMessage
|
||||
{
|
||||
LLKDUMessageWarning():
|
||||
LLKDUMessage("Warning")
|
||||
{
|
||||
kdu_customize_warnings(this);
|
||||
}
|
||||
};
|
||||
// Instantiating LLKDUMessageWarning calls kdu_customize_warnings() with the
|
||||
// new instance. Make it static so this only happens once.
|
||||
static LLKDUMessageWarning sWarningHandler;
|
||||
|
||||
struct LLKDUMessageError : public LLKDUMessage
|
||||
{
|
||||
LLKDUMessageError():
|
||||
LLKDUMessage("Error")
|
||||
{
|
||||
kdu_customize_errors(this);
|
||||
}
|
||||
|
||||
virtual void flush(bool end_of_message = false)
|
||||
{
|
||||
// According to the documentation nat found:
|
||||
// http://pirlwww.lpl.arizona.edu/resources/guide/software/Kakadu/html_pages/globals__kdu$mize_errors.html
|
||||
// "If a kdu_error object is destroyed, handler→flush will be called with
|
||||
// an end_of_message argument equal to true and the process will
|
||||
// subsequently be terminated through exit. The termination may be
|
||||
// avoided, however, by throwing an exception from within the message
|
||||
// terminating handler→flush call."
|
||||
// So throwing an exception here isn't arbitrary: we MUST throw an
|
||||
// exception if we want to recover from a KDU error.
|
||||
// Because this confused me: the above quote specifically refers to
|
||||
// the kdu_error class, which is constructed internally within KDU at
|
||||
// the point where a fatal error is discovered and reported. It is NOT
|
||||
// talking about the kdu_message subclass passed to
|
||||
// kdu_customize_errors(). Destroying this static object at program
|
||||
// shutdown will NOT engage the behavior described above.
|
||||
if (end_of_message)
|
||||
{
|
||||
LLTHROW(KDUError("LLKDUMessageError::flush()"));
|
||||
}
|
||||
}
|
||||
};
|
||||
// Instantiating LLKDUMessageError calls kdu_customize_errors() with the new
|
||||
// instance. Make it static so this only happens once.
|
||||
static LLKDUMessageError sErrorHandler;
|
||||
|
||||
LLImageJ2CKDU::LLImageJ2CKDU() : LLImageJ2CImpl(),
|
||||
mInputp(NULL),
|
||||
mCodeStreamp(NULL),
|
||||
mTPosp(NULL),
|
||||
mTileIndicesp(NULL),
|
||||
mRawImagep(NULL),
|
||||
mDecodeState(NULL),
|
||||
mBlocksSize(-1),
|
||||
mPrecinctsSize(-1),
|
||||
mLevels(0)
|
||||
mInputp(),
|
||||
mCodeStreamp(),
|
||||
mTPosp(),
|
||||
mTileIndicesp(),
|
||||
mRawImagep(NULL),
|
||||
mDecodeState(),
|
||||
mBlocksSize(-1),
|
||||
mPrecinctsSize(-1),
|
||||
mLevels(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -207,7 +259,11 @@ LLImageJ2CKDU::~LLImageJ2CKDU()
|
|||
// Stuff for new simple decode
|
||||
void transfer_bytes(kdu_byte *dest, kdu_line_buf &src, int gap, int precision);
|
||||
|
||||
void LLImageJ2CKDU::setupCodeStream(LLImageJ2C &base, BOOL keep_codestream, ECodeStreamMode mode)
|
||||
// This is called by the real (private) initDecode() (keep_codestream true)
|
||||
// and getMetadata() methods (keep_codestream false). As far as nat can tell,
|
||||
// mode is always MODE_FAST. It was called by findDiscardLevelsBoundaries()
|
||||
// as well, when that still existed, with keep_codestream true and MODE_FAST.
|
||||
void LLImageJ2CKDU::setupCodeStream(LLImageJ2C &base, bool keep_codestream, ECodeStreamMode mode)
|
||||
{
|
||||
S32 data_size = base.getDataSize();
|
||||
S32 max_bytes = (base.getMaxBytes() ? base.getMaxBytes() : data_size);
|
||||
|
|
@ -215,38 +271,33 @@ void LLImageJ2CKDU::setupCodeStream(LLImageJ2C &base, BOOL keep_codestream, ECod
|
|||
//
|
||||
// Initialization
|
||||
//
|
||||
if (!kdu_message_initialized)
|
||||
{
|
||||
kdu_message_initialized = true;
|
||||
kdu_customize_errors(&LLKDUMessageError::sDefaultMessage);
|
||||
kdu_customize_warnings(&LLKDUMessageWarning::sDefaultMessage);
|
||||
}
|
||||
|
||||
if (mCodeStreamp)
|
||||
{
|
||||
mCodeStreamp->destroy();
|
||||
delete mCodeStreamp;
|
||||
mCodeStreamp = NULL;
|
||||
}
|
||||
mCodeStreamp.reset();
|
||||
|
||||
// It's not clear to nat under what circumstances we would reuse a
|
||||
// pre-existing LLKDUMemSource instance. As of 2016-08-05, it consists of
|
||||
// two U32s and a pointer, so it's not as if it would be a huge overhead
|
||||
// to allocate a new one every time.
|
||||
// Also -- why is base.getData() tested specifically here? If that returns
|
||||
// NULL, shouldn't we bail out of the whole method?
|
||||
if (!mInputp && base.getData())
|
||||
{
|
||||
// The compressed data has been loaded
|
||||
// Setup the source for the codestream
|
||||
mInputp = new LLKDUMemSource(base.getData(), data_size);
|
||||
mInputp.reset(new LLKDUMemSource(base.getData(), data_size));
|
||||
}
|
||||
|
||||
if (mInputp)
|
||||
{
|
||||
// This is LLKDUMemSource::reset(), not boost::scoped_ptr::reset().
|
||||
mInputp->reset();
|
||||
}
|
||||
mCodeStreamp = new kdu_codestream;
|
||||
|
||||
mCodeStreamp->create(mInputp);
|
||||
mCodeStreamp->create(mInputp.get());
|
||||
|
||||
// Set the maximum number of bytes to use from the codestream
|
||||
// *TODO: This seems to be wrong. The base class should have no idea of how j2c compression works so no
|
||||
// good way of computing what's the byte range to be used.
|
||||
// *TODO: This seems to be wrong. The base class should have no idea of
|
||||
// how j2c compression works so no good way of computing what's the byte
|
||||
// range to be used.
|
||||
mCodeStreamp->set_max_bytes(max_bytes,true);
|
||||
|
||||
// If you want to flip or rotate the image for some reason, change
|
||||
|
|
@ -284,13 +335,19 @@ void LLImageJ2CKDU::setupCodeStream(LLImageJ2C &base, BOOL keep_codestream, ECod
|
|||
|
||||
S32 components = mCodeStreamp->get_num_components();
|
||||
|
||||
if (components >= 3)
|
||||
{ // Check that components have consistent dimensions (for PPM file)
|
||||
kdu_dims dims1; mCodeStreamp->get_dims(1,dims1);
|
||||
kdu_dims dims2; mCodeStreamp->get_dims(2,dims2);
|
||||
if ((dims1 != dims) || (dims2 != dims))
|
||||
// Check that components have consistent dimensions (for PPM file)
|
||||
for (int idx = 1; idx < components; ++idx)
|
||||
{
|
||||
kdu_dims other_dims;
|
||||
mCodeStreamp->get_dims(idx, other_dims);
|
||||
if (other_dims != dims)
|
||||
{
|
||||
LL_ERRS() << "Components don't have matching dimensions!" << LL_ENDL;
|
||||
// This method is only called from methods that catch KDUError.
|
||||
// We want to fail the image load, not crash the viewer.
|
||||
LLTHROW(KDUError(STRINGIZE("Component " << idx << " dimensions "
|
||||
<< other_dims
|
||||
<< " do not match component 0 dimensions "
|
||||
<< dims << "!")));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -303,42 +360,29 @@ void LLImageJ2CKDU::setupCodeStream(LLImageJ2C &base, BOOL keep_codestream, ECod
|
|||
|
||||
if (!keep_codestream)
|
||||
{
|
||||
mCodeStreamp->destroy();
|
||||
delete mCodeStreamp;
|
||||
mCodeStreamp = NULL;
|
||||
delete mInputp;
|
||||
mInputp = NULL;
|
||||
mCodeStreamp.reset();
|
||||
mInputp.reset();
|
||||
}
|
||||
}
|
||||
|
||||
void LLImageJ2CKDU::cleanupCodeStream()
|
||||
{
|
||||
delete mInputp;
|
||||
mInputp = NULL;
|
||||
|
||||
delete mDecodeState;
|
||||
mDecodeState = NULL;
|
||||
|
||||
if (mCodeStreamp)
|
||||
{
|
||||
mCodeStreamp->destroy();
|
||||
delete mCodeStreamp;
|
||||
mCodeStreamp = NULL;
|
||||
}
|
||||
|
||||
delete mTPosp;
|
||||
mTPosp = NULL;
|
||||
|
||||
delete mTileIndicesp;
|
||||
mTileIndicesp = NULL;
|
||||
mInputp.reset();
|
||||
mDecodeState.reset();
|
||||
mCodeStreamp.reset();
|
||||
mTPosp.reset();
|
||||
mTileIndicesp.reset();
|
||||
}
|
||||
|
||||
BOOL LLImageJ2CKDU::initDecode(LLImageJ2C &base, LLImageRaw &raw_image, int discard_level, int* region)
|
||||
// This is the protected virtual method called by LLImageJ2C::initDecode().
|
||||
// However, as far as nat can tell, LLImageJ2C::initDecode() is called only by
|
||||
// llimage_libtest.cpp's load_image() function. No detectable production use.
|
||||
bool LLImageJ2CKDU::initDecode(LLImageJ2C &base, LLImageRaw &raw_image, int discard_level, int* region)
|
||||
{
|
||||
return initDecode(base,raw_image,0.0f,MODE_FAST,0,4,discard_level,region);
|
||||
}
|
||||
|
||||
BOOL LLImageJ2CKDU::initEncode(LLImageJ2C &base, LLImageRaw &raw_image, int blocks_size, int precincts_size, int levels)
|
||||
bool LLImageJ2CKDU::initEncode(LLImageJ2C &base, LLImageRaw &raw_image, int blocks_size, int precincts_size, int levels)
|
||||
{
|
||||
mPrecinctsSize = precincts_size;
|
||||
if (mPrecinctsSize != -1)
|
||||
|
|
@ -362,10 +406,13 @@ BOOL LLImageJ2CKDU::initEncode(LLImageJ2C &base, LLImageRaw &raw_image, int bloc
|
|||
mLevels = llclamp(mLevels,MIN_DECOMPOSITION_LEVELS,MAX_DECOMPOSITION_LEVELS);
|
||||
base.setLevels(mLevels);
|
||||
}
|
||||
return TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
BOOL LLImageJ2CKDU::initDecode(LLImageJ2C &base, LLImageRaw &raw_image, F32 decode_time, ECodeStreamMode mode, S32 first_channel, S32 max_channel_count, int discard_level, int* region)
|
||||
// This is the real (private) initDecode() called both by the protected
|
||||
// initDecode() method and by decodeImpl(). As far as nat can tell, only the
|
||||
// decodeImpl() usage matters for production.
|
||||
bool LLImageJ2CKDU::initDecode(LLImageJ2C &base, LLImageRaw &raw_image, F32 decode_time, ECodeStreamMode mode, S32 first_channel, S32 max_channel_count, int discard_level, int* region)
|
||||
{
|
||||
base.resetLastError();
|
||||
|
||||
|
|
@ -377,7 +424,7 @@ BOOL LLImageJ2CKDU::initDecode(LLImageJ2C &base, LLImageRaw &raw_image, F32 deco
|
|||
//findDiscardLevelsBoundaries(base);
|
||||
|
||||
base.updateRawDiscardLevel();
|
||||
setupCodeStream(base, TRUE, mode);
|
||||
setupCodeStream(base, true, mode);
|
||||
|
||||
mRawImagep = &raw_image;
|
||||
mCodeStreamp->change_appearance(false, true, false);
|
||||
|
|
@ -412,45 +459,55 @@ BOOL LLImageJ2CKDU::initDecode(LLImageJ2C &base, LLImageRaw &raw_image, F32 deco
|
|||
|
||||
if (!mTileIndicesp)
|
||||
{
|
||||
mTileIndicesp = new kdu_dims;
|
||||
mTileIndicesp.reset(new kdu_dims);
|
||||
}
|
||||
mCodeStreamp->get_valid_tiles(*mTileIndicesp);
|
||||
if (!mTPosp)
|
||||
{
|
||||
mTPosp = new kdu_coords;
|
||||
mTPosp.reset(new kdu_coords);
|
||||
mTPosp->y = 0;
|
||||
mTPosp->x = 0;
|
||||
}
|
||||
}
|
||||
catch (const char* msg)
|
||||
catch (const KDUError& msg)
|
||||
{
|
||||
base.setLastError(ll_safe_string(msg));
|
||||
return FALSE;
|
||||
base.setLastError(msg.what());
|
||||
return false;
|
||||
}
|
||||
catch (kdu_exception kdu_value)
|
||||
{
|
||||
// KDU internally throws kdu_exception. It's possible that such an
|
||||
// exception might leak out into our code. Catch kdu_exception
|
||||
// specially because boost::current_exception_diagnostic_information()
|
||||
// could do nothing with it.
|
||||
base.setLastError(report_kdu_exception(kdu_value));
|
||||
return false;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
base.setLastError("Unknown J2C error");
|
||||
return FALSE;
|
||||
base.setLastError("Unknown J2C error: " +
|
||||
boost::current_exception_diagnostic_information());
|
||||
return false;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// Returns TRUE to mean done, whether successful or not.
|
||||
BOOL LLImageJ2CKDU::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decode_time, S32 first_channel, S32 max_channel_count)
|
||||
// Returns true to mean done, whether successful or not.
|
||||
bool LLImageJ2CKDU::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decode_time, S32 first_channel, S32 max_channel_count)
|
||||
{
|
||||
ECodeStreamMode mode = MODE_FAST;
|
||||
|
||||
LLTimer decode_timer;
|
||||
|
||||
if (!mCodeStreamp)
|
||||
if (!mCodeStreamp->exists())
|
||||
{
|
||||
if (!initDecode(base, raw_image, decode_time, mode, first_channel, max_channel_count))
|
||||
{
|
||||
// Initializing the J2C decode failed, bail out.
|
||||
cleanupCodeStream();
|
||||
return TRUE; // done
|
||||
return true; // done
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -460,6 +517,13 @@ BOOL LLImageJ2CKDU::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 deco
|
|||
|
||||
// Now we are ready to walk through the tiles processing them one-by-one.
|
||||
kdu_byte *buffer = raw_image.getData();
|
||||
if (!buffer)
|
||||
{
|
||||
base.setLastError("Memory error");
|
||||
base.decodeFailed();
|
||||
cleanupCodeStream();
|
||||
return true; // done
|
||||
}
|
||||
|
||||
while (mTPosp->y < mTileIndicesp->size.y)
|
||||
{
|
||||
|
|
@ -495,36 +559,47 @@ BOOL LLImageJ2CKDU::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 deco
|
|||
kdu_coords offset = tile_dims.pos - dims.pos;
|
||||
int row_gap = channels*dims.size.x; // inter-row separation
|
||||
kdu_byte *buf = buffer + offset.y*row_gap + offset.x*channels;
|
||||
mDecodeState = new LLKDUDecodeState(tile, buf, row_gap);
|
||||
mDecodeState.reset(new LLKDUDecodeState(tile, buf, row_gap));
|
||||
}
|
||||
// Do the actual processing
|
||||
F32 remaining_time = decode_time - decode_timer.getElapsedTimeF32();
|
||||
// This is where we do the actual decode. If we run out of time, return false.
|
||||
if (mDecodeState->processTileDecode(remaining_time, (decode_time > 0.0f)))
|
||||
{
|
||||
delete mDecodeState;
|
||||
mDecodeState = NULL;
|
||||
mDecodeState.reset();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Not finished decoding yet.
|
||||
// setLastError("Ran out of time while decoding");
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch (const char* msg)
|
||||
catch (const KDUError& msg)
|
||||
{
|
||||
base.setLastError(ll_safe_string(msg));
|
||||
base.setLastError(msg.what());
|
||||
base.decodeFailed();
|
||||
cleanupCodeStream();
|
||||
return TRUE; // done
|
||||
return true; // done
|
||||
}
|
||||
catch (kdu_exception kdu_value)
|
||||
{
|
||||
// KDU internally throws kdu_exception. It's possible that such an
|
||||
// exception might leak out into our code. Catch kdu_exception
|
||||
// specially because boost::current_exception_diagnostic_information()
|
||||
// could do nothing with it.
|
||||
base.setLastError(report_kdu_exception(kdu_value));
|
||||
base.decodeFailed();
|
||||
cleanupCodeStream();
|
||||
return true; // done
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
base.setLastError( "Unknown J2C error" );
|
||||
base.setLastError("Unknown J2C error: " +
|
||||
boost::current_exception_diagnostic_information());
|
||||
base.decodeFailed();
|
||||
cleanupCodeStream();
|
||||
return TRUE; // done
|
||||
return true; // done
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -536,11 +611,11 @@ BOOL LLImageJ2CKDU::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 deco
|
|||
|
||||
cleanupCodeStream();
|
||||
|
||||
return TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
BOOL LLImageJ2CKDU::encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, const char* comment_text, F32 encode_time, BOOL reversible)
|
||||
bool LLImageJ2CKDU::encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, const char* comment_text, F32 encode_time, bool reversible)
|
||||
{
|
||||
// Declare and set simple arguments
|
||||
bool transpose = false;
|
||||
|
|
@ -705,39 +780,59 @@ BOOL LLImageJ2CKDU::encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, co
|
|||
base.updateData(); // set width, height
|
||||
delete[] output_buffer;
|
||||
}
|
||||
catch(const char* msg)
|
||||
catch(const KDUError& msg)
|
||||
{
|
||||
base.setLastError(ll_safe_string(msg));
|
||||
return FALSE;
|
||||
base.setLastError(msg.what());
|
||||
return false;
|
||||
}
|
||||
catch (kdu_exception kdu_value)
|
||||
{
|
||||
// KDU internally throws kdu_exception. It's possible that such an
|
||||
// exception might leak out into our code. Catch kdu_exception
|
||||
// specially because boost::current_exception_diagnostic_information()
|
||||
// could do nothing with it.
|
||||
base.setLastError(report_kdu_exception(kdu_value));
|
||||
return false;
|
||||
}
|
||||
catch( ... )
|
||||
{
|
||||
base.setLastError( "Unknown J2C error" );
|
||||
return FALSE;
|
||||
base.setLastError("Unknown J2C error: " +
|
||||
boost::current_exception_diagnostic_information());
|
||||
return false;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
BOOL LLImageJ2CKDU::getMetadata(LLImageJ2C &base)
|
||||
bool LLImageJ2CKDU::getMetadata(LLImageJ2C &base)
|
||||
{
|
||||
// *FIX: kdu calls our callback function if there's an error, and
|
||||
// then bombs. To regain control, we throw an exception, and
|
||||
// catch it here.
|
||||
try
|
||||
{
|
||||
setupCodeStream(base, FALSE, MODE_FAST);
|
||||
return TRUE;
|
||||
setupCodeStream(base, false, MODE_FAST);
|
||||
return true;
|
||||
}
|
||||
catch (const char* msg)
|
||||
catch (const KDUError& msg)
|
||||
{
|
||||
base.setLastError(ll_safe_string(msg));
|
||||
return FALSE;
|
||||
base.setLastError(msg.what());
|
||||
return false;
|
||||
}
|
||||
catch (kdu_exception kdu_value)
|
||||
{
|
||||
// KDU internally throws kdu_exception. It's possible that such an
|
||||
// exception might leak out into our code. Catch kdu_exception
|
||||
// specially because boost::current_exception_diagnostic_information()
|
||||
// could do nothing with it.
|
||||
base.setLastError(report_kdu_exception(kdu_value));
|
||||
return false;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
base.setLastError( "Unknown J2C error" );
|
||||
return FALSE;
|
||||
base.setLastError("Unknown J2C error: " +
|
||||
boost::current_exception_diagnostic_information());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -745,6 +840,8 @@ BOOL LLImageJ2CKDU::getMetadata(LLImageJ2C &base)
|
|||
/* STATIC copy_block */
|
||||
/*****************************************************************************/
|
||||
|
||||
/*==========================================================================*|
|
||||
// Only called by copy_tile(), which is itself commented out
|
||||
static void copy_block(kdu_block *in, kdu_block *out)
|
||||
{
|
||||
if (in->K_max_prime != out->K_max_prime)
|
||||
|
|
@ -773,11 +870,14 @@ static void copy_block(kdu_block *in, kdu_block *out)
|
|||
out->set_max_bytes(num_bytes,false);
|
||||
memcpy(out->byte_buffer,in->byte_buffer,(size_t) num_bytes);
|
||||
}
|
||||
|*==========================================================================*/
|
||||
|
||||
/*****************************************************************************/
|
||||
/* STATIC copy_tile */
|
||||
/*****************************************************************************/
|
||||
|
||||
/*==========================================================================*|
|
||||
// Only called by findDiscardLevelsBoundaries(), which is itself commented out
|
||||
static void
|
||||
copy_tile(kdu_tile tile_in, kdu_tile tile_out, int tnum_in, int tnum_out,
|
||||
kdu_params *siz_in, kdu_params *siz_out, int skip_components,
|
||||
|
|
@ -834,10 +934,13 @@ copy_tile(kdu_tile tile_in, kdu_tile tile_out, int tnum_in, int tnum_out,
|
|||
}
|
||||
}
|
||||
}
|
||||
|*==========================================================================*/
|
||||
|
||||
// Find the block boundary for each discard level in the input image.
|
||||
// We parse the input blocks and copy them in a temporary output stream.
|
||||
// For the moment, we do nothing more that parsing the raw list of blocks and outputing result.
|
||||
/*==========================================================================*|
|
||||
// See comments in header file for why this is commented out.
|
||||
void LLImageJ2CKDU::findDiscardLevelsBoundaries(LLImageJ2C &base)
|
||||
{
|
||||
// We need the number of levels in that image before starting.
|
||||
|
|
@ -847,7 +950,7 @@ void LLImageJ2CKDU::findDiscardLevelsBoundaries(LLImageJ2C &base)
|
|||
{
|
||||
//std::cout << "Parsing discard level = " << discard_level << std::endl;
|
||||
// Create the input codestream object.
|
||||
setupCodeStream(base, TRUE, MODE_FAST);
|
||||
setupCodeStream(base, true, MODE_FAST);
|
||||
mCodeStreamp->apply_input_restrictions(0, 4, discard_level, 0, NULL);
|
||||
mCodeStreamp->set_max_bytes(KDU_LONG_MAX,true);
|
||||
siz_params *siz_in = mCodeStreamp->access_siz();
|
||||
|
|
@ -941,6 +1044,7 @@ void LLImageJ2CKDU::findDiscardLevelsBoundaries(LLImageJ2C &base)
|
|||
}
|
||||
return;
|
||||
}
|
||||
|*==========================================================================*/
|
||||
|
||||
void set_default_colour_weights(kdu_params *siz)
|
||||
{
|
||||
|
|
@ -1206,7 +1310,7 @@ LLKDUDecodeState::~LLKDUDecodeState()
|
|||
mTile.close();
|
||||
}
|
||||
|
||||
BOOL LLKDUDecodeState::processTileDecode(F32 decode_time, BOOL limit_time)
|
||||
bool LLKDUDecodeState::processTileDecode(F32 decode_time, bool limit_time)
|
||||
/* Decompresses a tile, writing the data into the supplied byte buffer.
|
||||
The buffer contains interleaved image components, if there are any.
|
||||
Although you may think of the buffer as belonging entirely to this tile,
|
||||
|
|
@ -1238,11 +1342,11 @@ separation between consecutive rows in the real buffer. */
|
|||
{
|
||||
if (limit_time && decode_timer.getElapsedTimeF32() > decode_time)
|
||||
{
|
||||
return FALSE;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
// kdc_flow_control
|
||||
|
|
|
|||
|
|
@ -48,6 +48,8 @@
|
|||
#endif
|
||||
|
||||
#include "kdu_sample_processing.h"
|
||||
#include <boost/scoped_ptr.hpp>
|
||||
#include <boost/noncopyable.hpp>
|
||||
|
||||
class LLKDUDecodeState;
|
||||
class LLKDUMemSource;
|
||||
|
|
@ -65,43 +67,70 @@ public:
|
|||
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);
|
||||
/*virtual*/ BOOL initDecode(LLImageJ2C &base, LLImageRaw &raw_image, int discard_level = -1, int* region = NULL);
|
||||
/*virtual*/ BOOL initEncode(LLImageJ2C &base, LLImageRaw &raw_image, int blocks_size = -1, int precincts_size = -1, int levels = 0);
|
||||
void findDiscardLevelsBoundaries(LLImageJ2C &base);
|
||||
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);
|
||||
virtual bool initDecode(LLImageJ2C &base, LLImageRaw &raw_image, int discard_level = -1, int* region = NULL);
|
||||
virtual bool initEncode(LLImageJ2C &base, LLImageRaw &raw_image, int blocks_size = -1, int precincts_size = -1, int levels = 0);
|
||||
virtual std::string getEngineInfo() const;
|
||||
|
||||
private:
|
||||
BOOL initDecode(LLImageJ2C &base, LLImageRaw &raw_image, F32 decode_time, ECodeStreamMode mode, S32 first_channel, S32 max_channel_count, int discard_level = -1, int* region = NULL);
|
||||
void setupCodeStream(LLImageJ2C &base, BOOL keep_codestream, ECodeStreamMode mode);
|
||||
bool initDecode(LLImageJ2C &base, LLImageRaw &raw_image, F32 decode_time, ECodeStreamMode mode, S32 first_channel, S32 max_channel_count, int discard_level = -1, int* region = NULL);
|
||||
void setupCodeStream(LLImageJ2C &base, bool keep_codestream, ECodeStreamMode mode);
|
||||
void cleanupCodeStream();
|
||||
|
||||
// This method was public, but the only call to it is commented out in our
|
||||
// own initDecode() method. I (nat 2016-08-04) don't know what it does or
|
||||
// why. Even if it should be uncommented, it should probably still be
|
||||
// private.
|
||||
// void findDiscardLevelsBoundaries(LLImageJ2C &base);
|
||||
|
||||
// Helper class to hold a kdu_codestream, which is a handle to the
|
||||
// underlying implementation object. When CodeStreamHolder is reset() or
|
||||
// destroyed, it calls kdu_codestream::destroy() -- which kdu_codestream
|
||||
// itself does not.
|
||||
//
|
||||
// Call through it like a smart pointer using operator->().
|
||||
//
|
||||
// Every RAII class must be noncopyable. For this we don't need move
|
||||
// support.
|
||||
class CodeStreamHolder: public boost::noncopyable
|
||||
{
|
||||
public:
|
||||
~CodeStreamHolder()
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
void reset()
|
||||
{
|
||||
if (mCodeStream.exists())
|
||||
{
|
||||
mCodeStream.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
kdu_codestream* operator->() { return &mCodeStream; }
|
||||
|
||||
private:
|
||||
kdu_codestream mCodeStream;
|
||||
};
|
||||
|
||||
// Encode variable
|
||||
LLKDUMemSource *mInputp;
|
||||
kdu_codestream *mCodeStreamp;
|
||||
kdu_coords *mTPosp; // tile position
|
||||
kdu_dims *mTileIndicesp;
|
||||
boost::scoped_ptr<LLKDUMemSource> mInputp;
|
||||
CodeStreamHolder mCodeStreamp;
|
||||
boost::scoped_ptr<kdu_coords> mTPosp; // tile position
|
||||
boost::scoped_ptr<kdu_dims> mTileIndicesp;
|
||||
int mBlocksSize;
|
||||
int mPrecinctsSize;
|
||||
int mLevels;
|
||||
|
||||
// Temporary variables for in-progress decodes...
|
||||
// We don't own this LLImageRaw. We're simply pointing to an instance
|
||||
// passed into initDecode().
|
||||
LLImageRaw *mRawImagep;
|
||||
LLKDUDecodeState *mDecodeState;
|
||||
boost::scoped_ptr<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
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ LLImageRaw::~LLImageRaw() { }
|
|||
U8* LLImageRaw::allocateData(S32 ) { return NULL; }
|
||||
void LLImageRaw::deleteData() { }
|
||||
U8* LLImageRaw::reallocateData(S32 ) { return NULL; }
|
||||
BOOL LLImageRaw::resize(U16, U16, S8) { return TRUE; } // this method always returns TRUE...
|
||||
bool LLImageRaw::resize(U16, U16, S8) { return true; } // this method always returns true...
|
||||
|
||||
LLImageBase::LLImageBase()
|
||||
: LLTrace::MemTrackable<LLImageBase>("LLImageBase"),
|
||||
|
|
@ -89,8 +89,8 @@ LLImageFormatted::~LLImageFormatted() { }
|
|||
U8* LLImageFormatted::allocateData(S32 ) { return NULL; }
|
||||
S32 LLImageFormatted::calcDataSize(S32 ) { return 0; }
|
||||
S32 LLImageFormatted::calcDiscardLevelBytes(S32 ) { return 0; }
|
||||
BOOL LLImageFormatted::decodeChannels(LLImageRaw*, F32, S32, S32) { return FALSE; }
|
||||
BOOL LLImageFormatted::copyData(U8 *, S32) { return TRUE; } // this method always returns TRUE...
|
||||
bool LLImageFormatted::decodeChannels(LLImageRaw*, F32, S32, S32) { return false; }
|
||||
bool LLImageFormatted::copyData(U8 *, S32) { return true; } // this method always returns true...
|
||||
void LLImageFormatted::deleteData() { }
|
||||
void LLImageFormatted::dump() { }
|
||||
U8* LLImageFormatted::reallocateData(S32 ) { return NULL; }
|
||||
|
|
@ -103,14 +103,14 @@ LLImageJ2C::~LLImageJ2C() { }
|
|||
S32 LLImageJ2C::calcDataSize(S32 ) { return 0; }
|
||||
S32 LLImageJ2C::calcDiscardLevelBytes(S32 ) { return 0; }
|
||||
S32 LLImageJ2C::calcHeaderSize() { return 0; }
|
||||
BOOL LLImageJ2C::decode(LLImageRaw*, F32) { return FALSE; }
|
||||
BOOL LLImageJ2C::decodeChannels(LLImageRaw*, F32, S32, S32 ) { return FALSE; }
|
||||
bool LLImageJ2C::decode(LLImageRaw*, F32) { return false; }
|
||||
bool LLImageJ2C::decodeChannels(LLImageRaw*, F32, S32, S32 ) { return false; }
|
||||
void LLImageJ2C::decodeFailed() { }
|
||||
BOOL LLImageJ2C::encode(const LLImageRaw*, F32) { return FALSE; }
|
||||
bool LLImageJ2C::encode(const LLImageRaw*, F32) { return false; }
|
||||
S8 LLImageJ2C::getRawDiscardLevel() { return 0; }
|
||||
void LLImageJ2C::resetLastError() { }
|
||||
void LLImageJ2C::setLastError(const std::string&, const std::string&) { }
|
||||
BOOL LLImageJ2C::updateData() { return FALSE; }
|
||||
bool LLImageJ2C::updateData() { return false; }
|
||||
void LLImageJ2C::updateRawDiscardLevel() { }
|
||||
|
||||
LLKDUMemIn::LLKDUMemIn(const U8*, const U32, const U16, const U16, const U8, siz_params*) { }
|
||||
|
|
@ -212,12 +212,12 @@ namespace tut
|
|||
{
|
||||
public:
|
||||
// Provides public access to some protected methods for testing
|
||||
BOOL callGetMetadata(LLImageJ2C &base) { return getMetadata(base); }
|
||||
BOOL callDecodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decode_time, S32 first_channel, S32 max_channel_count)
|
||||
bool callGetMetadata(LLImageJ2C &base) { return getMetadata(base); }
|
||||
bool callDecodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decode_time, S32 first_channel, S32 max_channel_count)
|
||||
{
|
||||
return decodeImpl(base, raw_image, decode_time, first_channel, max_channel_count);
|
||||
}
|
||||
BOOL callEncodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, const char* comment_text)
|
||||
bool callEncodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, const char* comment_text)
|
||||
{
|
||||
return encodeImpl(base, raw_image, comment_text);
|
||||
}
|
||||
|
|
@ -254,10 +254,10 @@ namespace tut
|
|||
void llimagej2ckdu_object_t::test<1>()
|
||||
{
|
||||
LLImageJ2C* image = new LLImageJ2C();
|
||||
BOOL res = mImage->callGetMetadata(*image);
|
||||
// Trying to set up a data stream with all NIL values and stubbed KDU will "work" and return TRUE
|
||||
// Note that is linking with KDU, that call will throw an exception and fail, returning FALSE
|
||||
ensure("getMetadata() test failed", res == TRUE);
|
||||
bool res = mImage->callGetMetadata(*image);
|
||||
// Trying to set up a data stream with all NIL values and stubbed KDU will "work" and return true
|
||||
// Note that is linking with KDU, that call will throw an exception and fail, returning false
|
||||
ensure("getMetadata() test failed", res);
|
||||
}
|
||||
|
||||
// Test 2 : test decodeImpl()
|
||||
|
|
@ -266,9 +266,9 @@ namespace tut
|
|||
{
|
||||
LLImageJ2C* image = new LLImageJ2C();
|
||||
LLImageRaw* raw = new LLImageRaw();
|
||||
BOOL res = mImage->callDecodeImpl(*image, *raw, 0.0, 0, 0);
|
||||
// Decoding returns TRUE whenever there's nothing else to do, including if decoding failed, so we'll get TRUE here
|
||||
ensure("decodeImpl() test failed", res == TRUE);
|
||||
bool res = mImage->callDecodeImpl(*image, *raw, 0.0, 0, 0);
|
||||
// Decoding returns true whenever there's nothing else to do, including if decoding failed, so we'll get true here
|
||||
ensure("decodeImpl() test failed", res);
|
||||
}
|
||||
|
||||
// Test 3 : test encodeImpl()
|
||||
|
|
@ -277,8 +277,8 @@ namespace tut
|
|||
{
|
||||
LLImageJ2C* image = new LLImageJ2C();
|
||||
LLImageRaw* raw = new LLImageRaw();
|
||||
BOOL res = mImage->callEncodeImpl(*image, *raw, NULL);
|
||||
// Encoding returns TRUE unless an exception was raised, so we'll get TRUE here though nothing really was done
|
||||
ensure("encodeImpl() test failed", res == TRUE);
|
||||
bool res = mImage->callEncodeImpl(*image, *raw, NULL);
|
||||
// Encoding returns true unless an exception was raised, so we'll get true here though nothing really was done
|
||||
ensure("encodeImpl() test failed", res);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -181,6 +181,10 @@ protected:
|
|||
// Map of known bad assets
|
||||
typedef std::map<LLUUID,U64,lluuid_less> toxic_asset_map_t;
|
||||
|
||||
// *TODO: these typedefs are passed into the VFS via a legacy C function pointer
|
||||
// future project would be to convert these to C++ callables (std::function<>) so that
|
||||
// we can use bind and remove the userData parameter.
|
||||
//
|
||||
typedef void (*LLGetAssetCallback)(LLVFS *vfs, const LLUUID &asset_id,
|
||||
LLAssetType::EType asset_type, void *user_data, S32 status, LLExtStat ext_status);
|
||||
|
||||
|
|
|
|||
|
|
@ -166,7 +166,7 @@ void LLAvatarName::setExpires(F64 expires)
|
|||
mExpires = LLFrameTimer::getTotalSeconds() + expires;
|
||||
}
|
||||
|
||||
std::string LLAvatarName::getCompleteName() const
|
||||
std::string LLAvatarName::getCompleteName(bool use_parentheses) const
|
||||
{
|
||||
std::string name;
|
||||
if (sUseDisplayNames)
|
||||
|
|
@ -182,7 +182,14 @@ std::string LLAvatarName::getCompleteName() const
|
|||
name = mDisplayName;
|
||||
if(sUseUsernames)
|
||||
{
|
||||
name += " (" + mUsername + ")";
|
||||
if(use_parentheses)
|
||||
{
|
||||
name += " (" + mUsername + ")";
|
||||
}
|
||||
else
|
||||
{
|
||||
name += " [ " + mUsername + " ]";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -220,7 +227,7 @@ std::string LLAvatarName::getDisplayName() const
|
|||
}
|
||||
}
|
||||
|
||||
std::string LLAvatarName::getUserName() const
|
||||
std::string LLAvatarName::getUserName(bool lowercase) const
|
||||
{
|
||||
std::string name;
|
||||
if (mLegacyLastName.empty() || (mLegacyLastName == "Resident"))
|
||||
|
|
@ -238,7 +245,15 @@ std::string LLAvatarName::getUserName() const
|
|||
}
|
||||
else
|
||||
{
|
||||
name = mLegacyFirstName + " " + mLegacyLastName;
|
||||
if(lowercase)
|
||||
{
|
||||
name = mLegacyFirstName + "." + mLegacyLastName;
|
||||
LLStringUtil::toLower(name);
|
||||
}
|
||||
else
|
||||
{
|
||||
name = mLegacyFirstName + " " + mLegacyLastName;
|
||||
}
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ public:
|
|||
|
||||
// For normal names, returns "James Linden (james.linden)"
|
||||
// When display names are disabled returns just "James Linden"
|
||||
std::string getCompleteName() const;
|
||||
std::string getCompleteName(bool use_parentheses = true) const;
|
||||
|
||||
// Returns "James Linden" or "bobsmith123 Resident" for backwards
|
||||
// compatibility with systems like voice and muting
|
||||
|
|
@ -80,7 +80,7 @@ public:
|
|||
// Returns "James Linden" or "bobsmith123 Resident"
|
||||
// Used where we explicitely prefer or need a non UTF-8 legacy (ASCII) name
|
||||
// Also used for backwards compatibility with systems like voice and muting
|
||||
std::string getUserName() const;
|
||||
std::string getUserName(bool lowercase = false) const;
|
||||
|
||||
// Returns "james.linden" or the legacy name for very old names
|
||||
std::string getAccountName() const { return mUsername; }
|
||||
|
|
|
|||
|
|
@ -43,6 +43,8 @@
|
|||
#include "llcoros.h"
|
||||
#include "lleventcoro.h"
|
||||
#include "llcorehttputil.h"
|
||||
#include "llexception.h"
|
||||
#include "stringize.h"
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
|
@ -231,13 +233,12 @@ void LLAvatarNameCache::requestAvatarNameCache_(std::string url, std::vector<LLU
|
|||
LLAvatarNameCache::handleAvNameCacheSuccess(results, httpResults);
|
||||
|
||||
}
|
||||
catch (std::exception e)
|
||||
{
|
||||
LL_WARNS() << "Caught exception '" << e.what() << "'" << LL_ENDL;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
LL_WARNS() << "Caught unknown exception." << LL_ENDL;
|
||||
LOG_UNHANDLED_EXCEPTION(STRINGIZE("coroutine " << LLCoros::instance().getName()
|
||||
<< "('" << url << "', " << agentIds.size()
|
||||
<< " Agent Ids)"));
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -27,6 +27,8 @@
|
|||
|
||||
#include "linden_common.h"
|
||||
#include "llcoproceduremanager.h"
|
||||
#include "llexception.h"
|
||||
#include "stringize.h"
|
||||
#include <boost/assign.hpp>
|
||||
|
||||
//=========================================================================
|
||||
|
|
@ -388,14 +390,14 @@ void LLCoprocedurePool::coprocedureInvokerCoro(LLCoreHttpUtil::HttpCoroutineAdap
|
|||
{
|
||||
coproc->mProc(httpAdapter, coproc->mId);
|
||||
}
|
||||
catch (std::exception &e)
|
||||
{
|
||||
LL_WARNS() << "Coprocedure(" << coproc->mName << ") id=" << coproc->mId.asString() <<
|
||||
" threw an exception! Message=\"" << e.what() << "\"" << LL_ENDL;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
LL_WARNS() << "A non std::exception was thrown from " << coproc->mName << " with id=" << coproc->mId << "." << " in pool \"" << mPoolName << "\"" << LL_ENDL;
|
||||
LOG_UNHANDLED_EXCEPTION(STRINGIZE("Coprocedure('" << coproc->mName
|
||||
<< "', id=" << coproc->mId.asString()
|
||||
<< ") in pool '" << mPoolName << "'"));
|
||||
// must NOT omit this or we deplete the pool
|
||||
mActiveCoprocs.erase(itActive);
|
||||
throw;
|
||||
}
|
||||
|
||||
LL_INFOS() << "Finished coprocedure(" << coproc->mName << ")" << " in pool \"" << mPoolName << "\"" << LL_ENDL;
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@
|
|||
|
||||
#include "llstl.h"
|
||||
#include "llhttpconstants.h"
|
||||
#include "llexception.h"
|
||||
|
||||
const std::string CONTEXT_HEADERS("headers");
|
||||
const std::string CONTEXT_PATH("path");
|
||||
|
|
@ -92,27 +93,28 @@ LLHTTPNode::~LLHTTPNode()
|
|||
|
||||
|
||||
namespace {
|
||||
class NotImplemented
|
||||
struct NotImplemented: public LLException
|
||||
{
|
||||
NotImplemented(): LLException("LLHTTPNode::NotImplemented") {}
|
||||
};
|
||||
}
|
||||
|
||||
// virtual
|
||||
LLSD LLHTTPNode::simpleGet() const
|
||||
{
|
||||
throw NotImplemented();
|
||||
LLTHROW(NotImplemented());
|
||||
}
|
||||
|
||||
// virtual
|
||||
LLSD LLHTTPNode::simplePut(const LLSD& input) const
|
||||
{
|
||||
throw NotImplemented();
|
||||
LLTHROW(NotImplemented());
|
||||
}
|
||||
|
||||
// virtual
|
||||
LLSD LLHTTPNode::simplePost(const LLSD& input) const
|
||||
{
|
||||
throw NotImplemented();
|
||||
LLTHROW(NotImplemented());
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -172,7 +174,7 @@ void LLHTTPNode::del(LLHTTPNode::ResponsePtr response, const LLSD& context) cons
|
|||
// virtual
|
||||
LLSD LLHTTPNode::simpleDel(const LLSD&) const
|
||||
{
|
||||
throw NotImplemented();
|
||||
LLTHROW(NotImplemented());
|
||||
}
|
||||
|
||||
// virtual
|
||||
|
|
|
|||
|
|
@ -33,15 +33,15 @@
|
|||
#include "llevents.h"
|
||||
#include "llsd.h"
|
||||
#include "llhost.h"
|
||||
#include "llexception.h"
|
||||
#include "stringize.h"
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
struct CommtestError: public std::runtime_error
|
||||
struct CommtestError: public LLException
|
||||
{
|
||||
CommtestError(const std::string& what): std::runtime_error(what) {}
|
||||
CommtestError(const std::string& what): LLException(what) {}
|
||||
};
|
||||
|
||||
static bool query_verbose()
|
||||
|
|
@ -68,7 +68,7 @@ static int query_port(const std::string& var)
|
|||
const char* cport = getenv(var.c_str());
|
||||
if (! cport)
|
||||
{
|
||||
throw CommtestError(STRINGIZE("missing environment variable" << var));
|
||||
LLTHROW(CommtestError(STRINGIZE("missing environment variable" << var)));
|
||||
}
|
||||
// This will throw, too, if the value of PORT isn't numeric.
|
||||
int port(boost::lexical_cast<int>(cport));
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@
|
|||
#include "llares.h"
|
||||
#include "llpumpio.h"
|
||||
#include "llhttpclient.h"
|
||||
#include "llexception.h"
|
||||
|
||||
/*****************************************************************************
|
||||
* NetworkIO
|
||||
|
|
@ -51,7 +52,7 @@ public:
|
|||
ll_init_apr();
|
||||
if (! gAPRPoolp)
|
||||
{
|
||||
throw std::runtime_error("Can't initialize APR");
|
||||
LLTHROW(LLException("Can't initialize APR"));
|
||||
}
|
||||
|
||||
// Create IO Pump to use for HTTP Requests.
|
||||
|
|
@ -59,7 +60,7 @@ public:
|
|||
LLHTTPClient::setPump(*mServicePump);
|
||||
if (ll_init_ares() == NULL || !gAres->isInitialized())
|
||||
{
|
||||
throw std::runtime_error("Can't start DNS resolver");
|
||||
LLTHROW(LLException("Can't start DNS resolver"));
|
||||
}
|
||||
|
||||
// You can interrupt pump() without waiting the full timeout duration
|
||||
|
|
|
|||
|
|
@ -116,7 +116,7 @@ void LLPluginClassMedia::reset()
|
|||
mMediaHeight = 0;
|
||||
mDirtyRect = LLRect::null;
|
||||
mAutoScaleMedia = false;
|
||||
mRequestedVolume = 1.0f;
|
||||
mRequestedVolume = 0.0f;
|
||||
mPriority = PRIORITY_NORMAL;
|
||||
mLowPrioritySizeLimit = LOW_PRIORITY_TEXTURE_SIZE_DEFAULT;
|
||||
mAllowDownsample = false;
|
||||
|
|
|
|||
|
|
@ -2235,7 +2235,11 @@ std::string LLDAELoader::getElementLabel(daeElement *element)
|
|||
// retrieve index to distinguish items inside same parent
|
||||
size_t ind = 0;
|
||||
parent->getChildren().find(element, ind);
|
||||
index_string = "_" + boost::lexical_cast<std::string>(ind);
|
||||
|
||||
if (ind > 0)
|
||||
{
|
||||
index_string = "_" + boost::lexical_cast<std::string>(ind);
|
||||
}
|
||||
|
||||
// if parent has a name or ID, use it
|
||||
std::string name = parent->getAttribute("name");
|
||||
|
|
|
|||
|
|
@ -349,8 +349,8 @@ void LLGLSLShader::unloadInternal()
|
|||
for (GLsizei i = 0; i < count; i++)
|
||||
{
|
||||
glDetachObjectARB(mProgramObject, obj[i]);
|
||||
glDeleteObjectARB(obj[i]);
|
||||
}
|
||||
glDeleteObjectARB(obj[i]);
|
||||
}
|
||||
|
||||
glDeleteObjectARB(mProgramObject);
|
||||
|
||||
|
|
|
|||
|
|
@ -520,7 +520,7 @@ void LLShaderMgr::dumpObjectLog(GLhandleARB ret, BOOL warns, const std::string&
|
|||
if (!filename.empty())
|
||||
{
|
||||
LL_CONT << "From " << filename << ":\n";
|
||||
}
|
||||
}
|
||||
LL_CONT << log << LL_ENDL;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1326,7 +1326,7 @@ void LLFloater::setMinimized(BOOL minimize)
|
|||
}
|
||||
|
||||
mMinimized = FALSE;
|
||||
|
||||
setFrontmost();
|
||||
// Reshape *after* setting mMinimized
|
||||
reshape( mExpandedRect.getWidth(), mExpandedRect.getHeight(), TRUE );
|
||||
}
|
||||
|
|
@ -1575,6 +1575,7 @@ BOOL LLFloater::handleMouseDown(S32 x, S32 y, MASK mask)
|
|||
if(offerClickToButton(x, y, mask, BUTTON_TEAR_OFF)) return TRUE;
|
||||
if(offerClickToButton(x, y, mask, BUTTON_DOCK)) return TRUE;
|
||||
|
||||
setFrontmost(TRUE, FALSE);
|
||||
// Otherwise pass to drag handle for movement
|
||||
return mDragHandle->handleMouseDown(x, y, mask);
|
||||
}
|
||||
|
|
@ -1649,7 +1650,7 @@ void LLFloater::setVisibleAndFrontmost(BOOL take_focus,const LLSD& key)
|
|||
}
|
||||
}
|
||||
|
||||
void LLFloater::setFrontmost(BOOL take_focus)
|
||||
void LLFloater::setFrontmost(BOOL take_focus, BOOL restore)
|
||||
{
|
||||
LLMultiFloater* hostp = getHost();
|
||||
if (hostp)
|
||||
|
|
@ -1665,7 +1666,7 @@ void LLFloater::setFrontmost(BOOL take_focus)
|
|||
LLFloaterView * parent = dynamic_cast<LLFloaterView*>( getParent() );
|
||||
if (parent)
|
||||
{
|
||||
parent->bringToFront(this, take_focus);
|
||||
parent->bringToFront(this, take_focus, restore);
|
||||
}
|
||||
|
||||
// Make sure to set the appropriate transparency type (STORM-732).
|
||||
|
|
@ -2262,7 +2263,7 @@ void LLFloaterView::reshape(S32 width, S32 height, BOOL called_from_parent)
|
|||
for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it)
|
||||
{
|
||||
LLView* viewp = *child_it;
|
||||
LLFloater* floaterp = (LLFloater*)viewp;
|
||||
LLFloater* floaterp = dynamic_cast<LLFloater*>(viewp);
|
||||
if (floaterp->isDependent())
|
||||
{
|
||||
// dependents are moved with their "dependee"
|
||||
|
|
@ -2317,10 +2318,14 @@ void LLFloaterView::reshape(S32 width, S32 height, BOOL called_from_parent)
|
|||
void LLFloaterView::restoreAll()
|
||||
{
|
||||
// make sure all subwindows aren't minimized
|
||||
for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it)
|
||||
child_list_t child_list = *(getChildList());
|
||||
for (child_list_const_iter_t child_it = child_list.begin(); child_it != child_list.end(); ++child_it)
|
||||
{
|
||||
LLFloater* floaterp = (LLFloater*)*child_it;
|
||||
floaterp->setMinimized(FALSE);
|
||||
LLFloater* floaterp = dynamic_cast<LLFloater*>(*child_it);
|
||||
if (floaterp)
|
||||
{
|
||||
floaterp->setMinimized(FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
// *FIX: make sure dependents are restored
|
||||
|
|
@ -2394,7 +2399,7 @@ LLRect LLFloaterView::findNeighboringPosition( LLFloater* reference_floater, LLF
|
|||
}
|
||||
|
||||
|
||||
void LLFloaterView::bringToFront(LLFloater* child, BOOL give_focus)
|
||||
void LLFloaterView::bringToFront(LLFloater* child, BOOL give_focus, BOOL restore)
|
||||
{
|
||||
if (!child)
|
||||
return;
|
||||
|
|
@ -2478,7 +2483,12 @@ void LLFloaterView::bringToFront(LLFloater* child, BOOL give_focus)
|
|||
{
|
||||
sendChildToFront(child);
|
||||
}
|
||||
child->setMinimized(FALSE);
|
||||
|
||||
if(restore)
|
||||
{
|
||||
child->setMinimized(FALSE);
|
||||
}
|
||||
|
||||
if (give_focus && !gFocusMgr.childHasKeyboardFocus(child))
|
||||
{
|
||||
child->setFocus(TRUE);
|
||||
|
|
@ -2591,7 +2601,7 @@ void LLFloaterView::getMinimizePosition(S32 *left, S32 *bottom)
|
|||
++child_it) //loop floaters
|
||||
{
|
||||
// Examine minimized children.
|
||||
LLFloater* floater = (LLFloater*)((LLView*)*child_it);
|
||||
LLFloater* floater = dynamic_cast<LLFloater*>(*child_it);
|
||||
if(floater->isMinimized())
|
||||
{
|
||||
LLRect r = floater->getRect();
|
||||
|
|
@ -2644,7 +2654,7 @@ void LLFloaterView::closeAllChildren(bool app_quitting)
|
|||
continue;
|
||||
}
|
||||
|
||||
LLFloater* floaterp = (LLFloater*)viewp;
|
||||
LLFloater* floaterp = dynamic_cast<LLFloater*>(viewp);
|
||||
|
||||
// Attempt to close floater. This will cause the "do you want to save"
|
||||
// dialogs to appear.
|
||||
|
|
@ -2710,8 +2720,7 @@ BOOL LLFloaterView::allChildrenClosed()
|
|||
// by setting themselves invisible)
|
||||
for (child_list_const_iter_t it = getChildList()->begin(); it != getChildList()->end(); ++it)
|
||||
{
|
||||
LLView* viewp = *it;
|
||||
LLFloater* floaterp = (LLFloater*)viewp;
|
||||
LLFloater* floaterp = dynamic_cast<LLFloater*>(*it);
|
||||
|
||||
if (floaterp->getVisible() && !floaterp->isDead() && floaterp->isCloseable())
|
||||
{
|
||||
|
|
@ -2947,7 +2956,7 @@ void LLFloaterView::syncFloaterTabOrder()
|
|||
// otherwise, make sure the focused floater is in the front of the child list
|
||||
for ( child_list_const_reverse_iter_t child_it = getChildList()->rbegin(); child_it != getChildList()->rend(); ++child_it)
|
||||
{
|
||||
LLFloater* floaterp = (LLFloater*)*child_it;
|
||||
LLFloater* floaterp = dynamic_cast<LLFloater*>(*child_it);
|
||||
if (gFocusMgr.childHasKeyboardFocus(floaterp))
|
||||
{
|
||||
bringToFront(floaterp, FALSE);
|
||||
|
|
@ -2969,7 +2978,7 @@ LLFloater* LLFloaterView::getParentFloater(LLView* viewp) const
|
|||
|
||||
if (parentp == this)
|
||||
{
|
||||
return (LLFloater*)viewp;
|
||||
return dynamic_cast<LLFloater*>(viewp);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
|
|
|||
|
|
@ -310,7 +310,7 @@ public:
|
|||
/*virtual*/ void setVisible(BOOL visible); // do not override
|
||||
/*virtual*/ void onVisibilityChange ( BOOL new_visibility ); // do not override
|
||||
|
||||
void setFrontmost(BOOL take_focus = TRUE);
|
||||
void setFrontmost(BOOL take_focus = TRUE, BOOL restore = TRUE);
|
||||
virtual void setVisibleAndFrontmost(BOOL take_focus=TRUE, const LLSD& key = LLSD());
|
||||
|
||||
// Defaults to false.
|
||||
|
|
@ -547,7 +547,7 @@ public:
|
|||
|
||||
void setCycleMode(BOOL mode) { mFocusCycleMode = mode; }
|
||||
BOOL getCycleMode() const { return mFocusCycleMode; }
|
||||
void bringToFront( LLFloater* child, BOOL give_focus = TRUE );
|
||||
void bringToFront( LLFloater* child, BOOL give_focus = TRUE, BOOL restore = TRUE );
|
||||
void highlightFocusedFloater();
|
||||
void unhighlightFocusedFloater();
|
||||
void focusFrontFloater();
|
||||
|
|
|
|||
|
|
@ -186,7 +186,6 @@ void LLFocusMgr::releaseFocusIfNeeded( LLView* view )
|
|||
LLUI::removePopup(view);
|
||||
}
|
||||
|
||||
|
||||
void LLFocusMgr::setKeyboardFocus(LLFocusableElement* new_focus, BOOL lock, BOOL keystrokes_only)
|
||||
{
|
||||
// notes if keyboard focus is changed again (by onFocusLost/onFocusReceived)
|
||||
|
|
|
|||
|
|
@ -1629,9 +1629,9 @@ void LLFolderView::update()
|
|||
if (mNeedsAutoSelect)
|
||||
{
|
||||
LL_RECORD_BLOCK_TIME(FTM_AUTO_SELECT);
|
||||
// select new item only if a filtered item not currently selected
|
||||
// select new item only if a filtered item not currently selected and there was a selection
|
||||
LLFolderViewItem* selected_itemp = mSelectedItems.empty() ? NULL : mSelectedItems.back();
|
||||
if (!mAutoSelectOverride && (!selected_itemp || !selected_itemp->getViewModelItem()->potentiallyVisible()))
|
||||
if (!mAutoSelectOverride && selected_itemp && !selected_itemp->getViewModelItem()->potentiallyVisible())
|
||||
{
|
||||
// these are named variables to get around gcc not binding non-const references to rvalues
|
||||
// and functor application is inherently non-const to allow for stateful functors
|
||||
|
|
|
|||
|
|
@ -242,6 +242,8 @@ public:
|
|||
bool useLabelSuffix() { return mUseLabelSuffix; }
|
||||
virtual void updateMenu();
|
||||
|
||||
void finishRenamingItem( void );
|
||||
|
||||
// Note: We may eventually have to move that method up the hierarchy to LLFolderViewItem.
|
||||
LLHandle<LLFolderView> getHandle() const { return getDerivedHandle<LLFolderView>(); }
|
||||
|
||||
|
|
@ -255,7 +257,6 @@ protected:
|
|||
void commitRename( const LLSD& data );
|
||||
void onRenamerLost();
|
||||
|
||||
void finishRenamingItem( void );
|
||||
void closeRenamer( void );
|
||||
|
||||
bool selectFirstItem();
|
||||
|
|
|
|||
|
|
@ -972,6 +972,11 @@ void LLFolderViewFolder::addToFolder(LLFolderViewFolder* folder)
|
|||
mIndentation = (getParentFolder())
|
||||
? getParentFolder()->getIndentation() + mLocalIndentation
|
||||
: 0;
|
||||
|
||||
if(isOpen() && folder->isOpen())
|
||||
{
|
||||
requestArrange();
|
||||
}
|
||||
}
|
||||
|
||||
static LLTrace::BlockTimerStatHandle FTM_ARRANGE("Arrange");
|
||||
|
|
|
|||
|
|
@ -400,12 +400,7 @@ void LLLineEditor::setText(const LLStringExplicit &new_text)
|
|||
|
||||
if (mMaxLengthChars)
|
||||
{
|
||||
LLWString truncated_wstring = utf8str_to_wstring(truncated_utf8);
|
||||
if (truncated_wstring.size() > (U32)mMaxLengthChars)
|
||||
{
|
||||
truncated_wstring = truncated_wstring.substr(0, mMaxLengthChars);
|
||||
}
|
||||
mText.assign(wstring_to_utf8str(truncated_wstring));
|
||||
mText.assign(utf8str_symbol_truncate(truncated_utf8, mMaxLengthChars));
|
||||
}
|
||||
|
||||
if (all_selected)
|
||||
|
|
|
|||
|
|
@ -177,6 +177,7 @@ LLTextBase::LLTextBase(const LLTextBase::Params &p)
|
|||
: LLUICtrl(p, LLTextViewModelPtr(new LLTextViewModel)),
|
||||
mURLClickSignal(NULL),
|
||||
mIsFriendSignal(NULL),
|
||||
mIsObjectBlockedSignal(NULL),
|
||||
mMaxTextByteLength( p.max_text_length ),
|
||||
mFont(p.font),
|
||||
mFontShadow(p.font_shadow),
|
||||
|
|
@ -268,6 +269,8 @@ LLTextBase::~LLTextBase()
|
|||
{
|
||||
mSegments.clear();
|
||||
delete mURLClickSignal;
|
||||
delete mIsFriendSignal;
|
||||
delete mIsObjectBlockedSignal;
|
||||
}
|
||||
|
||||
void LLTextBase::initFromParams(const LLTextBase::Params& p)
|
||||
|
|
@ -1942,6 +1945,7 @@ void LLTextBase::createUrlContextMenu(S32 x, S32 y, const std::string &in_url)
|
|||
registrar.add("Url.OpenExternal", boost::bind(&LLUrlAction::openURLExternal, url));
|
||||
registrar.add("Url.Execute", boost::bind(&LLUrlAction::executeSLURL, url, true));
|
||||
registrar.add("Url.Block", boost::bind(&LLUrlAction::blockObject, url));
|
||||
registrar.add("Url.Unblock", boost::bind(&LLUrlAction::unblockObject, url));
|
||||
registrar.add("Url.Teleport", boost::bind(&LLUrlAction::teleportToLocation, url));
|
||||
registrar.add("Url.ShowProfile", boost::bind(&LLUrlAction::showProfile, url));
|
||||
registrar.add("Url.AddFriend", boost::bind(&LLUrlAction::addFriend, url));
|
||||
|
|
@ -1968,6 +1972,19 @@ void LLTextBase::createUrlContextMenu(S32 x, S32 y, const std::string &in_url)
|
|||
removeFriendButton->setEnabled(isFriend);
|
||||
}
|
||||
}
|
||||
|
||||
if (mIsObjectBlockedSignal)
|
||||
{
|
||||
bool is_blocked = *(*mIsObjectBlockedSignal)(LLUUID(LLUrlAction::getObjectId(url)), LLUrlAction::getObjectName(url));
|
||||
LLView* blockButton = mPopupMenu->getChild<LLView>("block_object");
|
||||
LLView* unblockButton = mPopupMenu->getChild<LLView>("unblock_object");
|
||||
|
||||
if (blockButton && unblockButton)
|
||||
{
|
||||
blockButton->setVisible(!is_blocked);
|
||||
unblockButton->setVisible(is_blocked);
|
||||
}
|
||||
}
|
||||
|
||||
if (mPopupMenu)
|
||||
{
|
||||
|
|
@ -3022,6 +3039,15 @@ boost::signals2::connection LLTextBase::setIsFriendCallback(const is_friend_sign
|
|||
return mIsFriendSignal->connect(cb);
|
||||
}
|
||||
|
||||
boost::signals2::connection LLTextBase::setIsObjectBlockedCallback(const is_blocked_signal_t::slot_type& cb)
|
||||
{
|
||||
if (!mIsObjectBlockedSignal)
|
||||
{
|
||||
mIsObjectBlockedSignal = new is_blocked_signal_t();
|
||||
}
|
||||
return mIsObjectBlockedSignal->connect(cb);
|
||||
}
|
||||
|
||||
//
|
||||
// LLTextSegment
|
||||
//
|
||||
|
|
|
|||
|
|
@ -270,6 +270,7 @@ public:
|
|||
friend class LLUICtrlFactory;
|
||||
|
||||
typedef boost::signals2::signal<bool (const LLUUID& user_id)> is_friend_signal_t;
|
||||
typedef boost::signals2::signal<bool (const LLUUID& blocked_id, const std::string from)> is_blocked_signal_t;
|
||||
|
||||
struct LineSpacingParams : public LLInitParam::ChoiceBlock<LineSpacingParams>
|
||||
{
|
||||
|
|
@ -456,6 +457,7 @@ public:
|
|||
virtual void appendWidget(const LLInlineViewSegment::Params& params, const std::string& text, bool allow_undo);
|
||||
boost::signals2::connection setURLClickedCallback(const commit_signal_t::slot_type& cb);
|
||||
boost::signals2::connection setIsFriendCallback(const is_friend_signal_t::slot_type& cb);
|
||||
boost::signals2::connection setIsObjectBlockedCallback(const is_blocked_signal_t::slot_type& cb);
|
||||
|
||||
void setWordWrap(bool wrap);
|
||||
LLScrollContainer* getScrollContainer() const { return mScroller; }
|
||||
|
|
@ -685,6 +687,7 @@ protected:
|
|||
|
||||
// Used to check if user with given ID is avatar's friend
|
||||
is_friend_signal_t* mIsFriendSignal;
|
||||
is_blocked_signal_t* mIsObjectBlockedSignal;
|
||||
|
||||
LLUIString mLabel; // text label that is visible when no user text provided
|
||||
};
|
||||
|
|
|
|||
|
|
@ -56,6 +56,26 @@ void LLTextUtil::textboxSetHighlightedVal(LLTextBox *txtbox, const LLStyle::Para
|
|||
txtbox->appendText(text.substr(hl_begin + hl_len), false, normal_style);
|
||||
}
|
||||
|
||||
void LLTextUtil::textboxSetGreyedVal(LLTextBox *txtbox, const LLStyle::Params& normal_style, const std::string& text, const std::string& greyed)
|
||||
{
|
||||
static LLUIColor sGreyedTextColor = LLUIColorTable::instance().getColor("Gray", LLColor4::grey);
|
||||
|
||||
size_t greyed_begin = 0, greyed_len = greyed.size();
|
||||
|
||||
if (greyed_len == 0 || (greyed_begin = text.find(greyed)) == std::string::npos)
|
||||
{
|
||||
txtbox->setText(text, normal_style);
|
||||
return;
|
||||
}
|
||||
|
||||
LLStyle::Params greyed_style = normal_style;
|
||||
greyed_style.color = sGreyedTextColor;
|
||||
txtbox->setText(LLStringUtil::null); // clear text
|
||||
txtbox->appendText(text.substr(0, greyed_begin), false, normal_style);
|
||||
txtbox->appendText(text.substr(greyed_begin, greyed_len), false, greyed_style);
|
||||
txtbox->appendText(text.substr(greyed_begin + greyed_len), false, normal_style);
|
||||
}
|
||||
|
||||
const std::string& LLTextUtil::formatPhoneNumber(const std::string& phone_str)
|
||||
{
|
||||
static const std::string PHONE_SEPARATOR = LLUI::sSettingGroups["config"]->getString("AvalinePhoneSeparator");
|
||||
|
|
|
|||
|
|
@ -52,6 +52,12 @@ namespace LLTextUtil
|
|||
const std::string& text,
|
||||
const std::string& hl);
|
||||
|
||||
void textboxSetGreyedVal(
|
||||
LLTextBox *txtbox,
|
||||
const LLStyle::Params& normal_style,
|
||||
const std::string& text,
|
||||
const std::string& greyed);
|
||||
|
||||
/**
|
||||
* Formats passed phone number to be more human readable.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -231,3 +231,13 @@ void LLUrlAction::blockObject(std::string url)
|
|||
executeSLURL("secondlife:///app/agent/" + object_id + "/block/" + LLURI::escape(object_name));
|
||||
}
|
||||
}
|
||||
|
||||
void LLUrlAction::unblockObject(std::string url)
|
||||
{
|
||||
std::string object_id = getObjectId(url);
|
||||
std::string object_name = getObjectName(url);
|
||||
if (LLUUID::validate(object_id))
|
||||
{
|
||||
executeSLURL("secondlife:///app/agent/" + object_id + "/unblock/" + object_name);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -83,6 +83,7 @@ public:
|
|||
static void addFriend(std::string url);
|
||||
static void removeFriend(std::string url);
|
||||
static void blockObject(std::string url);
|
||||
static void unblockObject(std::string url);
|
||||
|
||||
/// specify the callbacks to enable this class's functionality
|
||||
typedef boost::function<void (const std::string&)> url_callback_t;
|
||||
|
|
|
|||
|
|
@ -588,6 +588,11 @@ void LLView::onVisibilityChange ( BOOL new_visibility )
|
|||
BOOL log_visibility_change = LLViewerEventRecorder::instance().getLoggingStatus();
|
||||
BOOST_FOREACH(LLView* viewp, mChildList)
|
||||
{
|
||||
if (!viewp)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// only views that are themselves visible will have their overall visibility affected by their ancestors
|
||||
old_visibility=viewp->getVisible();
|
||||
|
||||
|
|
@ -807,7 +812,7 @@ LLView* LLView::childrenHandleHover(S32 x, S32 y, MASK mask)
|
|||
LLView* LLView::childFromPoint(S32 x, S32 y, bool recur)
|
||||
{
|
||||
if (!getVisible())
|
||||
return false;
|
||||
return NULL;
|
||||
|
||||
BOOST_FOREACH(LLView* viewp, mChildList)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@
|
|||
|
||||
@property (retain) NSString *currentInputLanguage;
|
||||
|
||||
- (void) mainLoop;
|
||||
- (void) oneFrame;
|
||||
- (void) showInputWindow:(bool)show withEvent:(NSEvent*)textEvent;
|
||||
- (void) languageUpdated;
|
||||
- (bool) romanScript;
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ typedef const NativeKeyEventData * NSKeyEventRef;
|
|||
// These are defined in llappviewermacosx.cpp.
|
||||
bool initViewer();
|
||||
void handleQuit();
|
||||
bool runMainLoop();
|
||||
bool pumpMainLoop();
|
||||
void initMainLoop();
|
||||
void cleanupViewer();
|
||||
void handleUrl(const char* url);
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ void LLCrashLoggerMac::gatherPlatformSpecificFiles()
|
|||
{
|
||||
}
|
||||
|
||||
bool LLCrashLoggerMac::mainLoop()
|
||||
bool LLCrashLoggerMac::frame()
|
||||
{
|
||||
|
||||
if (mCrashBehavior == CRASH_BEHAVIOR_ALWAYS_SEND)
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ public:
|
|||
LLCrashLoggerMac(void);
|
||||
~LLCrashLoggerMac(void);
|
||||
virtual bool init();
|
||||
virtual bool mainLoop();
|
||||
virtual bool frame();
|
||||
virtual bool cleanup();
|
||||
virtual void gatherPlatformSpecificFiles();
|
||||
};
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ int main(int argc, char **argv)
|
|||
{
|
||||
// return NSApplicationMain(argc, (const char **)argv);
|
||||
}
|
||||
app.mainLoop();
|
||||
app.frame();
|
||||
app.cleanup();
|
||||
|
||||
LL_INFOS() << "Crash reporter finished normally." << LL_ENDL;
|
||||
|
|
|
|||
|
|
@ -4,15 +4,18 @@ add_subdirectory(base)
|
|||
|
||||
if (LINUX)
|
||||
add_subdirectory(gstreamer010)
|
||||
add_subdirectory(libvlc)
|
||||
endif (LINUX)
|
||||
|
||||
if (WINDOWS OR DARWIN)
|
||||
if (DARWIN)
|
||||
add_subdirectory(quicktime)
|
||||
add_subdirectory(cef)
|
||||
endif (WINDOWS OR DARWIN)
|
||||
endif (DARWIN)
|
||||
|
||||
if (WINDOWS)
|
||||
add_subdirectory(cef)
|
||||
add_subdirectory(winmmshim)
|
||||
add_subdirectory(libvlc)
|
||||
endif (WINDOWS)
|
||||
|
||||
### add_subdirectory(example)
|
||||
|
|
|
|||
|
|
@ -100,6 +100,12 @@ private:
|
|||
LLCEFLib* mLLCEFLib;
|
||||
|
||||
VolumeCatcher mVolumeCatcher;
|
||||
|
||||
U8 *mPopupBuffer;
|
||||
U32 mPopupW;
|
||||
U32 mPopupH;
|
||||
U32 mPopupX;
|
||||
U32 mPopupY;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -127,12 +133,19 @@ MediaPluginBase(host_send_func, host_user_data)
|
|||
mCookiePath = "";
|
||||
mPickedFile = "";
|
||||
mLLCEFLib = new LLCEFLib();
|
||||
|
||||
mPopupBuffer = NULL;
|
||||
mPopupW = 0;
|
||||
mPopupH = 0;
|
||||
mPopupX = 0;
|
||||
mPopupY = 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
MediaPluginCEF::~MediaPluginCEF()
|
||||
{
|
||||
delete[] mPopupBuffer;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -155,20 +168,28 @@ void MediaPluginCEF::postDebugMessage(const std::string& msg)
|
|||
//
|
||||
void MediaPluginCEF::onPageChangedCallback(unsigned char* pixels, int x, int y, int width, int height, bool is_popup)
|
||||
{
|
||||
if (mPixels && pixels)
|
||||
if( is_popup )
|
||||
{
|
||||
delete mPopupBuffer;
|
||||
mPopupBuffer = NULL;
|
||||
mPopupH = 0;
|
||||
mPopupW = 0;
|
||||
mPopupX = 0;
|
||||
mPopupY = 0;
|
||||
}
|
||||
|
||||
if( mPixels && pixels )
|
||||
{
|
||||
if (is_popup)
|
||||
{
|
||||
for (int line = 0; line < height; ++line)
|
||||
if( width > 0 && height> 0 )
|
||||
{
|
||||
int inverted_y = mHeight - y - height;
|
||||
int src = line * width * mDepth;
|
||||
int dst = (inverted_y + line) * mWidth * mDepth + x * mDepth;
|
||||
|
||||
if (dst + width * mDepth < mWidth * mHeight * mDepth)
|
||||
{
|
||||
memcpy(mPixels + dst, pixels + src, width * mDepth);
|
||||
}
|
||||
mPopupBuffer = new U8[ width * height * mDepth ];
|
||||
memcpy( mPopupBuffer, pixels, width * height * mDepth );
|
||||
mPopupH = height;
|
||||
mPopupW = width;
|
||||
mPopupX = x;
|
||||
mPopupY = mHeight - y - height;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
@ -177,6 +198,23 @@ void MediaPluginCEF::onPageChangedCallback(unsigned char* pixels, int x, int y,
|
|||
{
|
||||
memcpy(mPixels, pixels, mWidth * mHeight * mDepth);
|
||||
}
|
||||
if( mPopupBuffer && mPopupH && mPopupW )
|
||||
{
|
||||
U32 bufferSize = mWidth * mHeight * mDepth;
|
||||
U32 popupStride = mPopupW * mDepth;
|
||||
U32 bufferStride = mWidth * mDepth;
|
||||
int dstY = mPopupY;
|
||||
|
||||
int src = 0;
|
||||
int dst = dstY * mWidth * mDepth + mPopupX * mDepth;
|
||||
|
||||
for( int line = 0; dst + popupStride < bufferSize && line < mPopupH; ++line )
|
||||
{
|
||||
memcpy( mPixels + dst, mPopupBuffer + src, popupStride );
|
||||
src += popupStride;
|
||||
dst += bufferStride;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
setDirty(0, 0, mWidth, mHeight);
|
||||
|
|
@ -559,6 +597,8 @@ void MediaPluginCEF::receiveMessage(const char* message_string)
|
|||
S32 x = message_in.getValueS32("x");
|
||||
S32 y = message_in.getValueS32("y");
|
||||
|
||||
y = mHeight - y;
|
||||
|
||||
// only even send left mouse button events to LLCEFLib
|
||||
// (partially prompted by crash in OS X CEF when sending right button events)
|
||||
// we catch the right click in viewer and display our own context menu anyway
|
||||
|
|
|
|||
|
|
@ -0,0 +1,86 @@
|
|||
# -*- cmake -*-
|
||||
|
||||
project(media_plugin_libvlc)
|
||||
|
||||
include(00-Common)
|
||||
include(LLCommon)
|
||||
include(LLImage)
|
||||
include(LLPlugin)
|
||||
include(LLMath)
|
||||
include(LLRender)
|
||||
include(LLWindow)
|
||||
include(Linking)
|
||||
include(PluginAPI)
|
||||
include(MediaPluginBase)
|
||||
include(OpenGL)
|
||||
|
||||
include(LibVLCPlugin)
|
||||
|
||||
include_directories(
|
||||
${LLPLUGIN_INCLUDE_DIRS}
|
||||
${MEDIA_PLUGIN_BASE_INCLUDE_DIRS}
|
||||
${LLCOMMON_INCLUDE_DIRS}
|
||||
${LLMATH_INCLUDE_DIRS}
|
||||
${LLIMAGE_INCLUDE_DIRS}
|
||||
${LLRENDER_INCLUDE_DIRS}
|
||||
${LLWINDOW_INCLUDE_DIRS}
|
||||
${VLC_INCLUDE_DIR}
|
||||
)
|
||||
include_directories(SYSTEM
|
||||
${LLCOMMON_SYSTEM_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
|
||||
### media_plugin_libvlc
|
||||
|
||||
if(NOT WORD_SIZE EQUAL 32)
|
||||
if(WINDOWS)
|
||||
add_definitions(/FIXED:NO)
|
||||
else(WINDOWS) # not windows therefore gcc LINUX and DARWIN
|
||||
add_definitions(-fPIC)
|
||||
endif(WINDOWS)
|
||||
endif(NOT WORD_SIZE EQUAL 32)
|
||||
|
||||
set(media_plugin_libvlc_SOURCE_FILES
|
||||
media_plugin_libvlc.cpp
|
||||
)
|
||||
|
||||
add_library(media_plugin_libvlc
|
||||
SHARED
|
||||
${media_plugin_libvlc_SOURCE_FILES}
|
||||
)
|
||||
|
||||
target_link_libraries(media_plugin_libvlc
|
||||
${LLPLUGIN_LIBRARIES}
|
||||
${MEDIA_PLUGIN_BASE_LIBRARIES}
|
||||
${LLCOMMON_LIBRARIES}
|
||||
${VLC_PLUGIN_LIBRARIES}
|
||||
${PLUGIN_API_WINDOWS_LIBRARIES}
|
||||
)
|
||||
|
||||
add_dependencies(media_plugin_libvlc
|
||||
${LLPLUGIN_LIBRARIES}
|
||||
${MEDIA_PLUGIN_BASE_LIBRARIES}
|
||||
${LLCOMMON_LIBRARIES}
|
||||
)
|
||||
|
||||
if (WINDOWS)
|
||||
set_target_properties(
|
||||
media_plugin_libvlc
|
||||
PROPERTIES
|
||||
LINK_FLAGS "/MANIFEST:NO /SAFESEH:NO /LTCG /NODEFAULTLIB:LIBCMT"
|
||||
)
|
||||
endif (WINDOWS)
|
||||
|
||||
if (DARWIN)
|
||||
# Don't prepend 'lib' to the executable name, and don't embed a full path in the library's install name
|
||||
set_target_properties(
|
||||
media_plugin_libvlc
|
||||
PROPERTIES
|
||||
PREFIX ""
|
||||
BUILD_WITH_INSTALL_RPATH 1
|
||||
INSTALL_NAME_DIR "@executable_path"
|
||||
LINK_FLAGS "-exported_symbols_list ${CMAKE_CURRENT_SOURCE_DIR}/../base/media_plugin_base.exp"
|
||||
)
|
||||
|
||||
endif (DARWIN)
|
||||
|
|
@ -0,0 +1,618 @@
|
|||
/**
|
||||
* @file media_plugin_libvlc.cpp
|
||||
* @brief LibVLC plugin for LLMedia API plugin system
|
||||
*
|
||||
* @cond
|
||||
* $LicenseInfo:firstyear=2008&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
* @endcond
|
||||
*/
|
||||
|
||||
#include "linden_common.h"
|
||||
|
||||
#include "llgl.h"
|
||||
#include "llplugininstance.h"
|
||||
#include "llpluginmessage.h"
|
||||
#include "llpluginmessageclasses.h"
|
||||
#include "media_plugin_base.h"
|
||||
|
||||
#include "vlc/vlc.h"
|
||||
#include "vlc/libvlc_version.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
class MediaPluginLibVLC :
|
||||
public MediaPluginBase
|
||||
{
|
||||
public:
|
||||
MediaPluginLibVLC(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data);
|
||||
~MediaPluginLibVLC();
|
||||
|
||||
/*virtual*/ void receiveMessage(const char* message_string);
|
||||
|
||||
private:
|
||||
bool init();
|
||||
|
||||
void initVLC();
|
||||
void playMedia();
|
||||
void resetVLC();
|
||||
void setVolume(const F64 volume);
|
||||
void updateTitle(const char* title);
|
||||
|
||||
static void* lock(void* data, void** p_pixels);
|
||||
static void unlock(void* data, void* id, void* const* raw_pixels);
|
||||
static void display(void* data, void* id);
|
||||
|
||||
/*virtual*/ void setDirty(int left, int top, int right, int bottom) /* override, but that is not supported in gcc 4.6 */;
|
||||
|
||||
static void eventCallbacks(const libvlc_event_t* event, void* ptr);
|
||||
|
||||
libvlc_instance_t* mLibVLC;
|
||||
libvlc_media_t* mLibVLCMedia;
|
||||
libvlc_media_player_t* mLibVLCMediaPlayer;
|
||||
|
||||
struct mLibVLCContext
|
||||
{
|
||||
unsigned char* texture_pixels;
|
||||
libvlc_media_player_t* mp;
|
||||
MediaPluginLibVLC* parent;
|
||||
};
|
||||
struct mLibVLCContext mLibVLCCallbackContext;
|
||||
|
||||
std::string mURL;
|
||||
F64 mCurVolume;
|
||||
|
||||
bool mIsLooping;
|
||||
|
||||
float mCurTime;
|
||||
float mDuration;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
MediaPluginLibVLC::MediaPluginLibVLC(LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data) :
|
||||
MediaPluginBase(host_send_func, host_user_data)
|
||||
{
|
||||
mTextureWidth = 0;
|
||||
mTextureHeight = 0;
|
||||
mWidth = 0;
|
||||
mHeight = 0;
|
||||
mDepth = 4;
|
||||
mPixels = 0;
|
||||
|
||||
mLibVLC = 0;
|
||||
mLibVLCMedia = 0;
|
||||
mLibVLCMediaPlayer = 0;
|
||||
|
||||
mCurVolume = 0.0;
|
||||
|
||||
mIsLooping = false;
|
||||
|
||||
mCurTime = 0.0;
|
||||
mDuration = 0.0;
|
||||
|
||||
mURL = std::string();
|
||||
|
||||
setStatus(STATUS_NONE);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
MediaPluginLibVLC::~MediaPluginLibVLC()
|
||||
{
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
void* MediaPluginLibVLC::lock(void* data, void** p_pixels)
|
||||
{
|
||||
struct mLibVLCContext* context = (mLibVLCContext*)data;
|
||||
|
||||
*p_pixels = context->texture_pixels;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
void MediaPluginLibVLC::unlock(void* data, void* id, void* const* raw_pixels)
|
||||
{
|
||||
// nothing to do here for the moment
|
||||
// we *could* modify pixels here to, for example, Y flip, but this is done with
|
||||
// a VLC video filter transform.
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
void MediaPluginLibVLC::display(void* data, void* id)
|
||||
{
|
||||
struct mLibVLCContext* context = (mLibVLCContext*)data;
|
||||
|
||||
context->parent->setDirty(0, 0, context->parent->mWidth, context->parent->mHeight);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
void MediaPluginLibVLC::initVLC()
|
||||
{
|
||||
char const* vlc_argv[] =
|
||||
{
|
||||
"--no-xlib",
|
||||
"--video-filter=transform{type=vflip}", // MAINT-6578 Y flip textures in plugin vs client
|
||||
};
|
||||
|
||||
int vlc_argc = sizeof(vlc_argv) / sizeof(*vlc_argv);
|
||||
mLibVLC = libvlc_new(vlc_argc, vlc_argv);
|
||||
|
||||
if (!mLibVLC)
|
||||
{
|
||||
// for the moment, if this fails, the plugin will fail and
|
||||
// the media sub-system will tell the viewer something went wrong.
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
void MediaPluginLibVLC::resetVLC()
|
||||
{
|
||||
libvlc_media_player_stop(mLibVLCMediaPlayer);
|
||||
libvlc_media_player_release(mLibVLCMediaPlayer);
|
||||
libvlc_release(mLibVLC);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// *virtual*
|
||||
void MediaPluginLibVLC::setDirty(int left, int top, int right, int bottom)
|
||||
{
|
||||
LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "updated");
|
||||
|
||||
message.setValueS32("left", left);
|
||||
message.setValueS32("top", top);
|
||||
message.setValueS32("right", right);
|
||||
message.setValueS32("bottom", bottom);
|
||||
|
||||
message.setValueReal("current_time", mCurTime);
|
||||
message.setValueReal("duration", mDuration);
|
||||
message.setValueReal("current_rate", 1.0f);
|
||||
|
||||
sendMessage(message);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
void MediaPluginLibVLC::eventCallbacks(const libvlc_event_t* event, void* ptr)
|
||||
{
|
||||
MediaPluginLibVLC* parent = (MediaPluginLibVLC*)ptr;
|
||||
if (parent == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
switch (event->type)
|
||||
{
|
||||
case libvlc_MediaPlayerOpening:
|
||||
parent->setStatus(STATUS_LOADING);
|
||||
break;
|
||||
|
||||
case libvlc_MediaPlayerPlaying:
|
||||
parent->mDuration = (float)(libvlc_media_get_duration(parent->mLibVLCMedia)) / 1000.0f;
|
||||
parent->setStatus(STATUS_PLAYING);
|
||||
break;
|
||||
|
||||
case libvlc_MediaPlayerPaused:
|
||||
parent->setStatus(STATUS_PAUSED);
|
||||
break;
|
||||
|
||||
case libvlc_MediaPlayerStopped:
|
||||
parent->setStatus(STATUS_DONE);
|
||||
break;
|
||||
|
||||
case libvlc_MediaPlayerEndReached:
|
||||
parent->setStatus(STATUS_DONE);
|
||||
break;
|
||||
|
||||
case libvlc_MediaPlayerEncounteredError:
|
||||
parent->setStatus(STATUS_ERROR);
|
||||
break;
|
||||
|
||||
case libvlc_MediaPlayerTimeChanged:
|
||||
parent->mCurTime = (float)libvlc_media_player_get_time(parent->mLibVLCMediaPlayer) / 1000.0f;
|
||||
break;
|
||||
|
||||
case libvlc_MediaPlayerPositionChanged:
|
||||
break;
|
||||
|
||||
case libvlc_MediaPlayerLengthChanged:
|
||||
parent->mDuration = (float)libvlc_media_get_duration(parent->mLibVLCMedia) / 1000.0f;
|
||||
break;
|
||||
|
||||
case libvlc_MediaPlayerTitleChanged:
|
||||
{
|
||||
char* title = libvlc_media_get_meta(parent->mLibVLCMedia, libvlc_meta_Title);
|
||||
if (title)
|
||||
{
|
||||
parent->updateTitle(title);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
void MediaPluginLibVLC::playMedia()
|
||||
{
|
||||
if (mURL.length() == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (mLibVLCMediaPlayer)
|
||||
{
|
||||
// stop listening to events while we reset things
|
||||
libvlc_event_manager_t* em = libvlc_media_player_event_manager(mLibVLCMediaPlayer);
|
||||
if (em)
|
||||
{
|
||||
libvlc_event_detach(em, libvlc_MediaPlayerOpening, eventCallbacks, NULL);
|
||||
libvlc_event_detach(em, libvlc_MediaPlayerPlaying, eventCallbacks, NULL);
|
||||
libvlc_event_detach(em, libvlc_MediaPlayerPaused, eventCallbacks, NULL);
|
||||
libvlc_event_detach(em, libvlc_MediaPlayerStopped, eventCallbacks, NULL);
|
||||
libvlc_event_detach(em, libvlc_MediaPlayerEndReached, eventCallbacks, NULL);
|
||||
libvlc_event_detach(em, libvlc_MediaPlayerEncounteredError, eventCallbacks, NULL);
|
||||
libvlc_event_detach(em, libvlc_MediaPlayerTimeChanged, eventCallbacks, NULL);
|
||||
libvlc_event_detach(em, libvlc_MediaPlayerPositionChanged, eventCallbacks, NULL);
|
||||
libvlc_event_detach(em, libvlc_MediaPlayerLengthChanged, eventCallbacks, NULL);
|
||||
libvlc_event_detach(em, libvlc_MediaPlayerTitleChanged, eventCallbacks, NULL);
|
||||
};
|
||||
|
||||
libvlc_media_player_stop(mLibVLCMediaPlayer);
|
||||
libvlc_media_player_release(mLibVLCMediaPlayer);
|
||||
|
||||
mLibVLCMediaPlayer = 0;
|
||||
}
|
||||
|
||||
if (mLibVLCMedia)
|
||||
{
|
||||
libvlc_media_release(mLibVLCMedia);
|
||||
|
||||
mLibVLCMedia = 0;
|
||||
}
|
||||
|
||||
mLibVLCMedia = libvlc_media_new_location(mLibVLC, mURL.c_str());
|
||||
if (!mLibVLCMedia)
|
||||
{
|
||||
mLibVLCMediaPlayer = 0;
|
||||
setStatus(STATUS_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
mLibVLCMediaPlayer = libvlc_media_player_new_from_media(mLibVLCMedia);
|
||||
if (!mLibVLCMediaPlayer)
|
||||
{
|
||||
setStatus(STATUS_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
// listen to events
|
||||
libvlc_event_manager_t* em = libvlc_media_player_event_manager(mLibVLCMediaPlayer);
|
||||
if (em)
|
||||
{
|
||||
libvlc_event_attach(em, libvlc_MediaPlayerOpening, eventCallbacks, this);
|
||||
libvlc_event_attach(em, libvlc_MediaPlayerPlaying, eventCallbacks, this);
|
||||
libvlc_event_attach(em, libvlc_MediaPlayerPaused, eventCallbacks, this);
|
||||
libvlc_event_attach(em, libvlc_MediaPlayerStopped, eventCallbacks, this);
|
||||
libvlc_event_attach(em, libvlc_MediaPlayerEndReached, eventCallbacks, this);
|
||||
libvlc_event_attach(em, libvlc_MediaPlayerEncounteredError, eventCallbacks, this);
|
||||
libvlc_event_attach(em, libvlc_MediaPlayerTimeChanged, eventCallbacks, this);
|
||||
libvlc_event_attach(em, libvlc_MediaPlayerPositionChanged, eventCallbacks, this);
|
||||
libvlc_event_attach(em, libvlc_MediaPlayerLengthChanged, eventCallbacks, this);
|
||||
libvlc_event_attach(em, libvlc_MediaPlayerTitleChanged, eventCallbacks, this);
|
||||
}
|
||||
|
||||
mLibVLCCallbackContext.parent = this;
|
||||
mLibVLCCallbackContext.texture_pixels = mPixels;
|
||||
mLibVLCCallbackContext.mp = mLibVLCMediaPlayer;
|
||||
|
||||
// Send a "navigate begin" event.
|
||||
// This is really a browser message but the QuickTime plugin did it and
|
||||
// the media system relies on this message to update internal state so we must send it too
|
||||
// Note: see "navigate_complete" message below too
|
||||
// https://jira.secondlife.com/browse/MAINT-6528
|
||||
LLPluginMessage message_begin(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "navigate_begin");
|
||||
message_begin.setValue("uri", mURL);
|
||||
message_begin.setValueBoolean("history_back_available", false);
|
||||
message_begin.setValueBoolean("history_forward_available", false);
|
||||
sendMessage(message_begin);
|
||||
|
||||
// volume level gets set before VLC is initialized (thanks media system) so we have to record
|
||||
// it in mCurVolume and set it again here so that volume levels are correctly initialized
|
||||
setVolume(mCurVolume);
|
||||
|
||||
setStatus(STATUS_LOADED);
|
||||
|
||||
libvlc_video_set_callbacks(mLibVLCMediaPlayer, lock, unlock, display, &mLibVLCCallbackContext);
|
||||
libvlc_video_set_format(mLibVLCMediaPlayer, "RV32", mWidth, mHeight, mWidth * mDepth);
|
||||
|
||||
// note this relies on the "set_loop" message arriving before the "start" (play) one
|
||||
// but that appears to always be the case
|
||||
if (mIsLooping)
|
||||
{
|
||||
libvlc_media_add_option(mLibVLCMedia, "input-repeat=-1");
|
||||
}
|
||||
|
||||
libvlc_media_player_play(mLibVLCMediaPlayer);
|
||||
|
||||
// send a "location_changed" message - this informs the media system
|
||||
// that a new URL is the 'current' one and is used extensively.
|
||||
// Again, this is really a browser message but we will use it here.
|
||||
LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "location_changed");
|
||||
message.setValue("uri", mURL);
|
||||
sendMessage(message);
|
||||
|
||||
// Send a "navigate complete" event.
|
||||
// This is really a browser message but the QuickTime plugin did it and
|
||||
// the media system relies on this message to update internal state so we must send it too
|
||||
// Note: see "navigate_begin" message above too
|
||||
// https://jira.secondlife.com/browse/MAINT-6528
|
||||
LLPluginMessage message_complete(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "navigate_complete");
|
||||
message_complete.setValue("uri", mURL);
|
||||
message_complete.setValueS32("result_code", 200);
|
||||
message_complete.setValue("result_string", "OK");
|
||||
sendMessage(message_complete);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
void MediaPluginLibVLC::updateTitle(const char* title)
|
||||
{
|
||||
LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "name_text");
|
||||
message.setValue("name", title);
|
||||
sendMessage(message);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
void MediaPluginLibVLC::setVolume(const F64 volume)
|
||||
{
|
||||
mCurVolume = volume;
|
||||
|
||||
if (mLibVLCMediaPlayer)
|
||||
{
|
||||
int result = libvlc_audio_set_volume(mLibVLCMediaPlayer, (int)(volume * 100));
|
||||
if (result != 0)
|
||||
{
|
||||
// volume wasn't set but not much to be done here
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// volume change was requested but VLC wasn't ready.
|
||||
// that's okay thought because we saved the value in mCurVolume and
|
||||
// the next volume change after the VLC system is initilzied will set it
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
void MediaPluginLibVLC::receiveMessage(const char* message_string)
|
||||
{
|
||||
LLPluginMessage message_in;
|
||||
|
||||
if (message_in.parse(message_string) >= 0)
|
||||
{
|
||||
std::string message_class = message_in.getClass();
|
||||
std::string message_name = message_in.getName();
|
||||
if (message_class == LLPLUGIN_MESSAGE_CLASS_BASE)
|
||||
{
|
||||
if (message_name == "init")
|
||||
{
|
||||
initVLC();
|
||||
|
||||
LLPluginMessage message("base", "init_response");
|
||||
LLSD versions = LLSD::emptyMap();
|
||||
versions[LLPLUGIN_MESSAGE_CLASS_BASE] = LLPLUGIN_MESSAGE_CLASS_BASE_VERSION;
|
||||
versions[LLPLUGIN_MESSAGE_CLASS_MEDIA] = LLPLUGIN_MESSAGE_CLASS_MEDIA_VERSION;
|
||||
versions[LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME] = LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME_VERSION;
|
||||
message.setValueLLSD("versions", versions);
|
||||
|
||||
std::ostringstream s;
|
||||
s << "LibVLC plugin ";
|
||||
s << LIBVLC_VERSION_MAJOR;
|
||||
s << ".";
|
||||
s << LIBVLC_VERSION_MINOR;
|
||||
s << ".";
|
||||
s << LIBVLC_VERSION_REVISION;
|
||||
|
||||
message.setValue("plugin_version", s.str());
|
||||
sendMessage(message);
|
||||
}
|
||||
else if (message_name == "idle")
|
||||
{
|
||||
}
|
||||
else if (message_name == "cleanup")
|
||||
{
|
||||
resetVLC();
|
||||
}
|
||||
else if (message_name == "shm_added")
|
||||
{
|
||||
SharedSegmentInfo info;
|
||||
info.mAddress = message_in.getValuePointer("address");
|
||||
info.mSize = (size_t)message_in.getValueS32("size");
|
||||
std::string name = message_in.getValue("name");
|
||||
|
||||
mSharedSegments.insert(SharedSegmentMap::value_type(name, info));
|
||||
|
||||
}
|
||||
else if (message_name == "shm_remove")
|
||||
{
|
||||
std::string name = message_in.getValue("name");
|
||||
|
||||
SharedSegmentMap::iterator iter = mSharedSegments.find(name);
|
||||
if (iter != mSharedSegments.end())
|
||||
{
|
||||
if (mPixels == iter->second.mAddress)
|
||||
{
|
||||
libvlc_media_player_stop(mLibVLCMediaPlayer);
|
||||
libvlc_media_player_release(mLibVLCMediaPlayer);
|
||||
mLibVLCMediaPlayer = 0;
|
||||
|
||||
mPixels = NULL;
|
||||
mTextureSegmentName.clear();
|
||||
}
|
||||
mSharedSegments.erase(iter);
|
||||
}
|
||||
else
|
||||
{
|
||||
//std::cerr << "MediaPluginWebKit::receiveMessage: unknown shared memory region!" << std::endl;
|
||||
}
|
||||
|
||||
// Send the response so it can be cleaned up.
|
||||
LLPluginMessage message("base", "shm_remove_response");
|
||||
message.setValue("name", name);
|
||||
sendMessage(message);
|
||||
}
|
||||
else
|
||||
{
|
||||
//std::cerr << "MediaPluginWebKit::receiveMessage: unknown base message: " << message_name << std::endl;
|
||||
}
|
||||
}
|
||||
else if (message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA)
|
||||
{
|
||||
if (message_name == "init")
|
||||
{
|
||||
LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "texture_params");
|
||||
message.setValueS32("default_width", 1024);
|
||||
message.setValueS32("default_height", 1024);
|
||||
message.setValueS32("depth", mDepth);
|
||||
message.setValueU32("internalformat", GL_RGB);
|
||||
message.setValueU32("format", GL_BGRA_EXT);
|
||||
message.setValueU32("type", GL_UNSIGNED_BYTE);
|
||||
message.setValueBoolean("coords_opengl", true);
|
||||
sendMessage(message);
|
||||
}
|
||||
else if (message_name == "size_change")
|
||||
{
|
||||
std::string name = message_in.getValue("name");
|
||||
S32 width = message_in.getValueS32("width");
|
||||
S32 height = message_in.getValueS32("height");
|
||||
S32 texture_width = message_in.getValueS32("texture_width");
|
||||
S32 texture_height = message_in.getValueS32("texture_height");
|
||||
|
||||
if (!name.empty())
|
||||
{
|
||||
// Find the shared memory region with this name
|
||||
SharedSegmentMap::iterator iter = mSharedSegments.find(name);
|
||||
if (iter != mSharedSegments.end())
|
||||
{
|
||||
mPixels = (unsigned char*)iter->second.mAddress;
|
||||
mWidth = width;
|
||||
mHeight = height;
|
||||
mTextureWidth = texture_width;
|
||||
mTextureHeight = texture_height;
|
||||
|
||||
playMedia();
|
||||
};
|
||||
};
|
||||
|
||||
LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change_response");
|
||||
message.setValue("name", name);
|
||||
message.setValueS32("width", width);
|
||||
message.setValueS32("height", height);
|
||||
message.setValueS32("texture_width", texture_width);
|
||||
message.setValueS32("texture_height", texture_height);
|
||||
sendMessage(message);
|
||||
}
|
||||
else if (message_name == "load_uri")
|
||||
{
|
||||
mURL = message_in.getValue("uri");
|
||||
playMedia();
|
||||
}
|
||||
}
|
||||
else
|
||||
if (message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME)
|
||||
{
|
||||
if (message_name == "stop")
|
||||
{
|
||||
if (mLibVLCMediaPlayer)
|
||||
{
|
||||
libvlc_media_player_stop(mLibVLCMediaPlayer);
|
||||
}
|
||||
}
|
||||
else if (message_name == "start")
|
||||
{
|
||||
if (mLibVLCMediaPlayer)
|
||||
{
|
||||
libvlc_media_player_play(mLibVLCMediaPlayer);
|
||||
}
|
||||
}
|
||||
else if (message_name == "pause")
|
||||
{
|
||||
if (mLibVLCMediaPlayer)
|
||||
{
|
||||
libvlc_media_player_pause(mLibVLCMediaPlayer);
|
||||
}
|
||||
}
|
||||
else if (message_name == "seek")
|
||||
{
|
||||
if (mDuration > 0)
|
||||
{
|
||||
F64 normalized_offset = message_in.getValueReal("time") / mDuration;
|
||||
libvlc_media_player_set_position(mLibVLCMediaPlayer, normalized_offset);
|
||||
}
|
||||
}
|
||||
else if (message_name == "set_loop")
|
||||
{
|
||||
mIsLooping = true;
|
||||
}
|
||||
else if (message_name == "set_volume")
|
||||
{
|
||||
// volume comes in 0 -> 1.0
|
||||
F64 volume = message_in.getValueReal("volume");
|
||||
setVolume(volume);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
bool MediaPluginLibVLC::init()
|
||||
{
|
||||
LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "name_text");
|
||||
message.setValue("name", "LibVLC Plugin");
|
||||
sendMessage(message);
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
int init_media_plugin(LLPluginInstance::sendMessageFunction host_send_func,
|
||||
void* host_user_data,
|
||||
LLPluginInstance::sendMessageFunction *plugin_send_func,
|
||||
void **plugin_user_data)
|
||||
{
|
||||
MediaPluginLibVLC* self = new MediaPluginLibVLC(host_send_func, host_user_data);
|
||||
*plugin_send_func = MediaPluginLibVLC::staticReceiveMessage;
|
||||
*plugin_user_data = (void*)self;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -14,7 +14,6 @@ include(PluginAPI)
|
|||
include(MediaPluginBase)
|
||||
include(OpenGL)
|
||||
include(QuickTimePlugin)
|
||||
include(Boost)
|
||||
|
||||
include_directories(
|
||||
${LLPLUGIN_INCLUDE_DIRS}
|
||||
|
|
@ -54,12 +53,17 @@ target_link_libraries(media_plugin_quicktime
|
|||
${PLUGIN_API_WINDOWS_LIBRARIES}
|
||||
)
|
||||
|
||||
add_dependencies(media_plugin_quicktime
|
||||
${LLPLUGIN_LIBRARIES}
|
||||
${MEDIA_PLUGIN_BASE_LIBRARIES}
|
||||
${LLCOMMON_LIBRARIES}
|
||||
)
|
||||
|
||||
if (WINDOWS)
|
||||
set_target_properties(
|
||||
media_plugin_quicktime
|
||||
PROPERTIES
|
||||
LINK_FLAGS "/MANIFEST:NO /SAFESEH:NO /NODEFAULTLIB:LIBCMT"
|
||||
LINK_FLAGS_DEBUG "/MANIFEST:NO /SAFESEH:NO /NODEFAULTLIB:LIBCMTD"
|
||||
LINK_FLAGS "/MANIFEST:NO"
|
||||
)
|
||||
endif (WINDOWS)
|
||||
|
||||
|
|
|
|||
|
|
@ -837,9 +837,7 @@ void MediaPluginQuickTime::receiveMessage(const char *message_string)
|
|||
else if(message_name == "cleanup")
|
||||
{
|
||||
// TODO: clean up here
|
||||
LLPluginMessage message("base", "goodbye");
|
||||
sendMessage(message);
|
||||
}
|
||||
}
|
||||
else if(message_name == "shm_added")
|
||||
{
|
||||
SharedSegmentInfo info;
|
||||
|
|
@ -921,6 +919,9 @@ void MediaPluginQuickTime::receiveMessage(const char *message_string)
|
|||
#endif
|
||||
message.setValueS32("depth", mDepth);
|
||||
message.setValueU32("internalformat", GL_RGB);
|
||||
|
||||
// note this apparently only has an effect when media is opened in 2D browser.
|
||||
// see https://jira.secondlife.com/browse/BUG-18252 - media flipped in 2D so flipping it back.
|
||||
message.setValueBoolean("coords_opengl", true); // true == use OpenGL-style coordinates, false == (0,0) is upper left.
|
||||
message.setValueBoolean("allow_downsample", true);
|
||||
sendMessage(message);
|
||||
|
|
|
|||
|
|
@ -264,6 +264,7 @@ set(viewer_SOURCE_FILES
|
|||
llfloaternamedesc.cpp
|
||||
llfloaternotificationsconsole.cpp
|
||||
llfloaternotificationstabbed.cpp
|
||||
llfloateroutfitsnapshot.cpp
|
||||
llfloaterobjectweights.cpp
|
||||
llfloateropenobject.cpp
|
||||
llfloaterpathfindingcharacters.cpp
|
||||
|
|
@ -404,6 +405,7 @@ set(viewer_SOURCE_FILES
|
|||
llnotificationscripthandler.cpp
|
||||
llnotificationstorage.cpp
|
||||
llnotificationtiphandler.cpp
|
||||
lloutfitgallery.cpp
|
||||
lloutfitslist.cpp
|
||||
lloutfitobserver.cpp
|
||||
lloutputmonitorctrl.cpp
|
||||
|
|
@ -880,6 +882,7 @@ set(viewer_HEADER_FILES
|
|||
llfloaternamedesc.h
|
||||
llfloaternotificationsconsole.h
|
||||
llfloaternotificationstabbed.h
|
||||
llfloateroutfitsnapshot.h
|
||||
llfloaterobjectweights.h
|
||||
llfloateropenobject.h
|
||||
llfloaterpathfindingcharacters.h
|
||||
|
|
@ -1010,6 +1013,7 @@ set(viewer_HEADER_FILES
|
|||
llnotificationlistview.h
|
||||
llnotificationmanager.h
|
||||
llnotificationstorage.h
|
||||
lloutfitgallery.h
|
||||
lloutfitslist.h
|
||||
lloutfitobserver.h
|
||||
lloutputmonitorctrl.h
|
||||
|
|
@ -1141,6 +1145,7 @@ set(viewer_HEADER_FILES
|
|||
llsky.h
|
||||
llslurl.h
|
||||
llsnapshotlivepreview.h
|
||||
llsnapshotmodel.h
|
||||
llspatialpartition.h
|
||||
llspeakers.h
|
||||
llspeakingindicatormanager.h
|
||||
|
|
@ -1316,13 +1321,10 @@ set(viewer_HEADER_FILES
|
|||
|
||||
source_group("CMake Rules" FILES ViewerInstall.cmake)
|
||||
|
||||
#summary.json creation moved to viewer_manifest.py MAINT-6413
|
||||
# the viewer_version.txt file created here is for passing to viewer_manifest and autobuild
|
||||
# the summary.json file is created for the benefit of the TeamCity builds, where
|
||||
# it is used to provide descriptive information to the build results page
|
||||
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/viewer_version.txt"
|
||||
"${VIEWER_SHORT_VERSION}.${VIEWER_VERSION_REVISION}\n")
|
||||
file(WRITE "${CMAKE_BINARY_DIR}/summary.json"
|
||||
"{\"Type\":\"viewer\",\"Version\":\"${VIEWER_SHORT_VERSION}.${VIEWER_VERSION_REVISION}\"}\n")
|
||||
|
||||
set_source_files_properties(
|
||||
llversioninfo.cpp tests/llversioninfo_test.cpp
|
||||
|
|
@ -1755,6 +1757,7 @@ if (WINDOWS)
|
|||
SLPlugin
|
||||
media_plugin_quicktime
|
||||
media_plugin_cef
|
||||
media_plugin_libvlc
|
||||
winmm_shim
|
||||
windows-crash-logger
|
||||
)
|
||||
|
|
@ -1970,6 +1973,7 @@ if (LINUX)
|
|||
linux-crash-logger
|
||||
SLPlugin
|
||||
media_plugin_gstreamer010
|
||||
media_plugin_libvlc
|
||||
llcommon
|
||||
)
|
||||
|
||||
|
|
@ -2077,7 +2081,7 @@ if (DARWIN)
|
|||
${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py
|
||||
)
|
||||
|
||||
add_dependencies(${VIEWER_BINARY_NAME} SLPlugin media_plugin_quicktime media_plugin_cef mac-crash-logger)
|
||||
add_dependencies(${VIEWER_BINARY_NAME} SLPlugin media_plugin_quicktime media_plugin_libvlc media_plugin_cef mac-crash-logger)
|
||||
add_dependencies(${VIEWER_BINARY_NAME} mac-crash-logger)
|
||||
|
||||
if (ENABLE_SIGNING)
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue