summaryrefslogtreecommitdiff
path: root/indra
diff options
context:
space:
mode:
authorJosh Bell <josh@lindenlab.com>2007-03-09 01:09:20 +0000
committerJosh Bell <josh@lindenlab.com>2007-03-09 01:09:20 +0000
commitb36dc363061ec5bf6b092c14193198e9a5eef816 (patch)
treeb067586bd545dfa6dce9dd0b1243b9c0aa143f33 /indra
parent6fa974fc64b172a7324b28d40f08f2a861d87f8d (diff)
svn merge -r 58902:58986 svn+ssh://svn.lindenlab.com/svn/linden/branches/maintenance --> release
Diffstat (limited to 'indra')
-rw-r--r--indra/llcommon/llavatarconstants.h12
-rw-r--r--indra/llcommon/llbase64.cpp86
-rw-r--r--indra/llcommon/llbase64.h38
-rw-r--r--indra/llcommon/llfasttimer.h1
-rw-r--r--indra/llcommon/llliveappconfig.cpp92
-rw-r--r--indra/llcommon/llliveappconfig.h66
-rw-r--r--indra/llcommon/lluri.cpp3
-rw-r--r--indra/llcommon/metaproperty.cpp2
-rw-r--r--indra/llimage/llimageworker.cpp330
-rw-r--r--indra/llimage/llimageworker.h114
-rw-r--r--indra/llmath/lloctree.h4
-rw-r--r--indra/llrender/llimagegl.cpp2
-rw-r--r--indra/llrender/llvertexbuffer.cpp32
-rw-r--r--indra/llrender/llvertexbuffer.h6
-rw-r--r--indra/llui/llctrlselectioninterface.cpp88
-rw-r--r--indra/llui/llctrlselectioninterface.h168
-rw-r--r--indra/llui/llscrolllistctrl.cpp9
-rw-r--r--indra/llui/llviewquery.cpp252
-rw-r--r--indra/llui/llviewquery.h178
-rw-r--r--indra/newview/lldrawable.cpp4
-rw-r--r--indra/newview/llface.cpp10
-rw-r--r--indra/newview/llfasttimerview.cpp2
-rw-r--r--indra/newview/llflexibleobject.cpp17
-rw-r--r--indra/newview/llfloaterinspect.cpp441
-rw-r--r--indra/newview/llfloaterinspect.h100
-rw-r--r--indra/newview/llfloaterland.cpp4
-rw-r--r--indra/newview/llfloaterpostcard.cpp2
-rw-r--r--indra/newview/llfloaterproperties.cpp4
-rw-r--r--indra/newview/llfloatertools.cpp2
-rw-r--r--indra/newview/llgroupmgr.cpp4
-rw-r--r--indra/newview/llinventorybridge.cpp8
-rw-r--r--indra/newview/llmaniptranslate.cpp2
-rw-r--r--indra/newview/llpanelavatar.cpp22
-rw-r--r--indra/newview/llpanelclassified.cpp9
-rw-r--r--indra/newview/llpanelgroup.cpp2
-rw-r--r--indra/newview/llpanelgrouproles.cpp7
-rw-r--r--indra/newview/llpreview.cpp2
-rw-r--r--indra/newview/llselectmgr.cpp2
-rw-r--r--indra/newview/llspatialpartition.cpp118
-rw-r--r--indra/newview/llspatialpartition.h3
-rw-r--r--indra/newview/lltexturecache.cpp2730
-rw-r--r--indra/newview/lltexturecache.h298
-rw-r--r--indra/newview/lltexturefetch.cpp6
-rw-r--r--indra/newview/lltexturefetch.h2
-rw-r--r--indra/newview/llviewerdisplay.cpp10
-rw-r--r--indra/newview/llviewermenu.cpp3
-rw-r--r--indra/newview/llviewermessage.cpp2
-rw-r--r--indra/newview/llviewernetwork.cpp2
-rw-r--r--indra/newview/llviewerparcelmgr.cpp10
-rw-r--r--indra/newview/llviewerwindow.cpp7
-rw-r--r--indra/newview/llvoavatar.cpp10
-rw-r--r--indra/newview/llvovolume.cpp64
-rw-r--r--indra/newview/llvovolume.h2
-rw-r--r--indra/newview/pipeline.cpp11
-rw-r--r--indra/newview/pipeline.h3
55 files changed, 2754 insertions, 2654 deletions
diff --git a/indra/llcommon/llavatarconstants.h b/indra/llcommon/llavatarconstants.h
index 67bd329732..d66627c4b0 100644
--- a/indra/llcommon/llavatarconstants.h
+++ b/indra/llcommon/llavatarconstants.h
@@ -20,16 +20,16 @@ const char* const BLACKLIST_PROFILE_WEB_URL = "http://secondlife.com/app/webdisa
// Maximum number of avatar picks
const S32 MAX_AVATAR_PICKS = 10;
-// For Flags in AvatarPropertiesReply
-const U32 AVATAR_ALLOW_PUBLISH = 0x1 << 0; // whether profile is externally visible or not
-const U32 AVATAR_MATURE_PUBLISH = 0x1 << 1; // profile is "mature"
-const U32 AVATAR_IDENTIFIED = 0x1 << 2; // whether avatar has provided payment info
+// For Flags in AvatarPropertiesReply
+const U32 AVATAR_ALLOW_PUBLISH = 0x1 << 0; // whether profile is externally visible or not
+const U32 AVATAR_MATURE_PUBLISH = 0x1 << 1; // profile is "mature"
+const U32 AVATAR_IDENTIFIED = 0x1 << 2; // whether avatar has provided payment info
const U32 AVATAR_TRANSACTED = 0x1 << 3; // whether avatar has actively used payment info
const U32 AVATAR_ONLINE = 0x1 << 4; // the online status of this avatar, if known.
-static const std::string VISIBILITY_DEFAULT("default");
+static const std::string VISIBILITY_DEFAULT("default");
static const std::string VISIBILITY_HIDDEN("hidden");
-static const std::string VISIBILITY_VISIBLE("visible");
+static const std::string VISIBILITY_VISIBLE("visible");
static const std::string VISIBILITY_INVISIBLE("invisible");
#endif
diff --git a/indra/llcommon/llbase64.cpp b/indra/llcommon/llbase64.cpp
index 88e9d960a2..6c4bc59e68 100644
--- a/indra/llcommon/llbase64.cpp
+++ b/indra/llcommon/llbase64.cpp
@@ -1,43 +1,43 @@
-/**
- * @file llbase64.cpp
- * @brief Wrapper for apr base64 encoding that returns a std::string
- * @author James Cook
- *
- * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
- * $License$
- */
-
-#include "linden_common.h"
-
-#include "llbase64.h"
-
-#include <string>
-
-#include "apr-1/apr_base64.h"
-
-
-// static
-std::string LLBase64::encode(const U8* input, size_t input_size)
-{
- std::string output;
- if (input
- && input_size > 0)
- {
- // Yes, it returns int.
- int b64_buffer_length = apr_base64_encode_len(input_size);
- char* b64_buffer = new char[b64_buffer_length];
-
- // This is faster than apr_base64_encode() if you know
- // you're not on an EBCDIC machine. Also, the output is
- // null terminated, even though the documentation doesn't
- // specify. See apr_base64.c for details. JC
- b64_buffer_length = apr_base64_encode_binary(
- b64_buffer,
- input,
- input_size);
- output.assign(b64_buffer);
- delete[] b64_buffer;
- }
- return output;
-}
-
+/**
+ * @file llbase64.cpp
+ * @brief Wrapper for apr base64 encoding that returns a std::string
+ * @author James Cook
+ *
+ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+#include "linden_common.h"
+
+#include "llbase64.h"
+
+#include <string>
+
+#include "apr-1/apr_base64.h"
+
+
+// static
+std::string LLBase64::encode(const U8* input, size_t input_size)
+{
+ std::string output;
+ if (input
+ && input_size > 0)
+ {
+ // Yes, it returns int.
+ int b64_buffer_length = apr_base64_encode_len(input_size);
+ char* b64_buffer = new char[b64_buffer_length];
+
+ // This is faster than apr_base64_encode() if you know
+ // you're not on an EBCDIC machine. Also, the output is
+ // null terminated, even though the documentation doesn't
+ // specify. See apr_base64.c for details. JC
+ b64_buffer_length = apr_base64_encode_binary(
+ b64_buffer,
+ input,
+ input_size);
+ output.assign(b64_buffer);
+ delete[] b64_buffer;
+ }
+ return output;
+}
+
diff --git a/indra/llcommon/llbase64.h b/indra/llcommon/llbase64.h
index 6e8b817ba7..4f59ceded6 100644
--- a/indra/llcommon/llbase64.h
+++ b/indra/llcommon/llbase64.h
@@ -1,19 +1,19 @@
-/**
- * @file llbase64.h
- * @brief Wrapper for apr base64 encoding that returns a std::string
- * @author James Cook
- *
- * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
- * $License$
- */
-
-#ifndef LLBASE64_H
-#define LLBASE64_h
-
-class LLBase64
-{
-public:
- static std::string encode(const U8* input, size_t input_size);
-};
-
-#endif
+/**
+ * @file llbase64.h
+ * @brief Wrapper for apr base64 encoding that returns a std::string
+ * @author James Cook
+ *
+ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+#ifndef LLBASE64_H
+#define LLBASE64_h
+
+class LLBase64
+{
+public:
+ static std::string encode(const U8* input, size_t input_size);
+};
+
+#endif
diff --git a/indra/llcommon/llfasttimer.h b/indra/llcommon/llfasttimer.h
index 16af098ed5..3e88784d3c 100644
--- a/indra/llcommon/llfasttimer.h
+++ b/indra/llcommon/llfasttimer.h
@@ -25,6 +25,7 @@ public:
FTM_UPDATE,
FTM_RENDER,
FTM_SWAP,
+ FTM_CLIENT_COPY,
FTM_IDLE,
FTM_SLEEP,
diff --git a/indra/llcommon/llliveappconfig.cpp b/indra/llcommon/llliveappconfig.cpp
index 8bcaeb898f..b446c1f18e 100644
--- a/indra/llcommon/llliveappconfig.cpp
+++ b/indra/llcommon/llliveappconfig.cpp
@@ -1,46 +1,46 @@
-/**
- * @file llliveappconfig.cpp
- * @brief Configuration information for an LLApp that overrides indra.xml
- *
- * Copyright (c) 2003-$CurrentYear$, Linden Research, Inc.
- * $License$
- */
-
-#include "linden_common.h"
-
-#include "llliveappconfig.h"
-
-#include "llapp.h"
-#include "llsd.h"
-#include "llsdserialize.h"
-
-LLLiveAppConfig::LLLiveAppConfig(LLApp* app, const std::string& filename, F32 refresh_period)
-: LLLiveFile(filename, refresh_period),
- mApp(app)
-{ }
-
-
-LLLiveAppConfig::~LLLiveAppConfig()
-{ }
-
-// virtual
-void LLLiveAppConfig::loadFile()
-{
- llinfos << "LLLiveAppConfig::loadFile(): reading from "
- << filename() << llendl;
- llifstream file(filename().c_str());
- LLSD config;
- if (file.is_open())
- {
- LLSDSerialize::fromXML(config, file);
- if(!config.isMap())
- {
- llinfos << "LLDataserverConfig::loadFile(): not an map!"
- << " Ignoring the data." << llendl;
- return;
- }
- file.close();
- }
- mApp->setOptionData(
- LLApp::PRIORITY_SPECIFIC_CONFIGURATION, config);
-}
+/**
+ * @file llliveappconfig.cpp
+ * @brief Configuration information for an LLApp that overrides indra.xml
+ *
+ * Copyright (c) 2003-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+#include "linden_common.h"
+
+#include "llliveappconfig.h"
+
+#include "llapp.h"
+#include "llsd.h"
+#include "llsdserialize.h"
+
+LLLiveAppConfig::LLLiveAppConfig(LLApp* app, const std::string& filename, F32 refresh_period)
+: LLLiveFile(filename, refresh_period),
+ mApp(app)
+{ }
+
+
+LLLiveAppConfig::~LLLiveAppConfig()
+{ }
+
+// virtual
+void LLLiveAppConfig::loadFile()
+{
+ llinfos << "LLLiveAppConfig::loadFile(): reading from "
+ << filename() << llendl;
+ llifstream file(filename().c_str());
+ LLSD config;
+ if (file.is_open())
+ {
+ LLSDSerialize::fromXML(config, file);
+ if(!config.isMap())
+ {
+ llinfos << "LLDataserverConfig::loadFile(): not an map!"
+ << " Ignoring the data." << llendl;
+ return;
+ }
+ file.close();
+ }
+ mApp->setOptionData(
+ LLApp::PRIORITY_SPECIFIC_CONFIGURATION, config);
+}
diff --git a/indra/llcommon/llliveappconfig.h b/indra/llcommon/llliveappconfig.h
index ceceda5b18..8875f3adc3 100644
--- a/indra/llcommon/llliveappconfig.h
+++ b/indra/llcommon/llliveappconfig.h
@@ -1,33 +1,33 @@
-/**
- * @file llliveappconfig.h
- * @brief Configuration information for an LLApp that overrides indra.xml
- *
- * Copyright (c) 2003-$CurrentYear$, Linden Research, Inc.
- * $License$
- */
-
-#ifndef LLLIVEAPPCONFIG_H
-#define LLLIVEAPPCONFIG_H
-
-#include "lllivefile.h"
-
-class LLApp;
-
-class LLLiveAppConfig : public LLLiveFile
-{
-public:
- // To use this, instantiate a LLLiveAppConfig object inside your main loop.
- // The traditional name for it is live_config.
- // Be sure to call live_config.checkAndReload() periodically.
-
- LLLiveAppConfig(LLApp* app, const std::string& filename, F32 refresh_period);
- ~LLLiveAppConfig();
-
-protected:
- /*virtual*/ void loadFile();
-
-private:
- LLApp* mApp;
-};
-
-#endif
+/**
+ * @file llliveappconfig.h
+ * @brief Configuration information for an LLApp that overrides indra.xml
+ *
+ * Copyright (c) 2003-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+#ifndef LLLIVEAPPCONFIG_H
+#define LLLIVEAPPCONFIG_H
+
+#include "lllivefile.h"
+
+class LLApp;
+
+class LLLiveAppConfig : public LLLiveFile
+{
+public:
+ // To use this, instantiate a LLLiveAppConfig object inside your main loop.
+ // The traditional name for it is live_config.
+ // Be sure to call live_config.checkAndReload() periodically.
+
+ LLLiveAppConfig(LLApp* app, const std::string& filename, F32 refresh_period);
+ ~LLLiveAppConfig();
+
+protected:
+ /*virtual*/ void loadFile();
+
+private:
+ LLApp* mApp;
+};
+
+#endif
diff --git a/indra/llcommon/lluri.cpp b/indra/llcommon/lluri.cpp
index cf06fe3f40..1f64c3bde3 100644
--- a/indra/llcommon/lluri.cpp
+++ b/indra/llcommon/lluri.cpp
@@ -359,8 +359,7 @@ LLURI LLURI::buildHTTP(const std::string& host_port,
LLURI result;
// TODO: deal with '/' '?' '#' in host_port
- S32 index = host_port.find("://");
- if (index != host_port.npos)
+ if (host_port.find("://") != host_port.npos)
{
// The scheme is part of the host_port
result.mScheme = "";
diff --git a/indra/llcommon/metaproperty.cpp b/indra/llcommon/metaproperty.cpp
index befee61a8a..adcda03389 100644
--- a/indra/llcommon/metaproperty.cpp
+++ b/indra/llcommon/metaproperty.cpp
@@ -25,7 +25,7 @@ const LLMetaClass& LLMetaProperty::getObjectMetaClass() const
{
return mObjectClass;
}
-
+
void LLMetaProperty::checkObjectClass(const LLReflective* object) const
{
if(! mObjectClass.isInstance(object))
diff --git a/indra/llimage/llimageworker.cpp b/indra/llimage/llimageworker.cpp
index b44bf19227..297482a222 100644
--- a/indra/llimage/llimageworker.cpp
+++ b/indra/llimage/llimageworker.cpp
@@ -1,165 +1,165 @@
-/**
- * @file llimage.cpp
- * @brief Base class for images.
- *
- * Copyright (c) 2001-$CurrentYear$, Linden Research, Inc.
- * $License$
- */
-
-#include "linden_common.h"
-
-#include "llimageworker.h"
-#include "llimagedxt.h"
-
-//----------------------------------------------------------------------------
-
-//static
-LLWorkerThread* LLImageWorker::sWorkerThread = NULL;
-S32 LLImageWorker::sCount = 0;
-
-//static
-void LLImageWorker::initClass(LLWorkerThread* workerthread)
-{
- sWorkerThread = workerthread;
-}
-
-//static
-void LLImageWorker::cleanupClass()
-{
-}
-
-//----------------------------------------------------------------------------
-
-LLImageWorker::LLImageWorker(LLImageFormatted* image, U32 priority, S32 discard, LLResponder* responder)
- : LLWorkerClass(sWorkerThread, "Image"),
- mFormattedImage(image),
- mDecodedType(-1),
- mDiscardLevel(discard),
- mPriority(priority),
- mResponder(responder)
-{
- ++sCount;
-}
-
-LLImageWorker::~LLImageWorker()
-{
- mDecodedImage = NULL;
- mFormattedImage = NULL;
- --sCount;
-}
-
-//----------------------------------------------------------------------------
-
-//virtual, main thread
-void LLImageWorker::startWork(S32 param)
-{
- llassert_always(mDecodedImage.isNull());
- mDecodedType = -1;
-}
-
-bool LLImageWorker::doWork(S32 param)
-{
- bool decoded = false;
- if(mDecodedImage.isNull())
- {
- if (!mFormattedImage->updateData())
- {
- mDecodedType = -2; // failed
- return true;
- }
- if (mDiscardLevel >= 0)
- {
- mFormattedImage->setDiscardLevel(mDiscardLevel);
- }
- if (!(mFormattedImage->getWidth() * mFormattedImage->getHeight() * mFormattedImage->getComponents()))
- {
- decoded = true; // failed
- }
- else
- {
- S32 nc = param ? 1 : mFormattedImage->getComponents();
- mDecodedImage = new LLImageRaw(mFormattedImage->getWidth(),
- mFormattedImage->getHeight(),
- nc);
- }
- }
- if (!decoded)
- {
- if (param == 0)
- {
- // Decode primary channels
- decoded = mFormattedImage->decode(mDecodedImage, .1f); // 1ms
- }
- else
- {
- // Decode aux channel
- decoded = mFormattedImage->decode(mDecodedImage, .1f, param, param); // 1ms
- }
- }
- if (decoded)
- {
- // Call the callback immediately; endWork doesn't get called until ckeckWork
- if (mResponder.notNull())
- {
- bool success = (!wasAborted() && mDecodedImage.notNull() && mDecodedImage->getDataSize() != 0);
- mResponder->completed(success);
- }
- }
- return decoded;
-}
-
-void LLImageWorker::endWork(S32 param, bool aborted)
-{
- if (mDecodedType != -2)
- {
- mDecodedType = aborted ? -2 : param;
- }
-}
-
-//----------------------------------------------------------------------------
-
-
-BOOL LLImageWorker::requestDecodedAuxData(LLPointer<LLImageRaw>& raw, S32 channel, S32 discard)
-{
- // For most codecs, only mDiscardLevel data is available.
- // (see LLImageDXT for exception)
- if (discard >= 0 && discard != mFormattedImage->getDiscardLevel())
- {
- llerrs << "Request for invalid discard level" << llendl;
- }
- checkWork();
- if (mDecodedType == -2)
- {
- return TRUE; // aborted, done
- }
- if (mDecodedType != channel)
- {
- if (!haveWork())
- {
- addWork(channel, mPriority);
- }
- return FALSE;
- }
- else
- {
- llassert_always(!haveWork());
- llassert_always(mDecodedType == channel);
- raw = mDecodedImage; // smart pointer acquires ownership of data
- mDecodedImage = NULL;
- return TRUE;
- }
-}
-
-BOOL LLImageWorker::requestDecodedData(LLPointer<LLImageRaw>& raw, S32 discard)
-{
- if (mFormattedImage->getCodec() == IMG_CODEC_DXT)
- {
- // special case
- LLImageDXT* imagedxt = (LLImageDXT*)((LLImageFormatted*)mFormattedImage);
- return imagedxt->getMipData(raw, discard);
- }
- else
- {
- return requestDecodedAuxData(raw, 0, discard);
- }
-}
+/**
+ * @file llimage.cpp
+ * @brief Base class for images.
+ *
+ * Copyright (c) 2001-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+#include "linden_common.h"
+
+#include "llimageworker.h"
+#include "llimagedxt.h"
+
+//----------------------------------------------------------------------------
+
+//static
+LLWorkerThread* LLImageWorker::sWorkerThread = NULL;
+S32 LLImageWorker::sCount = 0;
+
+//static
+void LLImageWorker::initClass(LLWorkerThread* workerthread)
+{
+ sWorkerThread = workerthread;
+}
+
+//static
+void LLImageWorker::cleanupClass()
+{
+}
+
+//----------------------------------------------------------------------------
+
+LLImageWorker::LLImageWorker(LLImageFormatted* image, U32 priority, S32 discard, LLResponder* responder)
+ : LLWorkerClass(sWorkerThread, "Image"),
+ mFormattedImage(image),
+ mDecodedType(-1),
+ mDiscardLevel(discard),
+ mPriority(priority),
+ mResponder(responder)
+{
+ ++sCount;
+}
+
+LLImageWorker::~LLImageWorker()
+{
+ mDecodedImage = NULL;
+ mFormattedImage = NULL;
+ --sCount;
+}
+
+//----------------------------------------------------------------------------
+
+//virtual, main thread
+void LLImageWorker::startWork(S32 param)
+{
+ llassert_always(mDecodedImage.isNull());
+ mDecodedType = -1;
+}
+
+bool LLImageWorker::doWork(S32 param)
+{
+ bool decoded = false;
+ if(mDecodedImage.isNull())
+ {
+ if (!mFormattedImage->updateData())
+ {
+ mDecodedType = -2; // failed
+ return true;
+ }
+ if (mDiscardLevel >= 0)
+ {
+ mFormattedImage->setDiscardLevel(mDiscardLevel);
+ }
+ if (!(mFormattedImage->getWidth() * mFormattedImage->getHeight() * mFormattedImage->getComponents()))
+ {
+ decoded = true; // failed
+ }
+ else
+ {
+ S32 nc = param ? 1 : mFormattedImage->getComponents();
+ mDecodedImage = new LLImageRaw(mFormattedImage->getWidth(),
+ mFormattedImage->getHeight(),
+ nc);
+ }
+ }
+ if (!decoded)
+ {
+ if (param == 0)
+ {
+ // Decode primary channels
+ decoded = mFormattedImage->decode(mDecodedImage, .1f); // 1ms
+ }
+ else
+ {
+ // Decode aux channel
+ decoded = mFormattedImage->decode(mDecodedImage, .1f, param, param); // 1ms
+ }
+ }
+ if (decoded)
+ {
+ // Call the callback immediately; endWork doesn't get called until ckeckWork
+ if (mResponder.notNull())
+ {
+ bool success = (!wasAborted() && mDecodedImage.notNull() && mDecodedImage->getDataSize() != 0);
+ mResponder->completed(success);
+ }
+ }
+ return decoded;
+}
+
+void LLImageWorker::endWork(S32 param, bool aborted)
+{
+ if (mDecodedType != -2)
+ {
+ mDecodedType = aborted ? -2 : param;
+ }
+}
+
+//----------------------------------------------------------------------------
+
+
+BOOL LLImageWorker::requestDecodedAuxData(LLPointer<LLImageRaw>& raw, S32 channel, S32 discard)
+{
+ // For most codecs, only mDiscardLevel data is available.
+ // (see LLImageDXT for exception)
+ if (discard >= 0 && discard != mFormattedImage->getDiscardLevel())
+ {
+ llerrs << "Request for invalid discard level" << llendl;
+ }
+ checkWork();
+ if (mDecodedType == -2)
+ {
+ return TRUE; // aborted, done
+ }
+ if (mDecodedType != channel)
+ {
+ if (!haveWork())
+ {
+ addWork(channel, mPriority);
+ }
+ return FALSE;
+ }
+ else
+ {
+ llassert_always(!haveWork());
+ llassert_always(mDecodedType == channel);
+ raw = mDecodedImage; // smart pointer acquires ownership of data
+ mDecodedImage = NULL;
+ return TRUE;
+ }
+}
+
+BOOL LLImageWorker::requestDecodedData(LLPointer<LLImageRaw>& raw, S32 discard)
+{
+ if (mFormattedImage->getCodec() == IMG_CODEC_DXT)
+ {
+ // special case
+ LLImageDXT* imagedxt = (LLImageDXT*)((LLImageFormatted*)mFormattedImage);
+ return imagedxt->getMipData(raw, discard);
+ }
+ else
+ {
+ return requestDecodedAuxData(raw, 0, discard);
+ }
+}
diff --git a/indra/llimage/llimageworker.h b/indra/llimage/llimageworker.h
index cdd30417ce..6e9ecacc89 100644
--- a/indra/llimage/llimageworker.h
+++ b/indra/llimage/llimageworker.h
@@ -1,57 +1,57 @@
-/**
- * @file llimageworker.h
- * @brief Object for managing images and their textures.
- *
- * Copyright (c) 2000-$CurrentYear$, Linden Research, Inc.
- * $License$
- */
-
-#ifndef LL_LLIMAGEWORKER_H
-#define LL_LLIMAGEWORKER_H
-
-#include "llimage.h"
-#include "llworkerthread.h"
-
-class LLImageWorker : public LLWorkerClass
-{
-public:
- static void initClass(LLWorkerThread* workerthread);
- static void cleanupClass();
- static LLWorkerThread* getWorkerThread() { return sWorkerThread; }
-
- // LLWorkerThread
-public:
- LLImageWorker(LLImageFormatted* image, U32 priority, S32 discard, LLResponder* responder = NULL);
- ~LLImageWorker();
-
- // called from WORKER THREAD, returns TRUE if done
- /*virtual*/ bool doWork(S32 param);
-
- BOOL requestDecodedData(LLPointer<LLImageRaw>& raw, S32 discard = -1);
- BOOL requestDecodedAuxData(LLPointer<LLImageRaw>& raw, S32 channel, S32 discard = -1);
- void releaseDecodedData();
- void cancelDecode();
-
-private:
- // called from MAIN THREAD
- /*virtual*/ void startWork(S32 param); // called from addWork()
- /*virtual*/ void endWork(S32 param, bool aborted); // called from doWork()
-
-protected:
- LLPointer<LLImageFormatted> mFormattedImage;
- LLPointer<LLImageRaw> mDecodedImage;
- S32 mDecodedType;
- S32 mDiscardLevel;
-
-private:
- U32 mPriority;
- LLPointer<LLResponder> mResponder;
-
-protected:
- static LLWorkerThread* sWorkerThread;
-
-public:
- static S32 sCount;
-};
-
-#endif
+/**
+ * @file llimageworker.h
+ * @brief Object for managing images and their textures.
+ *
+ * Copyright (c) 2000-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+#ifndef LL_LLIMAGEWORKER_H
+#define LL_LLIMAGEWORKER_H
+
+#include "llimage.h"
+#include "llworkerthread.h"
+
+class LLImageWorker : public LLWorkerClass
+{
+public:
+ static void initClass(LLWorkerThread* workerthread);
+ static void cleanupClass();
+ static LLWorkerThread* getWorkerThread() { return sWorkerThread; }
+
+ // LLWorkerThread
+public:
+ LLImageWorker(LLImageFormatted* image, U32 priority, S32 discard, LLResponder* responder = NULL);
+ ~LLImageWorker();
+
+ // called from WORKER THREAD, returns TRUE if done
+ /*virtual*/ bool doWork(S32 param);
+
+ BOOL requestDecodedData(LLPointer<LLImageRaw>& raw, S32 discard = -1);
+ BOOL requestDecodedAuxData(LLPointer<LLImageRaw>& raw, S32 channel, S32 discard = -1);
+ void releaseDecodedData();
+ void cancelDecode();
+
+private:
+ // called from MAIN THREAD
+ /*virtual*/ void startWork(S32 param); // called from addWork()
+ /*virtual*/ void endWork(S32 param, bool aborted); // called from doWork()
+
+protected:
+ LLPointer<LLImageFormatted> mFormattedImage;
+ LLPointer<LLImageRaw> mDecodedImage;
+ S32 mDecodedType;
+ S32 mDiscardLevel;
+
+private:
+ U32 mPriority;
+ LLPointer<LLResponder> mResponder;
+
+protected:
+ static LLWorkerThread* sWorkerThread;
+
+public:
+ static S32 sCount;
+};
+
+#endif
diff --git a/indra/llmath/lloctree.h b/indra/llmath/lloctree.h
index e5b2a5f312..f7ad363206 100644
--- a/indra/llmath/lloctree.h
+++ b/indra/llmath/lloctree.h
@@ -21,7 +21,11 @@
#endif
#define LL_OCTREE_PARANOIA_CHECK 0
+#if LL_DARWIN
+#define LL_OCTREE_MAX_CAPACITY 32
+#else
#define LL_OCTREE_MAX_CAPACITY 256
+#endif
template <class T> class LLOctreeState;
template <class T> class LLOctreeNode;
diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp
index 9c1178b9f7..1196db18fa 100644
--- a/indra/llrender/llimagegl.cpp
+++ b/indra/llrender/llimagegl.cpp
@@ -713,6 +713,8 @@ BOOL LLImageGL::setSubImage(const U8* datap, S32 data_width, S32 data_height, S3
if (!res) llerrs << "LLImageGL::setSubImage(): bindTexture failed" << llendl;
stop_glerror();
+ LLGLEnable tex( GL_TEXTURE_2D );
+
glTexSubImage2D(mTarget, 0, x_pos, y_pos,
width, height, mFormatPrimary, mFormatType, datap);
stop_glerror();
diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp
index d6477d69ec..b94f593d7f 100644
--- a/indra/llrender/llvertexbuffer.cpp
+++ b/indra/llrender/llvertexbuffer.cpp
@@ -12,8 +12,8 @@
S32 LLVertexBuffer::sCount = 0;
S32 LLVertexBuffer::sGLCount = 0;
BOOL LLVertexBuffer::sEnableVBOs = TRUE;
-S32 LLVertexBuffer::sGLRenderBuffer = 0;
-S32 LLVertexBuffer::sGLRenderIndices = 0;
+U32 LLVertexBuffer::sGLRenderBuffer = 0;
+U32 LLVertexBuffer::sGLRenderIndices = 0;
U32 LLVertexBuffer::sLastMask = 0;
BOOL LLVertexBuffer::sVBOActive = FALSE;
BOOL LLVertexBuffer::sIBOActive = FALSE;
@@ -92,7 +92,7 @@ void LLVertexBuffer::stopRender()
sRenderActive = FALSE;
}
-void LLVertexBuffer::clientCopy()
+void LLVertexBuffer::clientCopy(F64 max_time)
{
if (!sDeleteList.empty())
{
@@ -122,7 +122,7 @@ void LLVertexBuffer::clientCopy()
}
else
{
- if (timer.getElapsedTimeF64() > 0.005)
+ if (timer.getElapsedTimeF64() > max_time)
{
break;
}
@@ -191,7 +191,10 @@ LLVertexBuffer::LLVertexBuffer(U32 typemask, S32 usage) :
mNumVerts(0), mNumIndices(0), mUsage(usage), mGLBuffer(0), mGLIndices(0),
mMappedData(NULL),
mMappedIndexData(NULL), mLocked(FALSE),
- mResized(FALSE), mEmpty(TRUE), mFinal(FALSE), mFilthy(FALSE)
+ mFinal(FALSE),
+ mFilthy(FALSE),
+ mEmpty(TRUE),
+ mResized(FALSE)
{
LLMemType mt(LLMemType::MTYPE_VERTEX_DATA);
if (!sEnableVBOs)
@@ -614,7 +617,6 @@ void LLVertexBuffer::unmapBuffer()
{
DirtyRegion& region = *i;
glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, region.mIndex*mStride, region.mCount*mStride, mMappedData + region.mIndex*mStride);
- glFlush();
}
}
}
@@ -639,7 +641,6 @@ void LLVertexBuffer::unmapBuffer()
DirtyRegion& region = *i;
glBufferSubDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, region.mIndicesIndex*sizeof(U32),
region.mIndicesCount*sizeof(U32), mMappedIndexData + region.mIndicesIndex*sizeof(U32));
- glFlush();
}
}
}
@@ -786,13 +787,7 @@ void LLVertexBuffer::setBuffer(U32 data_mask)
unmapBuffer();
}
else
- {
- if (!mDirtyRegions.empty())
- {
- mFilthy = TRUE;
- mDirtyRegions.clear();
- }
-
+ {
if (mGLBuffer)
{
if (sEnableVBOs && sVBOActive)
@@ -890,6 +885,15 @@ void LLVertexBuffer::markDirty(U32 vert_index, U32 vert_count, U32 indices_index
if (!mDirtyRegions.empty())
{
DirtyRegion& region = *(mDirtyRegions.rbegin());
+
+ if (region.mIndex+region.mCount > vert_index)
+ {
+ //this buffer has received multiple updates since the last copy, mark it filthy
+ mFilthy = TRUE;
+ mDirtyRegions.clear();
+ return;
+ }
+
if (region.mIndex + region.mCount == vert_index &&
region.mIndicesIndex + region.mIndicesCount == indices_index)
{
diff --git a/indra/llrender/llvertexbuffer.h b/indra/llrender/llvertexbuffer.h
index e672321e76..b221d35ee3 100644
--- a/indra/llrender/llvertexbuffer.h
+++ b/indra/llrender/llvertexbuffer.h
@@ -29,7 +29,7 @@ public:
static void cleanupClass();
static void startRender(); //between start and stop render, no client copies will occur
static void stopRender(); //any buffer not copied to GL will be rendered from client memory
- static void clientCopy(); //copy data from client to GL
+ static void clientCopy(F64 max_time = 0.005); //copy data from client to GL
static void unbind(); //unbind any bound vertex buffer
enum {
@@ -167,8 +167,8 @@ public:
static BOOL sEnableVBOs;
static S32 sTypeOffsets[TYPE_MAX];
- static S32 sGLRenderBuffer;
- static S32 sGLRenderIndices;
+ static U32 sGLRenderBuffer;
+ static U32 sGLRenderIndices;
static BOOL sVBOActive;
static BOOL sIBOActive;
static U32 sLastMask;
diff --git a/indra/llui/llctrlselectioninterface.cpp b/indra/llui/llctrlselectioninterface.cpp
index a58fb88e75..61044aa7da 100644
--- a/indra/llui/llctrlselectioninterface.cpp
+++ b/indra/llui/llctrlselectioninterface.cpp
@@ -1,44 +1,44 @@
-/**
- * @file llctrlselectioninterface.cpp
- * @brief Programmatic selection of items in a list.
- *
- * Copyright (c) 2006-$CurrentYear$, Linden Research, Inc.
- * $License$
- */
-
-#include "llctrlselectioninterface.h"
-
-#include "llsd.h"
-
-// virtual
-LLCtrlSelectionInterface::~LLCtrlSelectionInterface()
-{ }
-
-BOOL LLCtrlSelectionInterface::selectByValue(LLSD value)
-{
- return setSelectedByValue(value, TRUE);
-}
-
-BOOL LLCtrlSelectionInterface::deselectByValue(LLSD value)
-{
- return setSelectedByValue(value, FALSE);
-}
-
-
-// virtual
-LLCtrlListInterface::~LLCtrlListInterface()
-{ }
-
-LLScrollListItem* LLCtrlListInterface::addSimpleElement(const LLString& value)
-{
- return addSimpleElement(value, ADD_BOTTOM, LLSD());
-}
-
-LLScrollListItem* LLCtrlListInterface::addSimpleElement(const LLString& value, EAddPosition pos)
-{
- return addSimpleElement(value, pos, LLSD());
-}
-
-// virtual
-LLCtrlScrollInterface::~LLCtrlScrollInterface()
-{ }
+/**
+ * @file llctrlselectioninterface.cpp
+ * @brief Programmatic selection of items in a list.
+ *
+ * Copyright (c) 2006-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+#include "llctrlselectioninterface.h"
+
+#include "llsd.h"
+
+// virtual
+LLCtrlSelectionInterface::~LLCtrlSelectionInterface()
+{ }
+
+BOOL LLCtrlSelectionInterface::selectByValue(LLSD value)
+{
+ return setSelectedByValue(value, TRUE);
+}
+
+BOOL LLCtrlSelectionInterface::deselectByValue(LLSD value)
+{
+ return setSelectedByValue(value, FALSE);
+}
+
+
+// virtual
+LLCtrlListInterface::~LLCtrlListInterface()
+{ }
+
+LLScrollListItem* LLCtrlListInterface::addSimpleElement(const LLString& value)
+{
+ return addSimpleElement(value, ADD_BOTTOM, LLSD());
+}
+
+LLScrollListItem* LLCtrlListInterface::addSimpleElement(const LLString& value, EAddPosition pos)
+{
+ return addSimpleElement(value, pos, LLSD());
+}
+
+// virtual
+LLCtrlScrollInterface::~LLCtrlScrollInterface()
+{ }
diff --git a/indra/llui/llctrlselectioninterface.h b/indra/llui/llctrlselectioninterface.h
index 4e2807e9a1..698d609593 100644
--- a/indra/llui/llctrlselectioninterface.h
+++ b/indra/llui/llctrlselectioninterface.h
@@ -1,84 +1,84 @@
-/**
- * @file llctrlselectioninterface.h
- * @brief Programmatic selection of items in a list.
- *
- * Copyright (c) 2006-$CurrentYear$, Linden Research, Inc.
- * $License$
- */
-
-#ifndef LLCTRLSELECTIONINTERFACE_H
-#define LLCTRLSELECTIONINTERFACE_H
-
-#include "stdtypes.h"
-#include "stdenums.h"
-#include "llstring.h"
-
-class LLSD;
-class LLUUID;
-class LLScrollListItem;
-
-class LLCtrlSelectionInterface
-{
-public:
- virtual ~LLCtrlSelectionInterface();
-
- enum EOperation
- {
- OP_DELETE = 1,
- OP_SELECT,
- OP_DESELECT,
- };
-
- virtual BOOL getCanSelect() const = 0;
-
- virtual BOOL selectFirstItem() = 0;
- virtual BOOL selectNthItem( S32 index ) = 0;
-
- virtual S32 getFirstSelectedIndex() = 0;
-
- // TomY TODO: Simply cast the UUIDs to LLSDs, using the selectByValue function
- virtual BOOL setCurrentByID( const LLUUID& id ) = 0;
- virtual LLUUID getCurrentID() = 0;
-
- BOOL selectByValue(LLSD value);
- BOOL deselectByValue(LLSD value);
- virtual BOOL setSelectedByValue(LLSD value, BOOL selected) = 0;
- virtual LLSD getSimpleSelectedValue() = 0;
-
- virtual BOOL isSelected(LLSD value) = 0;
-
- virtual BOOL operateOnSelection(EOperation op) = 0;
- virtual BOOL operateOnAll(EOperation op) = 0;
-};
-
-class LLCtrlListInterface : public LLCtrlSelectionInterface
-{
-public:
- virtual ~LLCtrlListInterface();
-
- virtual S32 getItemCount() const = 0;
- virtual void addColumn(const LLSD& column, EAddPosition pos = ADD_BOTTOM) = 0;
- virtual void clearColumns() = 0;
- virtual void setColumnLabel(const LLString& column, const LLString& label) = 0;
- // TomY TODO: Document this
- virtual LLScrollListItem* addElement(const LLSD& value, EAddPosition pos = ADD_BOTTOM, void* userdata = NULL) = 0;
-
- LLScrollListItem* addSimpleElement(const LLString& value); // defaults to bottom
- LLScrollListItem* addSimpleElement(const LLString& value, EAddPosition pos); // defaults to no LLSD() id
- virtual LLScrollListItem* addSimpleElement(const LLString& value, EAddPosition pos, const LLSD& id) = 0;
-
- virtual void clearRows() = 0;
- virtual void sortByColumn(LLString name, BOOL ascending) = 0;
-};
-
-class LLCtrlScrollInterface
-{
-public:
- virtual ~LLCtrlScrollInterface();
-
- virtual S32 getScrollPos() = 0;
- virtual void setScrollPos( S32 pos ) = 0;
- virtual void scrollToShowSelected() = 0;
-};
-
-#endif
+/**
+ * @file llctrlselectioninterface.h
+ * @brief Programmatic selection of items in a list.
+ *
+ * Copyright (c) 2006-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+#ifndef LLCTRLSELECTIONINTERFACE_H
+#define LLCTRLSELECTIONINTERFACE_H
+
+#include "stdtypes.h"
+#include "stdenums.h"
+#include "llstring.h"
+
+class LLSD;
+class LLUUID;
+class LLScrollListItem;
+
+class LLCtrlSelectionInterface
+{
+public:
+ virtual ~LLCtrlSelectionInterface();
+
+ enum EOperation
+ {
+ OP_DELETE = 1,
+ OP_SELECT,
+ OP_DESELECT,
+ };
+
+ virtual BOOL getCanSelect() const = 0;
+
+ virtual BOOL selectFirstItem() = 0;
+ virtual BOOL selectNthItem( S32 index ) = 0;
+
+ virtual S32 getFirstSelectedIndex() = 0;
+
+ // TomY TODO: Simply cast the UUIDs to LLSDs, using the selectByValue function
+ virtual BOOL setCurrentByID( const LLUUID& id ) = 0;
+ virtual LLUUID getCurrentID() = 0;
+
+ BOOL selectByValue(LLSD value);
+ BOOL deselectByValue(LLSD value);
+ virtual BOOL setSelectedByValue(LLSD value, BOOL selected) = 0;
+ virtual LLSD getSimpleSelectedValue() = 0;
+
+ virtual BOOL isSelected(LLSD value) = 0;
+
+ virtual BOOL operateOnSelection(EOperation op) = 0;
+ virtual BOOL operateOnAll(EOperation op) = 0;
+};
+
+class LLCtrlListInterface : public LLCtrlSelectionInterface
+{
+public:
+ virtual ~LLCtrlListInterface();
+
+ virtual S32 getItemCount() const = 0;
+ virtual void addColumn(const LLSD& column, EAddPosition pos = ADD_BOTTOM) = 0;
+ virtual void clearColumns() = 0;
+ virtual void setColumnLabel(const LLString& column, const LLString& label) = 0;
+ // TomY TODO: Document this
+ virtual LLScrollListItem* addElement(const LLSD& value, EAddPosition pos = ADD_BOTTOM, void* userdata = NULL) = 0;
+
+ LLScrollListItem* addSimpleElement(const LLString& value); // defaults to bottom
+ LLScrollListItem* addSimpleElement(const LLString& value, EAddPosition pos); // defaults to no LLSD() id
+ virtual LLScrollListItem* addSimpleElement(const LLString& value, EAddPosition pos, const LLSD& id) = 0;
+
+ virtual void clearRows() = 0;
+ virtual void sortByColumn(LLString name, BOOL ascending) = 0;
+};
+
+class LLCtrlScrollInterface
+{
+public:
+ virtual ~LLCtrlScrollInterface();
+
+ virtual S32 getScrollPos() = 0;
+ virtual void setScrollPos( S32 pos ) = 0;
+ virtual void scrollToShowSelected() = 0;
+};
+
+#endif
diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp
index f2ae318dca..35d5affa5d 100644
--- a/indra/llui/llscrolllistctrl.cpp
+++ b/indra/llui/llscrolllistctrl.cpp
@@ -377,20 +377,21 @@ LLScrollListCtrl::LLScrollListCtrl(const LLString& name, const LLRect& rect,
mFgUnselectedColor( LLUI::sColorsGroup->getColor("ScrollUnselectedColor") ),
mFgDisabledColor( LLUI::sColorsGroup->getColor("ScrollDisabledColor") ),
mHighlightedColor( LLUI::sColorsGroup->getColor("ScrollHighlightedColor") ),
- mHighlightedItem(-1),
mBorderThickness( 2 ),
mOnDoubleClickCallback( NULL ),
mOnMaximumSelectCallback( NULL ),
mOnSortChangedCallback( NULL ),
- mDrewSelected(FALSE),
+ mHighlightedItem(-1),
mBorder(NULL),
- mSearchColumn(0),
mDefaultColumn("SIMPLE"),
+ mSearchColumn(0),
mNumDynamicWidthColumns(0),
mTotalStaticColumnWidth(0),
mSortColumn(0),
- mSortAscending(TRUE)
+ mSortAscending(TRUE),
+
+ mDrewSelected(FALSE)
{
mItemListRect.setOriginAndSize(
mBorderThickness + LIST_BORDER_PAD,
diff --git a/indra/llui/llviewquery.cpp b/indra/llui/llviewquery.cpp
index 416ca623bc..650125d486 100644
--- a/indra/llui/llviewquery.cpp
+++ b/indra/llui/llviewquery.cpp
@@ -1,126 +1,126 @@
-/**
- * @file llviewquery.cpp
- * @brief Implementation of view query class.
- *
- * Copyright (c) 2001-$CurrentYear$, Linden Research, Inc.
- * $License$
- */
-
-#include "llview.h"
-#include "lluictrl.h"
-#include "llviewquery.h"
-
-void LLQuerySorter::operator() (LLView * parent, viewList_t &children) const {}
-
-filterResult_t LLNoLeavesFilter::operator() (const LLView* const view, const viewList_t & children) const
-{
- return filterResult_t(!(view->getChildList()->size() == 0), TRUE);
-}
-
-filterResult_t LLVisibleFilter::operator() (const LLView* const view, const viewList_t & children) const
-{
- return filterResult_t(view->getVisible(), view->getVisible());
-}
-filterResult_t LLEnabledFilter::operator() (const LLView* const view, const viewList_t & children) const
-{
- return filterResult_t(view->getEnabled(), view->getEnabled());
-}
-filterResult_t LLTabStopFilter::operator() (const LLView* const view, const viewList_t & children) const
-{
- return filterResult_t(view->isCtrl() && static_cast<const LLUICtrl* const>(view)->hasTabStop(),
- view->canFocusChildren());
-}
-
-// LLViewQuery
-
-LLViewQuery::LLViewQuery(): mPreFilters(), mPostFilters(), mSorterp()
-{
-}
-
-void LLViewQuery::addPreFilter(const LLQueryFilter* prefilter) { mPreFilters.push_back(prefilter); }
-
-void LLViewQuery::addPostFilter(const LLQueryFilter* postfilter) { mPostFilters.push_back(postfilter); }
-
-const LLViewQuery::filterList_t & LLViewQuery::getPreFilters() const { return mPreFilters; }
-
-const LLViewQuery::filterList_t & LLViewQuery::getPostFilters() const { return mPostFilters; }
-
-void LLViewQuery::setSorter(const LLQuerySorter* sorterp) { mSorterp = sorterp; }
-const LLQuerySorter* LLViewQuery::getSorter() const { return mSorterp; }
-
-viewList_t LLViewQuery::run(LLView * view) const
-{
- viewList_t result;
-
- filterResult_t pre = runFilters(view, viewList_t(), mPreFilters);
- if(!pre.first && !pre.second)
- {
- // skip post filters completely if we're not including ourselves or the children
- return result;
- }
- if(pre.second)
- {
- // run filters on children
- viewList_t filtered_children;
- filterChildren(view, filtered_children);
- filterResult_t post = runFilters(view, filtered_children, mPostFilters);
- if(pre.first && post.first)
- {
- result.push_back(view);
- }
- if(post.second)
- {
- result.insert(result.end(), filtered_children.begin(), filtered_children.end());
- }
- }
- else
- {
- if(pre.first)
- {
- result.push_back(view);
- }
- }
- return result;
-}
-
-void LLViewQuery::filterChildren(LLView * view, viewList_t & filtered_children) const
-{
- LLView::child_list_t views(*(view->getChildList()));
- (*mSorterp)(view, views); // sort the children per the sorter
- for(LLView::child_list_iter_t iter = views.begin();
- iter != views.end();
- iter++)
- {
- viewList_t indiv_children = this->run(*iter);
- filtered_children.insert(filtered_children.end(), indiv_children.begin(), indiv_children.end());
- }
-}
-
-filterResult_t LLViewQuery::runFilters(LLView * view, const viewList_t children, const filterList_t filters) const
-{
- filterResult_t result = filterResult_t(TRUE, TRUE);
- for(filterList_const_iter_t iter = filters.begin();
- iter != filters.end();
- iter++)
- {
- filterResult_t filtered = (**iter)(view, children);
- result.first = result.first && filtered.first;
- result.second = result.second && filtered.second;
- }
- return result;
-}
-
-class SortByTabOrder : public LLQuerySorter, public LLSingleton<SortByTabOrder>
-{
- /*virtual*/ void operator() (LLView * parent, LLView::child_list_t &children) const
- {
- children.sort(LLCompareByTabOrder(parent->getCtrlOrder()));
- }
-};
-
-LLCtrlQuery::LLCtrlQuery() :
- LLViewQuery()
-{
- setSorter(SortByTabOrder::getInstance());
-}
-
+/**
+ * @file llviewquery.cpp
+ * @brief Implementation of view query class.
+ *
+ * Copyright (c) 2001-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+#include "llview.h"
+#include "lluictrl.h"
+#include "llviewquery.h"
+
+void LLQuerySorter::operator() (LLView * parent, viewList_t &children) const {}
+
+filterResult_t LLNoLeavesFilter::operator() (const LLView* const view, const viewList_t & children) const
+{
+ return filterResult_t(!(view->getChildList()->size() == 0), TRUE);
+}
+
+filterResult_t LLVisibleFilter::operator() (const LLView* const view, const viewList_t & children) const
+{
+ return filterResult_t(view->getVisible(), view->getVisible());
+}
+filterResult_t LLEnabledFilter::operator() (const LLView* const view, const viewList_t & children) const
+{
+ return filterResult_t(view->getEnabled(), view->getEnabled());
+}
+filterResult_t LLTabStopFilter::operator() (const LLView* const view, const viewList_t & children) const
+{
+ return filterResult_t(view->isCtrl() && static_cast<const LLUICtrl* const>(view)->hasTabStop(),
+ view->canFocusChildren());
+}
+
+// LLViewQuery
+
+LLViewQuery::LLViewQuery(): mPreFilters(), mPostFilters(), mSorterp()
+{
+}
+
+void LLViewQuery::addPreFilter(const LLQueryFilter* prefilter) { mPreFilters.push_back(prefilter); }
+
+void LLViewQuery::addPostFilter(const LLQueryFilter* postfilter) { mPostFilters.push_back(postfilter); }
+
+const LLViewQuery::filterList_t & LLViewQuery::getPreFilters() const { return mPreFilters; }
+
+const LLViewQuery::filterList_t & LLViewQuery::getPostFilters() const { return mPostFilters; }
+
+void LLViewQuery::setSorter(const LLQuerySorter* sorterp) { mSorterp = sorterp; }
+const LLQuerySorter* LLViewQuery::getSorter() const { return mSorterp; }
+
+viewList_t LLViewQuery::run(LLView * view) const
+{
+ viewList_t result;
+
+ filterResult_t pre = runFilters(view, viewList_t(), mPreFilters);
+ if(!pre.first && !pre.second)
+ {
+ // skip post filters completely if we're not including ourselves or the children
+ return result;
+ }
+ if(pre.second)
+ {
+ // run filters on children
+ viewList_t filtered_children;
+ filterChildren(view, filtered_children);
+ filterResult_t post = runFilters(view, filtered_children, mPostFilters);
+ if(pre.first && post.first)
+ {
+ result.push_back(view);
+ }
+ if(post.second)
+ {
+ result.insert(result.end(), filtered_children.begin(), filtered_children.end());
+ }
+ }
+ else
+ {
+ if(pre.first)
+ {
+ result.push_back(view);
+ }
+ }
+ return result;
+}
+
+void LLViewQuery::filterChildren(LLView * view, viewList_t & filtered_children) const
+{
+ LLView::child_list_t views(*(view->getChildList()));
+ (*mSorterp)(view, views); // sort the children per the sorter
+ for(LLView::child_list_iter_t iter = views.begin();
+ iter != views.end();
+ iter++)
+ {
+ viewList_t indiv_children = this->run(*iter);
+ filtered_children.insert(filtered_children.end(), indiv_children.begin(), indiv_children.end());
+ }
+}
+
+filterResult_t LLViewQuery::runFilters(LLView * view, const viewList_t children, const filterList_t filters) const
+{
+ filterResult_t result = filterResult_t(TRUE, TRUE);
+ for(filterList_const_iter_t iter = filters.begin();
+ iter != filters.end();
+ iter++)
+ {
+ filterResult_t filtered = (**iter)(view, children);
+ result.first = result.first && filtered.first;
+ result.second = result.second && filtered.second;
+ }
+ return result;
+}
+
+class SortByTabOrder : public LLQuerySorter, public LLSingleton<SortByTabOrder>
+{
+ /*virtual*/ void operator() (LLView * parent, LLView::child_list_t &children) const
+ {
+ children.sort(LLCompareByTabOrder(parent->getCtrlOrder()));
+ }
+};
+
+LLCtrlQuery::LLCtrlQuery() :
+ LLViewQuery()
+{
+ setSorter(SortByTabOrder::getInstance());
+}
+
diff --git a/indra/llui/llviewquery.h b/indra/llui/llviewquery.h
index ba59965c59..32852791af 100644
--- a/indra/llui/llviewquery.h
+++ b/indra/llui/llviewquery.h
@@ -1,89 +1,89 @@
-/**
- * @file llviewquery.h
- * @brief Query algorithm for flattening and filtering the view hierarchy.
- *
- * Copyright (c) 2001-$CurrentYear$, Linden Research, Inc.
- * $License$
- */
-
-#ifndef LL_LLVIEWQUERY_H
-#define LL_LLVIEWQUERY_H
-
-#include <list>
-
-#include "llmemory.h"
-
-class LLView;
-
-typedef std::list<LLView *> viewList_t;
-typedef std::pair<BOOL, BOOL> filterResult_t;
-
-// Abstract base class for all filters.
-class LLQueryFilter : public LLRefCount
-{
-public:
- virtual filterResult_t operator() (const LLView* const view, const viewList_t & children) const =0;
-};
-
-class LLQuerySorter : public LLRefCount
-{
-public:
- virtual void operator() (LLView * parent, viewList_t &children) const;
-};
-
-class LLNoLeavesFilter : public LLQueryFilter, public LLSingleton<LLNoLeavesFilter>
-{
- /*virtual*/ filterResult_t operator() (const LLView* const view, const viewList_t & children) const;
-};
-class LLVisibleFilter : public LLQueryFilter, public LLSingleton<LLVisibleFilter>
-{
- /*virtual*/ filterResult_t operator() (const LLView* const view, const viewList_t & children) const;
-};
-class LLEnabledFilter : public LLQueryFilter, public LLSingleton<LLEnabledFilter>
-{
- /*virtual*/ filterResult_t operator() (const LLView* const view, const viewList_t & children) const;
-};
-class LLTabStopFilter : public LLQueryFilter, public LLSingleton<LLTabStopFilter>
-{
- /*virtual*/ filterResult_t operator() (const LLView* const view, const viewList_t & children) const;
-};
-
-// Algorithm for flattening
-class LLViewQuery
-{
-public:
- typedef std::list<const LLQueryFilter*> filterList_t;
- typedef filterList_t::iterator filterList_iter_t;
- typedef filterList_t::const_iterator filterList_const_iter_t;
-
- LLViewQuery();
- virtual ~LLViewQuery() {}
-
- void addPreFilter(const LLQueryFilter* prefilter);
- void addPostFilter(const LLQueryFilter* postfilter);
- const filterList_t & getPreFilters() const;
- const filterList_t & getPostFilters() const;
-
- void setSorter(const LLQuerySorter* sorter);
- const LLQuerySorter* getSorter() const;
-
- viewList_t run(LLView * view) const;
- // syntactic sugar
- viewList_t operator () (LLView * view) const { return run(view); }
-protected:
- // override this method to provide iteration over other types of children
- virtual void filterChildren(LLView * view, viewList_t & filtered_children) const;
- filterResult_t runFilters(LLView * view, const viewList_t children, const filterList_t filters) const;
-protected:
- filterList_t mPreFilters;
- filterList_t mPostFilters;
- const LLQuerySorter* mSorterp;
-};
-
-class LLCtrlQuery : public LLViewQuery
-{
-public:
- LLCtrlQuery();
-};
-
-#endif
+/**
+ * @file llviewquery.h
+ * @brief Query algorithm for flattening and filtering the view hierarchy.
+ *
+ * Copyright (c) 2001-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+#ifndef LL_LLVIEWQUERY_H
+#define LL_LLVIEWQUERY_H
+
+#include <list>
+
+#include "llmemory.h"
+
+class LLView;
+
+typedef std::list<LLView *> viewList_t;
+typedef std::pair<BOOL, BOOL> filterResult_t;
+
+// Abstract base class for all filters.
+class LLQueryFilter : public LLRefCount
+{
+public:
+ virtual filterResult_t operator() (const LLView* const view, const viewList_t & children) const =0;
+};
+
+class LLQuerySorter : public LLRefCount
+{
+public:
+ virtual void operator() (LLView * parent, viewList_t &children) const;
+};
+
+class LLNoLeavesFilter : public LLQueryFilter, public LLSingleton<LLNoLeavesFilter>
+{
+ /*virtual*/ filterResult_t operator() (const LLView* const view, const viewList_t & children) const;
+};
+class LLVisibleFilter : public LLQueryFilter, public LLSingleton<LLVisibleFilter>
+{
+ /*virtual*/ filterResult_t operator() (const LLView* const view, const viewList_t & children) const;
+};
+class LLEnabledFilter : public LLQueryFilter, public LLSingleton<LLEnabledFilter>
+{
+ /*virtual*/ filterResult_t operator() (const LLView* const view, const viewList_t & children) const;
+};
+class LLTabStopFilter : public LLQueryFilter, public LLSingleton<LLTabStopFilter>
+{
+ /*virtual*/ filterResult_t operator() (const LLView* const view, const viewList_t & children) const;
+};
+
+// Algorithm for flattening
+class LLViewQuery
+{
+public:
+ typedef std::list<const LLQueryFilter*> filterList_t;
+ typedef filterList_t::iterator filterList_iter_t;
+ typedef filterList_t::const_iterator filterList_const_iter_t;
+
+ LLViewQuery();
+ virtual ~LLViewQuery() {}
+
+ void addPreFilter(const LLQueryFilter* prefilter);
+ void addPostFilter(const LLQueryFilter* postfilter);
+ const filterList_t & getPreFilters() const;
+ const filterList_t & getPostFilters() const;
+
+ void setSorter(const LLQuerySorter* sorter);
+ const LLQuerySorter* getSorter() const;
+
+ viewList_t run(LLView * view) const;
+ // syntactic sugar
+ viewList_t operator () (LLView * view) const { return run(view); }
+protected:
+ // override this method to provide iteration over other types of children
+ virtual void filterChildren(LLView * view, viewList_t & filtered_children) const;
+ filterResult_t runFilters(LLView * view, const viewList_t children, const filterList_t filters) const;
+protected:
+ filterList_t mPreFilters;
+ filterList_t mPostFilters;
+ const LLQuerySorter* mSorterp;
+};
+
+class LLCtrlQuery : public LLViewQuery
+{
+public:
+ LLCtrlQuery();
+};
+
+#endif
diff --git a/indra/newview/lldrawable.cpp b/indra/newview/lldrawable.cpp
index 868d61942d..3418007d41 100644
--- a/indra/newview/lldrawable.cpp
+++ b/indra/newview/lldrawable.cpp
@@ -908,8 +908,8 @@ void LLDrawable::updateLightSet()
// mLightSet points to nearby lights
mLightSet.clear();
part->getLights(getPositionAgent(), getRadius(), mLightSet);
- const S32 max_lights = 16;
- if (mLightSet.size() > max_lights)
+ const drawable_set_t::size_type MAX_LIGHTS = 16;
+ if (mLightSet.size() > MAX_LIGHTS)
{
typedef std::set<std::pair<F32,LLPointer<LLDrawable> > > sorted_pair_set_t;
sorted_pair_set_t sorted_set;
diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp
index 64edcecdc6..bb76957da1 100644
--- a/indra/newview/llface.cpp
+++ b/indra/newview/llface.cpp
@@ -711,11 +711,13 @@ BOOL LLFace::genVolumeBBoxes(const LLVolume &volume, S32 f,
const LLVolumeFace &face = volume.getVolumeFace(f);
//get bounding box
- if (mDrawablep->isState(LLDrawable::REBUILD_ALL))
+ if (mDrawablep->isState(LLDrawable::REBUILD_VOLUME | LLDrawable::REBUILD_POSITION))
{
- //vertex buffer no longer valid
- mVertexBuffer = NULL;
- mLastVertexBuffer = NULL;
+ if (mDrawablep->isState(LLDrawable::REBUILD_VOLUME))
+ { //vertex buffer no longer valid
+ mVertexBuffer = NULL;
+ mLastVertexBuffer = NULL;
+ }
LLVector3 min,max;
diff --git a/indra/newview/llfasttimerview.cpp b/indra/newview/llfasttimerview.cpp
index 85b8bbebd4..cbcdfaa55c 100644
--- a/indra/newview/llfasttimerview.cpp
+++ b/indra/newview/llfasttimerview.cpp
@@ -159,7 +159,7 @@ static struct ft_display_info ft_display_table[] =
// { LLFastTimer::FTM_RENDER_FONTS, " Fonts", &LLColor4::pink1, 0 },
// { LLFastTimer::FTM_UPDATE_TEXTURES, " Textures", &LLColor4::pink2, 0 },
{ LLFastTimer::FTM_SWAP, " Swap", &LLColor4::pink1, 0 },
-// { LLFastTimer::FTM_TEMP6, " Client Copy", &LLColor4::red1, 1},
+ { LLFastTimer::FTM_CLIENT_COPY, " Client Copy", &LLColor4::red1, 1},
// { LLFastTimer::FTM_TEMP1, " Temp1", &LLColor4::red1, 0 },
// { LLFastTimer::FTM_TEMP2, " Temp2", &LLColor4::magenta1, 0 },
diff --git a/indra/newview/llflexibleobject.cpp b/indra/newview/llflexibleobject.cpp
index 4e03e34663..020ce00bab 100644
--- a/indra/newview/llflexibleobject.cpp
+++ b/indra/newview/llflexibleobject.cpp
@@ -216,12 +216,6 @@ void LLVolumeImplFlexible::setAttributesOfAllSections()
void LLVolumeImplFlexible::onSetVolume(const LLVolumeParams &volume_params, const S32 detail)
{
- if (mVO && mVO->mDrawable.notNull())
- {
- LLVOVolume* volume = (LLVOVolume*) mVO;
- volume->regenFaces();
- }
-
/*doIdleUpdate(gAgent, *gWorldp, 0.0);
if (mVO && mVO->mDrawable.notNull())
{
@@ -615,11 +609,19 @@ BOOL LLVolumeImplFlexible::doUpdateGeometry(LLDrawable *drawable)
{
LLVolumeParams volume_params = volume->getVolume()->getParams();
volume->setVolume(volume_params, 0);
+ mUpdated = FALSE;
}
volume->updateRelativeXform();
doFlexibleUpdate();
- if (!mUpdated || volume->mFaceMappingChanged)
+
+ if (volume->mLODChanged || volume->mFaceMappingChanged ||
+ volume->mVolumeChanged)
+ {
+ volume->regenFaces();
+ }
+
+ if (!mUpdated || volume->mFaceMappingChanged || volume->mVolumeChanged)
{
doFlexibleRebuild();
volume->genBBoxes(isVolumeGlobal());
@@ -629,6 +631,7 @@ BOOL LLVolumeImplFlexible::doUpdateGeometry(LLDrawable *drawable)
volume->mLODChanged = FALSE;
volume->mFaceMappingChanged = FALSE;
+
// clear UV flag
drawable->clearState(LLDrawable::UV);
diff --git a/indra/newview/llfloaterinspect.cpp b/indra/newview/llfloaterinspect.cpp
index 0b9d836a1a..8bb73e3a9b 100644
--- a/indra/newview/llfloaterinspect.cpp
+++ b/indra/newview/llfloaterinspect.cpp
@@ -1,220 +1,221 @@
-#include "llviewerprecompiledheaders.h"
-#include "llfloateravatarinfo.h"
-#include "llfloaterinspect.h"
-#include "llfloatertools.h"
-#include "llcachename.h"
-#include "llscrolllistctrl.h"
-#include "llselectmgr.h"
-#include "lltoolcomp.h"
-#include "lltoolmgr.h"
-#include "llviewercontrol.h"
-#include "llviewerobject.h"
-#include "llvieweruictrlfactory.h"
-
-LLFloaterInspect* LLFloaterInspect::sInstance = NULL;
-
-LLFloaterInspect::LLFloaterInspect(void) :
- LLFloater("Inspect Object"),
- mDirty(FALSE)
-{
- sInstance = this;
- gUICtrlFactory->buildFloater(this, "floater_inspect.xml");
-}
-
-LLFloaterInspect::~LLFloaterInspect(void)
-{
- if(!gFloaterTools->getVisible())
- {
- if(gToolMgr->getBaseTool() == gToolInspect)
- {
- select_tool(gToolNull);
- }
- // Switch back to basic toolset
- gToolMgr->setCurrentToolset(gBasicToolset);
- }
- else
- {
- gFloaterTools->setFocus(TRUE);
- }
- sInstance = NULL;
-}
-
-BOOL LLFloaterInspect::isVisible()
-{
- return (!!sInstance);
-}
-
-void LLFloaterInspect::show(void* ignored)
-{
- if(sInstance)
- {
- sInstance->open();
- }
- else
- {
- LLFloaterInspect* self = new LLFloaterInspect;
- self->open();
- }
-
- sInstance->mObjectSelection = gSelectMgr->getSelection();
- select_tool(gToolInspect);
- sInstance->refresh();
-}
-
-void LLFloaterInspect::onClickCreatorProfile(void* ctrl)
-{
- if(sInstance->mObjectList->getAllSelected().size() == 0) return;
- LLSelectNode* obj = sInstance->mObjectSelection->getFirstNode();
- LLUUID obj_id, creator_id;
- obj_id = sInstance->mObjectList->getFirstSelected()->getUUID();
- while(obj)
- {
- if(obj_id == obj->getObject()->getID())
- {
- creator_id = obj->mPermissions->getCreator();
- break;
- }
- obj = sInstance->mObjectSelection->getNextNode();
- }
- if(obj)
- {
- LLFloaterAvatarInfo::showFromDirectory(creator_id);
- }
-}
-
-void LLFloaterInspect::onClickOwnerProfile(void* ctrl)
-{
- if(sInstance->mObjectList->getAllSelected().size() == 0) return;
- LLSelectNode* obj = sInstance->mObjectSelection->getFirstNode();
- LLUUID obj_id, owner_id;
- obj_id = sInstance->mObjectList->getFirstSelected()->getUUID();
- while(obj)
- {
- if(obj_id == obj->getObject()->getID())
- {
- owner_id = obj->mPermissions->getOwner();
- break;
- }
- obj = sInstance->mObjectSelection->getNextNode();
- }
- if(obj)
- {
- LLFloaterAvatarInfo::showFromDirectory(owner_id);
- }
-}
-
-BOOL LLFloaterInspect::postBuild()
-{
- mObjectList = LLUICtrlFactory::getScrollListByName(this, "object_list");
- childSetAction("button owner",onClickOwnerProfile, this);
- childSetAction("button creator",onClickCreatorProfile, this);
- childSetCommitCallback("object_list", onSelectObject);
- return TRUE;
-}
-
-void LLFloaterInspect::onSelectObject(LLUICtrl* ctrl, void* user_data)
-{
- if(LLFloaterInspect::getSelectedUUID() != LLUUID::null)
- {
- sInstance->childSetEnabled("button owner", true);
- sInstance->childSetEnabled("button creator", true);
- }
-}
-
-LLUUID LLFloaterInspect::getSelectedUUID()
-{
- if(sInstance)
- {
- if(sInstance->mObjectList->getAllSelected().size() > 0) return sInstance->mObjectList->getFirstSelected()->getUUID();
- }
- return LLUUID::null;
-}
-
-void LLFloaterInspect::refresh()
-{
- LLUUID creator_id;
- LLString creator_name;
- S32 pos = mObjectList->getScrollPos();
- childSetEnabled("button owner", false);
- childSetEnabled("button creator", false);
- LLUUID selected_uuid;
- S32 selected_index = mObjectList->getFirstSelectedIndex();
- if(selected_index > -1) selected_uuid = mObjectList->getFirstSelected()->getUUID();
- mObjectList->operateOnAll(LLScrollListCtrl::OP_DELETE);
- //List all transient objects, then all linked objects
- LLSelectNode* obj = mObjectSelection->getFirstNode();
- LLSD row;
- while(obj)
- {
- char owner_first_name[MAX_STRING], owner_last_name[MAX_STRING];
- char creator_first_name[MAX_STRING], creator_last_name[MAX_STRING];
- char time[MAX_STRING];
- std::ostringstream owner_name, creator_name, date;
- time_t timestamp = (time_t) (obj->mCreationDate/1000000);
- LLString::copy(time, ctime(&timestamp), MAX_STRING);
- time[24] = '\0';
- date << obj->mCreationDate;
- gCacheName->getName(obj->mPermissions->getOwner(), owner_first_name, owner_last_name);
- owner_name << owner_first_name << " " << owner_last_name;
- gCacheName->getName(obj->mPermissions->getCreator(), creator_first_name, creator_last_name);
- creator_name << creator_first_name << " " << creator_last_name;
- row["id"] = obj->getObject()->getID();
- row["columns"][0]["column"] = "object_name";
- row["columns"][0]["type"] = "text";
- // make sure we're either at the top of the link chain
- // or top of the editable chain, for attachments
- if(!(obj->getObject()->isRoot() || obj->getObject()->isRootEdit()))
- {
- row["columns"][0]["value"] = LLString(" ") + obj->mName;
- }
- else
- {
- row["columns"][0]["value"] = obj->mName;
- }
- row["columns"][1]["column"] = "owner_name";
- row["columns"][1]["type"] = "text";
- row["columns"][1]["value"] = owner_name.str().c_str();
- row["columns"][2]["column"] = "creator_name";
- row["columns"][2]["type"] = "text";
- row["columns"][2]["value"] = creator_name.str().c_str();
- row["columns"][3]["column"] = "creation_date";
- row["columns"][3]["type"] = "text";
- row["columns"][3]["value"] = time;
- mObjectList->addElement(row, ADD_TOP);
- obj = mObjectSelection->getNextNode();
- }
- if(selected_index > -1 && mObjectList->getItemIndex(selected_uuid) == selected_index)
- {
- mObjectList->selectNthItem(selected_index);
- }
- else
- {
- mObjectList->selectNthItem(0);
- }
- onSelectObject(this, NULL);
- mObjectList->setScrollPos(pos);
-}
-
-void LLFloaterInspect::onFocusReceived()
-{
- select_tool(gToolInspect);
-}
-
-void LLFloaterInspect::dirty()
-{
- if(sInstance)
- {
- sInstance->setDirty();
- }
-}
-
-void LLFloaterInspect::draw()
-{
- if (mDirty)
- {
- refresh();
- mDirty = FALSE;
- }
-
- LLFloater::draw();
-} \ No newline at end of file
+#include "llviewerprecompiledheaders.h"
+#include "llfloateravatarinfo.h"
+#include "llfloaterinspect.h"
+#include "llfloatertools.h"
+#include "llcachename.h"
+#include "llscrolllistctrl.h"
+#include "llselectmgr.h"
+#include "lltoolcomp.h"
+#include "lltoolmgr.h"
+#include "llviewercontrol.h"
+#include "llviewerobject.h"
+#include "llvieweruictrlfactory.h"
+
+LLFloaterInspect* LLFloaterInspect::sInstance = NULL;
+
+LLFloaterInspect::LLFloaterInspect(void) :
+ LLFloater("Inspect Object"),
+ mDirty(FALSE)
+{
+ sInstance = this;
+ gUICtrlFactory->buildFloater(this, "floater_inspect.xml");
+}
+
+LLFloaterInspect::~LLFloaterInspect(void)
+{
+ if(!gFloaterTools->getVisible())
+ {
+ if(gToolMgr->getBaseTool() == gToolInspect)
+ {
+ select_tool(gToolNull);
+ }
+ // Switch back to basic toolset
+ gToolMgr->setCurrentToolset(gBasicToolset);
+ }
+ else
+ {
+ gFloaterTools->setFocus(TRUE);
+ }
+ sInstance = NULL;
+}
+
+BOOL LLFloaterInspect::isVisible()
+{
+ return (!!sInstance);
+}
+
+void LLFloaterInspect::show(void* ignored)
+{
+ if(sInstance)
+ {
+ sInstance->open();
+ }
+ else
+ {
+ LLFloaterInspect* self = new LLFloaterInspect;
+ self->open();
+ }
+
+ sInstance->mObjectSelection = gSelectMgr->getSelection();
+ select_tool(gToolInspect);
+ sInstance->refresh();
+}
+
+void LLFloaterInspect::onClickCreatorProfile(void* ctrl)
+{
+ if(sInstance->mObjectList->getAllSelected().size() == 0) return;
+ LLSelectNode* obj = sInstance->mObjectSelection->getFirstNode();
+ LLUUID obj_id, creator_id;
+ obj_id = sInstance->mObjectList->getFirstSelected()->getUUID();
+ while(obj)
+ {
+ if(obj_id == obj->getObject()->getID())
+ {
+ creator_id = obj->mPermissions->getCreator();
+ break;
+ }
+ obj = sInstance->mObjectSelection->getNextNode();
+ }
+ if(obj)
+ {
+ LLFloaterAvatarInfo::showFromDirectory(creator_id);
+ }
+}
+
+void LLFloaterInspect::onClickOwnerProfile(void* ctrl)
+{
+ if(sInstance->mObjectList->getAllSelected().size() == 0) return;
+ LLSelectNode* obj = sInstance->mObjectSelection->getFirstNode();
+ LLUUID obj_id, owner_id;
+ obj_id = sInstance->mObjectList->getFirstSelected()->getUUID();
+ while(obj)
+ {
+ if(obj_id == obj->getObject()->getID())
+ {
+ owner_id = obj->mPermissions->getOwner();
+ break;
+ }
+ obj = sInstance->mObjectSelection->getNextNode();
+ }
+ if(obj)
+ {
+ LLFloaterAvatarInfo::showFromDirectory(owner_id);
+ }
+}
+
+BOOL LLFloaterInspect::postBuild()
+{
+ mObjectList = LLUICtrlFactory::getScrollListByName(this, "object_list");
+ childSetAction("button owner",onClickOwnerProfile, this);
+ childSetAction("button creator",onClickCreatorProfile, this);
+ childSetCommitCallback("object_list", onSelectObject);
+ return TRUE;
+}
+
+void LLFloaterInspect::onSelectObject(LLUICtrl* ctrl, void* user_data)
+{
+ if(LLFloaterInspect::getSelectedUUID() != LLUUID::null)
+ {
+ sInstance->childSetEnabled("button owner", true);
+ sInstance->childSetEnabled("button creator", true);
+ }
+}
+
+LLUUID LLFloaterInspect::getSelectedUUID()
+{
+ if(sInstance)
+ {
+ if(sInstance->mObjectList->getAllSelected().size() > 0) return sInstance->mObjectList->getFirstSelected()->getUUID();
+ }
+ return LLUUID::null;
+}
+
+void LLFloaterInspect::refresh()
+{
+ LLUUID creator_id;
+ LLString creator_name;
+ S32 pos = mObjectList->getScrollPos();
+ childSetEnabled("button owner", false);
+ childSetEnabled("button creator", false);
+ LLUUID selected_uuid;
+ S32 selected_index = mObjectList->getFirstSelectedIndex();
+ if(selected_index > -1) selected_uuid = mObjectList->getFirstSelected()->getUUID();
+ mObjectList->operateOnAll(LLScrollListCtrl::OP_DELETE);
+ //List all transient objects, then all linked objects
+ LLSelectNode* obj = mObjectSelection->getFirstNode();
+ LLSD row;
+ while(obj)
+ {
+ char owner_first_name[MAX_STRING], owner_last_name[MAX_STRING];
+ char creator_first_name[MAX_STRING], creator_last_name[MAX_STRING];
+ char time[MAX_STRING];
+ std::ostringstream owner_name, creator_name, date;
+ time_t timestamp = (time_t) (obj->mCreationDate/1000000);
+ LLString::copy(time, ctime(&timestamp), MAX_STRING);
+ time[24] = '\0';
+ date << obj->mCreationDate;
+ gCacheName->getName(obj->mPermissions->getOwner(), owner_first_name, owner_last_name);
+ owner_name << owner_first_name << " " << owner_last_name;
+ gCacheName->getName(obj->mPermissions->getCreator(), creator_first_name, creator_last_name);
+ creator_name << creator_first_name << " " << creator_last_name;
+ row["id"] = obj->getObject()->getID();
+ row["columns"][0]["column"] = "object_name";
+ row["columns"][0]["type"] = "text";
+ // make sure we're either at the top of the link chain
+ // or top of the editable chain, for attachments
+ if(!(obj->getObject()->isRoot() || obj->getObject()->isRootEdit()))
+ {
+ row["columns"][0]["value"] = LLString(" ") + obj->mName;
+ }
+ else
+ {
+ row["columns"][0]["value"] = obj->mName;
+ }
+ row["columns"][1]["column"] = "owner_name";
+ row["columns"][1]["type"] = "text";
+ row["columns"][1]["value"] = owner_name.str().c_str();
+ row["columns"][2]["column"] = "creator_name";
+ row["columns"][2]["type"] = "text";
+ row["columns"][2]["value"] = creator_name.str().c_str();
+ row["columns"][3]["column"] = "creation_date";
+ row["columns"][3]["type"] = "text";
+ row["columns"][3]["value"] = time;
+ mObjectList->addElement(row, ADD_TOP);
+ obj = mObjectSelection->getNextNode();
+ }
+ if(selected_index > -1 && mObjectList->getItemIndex(selected_uuid) == selected_index)
+ {
+ mObjectList->selectNthItem(selected_index);
+ }
+ else
+ {
+ mObjectList->selectNthItem(0);
+ }
+ onSelectObject(this, NULL);
+ mObjectList->setScrollPos(pos);
+}
+
+void LLFloaterInspect::onFocusReceived()
+{
+ select_tool(gToolInspect);
+}
+
+void LLFloaterInspect::dirty()
+{
+ if(sInstance)
+ {
+ sInstance->setDirty();
+ }
+}
+
+void LLFloaterInspect::draw()
+{
+ if (mDirty)
+ {
+ refresh();
+ mDirty = FALSE;
+ }
+
+ LLFloater::draw();
+}
+
diff --git a/indra/newview/llfloaterinspect.h b/indra/newview/llfloaterinspect.h
index 6a3f494978..d221879d0e 100644
--- a/indra/newview/llfloaterinspect.h
+++ b/indra/newview/llfloaterinspect.h
@@ -1,50 +1,50 @@
-/**
-* @file llfloaterfriends.h
-* @author Cube
-* @date 2006-12-16
-* @brief Declaration of class for displaying object attributes
-*
-* Copyright (c) 2005-$CurrentYear$, Linden Research, Inc.
-* $License$
-*/
-
-#ifndef LL_LLFLOATERINSPECT_H
-#define LL_LLFLOATERINSPECT_H
-
-#include "llfloater.h"
-
-//class LLTool;
-class LLObjectSelection;
-class LLScrollListCtrl;
-class LLUICtrl;
-
-class LLFloaterInspect : public LLFloater
-{
-public:
- virtual ~LLFloaterInspect(void);
- static void show(void* ignored = NULL);
- virtual BOOL postBuild();
- static void dirty();
- static LLUUID getSelectedUUID();
- virtual void draw();
- virtual void refresh();
- static BOOL isVisible();
- virtual void onFocusReceived();
- static void onClickCreatorProfile(void* ctrl);
- static void onClickOwnerProfile(void* ctrl);
- static void onSelectObject(LLUICtrl* ctrl, void* user_data);
- LLScrollListCtrl* mObjectList;
-protected:
- // protected members
- LLFloaterInspect();
- void setDirty() { mDirty = TRUE; }
- bool mDirty;
-
-private:
- // static data
- static LLFloaterInspect* sInstance;
-
- LLHandle<LLObjectSelection> mObjectSelection;
-};
-
-#endif //LL_LLFLOATERINSPECT_H \ No newline at end of file
+/**
+* @file llfloaterfriends.h
+* @author Cube
+* @date 2006-12-16
+* @brief Declaration of class for displaying object attributes
+*
+* Copyright (c) 2005-$CurrentYear$, Linden Research, Inc.
+* $License$
+*/
+
+#ifndef LL_LLFLOATERINSPECT_H
+#define LL_LLFLOATERINSPECT_H
+
+#include "llfloater.h"
+
+//class LLTool;
+class LLObjectSelection;
+class LLScrollListCtrl;
+class LLUICtrl;
+
+class LLFloaterInspect : public LLFloater
+{
+public:
+ virtual ~LLFloaterInspect(void);
+ static void show(void* ignored = NULL);
+ virtual BOOL postBuild();
+ static void dirty();
+ static LLUUID getSelectedUUID();
+ virtual void draw();
+ virtual void refresh();
+ static BOOL isVisible();
+ virtual void onFocusReceived();
+ static void onClickCreatorProfile(void* ctrl);
+ static void onClickOwnerProfile(void* ctrl);
+ static void onSelectObject(LLUICtrl* ctrl, void* user_data);
+ LLScrollListCtrl* mObjectList;
+protected:
+ // protected members
+ LLFloaterInspect();
+ void setDirty() { mDirty = TRUE; }
+ bool mDirty;
+
+private:
+ // static data
+ static LLFloaterInspect* sInstance;
+
+ LLHandle<LLObjectSelection> mObjectSelection;
+};
+
+#endif //LL_LLFLOATERINSPECT_H
diff --git a/indra/newview/llfloaterland.cpp b/indra/newview/llfloaterland.cpp
index 6f698d2734..3492f4fff8 100644
--- a/indra/newview/llfloaterland.cpp
+++ b/indra/newview/llfloaterland.cpp
@@ -346,8 +346,8 @@ void* LLFloaterLand::createPanelLandBan(void* data)
LLPanelLandGeneral::LLPanelLandGeneral(LLParcelSelectionHandle& parcel)
: LLPanel("land_general_panel"),
- mParcel(parcel),
- mUncheckedSell(FALSE)
+ mUncheckedSell(FALSE),
+ mParcel(parcel)
{
}
diff --git a/indra/newview/llfloaterpostcard.cpp b/indra/newview/llfloaterpostcard.cpp
index f6fcda29a3..f82978c5fc 100644
--- a/indra/newview/llfloaterpostcard.cpp
+++ b/indra/newview/llfloaterpostcard.cpp
@@ -51,8 +51,8 @@ LLLinkedList<LLFloaterPostcard> LLFloaterPostcard::sInstances;
LLFloaterPostcard::LLFloaterPostcard(LLImageJPEG* jpeg, LLImageGL *img, const LLVector2& img_scale, const LLVector3d& pos_taken_global)
: LLFloater("Postcard Floater"),
- mViewerImage(img),
mJPEGImage(jpeg),
+ mViewerImage(img),
mImageScale(img_scale),
mPosTakenGlobal(pos_taken_global)
{
diff --git a/indra/newview/llfloaterproperties.cpp b/indra/newview/llfloaterproperties.cpp
index 793884e008..feeedc5190 100644
--- a/indra/newview/llfloaterproperties.cpp
+++ b/indra/newview/llfloaterproperties.cpp
@@ -214,7 +214,7 @@ void LLFloaterProperties::refresh()
"RadioSaleType",
"EditPrice"
};
- for(int t=0;t<sizeof(enableNames)/sizeof(char*);t++)
+ for(size_t t=0; t<sizeof(enableNames)/sizeof(char*); ++t)
{
childSetEnabled(enableNames[t],false);
}
@@ -225,7 +225,7 @@ void LLFloaterProperties::refresh()
"EveryoneMaskDebug",
"NextMaskDebug"
};
- for(int t=0;t<sizeof(hideNames)/sizeof(char*);t++)
+ for(size_t t=0; t<sizeof(hideNames)/sizeof(char*); ++t)
{
childSetVisible(hideNames[t],false);
}
diff --git a/indra/newview/llfloatertools.cpp b/indra/newview/llfloatertools.cpp
index 34eb841568..63b1734642 100644
--- a/indra/newview/llfloatertools.cpp
+++ b/indra/newview/llfloatertools.cpp
@@ -245,7 +245,7 @@ BOOL LLFloaterTools::postBuild()
&LLToolPlacerPanel::sTriangleTorus,
&LLToolPlacerPanel::sTree,
&LLToolPlacerPanel::sGrass};
- for(int t=0;t<sizeof(toolNames)/sizeof(toolNames[0]);t++)
+ for(size_t t=0; t<sizeof(toolNames)/sizeof(toolNames[0]); ++t)
{
LLButton *found = LLViewerUICtrlFactory::getButtonByName(this,toolNames[t]);
if(found)
diff --git a/indra/newview/llgroupmgr.cpp b/indra/newview/llgroupmgr.cpp
index 33a675b59e..00108650ef 100644
--- a/indra/newview/llgroupmgr.cpp
+++ b/indra/newview/llgroupmgr.cpp
@@ -843,7 +843,7 @@ void LLGroupMgr::processGroupMembersReply(LLMessageSystem* msg, void** data)
}
}
- if (group_datap->mMembers.size() == group_datap->mMemberCount)
+ if (group_datap->mMembers.size() == (U32)group_datap->mMemberCount)
{
group_datap->mMemberDataComplete = TRUE;
group_datap->mMemberRequestID.setNull();
@@ -979,7 +979,7 @@ void LLGroupMgr::processGroupRoleDataReply(LLMessageSystem* msg, void** data)
group_data->mRoles[role_id] = rd;
}
- if (group_data->mRoles.size() == group_data->mRoleCount)
+ if (group_data->mRoles.size() == (U32)group_data->mRoleCount)
{
group_data->mRoleDataComplete = TRUE;
group_data->mRoleDataRequestID.setNull();
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index f090cea5f2..4de746fd4f 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -2174,6 +2174,8 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
case LLAssetType::AT_CATEGORY:
is_movable = ( LLAssetType::AT_NONE == ((LLInventoryCategory*)inv_item)->getPreferredType() );
break;
+ default:
+ break;
}
LLUUID trash_id = model->findCategoryUUIDForType(LLAssetType::AT_TRASH);
@@ -2190,6 +2192,8 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
case LLAssetType::AT_OBJECT:
is_movable = !avatar->isWearingAttachment(inv_item->getUUID());
break;
+ default:
+ break;
}
}
@@ -2759,6 +2763,8 @@ BOOL LLCallingCardBridge::dragOrDrop(MASK mask, BOOL drop,
}
break;
}
+ default:
+ break;
}
}
return rv;
@@ -3407,8 +3413,8 @@ struct LLFoundData
LLAssetType::EType asset_type) :
mItemID(item_id),
mAssetID(asset_id),
- mAssetType(asset_type),
mName(name),
+ mAssetType(asset_type),
mWearable( NULL ) {}
LLUUID mItemID;
diff --git a/indra/newview/llmaniptranslate.cpp b/indra/newview/llmaniptranslate.cpp
index 93ae74db22..9e26d951bc 100644
--- a/indra/newview/llmaniptranslate.cpp
+++ b/indra/newview/llmaniptranslate.cpp
@@ -1120,6 +1120,8 @@ void LLManipTranslate::renderSnapGuides()
inner_color.setVec(1,1,0,line_alpha);
mManipPart = LL_XY_PLANE;
break;
+ default:
+ break;
}
highlightIntersection(normal, selection_center, grid_rotation, inner_color);
diff --git a/indra/newview/llpanelavatar.cpp b/indra/newview/llpanelavatar.cpp
index 810e026d2a..3ec14b6117 100644
--- a/indra/newview/llpanelavatar.cpp
+++ b/indra/newview/llpanelavatar.cpp
@@ -512,25 +512,25 @@ BOOL LLPanelAvatarPicks::postBuild(void)
return TRUE;
}
-BOOL LLPanelAvatarAdvanced::postBuild()
+BOOL LLPanelAvatarAdvanced::postBuild()
{
- for( S32 i = 0; i < kArraySize(mWantToCheck); i++ )
- mWantToCheck[i] = NULL;
- for( S32 i = 0; i < kArraySize(mSkillsCheck); i++ )
- mSkillsCheck[i] = NULL;
+ for(size_t ii = 0; ii < kArraySize(mWantToCheck); ++ii)
+ mWantToCheck[ii] = NULL;
+ for(size_t ii = 0; ii < kArraySize(mSkillsCheck); ++ii)
+ mSkillsCheck[ii] = NULL;
mWantToCount = (8>kArraySize(mWantToCheck))?kArraySize(mWantToCheck):8;
- for(int t=0;t < mWantToCount ;t++)
+ for(S32 tt=0; tt < mWantToCount; ++tt)
{
- LLString ctlname = llformat("chk%d",t);
- mWantToCheck[t] = LLUICtrlFactory::getCheckBoxByName(this,ctlname);
+ LLString ctlname = llformat("chk%d", tt);
+ mWantToCheck[tt] = LLUICtrlFactory::getCheckBoxByName(this,ctlname);
}
mSkillsCount = (6>kArraySize(mSkillsCheck))?kArraySize(mSkillsCheck):6;
- for(int t=0;t<mSkillsCount;t++)
+ for(S32 tt=0; tt < mSkillsCount; ++tt)
{
//Find the Skills checkboxes and save off thier controls
- LLString ctlname = llformat("schk%d",t);
- mSkillsCheck[t] = LLUICtrlFactory::getCheckBoxByName(this,ctlname);
+ LLString ctlname = llformat("schk%d",tt);
+ mSkillsCheck[tt] = LLUICtrlFactory::getCheckBoxByName(this,ctlname);
}
mWantToEdit = LLUICtrlFactory::getLineEditorByName(this,"want_to_edit");
diff --git a/indra/newview/llpanelclassified.cpp b/indra/newview/llpanelclassified.cpp
index 2c6cbb9c08..9adc737aab 100644
--- a/indra/newview/llpanelclassified.cpp
+++ b/indra/newview/llpanelclassified.cpp
@@ -83,16 +83,17 @@ LLPanelClassified::LLPanelClassified(BOOL in_finder)
mDataRequested(FALSE),
mEnableCommit(FALSE),
mPaidFor(FALSE),
- mParcelID(),
mPosGlobal(),
mSnapshotCtrl(NULL),
mNameEditor(NULL),
- mLocationEditor(NULL),
mDescEditor(NULL),
+ mLocationEditor(NULL),
+ mCategoryCombo(NULL),
+ mUpdateBtn(NULL),
mTeleportBtn(NULL),
mMapBtn(NULL),
- //mLandmarkBtn(NULL),
- //mEnabledCheck(NULL),
+ mProfileBtn(NULL),
+ mInfoText(NULL),
mMatureCheck(NULL),
mAutoRenewCheck(NULL),
mSetBtn(NULL),
diff --git a/indra/newview/llpanelgroup.cpp b/indra/newview/llpanelgroup.cpp
index 9ad5855b8e..121dc4c67e 100644
--- a/indra/newview/llpanelgroup.cpp
+++ b/indra/newview/llpanelgroup.cpp
@@ -132,8 +132,8 @@ LLPanelGroup::LLPanelGroup(const std::string& filename,
mCurrentTab( NULL ),
mRequestedTab( NULL ),
mTabContainer( NULL ),
- mForceClose( FALSE ),
mIgnoreTransition( FALSE ),
+ mForceClose( FALSE ),
mInitialTab(initial_tab_selected),
mAllowEdit( TRUE ),
mShowingNotifyDialog( FALSE )
diff --git a/indra/newview/llpanelgrouproles.cpp b/indra/newview/llpanelgrouproles.cpp
index 0e295df94a..bda962ca56 100644
--- a/indra/newview/llpanelgrouproles.cpp
+++ b/indra/newview/llpanelgrouproles.cpp
@@ -1101,7 +1101,10 @@ void LLPanelGroupMembersSubTab::handleMemberSelect()
check->setCommitCallback(onRoleCheck);
check->setCallbackUserData(this);
check->set( count > 0 );
- check->setTentative(0 != count && selected_members.size() != count);
+ check->setTentative(
+ (0 != count)
+ && (selected_members.size() !=
+ (std::vector<LLUUID>::size_type)count));
//NOTE: as of right now a user can break the group
//by removing himself from a role if he is the
@@ -1996,7 +1999,7 @@ void LLPanelGroupRolesSubTab::update(LLGroupChange gc)
mRolesList->sortByColumn("name", TRUE);
- if ( (gdatap->mRoles.size() < MAX_ROLES)
+ if ( (gdatap->mRoles.size() < (U32)MAX_ROLES)
&& gAgent.hasPowerInGroup(mGroupID, GP_ROLE_CREATE) )
{
mCreateRoleButton->setEnabled(TRUE);
diff --git a/indra/newview/llpreview.cpp b/indra/newview/llpreview.cpp
index c5e589529c..91df61ca91 100644
--- a/indra/newview/llpreview.cpp
+++ b/indra/newview/llpreview.cpp
@@ -513,4 +513,4 @@ void LLMultiPreview::setAutoOpenInstance(LLMultiPreview* previewp, const LLUUID&
{
sAutoOpenPreviewHandles[id] = previewp->getHandle();
}
-} \ No newline at end of file
+}
diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp
index 950ed61b25..3eddc04259 100644
--- a/indra/newview/llselectmgr.cpp
+++ b/indra/newview/llselectmgr.cpp
@@ -5770,8 +5770,8 @@ BOOL LLSelectMgr::canSelectObject(LLViewerObject* object)
LLObjectSelection::LLObjectSelection() :
std::list<LLSelectNode*>(),
LLRefCount(),
- mCurrentTE(-1),
mCurrentNode(end()),
+ mCurrentTE(-1),
mSelectType(SELECT_TYPE_WORLD)
{
}
diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp
index 739d30bfe6..62903011cf 100644
--- a/indra/newview/llspatialpartition.cpp
+++ b/indra/newview/llspatialpartition.cpp
@@ -289,6 +289,7 @@ void LLSpatialGroup::validateDrawMap()
void LLSpatialGroup::makeStatic()
{
+#if !LL_DARWIN
if (isState(GEOM_DIRTY | ALPHA_DIRTY))
{
return;
@@ -309,6 +310,7 @@ void LLSpatialGroup::makeStatic()
mBuilt = 1.f;
}
+#endif
}
BOOL LLSpatialGroup::updateInGroup(LLDrawable *drawablep, BOOL immediate)
@@ -318,7 +320,12 @@ BOOL LLSpatialGroup::updateInGroup(LLDrawable *drawablep, BOOL immediate)
drawablep->updateSpatialExtents();
validate_drawable(drawablep);
- if (mOctreeNode->isInside(drawablep) && mOctreeNode->contains(drawablep))
+ OctreeNode* parent = mOctreeNode->getOctParent();
+
+ if (mOctreeNode->isInside(drawablep->getPositionGroup()) &&
+ (mOctreeNode->contains(drawablep) ||
+ (drawablep->getBinRadius() > mOctreeNode->getSize().mdV[0] &&
+ parent && parent->getElementCount() >= LL_OCTREE_MAX_CAPACITY)))
{
unbound();
setState(OBJECT_DIRTY);
@@ -697,14 +704,21 @@ void LLSpatialGroup::clearState(U32 state, S32 mode)
// Octree Listener Implementation
//======================================
-LLSpatialGroup::LLSpatialGroup(OctreeNode* node, LLSpatialPartition* part)
-: mOctreeNode(node), mState(0), mSpatialPartition(part), mVertexBuffer(NULL),
- mDistance(0.f), mLastUpdateDistance(-1.f),
- mViewAngle(0.f), mLastUpdateViewAngle(-1.f),
- mDepth(0.f), mBuilt(0.f),
- mLastUpdateTime(gFrameTimeSeconds), mLastRenderTime(gFrameTimeSeconds),
- mLastAddTime(gFrameTimeSeconds),
- mBufferUsage(GL_STATIC_DRAW_ARB)
+LLSpatialGroup::LLSpatialGroup(OctreeNode* node, LLSpatialPartition* part) :
+ mState(0),
+ mBuilt(0.f),
+ mOctreeNode(node),
+ mSpatialPartition(part),
+ mVertexBuffer(NULL),
+ mBufferUsage(GL_STATIC_DRAW_ARB),
+ mDistance(0.f),
+ mDepth(0.f),
+ mLastUpdateDistance(-1.f),
+ mLastUpdateTime(gFrameTimeSeconds),
+ mLastAddTime(gFrameTimeSeconds),
+ mLastRenderTime(gFrameTimeSeconds),
+ mViewAngle(0.f),
+ mLastUpdateViewAngle(-1.f)
{
LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
@@ -898,6 +912,31 @@ void LLSpatialGroup::handleChildRemoval(const OctreeNode* parent, const OctreeNo
unbound();
}
+void LLSpatialGroup::destroyGL()
+{
+ setState(LLSpatialGroup::GEOM_DIRTY |
+ LLSpatialGroup::OCCLUSION_DIRTY |
+ LLSpatialGroup::IMAGE_DIRTY);
+ mLastUpdateTime = gFrameTimeSeconds;
+ mVertexBuffer = NULL;
+ mBufferMap.clear();
+
+ mOcclusionVerts = NULL;
+ mReflectionMap = NULL;
+ clearDrawMap();
+
+ for (LLSpatialGroup::element_iter i = getData().begin(); i != getData().end(); ++i)
+ {
+ LLDrawable* drawable = *i;
+ for (S32 j = 0; j < drawable->getNumFaces(); j++)
+ {
+ LLFace* facep = drawable->getFace(j);
+ facep->mVertexBuffer = NULL;
+ facep->mLastVertexBuffer = NULL;
+ }
+ }
+}
+
BOOL LLSpatialGroup::rebound()
{
if (!isState(DIRTY))
@@ -1423,28 +1462,11 @@ public:
virtual void visit(const LLOctreeState<LLDrawable>* state)
{
LLSpatialGroup* group = (LLSpatialGroup*) state->getListener(0);
+ group->destroyGL();
- group->setState(LLSpatialGroup::GEOM_DIRTY |
- LLSpatialGroup::OCCLUSION_DIRTY |
- LLSpatialGroup::IMAGE_DIRTY);
- group->mLastUpdateTime = gFrameTimeSeconds;
- group->mVertexBuffer = NULL;
- group->mBufferMap.clear();
-
- group->mOcclusionVerts = NULL;
- group->mReflectionMap = NULL;
- group->clearDrawMap();
-
for (LLSpatialGroup::element_iter i = group->getData().begin(); i != group->getData().end(); ++i)
{
LLDrawable* drawable = *i;
- for (S32 j = 0; j < drawable->getNumFaces(); j++)
- {
- LLFace* facep = drawable->getFace(j);
- facep->mVertexBuffer = NULL;
- facep->mLastVertexBuffer = NULL;
- }
-
if (drawable->getVObj() && !group->mSpatialPartition->mRenderByGroup)
{
gPipeline.markRebuild(drawable, LLDrawable::REBUILD_ALL, TRUE);
@@ -1458,6 +1480,7 @@ public:
}
}
};
+
void LLSpatialPartition::restoreGL()
{
LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
@@ -1597,7 +1620,7 @@ void LLSpatialPartition::processGeometry(LLCamera* camera)
U32 process_count = 8;
LLSpatialGroup* root = (LLSpatialGroup*) mOctree->getListener(0);
- if (!root->isState(LLSpatialGroup::IN_GEOMETRY_QUEUE))
+ if (mUpdateQueue.empty())
{
root->setState(LLSpatialGroup::IN_GEOMETRY_QUEUE);
mUpdateQueue.push(root);
@@ -1628,18 +1651,19 @@ void LLSpatialPartition::processGeometry(LLCamera* camera)
}
}
- if (!group->isDead() &&
- !group->isVisible() &&
- !group->isState(LLSpatialGroup::OBJECT_DIRTY) &&
- group->mBufferUsage != GL_STREAM_DRAW_ARB)
+ if (!group->isDead() && !group->isVisible())
{
- group->updateDistance(*camera);
- for (LLSpatialGroup::element_iter i = group->getData().begin(); i != group->getData().end(); ++i)
+ if (!group->isState(LLSpatialGroup::OBJECT_DIRTY) &&
+ group->mBufferUsage != GL_STREAM_DRAW_ARB)
{
- LLDrawable* drawablep = *i;
- if (!drawablep->isDead())
+ group->updateDistance(*camera);
+ for (LLSpatialGroup::element_iter i = group->getData().begin(); i != group->getData().end(); ++i)
{
- drawablep->updateDistance(*camera);
+ LLDrawable* drawablep = *i;
+ if (!drawablep->isDead())
+ {
+ drawablep->updateDistance(*camera);
+ }
}
}
}
@@ -1703,7 +1727,7 @@ void LLSpatialPartition::processImagery(LLCamera* camera)
}
gPipeline.generateReflectionMap(gPipeline.mCubeBuffer, cube_cam, 128);
- gPipeline.blurReflectionMap(gPipeline.mCubeBuffer, cube_map, 32);
+ gPipeline.blurReflectionMap(gPipeline.mCubeBuffer, cube_map, 64);
group->mReflectionMap = cube_map;
group->setState(LLSpatialGroup::GEOM_DIRTY);
gPipeline.markRebuild(group);
@@ -2821,11 +2845,19 @@ LLDrawable* LLSpatialPartition::pickDrawable(const LLVector3& start, const LLVec
LLDrawInfo::LLDrawInfo(U32 start, U32 end, U32 count, U32 offset,
LLViewerImage* texture, LLVertexBuffer* buffer,
BOOL fullbright, U8 bump, BOOL particle, F32 part_size)
-: mStart(start), mEnd(end), mCount(count), mOffset(offset),
- mTexture(texture), mVertexBuffer(buffer),
- mFullbright(fullbright), mBump(bump),
- mParticle(particle), mPartSize(part_size),
- mVSize(0.f), mTextureMatrix(NULL)
+:
+ mVertexBuffer(buffer),
+ mTexture(texture),
+ mTextureMatrix(NULL),
+ mStart(start),
+ mEnd(end),
+ mCount(count),
+ mOffset(offset),
+ mFullbright(fullbright),
+ mBump(bump),
+ mParticle(particle),
+ mPartSize(part_size),
+ mVSize(0.f)
{
}
diff --git a/indra/newview/llspatialpartition.h b/indra/newview/llspatialpartition.h
index ea0802985e..6a795d4c6c 100644
--- a/indra/newview/llspatialpartition.h
+++ b/indra/newview/llspatialpartition.h
@@ -173,6 +173,7 @@ public:
BOOL boundObjects(BOOL empty, LLVector3& newMin, LLVector3& newMax);
void unbound();
BOOL rebound();
+ void destroyGL();
void updateDistance(LLCamera& camera);
BOOL changeLOD();
@@ -273,6 +274,8 @@ public:
BOOL isVolatile() const { return mVolatile; }
virtual LLSpatialBridge* asBridge() { return NULL; }
+ virtual BOOL isBridge() { return asBridge() != NULL; }
+
S32 getObjects(const LLVector3& pos, F32 rad, LLDrawable::drawable_set_t &results );
S32 getLights(const LLVector3& pos, F32 rad, LLDrawable::drawable_set_t &results );
diff --git a/indra/newview/lltexturecache.cpp b/indra/newview/lltexturecache.cpp
index 13efadf213..cb846a43fe 100644
--- a/indra/newview/lltexturecache.cpp
+++ b/indra/newview/lltexturecache.cpp
@@ -1,1365 +1,1365 @@
-/**
- * @file texturecache.cpp
- * @brief Object which handles local texture caching
- *
- * Copyright (c) 2000-$CurrentYear$, Linden Research, Inc.
- * $License$
- */
-
-#include "llviewerprecompiledheaders.h"
-
-#include "lltexturecache.h"
-
-#include "llapr.h"
-#include "lldir.h"
-#include "llimage.h"
-#include "lllfsthread.h"
-#include "llviewercontrol.h"
-
-#define USE_LFS_READ 0
-#define USE_LFS_WRITE 0
-
-// Note: first 4 bytes store file size, rest is j2c data
-const S32 TEXTURE_CACHE_ENTRY_SIZE = FIRST_PACKET_SIZE; //1024;
-
-class LLTextureCacheWorker : public LLWorkerClass
-{
- friend class LLTextureCache;
-
-private:
- enum e_state
- {
- INIT = 0,
- LOCAL = 1,
- CACHE = 2,
- HEADER = 3,
- BODY = 4
- };
-
- class ReadResponder : public LLLFSThread::Responder
- {
- public:
- ReadResponder(LLTextureCache* cache, handle_t handle) : mCache(cache), mHandle(handle) {}
- ~ReadResponder() {}
- void completed(S32 bytes)
- {
- mCache->lockWorkers();
- LLTextureCacheWorker* reader = mCache->getReader(mHandle);
- if (reader) reader->ioComplete(bytes);
- mCache->unlockWorkers();
- }
- LLTextureCache* mCache;
- LLTextureCacheWorker::handle_t mHandle;
- };
-
- class WriteResponder : public LLLFSThread::Responder
- {
- public:
- WriteResponder(LLTextureCache* cache, handle_t handle) : mCache(cache), mHandle(handle) {}
- ~WriteResponder() {}
- void completed(S32 bytes)
- {
- mCache->lockWorkers();
- LLTextureCacheWorker* writer = mCache->getWriter(mHandle);
- if (writer) writer->ioComplete(bytes);
- mCache->unlockWorkers();
- }
- LLTextureCache* mCache;
- LLTextureCacheWorker::handle_t mHandle;
- };
-
-public:
- LLTextureCacheWorker(LLTextureCache* cache, U32 priority, const LLUUID& id,
- U8* data, S32 datasize, S32 offset,
- S32 imagesize, // for writes
- LLTextureCache::Responder* responder)
- : LLWorkerClass(cache, "LLTextureCacheWorker"),
- mCache(cache),
- mPriority(priority),
- mID(id),
- mState(INIT),
- mReadData(NULL),
- mWriteData(data),
- mDataSize(datasize),
- mOffset(offset),
- mImageSize(imagesize),
- mImageFormat(IMG_CODEC_J2C),
- mImageLocal(FALSE),
- mResponder(responder),
- mFileHandle(LLLFSThread::nullHandle()),
- mBytesToRead(0),
- mBytesRead(0)
- {
- mPriority &= LLWorkerThread::PRIORITY_LOWBITS;
- }
- ~LLTextureCacheWorker()
- {
- llassert_always(!haveWork());
- delete[] mReadData;
- }
-
- bool doRead();
- bool doWrite();
- virtual bool doWork(S32 param); // Called from LLWorkerThread::processRequest()
-
- handle_t read() { addWork(0, LLWorkerThread::PRIORITY_HIGH | mPriority); return mRequestHandle; }
- handle_t write() { addWork(1, LLWorkerThread::PRIORITY_HIGH | mPriority); return mRequestHandle; }
- bool complete() { return checkWork(); }
- void ioComplete(S32 bytes)
- {
- mBytesRead = bytes;
- setPriority(LLWorkerThread::PRIORITY_HIGH | mPriority);
- }
-
-private:
- virtual void startWork(S32 param); // called from addWork() (MAIN THREAD)
- virtual void finishWork(S32 param, bool completed); // called from finishRequest() (WORK THREAD)
- virtual void endWork(S32 param, bool aborted); // called from doWork() (MAIN THREAD)
-
-private:
- LLTextureCache* mCache;
- U32 mPriority;
- LLUUID mID;
- e_state mState;
-
- U8* mReadData;
- U8* mWriteData;
- S32 mDataSize;
- S32 mOffset;
- S32 mImageSize;
- S32 mImageFormat;
- BOOL mImageLocal;
- LLPointer<LLTextureCache::Responder> mResponder;
- LLLFSThread::handle_t mFileHandle;
- S32 mBytesToRead;
- LLAtomicS32 mBytesRead;
-};
-
-//virtual
-void LLTextureCacheWorker::startWork(S32 param)
-{
-}
-
-bool LLTextureCacheWorker::doRead()
-{
- S32 local_size = 0;
- std::string local_filename;
-
- if (mState == INIT)
- {
- std::string filename = mCache->getLocalFileName(mID);
- local_filename = filename + ".j2c";
- local_size = ll_apr_file_size(local_filename, mCache->getFileAPRPool());
- if (local_size == 0)
- {
- local_filename = filename + ".tga";
- local_size = ll_apr_file_size(local_filename, mCache->getFileAPRPool());
- if (local_size > 0)
- {
- mImageFormat = IMG_CODEC_TGA;
- mDataSize = local_size; // Only a complete .tga file is valid
- }
- }
- if (local_size > 0)
- {
- mState = LOCAL;
- }
- else
- {
- mState = CACHE;
- }
- }
-
- if (mState == LOCAL)
- {
-#if USE_LFS_READ
- if (mFileHandle == LLLFSThread::nullHandle())
- {
- mImageLocal = TRUE;
- mImageSize = local_size;
- if (!mDataSize || mDataSize + mOffset > local_size)
- {
- mDataSize = local_size - mOffset;
- }
- if (mDataSize <= 0)
- {
- // no more data to read
- mDataSize = 0;
- return true;
- }
- mReadData = new U8[mDataSize];
- mBytesRead = -1;
- mBytesToRead = mDataSize;
- setPriority(LLWorkerThread::PRIORITY_LOW | mPriority);
- mFileHandle = LLLFSThread::sLocal->read(local_filename, mReadData, mOffset, mDataSize,
- new ReadResponder(mCache, mRequestHandle));
- return false;
- }
- else
- {
- if (mBytesRead >= 0)
- {
- if (mBytesRead != mBytesToRead)
- {
- llwarns << "Error reading file from local cache: " << local_filename
- << " Bytes: " << mDataSize << " Offset: " << mOffset
- << " / " << mDataSize << llendl;
- mDataSize = 0; // failed
- delete[] mReadData;
- mReadData = NULL;
- }
- return true;
- }
- else
- {
- return false;
- }
- }
-#else
- if (!mDataSize || mDataSize > local_size)
- {
- mDataSize = local_size;
- }
- mReadData = new U8[mDataSize];
- S32 bytes_read = ll_apr_file_read_ex(local_filename, mCache->getFileAPRPool(),
- mReadData, mOffset, mDataSize);
- if (bytes_read != mDataSize)
- {
- llwarns << "Error reading file from local cache: " << local_filename
- << " Bytes: " << mDataSize << " Offset: " << mOffset
- << " / " << mDataSize << llendl;
- mDataSize = 0;
- delete[] mReadData;
- mReadData = NULL;
- }
- else
- {
- mImageSize = local_size;
- mImageLocal = TRUE;
- }
- return true;
-#endif
- }
-
- S32 idx = -1;
-
- if (mState == CACHE)
- {
- llassert_always(mImageSize == 0);
- idx = mCache->getHeaderCacheEntry(mID, false, &mImageSize);
- if (idx >= 0 && mImageSize > mOffset)
- {
- llassert_always(mImageSize > 0);
- if (!mDataSize || mDataSize > mImageSize)
- {
- mDataSize = mImageSize;
- }
- mState = mOffset < TEXTURE_CACHE_ENTRY_SIZE ? HEADER : BODY;
- }
- else
- {
- mDataSize = 0; // no data
- return true;
- }
- }
-
- if (mState == HEADER)
- {
-#if USE_LFS_READ
- if (mFileHandle == LLLFSThread::nullHandle())
- {
- llassert_always(idx >= 0);
- llassert_always(mOffset < TEXTURE_CACHE_ENTRY_SIZE);
- S32 offset = idx * TEXTURE_CACHE_ENTRY_SIZE + mOffset;
- S32 size = TEXTURE_CACHE_ENTRY_SIZE - mOffset;
- llassert_always(mReadData == NULL);
- mReadData = new U8[size];
- mBytesRead = -1;
- mBytesToRead = size;
- setPriority(LLWorkerThread::PRIORITY_LOW | mPriority);
- mFileHandle = LLLFSThread::sLocal->read(mCache->mHeaderDataFileName,
- mReadData, offset, mBytesToRead,
- new ReadResponder(mCache, mRequestHandle));
- return false;
- }
- else
- {
- if (mBytesRead >= 0)
- {
- if (mBytesRead != mBytesToRead)
- {
- llwarns << "LLTextureCacheWorker: " << mID
- << " incorrect number of bytes read from header: " << mBytesRead
- << " != " << mBytesToRead << llendl;
- mDataSize = -1; // failed
- return true;
- }
- if (mDataSize <= TEXTURE_CACHE_ENTRY_SIZE)
- {
- return true; // done
- }
- else
- {
- mFileHandle = LLLFSThread::nullHandle();
- mState = BODY;
- }
- }
- else
- {
- return false;
- }
- }
-#else
- llassert_always(idx >= 0);
- llassert_always(mOffset < TEXTURE_CACHE_ENTRY_SIZE);
- S32 offset = idx * TEXTURE_CACHE_ENTRY_SIZE + mOffset;
- S32 size = TEXTURE_CACHE_ENTRY_SIZE - mOffset;
- mReadData = new U8[size];
- S32 bytes_read = ll_apr_file_read_ex(mCache->mHeaderDataFileName, mCache->getFileAPRPool(),
- mReadData, offset, size);
- if (bytes_read != size)
- {
- llwarns << "LLTextureCacheWorker: " << mID
- << " incorrect number of bytes read from header: " << bytes_read
- << " / " << size << llendl;
- mDataSize = -1; // failed
- return true;
- }
- if (mDataSize <= TEXTURE_CACHE_ENTRY_SIZE)
- {
- return true; // done
- }
- else
- {
- mState = BODY;
- }
-#endif
- }
-
- if (mState == BODY)
- {
-#if USE_LFS_READ
- if (mFileHandle == LLLFSThread::nullHandle())
- {
- std::string filename = mCache->getTextureFileName(mID);
- S32 filesize = ll_apr_file_size(filename, mCache->getFileAPRPool());
- if (filesize > mOffset)
- {
- S32 datasize = TEXTURE_CACHE_ENTRY_SIZE + filesize;
- mDataSize = llmin(datasize, mDataSize);
- S32 data_offset = TEXTURE_CACHE_ENTRY_SIZE - mOffset;
- data_offset = llmax(data_offset, 0);
- S32 file_size = mDataSize - data_offset;
- S32 file_offset = mOffset - TEXTURE_CACHE_ENTRY_SIZE;
- file_offset = llmax(file_offset, 0);
-
- llassert_always(mDataSize > 0);
- U8* data = new U8[mDataSize];
- if (data_offset > 0)
- {
- llassert_always(mReadData);
- llassert_always(data_offset <= mDataSize);
- memcpy(data, mReadData, data_offset);
- delete[] mReadData;
- mReadData = NULL;
- }
- llassert_always(mReadData == NULL);
- mReadData = data;
-
- mBytesRead = -1;
- mBytesToRead = file_size;
- setPriority(LLWorkerThread::PRIORITY_LOW | mPriority);
- llassert_always(data_offset + mBytesToRead <= mDataSize);
- mFileHandle = LLLFSThread::sLocal->read(filename,
- mReadData + data_offset, file_offset, mBytesToRead,
- new ReadResponder(mCache, mRequestHandle));
- return false;
- }
- else
- {
- mDataSize = TEXTURE_CACHE_ENTRY_SIZE;
- return true; // done
- }
- }
- else
- {
- if (mBytesRead >= 0)
- {
- if (mBytesRead != mBytesToRead)
- {
- llwarns << "LLTextureCacheWorker: " << mID
- << " incorrect number of bytes read from body: " << mBytesRead
- << " != " << mBytesToRead << llendl;
- mDataSize = -1; // failed
- }
- return true;
- }
- else
- {
- return false;
- }
- }
-#else
- std::string filename = mCache->getTextureFileName(mID);
- S32 filesize = ll_apr_file_size(filename, mCache->getFileAPRPool());
- S32 bytes_read = 0;
- if (filesize > mOffset)
- {
- S32 datasize = TEXTURE_CACHE_ENTRY_SIZE + filesize;
- mDataSize = llmin(datasize, mDataSize);
- S32 data_offset = TEXTURE_CACHE_ENTRY_SIZE - mOffset;
- data_offset = llmax(data_offset, 0);
- S32 file_size = mDataSize - data_offset;
- S32 file_offset = mOffset - TEXTURE_CACHE_ENTRY_SIZE;
- file_offset = llmax(file_offset, 0);
-
- U8* data = new U8[mDataSize];
- if (data_offset > 0)
- {
- llassert_always(mReadData);
- memcpy(data, mReadData, data_offset);
- delete[] mReadData;
- }
- mReadData = data;
- bytes_read = ll_apr_file_read_ex(filename, mCache->getFileAPRPool(),
- mReadData + data_offset,
- file_offset, file_size);
- if (bytes_read != file_size)
- {
- llwarns << "LLTextureCacheWorker: " << mID
- << " incorrect number of bytes read from body: " << bytes_read
- << " / " << file_size << llendl;
- mDataSize = -1; // failed
- return true;
- }
- }
- else
- {
- mDataSize = TEXTURE_CACHE_ENTRY_SIZE;
- }
-
- return true;
-#endif
- }
-
- return false;
-}
-
-bool LLTextureCacheWorker::doWrite()
-{
- S32 idx = -1;
-
- if (mState == INIT)
- {
- llassert_always(mOffset == 0); // Currently don't support offsets
- mState = CACHE;
- }
-
- // No LOCAL state for write()
-
- if (mState == CACHE)
- {
- S32 cur_imagesize = 0;
- S32 offset = mOffset;
- idx = mCache->getHeaderCacheEntry(mID, false, &cur_imagesize);
- if (idx >= 0 && cur_imagesize > 0)
- {
- offset = TEXTURE_CACHE_ENTRY_SIZE; // don't re-write header
- }
- idx = mCache->getHeaderCacheEntry(mID, true, &mImageSize); // touch entry
- if (idx >= 0)
- {
- llassert_always(cur_imagesize <= 0 || mImageSize == cur_imagesize);
- mState = offset < TEXTURE_CACHE_ENTRY_SIZE ? HEADER : BODY;
- }
- else
- {
- mDataSize = -1; // failed
- return true;
- }
- }
-
- if (mState == HEADER)
- {
-#if USE_LFS_WRITE
- if (mFileHandle == LLLFSThread::nullHandle())
- {
- llassert_always(idx >= 0);
- llassert_always(mOffset < TEXTURE_CACHE_ENTRY_SIZE);
- S32 offset = idx * TEXTURE_CACHE_ENTRY_SIZE + mOffset;
- S32 size = TEXTURE_CACHE_ENTRY_SIZE - mOffset;
- mBytesRead = -1;
- mBytesToRead = size;
- setPriority(LLWorkerThread::PRIORITY_LOW | mPriority);
- mFileHandle = LLLFSThread::sLocal->write(mCache->mHeaderDataFileName,
- mWriteData, offset, mBytesToRead,
- new WriteResponder(mCache, mRequestHandle));
- return false;
- }
- else
- {
- if (mBytesRead >= 0)
- {
- if (mBytesRead != mBytesToRead)
- {
- llwarns << "LLTextureCacheWorker: " << mID
- << " incorrect number of bytes written to header: " << mBytesRead
- << " != " << mBytesToRead << llendl;
- mDataSize = -1; // failed
- return true;
- }
- if (mDataSize <= mBytesToRead)
- {
- return true; // done
- }
- else
- {
- mFileHandle = LLLFSThread::nullHandle();
- mState = BODY;
- }
- }
- else
- {
- return false;
- }
- }
-#else
- llassert_always(idx >= 0);
- llassert_always(mOffset < TEXTURE_CACHE_ENTRY_SIZE);
- S32 offset = idx * TEXTURE_CACHE_ENTRY_SIZE + mOffset;
- S32 size = TEXTURE_CACHE_ENTRY_SIZE - mOffset;
- S32 bytes_written = ll_apr_file_write_ex(mCache->mHeaderDataFileName, mCache->getFileAPRPool(),
- mWriteData, offset, size);
-
- if (bytes_written <= 0)
- {
- llwarns << "LLTextureCacheWorker: missing entry: " << mID << llendl;
- mDataSize = -1; // failed
- return true;
- }
-
- if (mDataSize <= size)
- {
- return true; // done
- }
- else
- {
- mState = BODY;
- }
-#endif
- }
-
- if (mState == BODY)
- {
-#if USE_LFS_WRITE
- if (mFileHandle == LLLFSThread::nullHandle())
- {
- S32 data_offset = TEXTURE_CACHE_ENTRY_SIZE - mOffset;
- data_offset = llmax(data_offset, 0);
- S32 file_size = mDataSize - data_offset;
- S32 file_offset = mOffset - TEXTURE_CACHE_ENTRY_SIZE;
- file_offset = llmax(file_offset, 0);
- if (file_size > 0 && mCache->appendToTextureEntryList(mID, file_size))
- {
- std::string filename = mCache->getTextureFileName(mID);
- mBytesRead = -1;
- mBytesToRead = file_size;
- setPriority(LLWorkerThread::PRIORITY_LOW | mPriority);
- mFileHandle = LLLFSThread::sLocal->write(filename,
- mWriteData + data_offset, file_offset, mBytesToRead,
- new WriteResponder(mCache, mRequestHandle));
- return false;
- }
- else
- {
- mDataSize = 0; // no data written
- return true; // done
- }
- }
- else
- {
- if (mBytesRead >= 0)
- {
- if (mBytesRead != mBytesToRead)
- {
- llwarns << "LLTextureCacheWorker: " << mID
- << " incorrect number of bytes written to body: " << mBytesRead
- << " != " << mBytesToRead << llendl;
- mDataSize = -1; // failed
- }
- return true;
- }
- else
- {
- return false;
- }
- }
-#else
- S32 data_offset = TEXTURE_CACHE_ENTRY_SIZE - mOffset;
- data_offset = llmax(data_offset, 0);
- S32 file_size = mDataSize - data_offset;
- S32 file_offset = mOffset - TEXTURE_CACHE_ENTRY_SIZE;
- file_offset = llmax(file_offset, 0);
- S32 bytes_written = 0;
- if (file_size > 0 && mCache->appendToTextureEntryList(mID, file_size))
- {
- std::string filename = mCache->getTextureFileName(mID);
- bytes_written = ll_apr_file_write_ex(filename, mCache->getFileAPRPool(),
- mWriteData + data_offset,
- file_offset, file_size);
- if (bytes_written <= 0)
- {
- mDataSize = -1; // failed
- }
- }
- else
- {
- mDataSize = 0; // no data written
- }
-
- return true;
-#endif
- }
-
- return false;
-}
-
-//virtual
-bool LLTextureCacheWorker::doWork(S32 param)
-{
- bool res = false;
- if (param == 0) // read
- {
- res = doRead();
- }
- else if (param == 1) // write
- {
- res = doWrite();
- }
- else
- {
- llassert_always(0);
- }
- return res;
-}
-
-//virtual (WORKER THREAD)
-void LLTextureCacheWorker::finishWork(S32 param, bool completed)
-{
- if (mResponder.notNull())
- {
- bool success = (completed && mDataSize > 0);
- if (param == 0)
- {
- // read
- if (success)
- {
- mResponder->setData(mReadData, mDataSize, mImageSize, mImageFormat, mImageLocal);
- mReadData = NULL; // responder owns data
- mDataSize = 0;
- }
- else
- {
- delete[] mReadData;
- mReadData = NULL;
-
- }
- }
- else
- {
- // write
- mWriteData = NULL; // we never owned data
- mDataSize = 0;
- }
- mResponder->completed(success);
- }
-}
-
-//virtual (MAIN THREAD)
-void LLTextureCacheWorker::endWork(S32 param, bool aborted)
-{
- if (aborted)
- {
- // Let the destructor handle any cleanup
- return;
- }
- switch(param)
- {
- default:
- case 0: // read
- case 1: // write
- {
- if (mDataSize < 0)
- {
- // failed
- mCache->removeFromCache(mID);
- }
- break;
- }
- }
-}
-
-//////////////////////////////////////////////////////////////////////////////
-
-LLTextureCache::LLTextureCache(bool threaded)
- : LLWorkerThread("TextureCache", threaded),
- mWorkersMutex(getAPRPool()),
- mHeaderMutex(getAPRPool()),
- mFileAPRPool(NULL),
- mReadOnly(FALSE),
- mTexturesSizeTotal(0),
- mDoPurge(FALSE)
-{
- apr_pool_create(&mFileAPRPool, NULL);
-}
-
-LLTextureCache::~LLTextureCache()
-{
- apr_pool_destroy(mFileAPRPool);
-}
-
-//////////////////////////////////////////////////////////////////////////////
-
-//virtual
-S32 LLTextureCache::update(U32 max_time_ms)
-{
- S32 res;
- res = LLWorkerThread::update(max_time_ms);
-
- lockWorkers();
- for (std::vector<handle_t>::iterator iter1 = mPrioritizeWriteList.begin();
- iter1 != mPrioritizeWriteList.end(); ++iter1)
- {
- handle_t handle = *iter1;
- handle_map_t::iterator iter2 = mWriters.find(handle);
- if(iter2 != mWriters.end())
- {
- LLTextureCacheWorker* worker = iter2->second;
- worker->setPriority(LLWorkerThread::PRIORITY_HIGH | worker->mPriority);
- }
- }
- mPrioritizeWriteList.clear();
- unlockWorkers();
- return res;
-}
-
-//////////////////////////////////////////////////////////////////////////////
-
-std::string LLTextureCache::getLocalFileName(const LLUUID& id)
-{
- // Does not include extension
- std::string idstr = id.asString();
- std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_SKINS, "textures", idstr);
- return filename;
-}
-
-std::string LLTextureCache::getTextureFileName(const LLUUID& id)
-{
- std::string idstr = id.asString();
- std::string delem = gDirUtilp->getDirDelimiter();
- std::string filename = mTexturesDirName + delem + idstr[0] + delem + idstr;
- return filename;
-}
-
-bool LLTextureCache::appendToTextureEntryList(const LLUUID& id, S32 bodysize)
-{
- bool res = false;
- bool purge = false;
- // Append UUID to end of texture entries
- {
- LLMutexLock lock(&mHeaderMutex);
- size_map_t::iterator iter = mTexturesSizeMap.find(id);
- if (iter == mTexturesSizeMap.end() || iter->second < bodysize)
- {
- llassert_always(bodysize > 0);
- Entry* entry = new Entry(id, bodysize, time(NULL));
- ll_apr_file_write_ex(mTexturesDirEntriesFileName, getFileAPRPool(),
- (U8*)entry, -1, 1*sizeof(Entry));
- delete entry;
- if (iter != mTexturesSizeMap.end())
- {
- mTexturesSizeTotal -= iter->second;
- }
- mTexturesSizeTotal += bodysize;
- mTexturesSizeMap[id] = bodysize;
- if (mTexturesSizeTotal > sCacheMaxTexturesSize)
- {
- purge = true;
- }
- res = true;
- }
- }
- if (purge)
- {
- mDoPurge = TRUE;
- }
- return res;
-}
-
-//////////////////////////////////////////////////////////////////////////////
-
-//static
-const S32 MAX_REASONABLE_FILE_SIZE = 512*1024*1024; // 512 MB
-F32 LLTextureCache::sHeaderCacheVersion = 1.0f;
-U32 LLTextureCache::sCacheMaxEntries = MAX_REASONABLE_FILE_SIZE / TEXTURE_CACHE_ENTRY_SIZE;
-S64 LLTextureCache::sCacheMaxTexturesSize = 0; // no limit
-const char* entries_filename = "texture.entries";
-const char* cache_filename = "texture.cache";
-const char* textures_dirname = "textures";
-
-void LLTextureCache::setDirNames(ELLPath location)
-{
- std::string delem = gDirUtilp->getDirDelimiter();
- mHeaderEntriesFileName = gDirUtilp->getExpandedFilename(location, entries_filename);
- mHeaderDataFileName = gDirUtilp->getExpandedFilename(location, cache_filename);
- mTexturesDirName = gDirUtilp->getExpandedFilename(location, textures_dirname);
- mTexturesDirEntriesFileName = mTexturesDirName + delem + entries_filename;
-}
-
-void LLTextureCache::purgeCache(ELLPath location)
-{
- if (!mReadOnly)
- {
- setDirNames(location);
-
- ll_apr_file_remove(mHeaderEntriesFileName, NULL);
- ll_apr_file_remove(mHeaderDataFileName, NULL);
- }
- purgeAllTextures(true);
-}
-
-S64 LLTextureCache::initCache(ELLPath location, S64 max_size, BOOL read_only)
-{
- mReadOnly = read_only;
-
- S64 header_size = (max_size * 2) / 10;
- S64 max_entries = header_size / TEXTURE_CACHE_ENTRY_SIZE;
- sCacheMaxEntries = (S32)(llmin((S64)sCacheMaxEntries, max_entries));
- header_size = sCacheMaxEntries * TEXTURE_CACHE_ENTRY_SIZE;
- max_size -= header_size;
- if (sCacheMaxTexturesSize > 0)
- sCacheMaxTexturesSize = llmin(sCacheMaxTexturesSize, max_size);
- else
- sCacheMaxTexturesSize = max_size;
- max_size -= sCacheMaxTexturesSize;
-
- llinfos << "TEXTURE CACHE: Headers: " << sCacheMaxEntries
- << " Textures size: " << sCacheMaxTexturesSize/(1024*1024) << " MB" << llendl;
-
- setDirNames(location);
-
- if (!mReadOnly)
- {
- LLFile::mkdir(mTexturesDirName.c_str());
- const char* subdirs = "0123456789abcdef";
- for (S32 i=0; i<16; i++)
- {
- std::string dirname = mTexturesDirName + gDirUtilp->getDirDelimiter() + subdirs[i];
- LLFile::mkdir(dirname.c_str());
- }
- }
- readHeaderCache();
- purgeTextures(true); // calc mTexturesSize and make some room in the texture cache if we need it
-
- return max_size; // unused cache space
-}
-
-struct lru_data
-{
- lru_data(U32 t, S32 i, const LLUUID& id) { time=t; index=i; uuid=id; }
- U32 time;
- S32 index;
- LLUUID uuid;
- struct Compare
- {
- // lhs < rhs
- typedef const lru_data* lru_data_ptr;
- bool operator()(const lru_data_ptr& a, const lru_data_ptr& b) const
- {
- if (!(a->time < b->time))
- return true;
- else if (!(b->time < a->time))
- return false;
- else
- return a->index < b->index;
- }
- };
-};
-
-// Called from either the main thread or the worker thread
-void LLTextureCache::readHeaderCache(apr_pool_t* poolp)
-{
- LLMutexLock lock(&mHeaderMutex);
- mHeaderEntriesInfo.mVersion = 0.f;
- mHeaderEntriesInfo.mEntries = 0;
- if (ll_apr_file_exists(mHeaderEntriesFileName, poolp))
- {
- ll_apr_file_read_ex(mHeaderEntriesFileName, poolp,
- (U8*)&mHeaderEntriesInfo, 0, sizeof(EntriesInfo));
- }
- if (mHeaderEntriesInfo.mVersion != sHeaderCacheVersion)
- {
- if (!mReadOnly)
- {
- // Info with 0 entries
- mHeaderEntriesInfo.mVersion = sHeaderCacheVersion;
- ll_apr_file_write_ex(mHeaderEntriesFileName, poolp,
- (U8*)&mHeaderEntriesInfo, 0, sizeof(EntriesInfo));
- }
- }
- else
- {
- S32 num_entries = mHeaderEntriesInfo.mEntries;
- if (num_entries)
- {
- Entry* entries = new Entry[num_entries];
- ll_apr_file_read_ex(mHeaderEntriesFileName, poolp,
- (U8*)entries, sizeof(EntriesInfo), num_entries*sizeof(Entry));
- typedef std::set<lru_data*, lru_data::Compare> lru_set_t;
- lru_set_t lru;
- for (S32 i=0; i<num_entries; i++)
- {
- if (entries[i].mSize >= 0) // -1 indicates erased entry, skip
- {
- const LLUUID& id = entries[i].mID;
- lru.insert(new lru_data(entries[i].mTime, i, id));
- mHeaderIDMap[id] = i;
- }
- }
- mLRU.clear();
- S32 lru_entries = sCacheMaxEntries / 10;
- for (lru_set_t::iterator iter = lru.begin(); iter != lru.end(); ++iter)
- {
- lru_data* data = *iter;
- mLRU[data->index] = data->uuid;
- if (--lru_entries <= 0)
- break;
- }
- for_each(lru.begin(), lru.end(), DeletePointer());
- delete[] entries;
- }
- }
-}
-
-//////////////////////////////////////////////////////////////////////////////
-
-void LLTextureCache::purgeAllTextures(bool purge_directories)
-{
- if (!mReadOnly)
- {
- const char* subdirs = "0123456789abcdef";
- std::string delem = gDirUtilp->getDirDelimiter();
- std::string mask = delem + "*";
- for (S32 i=0; i<16; i++)
- {
- std::string dirname = mTexturesDirName + delem + subdirs[i];
- gDirUtilp->deleteFilesInDir(dirname.c_str(),mask);
- if (purge_directories)
- {
- LLFile::rmdir(dirname.c_str());
- }
- }
- ll_apr_file_remove(mTexturesDirEntriesFileName, NULL);
- if (purge_directories)
- {
- LLFile::rmdir(mTexturesDirName.c_str());
- }
- }
- mTexturesSizeMap.clear();
-}
-
-void LLTextureCache::purgeTextures(bool validate)
-{
- if (mReadOnly)
- {
- return;
- }
-
- LLMutexLock lock(&mHeaderMutex);
-
- S32 filesize = ll_apr_file_size(mTexturesDirEntriesFileName, NULL);
- S32 num_entries = filesize / sizeof(Entry);
- if (num_entries * sizeof(Entry) != filesize)
- {
- llwarns << "Bad cache file: " << mTexturesDirEntriesFileName << " Purging." << llendl;
- purgeAllTextures(false);
- return;
- }
- if (num_entries == 0)
- {
- return; // nothing to do
- }
-
- Entry* entries = new Entry[num_entries];
- S32 bytes_read = ll_apr_file_read_ex(mTexturesDirEntriesFileName, NULL,
- (U8*)entries, 0, num_entries*sizeof(Entry));
- if (bytes_read != filesize)
- {
- llwarns << "Bad cache file (2): " << mTexturesDirEntriesFileName << " Purging." << llendl;
- purgeAllTextures(false);
- return;
- }
-
- llinfos << "TEXTURE CACHE: Reading Entries..." << llendl;
-
- std::map<LLUUID, S32> entry_idx_map;
- S64 total_size = 0;
- for (S32 idx=0; idx<num_entries; idx++)
- {
- const LLUUID& id = entries[idx].mID;
-// llinfos << "Entry: " << id << " Size: " << entries[i].mSize << " Time: " << entries[i].mTime << llendl;
- std::map<LLUUID, S32>::iterator iter = entry_idx_map.find(id);
- if (iter != entry_idx_map.end())
- {
- // Newer entry replacing older entry
- S32 pidx = iter->second;
- total_size -= entries[pidx].mSize;
- entries[pidx].mSize = 0; // flag: skip older entry
- }
- entry_idx_map[id] = idx;
- total_size += entries[idx].mSize;
- }
-
- U32 validate_idx = 0;
- if (validate)
- {
- validate_idx = gSavedSettings.getU32("CacheValidateCounter");
- U32 next_idx = (++validate_idx) % 256;
- gSavedSettings.setU32("CacheValidateCounter", next_idx);
- llinfos << "TEXTURE CACHE: Validating: " << validate_idx << llendl;
- }
-
- S64 min_cache_size = (sCacheMaxTexturesSize * 9) / 10;
- S32 purge_count = 0;
- S32 next_idx = 0;
- for (S32 idx=0; idx<num_entries; idx++)
- {
- if (entries[idx].mSize == 0)
- {
- continue;
- }
- bool purge_entry = false;
- std::string filename = getTextureFileName(entries[idx].mID);
- if (total_size >= min_cache_size)
- {
- purge_entry = true;
- }
- else if (validate)
- {
- // make sure file exists and is the correct size
- S32 uuididx = entries[idx].mID.mData[0];
- if (uuididx == validate_idx)
- {
-// llinfos << "Validating: " << filename << "Size: " << entries[idx].mSize << llendl;
- S32 bodysize = ll_apr_file_size(filename, NULL);
- if (bodysize != entries[idx].mSize)
- {
- llwarns << "TEXTURE CACHE BODY HAS BAD SIZE: " << bodysize << " != " << entries[idx].mSize
- << filename << llendl;
- purge_entry = true;
- }
- }
- }
- if (purge_entry)
- {
- purge_count++;
-// llinfos << "PURGING: " << filename << llendl;
- ll_apr_file_remove(filename, NULL);
- total_size -= entries[idx].mSize;
- entries[idx].mSize = 0;
- }
- else
- {
- if (next_idx != idx)
- {
- entries[next_idx] = entries[idx];
- }
- ++next_idx;
- }
- }
- num_entries = next_idx;
-
- llinfos << "TEXTURE CACHE: Writing Entries: " << num_entries << llendl;
-
- ll_apr_file_remove(mTexturesDirEntriesFileName, NULL);
- ll_apr_file_write_ex(mTexturesDirEntriesFileName, NULL,
- (U8*)&entries[0], 0, num_entries*sizeof(Entry));
-
- mTexturesSizeTotal = 0;
- mTexturesSizeMap.clear();
- for (S32 idx=0; idx<num_entries; idx++)
- {
- mTexturesSizeMap[entries[idx].mID] = entries[idx].mSize;
- mTexturesSizeTotal += entries[idx].mSize;
- }
- llassert(mTexturesSizeTotal == total_size);
-
- delete[] entries;
-
- llinfos << "TEXTURE CACHE:"
- << " PURGED: " << purge_count
- << " ENTRIES: " << num_entries
- << " CACHE SIZE: " << total_size / 1024*1024 << " MB"
- << llendl;
-}
-
-//////////////////////////////////////////////////////////////////////////////
-
-// call lockWorkers() first!
-LLTextureCacheWorker* LLTextureCache::getReader(handle_t handle)
-{
- LLTextureCacheWorker* res = NULL;
- handle_map_t::iterator iter = mReaders.find(handle);
- if (iter != mReaders.end())
- {
- res = iter->second;
- }
- return res;
-}
-
-LLTextureCacheWorker* LLTextureCache::getWriter(handle_t handle)
-{
- LLTextureCacheWorker* res = NULL;
- handle_map_t::iterator iter = mWriters.find(handle);
- if (iter != mWriters.end())
- {
- res = iter->second;
- }
- return res;
-}
-
-//////////////////////////////////////////////////////////////////////////////
-
-// Called from work thread
-S32 LLTextureCache::getHeaderCacheEntry(const LLUUID& id, bool touch, S32* imagesize)
-{
- bool retry = false;
- S32 idx = -1;
-
- {
- LLMutexLock lock(&mHeaderMutex);
- id_map_t::iterator iter = mHeaderIDMap.find(id);
- if (iter != mHeaderIDMap.end())
- {
- idx = iter->second;
- }
- else if (touch && !mReadOnly)
- {
- if (mHeaderEntriesInfo.mEntries < sCacheMaxEntries)
- {
- // Add an entry
- idx = mHeaderEntriesInfo.mEntries++;
- mHeaderIDMap[id] = idx;
- // Update Info
- ll_apr_file_write_ex(mHeaderEntriesFileName, getFileAPRPool(),
- (U8*)&mHeaderEntriesInfo, 0, sizeof(EntriesInfo));
- }
- else if (!mLRU.empty())
- {
- idx = mLRU.begin()->first; // will be erased below
- const LLUUID& oldid = mLRU.begin()->second;
- mHeaderIDMap.erase(oldid);
- mTexturesSizeMap.erase(oldid);
- mHeaderIDMap[id] = idx;
- }
- else
- {
- idx = -1;
- retry = true;
- }
- }
- if (idx >= 0)
- {
- if (touch && !mReadOnly)
- {
- // Update the lru entry
- mLRU.erase(idx);
- llassert_always(imagesize && *imagesize > 0);
- Entry* entry = new Entry(id, *imagesize, time(NULL));
- S32 offset = sizeof(EntriesInfo) + idx * sizeof(Entry);
- ll_apr_file_write_ex(mHeaderEntriesFileName, getFileAPRPool(),
- (U8*)entry, offset, sizeof(Entry));
- delete entry;
- }
- else if (imagesize)
- {
- // Get the image size
- Entry entry;
- S32 offset = sizeof(EntriesInfo) + idx * sizeof(Entry);
- ll_apr_file_read_ex(mHeaderEntriesFileName, getFileAPRPool(),
- (U8*)&entry, offset, sizeof(Entry));
- *imagesize = entry.mSize;
- }
- }
- }
- if (retry)
- {
- readHeaderCache(getFileAPRPool()); // updates the lru
- llassert_always(!mLRU.empty() || mHeaderEntriesInfo.mEntries < sCacheMaxEntries);
- idx = getHeaderCacheEntry(id, touch, imagesize); // assert above ensures no inf. recursion
- }
- return idx;
-}
-
-//////////////////////////////////////////////////////////////////////////////
-
-// Calls from texture pipeline thread (i.e. LLTextureFetch)
-
-LLTextureCache::handle_t LLTextureCache::readFromCache(const LLUUID& id, U32 priority,
- S32 offset, S32 size, ReadResponder* responder)
-{
- // Note: checking to see if an entry exists can cause a stall,
- // so let the thread handle it
- LLMutexLock lock(&mWorkersMutex);
- LLTextureCacheWorker* worker = new LLTextureCacheWorker(this, priority, id,
- NULL, size, offset, 0,
- responder);
- handle_t handle = worker->read();
- mReaders[handle] = worker;
- return handle;
-}
-
-bool LLTextureCache::readComplete(handle_t handle, bool abort)
-{
- lockWorkers();
- handle_map_t::iterator iter = mReaders.find(handle);
- llassert_always(iter != mReaders.end());
- LLTextureCacheWorker* worker = iter->second;
- bool res = worker->complete();
- if (res || abort)
- {
- mReaders.erase(handle);
- unlockWorkers();
- worker->scheduleDelete();
- return true;
- }
- else
- {
- unlockWorkers();
- return false;
- }
-}
-
-LLTextureCache::handle_t LLTextureCache::writeToCache(const LLUUID& id, U32 priority,
- U8* data, S32 datasize, S32 imagesize,
- WriteResponder* responder)
-{
- if (mReadOnly)
- {
- return LLWorkerThread::nullHandle();
- }
- if (mDoPurge)
- {
- // NOTE: This may cause an occasional hiccup,
- // but it really needs to be done on the control thread
- // (i.e. here)
- purgeTextures(false);
- mDoPurge = FALSE;
- }
- if (datasize >= TEXTURE_CACHE_ENTRY_SIZE)
- {
- LLMutexLock lock(&mWorkersMutex);
- llassert_always(imagesize > 0);
- LLTextureCacheWorker* worker = new LLTextureCacheWorker(this, priority, id,
- data, datasize, 0,
- imagesize, responder);
- handle_t handle = worker->write();
- mWriters[handle] = worker;
- return handle;
- }
- return LLWorkerThread::nullHandle();
-}
-
-bool LLTextureCache::writeComplete(handle_t handle, bool abort)
-{
- lockWorkers();
- handle_map_t::iterator iter = mWriters.find(handle);
- llassert_always(iter != mWriters.end());
- LLTextureCacheWorker* worker = iter->second;
- if (worker->complete() || abort)
- {
- mWriters.erase(handle);
- unlockWorkers();
- worker->scheduleDelete();
- return true;
- }
- else
- {
- unlockWorkers();
- return false;
- }
-}
-
-void LLTextureCache::prioritizeWrite(handle_t handle)
-{
- // Don't prioritize yet, we might be working on this now
- // which could create a deadlock
- mPrioritizeWriteList.push_back(handle);
-}
-
-//////////////////////////////////////////////////////////////////////////////
-
-// Called from MAIN thread (endWork())
-
-bool LLTextureCache::removeHeaderCacheEntry(const LLUUID& id)
-{
- if (mReadOnly)
- {
- return false;
- }
- LLMutexLock lock(&mHeaderMutex);
- id_map_t::iterator iter = mHeaderIDMap.find(id);
- if (iter != mHeaderIDMap.end())
- {
- S32 idx = iter->second;
- if (idx >= 0)
- {
- Entry* entry = new Entry(id, -1, time(NULL));
- S32 offset = sizeof(EntriesInfo) + idx * sizeof(Entry);
- ll_apr_file_write_ex(mHeaderEntriesFileName, NULL,
- (U8*)entry, offset, sizeof(Entry));
- delete entry;
- mLRU[idx] = id;
- mHeaderIDMap.erase(id);
- mTexturesSizeMap.erase(id);
- return true;
- }
- }
- return false;
-}
-
-void LLTextureCache::removeFromCache(const LLUUID& id)
-{
- llwarns << "Removing texture from cache: " << id << llendl;
- if (!mReadOnly)
- {
- removeHeaderCacheEntry(id);
- ll_apr_file_remove(getTextureFileName(id), NULL);
- }
-}
-
-//////////////////////////////////////////////////////////////////////////////
-
-LLTextureCache::ReadResponder::ReadResponder()
- : mImageSize(0),
- mImageLocal(FALSE)
-{
-}
-
-void LLTextureCache::ReadResponder::setData(U8* data, S32 datasize, S32 imagesize, S32 imageformat, BOOL imagelocal)
-{
- if (mFormattedImage.notNull())
- {
- llassert_always(mFormattedImage->getCodec() == imageformat);
- mFormattedImage->appendData(data, datasize);
- }
- else
- {
- mFormattedImage = LLImageFormatted::createFromType(imageformat);
- mFormattedImage->setData(data,datasize);
- }
- mImageSize = imagesize;
- mImageLocal = imagelocal;
-}
-
-//////////////////////////////////////////////////////////////////////////////
+/**
+ * @file texturecache.cpp
+ * @brief Object which handles local texture caching
+ *
+ * Copyright (c) 2000-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "lltexturecache.h"
+
+#include "llapr.h"
+#include "lldir.h"
+#include "llimage.h"
+#include "lllfsthread.h"
+#include "llviewercontrol.h"
+
+#define USE_LFS_READ 0
+#define USE_LFS_WRITE 0
+
+// Note: first 4 bytes store file size, rest is j2c data
+const S32 TEXTURE_CACHE_ENTRY_SIZE = FIRST_PACKET_SIZE; //1024;
+
+class LLTextureCacheWorker : public LLWorkerClass
+{
+ friend class LLTextureCache;
+
+private:
+ enum e_state
+ {
+ INIT = 0,
+ LOCAL = 1,
+ CACHE = 2,
+ HEADER = 3,
+ BODY = 4
+ };
+
+ class ReadResponder : public LLLFSThread::Responder
+ {
+ public:
+ ReadResponder(LLTextureCache* cache, handle_t handle) : mCache(cache), mHandle(handle) {}
+ ~ReadResponder() {}
+ void completed(S32 bytes)
+ {
+ mCache->lockWorkers();
+ LLTextureCacheWorker* reader = mCache->getReader(mHandle);
+ if (reader) reader->ioComplete(bytes);
+ mCache->unlockWorkers();
+ }
+ LLTextureCache* mCache;
+ LLTextureCacheWorker::handle_t mHandle;
+ };
+
+ class WriteResponder : public LLLFSThread::Responder
+ {
+ public:
+ WriteResponder(LLTextureCache* cache, handle_t handle) : mCache(cache), mHandle(handle) {}
+ ~WriteResponder() {}
+ void completed(S32 bytes)
+ {
+ mCache->lockWorkers();
+ LLTextureCacheWorker* writer = mCache->getWriter(mHandle);
+ if (writer) writer->ioComplete(bytes);
+ mCache->unlockWorkers();
+ }
+ LLTextureCache* mCache;
+ LLTextureCacheWorker::handle_t mHandle;
+ };
+
+public:
+ LLTextureCacheWorker(LLTextureCache* cache, U32 priority, const LLUUID& id,
+ U8* data, S32 datasize, S32 offset,
+ S32 imagesize, // for writes
+ LLTextureCache::Responder* responder)
+ : LLWorkerClass(cache, "LLTextureCacheWorker"),
+ mCache(cache),
+ mPriority(priority),
+ mID(id),
+ mState(INIT),
+ mReadData(NULL),
+ mWriteData(data),
+ mDataSize(datasize),
+ mOffset(offset),
+ mImageSize(imagesize),
+ mImageFormat(IMG_CODEC_J2C),
+ mImageLocal(FALSE),
+ mResponder(responder),
+ mFileHandle(LLLFSThread::nullHandle()),
+ mBytesToRead(0),
+ mBytesRead(0)
+ {
+ mPriority &= LLWorkerThread::PRIORITY_LOWBITS;
+ }
+ ~LLTextureCacheWorker()
+ {
+ llassert_always(!haveWork());
+ delete[] mReadData;
+ }
+
+ bool doRead();
+ bool doWrite();
+ virtual bool doWork(S32 param); // Called from LLWorkerThread::processRequest()
+
+ handle_t read() { addWork(0, LLWorkerThread::PRIORITY_HIGH | mPriority); return mRequestHandle; }
+ handle_t write() { addWork(1, LLWorkerThread::PRIORITY_HIGH | mPriority); return mRequestHandle; }
+ bool complete() { return checkWork(); }
+ void ioComplete(S32 bytes)
+ {
+ mBytesRead = bytes;
+ setPriority(LLWorkerThread::PRIORITY_HIGH | mPriority);
+ }
+
+private:
+ virtual void startWork(S32 param); // called from addWork() (MAIN THREAD)
+ virtual void finishWork(S32 param, bool completed); // called from finishRequest() (WORK THREAD)
+ virtual void endWork(S32 param, bool aborted); // called from doWork() (MAIN THREAD)
+
+private:
+ LLTextureCache* mCache;
+ U32 mPriority;
+ LLUUID mID;
+ e_state mState;
+
+ U8* mReadData;
+ U8* mWriteData;
+ S32 mDataSize;
+ S32 mOffset;
+ S32 mImageSize;
+ S32 mImageFormat;
+ BOOL mImageLocal;
+ LLPointer<LLTextureCache::Responder> mResponder;
+ LLLFSThread::handle_t mFileHandle;
+ S32 mBytesToRead;
+ LLAtomicS32 mBytesRead;
+};
+
+//virtual
+void LLTextureCacheWorker::startWork(S32 param)
+{
+}
+
+bool LLTextureCacheWorker::doRead()
+{
+ S32 local_size = 0;
+ std::string local_filename;
+
+ if (mState == INIT)
+ {
+ std::string filename = mCache->getLocalFileName(mID);
+ local_filename = filename + ".j2c";
+ local_size = ll_apr_file_size(local_filename, mCache->getFileAPRPool());
+ if (local_size == 0)
+ {
+ local_filename = filename + ".tga";
+ local_size = ll_apr_file_size(local_filename, mCache->getFileAPRPool());
+ if (local_size > 0)
+ {
+ mImageFormat = IMG_CODEC_TGA;
+ mDataSize = local_size; // Only a complete .tga file is valid
+ }
+ }
+ if (local_size > 0)
+ {
+ mState = LOCAL;
+ }
+ else
+ {
+ mState = CACHE;
+ }
+ }
+
+ if (mState == LOCAL)
+ {
+#if USE_LFS_READ
+ if (mFileHandle == LLLFSThread::nullHandle())
+ {
+ mImageLocal = TRUE;
+ mImageSize = local_size;
+ if (!mDataSize || mDataSize + mOffset > local_size)
+ {
+ mDataSize = local_size - mOffset;
+ }
+ if (mDataSize <= 0)
+ {
+ // no more data to read
+ mDataSize = 0;
+ return true;
+ }
+ mReadData = new U8[mDataSize];
+ mBytesRead = -1;
+ mBytesToRead = mDataSize;
+ setPriority(LLWorkerThread::PRIORITY_LOW | mPriority);
+ mFileHandle = LLLFSThread::sLocal->read(local_filename, mReadData, mOffset, mDataSize,
+ new ReadResponder(mCache, mRequestHandle));
+ return false;
+ }
+ else
+ {
+ if (mBytesRead >= 0)
+ {
+ if (mBytesRead != mBytesToRead)
+ {
+ llwarns << "Error reading file from local cache: " << local_filename
+ << " Bytes: " << mDataSize << " Offset: " << mOffset
+ << " / " << mDataSize << llendl;
+ mDataSize = 0; // failed
+ delete[] mReadData;
+ mReadData = NULL;
+ }
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+#else
+ if (!mDataSize || mDataSize > local_size)
+ {
+ mDataSize = local_size;
+ }
+ mReadData = new U8[mDataSize];
+ S32 bytes_read = ll_apr_file_read_ex(local_filename, mCache->getFileAPRPool(),
+ mReadData, mOffset, mDataSize);
+ if (bytes_read != mDataSize)
+ {
+ llwarns << "Error reading file from local cache: " << local_filename
+ << " Bytes: " << mDataSize << " Offset: " << mOffset
+ << " / " << mDataSize << llendl;
+ mDataSize = 0;
+ delete[] mReadData;
+ mReadData = NULL;
+ }
+ else
+ {
+ mImageSize = local_size;
+ mImageLocal = TRUE;
+ }
+ return true;
+#endif
+ }
+
+ S32 idx = -1;
+
+ if (mState == CACHE)
+ {
+ llassert_always(mImageSize == 0);
+ idx = mCache->getHeaderCacheEntry(mID, false, &mImageSize);
+ if (idx >= 0 && mImageSize > mOffset)
+ {
+ llassert_always(mImageSize > 0);
+ if (!mDataSize || mDataSize > mImageSize)
+ {
+ mDataSize = mImageSize;
+ }
+ mState = mOffset < TEXTURE_CACHE_ENTRY_SIZE ? HEADER : BODY;
+ }
+ else
+ {
+ mDataSize = 0; // no data
+ return true;
+ }
+ }
+
+ if (mState == HEADER)
+ {
+#if USE_LFS_READ
+ if (mFileHandle == LLLFSThread::nullHandle())
+ {
+ llassert_always(idx >= 0);
+ llassert_always(mOffset < TEXTURE_CACHE_ENTRY_SIZE);
+ S32 offset = idx * TEXTURE_CACHE_ENTRY_SIZE + mOffset;
+ S32 size = TEXTURE_CACHE_ENTRY_SIZE - mOffset;
+ llassert_always(mReadData == NULL);
+ mReadData = new U8[size];
+ mBytesRead = -1;
+ mBytesToRead = size;
+ setPriority(LLWorkerThread::PRIORITY_LOW | mPriority);
+ mFileHandle = LLLFSThread::sLocal->read(mCache->mHeaderDataFileName,
+ mReadData, offset, mBytesToRead,
+ new ReadResponder(mCache, mRequestHandle));
+ return false;
+ }
+ else
+ {
+ if (mBytesRead >= 0)
+ {
+ if (mBytesRead != mBytesToRead)
+ {
+ llwarns << "LLTextureCacheWorker: " << mID
+ << " incorrect number of bytes read from header: " << mBytesRead
+ << " != " << mBytesToRead << llendl;
+ mDataSize = -1; // failed
+ return true;
+ }
+ if (mDataSize <= TEXTURE_CACHE_ENTRY_SIZE)
+ {
+ return true; // done
+ }
+ else
+ {
+ mFileHandle = LLLFSThread::nullHandle();
+ mState = BODY;
+ }
+ }
+ else
+ {
+ return false;
+ }
+ }
+#else
+ llassert_always(idx >= 0);
+ llassert_always(mOffset < TEXTURE_CACHE_ENTRY_SIZE);
+ S32 offset = idx * TEXTURE_CACHE_ENTRY_SIZE + mOffset;
+ S32 size = TEXTURE_CACHE_ENTRY_SIZE - mOffset;
+ mReadData = new U8[size];
+ S32 bytes_read = ll_apr_file_read_ex(mCache->mHeaderDataFileName, mCache->getFileAPRPool(),
+ mReadData, offset, size);
+ if (bytes_read != size)
+ {
+ llwarns << "LLTextureCacheWorker: " << mID
+ << " incorrect number of bytes read from header: " << bytes_read
+ << " / " << size << llendl;
+ mDataSize = -1; // failed
+ return true;
+ }
+ if (mDataSize <= TEXTURE_CACHE_ENTRY_SIZE)
+ {
+ return true; // done
+ }
+ else
+ {
+ mState = BODY;
+ }
+#endif
+ }
+
+ if (mState == BODY)
+ {
+#if USE_LFS_READ
+ if (mFileHandle == LLLFSThread::nullHandle())
+ {
+ std::string filename = mCache->getTextureFileName(mID);
+ S32 filesize = ll_apr_file_size(filename, mCache->getFileAPRPool());
+ if (filesize > mOffset)
+ {
+ S32 datasize = TEXTURE_CACHE_ENTRY_SIZE + filesize;
+ mDataSize = llmin(datasize, mDataSize);
+ S32 data_offset = TEXTURE_CACHE_ENTRY_SIZE - mOffset;
+ data_offset = llmax(data_offset, 0);
+ S32 file_size = mDataSize - data_offset;
+ S32 file_offset = mOffset - TEXTURE_CACHE_ENTRY_SIZE;
+ file_offset = llmax(file_offset, 0);
+
+ llassert_always(mDataSize > 0);
+ U8* data = new U8[mDataSize];
+ if (data_offset > 0)
+ {
+ llassert_always(mReadData);
+ llassert_always(data_offset <= mDataSize);
+ memcpy(data, mReadData, data_offset);
+ delete[] mReadData;
+ mReadData = NULL;
+ }
+ llassert_always(mReadData == NULL);
+ mReadData = data;
+
+ mBytesRead = -1;
+ mBytesToRead = file_size;
+ setPriority(LLWorkerThread::PRIORITY_LOW | mPriority);
+ llassert_always(data_offset + mBytesToRead <= mDataSize);
+ mFileHandle = LLLFSThread::sLocal->read(filename,
+ mReadData + data_offset, file_offset, mBytesToRead,
+ new ReadResponder(mCache, mRequestHandle));
+ return false;
+ }
+ else
+ {
+ mDataSize = TEXTURE_CACHE_ENTRY_SIZE;
+ return true; // done
+ }
+ }
+ else
+ {
+ if (mBytesRead >= 0)
+ {
+ if (mBytesRead != mBytesToRead)
+ {
+ llwarns << "LLTextureCacheWorker: " << mID
+ << " incorrect number of bytes read from body: " << mBytesRead
+ << " != " << mBytesToRead << llendl;
+ mDataSize = -1; // failed
+ }
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+#else
+ std::string filename = mCache->getTextureFileName(mID);
+ S32 filesize = ll_apr_file_size(filename, mCache->getFileAPRPool());
+ S32 bytes_read = 0;
+ if (filesize > mOffset)
+ {
+ S32 datasize = TEXTURE_CACHE_ENTRY_SIZE + filesize;
+ mDataSize = llmin(datasize, mDataSize);
+ S32 data_offset = TEXTURE_CACHE_ENTRY_SIZE - mOffset;
+ data_offset = llmax(data_offset, 0);
+ S32 file_size = mDataSize - data_offset;
+ S32 file_offset = mOffset - TEXTURE_CACHE_ENTRY_SIZE;
+ file_offset = llmax(file_offset, 0);
+
+ U8* data = new U8[mDataSize];
+ if (data_offset > 0)
+ {
+ llassert_always(mReadData);
+ memcpy(data, mReadData, data_offset);
+ delete[] mReadData;
+ }
+ mReadData = data;
+ bytes_read = ll_apr_file_read_ex(filename, mCache->getFileAPRPool(),
+ mReadData + data_offset,
+ file_offset, file_size);
+ if (bytes_read != file_size)
+ {
+ llwarns << "LLTextureCacheWorker: " << mID
+ << " incorrect number of bytes read from body: " << bytes_read
+ << " / " << file_size << llendl;
+ mDataSize = -1; // failed
+ return true;
+ }
+ }
+ else
+ {
+ mDataSize = TEXTURE_CACHE_ENTRY_SIZE;
+ }
+
+ return true;
+#endif
+ }
+
+ return false;
+}
+
+bool LLTextureCacheWorker::doWrite()
+{
+ S32 idx = -1;
+
+ if (mState == INIT)
+ {
+ llassert_always(mOffset == 0); // Currently don't support offsets
+ mState = CACHE;
+ }
+
+ // No LOCAL state for write()
+
+ if (mState == CACHE)
+ {
+ S32 cur_imagesize = 0;
+ S32 offset = mOffset;
+ idx = mCache->getHeaderCacheEntry(mID, false, &cur_imagesize);
+ if (idx >= 0 && cur_imagesize > 0)
+ {
+ offset = TEXTURE_CACHE_ENTRY_SIZE; // don't re-write header
+ }
+ idx = mCache->getHeaderCacheEntry(mID, true, &mImageSize); // touch entry
+ if (idx >= 0)
+ {
+ llassert_always(cur_imagesize <= 0 || mImageSize == cur_imagesize);
+ mState = offset < TEXTURE_CACHE_ENTRY_SIZE ? HEADER : BODY;
+ }
+ else
+ {
+ mDataSize = -1; // failed
+ return true;
+ }
+ }
+
+ if (mState == HEADER)
+ {
+#if USE_LFS_WRITE
+ if (mFileHandle == LLLFSThread::nullHandle())
+ {
+ llassert_always(idx >= 0);
+ llassert_always(mOffset < TEXTURE_CACHE_ENTRY_SIZE);
+ S32 offset = idx * TEXTURE_CACHE_ENTRY_SIZE + mOffset;
+ S32 size = TEXTURE_CACHE_ENTRY_SIZE - mOffset;
+ mBytesRead = -1;
+ mBytesToRead = size;
+ setPriority(LLWorkerThread::PRIORITY_LOW | mPriority);
+ mFileHandle = LLLFSThread::sLocal->write(mCache->mHeaderDataFileName,
+ mWriteData, offset, mBytesToRead,
+ new WriteResponder(mCache, mRequestHandle));
+ return false;
+ }
+ else
+ {
+ if (mBytesRead >= 0)
+ {
+ if (mBytesRead != mBytesToRead)
+ {
+ llwarns << "LLTextureCacheWorker: " << mID
+ << " incorrect number of bytes written to header: " << mBytesRead
+ << " != " << mBytesToRead << llendl;
+ mDataSize = -1; // failed
+ return true;
+ }
+ if (mDataSize <= mBytesToRead)
+ {
+ return true; // done
+ }
+ else
+ {
+ mFileHandle = LLLFSThread::nullHandle();
+ mState = BODY;
+ }
+ }
+ else
+ {
+ return false;
+ }
+ }
+#else
+ llassert_always(idx >= 0);
+ llassert_always(mOffset < TEXTURE_CACHE_ENTRY_SIZE);
+ S32 offset = idx * TEXTURE_CACHE_ENTRY_SIZE + mOffset;
+ S32 size = TEXTURE_CACHE_ENTRY_SIZE - mOffset;
+ S32 bytes_written = ll_apr_file_write_ex(mCache->mHeaderDataFileName, mCache->getFileAPRPool(),
+ mWriteData, offset, size);
+
+ if (bytes_written <= 0)
+ {
+ llwarns << "LLTextureCacheWorker: missing entry: " << mID << llendl;
+ mDataSize = -1; // failed
+ return true;
+ }
+
+ if (mDataSize <= size)
+ {
+ return true; // done
+ }
+ else
+ {
+ mState = BODY;
+ }
+#endif
+ }
+
+ if (mState == BODY)
+ {
+#if USE_LFS_WRITE
+ if (mFileHandle == LLLFSThread::nullHandle())
+ {
+ S32 data_offset = TEXTURE_CACHE_ENTRY_SIZE - mOffset;
+ data_offset = llmax(data_offset, 0);
+ S32 file_size = mDataSize - data_offset;
+ S32 file_offset = mOffset - TEXTURE_CACHE_ENTRY_SIZE;
+ file_offset = llmax(file_offset, 0);
+ if (file_size > 0 && mCache->appendToTextureEntryList(mID, file_size))
+ {
+ std::string filename = mCache->getTextureFileName(mID);
+ mBytesRead = -1;
+ mBytesToRead = file_size;
+ setPriority(LLWorkerThread::PRIORITY_LOW | mPriority);
+ mFileHandle = LLLFSThread::sLocal->write(filename,
+ mWriteData + data_offset, file_offset, mBytesToRead,
+ new WriteResponder(mCache, mRequestHandle));
+ return false;
+ }
+ else
+ {
+ mDataSize = 0; // no data written
+ return true; // done
+ }
+ }
+ else
+ {
+ if (mBytesRead >= 0)
+ {
+ if (mBytesRead != mBytesToRead)
+ {
+ llwarns << "LLTextureCacheWorker: " << mID
+ << " incorrect number of bytes written to body: " << mBytesRead
+ << " != " << mBytesToRead << llendl;
+ mDataSize = -1; // failed
+ }
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+#else
+ S32 data_offset = TEXTURE_CACHE_ENTRY_SIZE - mOffset;
+ data_offset = llmax(data_offset, 0);
+ S32 file_size = mDataSize - data_offset;
+ S32 file_offset = mOffset - TEXTURE_CACHE_ENTRY_SIZE;
+ file_offset = llmax(file_offset, 0);
+ S32 bytes_written = 0;
+ if (file_size > 0 && mCache->appendToTextureEntryList(mID, file_size))
+ {
+ std::string filename = mCache->getTextureFileName(mID);
+ bytes_written = ll_apr_file_write_ex(filename, mCache->getFileAPRPool(),
+ mWriteData + data_offset,
+ file_offset, file_size);
+ if (bytes_written <= 0)
+ {
+ mDataSize = -1; // failed
+ }
+ }
+ else
+ {
+ mDataSize = 0; // no data written
+ }
+
+ return true;
+#endif
+ }
+
+ return false;
+}
+
+//virtual
+bool LLTextureCacheWorker::doWork(S32 param)
+{
+ bool res = false;
+ if (param == 0) // read
+ {
+ res = doRead();
+ }
+ else if (param == 1) // write
+ {
+ res = doWrite();
+ }
+ else
+ {
+ llassert_always(0);
+ }
+ return res;
+}
+
+//virtual (WORKER THREAD)
+void LLTextureCacheWorker::finishWork(S32 param, bool completed)
+{
+ if (mResponder.notNull())
+ {
+ bool success = (completed && mDataSize > 0);
+ if (param == 0)
+ {
+ // read
+ if (success)
+ {
+ mResponder->setData(mReadData, mDataSize, mImageSize, mImageFormat, mImageLocal);
+ mReadData = NULL; // responder owns data
+ mDataSize = 0;
+ }
+ else
+ {
+ delete[] mReadData;
+ mReadData = NULL;
+
+ }
+ }
+ else
+ {
+ // write
+ mWriteData = NULL; // we never owned data
+ mDataSize = 0;
+ }
+ mResponder->completed(success);
+ }
+}
+
+//virtual (MAIN THREAD)
+void LLTextureCacheWorker::endWork(S32 param, bool aborted)
+{
+ if (aborted)
+ {
+ // Let the destructor handle any cleanup
+ return;
+ }
+ switch(param)
+ {
+ default:
+ case 0: // read
+ case 1: // write
+ {
+ if (mDataSize < 0)
+ {
+ // failed
+ mCache->removeFromCache(mID);
+ }
+ break;
+ }
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+LLTextureCache::LLTextureCache(bool threaded)
+ : LLWorkerThread("TextureCache", threaded),
+ mWorkersMutex(getAPRPool()),
+ mHeaderMutex(getAPRPool()),
+ mFileAPRPool(NULL),
+ mReadOnly(FALSE),
+ mTexturesSizeTotal(0),
+ mDoPurge(FALSE)
+{
+ apr_pool_create(&mFileAPRPool, NULL);
+}
+
+LLTextureCache::~LLTextureCache()
+{
+ apr_pool_destroy(mFileAPRPool);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+//virtual
+S32 LLTextureCache::update(U32 max_time_ms)
+{
+ S32 res;
+ res = LLWorkerThread::update(max_time_ms);
+
+ lockWorkers();
+ for (std::vector<handle_t>::iterator iter1 = mPrioritizeWriteList.begin();
+ iter1 != mPrioritizeWriteList.end(); ++iter1)
+ {
+ handle_t handle = *iter1;
+ handle_map_t::iterator iter2 = mWriters.find(handle);
+ if(iter2 != mWriters.end())
+ {
+ LLTextureCacheWorker* worker = iter2->second;
+ worker->setPriority(LLWorkerThread::PRIORITY_HIGH | worker->mPriority);
+ }
+ }
+ mPrioritizeWriteList.clear();
+ unlockWorkers();
+ return res;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+std::string LLTextureCache::getLocalFileName(const LLUUID& id)
+{
+ // Does not include extension
+ std::string idstr = id.asString();
+ std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_SKINS, "textures", idstr);
+ return filename;
+}
+
+std::string LLTextureCache::getTextureFileName(const LLUUID& id)
+{
+ std::string idstr = id.asString();
+ std::string delem = gDirUtilp->getDirDelimiter();
+ std::string filename = mTexturesDirName + delem + idstr[0] + delem + idstr;
+ return filename;
+}
+
+bool LLTextureCache::appendToTextureEntryList(const LLUUID& id, S32 bodysize)
+{
+ bool res = false;
+ bool purge = false;
+ // Append UUID to end of texture entries
+ {
+ LLMutexLock lock(&mHeaderMutex);
+ size_map_t::iterator iter = mTexturesSizeMap.find(id);
+ if (iter == mTexturesSizeMap.end() || iter->second < bodysize)
+ {
+ llassert_always(bodysize > 0);
+ Entry* entry = new Entry(id, bodysize, time(NULL));
+ ll_apr_file_write_ex(mTexturesDirEntriesFileName, getFileAPRPool(),
+ (U8*)entry, -1, 1*sizeof(Entry));
+ delete entry;
+ if (iter != mTexturesSizeMap.end())
+ {
+ mTexturesSizeTotal -= iter->second;
+ }
+ mTexturesSizeTotal += bodysize;
+ mTexturesSizeMap[id] = bodysize;
+ if (mTexturesSizeTotal > sCacheMaxTexturesSize)
+ {
+ purge = true;
+ }
+ res = true;
+ }
+ }
+ if (purge)
+ {
+ mDoPurge = TRUE;
+ }
+ return res;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+//static
+const S32 MAX_REASONABLE_FILE_SIZE = 512*1024*1024; // 512 MB
+F32 LLTextureCache::sHeaderCacheVersion = 1.0f;
+U32 LLTextureCache::sCacheMaxEntries = MAX_REASONABLE_FILE_SIZE / TEXTURE_CACHE_ENTRY_SIZE;
+S64 LLTextureCache::sCacheMaxTexturesSize = 0; // no limit
+const char* entries_filename = "texture.entries";
+const char* cache_filename = "texture.cache";
+const char* textures_dirname = "textures";
+
+void LLTextureCache::setDirNames(ELLPath location)
+{
+ std::string delem = gDirUtilp->getDirDelimiter();
+ mHeaderEntriesFileName = gDirUtilp->getExpandedFilename(location, entries_filename);
+ mHeaderDataFileName = gDirUtilp->getExpandedFilename(location, cache_filename);
+ mTexturesDirName = gDirUtilp->getExpandedFilename(location, textures_dirname);
+ mTexturesDirEntriesFileName = mTexturesDirName + delem + entries_filename;
+}
+
+void LLTextureCache::purgeCache(ELLPath location)
+{
+ if (!mReadOnly)
+ {
+ setDirNames(location);
+
+ ll_apr_file_remove(mHeaderEntriesFileName, NULL);
+ ll_apr_file_remove(mHeaderDataFileName, NULL);
+ }
+ purgeAllTextures(true);
+}
+
+S64 LLTextureCache::initCache(ELLPath location, S64 max_size, BOOL read_only)
+{
+ mReadOnly = read_only;
+
+ S64 header_size = (max_size * 2) / 10;
+ S64 max_entries = header_size / TEXTURE_CACHE_ENTRY_SIZE;
+ sCacheMaxEntries = (S32)(llmin((S64)sCacheMaxEntries, max_entries));
+ header_size = sCacheMaxEntries * TEXTURE_CACHE_ENTRY_SIZE;
+ max_size -= header_size;
+ if (sCacheMaxTexturesSize > 0)
+ sCacheMaxTexturesSize = llmin(sCacheMaxTexturesSize, max_size);
+ else
+ sCacheMaxTexturesSize = max_size;
+ max_size -= sCacheMaxTexturesSize;
+
+ llinfos << "TEXTURE CACHE: Headers: " << sCacheMaxEntries
+ << " Textures size: " << sCacheMaxTexturesSize/(1024*1024) << " MB" << llendl;
+
+ setDirNames(location);
+
+ if (!mReadOnly)
+ {
+ LLFile::mkdir(mTexturesDirName.c_str());
+ const char* subdirs = "0123456789abcdef";
+ for (S32 i=0; i<16; i++)
+ {
+ std::string dirname = mTexturesDirName + gDirUtilp->getDirDelimiter() + subdirs[i];
+ LLFile::mkdir(dirname.c_str());
+ }
+ }
+ readHeaderCache();
+ purgeTextures(true); // calc mTexturesSize and make some room in the texture cache if we need it
+
+ return max_size; // unused cache space
+}
+
+struct lru_data
+{
+ lru_data(U32 t, S32 i, const LLUUID& id) { time=t; index=i; uuid=id; }
+ U32 time;
+ S32 index;
+ LLUUID uuid;
+ struct Compare
+ {
+ // lhs < rhs
+ typedef const lru_data* lru_data_ptr;
+ bool operator()(const lru_data_ptr& a, const lru_data_ptr& b) const
+ {
+ if (!(a->time < b->time))
+ return true;
+ else if (!(b->time < a->time))
+ return false;
+ else
+ return a->index < b->index;
+ }
+ };
+};
+
+// Called from either the main thread or the worker thread
+void LLTextureCache::readHeaderCache(apr_pool_t* poolp)
+{
+ LLMutexLock lock(&mHeaderMutex);
+ mHeaderEntriesInfo.mVersion = 0.f;
+ mHeaderEntriesInfo.mEntries = 0;
+ if (ll_apr_file_exists(mHeaderEntriesFileName, poolp))
+ {
+ ll_apr_file_read_ex(mHeaderEntriesFileName, poolp,
+ (U8*)&mHeaderEntriesInfo, 0, sizeof(EntriesInfo));
+ }
+ if (mHeaderEntriesInfo.mVersion != sHeaderCacheVersion)
+ {
+ if (!mReadOnly)
+ {
+ // Info with 0 entries
+ mHeaderEntriesInfo.mVersion = sHeaderCacheVersion;
+ ll_apr_file_write_ex(mHeaderEntriesFileName, poolp,
+ (U8*)&mHeaderEntriesInfo, 0, sizeof(EntriesInfo));
+ }
+ }
+ else
+ {
+ S32 num_entries = mHeaderEntriesInfo.mEntries;
+ if (num_entries)
+ {
+ Entry* entries = new Entry[num_entries];
+ ll_apr_file_read_ex(mHeaderEntriesFileName, poolp,
+ (U8*)entries, sizeof(EntriesInfo), num_entries*sizeof(Entry));
+ typedef std::set<lru_data*, lru_data::Compare> lru_set_t;
+ lru_set_t lru;
+ for (S32 i=0; i<num_entries; i++)
+ {
+ if (entries[i].mSize >= 0) // -1 indicates erased entry, skip
+ {
+ const LLUUID& id = entries[i].mID;
+ lru.insert(new lru_data(entries[i].mTime, i, id));
+ mHeaderIDMap[id] = i;
+ }
+ }
+ mLRU.clear();
+ S32 lru_entries = sCacheMaxEntries / 10;
+ for (lru_set_t::iterator iter = lru.begin(); iter != lru.end(); ++iter)
+ {
+ lru_data* data = *iter;
+ mLRU[data->index] = data->uuid;
+ if (--lru_entries <= 0)
+ break;
+ }
+ for_each(lru.begin(), lru.end(), DeletePointer());
+ delete[] entries;
+ }
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+void LLTextureCache::purgeAllTextures(bool purge_directories)
+{
+ if (!mReadOnly)
+ {
+ const char* subdirs = "0123456789abcdef";
+ std::string delem = gDirUtilp->getDirDelimiter();
+ std::string mask = delem + "*";
+ for (S32 i=0; i<16; i++)
+ {
+ std::string dirname = mTexturesDirName + delem + subdirs[i];
+ gDirUtilp->deleteFilesInDir(dirname.c_str(),mask);
+ if (purge_directories)
+ {
+ LLFile::rmdir(dirname.c_str());
+ }
+ }
+ ll_apr_file_remove(mTexturesDirEntriesFileName, NULL);
+ if (purge_directories)
+ {
+ LLFile::rmdir(mTexturesDirName.c_str());
+ }
+ }
+ mTexturesSizeMap.clear();
+}
+
+void LLTextureCache::purgeTextures(bool validate)
+{
+ if (mReadOnly)
+ {
+ return;
+ }
+
+ LLMutexLock lock(&mHeaderMutex);
+
+ S32 filesize = ll_apr_file_size(mTexturesDirEntriesFileName, NULL);
+ S32 num_entries = filesize / sizeof(Entry);
+ if (num_entries * (S32)sizeof(Entry) != filesize)
+ {
+ llwarns << "Bad cache file: " << mTexturesDirEntriesFileName << " Purging." << llendl;
+ purgeAllTextures(false);
+ return;
+ }
+ if (num_entries == 0)
+ {
+ return; // nothing to do
+ }
+
+ Entry* entries = new Entry[num_entries];
+ S32 bytes_read = ll_apr_file_read_ex(mTexturesDirEntriesFileName, NULL,
+ (U8*)entries, 0, num_entries*sizeof(Entry));
+ if (bytes_read != filesize)
+ {
+ llwarns << "Bad cache file (2): " << mTexturesDirEntriesFileName << " Purging." << llendl;
+ purgeAllTextures(false);
+ return;
+ }
+
+ llinfos << "TEXTURE CACHE: Reading Entries..." << llendl;
+
+ std::map<LLUUID, S32> entry_idx_map;
+ S64 total_size = 0;
+ for (S32 idx=0; idx<num_entries; idx++)
+ {
+ const LLUUID& id = entries[idx].mID;
+// llinfos << "Entry: " << id << " Size: " << entries[i].mSize << " Time: " << entries[i].mTime << llendl;
+ std::map<LLUUID, S32>::iterator iter = entry_idx_map.find(id);
+ if (iter != entry_idx_map.end())
+ {
+ // Newer entry replacing older entry
+ S32 pidx = iter->second;
+ total_size -= entries[pidx].mSize;
+ entries[pidx].mSize = 0; // flag: skip older entry
+ }
+ entry_idx_map[id] = idx;
+ total_size += entries[idx].mSize;
+ }
+
+ U32 validate_idx = 0;
+ if (validate)
+ {
+ validate_idx = gSavedSettings.getU32("CacheValidateCounter");
+ U32 next_idx = (++validate_idx) % 256;
+ gSavedSettings.setU32("CacheValidateCounter", next_idx);
+ llinfos << "TEXTURE CACHE: Validating: " << validate_idx << llendl;
+ }
+
+ S64 min_cache_size = (sCacheMaxTexturesSize * 9) / 10;
+ S32 purge_count = 0;
+ S32 next_idx = 0;
+ for (S32 idx=0; idx<num_entries; idx++)
+ {
+ if (entries[idx].mSize == 0)
+ {
+ continue;
+ }
+ bool purge_entry = false;
+ std::string filename = getTextureFileName(entries[idx].mID);
+ if (total_size >= min_cache_size)
+ {
+ purge_entry = true;
+ }
+ else if (validate)
+ {
+ // make sure file exists and is the correct size
+ S32 uuididx = entries[idx].mID.mData[0];
+ if (uuididx == validate_idx)
+ {
+// llinfos << "Validating: " << filename << "Size: " << entries[idx].mSize << llendl;
+ S32 bodysize = ll_apr_file_size(filename, NULL);
+ if (bodysize != entries[idx].mSize)
+ {
+ llwarns << "TEXTURE CACHE BODY HAS BAD SIZE: " << bodysize << " != " << entries[idx].mSize
+ << filename << llendl;
+ purge_entry = true;
+ }
+ }
+ }
+ if (purge_entry)
+ {
+ purge_count++;
+// llinfos << "PURGING: " << filename << llendl;
+ ll_apr_file_remove(filename, NULL);
+ total_size -= entries[idx].mSize;
+ entries[idx].mSize = 0;
+ }
+ else
+ {
+ if (next_idx != idx)
+ {
+ entries[next_idx] = entries[idx];
+ }
+ ++next_idx;
+ }
+ }
+ num_entries = next_idx;
+
+ llinfos << "TEXTURE CACHE: Writing Entries: " << num_entries << llendl;
+
+ ll_apr_file_remove(mTexturesDirEntriesFileName, NULL);
+ ll_apr_file_write_ex(mTexturesDirEntriesFileName, NULL,
+ (U8*)&entries[0], 0, num_entries*sizeof(Entry));
+
+ mTexturesSizeTotal = 0;
+ mTexturesSizeMap.clear();
+ for (S32 idx=0; idx<num_entries; idx++)
+ {
+ mTexturesSizeMap[entries[idx].mID] = entries[idx].mSize;
+ mTexturesSizeTotal += entries[idx].mSize;
+ }
+ llassert(mTexturesSizeTotal == total_size);
+
+ delete[] entries;
+
+ llinfos << "TEXTURE CACHE:"
+ << " PURGED: " << purge_count
+ << " ENTRIES: " << num_entries
+ << " CACHE SIZE: " << total_size / 1024*1024 << " MB"
+ << llendl;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+// call lockWorkers() first!
+LLTextureCacheWorker* LLTextureCache::getReader(handle_t handle)
+{
+ LLTextureCacheWorker* res = NULL;
+ handle_map_t::iterator iter = mReaders.find(handle);
+ if (iter != mReaders.end())
+ {
+ res = iter->second;
+ }
+ return res;
+}
+
+LLTextureCacheWorker* LLTextureCache::getWriter(handle_t handle)
+{
+ LLTextureCacheWorker* res = NULL;
+ handle_map_t::iterator iter = mWriters.find(handle);
+ if (iter != mWriters.end())
+ {
+ res = iter->second;
+ }
+ return res;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+// Called from work thread
+S32 LLTextureCache::getHeaderCacheEntry(const LLUUID& id, bool touch, S32* imagesize)
+{
+ bool retry = false;
+ S32 idx = -1;
+
+ {
+ LLMutexLock lock(&mHeaderMutex);
+ id_map_t::iterator iter = mHeaderIDMap.find(id);
+ if (iter != mHeaderIDMap.end())
+ {
+ idx = iter->second;
+ }
+ else if (touch && !mReadOnly)
+ {
+ if (mHeaderEntriesInfo.mEntries < sCacheMaxEntries)
+ {
+ // Add an entry
+ idx = mHeaderEntriesInfo.mEntries++;
+ mHeaderIDMap[id] = idx;
+ // Update Info
+ ll_apr_file_write_ex(mHeaderEntriesFileName, getFileAPRPool(),
+ (U8*)&mHeaderEntriesInfo, 0, sizeof(EntriesInfo));
+ }
+ else if (!mLRU.empty())
+ {
+ idx = mLRU.begin()->first; // will be erased below
+ const LLUUID& oldid = mLRU.begin()->second;
+ mHeaderIDMap.erase(oldid);
+ mTexturesSizeMap.erase(oldid);
+ mHeaderIDMap[id] = idx;
+ }
+ else
+ {
+ idx = -1;
+ retry = true;
+ }
+ }
+ if (idx >= 0)
+ {
+ if (touch && !mReadOnly)
+ {
+ // Update the lru entry
+ mLRU.erase(idx);
+ llassert_always(imagesize && *imagesize > 0);
+ Entry* entry = new Entry(id, *imagesize, time(NULL));
+ S32 offset = sizeof(EntriesInfo) + idx * sizeof(Entry);
+ ll_apr_file_write_ex(mHeaderEntriesFileName, getFileAPRPool(),
+ (U8*)entry, offset, sizeof(Entry));
+ delete entry;
+ }
+ else if (imagesize)
+ {
+ // Get the image size
+ Entry entry;
+ S32 offset = sizeof(EntriesInfo) + idx * sizeof(Entry);
+ ll_apr_file_read_ex(mHeaderEntriesFileName, getFileAPRPool(),
+ (U8*)&entry, offset, sizeof(Entry));
+ *imagesize = entry.mSize;
+ }
+ }
+ }
+ if (retry)
+ {
+ readHeaderCache(getFileAPRPool()); // updates the lru
+ llassert_always(!mLRU.empty() || mHeaderEntriesInfo.mEntries < sCacheMaxEntries);
+ idx = getHeaderCacheEntry(id, touch, imagesize); // assert above ensures no inf. recursion
+ }
+ return idx;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+// Calls from texture pipeline thread (i.e. LLTextureFetch)
+
+LLTextureCache::handle_t LLTextureCache::readFromCache(const LLUUID& id, U32 priority,
+ S32 offset, S32 size, ReadResponder* responder)
+{
+ // Note: checking to see if an entry exists can cause a stall,
+ // so let the thread handle it
+ LLMutexLock lock(&mWorkersMutex);
+ LLTextureCacheWorker* worker = new LLTextureCacheWorker(this, priority, id,
+ NULL, size, offset, 0,
+ responder);
+ handle_t handle = worker->read();
+ mReaders[handle] = worker;
+ return handle;
+}
+
+bool LLTextureCache::readComplete(handle_t handle, bool abort)
+{
+ lockWorkers();
+ handle_map_t::iterator iter = mReaders.find(handle);
+ llassert_always(iter != mReaders.end());
+ LLTextureCacheWorker* worker = iter->second;
+ bool res = worker->complete();
+ if (res || abort)
+ {
+ mReaders.erase(handle);
+ unlockWorkers();
+ worker->scheduleDelete();
+ return true;
+ }
+ else
+ {
+ unlockWorkers();
+ return false;
+ }
+}
+
+LLTextureCache::handle_t LLTextureCache::writeToCache(const LLUUID& id, U32 priority,
+ U8* data, S32 datasize, S32 imagesize,
+ WriteResponder* responder)
+{
+ if (mReadOnly)
+ {
+ return LLWorkerThread::nullHandle();
+ }
+ if (mDoPurge)
+ {
+ // NOTE: This may cause an occasional hiccup,
+ // but it really needs to be done on the control thread
+ // (i.e. here)
+ purgeTextures(false);
+ mDoPurge = FALSE;
+ }
+ if (datasize >= TEXTURE_CACHE_ENTRY_SIZE)
+ {
+ LLMutexLock lock(&mWorkersMutex);
+ llassert_always(imagesize > 0);
+ LLTextureCacheWorker* worker = new LLTextureCacheWorker(this, priority, id,
+ data, datasize, 0,
+ imagesize, responder);
+ handle_t handle = worker->write();
+ mWriters[handle] = worker;
+ return handle;
+ }
+ return LLWorkerThread::nullHandle();
+}
+
+bool LLTextureCache::writeComplete(handle_t handle, bool abort)
+{
+ lockWorkers();
+ handle_map_t::iterator iter = mWriters.find(handle);
+ llassert_always(iter != mWriters.end());
+ LLTextureCacheWorker* worker = iter->second;
+ if (worker->complete() || abort)
+ {
+ mWriters.erase(handle);
+ unlockWorkers();
+ worker->scheduleDelete();
+ return true;
+ }
+ else
+ {
+ unlockWorkers();
+ return false;
+ }
+}
+
+void LLTextureCache::prioritizeWrite(handle_t handle)
+{
+ // Don't prioritize yet, we might be working on this now
+ // which could create a deadlock
+ mPrioritizeWriteList.push_back(handle);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+// Called from MAIN thread (endWork())
+
+bool LLTextureCache::removeHeaderCacheEntry(const LLUUID& id)
+{
+ if (mReadOnly)
+ {
+ return false;
+ }
+ LLMutexLock lock(&mHeaderMutex);
+ id_map_t::iterator iter = mHeaderIDMap.find(id);
+ if (iter != mHeaderIDMap.end())
+ {
+ S32 idx = iter->second;
+ if (idx >= 0)
+ {
+ Entry* entry = new Entry(id, -1, time(NULL));
+ S32 offset = sizeof(EntriesInfo) + idx * sizeof(Entry);
+ ll_apr_file_write_ex(mHeaderEntriesFileName, NULL,
+ (U8*)entry, offset, sizeof(Entry));
+ delete entry;
+ mLRU[idx] = id;
+ mHeaderIDMap.erase(id);
+ mTexturesSizeMap.erase(id);
+ return true;
+ }
+ }
+ return false;
+}
+
+void LLTextureCache::removeFromCache(const LLUUID& id)
+{
+ llwarns << "Removing texture from cache: " << id << llendl;
+ if (!mReadOnly)
+ {
+ removeHeaderCacheEntry(id);
+ ll_apr_file_remove(getTextureFileName(id), NULL);
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+LLTextureCache::ReadResponder::ReadResponder()
+ : mImageSize(0),
+ mImageLocal(FALSE)
+{
+}
+
+void LLTextureCache::ReadResponder::setData(U8* data, S32 datasize, S32 imagesize, S32 imageformat, BOOL imagelocal)
+{
+ if (mFormattedImage.notNull())
+ {
+ llassert_always(mFormattedImage->getCodec() == imageformat);
+ mFormattedImage->appendData(data, datasize);
+ }
+ else
+ {
+ mFormattedImage = LLImageFormatted::createFromType(imageformat);
+ mFormattedImage->setData(data,datasize);
+ }
+ mImageSize = imagesize;
+ mImageLocal = imagelocal;
+}
+
+//////////////////////////////////////////////////////////////////////////////
diff --git a/indra/newview/lltexturecache.h b/indra/newview/lltexturecache.h
index 3b16b26b4a..f9eb8cb177 100644
--- a/indra/newview/lltexturecache.h
+++ b/indra/newview/lltexturecache.h
@@ -1,149 +1,149 @@
-/**
- * @file lltexturecache.h
- * @brief Object for managing texture cachees.
- *
- * Copyright (c) 2000-$CurrentYear$, Linden Research, Inc.
- * $License$
- */
-
-#ifndef LL_LLTEXTURECACHE_
-#define LL_LLTEXTURECACHE_H
-
-#include "lldir.h"
-#include "llstl.h"
-#include "llstring.h"
-#include "lluuid.h"
-
-#include "llworkerthread.h"
-
-class LLTextureCacheWorker;
-
-class LLTextureCache : public LLWorkerThread
-{
- friend class LLTextureCacheWorker;
-
-public:
-
- class Responder : public LLResponder
- {
- public:
- virtual void setData(U8* data, S32 datasize, S32 imagesize, S32 imageformat, BOOL imagelocal) = 0;
- };
-
- class ReadResponder : public Responder
- {
- public:
- ReadResponder();
- void setData(U8* data, S32 datasize, S32 imagesize, S32 imageformat, BOOL imagelocal);
- void setImage(LLImageFormatted* image) { mFormattedImage = image; }
- protected:
- LLPointer<LLImageFormatted> mFormattedImage;
- S32 mImageSize;
- BOOL mImageLocal;
- };
-
- class WriteResponder : public Responder
- {
- void setData(U8* data, S32 datasize, S32 imagesize, S32 imageformat, BOOL imagelocal)
- {
- // not used
- }
- };
-
- LLTextureCache(bool threaded);
- ~LLTextureCache();
-
- /*virtual*/ S32 update(U32 max_time_ms);
-
- void purgeCache(ELLPath location);
- S64 initCache(ELLPath location, S64 maxsize, BOOL read_only);
-
- handle_t readFromCache(const LLUUID& id, U32 priority, S32 offset, S32 size,
- ReadResponder* responder);
- bool readComplete(handle_t handle, bool abort);
- handle_t writeToCache(const LLUUID& id, U32 priority, U8* data, S32 datasize, S32 imagesize,
- WriteResponder* responder);
- bool writeComplete(handle_t handle, bool abort = false);
- void prioritizeWrite(handle_t handle);
-
- void removeFromCache(const LLUUID& id);
-
- // For LLTextureCacheWorker::Responder
- LLTextureCacheWorker* getReader(handle_t handle);
- LLTextureCacheWorker* getWriter(handle_t handle);
- void lockWorkers() { mWorkersMutex.lock(); }
- void unlockWorkers() { mWorkersMutex.unlock(); }
-
- // debug
- S32 getNumReads() { return mReaders.size(); }
- S32 getNumWrites() { return mWriters.size(); }
-
-protected:
- // Accessed by LLTextureCacheWorker
- apr_pool_t* getFileAPRPool() { return mFileAPRPool; }
- bool appendToTextureEntryList(const LLUUID& id, S32 size);
- std::string getLocalFileName(const LLUUID& id);
- std::string getTextureFileName(const LLUUID& id);
-
-private:
- void setDirNames(ELLPath location);
- void readHeaderCache(apr_pool_t* poolp = NULL);
- void purgeAllTextures(bool purge_directories);
- void purgeTextures(bool validate);
- S32 getHeaderCacheEntry(const LLUUID& id, bool touch, S32* imagesize = NULL);
- bool removeHeaderCacheEntry(const LLUUID& id);
- void lockHeaders() { mHeaderMutex.lock(); }
- void unlockHeaders() { mHeaderMutex.unlock(); }
-
-private:
- // Internal
- LLMutex mWorkersMutex;
- LLMutex mHeaderMutex;
- apr_pool_t* mFileAPRPool;
-
- typedef std::map<handle_t, LLTextureCacheWorker*> handle_map_t;
- handle_map_t mReaders;
- handle_map_t mWriters;
- std::vector<handle_t> mPrioritizeWriteList;
-
- BOOL mReadOnly;
-
- // Entries
- struct EntriesInfo
- {
- F32 mVersion;
- U32 mEntries;
- };
- struct Entry
- {
- Entry() {}
- Entry(const LLUUID& id, S32 size, U32 time) : mID(id), mSize(size), mTime(time) {}
- LLUUID mID; // 128 bits
- S32 mSize; // total size of image if known (NOT size cached)
- U32 mTime; // seconds since 1/1/1970
- };
-
- // HEADERS (Include first mip)
- std::string mHeaderEntriesFileName;
- std::string mHeaderDataFileName;
- EntriesInfo mHeaderEntriesInfo;
- typedef std::map<S32,LLUUID> index_map_t;
- index_map_t mLRU; // index, id; stored as a map for fast removal
- typedef std::map<LLUUID,S32> id_map_t;
- id_map_t mHeaderIDMap;
-
- // BODIES (TEXTURES minus headers)
- std::string mTexturesDirName;
- std::string mTexturesDirEntriesFileName;
- typedef std::map<LLUUID,S32> size_map_t;
- size_map_t mTexturesSizeMap;
- S64 mTexturesSizeTotal;
- LLAtomic32<BOOL> mDoPurge;
-
- // Statics
- static F32 sHeaderCacheVersion;
- static U32 sCacheMaxEntries;
- static S64 sCacheMaxTexturesSize;
-};
-
-#endif // LL_LLTEXTURECACHE_H
+/**
+ * @file lltexturecache.h
+ * @brief Object for managing texture cachees.
+ *
+ * Copyright (c) 2000-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+#ifndef LL_LLTEXTURECACHE_
+#define LL_LLTEXTURECACHE_H
+
+#include "lldir.h"
+#include "llstl.h"
+#include "llstring.h"
+#include "lluuid.h"
+
+#include "llworkerthread.h"
+
+class LLTextureCacheWorker;
+
+class LLTextureCache : public LLWorkerThread
+{
+ friend class LLTextureCacheWorker;
+
+public:
+
+ class Responder : public LLResponder
+ {
+ public:
+ virtual void setData(U8* data, S32 datasize, S32 imagesize, S32 imageformat, BOOL imagelocal) = 0;
+ };
+
+ class ReadResponder : public Responder
+ {
+ public:
+ ReadResponder();
+ void setData(U8* data, S32 datasize, S32 imagesize, S32 imageformat, BOOL imagelocal);
+ void setImage(LLImageFormatted* image) { mFormattedImage = image; }
+ protected:
+ LLPointer<LLImageFormatted> mFormattedImage;
+ S32 mImageSize;
+ BOOL mImageLocal;
+ };
+
+ class WriteResponder : public Responder
+ {
+ void setData(U8* data, S32 datasize, S32 imagesize, S32 imageformat, BOOL imagelocal)
+ {
+ // not used
+ }
+ };
+
+ LLTextureCache(bool threaded);
+ ~LLTextureCache();
+
+ /*virtual*/ S32 update(U32 max_time_ms);
+
+ void purgeCache(ELLPath location);
+ S64 initCache(ELLPath location, S64 maxsize, BOOL read_only);
+
+ handle_t readFromCache(const LLUUID& id, U32 priority, S32 offset, S32 size,
+ ReadResponder* responder);
+ bool readComplete(handle_t handle, bool abort);
+ handle_t writeToCache(const LLUUID& id, U32 priority, U8* data, S32 datasize, S32 imagesize,
+ WriteResponder* responder);
+ bool writeComplete(handle_t handle, bool abort = false);
+ void prioritizeWrite(handle_t handle);
+
+ void removeFromCache(const LLUUID& id);
+
+ // For LLTextureCacheWorker::Responder
+ LLTextureCacheWorker* getReader(handle_t handle);
+ LLTextureCacheWorker* getWriter(handle_t handle);
+ void lockWorkers() { mWorkersMutex.lock(); }
+ void unlockWorkers() { mWorkersMutex.unlock(); }
+
+ // debug
+ S32 getNumReads() { return mReaders.size(); }
+ S32 getNumWrites() { return mWriters.size(); }
+
+protected:
+ // Accessed by LLTextureCacheWorker
+ apr_pool_t* getFileAPRPool() { return mFileAPRPool; }
+ bool appendToTextureEntryList(const LLUUID& id, S32 size);
+ std::string getLocalFileName(const LLUUID& id);
+ std::string getTextureFileName(const LLUUID& id);
+
+private:
+ void setDirNames(ELLPath location);
+ void readHeaderCache(apr_pool_t* poolp = NULL);
+ void purgeAllTextures(bool purge_directories);
+ void purgeTextures(bool validate);
+ S32 getHeaderCacheEntry(const LLUUID& id, bool touch, S32* imagesize = NULL);
+ bool removeHeaderCacheEntry(const LLUUID& id);
+ void lockHeaders() { mHeaderMutex.lock(); }
+ void unlockHeaders() { mHeaderMutex.unlock(); }
+
+private:
+ // Internal
+ LLMutex mWorkersMutex;
+ LLMutex mHeaderMutex;
+ apr_pool_t* mFileAPRPool;
+
+ typedef std::map<handle_t, LLTextureCacheWorker*> handle_map_t;
+ handle_map_t mReaders;
+ handle_map_t mWriters;
+ std::vector<handle_t> mPrioritizeWriteList;
+
+ BOOL mReadOnly;
+
+ // Entries
+ struct EntriesInfo
+ {
+ F32 mVersion;
+ U32 mEntries;
+ };
+ struct Entry
+ {
+ Entry() {}
+ Entry(const LLUUID& id, S32 size, U32 time) : mID(id), mSize(size), mTime(time) {}
+ LLUUID mID; // 128 bits
+ S32 mSize; // total size of image if known (NOT size cached)
+ U32 mTime; // seconds since 1/1/1970
+ };
+
+ // HEADERS (Include first mip)
+ std::string mHeaderEntriesFileName;
+ std::string mHeaderDataFileName;
+ EntriesInfo mHeaderEntriesInfo;
+ typedef std::map<S32,LLUUID> index_map_t;
+ index_map_t mLRU; // index, id; stored as a map for fast removal
+ typedef std::map<LLUUID,S32> id_map_t;
+ id_map_t mHeaderIDMap;
+
+ // BODIES (TEXTURES minus headers)
+ std::string mTexturesDirName;
+ std::string mTexturesDirEntriesFileName;
+ typedef std::map<LLUUID,S32> size_map_t;
+ size_map_t mTexturesSizeMap;
+ S64 mTexturesSizeTotal;
+ LLAtomic32<BOOL> mDoPurge;
+
+ // Statics
+ static F32 sHeaderCacheVersion;
+ static U32 sCacheMaxEntries;
+ static S64 sCacheMaxTexturesSize;
+};
+
+#endif // LL_LLTEXTURECACHE_H
diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp
index db747c60fc..4c90c3624b 100644
--- a/indra/newview/lltexturefetch.cpp
+++ b/indra/newview/lltexturefetch.cpp
@@ -1205,9 +1205,9 @@ bool LLTextureFetchWorker::writeToCacheComplete()
LLTextureFetch::LLTextureFetch(LLTextureCache* cache, bool threaded)
: LLWorkerThread("TextureFetch", threaded),
mDebugCount(0),
- mDebugPause(0),
- mTextureCache(cache),
- mQueueMutex(getAPRPool())
+ mDebugPause(FALSE),
+ mQueueMutex(getAPRPool()),
+ mTextureCache(cache)
{
}
diff --git a/indra/newview/lltexturefetch.h b/indra/newview/lltexturefetch.h
index b3510d9e82..7cf7cb45f2 100644
--- a/indra/newview/lltexturefetch.h
+++ b/indra/newview/lltexturefetch.h
@@ -82,4 +82,4 @@ private:
LLFrameTimer mNetworkTimer;
};
-#endif LL_LLTEXTUREFETCH_H
+#endif // LL_LLTEXTUREFETCH_H
diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp
index 837eaa90e9..f6fa23c6f6 100644
--- a/indra/newview/llviewerdisplay.cpp
+++ b/indra/newview/llviewerdisplay.cpp
@@ -582,6 +582,11 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield)
gPipeline.stateSort(hud_cam);
}
+ if (LLVertexBuffer::sEnableVBOs)
+ {
+ LLImageGL::sBoundTextureMemory += LLVertexBuffer::sAllocatedBytes;
+ }
+
gPipeline.renderGeom(hud_cam);
//restore type mask
@@ -716,9 +721,10 @@ void render_ui_and_swap()
}
{
-// LLFastTimer ftm(LLFastTimer::FTM_TEMP6);
- LLVertexBuffer::clientCopy();
+ LLFastTimer ftm(LLFastTimer::FTM_CLIENT_COPY);
+ LLVertexBuffer::clientCopy(0.016);
}
+
}
}
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index 275db0f906..64560efd67 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -1134,6 +1134,9 @@ void init_debug_rendering_menu(LLMenuGL* menu)
sub_menu->append(new LLMenuItemCheckGL("Texture Area (sqrt(A))",&LLPipeline::toggleRenderDebug, NULL,
&LLPipeline::toggleRenderDebugControl,
(void*)LLPipeline::RENDER_DEBUG_TEXTURE_AREA));
+ sub_menu->append(new LLMenuItemCheckGL("Face Area (sqrt(A))",&LLPipeline::toggleRenderDebug, NULL,
+ &LLPipeline::toggleRenderDebugControl,
+ (void*)LLPipeline::RENDER_DEBUG_FACE_AREA));
sub_menu->append(new LLMenuItemCheckGL("Pick Render", &LLPipeline::toggleRenderDebug, NULL,
&LLPipeline::toggleRenderDebugControl,
(void*)LLPipeline::RENDER_DEBUG_PICKING));
diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp
index 8ed5406e85..6d4170e437 100644
--- a/indra/newview/llviewermessage.cpp
+++ b/indra/newview/llviewermessage.cpp
@@ -1357,7 +1357,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
// Make sure the binary bucket is big enough to hold the header
// and a null terminated item name.
- if ( (binary_bucket_size < (sizeof(notice_bucket_header_t) + sizeof(U8)))
+ if ( (binary_bucket_size < (S32)((sizeof(notice_bucket_header_t) + sizeof(U8))))
|| (binary_bucket[binary_bucket_size - 1] != '\0') )
{
llwarns << "Malformed group notice binary bucket" << llendl;
diff --git a/indra/newview/llviewernetwork.cpp b/indra/newview/llviewernetwork.cpp
index b02985ddfa..189b314e55 100644
--- a/indra/newview/llviewernetwork.cpp
+++ b/indra/newview/llviewernetwork.cpp
@@ -71,4 +71,4 @@ F32 gPacketDropPercentage = 0.f;
F32 gInBandwidth = 0.f;
F32 gOutBandwidth = 0.f;
-unsigned char gMACAddress[MAC_ADDRESS_BYTES]; /* Flawfinder: ignore */ \ No newline at end of file
+unsigned char gMACAddress[MAC_ADDRESS_BYTES]; /* Flawfinder: ignore */
diff --git a/indra/newview/llviewerparcelmgr.cpp b/indra/newview/llviewerparcelmgr.cpp
index cd915317ba..ee29876274 100644
--- a/indra/newview/llviewerparcelmgr.cpp
+++ b/indra/newview/llviewerparcelmgr.cpp
@@ -2523,9 +2523,9 @@ LLParcelSelection::LLParcelSelection() :
mParcel(NULL),
mSelectedMultipleOwners(FALSE),
mWholeParcelSelected(FALSE),
- mSelectedPublicCount(0),
mSelectedSelfCount(0),
- mSelectedOtherCount(0)
+ mSelectedOtherCount(0),
+ mSelectedPublicCount(0)
{
}
@@ -2533,9 +2533,9 @@ LLParcelSelection::LLParcelSelection(LLParcel* parcel) :
mParcel(parcel),
mSelectedMultipleOwners(FALSE),
mWholeParcelSelected(FALSE),
- mSelectedPublicCount(0),
mSelectedSelfCount(0),
- mSelectedOtherCount(0)
+ mSelectedOtherCount(0),
+ mSelectedPublicCount(0)
{
}
@@ -2570,4 +2570,4 @@ LLParcelSelection* get_null_parcel_selection()
{
static LLParcelSelectionHandle null_ptr = new LLParcelSelection();
return null_ptr;
-} \ No newline at end of file
+}
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index aebcfdb9ce..36c08321ed 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -1842,13 +1842,6 @@ void LLViewerWindow::reshape(S32 width, S32 height)
gViewerStats->setStat(LLViewerStats::ST_WINDOW_WIDTH, (F64)width);
gViewerStats->setStat(LLViewerStats::ST_WINDOW_HEIGHT, (F64)height);
-
- //reposition HUD attachments
- LLVOAvatar* avatarp = gAgent.getAvatarObject();
- if (avatarp)
- {
- avatarp->resetHUDAttachments();
- }
}
}
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 507a1468c7..afeffa0aec 100644
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -748,9 +748,9 @@ LLVOAvatar::LLVOAvatar(
mLastSkirtBakedID( IMG_DEFAULT_AVATAR ),
mIsDummy(FALSE),
mSpecialRenderMode(0),
+ mTurning(FALSE),
mPelvisToFoot(0.f),
mLastSkeletonSerialNum( 0 ),
- mTurning(FALSE),
mHeadOffset(),
mIsSitting(FALSE),
mTimeVisible(),
@@ -3005,8 +3005,12 @@ void LLVOAvatar::updateCharacter(LLAgent &agent)
{
F32 aspect = gCamera->getAspect();
LLVector3 scale(1.f, aspect, 1.f);
- mScreenp->setScale(scale);
- mScreenp->updateWorldMatrixChildren();
+ if (mScreenp->getScale() != scale)
+ {
+ mScreenp->setScale(scale);
+ mScreenp->updateWorldMatrixChildren();
+ resetHUDAttachments();
+ }
}
// clear debug text
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index 2d898a1a5d..d08c5311d7 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -244,7 +244,7 @@ BOOL LLVOVolume::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)
S32 result;
if (result = mTextureAnimp->animateTextures(off_s, off_t, scale_s, scale_t, rot))
{
- mTexAnimMode = result | mTextureAnimp->mMode;
+ mTexAnimMode = mTextureAnimp->mMode | result;
S32 start, end;
if (mTextureAnimp->mFace == -1)
@@ -309,6 +309,13 @@ BOOL LLVOVolume::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)
tex_mat.translate(trans);
}
}
+ else
+ {
+ if (mTextureAnimp->mRate == 0)
+ {
+ mTexAnimMode = 0;
+ }
+ }
}
// Dispatch to implementation
@@ -349,17 +356,18 @@ void LLVOVolume::updateTextures()
mTextureUpdateTimer.reset();
+ F32 old_area = mPixelArea;
mPixelArea = 0.f;
- const S32 num_faces = mDrawable->getNumFaces();
+ const S32 num_faces = mDrawable->getNumFaces();
F32 min_vsize=999999999.f, max_vsize=0.f;
for (S32 i = 0; i < num_faces; i++)
{
LLFace* face = mDrawable->getFace(i);
const LLTextureEntry *te = face->getTextureEntry();
LLViewerImage *imagep = face->getTexture();
-
- if (!imagep || !te)
+ if (!imagep || !te ||
+ face->mExtents[0] == face->mExtents[1])
{
continue;
}
@@ -392,11 +400,12 @@ void LLVOVolume::updateTextures()
if (pri < min_vsize) min_vsize = pri;
if (pri > max_vsize) max_vsize = pri;
}
- // U8 bump = te->getBumpmap();
- // if( te && bump)
- // {
- // gBumpImageList.addTextureStats( bump, imagep->getID(), vsize, 1, 1);
- // }
+ else if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_FACE_AREA))
+ {
+ F32 pri = mPixelArea;
+ if (pri < min_vsize) min_vsize = pri;
+ if (pri > max_vsize) max_vsize = pri;
+ }
}
if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_AREA))
@@ -407,15 +416,22 @@ void LLVOVolume::updateTextures()
{
setDebugText(llformat("%.0f:%.0f", fsqrtf(min_vsize),fsqrtf(max_vsize)));
}
+ else if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_FACE_AREA))
+ {
+ setDebugText(llformat("%.0f:%.0f", fsqrtf(min_vsize),fsqrtf(max_vsize)));
+ }
+
+ if (mPixelArea == 0)
+ { //flexi phasing issues make this happen
+ mPixelArea = old_area;
+ }
}
F32 LLVOVolume::getTextureVirtualSize(LLFace* face)
{
//get area of circle around face
LLVector3 center = face->getPositionAgent();
- LLVector3 size = //isFlexible() ?
- // getScale()*3.f :
- (face->mExtents[1] - face->mExtents[0]) * 0.5f;
+ LLVector3 size = (face->mExtents[1] - face->mExtents[0]) * 0.5f;
F32 face_area = LLPipeline::calcPixelArea(center, size, *gCamera);
@@ -585,9 +601,6 @@ BOOL LLVOVolume::calcLOD()
return FALSE;
}
- //update textures here as well
- updateTextures();
-
S32 cur_detail = 0;
F32 radius = mVolumep->mLODScaleBias.scaledVec(getScale()).magVec();
@@ -689,6 +702,17 @@ void LLVOVolume::updateFaceFlags()
}
}
+void LLVOVolume::setParent(LLViewerObject* parent)
+{
+ LLViewerObject::setParent(parent);
+ if (mDrawable)
+ {
+ gPipeline.markMoved(mDrawable);
+ mVolumeChanged = TRUE;
+ gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, TRUE);
+ }
+}
+
// NOTE: regenFaces() MUST be followed by genTriangles()!
void LLVOVolume::regenFaces()
{
@@ -748,6 +772,8 @@ BOOL LLVOVolume::genBBoxes(BOOL force_global)
{
mDrawable->setSpatialExtents(min,max);
mDrawable->setPositionGroup((min+max)*0.5f);
+ //bounding boxes changed, update texture priorities
+ updateTextures();
}
updateRadius();
@@ -1918,8 +1944,10 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep,
draw_vec[idx]->mVertexBuffer == facep->mVertexBuffer &&
draw_vec[idx]->mEnd == facep->getGeomIndex()-1 &&
draw_vec[idx]->mTexture == tex &&
- //draw_vec[idx]->mEnd - draw_vec[idx]->mStart + facep->getGeomCount() <= (U32) gGLManager.mGLMaxVertexRange &&
- //draw_vec[idx]->mCount + facep->getIndicesCount() <= (U32) gGLManager.mGLMaxIndexRange &&
+#if LL_DARWIN
+ draw_vec[idx]->mEnd - draw_vec[idx]->mStart + facep->getGeomCount() <= (U32) gGLManager.mGLMaxVertexRange &&
+ draw_vec[idx]->mCount + facep->getIndicesCount() <= (U32) gGLManager.mGLMaxIndexRange &&
+#endif
draw_vec[idx]->mFullbright == fullbright &&
draw_vec[idx]->mBump == bump &&
draw_vec[idx]->mTextureMatrix == tex_mat)
@@ -2220,7 +2248,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
registerFace(group, facep, LLRenderPass::PASS_BUMP);
}
- if (!force_simple && vobj->getIsLight())
+ if (vobj->getIsLight())
{
registerFace(group, facep, LLRenderPass::PASS_GLOW);
}
diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h
index 3eb8ad6c14..76b469e6aa 100644
--- a/indra/newview/llvovolume.h
+++ b/indra/newview/llvovolume.h
@@ -79,7 +79,7 @@ public:
/*virtual*/ BOOL isHUDAttachment() const;
void generateSilhouette(LLSelectNode* nodep, const LLVector3& view_point);
-
+ /*virtual*/ void setParent(LLViewerObject* parent);
F32 getIndividualRadius() { return mRadius; }
S32 getLOD() const { return mLOD; }
const LLVector3 getPivotPositionAgent() const;
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index 250b9bc7df..d7abae32c8 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -212,6 +212,8 @@ BOOL LLPipeline::sSkipUpdate = FALSE;
BOOL LLPipeline::sDynamicReflections = FALSE;
LLPipeline::LLPipeline() :
+ mCubeBuffer(NULL),
+ mCubeList(0),
mVertexShadersEnabled(FALSE),
mVertexShadersLoaded(0),
mLastRebuildPool(NULL),
@@ -225,9 +227,7 @@ LLPipeline::LLPipeline() :
mSimplePool(NULL),
mBumpPool(NULL),
mLightMask(0),
- mLightMovingMask(0),
- mCubeBuffer(NULL),
- mCubeList(0)
+ mLightMovingMask(0)
{
}
@@ -1710,7 +1710,6 @@ void LLPipeline::updateMove()
F32 LLPipeline::calcPixelArea(LLVector3 center, LLVector3 size, LLCamera &camera)
{
LLVector3 lookAt = center - camera.getOrigin();
- LLVector3 cross_vec = size * 2.f;
F32 dist = lookAt.magVec();
//ramp down distance for nearby objects
@@ -1722,7 +1721,7 @@ F32 LLPipeline::calcPixelArea(LLVector3 center, LLVector3 size, LLCamera &camera
}
//get area of circle around node
- F32 app_angle = atanf((cross_vec*0.5f).magVec()/dist);
+ F32 app_angle = atanf(size.magVec()/dist);
F32 radius = app_angle*LLDrawable::sCurPixelAngle;
return radius*radius * 3.14159f;
}
@@ -2196,10 +2195,12 @@ void LLPipeline::stateSort(LLSpatialGroup* group, LLCamera& camera)
}
}
+#if !LL_DARWIN
if (gFrameTimeSeconds - group->mLastUpdateTime > 4.f)
{
group->makeStatic();
}
+#endif
}
void LLPipeline::stateSort(LLSpatialBridge* bridge, LLCamera& camera)
diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h
index c744a29bec..0fadae0a61 100644
--- a/indra/newview/pipeline.h
+++ b/indra/newview/pipeline.h
@@ -325,7 +325,8 @@ public:
RENDER_DEBUG_POINTS = 0x02000,
RENDER_DEBUG_TEXTURE_PRIORITY = 0x04000,
RENDER_DEBUG_TEXTURE_AREA = 0x08000,
- RENDER_DEBUG_PARTICLES = 0x10000,
+ RENDER_DEBUG_FACE_AREA = 0x10000,
+ RENDER_DEBUG_PARTICLES = 0x20000,
};
LLPointer<LLViewerImage> mAlphaSizzleImagep;