diff --git a/indra/llrender/llfont.cpp b/indra/llrender/llfont.cpp index 64c01406e..80f938ec6 100644 --- a/indra/llrender/llfont.cpp +++ b/indra/llrender/llfont.cpp @@ -65,6 +65,8 @@ LLFontManager *gFontManagerp = NULL; FT_Library gFTLibrary = NULL; +bool LLFont::sOpenGLcrashOnRestart = false; + //static void LLFontManager::initClass() { @@ -269,8 +271,11 @@ void LLFont::resetBitmapCache() } mFontBitmapCachep->reset(); + if (!mIsFallback || !sOpenGLcrashOnRestart) // because this often crashes under Linux... + { // Add the empty glyph`5 addGlyph(0, 0); + } } LLFontGlyphInfo* LLFont::getGlyphInfo(const llwchar wch) const diff --git a/indra/llrender/llfont.h b/indra/llrender/llfont.h index b423f7d32..68bfad641 100644 --- a/indra/llrender/llfont.h +++ b/indra/llrender/llfont.h @@ -151,6 +151,8 @@ public: F32 getXKerning(const llwchar char_left, const llwchar char_right) const; // Get the kerning between the two characters virtual void reset() = 0; + static bool sOpenGLcrashOnRestart; + protected: virtual BOOL hasGlyph(const llwchar wch) const; // Has a glyph for this character virtual BOOL addChar(const llwchar wch) const; // Add a new character to the font if necessary diff --git a/indra/llrender/llfontgl.cpp b/indra/llrender/llfontgl.cpp index 507a8b926..c3d50678f 100644 --- a/indra/llrender/llfontgl.cpp +++ b/indra/llrender/llfontgl.cpp @@ -267,8 +267,16 @@ void LLFontGL::destroyAllGL() { if (sFontRegistry) { + if (LLFont::sOpenGLcrashOnRestart) + { + // This will leak memory but will prevent a crash... + sFontRegistry = NULL; + } + else + { sFontRegistry->destroyGL(); } + } } void LLFontGL::destroyGL() diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp index 60eca9719..2ea3423b0 100644 --- a/indra/llui/lltexteditor.cpp +++ b/indra/llui/lltexteditor.cpp @@ -927,11 +927,6 @@ S32 LLTextEditor::getCursorPosFromLocalCoord( S32 local_x, S32 local_y, BOOL rou void LLTextEditor::setCursor(S32 row, S32 column) { - // Make sure we're not trying to set the cursor anywhere - // it can't go by always setting the min to 0 -- MC - row = (row < 0) ? 0 : row; - column = (column < 0) ? 0 : column; - const llwchar* doc = mWText.c_str(); const char CR = 10; diff --git a/indra/newview/linux_tools/wrapper.sh b/indra/newview/linux_tools/wrapper.sh index 755157d20..ba101cdf9 100755 --- a/indra/newview/linux_tools/wrapper.sh +++ b/indra/newview/linux_tools/wrapper.sh @@ -74,6 +74,13 @@ if [ "$GTK_IM_MODULE" = "scim" ]; then export GTK_IM_MODULE=xim fi +# Work around for a crash bug when restarting OpenGL after a change in the +# graphic settings (anti-aliasing, VBO, FSAA, full screen mode, UI scale). +# When you enable this work around, you can change the settings without +# crashing, but you will have to restart the viewer after changing them +# because the display still gets corrupted. +export LL_OPENGL_RESTART_CRASH_BUG=x + ## - Automatically work around the ATI mouse cursor crash bug: ## (this workaround is disabled as most fglrx users do not see the bug) #if lsmod | grep fglrx &>/dev/null ; then diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 34fbbdbd0..a75e4162c 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -74,6 +74,7 @@ #include "llurlhistory.h" #include "llfirstuse.h" #include "llrender.h" +#include "llfont.h" #include "llweb.h" #include "llsecondlifeurls.h" @@ -680,6 +681,8 @@ bool LLAppViewer::init() settings_setup_listeners(); // Modify settings based on system configuration and compile options settings_modify(); + // Work around for a crash bug when changing OpenGL settings + LLFont::sOpenGLcrashOnRestart = (getenv("LL_OPENGL_RESTART_CRASH_BUG") != NULL); // Find partition serial number (Windows) or hardware serial (Mac) mSerialNumber = generateSerialNumber(); diff --git a/indra/newview/llfolderview.cpp b/indra/newview/llfolderview.cpp index 6eec5fde9..603ed921a 100644 --- a/indra/newview/llfolderview.cpp +++ b/indra/newview/llfolderview.cpp @@ -120,6 +120,10 @@ LLColor4 LLFolderViewItem::sSearchStatusColor; LLUIImagePtr LLFolderViewItem::sArrowImage; LLUIImagePtr LLFolderViewItem::sBoxImage; +// This is used to keep track of existing folder view items and +// avoid a crash bug due to a race condition (see in doIdle()). +static std::set sFolderViewItems; + //static void LLFolderViewItem::initClass() { @@ -170,6 +174,7 @@ LLFolderViewItem::LLFolderViewItem( const std::string& name, LLUIImagePtr icon, mDragAndDropTarget(FALSE), mIsLoading(FALSE) { + sFolderViewItems.insert(this); refresh(); // possible opt: only call refreshFromListener() setTabStop(FALSE); } @@ -177,6 +182,7 @@ LLFolderViewItem::LLFolderViewItem( const std::string& name, LLUIImagePtr icon, // Destroys the object LLFolderViewItem::~LLFolderViewItem( void ) { + sFolderViewItems.erase(this); delete mListener; mListener = NULL; } @@ -4401,7 +4407,19 @@ void LLFolderView::doIdle() LLFastTimer t3(LLFastTimer::FTM_AUTO_SELECT); // select new item only if a filtered item not currently selected LLFolderViewItem* selected_itemp = mSelectedItems.empty() ? NULL : mSelectedItems.back(); - if ((!selected_itemp || !selected_itemp->getFiltered()) && !mAutoSelectOverride) + if (selected_itemp != NULL && sFolderViewItems.count(selected_itemp) == 0) + { + // There is a crash bug due to a race condition: when a folder view item is + // destroyed, its address may still appear in mSelectedItems a couple of doIdle() + // later, even if you explicitely clear this list and dirty the filters in the + // destructor... + // This code avoids the crash bug. + llwarns << "Invalid folder view item (" << selected_itemp << ") in selection: clearing the latter." << llendl; + dirtyFilter(); + clearSelection(); + requestArrange(); + } + else if (!mAutoSelectOverride && (!selected_itemp || !selected_itemp->getFiltered())) { // select first filtered item LLSelectFirstFilteredItem filter; diff --git a/indra/newview/llinventoryview.cpp b/indra/newview/llinventoryview.cpp index c9ec3d6a7..0007034a3 100644 --- a/indra/newview/llinventoryview.cpp +++ b/indra/newview/llinventoryview.cpp @@ -1812,12 +1812,19 @@ void LLInventoryPanel::modelChanged(U32 mask) } LLFolderViewFolder* new_parent = (LLFolderViewFolder*)mFolders->getItemByID(model_item->getParentUUID()); + if (new_parent) + { if (view_item->getParentFolder() != new_parent) { view_item->getParentFolder()->extractItem(view_item); view_item->addToFolder(new_parent, mFolders); } } + else + { + llwarns << model_item->getParentUUID() << ": parent folder gone !" << llendl; + } + } } else { @@ -1832,7 +1839,7 @@ void LLInventoryPanel::modelChanged(U32 mask) } else { - llwarns << *id_it << "Item does not exist in either view or model, but notification triggered" << llendl; + llwarns << *id_it << ": Item does not exist in either view or model, but notification triggered" << llendl; } } } diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index 9964eea6f..6a754665c 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -2778,11 +2778,11 @@ LLViewerInventoryItem* LLViewerObject::getInventoryItemByAsset(const LLUUID& ass for( ; it != end; ++it) { LLInventoryObject* obj = *it; - if(obj->getType() != LLAssetType::AT_CATEGORY) + if (obj && obj->getType() != LLAssetType::AT_CATEGORY && obj->getType() != LLAssetType::AT_NONE) { // *FIX: gank-ass down cast! item = (LLViewerInventoryItem*)obj; - if(item->getAssetUUID() == asset_id) + if (item && item->getAssetUUID() == asset_id) { rv = item; break; diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 0bfb7de7c..674b412c4 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -4375,10 +4375,13 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei if (high_res) { send_agent_pause(); + if (show_ui || !hide_hud) + { //rescale fonts initFonts(scale_factor); LLHUDText::reshape(); } + } S32 output_buffer_offset_y = 0; @@ -4501,7 +4504,7 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei LLPipeline::sShowHUDAttachments = TRUE; } - if (high_res) + if (high_res && (show_ui || !hide_hud)) { initFonts(1.f); LLHUDText::reshape();