summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--indra/CMakeLists.txt5
-rw-r--r--indra/cmake/Copy3rdPartyLibs.cmake103
-rw-r--r--indra/cmake/LLKDU.cmake17
-rw-r--r--indra/integration_tests/llui_libtest/CMakeLists.txt6
-rw-r--r--indra/llimage/CMakeLists.txt1
-rw-r--r--indra/llimage/llimage.cpp2
-rw-r--r--indra/llimage/llimagej2c.cpp162
-rw-r--r--indra/llimage/llimagej2c.h2
-rw-r--r--indra/llkdu/CMakeLists.txt45
-rw-r--r--indra/llkdu/llimagej2ckdu.cpp1084
-rw-r--r--indra/llkdu/llimagej2ckdu.h91
-rw-r--r--indra/llkdu/llkdumem.cpp196
-rw-r--r--indra/llkdu/llkdumem.h145
-rw-r--r--indra/newview/CMakeLists.txt19
-rw-r--r--indra/newview/viewer_manifest.py51
-rw-r--r--install.xml12
16 files changed, 1646 insertions, 295 deletions
diff --git a/indra/CMakeLists.txt b/indra/CMakeLists.txt
index d01e1869b6..6d17a6f402 100644
--- a/indra/CMakeLists.txt
+++ b/indra/CMakeLists.txt
@@ -43,6 +43,7 @@ add_subdirectory(${LIBS_OPEN_PREFIX}llaudio)
add_subdirectory(${LIBS_OPEN_PREFIX}llcharacter)
add_subdirectory(${LIBS_OPEN_PREFIX}llcommon)
add_subdirectory(${LIBS_OPEN_PREFIX}llimage)
+add_subdirectory(${LIBS_OPEN_PREFIX}llkdu)
add_subdirectory(${LIBS_OPEN_PREFIX}llimagej2coj)
add_subdirectory(${LIBS_OPEN_PREFIX}llinventory)
add_subdirectory(${LIBS_OPEN_PREFIX}llmath)
@@ -53,10 +54,6 @@ add_subdirectory(${LIBS_OPEN_PREFIX}llvfs)
add_subdirectory(${LIBS_OPEN_PREFIX}llwindow)
add_subdirectory(${LIBS_OPEN_PREFIX}llxml)
-if (EXISTS ${LIBS_CLOSED_DIR}llkdu)
- add_subdirectory(${LIBS_CLOSED_PREFIX}llkdu)
-endif (EXISTS ${LIBS_CLOSED_DIR}llkdu)
-
add_subdirectory(${LIBS_OPEN_PREFIX}lscript)
if (WINDOWS AND EXISTS ${LIBS_CLOSED_DIR}copy_win_scripts)
diff --git a/indra/cmake/Copy3rdPartyLibs.cmake b/indra/cmake/Copy3rdPartyLibs.cmake
index e852cf463c..176ae9787e 100644
--- a/indra/cmake/Copy3rdPartyLibs.cmake
+++ b/indra/cmake/Copy3rdPartyLibs.cmake
@@ -60,22 +60,6 @@ if(WINDOWS)
set(release_files ${release_files} fmod.dll)
endif (FMOD)
- #*******************************
- # LLKDU
- set(internal_llkdu_path "${CMAKE_SOURCE_DIR}/llkdu")
- if(NOT EXISTS ${internal_llkdu_path})
- if (EXISTS "${debug_src_dir}/llkdu.dll")
- set(debug_llkdu_src "${debug_src_dir}/llkdu.dll")
- set(debug_llkdu_dst "${SHARED_LIB_STAGING_DIR_DEBUG}/llkdu.dll")
- endif (EXISTS "${debug_src_dir}/llkdu.dll")
-
- if (EXISTS "${release_src_dir}/llkdu.dll")
- set(release_llkdu_src "${release_src_dir}/llkdu.dll")
- set(release_llkdu_dst "${SHARED_LIB_STAGING_DIR_RELEASE}/llkdu.dll")
- set(relwithdebinfo_llkdu_dst "${SHARED_LIB_STAGING_DIR_RELWITHDEBINFO}/llkdu.dll")
- endif (EXISTS "${release_src_dir}/llkdu.dll")
- endif (NOT EXISTS ${internal_llkdu_path})
-
#*******************************
# Copy MS C runtime dlls, required for packaging.
# *TODO - Adapt this to support VC9
@@ -174,21 +158,6 @@ elseif(DARWIN)
# fmod is statically linked on darwin
set(fmod_files "")
- #*******************************
- # LLKDU
- set(internal_llkdu_path "${CMAKE_SOURCE_DIR}/llkdu")
- if(NOT EXISTS ${internal_llkdu_path})
- if (EXISTS "${debug_src_dir}/libllkdu.dylib")
- set(debug_llkdu_src "${debug_src_dir}/libllkdu.dylib")
- set(debug_llkdu_dst "${SHARED_LIB_STAGING_DIR_DEBUG}/libllkdu.dylib")
- endif (EXISTS "${debug_src_dir}/libllkdu.dylib")
-
- if (EXISTS "${release_src_dir}/libllkdu.dylib")
- set(release_llkdu_src "${release_src_dir}/libllkdu.dylib")
- set(release_llkdu_dst "${SHARED_LIB_STAGING_DIR_RELEASE}/libllkdu.dylib")
- set(relwithdebinfo_llkdu_dst "${SHARED_LIB_STAGING_DIR_RELWITHDEBINFO}/libllkdu.dylib")
- endif (EXISTS "${release_src_dir}/libllkdu.dylib")
- endif (NOT EXISTS ${internal_llkdu_path})
elseif(LINUX)
# linux is weird, multiple side by side configurations aren't supported
# and we don't seem to have any debug shared libs built yet anyways...
@@ -242,21 +211,6 @@ elseif(LINUX)
set(release_files ${release_files} "libfmod-3.75.so")
endif (FMOD)
- #*******************************
- # LLKDU
- set(internal_llkdu_path "${CMAKE_SOURCE_DIR}/llkdu")
- if(NOT EXISTS ${internal_llkdu_path})
- if (EXISTS "${debug_src_dir}/libllkdu.so")
- set(debug_llkdu_src "${debug_src_dir}/libllkdu.so")
- set(debug_llkdu_dst "${SHARED_LIB_STAGING_DIR_DEBUG}/libllkdu.so")
- endif (EXISTS "${debug_src_dir}/libllkdu.so")
-
- if (EXISTS "${release_src_dir}/libllkdu.so")
- set(release_llkdu_src "${release_src_dir}/libllkdu.so")
- set(release_llkdu_dst "${SHARED_LIB_STAGING_DIR_RELEASE}/libllkdu.so")
- set(relwithdebinfo_llkdu_dst "${SHARED_LIB_STAGING_DIR_RELWITHDEBINFO}/libllkdu.so")
- endif (EXISTS "${release_src_dir}/libllkdu.so")
- endif(NOT EXISTS ${internal_llkdu_path})
else(WINDOWS)
message(STATUS "WARNING: unrecognized platform for staging 3rd party libs, skipping...")
set(vivox_src_dir "${CMAKE_SOURCE_DIR}/newview/vivox-runtime/i686-linux")
@@ -334,40 +288,29 @@ copy_if_different(
)
set(third_party_targets ${third_party_targets} ${out_targets})
-#*******************************
-# LLKDU
-set(internal_llkdu_path "${CMAKE_SOURCE_DIR}/llkdu")
-if(NOT EXISTS ${internal_llkdu_path})
- if (EXISTS "${debug_llkdu_src}")
- ADD_CUSTOM_COMMAND(
- OUTPUT ${debug_llkdu_dst}
- COMMAND ${CMAKE_COMMAND} -E copy_if_different ${debug_llkdu_src} ${debug_llkdu_dst}
- DEPENDS ${debug_llkdu_src}
- COMMENT "Copying llkdu.dll ${SHARED_LIB_STAGING_DIR_DEBUG}"
- )
- set(third_party_targets ${third_party_targets} $} ${debug_llkdu_dst})
- endif (EXISTS "${debug_llkdu_src}")
-
- if (EXISTS "${release_llkdu_src}")
- ADD_CUSTOM_COMMAND(
- OUTPUT ${release_llkdu_dst}
- COMMAND ${CMAKE_COMMAND} -E copy_if_different ${release_llkdu_src} ${release_llkdu_dst}
- DEPENDS ${release_llkdu_src}
- COMMENT "Copying llkdu.dll ${SHARED_LIB_STAGING_DIR_RELEASE}"
- )
- set(third_party_targets ${third_party_targets} ${release_llkdu_dst})
-
- ADD_CUSTOM_COMMAND(
- OUTPUT ${relwithdebinfo_llkdu_dst}
- COMMAND ${CMAKE_COMMAND} -E copy_if_different ${release_llkdu_src} ${relwithdebinfo_llkdu_dst}
- DEPENDS ${release_llkdu_src}
- COMMENT "Copying llkdu.dll ${SHARED_LIB_STAGING_DIR_RELWITHDEBINFO}"
- )
- set(third_party_targets ${third_party_targets} ${relwithdebinfo_llkdu_dst})
- endif (EXISTS "${release_llkdu_src}")
-
-endif (NOT EXISTS ${internal_llkdu_path})
-
+if (FMOD_SDK_DIR)
+ copy_if_different(
+ ${FMOD_SDK_DIR}
+ "${CMAKE_CURRENT_BINARY_DIR}/Debug"
+ out_targets
+ ${fmod_files}
+ )
+ set(all_targets ${all_targets} ${out_targets})
+ copy_if_different(
+ ${FMOD_SDK_DIR}
+ "${CMAKE_CURRENT_BINARY_DIR}/Release"
+ out_targets
+ ${fmod_files}
+ )
+ set(all_targets ${all_targets} ${out_targets})
+ copy_if_different(
+ ${FMOD_SDK_DIR}
+ "${CMAKE_CURRENT_BINARY_DIR}/RelWithDbgInfo"
+ out_targets
+ ${fmod_files}
+ )
+ set(all_targets ${all_targets} ${out_targets})
+endif (FMOD_SDK_DIR)
if(NOT STANDALONE)
add_custom_target(
diff --git a/indra/cmake/LLKDU.cmake b/indra/cmake/LLKDU.cmake
index 27c8ada686..f5cbad03a6 100644
--- a/indra/cmake/LLKDU.cmake
+++ b/indra/cmake/LLKDU.cmake
@@ -1,7 +1,20 @@
# -*- cmake -*-
include(Prebuilt)
+# USE_KDU can be set when launching cmake or develop.py as an option using the argument -DUSE_KDU:BOOL=ON
+# When building using proprietary binaries though (i.e. having access to LL private servers), we always build with KDU
if (INSTALL_PROPRIETARY AND NOT STANDALONE)
- use_prebuilt_binary(kdu)
- set(LLKDU_LIBRARY llkdu)
+ set(USE_KDU ON)
endif (INSTALL_PROPRIETARY AND NOT STANDALONE)
+
+if (USE_KDU)
+ use_prebuilt_binary(kdu)
+ if (WINDOWS)
+ set(KDU_LIBRARY kdu.lib)
+ else (WINDOWS)
+ set(KDU_LIBRARY libkdu.a)
+ endif (WINDOWS)
+ set(KDU_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include/kdu)
+ set(LLKDU_INCLUDE_DIRS ${LIBS_OPEN_DIR}/llkdu)
+ set(LLKDU_LIBRARIES llkdu)
+endif (USE_KDU)
diff --git a/indra/integration_tests/llui_libtest/CMakeLists.txt b/indra/integration_tests/llui_libtest/CMakeLists.txt
index 452d37d3be..e0772e55ca 100644
--- a/indra/integration_tests/llui_libtest/CMakeLists.txt
+++ b/indra/integration_tests/llui_libtest/CMakeLists.txt
@@ -10,6 +10,7 @@ include(00-Common)
include(LLCommon)
include(LLImage)
include(LLImageJ2COJ) # ugh, needed for images
+include(LLKDU)
include(LLMath)
include(LLMessage)
include(LLRender)
@@ -71,6 +72,11 @@ endif (DARWIN)
target_link_libraries(llui_libtest
llui
llmessage
+ ${LLRENDER_LIBRARIES}
+ ${LLIMAGE_LIBRARIES}
+ ${LLKDU_LIBRARIES}
+ ${KDU_LIBRARY}
+ ${LLIMAGEJ2COJ_LIBRARIES}
${OS_LIBRARIES}
${GOOGLE_PERFTOOLS_LIBRARIES}
)
diff --git a/indra/llimage/CMakeLists.txt b/indra/llimage/CMakeLists.txt
index a69621a57b..6834267d4b 100644
--- a/indra/llimage/CMakeLists.txt
+++ b/indra/llimage/CMakeLists.txt
@@ -57,7 +57,6 @@ add_library (llimage ${llimage_SOURCE_FILES})
# Sort by high-level to low-level
target_link_libraries(llimage
llcommon
- llimagej2coj # *HACK: In theory a noop for KDU builds?
${JPEG_LIBRARIES}
${PNG_LIBRARIES}
${ZLIB_LIBRARIES}
diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp
index 5c33b675ca..b46a99e030 100644
--- a/indra/llimage/llimage.cpp
+++ b/indra/llimage/llimage.cpp
@@ -52,13 +52,11 @@ LLMutex* LLImage::sMutex = NULL;
void LLImage::initClass()
{
sMutex = new LLMutex(NULL);
- LLImageJ2C::openDSO();
}
//static
void LLImage::cleanupClass()
{
- LLImageJ2C::closeDSO();
delete sMutex;
sMutex = NULL;
}
diff --git a/indra/llimage/llimagej2c.cpp b/indra/llimage/llimagej2c.cpp
index d005aaf29f..cb2a85fa91 100644
--- a/indra/llimage/llimagej2c.cpp
+++ b/indra/llimage/llimagej2c.cpp
@@ -24,9 +24,6 @@
*/
#include "linden_common.h"
-#include "apr_pools.h"
-#include "apr_dso.h"
-
#include "lldir.h"
#include "llimagej2c.h"
#include "llmemtype.h"
@@ -37,18 +34,10 @@ typedef LLImageJ2CImpl* (*CreateLLImageJ2CFunction)();
typedef void (*DestroyLLImageJ2CFunction)(LLImageJ2CImpl*);
typedef const char* (*EngineInfoLLImageJ2CFunction)();
-//some "private static" variables so we only attempt to load
-//dynamic libaries once
-CreateLLImageJ2CFunction j2cimpl_create_func;
-DestroyLLImageJ2CFunction j2cimpl_destroy_func;
-EngineInfoLLImageJ2CFunction j2cimpl_engineinfo_func;
-apr_pool_t *j2cimpl_dso_memory_pool;
-apr_dso_handle_t *j2cimpl_dso_handle;
-
-//Declare the prototype for theses functions here, their functionality
-//will be implemented in other files which define a derived LLImageJ2CImpl
-//but only ONE static library which has the implementation for this
-//function should ever be included
+// Declare the prototype for theses functions here. Their functionality
+// will be implemented in other files which define a derived LLImageJ2CImpl
+// but only ONE static library which has the implementation for these
+// functions should ever be included.
LLImageJ2CImpl* fallbackCreateLLImageJ2CImpl();
void fallbackDestroyLLImageJ2CImpl(LLImageJ2CImpl* impl);
const char* fallbackEngineInfoLLImageJ2CImpl();
@@ -58,120 +47,9 @@ LLImageCompressionTester* LLImageJ2C::sTesterp = NULL ;
const std::string sTesterName("ImageCompressionTester");
//static
-//Loads the required "create", "destroy" and "engineinfo" functions needed
-void LLImageJ2C::openDSO()
-{
- //attempt to load a DSO and get some functions from it
- std::string dso_name;
- std::string dso_path;
-
- bool all_functions_loaded = false;
- apr_status_t rv;
-
-#if LL_WINDOWS
- dso_name = "llkdu.dll";
-#elif LL_DARWIN
- dso_name = "libllkdu.dylib";
-#else
- dso_name = "libllkdu.so";
-#endif
-
- dso_path = gDirUtilp->findFile(dso_name,
- gDirUtilp->getAppRODataDir(),
- gDirUtilp->getExecutableDir());
-
- j2cimpl_dso_handle = NULL;
- j2cimpl_dso_memory_pool = NULL;
-
- //attempt to load the shared library
- apr_pool_create(&j2cimpl_dso_memory_pool, NULL);
- rv = apr_dso_load(&j2cimpl_dso_handle,
- dso_path.c_str(),
- j2cimpl_dso_memory_pool);
-
- //now, check for success
- if ( rv == APR_SUCCESS )
- {
- //found the dynamic library
- //now we want to load the functions we're interested in
- CreateLLImageJ2CFunction create_func = NULL;
- DestroyLLImageJ2CFunction dest_func = NULL;
- EngineInfoLLImageJ2CFunction engineinfo_func = NULL;
-
- rv = apr_dso_sym((apr_dso_handle_sym_t*)&create_func,
- j2cimpl_dso_handle,
- "createLLImageJ2CKDU");
- if ( rv == APR_SUCCESS )
- {
- //we've loaded the create function ok
- //we need to delete via the DSO too
- //so lets check for a destruction function
- rv = apr_dso_sym((apr_dso_handle_sym_t*)&dest_func,
- j2cimpl_dso_handle,
- "destroyLLImageJ2CKDU");
- if ( rv == APR_SUCCESS )
- {
- //we've loaded the destroy function ok
- rv = apr_dso_sym((apr_dso_handle_sym_t*)&engineinfo_func,
- j2cimpl_dso_handle,
- "engineInfoLLImageJ2CKDU");
- if ( rv == APR_SUCCESS )
- {
- //ok, everything is loaded alright
- j2cimpl_create_func = create_func;
- j2cimpl_destroy_func = dest_func;
- j2cimpl_engineinfo_func = engineinfo_func;
- all_functions_loaded = true;
- }
- }
- }
- }
-
- if ( !all_functions_loaded )
- {
- //something went wrong with the DSO or function loading..
- //fall back onto our satefy impl creation function
-
-#if 0
- // precious verbose debugging, sadly we can't use our
- // 'llinfos' stream etc. this early in the initialisation seq.
- char errbuf[256];
- fprintf(stderr, "failed to load syms from DSO %s (%s)\n",
- dso_name.c_str(), dso_path.c_str());
- apr_strerror(rv, errbuf, sizeof(errbuf));
- fprintf(stderr, "error: %d, %s\n", rv, errbuf);
- apr_dso_error(j2cimpl_dso_handle, errbuf, sizeof(errbuf));
- fprintf(stderr, "dso-error: %d, %s\n", rv, errbuf);
-#endif
-
- if ( j2cimpl_dso_handle )
- {
- apr_dso_unload(j2cimpl_dso_handle);
- j2cimpl_dso_handle = NULL;
- }
-
- if ( j2cimpl_dso_memory_pool )
- {
- apr_pool_destroy(j2cimpl_dso_memory_pool);
- j2cimpl_dso_memory_pool = NULL;
- }
- }
-}
-
-//static
-void LLImageJ2C::closeDSO()
-{
- if ( j2cimpl_dso_handle ) apr_dso_unload(j2cimpl_dso_handle);
- if (j2cimpl_dso_memory_pool) apr_pool_destroy(j2cimpl_dso_memory_pool);
-}
-
-//static
std::string LLImageJ2C::getEngineInfo()
{
- if (!j2cimpl_engineinfo_func)
- j2cimpl_engineinfo_func = fallbackEngineInfoLLImageJ2CImpl;
-
- return j2cimpl_engineinfo_func();
+ return fallbackEngineInfoLLImageJ2CImpl();
}
LLImageJ2C::LLImageJ2C() : LLImageFormatted(IMG_CODEC_J2C),
@@ -181,20 +59,7 @@ LLImageJ2C::LLImageJ2C() : LLImageFormatted(IMG_CODEC_J2C),
mReversible(FALSE),
mAreaUsedForDataSizeCalcs(0)
{
- //We assume here that if we wanted to create via
- //a dynamic library that the approriate open calls were made
- //before any calls to this constructor.
-
- //Therefore, a NULL creation function pointer here means
- //we either did not want to create using functions from the dynamic
- //library or there were issues loading it, either way
- //use our fall back
- if ( !j2cimpl_create_func )
- {
- j2cimpl_create_func = fallbackCreateLLImageJ2CImpl;
- }
-
- mImpl = j2cimpl_create_func();
+ mImpl = fallbackCreateLLImageJ2CImpl();
// Clear data size table
for( S32 i = 0; i <= MAX_DISCARD_LEVEL; i++)
@@ -217,22 +82,9 @@ LLImageJ2C::LLImageJ2C() : LLImageFormatted(IMG_CODEC_J2C),
// virtual
LLImageJ2C::~LLImageJ2C()
{
- //We assume here that if we wanted to destroy via
- //a dynamic library that the approriate open calls were made
- //before any calls to this destructor.
-
- //Therefore, a NULL creation function pointer here means
- //we either did not want to destroy using functions from the dynamic
- //library or there were issues loading it, either way
- //use our fall back
- if ( !j2cimpl_destroy_func )
- {
- j2cimpl_destroy_func = fallbackDestroyLLImageJ2CImpl;
- }
-
if ( mImpl )
{
- j2cimpl_destroy_func(mImpl);
+ fallbackDestroyLLImageJ2CImpl(mImpl);
}
}
diff --git a/indra/llimage/llimagej2c.h b/indra/llimage/llimagej2c.h
index cc3dabd7d8..dd5bec8b2e 100644
--- a/indra/llimage/llimagej2c.h
+++ b/indra/llimage/llimagej2c.h
@@ -72,8 +72,6 @@ public:
static S32 calcHeaderSizeJ2C();
static S32 calcDataSizeJ2C(S32 w, S32 h, S32 comp, S32 discard_level, F32 rate = 0.f);
- static void openDSO();
- static void closeDSO();
static std::string getEngineInfo();
protected:
diff --git a/indra/llkdu/CMakeLists.txt b/indra/llkdu/CMakeLists.txt
new file mode 100644
index 0000000000..b8b44b44fc
--- /dev/null
+++ b/indra/llkdu/CMakeLists.txt
@@ -0,0 +1,45 @@
+# -*- cmake -*-
+
+project(llkdu)
+
+# Visual Studio 2005 has a dumb bug that causes it to fail compilation
+# of KDU if building with both optimisation and /WS (treat warnings as
+# errors), even when the specific warnings that make it croak are
+# disabled.
+
+#set(VS_DISABLE_FATAL_WARNINGS ON)
+
+include(00-Common)
+include(LLCommon)
+include(LLImage)
+include(LLKDU)
+include(LLMath)
+
+include_directories(
+ ${LLCOMMON_INCLUDE_DIRS}
+ ${LLIMAGE_INCLUDE_DIRS}
+ ${KDU_INCLUDE_DIR}
+ ${LLMATH_INCLUDE_DIRS}
+ )
+
+set(llkdu_SOURCE_FILES
+ llimagej2ckdu.cpp
+ llkdumem.cpp
+ )
+
+set(llkdu_HEADER_FILES
+ CMakeLists.txt
+
+ llimagej2ckdu.h
+ llkdumem.h
+ )
+
+set_source_files_properties(${llkdu_HEADER_FILES}
+ PROPERTIES HEADER_FILE_ONLY TRUE)
+
+list(APPEND llkdu_SOURCE_FILES ${llkdu_HEADER_FILES})
+
+if (USE_KDU)
+ add_library (${LLKDU_LIBRARIES} ${llkdu_SOURCE_FILES})
+
+endif (USE_KDU)
diff --git a/indra/llkdu/llimagej2ckdu.cpp b/indra/llkdu/llimagej2ckdu.cpp
new file mode 100644
index 0000000000..1a286d1406
--- /dev/null
+++ b/indra/llkdu/llimagej2ckdu.cpp
@@ -0,0 +1,1084 @@
+ /**
+ * @file llimagej2ckdu.cpp
+ * @brief This is an implementation of JPEG2000 encode/decode using Kakadu
+ *
+ * $LicenseInfo:firstyear=2010&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+#include "llimagej2ckdu.h"
+
+#include "lltimer.h"
+#include "llpointer.h"
+#include "llkdumem.h"
+
+
+class kdc_flow_control {
+
+public: // Member functions
+ kdc_flow_control(kdu_image_in_base *img_in, kdu_codestream codestream);
+ ~kdc_flow_control();
+ bool advance_components();
+ void process_components();
+
+private: // Data
+
+ struct kdc_component_flow_control {
+ public: // Data
+ kdu_image_in_base *reader;
+ int vert_subsampling;
+ int ratio_counter; /* Initialized to 0, decremented by `count_delta';
+ when < 0, a new line must be processed, after
+ which it is incremented by `vert_subsampling'. */
+ int initial_lines;
+ int remaining_lines;
+ kdu_line_buf *line;
+ };
+
+ kdu_codestream codestream;
+ kdu_dims valid_tile_indices;
+ kdu_coords tile_idx;
+ kdu_tile tile;
+ int num_components;
+ kdc_component_flow_control *components;
+ int count_delta; // Holds the minimum of the `vert_subsampling' fields
+ kdu_multi_analysis engine;
+ kdu_long max_buffer_memory;
+};
+
+//
+// Kakadu specific implementation
+//
+void set_default_colour_weights(kdu_params *siz);
+
+const char* engineInfoLLImageJ2CKDU()
+{
+ return "KDU v6.4.1";
+}
+
+LLImageJ2CKDU* createLLImageJ2CKDU()
+{
+ return new LLImageJ2CKDU();
+}
+
+void destroyLLImageJ2CKDU(LLImageJ2CKDU* kdu)
+{
+ delete kdu;
+ kdu = NULL;
+}
+
+LLImageJ2CImpl* fallbackCreateLLImageJ2CImpl()
+{
+ return new LLImageJ2CKDU();
+}
+
+void fallbackDestroyLLImageJ2CImpl(LLImageJ2CImpl* impl)
+{
+ delete impl;
+ impl = NULL;
+}
+
+const char* fallbackEngineInfoLLImageJ2CImpl()
+{
+ return engineInfoLLImageJ2CKDU();
+}
+
+class LLKDUDecodeState
+{
+public:
+
+ S32 mNumComponents;
+ BOOL mUseYCC;
+ kdu_dims mDims;
+ kdu_sample_allocator mAllocator;
+ kdu_tile_comp mComps[4];
+ kdu_line_buf mLines[4];
+ kdu_pull_ifc mEngines[4];
+ bool mReversible[4]; // Some components may be reversible and others not.
+ int mBitDepths[4]; // Original bit-depth may be quite different from 8.
+
+ kdu_tile mTile;
+ kdu_byte *mBuf;
+ S32 mRowGap;
+
+ LLKDUDecodeState(kdu_tile tile, kdu_byte *buf, S32 row_gap);
+ ~LLKDUDecodeState();
+ BOOL processTileDecode(F32 decode_time, BOOL limit_time = TRUE);
+
+public:
+ int *AssignLayerBytes(siz_params *siz, int &num_specs);
+
+ void setupCodeStream(BOOL keep_codestream, LLImageJ2CKDU::ECodeStreamMode mode);
+ BOOL initDecode(LLImageRaw &raw_image, F32 decode_time, LLImageJ2CKDU::ECodeStreamMode mode, S32 first_channel, S32 max_channel_count );
+};
+
+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
+{
+public:
+ /*virtual*/ void put_text(const char *s);
+ /*virtual*/ void put_text(const kdu_uint16 *s);
+
+ 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)
+{
+ llinfos << "KDU Warning: " << s << llendl;
+}
+
+void LLKDUMessageWarning::put_text(const kdu_uint16 *s)
+{
+ llinfos << "KDU Warning: " << s << llendl;
+}
+
+void LLKDUMessageError::put_text(const char *s)
+{
+ llinfos << "KDU Error: " << s << llendl;
+}
+
+void LLKDUMessageError::put_text(const kdu_uint16 *s)
+{
+ llinfos << "KDU Error: " << s << llendl;
+}
+
+void LLKDUMessageError::flush(bool end_of_message)
+{
+ if( end_of_message )
+ {
+ throw "KDU throwing an exception";
+ }
+}
+
+LLKDUMessageWarning LLKDUMessageWarning::sDefaultMessage;
+LLKDUMessageError LLKDUMessageError::sDefaultMessage;
+static bool kdu_message_initialized = false;
+
+LLImageJ2CKDU::LLImageJ2CKDU() : LLImageJ2CImpl(),
+mInputp(NULL),
+mCodeStreamp(NULL),
+mTPosp(NULL),
+mTileIndicesp(NULL),
+mRawImagep(NULL),
+mDecodeState(NULL)
+{
+}
+
+LLImageJ2CKDU::~LLImageJ2CKDU()
+{
+ cleanupCodeStream(); // in case destroyed before decode completed
+}
+
+// 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)
+{
+ S32 data_size = base.getDataSize();
+ S32 max_bytes = base.getMaxBytes() ? base.getMaxBytes() : data_size;
+
+ //
+ // 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;
+ }
+
+ if (!mInputp)
+ {
+ llassert(base.getData());
+ // The compressed data has been loaded
+ // Setup the source for the codestrea
+ mInputp = new LLKDUMemSource(base.getData(), data_size);
+ }
+
+ llassert(mInputp);
+ mInputp->reset();
+ mCodeStreamp = new kdu_codestream;
+
+ mCodeStreamp->create(mInputp);
+
+ // Set the maximum number of bytes to use from the codestream
+ mCodeStreamp->set_max_bytes(max_bytes);
+
+ // If you want to flip or rotate the image for some reason, change
+ // the resolution, or identify a restricted region of interest, this is
+ // the place to do it. You may use "kdu_codestream::change_appearance"
+ // and "kdu_codestream::apply_input_restrictions" for this purpose.
+ // If you wish to truncate the code-stream prior to decompression, you
+ // may use "kdu_codestream::set_max_bytes".
+ // If you wish to retain all compressed data so that the material
+ // can be decompressed multiple times, possibly with different appearance
+ // parameters, you should call "kdu_codestream::set_persistent" here.
+ // There are a variety of other features which must be enabled at
+ // this point if you want to take advantage of them. See the
+ // descriptions appearing with the "kdu_codestream" interface functions
+ // in "kdu_compressed.h" for an itemized account of these capabilities.
+
+ switch( mode )
+ {
+ case MODE_FAST:
+ mCodeStreamp->set_fast();
+ break;
+ case MODE_RESILIENT:
+ mCodeStreamp->set_resilient();
+ break;
+ case MODE_FUSSY:
+ mCodeStreamp->set_fussy();
+ break;
+ default:
+ llassert(0);
+ mCodeStreamp->set_fast();
+ }
+
+ kdu_dims dims;
+ mCodeStreamp->get_dims(0,dims);
+
+ 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))
+ {
+ llerrs << "Components don't have matching dimensions!" << llendl;
+ }
+ }
+
+ base.setSize(dims.size.x, dims.size.y, components);
+
+ if (!keep_codestream)
+ {
+ mCodeStreamp->destroy();
+ delete mCodeStreamp;
+ mCodeStreamp = NULL;
+ delete mInputp;
+ mInputp = NULL;
+ }
+}
+
+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;
+}
+
+BOOL LLImageJ2CKDU::initDecode(LLImageJ2C &base, LLImageRaw &raw_image, F32 decode_time, ECodeStreamMode mode, S32 first_channel, S32 max_channel_count )
+{
+ base.resetLastError();
+
+ // *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
+ {
+ base.updateRawDiscardLevel();
+ setupCodeStream(base, TRUE, mode);
+
+ mRawImagep = &raw_image;
+ mCodeStreamp->change_appearance(false, true, false);
+ mCodeStreamp->apply_input_restrictions(first_channel,max_channel_count,base.getRawDiscardLevel(),0,NULL);
+
+ kdu_dims dims; mCodeStreamp->get_dims(0,dims);
+ S32 channels = base.getComponents() - first_channel;
+ if( channels > max_channel_count )
+ {
+ channels = max_channel_count;
+ }
+ raw_image.resize(dims.size.x, dims.size.y, channels);
+
+ // llinfos << "Resizing to " << dims.size.x << ":" << dims.size.y << llendl;
+ if (!mTileIndicesp)
+ {
+ mTileIndicesp = new kdu_dims;
+ }
+ mCodeStreamp->get_valid_tiles(*mTileIndicesp);
+ if (!mTPosp)
+ {
+ mTPosp = new kdu_coords;
+ mTPosp->y = 0;
+ mTPosp->x = 0;
+ }
+ }
+ catch (const char* msg)
+ {
+ base.setLastError(ll_safe_string(msg));
+ return FALSE;
+ }
+ catch (...)
+ {
+ base.setLastError("Unknown J2C error");
+ return FALSE;
+ }
+
+ 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)
+{
+ ECodeStreamMode mode = MODE_FAST;
+
+ LLTimer decode_timer;
+
+ if (!mCodeStreamp)
+ {
+ if (!initDecode(base, raw_image, decode_time, mode, first_channel, max_channel_count))
+ {
+ // Initializing the J2C decode failed, bail out.
+ cleanupCodeStream();
+ return TRUE; // done
+ }
+ }
+
+ // These can probably be grabbed from what's saved in the class.
+ kdu_dims dims;
+ mCodeStreamp->get_dims(0,dims);
+
+ // Now we are ready to walk through the tiles processing them one-by-one.
+ kdu_byte *buffer = raw_image.getData();
+
+ while (mTPosp->y < mTileIndicesp->size.y)
+ {
+ while (mTPosp->x < mTileIndicesp->size.x)
+ {
+ try
+ {
+ if (!mDecodeState)
+ {
+ kdu_tile tile = mCodeStreamp->open_tile(*(mTPosp)+mTileIndicesp->pos);
+
+ // Find the region of the buffer occupied by this
+ // tile. Note that we have no control over
+ // sub-sampling factors which might have been used
+ // during compression and so it can happen that tiles
+ // (at the image component level) actually have
+ // different dimensions. For this reason, we cannot
+ // figure out the buffer region occupied by a tile
+ // directly from the tile indices. Instead, we query
+ // the highest resolution of the first tile-component
+ // concerning its location and size on the canvas --
+ // the `dims' object already holds the location and
+ // size of the entire image component on the same
+ // canvas coordinate system. Comparing the two tells
+ // us where the current tile is in the buffer.
+ S32 channels = base.getComponents() - first_channel;
+ if( channels > max_channel_count )
+ {
+ channels = max_channel_count;
+ }
+ kdu_resolution res = tile.access_component(0).access_resolution();
+ kdu_dims tile_dims; res.get_dims(tile_dims);
+ kdu_coords offset = tile_dims.pos - dims.pos;
+ int row_gap = 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);
+ }
+ // 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;
+ }
+ else
+ {
+ // Not finished decoding yet.
+ // setLastError("Ran out of time while decoding");
+ return FALSE;
+ }
+ }
+ catch( const char* msg )
+ {
+ base.setLastError(ll_safe_string(msg));
+ base.decodeFailed();
+ cleanupCodeStream();
+ return TRUE; // done
+ }
+ catch( ... )
+ {
+ base.setLastError( "Unknown J2C error" );
+ base.decodeFailed();
+ cleanupCodeStream();
+ return TRUE; // done
+ }
+
+
+ mTPosp->x++;
+ }
+ mTPosp->y++;
+ mTPosp->x = 0;
+ }
+
+ cleanupCodeStream();
+
+ return TRUE;
+}
+
+
+BOOL LLImageJ2CKDU::encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, const char* comment_text, F32 encode_time, BOOL reversible)
+{
+ // Collect simple arguments.
+ bool transpose, vflip, hflip;
+ bool allow_rate_prediction, mem, quiet, no_weights;
+ int cpu_iterations;
+ std::ostream *record_stream;
+
+ transpose = false;
+ record_stream = NULL;
+ allow_rate_prediction = true;
+ no_weights = false;
+ cpu_iterations = -1;
+ mem = false;
+ quiet = false;
+ vflip = true;
+ hflip = false;
+
+ try
+ {
+ // Set up input image files.
+ siz_params siz;
+
+ // Should set rate someplace here.
+ LLKDUMemIn mem_in(raw_image.getData(),
+ raw_image.getDataSize(),
+ raw_image.getWidth(),
+ raw_image.getHeight(),
+ raw_image.getComponents(),
+ &siz);
+
+ base.setSize(raw_image.getWidth(), raw_image.getHeight(), raw_image.getComponents());
+
+ int num_components = raw_image.getComponents();
+
+ siz.set(Scomponents,0,0,num_components);
+ siz.set(Sdims,0,0,base.getHeight()); // Height of first image component
+ siz.set(Sdims,0,1,base.getWidth()); // Width of first image component
+ siz.set(Sprecision,0,0,8); // Image samples have original bit-depth of 8
+ siz.set(Ssigned,0,0,false); // Image samples are originally unsigned
+
+ kdu_params *siz_ref = &siz; siz_ref->finalize();
+ siz_params transformed_siz; // Use this one to construct code-strea
+ transformed_siz.copy_from(&siz,-1,-1,-1,0,transpose,false,false);
+
+ // Construct the `kdu_codestream' object and parse all remaining arguments.
+
+ U32 max_output_size = base.getWidth()*base.getHeight()*base.getComponents();
+ if (max_output_size < 1000)
+ {
+ max_output_size = 1000;
+ }
+ U8 *output_buffer = new U8[max_output_size];
+
+ U32 output_size = max_output_size; // gets modified
+ LLKDUMemTarget output(output_buffer, output_size, base.getWidth()*base.getHeight()*base.getComponents());
+ if (output_size > max_output_size)
+ {
+ llerrs << llformat("LLImageJ2C::encode output_size(%d) > max_output_size(%d)",
+ output_size,max_output_size) << llendl;
+ }
+
+ kdu_codestream codestream;
+ codestream.create(&transformed_siz,&output);
+
+ if (comment_text)
+ {
+ // Set the comments for the codestream
+ kdu_codestream_comment comment = codestream.add_comment();
+ comment.put_text(comment_text);
+ }
+
+ // Set codestream options
+ int num_layer_specs = 0;
+
+ kdu_long layer_bytes[64];
+ U32 max_bytes = 0;
+
+ if ((num_components >= 3) && !no_weights)
+ {
+ set_default_colour_weights(codestream.access_siz());
+ }
+
+ if (reversible)
+ {
+ // If we're doing reversible, assume we're not using quality layers.
+ // Yes, I know this is incorrect!
+ codestream.access_siz()->parse_string("Creversible=yes");
+ codestream.access_siz()->parse_string("Clayers=1");
+ num_layer_specs = 1;
+ layer_bytes[0] = 0;
+ }
+ else
+ {
+ // Rate is the argument passed into the LLImageJ2C which
+ // specifies the target compression rate. The default is 8:1.
+ // Possibly if max_bytes < 500, we should just use the default setting?
+ if (base.mRate != 0.f)
+ {
+ max_bytes = (U32)(base.mRate*base.getWidth()*base.getHeight()*base.getComponents());
+ }
+ else
+ {
+ max_bytes = (U32)(base.getWidth()*base.getHeight()*base.getComponents()*0.125);
+ }
+
+ const U32 min_bytes = FIRST_PACKET_SIZE;
+ if (max_bytes > min_bytes)
+ {
+ U32 i;
+ // This code is where we specify the target number of bytes for
+ // each layer. Not sure if we should do this for small images
+ // or not. The goal is to have this roughly align with
+ // different quality levels that we decode at.
+ for (i = min_bytes; i < max_bytes; i*=4)
+ {
+ if (i == min_bytes * 4)
+ {
+ i = 2000;
+ }
+ layer_bytes[num_layer_specs] = i;
+ num_layer_specs++;
+ }
+ layer_bytes[num_layer_specs] = max_bytes;
+ num_layer_specs++;
+
+ std::string layer_string = llformat("Clayers=%d",num_layer_specs);
+ codestream.access_siz()->parse_string(layer_string.c_str());
+ }
+ else
+ {
+ layer_bytes[0] = min_bytes;
+ num_layer_specs = 1;
+ std::string layer_string = llformat("Clayers=%d",num_layer_specs);
+ codestream.access_siz()->parse_string(layer_string.c_str());
+ }
+ }
+ codestream.access_siz()->finalize_all();
+ if (cpu_iterations >= 0)
+ {
+ codestream.collect_timing_stats(cpu_iterations);
+ }
+ codestream.change_appearance(transpose,vflip,hflip);
+
+ // Now we are ready for sample data processing.
+ kdc_flow_control *tile = new kdc_flow_control(&mem_in,codestream);
+ bool done = false;
+ while (!done)
+ {
+ // Process line by line
+ done = true;
+ if (tile->advance_components())
+ {
+ done = false;
+ tile->process_components();
+ }
+ }
+
+ // Produce the compressed output
+ codestream.flush(layer_bytes,num_layer_specs);
+
+ // Cleanup
+ delete tile;
+
+ codestream.destroy();
+ if (record_stream != NULL)
+ {
+ delete record_stream;
+ }
+
+ // Now that we're done encoding, create the new data buffer for the compressed
+ // image and stick it there.
+
+ base.copyData(output_buffer, output_size);
+ base.updateData(); // set width, height
+ delete[] output_buffer;
+ }
+ catch(const char* msg)
+ {
+ base.setLastError(ll_safe_string(msg));
+ return FALSE;
+ }
+ catch( ... )
+ {
+ base.setLastError( "Unknown J2C error" );
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+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;
+ }
+ catch( const char* msg )
+ {
+ base.setLastError(ll_safe_string(msg));
+ return FALSE;
+ }
+ catch( ... )
+ {
+ base.setLastError( "Unknown J2C error" );
+ return FALSE;
+ }
+}
+
+void set_default_colour_weights(kdu_params *siz)
+{
+ kdu_params *cod = siz->access_cluster(COD_params);
+ assert(cod != NULL);
+
+ bool can_use_ycc = true;
+ bool rev0=false;
+ int depth0=0, sub_x0=1, sub_y0=1;
+ for (int c=0; c < 3; c++)
+ {
+ int depth=0; siz->get(Sprecision,c,0,depth);
+ int sub_y=1; siz->get(Ssampling,c,0,sub_y);
+ int sub_x=1; siz->get(Ssampling,c,1,sub_x);
+ kdu_params *coc = cod->access_relation(-1,c);
+ bool rev=false; coc->get(Creversible,0,0,rev);
+ if (c == 0)
+ { rev0=rev; depth0=depth; sub_x0=sub_x; sub_y0=sub_y; }
+ else if ((rev != rev0) || (depth != depth0) ||
+ (sub_x != sub_x0) || (sub_y != sub_y0))
+ can_use_ycc = false;
+ }
+ if (!can_use_ycc)
+ return;
+
+ bool use_ycc;
+ if (!cod->get(Cycc,0,0,use_ycc))
+ cod->set(Cycc,0,0,use_ycc=true);
+ if (!use_ycc)
+ return;
+ float weight;
+ if (cod->get(Clev_weights,0,0,weight) ||
+ cod->get(Cband_weights,0,0,weight))
+ return; // Weights already specified explicitly.
+
+ /* These example weights are adapted from numbers generated by Marcus Nadenau
+ at EPFL, for a viewing distance of 15 cm and a display resolution of
+ 300 DPI. */
+
+ cod->parse_string("Cband_weights:C0="
+ "{0.0901},{0.2758},{0.2758},"
+ "{0.7018},{0.8378},{0.8378},{1}");
+ cod->parse_string("Cband_weights:C1="
+ "{0.0263},{0.0863},{0.0863},"
+ "{0.1362},{0.2564},{0.2564},"
+ "{0.3346},{0.4691},{0.4691},"
+ "{0.5444},{0.6523},{0.6523},"
+ "{0.7078},{0.7797},{0.7797},{1}");
+ cod->parse_string("Cband_weights:C2="
+ "{0.0773},{0.1835},{0.1835},"
+ "{0.2598},{0.4130},{0.4130},"
+ "{0.5040},{0.6464},{0.6464},"
+ "{0.7220},{0.8254},{0.8254},"
+ "{0.8769},{0.9424},{0.9424},{1}");
+}
+
+/******************************************************************************/
+/* transfer_bytes */
+/******************************************************************************/
+
+void transfer_bytes(kdu_byte *dest, kdu_line_buf &src, int gap, int precision)
+/* Transfers source samples from the supplied line buffer into the output
+byte buffer, spacing successive output samples apart by `gap' bytes
+(to allow for interleaving of colour components). The function performs
+all necessary level shifting, type conversion, rounding and truncation. */
+{
+ int width = src.get_width();
+ if (src.get_buf32() != NULL)
+ { // Decompressed samples have a 32-bit representation (integer or float)
+ assert(precision >= 8); // Else would have used 16 bit representation
+ kdu_sample32 *sp = src.get_buf32();
+ if (!src.is_absolute())
+ { // Transferring normalized floating point data.
+ float scale16 = (float)(1<<16);
+ kdu_int32 val;
+
+ for (; width > 0; width--, sp++, dest+=gap)
+ {
+ val = (kdu_int32)(sp->fval*scale16);
+ val = (val+128)>>8; // May be faster than true rounding
+ val += 128;
+ if (val & ((-1)<<8))
+ {
+ val = (val<0)?0:255;
+ }
+ *dest = (kdu_byte) val;
+ }
+ }
+ else
+ { // Transferring 32-bit absolute integers.
+ kdu_int32 val;
+ kdu_int32 downshift = precision-8;
+ kdu_int32 offset = (1<<downshift)>>1;
+
+ for (; width > 0; width--, sp++, dest+=gap)
+ {
+ val = sp->ival;
+ val = (val+offset)>>downshift;
+ val += 128;
+ if (val & ((-1)<<8))
+ {
+ val = (val<0)?0:255;
+ }
+ *dest = (kdu_byte) val;
+ }
+ }
+ }
+ else
+ { // Source data is 16 bits.
+ kdu_sample16 *sp = src.get_buf16();
+ if (!src.is_absolute())
+ { // Transferring 16-bit fixed point quantities
+ kdu_int16 val;
+
+ if (precision >= 8)
+ { // Can essentially ignore the bit-depth.
+ for (; width > 0; width--, sp++, dest+=gap)
+ {
+ val = sp->ival;
+ val += (1<<(KDU_FIX_POINT-8))>>1;
+ val >>= (KDU_FIX_POINT-8);
+ val += 128;
+ if (val & ((-1)<<8))
+ {
+ val = (val<0)?0:255;
+ }
+ *dest = (kdu_byte) val;
+ }
+ }
+ else
+ { // Need to force zeros into one or more least significant bits.
+ kdu_int16 downshift = KDU_FIX_POINT-precision;
+ kdu_int16 upshift = 8-precision;
+ kdu_int16 offset = 1<<(downshift-1);
+
+ for (; width > 0; width--, sp++, dest+=gap)
+ {
+ val = sp->ival;
+ val = (val+offset)>>downshift;
+ val <<= upshift;
+ val += 128;
+ if (val & ((-1)<<8))
+ {
+ val = (val<0)?0:(256-(1<<upshift));
+ }
+ *dest = (kdu_byte) val;
+ }
+ }
+ }
+ else
+ { // Transferring 16-bit absolute integers.
+ kdu_int16 val;
+
+ if (precision >= 8)
+ {
+ kdu_int16 downshift = precision-8;
+ kdu_int16 offset = (1<<downshift)>>1;
+
+ for (; width > 0; width--, sp++, dest+=gap)
+ {
+ val = sp->ival;
+ val = (val+offset)>>downshift;
+ val += 128;
+ if (val & ((-1)<<8))
+ {
+ val = (val<0)?0:255;
+ }
+ *dest = (kdu_byte) val;
+ }
+ }
+ else
+ {
+ kdu_int16 upshift = 8-precision;
+
+ for (; width > 0; width--, sp++, dest+=gap)
+ {
+ val = sp->ival;
+ val <<= upshift;
+ val += 128;
+ if (val & ((-1)<<8))
+ {
+ val = (val<0)?0:(256-(1<<upshift));
+ }
+ *dest = (kdu_byte) val;
+ }
+ }
+ }
+ }
+}
+
+LLKDUDecodeState::LLKDUDecodeState(kdu_tile tile, kdu_byte *buf, S32 row_gap)
+{
+ S32 c;
+
+ mTile = tile;
+ mBuf = buf;
+ mRowGap = row_gap;
+
+ mNumComponents = tile.get_num_components();
+
+ llassert(mNumComponents<=4);
+ mUseYCC = tile.get_ycc();
+
+ for (c=0; c<4; ++c)
+ {
+ mReversible[c] = false;
+ mBitDepths[c] = 0;
+ }
+
+ // Open tile-components and create processing engines and resources
+ for (c=0; c < mNumComponents; c++)
+ {
+ mComps[c] = mTile.access_component(c);
+ mReversible[c] = mComps[c].get_reversible();
+ mBitDepths[c] = mComps[c].get_bit_depth();
+ kdu_resolution res = mComps[c].access_resolution(); // Get top resolution
+ kdu_dims comp_dims; res.get_dims(comp_dims);
+ if (c == 0)
+ {
+ mDims = comp_dims;
+ }
+ else
+ {
+ llassert(mDims == comp_dims); // Safety check; the caller has ensured this
+ }
+ bool use_shorts = (mComps[c].get_bit_depth(true) <= 16);
+ mLines[c].pre_create(&mAllocator,mDims.size.x,mReversible[c],use_shorts);
+ if (res.which() == 0) // No DWT levels used
+ {
+ mEngines[c] = kdu_decoder(res.access_subband(LL_BAND),&mAllocator,use_shorts);
+ }
+ else
+ {
+ mEngines[c] = kdu_synthesis(res,&mAllocator,use_shorts);
+ }
+ }
+ mAllocator.finalize(); // Actually creates buffering resources
+ for (c=0; c < mNumComponents; c++)
+ {
+ mLines[c].create(); // Grabs resources from the allocator.
+ }
+}
+
+LLKDUDecodeState::~LLKDUDecodeState()
+{
+ S32 c;
+ // Cleanup
+ for (c=0; c < mNumComponents; c++)
+ {
+ mEngines[c].destroy(); // engines are interfaces; no default destructors
+ }
+
+ mTile.close();
+}
+
+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,
+the `buf' pointer may actually point into a larger buffer representing
+multiple tiles. For this reason, `row_gap' is needed to identify the
+separation between consecutive rows in the real buffer. */
+{
+ S32 c;
+ // Now walk through the lines of the buffer, recovering them from the
+ // relevant tile-component processing engines.
+
+ LLTimer decode_timer;
+ while (mDims.size.y--)
+ {
+ for (c=0; c < mNumComponents; c++)
+ {
+ mEngines[c].pull(mLines[c],true);
+ }
+ if ((mNumComponents >= 3) && mUseYCC)
+ {
+ kdu_convert_ycc_to_rgb(mLines[0],mLines[1],mLines[2]);
+ }
+ for (c=0; c < mNumComponents; c++)
+ {
+ transfer_bytes(mBuf+c,mLines[c],mNumComponents,mBitDepths[c]);
+ }
+ mBuf += mRowGap;
+ if (mDims.size.y % 10)
+ {
+ if (limit_time && decode_timer.getElapsedTimeF32() > decode_time)
+ {
+ return FALSE;
+ }
+ }
+ }
+ return TRUE;
+}
+
+// kdc_flow_control
+
+kdc_flow_control::kdc_flow_control (kdu_image_in_base *img_in, kdu_codestream codestream)
+{
+ int n;
+
+ this->codestream = codestream;
+ codestream.get_valid_tiles(valid_tile_indices);
+ tile_idx = valid_tile_indices.pos;
+ tile = codestream.open_tile(tile_idx,NULL);
+
+ // Set up the individual components
+ num_components = codestream.get_num_components(true);
+ components = new kdc_component_flow_control[num_components];
+ count_delta = 0;
+ kdc_component_flow_control *comp = components;
+ for (n = 0; n < num_components; n++, comp++)
+ {
+ comp->line = NULL;
+ comp->reader = img_in;
+ kdu_coords subsampling;
+ codestream.get_subsampling(n,subsampling,true);
+ kdu_dims dims;
+ codestream.get_tile_dims(tile_idx,n,dims,true);
+ comp->vert_subsampling = subsampling.y;
+ if ((n == 0) || (comp->vert_subsampling < count_delta))
+ {
+ count_delta = comp->vert_subsampling;
+ }
+ comp->ratio_counter = 0;
+ comp->remaining_lines = comp->initial_lines = dims.size.y;
+ }
+ assert(num_components > 0);
+
+ tile.set_components_of_interest(num_components);
+ max_buffer_memory = engine.create(codestream,tile,false,NULL,false,1,NULL,NULL,false);
+}
+
+kdc_flow_control::~kdc_flow_control()
+{
+ if (components != NULL)
+ delete[] components;
+ if (engine.exists())
+ engine.destroy();
+}
+
+bool kdc_flow_control::advance_components()
+{
+ bool found_line = false;
+ while (!found_line)
+ {
+ bool all_done = true;
+ kdc_component_flow_control *comp = components;
+ for (int n = 0; n < num_components; n++, comp++)
+ {
+ assert(comp->ratio_counter >= 0);
+ if (comp->remaining_lines > 0)
+ {
+ all_done = false;
+ comp->ratio_counter -= count_delta;
+ if (comp->ratio_counter < 0)
+ {
+ found_line = true;
+ comp->line = engine.exchange_line(n,NULL,NULL);
+ assert(comp->line != NULL);
+ if (comp->line->get_width())
+ {
+ comp->reader->get(n,*(comp->line),0);
+ }
+ }
+ }
+ }
+ if (all_done)
+ {
+ return false;
+ }
+ }
+ return true;
+}
+
+void kdc_flow_control::process_components()
+{
+ kdc_component_flow_control *comp = components;
+ for (int n = 0; n < num_components; n++, comp++)
+ {
+ if (comp->ratio_counter < 0)
+ {
+ comp->ratio_counter += comp->vert_subsampling;
+ assert(comp->ratio_counter >= 0);
+ assert(comp->remaining_lines > 0);
+ comp->remaining_lines--;
+ assert(comp->line != NULL);
+ engine.exchange_line(n,comp->line,NULL);
+ comp->line = NULL;
+ }
+ }
+}
diff --git a/indra/llkdu/llimagej2ckdu.h b/indra/llkdu/llimagej2ckdu.h
new file mode 100644
index 0000000000..03f289f8b1
--- /dev/null
+++ b/indra/llkdu/llimagej2ckdu.h
@@ -0,0 +1,91 @@
+/**
+ * @file llimagej2ckdu.h
+ * @brief This is an implementation of JPEG2000 encode/decode using Kakadu
+ *
+ * $LicenseInfo:firstyear=2010&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLIMAGEJ2CKDU_H
+#define LL_LLIMAGEJ2CKDU_H
+
+#include "llimagej2c.h"
+
+//
+// KDU core header files
+//
+#include "kdu_elementary.h"
+#include "kdu_messaging.h"
+#include "kdu_params.h"
+#include "kdu_compressed.h"
+#include "kdu_sample_processing.h"
+
+class LLKDUDecodeState;
+class LLKDUMemSource;
+
+class LLImageJ2CKDU : public LLImageJ2CImpl
+{
+public:
+ enum ECodeStreamMode
+ {
+ MODE_FAST = 0,
+ MODE_RESILIENT = 1,
+ MODE_FUSSY = 2
+ };
+
+public:
+ LLImageJ2CKDU();
+ virtual ~LLImageJ2CKDU();
+
+protected:
+ /*virtual*/ BOOL getMetadata(LLImageJ2C &base);
+ /*virtual*/ BOOL decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decode_time, S32 first_channel, S32 max_channel_count);
+ /*virtual*/ BOOL encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, const char* comment_text, F32 encode_time=0.0,
+ BOOL reversible=FALSE);
+
+ void setupCodeStream(LLImageJ2C &base, BOOL keep_codestream, ECodeStreamMode mode);
+ void cleanupCodeStream();
+ BOOL initDecode(LLImageJ2C &base, LLImageRaw &raw_image, F32 decode_time, ECodeStreamMode mode, S32 first_channel, S32 max_channel_count );
+
+ // Encode variable
+ LLKDUMemSource *mInputp;
+ kdu_codestream *mCodeStreamp;
+ kdu_coords *mTPosp; // tile position
+ kdu_dims *mTileIndicesp;
+
+ // Temporary variables for in-progress decodes...
+ LLImageRaw *mRawImagep;
+ LLKDUDecodeState *mDecodeState;
+};
+
+#if LL_WINDOWS
+# define LLSYMEXPORT __declspec(dllexport)
+#elif LL_LINUX
+# define LLSYMEXPORT __attribute__ ((visibility("default")))
+#else
+# define LLSYMEXPORT
+#endif
+
+extern "C" LLSYMEXPORT const char* engineInfoLLImageJ2CKDU();
+extern "C" LLSYMEXPORT LLImageJ2CKDU* createLLImageJ2CKDU();
+extern "C" LLSYMEXPORT void destroyLLImageJ2CKDU(LLImageJ2CKDU* kdu);
+
+#endif
diff --git a/indra/llkdu/llkdumem.cpp b/indra/llkdu/llkdumem.cpp
new file mode 100644
index 0000000000..1f549cbbe0
--- /dev/null
+++ b/indra/llkdu/llkdumem.cpp
@@ -0,0 +1,196 @@
+ /**
+ * @file llkdumem.cpp
+ * @brief Helper class for kdu memory management
+ *
+ * $LicenseInfo:firstyear=2010&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+#include "llkdumem.h"
+#include "llerror.h"
+
+#if defined(LL_WINDOWS)
+# pragma warning(disable: 4702) // unreachable code
+#endif
+
+LLKDUMemIn::LLKDUMemIn(const U8 *data,
+ const U32 size,
+ const U16 width,
+ const U16 height,
+ const U8 in_num_components,
+ siz_params *siz)
+{
+ U8 n;
+
+ first_comp_idx = 0;
+ rows = height;
+ cols = width;
+ num_components = in_num_components;
+ alignment_bytes = 0;
+
+ for (n=0; n<3; ++n)
+ {
+ precision[n] = 0;
+ }
+
+ for (n=0; n < num_components; ++n)
+ {
+ siz->set(Sdims,n,0,rows);
+ siz->set(Sdims,n,1,cols);
+ siz->set(Ssigned,n,0,false);
+ siz->set(Sprecision,n,0,8);
+ }
+ incomplete_lines = NULL;
+ free_lines = NULL;
+ num_unread_rows = rows;
+
+ mData = data;
+ mDataSize = size;
+ mCurPos = 0;
+}
+
+LLKDUMemIn::~LLKDUMemIn()
+{
+ if ((num_unread_rows > 0) || (incomplete_lines != NULL))
+ {
+ kdu_warning w;
+ w << "Not all rows of image components "
+ << first_comp_idx << " through "
+ << first_comp_idx+num_components-1
+ << " were consumed!";
+ }
+ image_line_buf *tmp;
+ while ((tmp=incomplete_lines) != NULL)
+ {
+ incomplete_lines = tmp->next;
+ delete tmp;
+ }
+ while ((tmp=free_lines) != NULL)
+ {
+ free_lines = tmp->next;
+ delete tmp;
+ }
+}
+
+
+bool LLKDUMemIn::get(int comp_idx, kdu_line_buf &line, int x_tnum)
+{
+ int idx = comp_idx - this->first_comp_idx;
+ assert((idx >= 0) && (idx < num_components));
+ x_tnum = x_tnum*num_components+idx;
+ image_line_buf *scan, *prev=NULL;
+ for (scan=incomplete_lines; scan != NULL; prev=scan, scan=scan->next)
+ {
+ assert(scan->next_x_tnum >= x_tnum);
+ if (scan->next_x_tnum == x_tnum)
+ {
+ break;
+ }
+ }
+ if (scan == NULL)
+ { // Need to read a new image line.
+ assert(x_tnum == 0); // Must consume in very specific order.
+ if (num_unread_rows == 0)
+ {
+ return false;
+ }
+ if ((scan = free_lines) == NULL)
+ {
+ scan = new image_line_buf(cols+3,num_components);
+ }
+ free_lines = scan->next;
+ if (prev == NULL)
+ {
+ incomplete_lines = scan;
+ }
+ else
+ {
+ prev->next = scan;
+ }
+
+ // Copy from image buffer into scan.
+ memcpy(scan->buf, mData+mCurPos, cols*num_components);
+ mCurPos += cols*num_components;
+
+ num_unread_rows--;
+ scan->accessed_samples = 0;
+ scan->next_x_tnum = 0;
+ }
+
+ assert((cols-scan->accessed_samples) >= line.get_width());
+
+ int comp_offset = idx;
+ kdu_byte *sp = scan->buf+num_components*scan->accessed_samples + comp_offset;
+ int n=line.get_width();
+
+ if (line.get_buf32() != NULL)
+ {
+ kdu_sample32 *dp = line.get_buf32();
+ if (line.is_absolute())
+ { // 32-bit absolute integers
+ for (; n > 0; n--, sp+=num_components, dp++)
+ {
+ dp->ival = ((kdu_int32)(*sp)) - 128;
+ }
+ }
+ else
+ { // true 32-bit floats
+ for (; n > 0; n--, sp+=num_components, dp++)
+ {
+ dp->fval = (((float)(*sp)) / 256.0F) - 0.5F;
+ }
+ }
+ }
+ else
+ {
+ kdu_sample16 *dp = line.get_buf16();
+ if (line.is_absolute())
+ { // 16-bit absolute integers
+ for (; n > 0; n--, sp+=num_components, dp++)
+ {
+ dp->ival = ((kdu_int16)(*sp)) - 128;
+ }
+ }
+ else
+ { // 16-bit normalized representation.
+ for (; n > 0; n--, sp+=num_components, dp++)
+ {
+ dp->ival = (((kdu_int16)(*sp)) - 128) << (KDU_FIX_POINT-8);
+ }
+ }
+ }
+
+ scan->next_x_tnum++;
+ if (idx == (num_components-1))
+ {
+ scan->accessed_samples += line.get_width();
+ }
+ if (scan->accessed_samples == cols)
+ { // Send empty line to free list.
+ assert(scan == incomplete_lines);
+ incomplete_lines = scan->next;
+ scan->next = free_lines;
+ free_lines = scan;
+ }
+
+ return true;
+}
diff --git a/indra/llkdu/llkdumem.h b/indra/llkdu/llkdumem.h
new file mode 100644
index 0000000000..7064de4408
--- /dev/null
+++ b/indra/llkdu/llkdumem.h
@@ -0,0 +1,145 @@
+/**
+ * @file llkdumem.h
+ * @brief Helper class for kdu memory management
+ *
+ * $LicenseInfo:firstyear=2010&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLKDUMEM_H
+#define LL_LLKDUMEM_H
+
+// Support classes for reading and writing from memory buffers in KDU
+#include "kdu_image.h"
+#include "kdu_elementary.h"
+#include "kdu_messaging.h"
+#include "kdu_params.h"
+#include "kdu_compressed.h"
+#include "kdu_sample_processing.h"
+#include "image_local.h"
+#include "stdtypes.h"
+
+class LLKDUMemSource: public kdu_compressed_source
+{
+public: // Member functions
+ LLKDUMemSource(U8 *input_buffer, U32 size)
+ {
+ mData = input_buffer;
+ mSize = size;
+ mCurPos = 0;
+ }
+
+ ~LLKDUMemSource()
+ {
+ }
+
+ int read(kdu_byte *buf, int num_bytes)
+ {
+ U32 num_out;
+ num_out = num_bytes;
+
+ if ((mSize - mCurPos) < (U32)num_bytes)
+ {
+ num_out = mSize -mCurPos;
+ }
+ memcpy(buf, mData + mCurPos, num_out);
+ mCurPos += num_out;
+ return num_out;
+ }
+
+ void reset()
+ {
+ mCurPos = 0;
+ }
+
+private: // Data
+ U8 *mData;
+ U32 mSize;
+ U32 mCurPos;
+};
+
+class LLKDUMemTarget: public kdu_compressed_target
+{
+public: // Member functions
+ LLKDUMemTarget(U8 *output_buffer, U32 &output_size, const U32 buffer_size)
+ {
+ mData = output_buffer;
+ mSize = buffer_size;
+ mCurPos = 0;
+ mOutputSize = &output_size;
+ }
+
+ ~LLKDUMemTarget()
+ {
+ }
+
+ bool write(const kdu_byte *buf, int num_bytes)
+ {
+ U32 num_out;
+ num_out = num_bytes;
+
+ if ((mSize - mCurPos) < (U32)num_bytes)
+ {
+ num_out = mSize - mCurPos;
+ memcpy(mData + mCurPos, buf, num_out);
+ return false;
+ }
+ memcpy(mData + mCurPos, buf, num_out);
+ mCurPos += num_out;
+ *mOutputSize = mCurPos;
+ return true;
+ }
+
+private: // Data
+ U8 *mData;
+ U32 mSize;
+ U32 mCurPos;
+ U32 *mOutputSize;
+};
+
+class LLKDUMemIn : public kdu_image_in_base
+{
+public: // Member functions
+ LLKDUMemIn(const U8 *data,
+ const U32 size,
+ const U16 rows,
+ const U16 cols,
+ U8 in_num_components,
+ siz_params *siz);
+ ~LLKDUMemIn();
+
+ bool get(int comp_idx, kdu_line_buf &line, int x_tnum);
+
+private: // Data
+ const U8 *mData;
+ int first_comp_idx;
+ int num_components;
+ int rows, cols;
+ int alignment_bytes; // Number of 0's at end of each line.
+ int precision[3];
+ image_line_buf *incomplete_lines; // Each "sample" represents a full pixel
+ image_line_buf *free_lines;
+ int num_unread_rows;
+
+ U32 mCurPos;
+ U32 mDataSize;
+};
+#endif
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 1176edc130..4869aa72a0 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -50,6 +50,7 @@ include_directories(
${LLCHARACTER_INCLUDE_DIRS}
${LLCOMMON_INCLUDE_DIRS}
${LLIMAGE_INCLUDE_DIRS}
+ ${LLKDU_INCLUDE_DIRS}
${LLINVENTORY_INCLUDE_DIRS}
${LLMATH_INCLUDE_DIRS}
${LLMESSAGE_INCLUDE_DIRS}
@@ -1455,11 +1456,6 @@ if (WINDOWS)
# In the meantime, if you have any ideas on how to easily maintain one list, either here or in viewer_manifest.py
# and have the build deps get tracked *please* tell me about it.
- if(LLKDU_LIBRARY)
- # Configure a var for llkdu which may not exist for all builds.
- set(LLKDU_DLL_SOURCE ${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/llkdu.dll)
- endif(LLKDU_LIBRARY)
-
if(USE_GOOGLE_PERFTOOLS)
# Configure a var for tcmalloc location, if used.
# Note the need to specify multiple names explicitly.
@@ -1476,7 +1472,6 @@ if (WINDOWS)
#${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/libtcmalloc_minimal.dll => None ... Skipping libtcmalloc_minimal.dll
${CMAKE_SOURCE_DIR}/../etc/message.xml
${CMAKE_SOURCE_DIR}/../scripts/messages/message_template.msg
- ${LLKDU_DLL_SOURCE}
${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/llcommon.dll
${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/libapr-1.dll
${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/libaprutil-1.dll
@@ -1662,7 +1657,6 @@ target_link_libraries(${VIEWER_BINARY_NAME}
${LLAUDIO_LIBRARIES}
${LLCHARACTER_LIBRARIES}
${LLIMAGE_LIBRARIES}
- ${LLIMAGEJ2COJ_LIBRARIES}
${LLINVENTORY_LIBRARIES}
${LLMESSAGE_LIBRARIES}
${LLPLUGIN_LIBRARIES}
@@ -1698,6 +1692,17 @@ target_link_libraries(${VIEWER_BINARY_NAME}
${GOOGLE_PERFTOOLS_LIBRARIES}
)
+if (USE_KDU)
+ target_link_libraries(${VIEWER_BINARY_NAME}
+ ${LLKDU_LIBRARIES}
+ ${KDU_LIBRARY}
+ )
+else (USE_KDU)
+ target_link_libraries(${VIEWER_BINARY_NAME}
+ ${LLIMAGEJ2COJ_LIBRARIES}
+ )
+endif (USE_KDU)
+
build_version(viewer)
set(ARTWORK_DIR ${CMAKE_CURRENT_SOURCE_DIR} CACHE PATH
diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py
index 6c77f8ec38..338c62b9fb 100644
--- a/indra/newview/viewer_manifest.py
+++ b/indra/newview/viewer_manifest.py
@@ -255,12 +255,6 @@ class WindowsManifest(ViewerManifest):
self.enable_crt_manifest_check()
- # Get kdu dll, continue if missing.
- try:
- self.path('llkdu.dll', dst='llkdu.dll')
- except RuntimeError:
- print "Skipping llkdu.dll"
-
# Get llcommon and deps. If missing assume static linkage and continue.
try:
self.path('llcommon.dll')
@@ -625,21 +619,21 @@ class DarwinManifest(ViewerManifest):
libdir = "../../libraries/universal-darwin/lib_release"
dylibs = {}
- # need to get the kdu dll from any of the build directories as well
- for lib in "llkdu", "llcommon":
- libfile = "lib%s.dylib" % lib
- try:
- self.path(self.find_existing_file(os.path.join(os.pardir,
- lib,
- self.args['configuration'],
- libfile),
- os.path.join(libdir, libfile)),
- dst=libfile)
- except RuntimeError:
- print "Skipping %s" % libfile
- dylibs[lib] = False
- else:
- dylibs[lib] = True
+ # Need to get the llcommon dll from any of the build directories as well
+ lib = "llcommon"
+ libfile = "lib%s.dylib" % lib
+ try:
+ self.path(self.find_existing_file(os.path.join(os.pardir,
+ lib,
+ self.args['configuration'],
+ libfile),
+ os.path.join(libdir, libfile)),
+ dst=libfile)
+ except RuntimeError:
+ print "Skipping %s" % libfile
+ dylibs[lib] = False
+ else:
+ dylibs[lib] = True
if dylibs["llcommon"]:
for libfile in ("libapr-1.0.3.7.dylib",
@@ -931,15 +925,6 @@ class Linux_i686Manifest(LinuxManifest):
def construct(self):
super(Linux_i686Manifest, self).construct()
- # install either the libllkdu we just built, or a prebuilt one, in
- # decreasing order of preference. for linux package, this goes to bin/
- try:
- self.path(self.find_existing_file('../llkdu/libllkdu.so',
- '../../libraries/i686-linux/lib_release_client/libllkdu.so'),
- dst='bin/libllkdu.so')
- except:
- print "Skipping libllkdu.so - not found"
-
if self.prefix("../../libraries/i686-linux/lib_release_client", dst="lib"):
self.path("libapr-1.so.0")
self.path("libaprutil-1.so.0")
@@ -956,12 +941,6 @@ class Linux_i686Manifest(LinuxManifest):
self.path("libopenal.so", "libopenal.so.1")
self.path("libopenal.so", "libvivoxoal.so.1") # vivox's sdk expects this soname
try:
- self.path("libkdu.so")
- pass
- except:
- print "Skipping libkdu.so - not found"
- pass
- try:
self.path("libfmod-3.75.so")
pass
except:
diff --git a/install.xml b/install.xml
index e727ba0e11..36e7824e1c 100644
--- a/install.xml
+++ b/install.xml
@@ -830,23 +830,23 @@
<key>darwin</key>
<map>
<key>md5sum</key>
- <string>ae18dd120807a46ac961b881a631ad94</string>
+ <string>8261994de5af6581e08c26fefe1b2810</string>
<key>url</key>
- <uri>scp:install-packages.lindenlab.com:/local/www/install-packages/doc/indra_private-2.1.1-darwin-20100820.tar.bz2</uri>
+ <uri>scp:install-packages.lindenlab.com:/local/www/install-packages/doc/kdu-6.4.1-darwin-20101123.tar.bz2</uri>
</map>
<key>linux</key>
<map>
<key>md5sum</key>
- <string>b1f15bbabb68445e55ce23a2aeaca598</string>
+ <string>ed3e58899a424684dad49c94ba3813e7</string>
<key>url</key>
- <uri>scp:install-packages.lindenlab.com:/local/www/install-packages/doc/indra_private-2.1.1-linux-20100826.tar.bz2</uri>
+ <uri>scp:install-packages.lindenlab.com:/local/www/install-packages/doc/kdu-6.4.1-linux-20101124.tar.bz2</uri>
</map>
<key>windows</key>
<map>
<key>md5sum</key>
- <string>0e2fe621ce99085eba00d86d9a3bc130</string>
+ <string>066e089a5d9faeaf131e1f4e4860a163</string>
<key>url</key>
- <uri>scp:install-packages.lindenlab.com:/local/www/install-packages/doc/indra_private-2.1.1-windows-20100820.tar.bz2</uri>
+ <uri>scp:install-packages.lindenlab.com:/local/www/install-packages/doc/kdu-6.4.1-windows-20101123.tar.bz2</uri>
</map>
</map>
</map>