diff --git a/indra/aistatemachine/aistatemachinethread.cpp b/indra/aistatemachine/aistatemachinethread.cpp index 030bd0a5a..f45d1e845 100644 --- a/indra/aistatemachine/aistatemachinethread.cpp +++ b/indra/aistatemachine/aistatemachinethread.cpp @@ -33,12 +33,12 @@ class AIStateMachineThreadBase::Thread : public LLThread { private: - LLPointer mImpl; + LLPointer mImpl; bool mNeedCleanup; public: - Thread(AIThreadImpl* impl) : + Thread(AIStateMachineThreadBase* impl) : #ifdef LL_DEBUG - LLThread(impl->getName()), + LLThread(impl->impl().getName()), #else LLThread("AIStateMachineThreadBase::Thread"), #endif @@ -46,7 +46,7 @@ class AIStateMachineThreadBase::Thread : public LLThread { protected: /*virtual*/ void run(void) { - mNeedCleanup = mImpl->thread_done(mImpl->run()); + mNeedCleanup = mImpl->impl().thread_done(mImpl->impl().run()); } /*virtual*/ void terminated(void) { @@ -65,7 +65,7 @@ class AIStateMachineThreadBase::Thread : public LLThread { } public: // TODO: Implement a thread pool. For now, just create a new one every time. - static Thread* allocate(AIThreadImpl* impl) { return new Thread(impl); } + static Thread* allocate(AIStateMachineThreadBase* impl) { return new Thread(impl); } static void completed(Thread* threadp) { delete threadp; } }; @@ -93,7 +93,7 @@ void AIStateMachineThreadBase::multiplex_impl(state_type run_state) switch(run_state) { case start_thread: - mThread = Thread::allocate(mImpl); + mThread = Thread::allocate(this); // Set next state. set_state(wait_stopped); idle(); // Wait till the thread returns. @@ -124,10 +124,10 @@ void AIStateMachineThreadBase::abort_impl(void) { if (mThread) { - // If this AIStateMachineThreadBase still exists then the first base class of - // AIStateMachineThread, LLPointer, also still exists - // and therefore mImpl is valid. - bool need_cleanup = mImpl->state_machine_done(mThread); // Signal the fact that we aborted. + // If this AIStateMachineThreadBase still exists then the AIStateMachineThread + // that is derived from it still exists and therefore its member THREAD_IMPL also still exists + // and therefore impl() is valid. + bool need_cleanup = impl().state_machine_done(mThread); // Signal the fact that we aborted. if (need_cleanup) { // This is an unlikely race condition. We have been aborted by our parent, diff --git a/indra/aistatemachine/aistatemachinethread.h b/indra/aistatemachine/aistatemachinethread.h index 85b2ff108..780060bb6 100644 --- a/indra/aistatemachine/aistatemachinethread.h +++ b/indra/aistatemachine/aistatemachinethread.h @@ -73,11 +73,11 @@ enum hello_world_state_type { // The statemachine class (this is almost a template). class HelloWorld : public AIStateMachine { private: - AIStateMachineThread mHelloWorld; + LLPointer > mHelloWorld; bool mErr; public: - HelloWorld() : mErr(false) { } + HelloWorld() : mHelloWorld(new AIStateMachineThread), mErr(false) { } // Print to stderr or stdout? void init(bool err) { mErr = err; } @@ -108,7 +108,7 @@ class HelloWorld : public AIStateMachine { void HelloWorld::initialize_impl(void) { - mHelloWorld->init(mErr); // Initialize the thread object. + mHelloWorld->thread_impl().init(mErr); // Initialize the thread object. set_state(HelloWorld_start); } @@ -118,14 +118,14 @@ void HelloWorld::multiplex_impl(state_type run_state) { case HelloWorld_start: { - mHelloWorld.run(this, HelloWorld_done); // Run HelloWorldThread and set the state of 'this' to HelloWorld_done when finished. + mHelloWorld->run(this, HelloWorld_done); // Run HelloWorldThread and set the state of 'this' to HelloWorld_done when finished. idle(HelloWorld_start); // Always go idle after starting a thread! break; } case HelloWorld_done: { // We're done. Lets also abort when the thread reported no success. - if (mHelloWorld->successful()) // Read output/result of thread object. + if (mHelloWorld->thread_impl().successful()) // Read output/result of thread object. finish(); else abort(); @@ -139,9 +139,9 @@ void HelloWorld::multiplex_impl(state_type run_state) class AIStateMachineThreadBase; // Derive from this to implement the code that must run in another thread. -class AIThreadImpl : public LLThreadSafeRefCount { +class AIThreadImpl { private: - template friend struct AIStateMachineThread; + template friend class AIStateMachineThread; typedef AIAccess StateMachineThread_wat; AIThreadSafeSimpleDC mStateMachineThread; @@ -158,6 +158,9 @@ class AIThreadImpl : public LLThreadSafeRefCount { public: char const* getName(void) const { return mName; } #endif + + protected: + virtual ~AIThreadImpl() { } }; // The base class for statemachine threads. @@ -178,7 +181,7 @@ class AIStateMachineThreadBase : public AIStateMachine { static state_type const max_state = wait_stopped + 1; protected: - AIStateMachineThreadBase(AIThreadImpl* impl) : mImpl(impl) { ref(); /* Never call delete */ } + AIStateMachineThreadBase(void) { } private: // Handle initializing the object. @@ -193,9 +196,11 @@ class AIStateMachineThreadBase : public AIStateMachine { // Implemenation of state_str for run states. /*virtual*/ char const* state_str_impl(state_type run_state) const; + // Returns a reference to the implementation code that needs to be run in the thread. + virtual AIThreadImpl& impl(void) = 0; + private: Thread* mThread; // The thread that the code is run in. - AIThreadImpl* mImpl; // Pointer to the implementation code that needs to be run in the thread. bool mAbort; // (Inverse of) return value of AIThreadImpl::run(). Only valid in state wait_stopped. public: @@ -206,14 +211,22 @@ class AIStateMachineThreadBase : public AIStateMachine { // The state machine that runs T::run() in a thread. // THREAD_IMPL Must be derived from AIThreadImpl. template -struct AIStateMachineThread : public LLPointer, public AIStateMachineThreadBase { - // Constructor. - AIStateMachineThread(void) : - LLPointer(new THREAD_IMPL), - AIStateMachineThreadBase(LLPointer::get()) - { - *AIThreadImpl::StateMachineThread_wat(static_cast(LLPointer::get())->mStateMachineThread) = this; - } +class AIStateMachineThread : public AIStateMachineThreadBase { + private: + THREAD_IMPL mThreadImpl; + + public: + // Constructor. + AIStateMachineThread(void) + { + *AIThreadImpl::StateMachineThread_wat(mThreadImpl.mStateMachineThread) = this; + } + + // Accessor. + THREAD_IMPL& thread_impl(void) { return mThreadImpl; } + + protected: + /*virtual*/ AIThreadImpl& impl(void) { return mThreadImpl; } }; #endif diff --git a/indra/llcommon/llfile.h b/indra/llcommon/llfile.h index 6d2bb8f13..12eb04932 100644 --- a/indra/llcommon/llfile.h +++ b/indra/llcommon/llfile.h @@ -95,7 +95,19 @@ public: namespace { #if LL_WINDOWS -typedef std::filebuf _Myfb; +//typedef std::filebuf _Myfb; +//Singu note: Wrap around std::filebuf to override the open procedure. +// The client encodes filepaths in UTF-8, however Windows uses UTF-16 encoding natively. +// Need to convert paths to UTF-16 before calling std::filebuf::open. +struct _Myfb : public std::filebuf +{ + _Myfb() : std::filebuf() {} + _Myfb(_Filet* file) : std::filebuf(file) {} + _Myt *open(const char *filename, std::ios_base::openmode mode, int prot = (int)std::ios_base::_Openprot) + { + return std::filebuf::open(utf8str_to_utf16str(filename).c_str(),mode,prot); + } +}; #else typedef __gnu_cxx::stdio_filebuf< char > _Myfb; typedef std::__c_file _Filet; diff --git a/indra/llcommon/llthread.cpp b/indra/llcommon/llthread.cpp index 4ddc58d18..8a2b6d0b5 100644 --- a/indra/llcommon/llthread.cpp +++ b/indra/llcommon/llthread.cpp @@ -486,14 +486,10 @@ LLThreadSafeRefCount::LLThreadSafeRefCount() : LLThreadSafeRefCount::~LLThreadSafeRefCount() { - llassert(mRef == 0); - /* TEMPORARILY disable erroring out on deleting this object with - nonzero reference count until the problem in AIStateMachine is fixed if (mRef != 0) { llerrs << "deleting non-zero reference" << llendl; } - */ } //============================================================================ diff --git a/indra/newview/llagentwearablesfetch.cpp b/indra/newview/llagentwearablesfetch.cpp index a1c60e921..3b48606a5 100644 --- a/indra/newview/llagentwearablesfetch.cpp +++ b/indra/newview/llagentwearablesfetch.cpp @@ -135,7 +135,7 @@ void LLInitialWearablesFetch::processContents() LLInventoryModel::cat_array_t cat_array; LLInventoryModel::item_array_t wearable_array; LLFindWearables is_wearable; - llassert_always(mComplete.size() != 0); + llassert(mComplete.size() != 0); gInventory.collectDescendentsIf(mComplete.front(), cat_array, wearable_array, LLInventoryModel::EXCLUDE_TRASH, is_wearable); diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp index 88f6c8e38..1c70e6fae 100644 --- a/indra/newview/llmeshrepository.cpp +++ b/indra/newview/llmeshrepository.cpp @@ -1329,9 +1329,10 @@ void LLMeshUploadThread::preStart() } AIMeshUpload::AIMeshUpload(LLMeshUploadThread::instance_list& data, LLVector3& scale, bool upload_textures, bool upload_skin, bool upload_joints, std::string const& upload_url, bool do_upload, - LLHandle const& fee_observer, LLHandle const& upload_observer) : mWholeModelUploadURL(upload_url) + LLHandle const& fee_observer, LLHandle const& upload_observer) : + mMeshUpload(new AIStateMachineThread), mWholeModelUploadURL(upload_url) { - mMeshUpload->init(data, scale, upload_textures, upload_skin, upload_joints, do_upload, fee_observer, upload_observer); + mMeshUpload->thread_impl().init(data, scale, upload_textures, upload_skin, upload_joints, do_upload, fee_observer, upload_observer); } char const* AIMeshUpload::state_str_impl(state_type run_state) const @@ -1347,7 +1348,7 @@ char const* AIMeshUpload::state_str_impl(state_type run_state) const void AIMeshUpload::initialize_impl() { - mMeshUpload->preStart(); + mMeshUpload->thread_impl().preStart(); set_state(AIMeshUpload_start); } @@ -1356,11 +1357,11 @@ void AIMeshUpload::multiplex_impl(state_type run_state) switch (run_state) { case AIMeshUpload_start: - mMeshUpload.run(this, AIMeshUpload_threadFinished); + mMeshUpload->run(this, AIMeshUpload_threadFinished); idle(); // Wait till the thread finished. break; case AIMeshUpload_threadFinished: - mMeshUpload->postRequest(mWholeModelUploadURL, this); + mMeshUpload->thread_impl().postRequest(mWholeModelUploadURL, this); idle(); // Wait till the responder finished. break; case AIMeshUpload_responderFinished: diff --git a/indra/newview/llmeshrepository.h b/indra/newview/llmeshrepository.h index d26316a85..ce79f9506 100644 --- a/indra/newview/llmeshrepository.h +++ b/indra/newview/llmeshrepository.h @@ -433,7 +433,7 @@ enum AIMeshUpload_state_type { class AIMeshUpload : public AIStateMachine { private: - AIStateMachineThread mMeshUpload; + LLPointer > mMeshUpload; std::string mWholeModelUploadURL; public: diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index d4d59df29..fdaf69036 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -622,6 +622,12 @@ void region_change(); void parse_simulator_features(); void custom_selected(void* user_data); +void reset_vertex_buffers(void *user_data) +{ + gPipeline.clearRebuildGroups(); + gPipeline.resetVertexBuffers(); +} + class LLMenuParcelObserver : public LLParcelObserver { public: @@ -1593,6 +1599,8 @@ void init_debug_rendering_menu(LLMenuGL* menu) item = new LLMenuItemCheckGL("Aggressive Alpha Masking", menu_toggle_control, NULL, menu_check_control, (void*)"SHUseRMSEAutoMask"); menu->addChild(item); + menu->addChild(new LLMenuItemCallGL("Rebuild Vertex Buffers", reset_vertex_buffers, NULL, NULL, 'V', MASK_CONTROL | MASK_SHIFT)); + item = new LLMenuItemCheckGL("Animate Textures", menu_toggle_control, NULL, menu_check_control, (void*)"AnimateTextures"); menu->addChild(item); diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index c151c691d..146d90d8f 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -234,7 +234,8 @@ const std::string SCRIPT_QUESTIONS[SCRIPT_PERMISSION_EOF] = "ChangePermissions", "TrackYourCamera", "ControlYourCamera", - "TeleportYourAgent" + "TeleportYourAgent", + "OverrideAnimations" }; const BOOL SCRIPT_QUESTION_IS_CAUTION[SCRIPT_PERMISSION_EOF] = @@ -250,7 +251,8 @@ const BOOL SCRIPT_QUESTION_IS_CAUTION[SCRIPT_PERMISSION_EOF] = FALSE, // ChangePermissions FALSE, // TrackYourCamera, FALSE, // ControlYourCamera - FALSE // TeleportYourAgent + FALSE, // TeleportYourAgent + FALSE // OverrideAnimations }; bool friendship_offer_callback(const LLSD& notification, const LLSD& response) diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp index 7a7b70f9b..d7a772f22 100644 --- a/indra/newview/llviewertexturelist.cpp +++ b/indra/newview/llviewertexturelist.cpp @@ -663,13 +663,15 @@ static LLFastTimer::DeclareTimer FTM_IMAGE_MEDIA("Media"); void LLViewerTextureList::updateImages(F32 max_time) { static BOOL cleared = FALSE; - static const LLCachedControl hide_tp_screen("AscentDisableTeleportScreens",false); + //Singu note: Don't clear vbos on local tp until some serious geom rebuild bugs are stomped out. + //Currently it causes prims to fail to rebuild when they should be popping back into visiblity. + //static const LLCachedControl hide_tp_screen("AscentDisableTeleportScreens",false); //Can't check gTeleportDisplay due to a process_teleport_local(), which sets it to true for local teleports... so: // Do this case if IS teleporting but NOT local teleporting, AND either the TP screen is set to appear OR we just entered the sim (TELEPORT_START_ARRIVAL) LLAgent::ETeleportState state = gAgent.getTeleportState(); if(state != LLAgent::TELEPORT_NONE && state != LLAgent::TELEPORT_LOCAL && state != LLAgent::TELEPORT_PENDING && - (!hide_tp_screen || state == LLAgent::TELEPORT_START_ARRIVAL || state == LLAgent::TELEPORT_ARRIVING)) + (/*!hide_tp_screen ||*/ state == LLAgent::TELEPORT_START_ARRIVAL || state == LLAgent::TELEPORT_ARRIVING)) { if(!cleared) { diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index e8e66bc27..fda306e0d 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -372,7 +372,7 @@ public: static const LLCachedControl use_rmse_auto_mask("SHUseRMSEAutoMask",false); static const LLCachedControl auto_mask_max_rmse("SHAutoMaskMaxRMSE",.09f); addText(xpos, ypos, llformat("Mask: %s", imagep->getIsAlphaMask(use_rmse_auto_mask ? auto_mask_max_rmse : -1.f) ? "TRUE":"FALSE")); ypos += y_inc; - addText(xpos, ypos, llformat("ID: %s", imagep->getID().asString())); ypos += y_inc; + addText(xpos, ypos, llformat("ID: %s", imagep->getID().asString().c_str())); ypos += y_inc; } } } diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 9e9f785c7..711406ea8 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -2403,15 +2403,18 @@ BOOL LLPipeline::updateDrawableGeom(LLDrawable* drawablep, BOOL priority) BOOL update_complete = drawablep->updateGeometry(priority); if (update_complete && assertInitialized()) { - drawablep->setState(LLDrawable::BUILT); //Workaround for 'missing prims' until it's fixed upstream by LL. //Sometimes clearing CLEAR_INVISIBLE and FORCE_INVISIBLE in LLPipeline::stateSort was too late. Do it here instead, before //the rebuild state is picked up on and LLVolumeGeometryManager::rebuildGeom is called. //If the FORCE_INVISIBLE isn't cleared before the rebuildGeom call, the geometry will NOT BE REBUILT! if(drawablep->isState(LLDrawable::CLEAR_INVISIBLE)) { + // clear invisible flag here to avoid single frame glitch drawablep->clearState(LLDrawable::FORCE_INVISIBLE|LLDrawable::CLEAR_INVISIBLE); + return false; //Defer to next mBuildQ1 iteration } + + drawablep->setState(LLDrawable::BUILT); mGeometryChanges++; } return update_complete; diff --git a/indra/newview/skins/default/xui/en-us/floater_chat_history.xml b/indra/newview/skins/default/xui/en-us/floater_chat_history.xml index 3d917fb28..6686a2ce8 100644 --- a/indra/newview/skins/default/xui/en-us/floater_chat_history.xml +++ b/indra/newview/skins/default/xui/en-us/floater_chat_history.xml @@ -22,6 +22,7 @@ Track your camera Teleport you Control your camera + Override your default animations diff --git a/indra/newview/skins/default/xui/en-us/strings.xml b/indra/newview/skins/default/xui/en-us/strings.xml index 38c87d0d3..40b2f3f91 100644 --- a/indra/newview/skins/default/xui/en-us/strings.xml +++ b/indra/newview/skins/default/xui/en-us/strings.xml @@ -299,6 +299,7 @@ Track your camera Control your camera Teleport you + Override your default animations PG