diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp index 0683bf3548..95ae0856fe 100644 --- a/indra/llimage/llimage.cpp +++ b/indra/llimage/llimage.cpp @@ -584,8 +584,7 @@ static void bilinear_scale(const U8 *src, U32 srcW, U32 srcH, U32 srcCh, U32 src //--------------------------------------------------------------------------- //static -std::string LLImage::sLastErrorMessage; -LLMutex* LLImage::sMutex = NULL; +thread_local std::string LLImage::sLastThreadErrorMessage; bool LLImage::sUseNewByteRange = false; S32 LLImage::sMinimalReverseByteRangePercent = 75; @@ -594,28 +593,24 @@ void LLImage::initClass(bool use_new_byte_range, S32 minimal_reverse_byte_range_ { sUseNewByteRange = use_new_byte_range; sMinimalReverseByteRangePercent = minimal_reverse_byte_range_percent; - sMutex = new LLMutex(); } //static void LLImage::cleanupClass() { - delete sMutex; - sMutex = NULL; } //static -const std::string& LLImage::getLastError() +const std::string& LLImage::getLastThreadError() { static const std::string noerr("No Error"); - return sLastErrorMessage.empty() ? noerr : sLastErrorMessage; + return sLastThreadErrorMessage.empty() ? noerr : sLastThreadErrorMessage; } //static void LLImage::setLastError(const std::string& message) { - LLMutexLock m(sMutex); - sLastErrorMessage = message; + sLastThreadErrorMessage = message; } //--------------------------------------------------------------------------- diff --git a/indra/llimage/llimage.h b/indra/llimage/llimage.h index 7327334ec4..c92ac2a73c 100644 --- a/indra/llimage/llimage.h +++ b/indra/llimage/llimage.h @@ -95,15 +95,14 @@ public: static void initClass(bool use_new_byte_range = false, S32 minimal_reverse_byte_range_percent = 75); static void cleanupClass(); - static const std::string& getLastError(); + static const std::string& getLastThreadError(); static void setLastError(const std::string& message); static bool useNewByteRange() { return sUseNewByteRange; } static S32 getReverseByteRangePercent() { return sMinimalReverseByteRangePercent; } protected: - static LLMutex* sMutex; - static std::string sLastErrorMessage; + static thread_local std::string sLastThreadErrorMessage; static bool sUseNewByteRange; static S32 sMinimalReverseByteRangePercent; }; diff --git a/indra/llimage/llimageworker.cpp b/indra/llimage/llimageworker.cpp index 8bd5bd9584..4d24fb7af0 100644 --- a/indra/llimage/llimageworker.cpp +++ b/indra/llimage/llimageworker.cpp @@ -55,6 +55,7 @@ private: BOOL mDecodedRaw; BOOL mDecodedAux; LLPointer mResponder; + std::string mErrorString; }; @@ -149,8 +150,9 @@ ImageRequest::~ImageRequest() bool ImageRequest::processRequest() { LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; - const F32 decode_time_slice = 0.f; //disable time slicing - bool done = true; + const F32 decode_time_slice = 0.f; //disable time slicing + bool done = true; + mErrorString.clear(); if (!mDecodedRaw && mFormattedImage.notNull()) { // Decode primary channels @@ -159,10 +161,13 @@ bool ImageRequest::processRequest() // parse formatted header if (!mFormattedImage->updateData()) { + // Pick up errors from updateData + mErrorString = LLImage::getLastThreadError(); return true; // done (failed) } if (0 == (mFormattedImage->getWidth() * mFormattedImage->getHeight() * mFormattedImage->getComponents())) { + mErrorString = "Invalid image size"; return true; // done (failed) } if (mDiscardLevel >= 0) @@ -188,6 +193,9 @@ bool ImageRequest::processRequest() // some decoders are removing data when task is complete and there were errors mDecodedRaw = done && mDecodedImageRaw->getData(); + + // Pick up errors from decoding + mErrorString = LLImage::getLastThreadError(); } if (done && mNeedsAux && !mDecodedAux && mFormattedImage.notNull()) { @@ -200,7 +208,10 @@ bool ImageRequest::processRequest() } done = mFormattedImage->decodeChannels(mDecodedImageAux, decode_time_slice, 4, 4); mDecodedAux = done && mDecodedImageAux->getData(); - } + + // Pick up errors from decoding + mErrorString = LLImage::getLastThreadError(); + } return done; } @@ -211,7 +222,7 @@ void ImageRequest::finishRequest(bool completed) if (mResponder.notNull()) { bool success = completed && mDecodedRaw && (!mNeedsAux || mDecodedAux); - mResponder->completed(success, mDecodedImageRaw, mDecodedImageAux); + mResponder->completed(success, mErrorString, mDecodedImageRaw, mDecodedImageAux); } // Will automatically be deleted } diff --git a/indra/llimage/llimageworker.h b/indra/llimage/llimageworker.h index ca4c0d93d0..c48c8084ee 100644 --- a/indra/llimage/llimageworker.h +++ b/indra/llimage/llimageworker.h @@ -39,7 +39,7 @@ public: protected: virtual ~Responder(); public: - virtual void completed(bool success, LLImageRaw* raw, LLImageRaw* aux) = 0; + virtual void completed(bool success, const std::string& error_message, LLImageRaw* raw, LLImageRaw* aux) = 0; }; public: diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index 24b0653d26..ff09c2c115 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -862,7 +862,7 @@ LLRender::~LLRender() shutdown(); } -void LLRender::init(bool needs_vertex_buffer) +bool LLRender::init(bool needs_vertex_buffer) { #if LL_WINDOWS if (gGLManager.mHasDebugOutput && gDebugGL) @@ -884,6 +884,13 @@ void LLRender::init(bool needs_vertex_buffer) // necessary for reflection maps glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS); +#if LL_WINDOWS + if (glGenVertexArrays == nullptr) + { + return false; + } +#endif + { //bind a dummy vertex array object so we're core profile compliant U32 ret; glGenVertexArrays(1, &ret); @@ -904,6 +911,7 @@ void LLRender::init(bool needs_vertex_buffer) stop_glerror(); mMaxLineWidthSmooth = range[1]; // + return true; } void LLRender::initVertexBuffer() diff --git a/indra/llrender/llrender.h b/indra/llrender/llrender.h index 6cc570543b..1956715e5b 100644 --- a/indra/llrender/llrender.h +++ b/indra/llrender/llrender.h @@ -386,7 +386,7 @@ public: LLRender(); ~LLRender(); - void init(bool needs_vertex_buffer); + bool init(bool needs_vertex_buffer); void initVertexBuffer(); void resetVertexBuffer(); void shutdown(); diff --git a/indra/llui/llcombobox.cpp b/indra/llui/llcombobox.cpp index 03215d3765..e5c6276c17 100644 --- a/indra/llui/llcombobox.cpp +++ b/indra/llui/llcombobox.cpp @@ -191,6 +191,8 @@ LLComboBox::~LLComboBox() // explicitly disconect this signal, since base class destructor might fire top lost mTopLostSignalConnection.disconnect(); mImageLoadedConnection.disconnect(); + + LLUI::getInstance()->removePopup(this); } diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp index 0e1236e563..f6d635be01 100644 --- a/indra/llui/llfolderview.cpp +++ b/indra/llui/llfolderview.cpp @@ -260,7 +260,13 @@ LLFolderView::LLFolderView(const Params& p) // Destroys the object LLFolderView::~LLFolderView( void ) { - closeRenamer(); + mRenamerTopLostSignalConnection.disconnect(); + if (mRenamer) + { + // instead of using closeRenamer remove it directly, + // since it might already be hidden + LLUI::getInstance()->removePopup(mRenamer); + } // The release focus call can potentially call the // scrollcontainer, which can potentially be called with a partly @@ -1109,7 +1115,10 @@ void LLFolderView::startRenamingSelectedItem( void ) mRenamer->setVisible( TRUE ); // set focus will fail unless item is visible mRenamer->setFocus( TRUE ); - mRenamer->setTopLostCallback(boost::bind(&LLFolderView::onRenamerLost, this)); + if (!mRenamerTopLostSignalConnection.connected()) + { + mRenamerTopLostSignalConnection = mRenamer->setTopLostCallback(boost::bind(&LLFolderView::onRenamerLost, this)); + } LLUI::getInstance()->addPopup(mRenamer); } } @@ -1692,7 +1701,11 @@ BOOL LLFolderView::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, void LLFolderView::deleteAllChildren() { - closeRenamer(); + mRenamerTopLostSignalConnection.disconnect(); + if (mRenamer) + { + LLUI::getInstance()->removePopup(mRenamer); + } if (mPopupMenuHandle.get()) mPopupMenuHandle.get()->die(); mPopupMenuHandle.markDead(); mScrollContainer = NULL; diff --git a/indra/llui/llfolderview.h b/indra/llui/llfolderview.h index 1894e06586..3ced3cb9ec 100644 --- a/indra/llui/llfolderview.h +++ b/indra/llui/llfolderview.h @@ -354,6 +354,8 @@ protected: LLUICtrl::CommitCallbackRegistry::ScopedRegistrar* mCallbackRegistrar; LLUICtrl::EnableCallbackRegistry::ScopedRegistrar* mEnableRegistrar; + boost::signals2::connection mRenamerTopLostSignalConnection; + bool mForceArrange; public: diff --git a/indra/llui/llmodaldialog.cpp b/indra/llui/llmodaldialog.cpp index 22d98469ec..c4dacd777e 100644 --- a/indra/llui/llmodaldialog.cpp +++ b/indra/llui/llmodaldialog.cpp @@ -67,6 +67,8 @@ LLModalDialog::~LLModalDialog() { LL_ERRS() << "Attempt to delete dialog while still in sModalStack!" << LL_ENDL; } + + LLUI::getInstance()->removePopup(this); } // virtual diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index 2cede8a019..0f631a2de9 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -1683,7 +1683,9 @@ const S32 max_format = (S32)num_formats - 1; } else { - LL_WARNS("Window") << "No wgl_ARB_pixel_format extension, using default ChoosePixelFormat!" << LL_ENDL; + LLError::LLUserWarningMsg::show(mCallbacks->translateString("MBVideoDrvErr")); + // mWindowHandle is 0, going to crash either way + LL_ERRS("Window") << "No wgl_ARB_pixel_format extension!" << LL_ENDL; } // Verify what pixel format we actually received. @@ -1937,12 +1939,16 @@ void LLWindowWin32::destroySharedContext(void* contextPtr) void LLWindowWin32::toggleVSync(bool enable_vsync) { - if (!enable_vsync && wglSwapIntervalEXT) + if (wglSwapIntervalEXT == nullptr) + { + LL_INFOS("Window") << "VSync: wglSwapIntervalEXT not initialized" << LL_ENDL; + } + else if (!enable_vsync) { LL_INFOS("Window") << "Disabling vertical sync" << LL_ENDL; wglSwapIntervalEXT(0); } - else if (wglSwapIntervalEXT) + else { LL_INFOS("Window") << "Enabling vertical sync" << LL_ENDL; wglSwapIntervalEXT(1); diff --git a/indra/newview/llaccountingcostmanager.cpp b/indra/newview/llaccountingcostmanager.cpp index d3f988d715..0a558da42b 100644 --- a/indra/newview/llaccountingcostmanager.cpp +++ b/indra/newview/llaccountingcostmanager.cpp @@ -58,16 +58,19 @@ void LLAccountingCostManager::accountingCostCoro(std::string url, try { + LLAccountingCostManager* self = LLAccountingCostManager::getInstance(); uuid_set_t diffSet; - std::set_difference(mObjectList.begin(), mObjectList.end(), - mPendingObjectQuota.begin(), mPendingObjectQuota.end(), - std::inserter(diffSet, diffSet.begin())); + std::set_difference(self->mObjectList.begin(), + self->mObjectList.end(), + self->mPendingObjectQuota.begin(), + self->mPendingObjectQuota.end(), + std::inserter(diffSet, diffSet.begin())); if (diffSet.empty()) return; - mObjectList.clear(); + self->mObjectList.clear(); std::string keystr; if (selectionType == Roots) @@ -91,18 +94,25 @@ void LLAccountingCostManager::accountingCostCoro(std::string url, objectList.append(*it); } - mPendingObjectQuota.insert(diffSet.begin(), diffSet.end()); + self->mPendingObjectQuota.insert(diffSet.begin(), diffSet.end()); LLSD dataToPost = LLSD::emptyMap(); dataToPost[keystr.c_str()] = objectList; - LLAccountingCostObserver* observer = NULL; - LLSD results = httpAdapter->postAndSuspend(httpRequest, url, dataToPost); LLSD httpResults = results["http_result"]; LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); + if (LLApp::isQuitting() + || observerHandle.isDead() + || !LLAccountingCostManager::instanceExists()) + { + return; + } + + LLAccountingCostObserver* observer = NULL; + // do/while(false) allows error conditions to break out of following // block while normal flow goes forward once. do @@ -159,7 +169,8 @@ void LLAccountingCostManager::accountingCostCoro(std::string url, throw; } - mPendingObjectQuota.clear(); + // self can be obsolete by this point + LLAccountingCostManager::getInstance()->mPendingObjectQuota.clear(); } //=============================================================================== @@ -172,7 +183,7 @@ void LLAccountingCostManager::fetchCosts( eSelectionType selectionType, { std::string coroname = LLCoros::instance().launch("LLAccountingCostManager::accountingCostCoro", - boost::bind(&LLAccountingCostManager::accountingCostCoro, this, url, selectionType, observer_handle)); + boost::bind(accountingCostCoro, url, selectionType, observer_handle)); LL_DEBUGS() << coroname << " with url '" << url << LL_ENDL; } diff --git a/indra/newview/llaccountingcostmanager.h b/indra/newview/llaccountingcostmanager.h index d133c6437b..9b2ffc7d7c 100644 --- a/indra/newview/llaccountingcostmanager.h +++ b/indra/newview/llaccountingcostmanager.h @@ -70,7 +70,7 @@ private: //a fetch has been instigated. uuid_set_t mPendingObjectQuota; - void accountingCostCoro(std::string url, eSelectionType selectionType, const LLHandle observerHandle); + static void accountingCostCoro(std::string url, eSelectionType selectionType, const LLHandle observerHandle); }; //=============================================================================== diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index 6d43b4cb46..d9339ba358 100644 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -108,6 +108,8 @@ LLConversationViewSession::~LLConversationViewSession() } mFlashTimer->unset(); + delete mFlashTimer; + mFlashStateOn = false; } void LLConversationViewSession::destroyView() diff --git a/indra/newview/llexpandabletextbox.cpp b/indra/newview/llexpandabletextbox.cpp index 2d332f75f5..8b7593e169 100644 --- a/indra/newview/llexpandabletextbox.cpp +++ b/indra/newview/llexpandabletextbox.cpp @@ -243,6 +243,12 @@ LLExpandableTextBox::LLExpandableTextBox(const Params& p) mTextBox->setCommitCallback(boost::bind(&LLExpandableTextBox::onExpandClicked, this)); } + +LLExpandableTextBox::~LLExpandableTextBox() +{ + gViewerWindow->removePopup(this); +} + void LLExpandableTextBox::draw() { if(mBGVisible && !mExpanded) diff --git a/indra/newview/llexpandabletextbox.h b/indra/newview/llexpandabletextbox.h index aaf393277f..17a98e44d5 100644 --- a/indra/newview/llexpandabletextbox.h +++ b/indra/newview/llexpandabletextbox.h @@ -154,6 +154,8 @@ public: */ /*virtual*/ void draw(); + virtual ~LLExpandableTextBox(); + protected: LLExpandableTextBox(const Params& p); diff --git a/indra/newview/llfloatersimplesnapshot.cpp b/indra/newview/llfloatersimplesnapshot.cpp index 58604c5628..40d5a5ed84 100644 --- a/indra/newview/llfloatersimplesnapshot.cpp +++ b/indra/newview/llfloatersimplesnapshot.cpp @@ -370,7 +370,7 @@ void LLFloaterSimpleSnapshot::onSend() else { LLSD notif_args; - notif_args["REASON"] = LLImage::getLastError().c_str(); + notif_args["REASON"] = LLImage::getLastThreadError().c_str(); LLNotificationsUtil::add("CannotUploadTexture", notif_args); } } @@ -389,7 +389,7 @@ void LLFloaterSimpleSnapshot::uploadThumbnail(const std::string &file_path, cons if (!LLViewerTextureList::createUploadFile(file_path, temp_file, codec, THUMBNAIL_SNAPSHOT_DIM_MAX, THUMBNAIL_SNAPSHOT_DIM_MIN, true)) { LLSD notif_args; - notif_args["REASON"] = LLImage::getLastError().c_str(); + notif_args["REASON"] = LLImage::getLastThreadError().c_str(); LLNotificationsUtil::add("CannotUploadTexture", notif_args); LL_WARNS("Thumbnail") << "Failed to upload thumbnail for " << inventory_id << " " << task_id << ", reason: " << notif_args["REASON"].asString() << LL_ENDL; return; @@ -404,7 +404,7 @@ void LLFloaterSimpleSnapshot::uploadThumbnail(LLPointer raw_image, c if (!LLViewerTextureList::createUploadFile(raw_image, temp_file, THUMBNAIL_SNAPSHOT_DIM_MAX, THUMBNAIL_SNAPSHOT_DIM_MIN)) { LLSD notif_args; - notif_args["REASON"] = LLImage::getLastError().c_str(); + notif_args["REASON"] = LLImage::getLastThreadError().c_str(); LLNotificationsUtil::add("CannotUploadTexture", notif_args); LL_WARNS("Thumbnail") << "Failed to upload thumbnail for " << inventory_id << " " << task_id << ", reason: " << notif_args["REASON"].asString() << LL_ENDL; return; diff --git a/indra/newview/llmodelpreview.cpp b/indra/newview/llmodelpreview.cpp index fde68b1db5..6614d31956 100644 --- a/indra/newview/llmodelpreview.cpp +++ b/indra/newview/llmodelpreview.cpp @@ -644,13 +644,13 @@ void LLModelPreview::rebuildUploadData() // That's ok, but might not what they wanted. Use default_physics_shape if found. std::ostringstream out; out << "No physics model specified for " << instance.mLabel; - if (mDefaultPhysicsShapeP) + if (mDefaultPhysicsShapeP.notNull()) { out << " - using: " << DEFAULT_PHYSICS_MESH_NAME; lod_model = mDefaultPhysicsShapeP; } LL_WARNS() << out.str() << LL_ENDL; - LLFloaterModelPreview::addStringToLog(out, !mDefaultPhysicsShapeP); // Flash log tab if no default. + LLFloaterModelPreview::addStringToLog(out, mDefaultPhysicsShapeP.isNull()); // Flash log tab if no default. } if (lod_model) @@ -1381,8 +1381,9 @@ void LLModelPreview::loadModelCallback(S32 loaded_lod) if (loaded_lod == LLModel::LOD_PHYSICS) { // Explicitly loading physics. See if there is a default mesh. LLMatrix4 ignored_transform; // Each mesh that uses this will supply their own. - mDefaultPhysicsShapeP = nullptr; - FindModel(mScene[loaded_lod], DEFAULT_PHYSICS_MESH_NAME + getLodSuffix(loaded_lod), mDefaultPhysicsShapeP, ignored_transform); + LLModel* out_model = nullptr; + FindModel(mScene[loaded_lod], DEFAULT_PHYSICS_MESH_NAME + getLodSuffix(loaded_lod), out_model, ignored_transform); + mDefaultPhysicsShapeP = out_model; mWarnOfUnmatchedPhyicsMeshes = true; } BOOL legacyMatching = gSavedSettings.getBOOL("ImporterLegacyMatching"); diff --git a/indra/newview/llmodelpreview.h b/indra/newview/llmodelpreview.h index 406ddfd0f4..8cbd249073 100644 --- a/indra/newview/llmodelpreview.h +++ b/indra/newview/llmodelpreview.h @@ -246,7 +246,7 @@ private: /// It is set only when the user chooses a physics shape file that contains a mesh with a name that matches DEFAULT_PHYSICS_MESH_NAME. /// It is reset when such a name is not found, and when resetting the modelpreview. /// Not read unless mWarnOfUnmatchedPhyicsMeshes is true. - LLModel* mDefaultPhysicsShapeP{}; + LLPointer mDefaultPhysicsShapeP; typedef enum { diff --git a/indra/newview/llpanelprofile.cpp b/indra/newview/llpanelprofile.cpp index 26117103ad..aabb627458 100644 --- a/indra/newview/llpanelprofile.cpp +++ b/indra/newview/llpanelprofile.cpp @@ -1858,7 +1858,7 @@ void LLProfileImagePicker::notify(const std::vector& filenames) if (!LLViewerTextureList::createUploadFile(file_path, temp_file, codec, MAX_DIM)) { LLSD notif_args; - notif_args["REASON"] = LLImage::getLastError().c_str(); + notif_args["REASON"] = LLImage::getLastThreadError().c_str(); LLNotificationsUtil::add("CannotUploadTexture", notif_args); LL_WARNS("AvatarProperties") << "Failed to upload profile image of type " << (S32)mType << ", " << notif_args["REASON"].asString() << LL_ENDL; return; diff --git a/indra/newview/llpopupview.cpp b/indra/newview/llpopupview.cpp index d1a9ca229f..aadef9a308 100644 --- a/indra/newview/llpopupview.cpp +++ b/indra/newview/llpopupview.cpp @@ -256,16 +256,16 @@ void LLPopupView::removePopup(LLView* popup) void LLPopupView::clearPopups() { - for (popup_list_t::iterator popup_it = mPopups.begin(); - popup_it != mPopups.end();) + while (!mPopups.empty()) { - LLView* popup = popup_it->get(); - - popup_list_t::iterator cur_popup_it = popup_it; - ++popup_it; - - mPopups.erase(cur_popup_it); - popup->onTopLost(); + popup_list_t::iterator popup_it = mPopups.begin(); + LLView* popup = popup_it->get(); + // Remove before notifying in case it will cause removePopup + mPopups.erase(popup_it); + if (popup) + { + popup->onTopLost(); + } } } diff --git a/indra/newview/llreflectionmap.cpp b/indra/newview/llreflectionmap.cpp index 90c2967861..2e5aaa997d 100644 --- a/indra/newview/llreflectionmap.cpp +++ b/indra/newview/llreflectionmap.cpp @@ -74,11 +74,9 @@ void LLReflectionMap::autoAdjustOrigin() { const LLVector4a* bounds = mGroup->getBounds(); auto* node = mGroup->getOctreeNode(); - // Bugsplat-Fix - // if (mGroup->getSpatialPartition()->mPartitionType == LLViewerRegion::PARTITION_VOLUME) - const auto* partition = mGroup->getSpatialPartition(); - if (partition && partition->mPartitionType == LLViewerRegion::PARTITION_VOLUME) - // + LLSpatialPartition* part = mGroup->getSpatialPartition(); + + if (part && part->mPartitionType == LLViewerRegion::PARTITION_VOLUME) { mPriority = 0; // cast a ray towards 8 corners of bounding box diff --git a/indra/newview/llsplitbutton.cpp b/indra/newview/llsplitbutton.cpp index 790305103d..c216319e76 100644 --- a/indra/newview/llsplitbutton.cpp +++ b/indra/newview/llsplitbutton.cpp @@ -243,7 +243,14 @@ LLSplitButton::LLSplitButton(const LLSplitButton::Params& p) item_top -= (rc.getHeight() + BUTTON_PAD); } - setTopLostCallback(boost::bind(&LLSplitButton::hideButtons, this)); + mTopLostSignalConnection = setTopLostCallback(boost::bind(&LLSplitButton::hideButtons, this)); +} + +LLSplitButton::~LLSplitButton() +{ + // explicitly disconect to avoid hideButtons with + // dead pointers being called on destruction + mTopLostSignalConnection.disconnect(); } diff --git a/indra/newview/llsplitbutton.h b/indra/newview/llsplitbutton.h index 4f20c8b379..dbb18c0c62 100644 --- a/indra/newview/llsplitbutton.h +++ b/indra/newview/llsplitbutton.h @@ -67,7 +67,7 @@ public: }; - virtual ~LLSplitButton() {}; + virtual ~LLSplitButton(); //Overridden virtual void onFocusLost(); @@ -99,6 +99,8 @@ protected: LLButton* mShownItem; EArrowPosition mArrowPosition; + boost::signals2::connection mTopLostSignalConnection; + commit_callback_t mSelectionCallback; }; diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp index 16a8d3d394..626e5e485c 100644 --- a/indra/newview/lltexturefetch.cpp +++ b/indra/newview/lltexturefetch.cpp @@ -352,13 +352,13 @@ private: } // Threads: Tid - virtual void completed(bool success, LLImageRaw* raw, LLImageRaw* aux) + virtual void completed(bool success, const std::string& error_message, LLImageRaw* raw, LLImageRaw* aux) { LL_PROFILE_ZONE_SCOPED; LLTextureFetchWorker* worker = mFetcher->getWorker(mID); if (worker) { - worker->callbackDecoded(success, raw, aux); + worker->callbackDecoded(success, error_message, raw, aux); } } private: @@ -402,7 +402,7 @@ public: void callbackCacheWrite(bool success); // Threads: Tid - void callbackDecoded(bool success, LLImageRaw* raw, LLImageRaw* aux); + void callbackDecoded(bool success, const std::string& error_message, LLImageRaw* raw, LLImageRaw* aux); // Threads: T* void setGetStatus(LLCore::HttpStatus status, const std::string& reason) @@ -2530,7 +2530,7 @@ void LLTextureFetchWorker::callbackCacheWrite(bool success) ////////////////////////////////////////////////////////////////////////////// // Threads: Tid -void LLTextureFetchWorker::callbackDecoded(bool success, LLImageRaw* raw, LLImageRaw* aux) +void LLTextureFetchWorker::callbackDecoded(bool success, const std::string &error_message, LLImageRaw* raw, LLImageRaw* aux) { LLMutexLock lock(&mWorkMutex); // +Mw if (mDecodeHandle == 0) @@ -2557,7 +2557,7 @@ void LLTextureFetchWorker::callbackDecoded(bool success, LLImageRaw* raw, LLImag } else { - LL_WARNS(LOG_TXT) << "DECODE FAILED: " << mID << " Discard: " << (S32)mFormattedImage->getDiscardLevel() << LL_ENDL; + LL_WARNS(LOG_TXT) << "DECODE FAILED: " << mID << " Discard: " << (S32)mFormattedImage->getDiscardLevel() << ", reason: " << error_message << LL_ENDL; removeFromCache(); mDecodedDiscard = -1; // Redundant, here for clarity and paranoia } diff --git a/indra/newview/lluploaddialog.cpp b/indra/newview/lluploaddialog.cpp index 78728b9e66..3f8fbd62a1 100644 --- a/indra/newview/lluploaddialog.cpp +++ b/indra/newview/lluploaddialog.cpp @@ -150,6 +150,7 @@ void LLUploadDialog::setMessage( const std::string& msg) LLUploadDialog::~LLUploadDialog() { + gViewerWindow->removePopup(this); gFocusMgr.releaseFocusIfNeeded( this ); // LLFilePicker::instance().reset(); diff --git a/indra/newview/llviewerassetupload.cpp b/indra/newview/llviewerassetupload.cpp index 87c1faee1e..6117643657 100644 --- a/indra/newview/llviewerassetupload.cpp +++ b/indra/newview/llviewerassetupload.cpp @@ -435,8 +435,8 @@ LLSD LLNewFileResourceUploadInfo::exportTempFile() { // Duplicate error message output //errorMessage = llformat("Problem with file %s:\n\n%s\n", - // getFileName().c_str(), LLImage::getLastError().c_str()); - errorMessage = LLImage::getLastError(); + // getFileName().c_str(), LLImage::getLastThreadError().c_str()); + errorMessage = LLImage::getLastThreadError(); // errorLabel = "ProblemWithFile"; error = true; diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp index 9bf8fec6d0..8668b181fe 100644 --- a/indra/newview/llviewermenufile.cpp +++ b/indra/newview/llviewermenufile.cpp @@ -1027,7 +1027,7 @@ void handle_compress_image(void*) } else { - LL_INFOS() << "Compression failed: " << LLImage::getLastError() << LL_ENDL; + LL_INFOS() << "Compression failed: " << LLImage::getLastThreadError() << LL_ENDL; } infile = picker.getNextFile(); diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index cf7325d744..fa98434f35 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -2067,7 +2067,11 @@ LLViewerWindow::LLViewerWindow(const Params& p) // Initialize OpenGL Renderer LLVertexBuffer::initClass(mWindow); LL_INFOS("RenderInit") << "LLVertexBuffer initialization done." << LL_ENDL ; - gGL.init(true); + if (!gGL.init(true)) + { + LLError::LLUserWarningMsg::show(LLTrans::getString("MBVideoDrvErr")); + LL_ERRS() << "gGL not initialized" << LL_ENDL; + } // Exodus vignette if (LLFeatureManager::getInstance()->isSafe() diff --git a/scripts/code_tools/fix_xml_indentations.py b/scripts/code_tools/fix_xml_indentations.py index 019f6db23c..9c8a1fc04b 100644 --- a/scripts/code_tools/fix_xml_indentations.py +++ b/scripts/code_tools/fix_xml_indentations.py @@ -79,7 +79,10 @@ def save_xml(tree, file_path, xml_decl, indent_text=False, indent_tab=False, rm_ with io.open(file_path, 'wb') as file: file.write(xml_decl.encode('utf-8')) file.write('\n'.encode('utf-8')) - file.write(xml_string.encode('utf-8')) + if xml_string: + file.write(xml_string.encode('utf-8')) + if not xml_string.endswith('\n'): + file.write('\n'.encode('utf-8')) except IOError as e: print(f"Error saving file {file_path}: {e}")