From 14e7b4aefee7b81808aaf835faf8b554acfb748b Mon Sep 17 00:00:00 2001 From: Shyotl Date: Mon, 19 Nov 2018 00:43:00 -0600 Subject: [PATCH] scrolllists were incredibly slow to render. This included the friends and groups lists. Should be much faster now due to not thrashing the bound texture quite as much. Also ui elements are culled on the cpu side if they are out of the current scissor region. list cells also had no clip logic, so added to that as well. --- indra/llui/llcheckboxctrl.cpp | 8 ++- indra/llui/llscrolllistctrl.cpp | 108 +++++++++++++++++++------------- indra/llui/llscrolllistitem.cpp | 88 +++++++++++++++++++------- indra/llui/llscrolllistitem.h | 2 +- indra/llui/llview.cpp | 21 +++++-- 5 files changed, 153 insertions(+), 74 deletions(-) diff --git a/indra/llui/llcheckboxctrl.cpp b/indra/llui/llcheckboxctrl.cpp index e8e34e64d..5df4ae675 100644 --- a/indra/llui/llcheckboxctrl.cpp +++ b/indra/llui/llcheckboxctrl.cpp @@ -93,11 +93,13 @@ LLCheckBoxCtrl::LLCheckBoxCtrl(const std::string& name, const LLRect& rect, // *HACK Get rid of this with SL-55508... // this allows blank check boxes and radio boxes for now - std::string local_label = label; + // Singu Note: Don't do this. Slows rendering down dramatically, and also seems to not fix anything? + /*std::string local_label = label; if(local_label.empty()) { - local_label = " "; - } + + //local_label = " "; + }*/ mLabel = new LLTextBox( std::string("CheckboxCtrl Label"), label_rect, local_label, mFont ); mLabel->setFollowsLeft(); diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp index 4e1531831..7af6313af 100644 --- a/indra/llui/llscrolllistctrl.cpp +++ b/indra/llui/llscrolllistctrl.cpp @@ -1403,7 +1403,16 @@ void LLScrollListCtrl::drawItems() { LLLocalClipRect clip(mItemListRect); - S32 cur_y = y; + LLRect clip_rect = LLUI::getRootView()->getRect(); + if (LLGLState::isEnabled()) + { + LLRect scissor = gGL.getScissor(); + scissor.mLeft /= LLUI::getScaleFactor().mV[VX]; + scissor.mTop /= LLUI::getScaleFactor().mV[VY]; + scissor.mRight /= LLUI::getScaleFactor().mV[VX]; + scissor.mBottom /= LLUI::getScaleFactor().mV[VY]; + clip_rect.intersectWith(scissor); + } S32 max_columns = 0; @@ -1418,55 +1427,70 @@ void LLScrollListCtrl::drawItems() { return; } - item_list::iterator iter; - for (S32 line = first_line; line <= last_line; line++) + bool done = false; + for (S32 pass = 0; !done; ++pass) { - LLScrollListItem* item = mItemList[line]; - - item_rect.setOriginAndSize( - x, - cur_y, - mItemListRect.getWidth(), - mLineHeight ); - item->setRect(item_rect); - - //LL_INFOS() << item_rect.getWidth() << LL_ENDL; - - max_columns = llmax(max_columns, item->getNumColumns()); - - LLColor4 fg_color; - LLColor4 bg_color(LLColor4::transparent); - - if( mScrollLines <= line && line < mScrollLines + num_page_lines ) + bool should_continue = false; // False until all passes are done for all row cells. + S32 cur_y = y; + for (S32 line = first_line; line <= last_line; line++) { - fg_color = (item->getEnabled() ? mFgUnselectedColor : mFgDisabledColor); - if( item->getSelected() && mCanSelect) + LLScrollListItem* item = mItemList[line]; + + item_rect.setOriginAndSize( + x, + cur_y, + mItemListRect.getWidth(), + mLineHeight); + item->setRect(item_rect); + + //LL_INFOS() << item_rect.getWidth() << LL_ENDL; + + max_columns = llmax(max_columns, item->getNumColumns()); + + LLColor4 fg_color; + LLColor4 bg_color(LLColor4::transparent); + + if (mScrollLines <= line && line < mScrollLines + num_page_lines) { - bg_color = mBgSelectedColor; - fg_color = (item->getEnabled() ? mFgSelectedColor : mFgDisabledColor); - } - else if (mHighlightedItem == line && mCanSelect) - { - bg_color = mHighlightedColor; - } - else - { - if (mDrawStripes && (line % 2 == 0) && (max_columns > 1)) + cur_y -= mLineHeight; + + // Do not draw if not on screen. + LLRect screen_rect = item_rect; + screen_rect.translate(LLFontGL::sCurOrigin.mX, LLFontGL::sCurOrigin.mY); + if (!clip_rect.overlaps(screen_rect)) { - bg_color = mBgStripeColor; + continue; } + + fg_color = (item->getEnabled() ? mFgUnselectedColor : mFgDisabledColor); + if (item->getSelected() && mCanSelect) + { + bg_color = mBgSelectedColor; + fg_color = (item->getEnabled() ? mFgSelectedColor : mFgDisabledColor); + } + else if (mHighlightedItem == line && mCanSelect) + { + bg_color = mHighlightedColor; + } + else + { + if (mDrawStripes && (line % 2 == 0) && (max_columns > 1)) + { + bg_color = mBgStripeColor; + } + } + + if (!item->getEnabled()) + { + bg_color = mBgReadOnlyColor; + } + + should_continue |= item->draw(pass, item_rect, fg_color, bg_color, highlight_color, mColumnPadding); } - - if (!item->getEnabled()) - { - bg_color = mBgReadOnlyColor; - } - - item->draw(item_rect, fg_color, bg_color, highlight_color, mColumnPadding); - - cur_y -= mLineHeight; } + done = !should_continue; } + } } diff --git a/indra/llui/llscrolllistitem.cpp b/indra/llui/llscrolllistitem.cpp index 3abe322a9..c490a5249 100644 --- a/indra/llui/llscrolllistitem.cpp +++ b/indra/llui/llscrolllistitem.cpp @@ -28,6 +28,7 @@ #include "linden_common.h" #include "llscrolllistitem.h" +#include "llview.h" //--------------------------------------------------------------------------- @@ -116,32 +117,73 @@ std::string LLScrollListItem::getContentsCSV() const } -void LLScrollListItem::draw(const LLRect& rect, const LLColor4& fg_color, const LLColor4& bg_color, const LLColor4& highlight_color, S32 column_padding) +bool LLScrollListItem::draw(const U32 pass, const LLRect& rect, const LLColor4& fg_color, const LLColor4& bg_color, const LLColor4& highlight_color, S32 column_padding) { + const U32 num_cols = (U32)getNumColumns(); + // draw background rect - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - LLRect bg_rect = rect; - gl_rect_2d( bg_rect, bg_color ); - - S32 cur_x = rect.mLeft; - S32 num_cols = getNumColumns(); - S32 cur_col = 0; - - for (LLScrollListCell* cell = getColumn(0); cur_col < num_cols; cell = getColumn(++cur_col)) + if (pass == 0) { - // Two ways a cell could be hidden - if (cell->getWidth() < 0 - || !cell->getVisible()) continue; - - LLUI::pushMatrix(); - { - LLUI::translate((F32) cur_x, (F32) rect.mBottom); - - cell->draw( fg_color, highlight_color ); - } - LLUI::popMatrix(); - - cur_x += cell->getWidth() + column_padding; + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + gl_rect_2d(rect, bg_color); + return true; } + // Draw column (pass - 1) + else if (pass <= num_cols) + { + LLScrollListCell* cur_cell = getColumn(pass - 1); + if (!cur_cell) + { + return false; + } + // Two ways a cell could be hidden + else if (cur_cell->getWidth() && cur_cell->getVisible()) + { + // Iterate over cells to the left and calculate offset. + S32 offset = rect.mLeft; + for (U32 i = 0; i < (pass - 1); ++i) + { + LLScrollListCell* cell = getColumn(i); + if (!cell) + { + return false; // Shouldn't happen. + } + if (cell->getVisible() && cell->getWidth()) + { + // Only apply padding if cell is visible and has width. + offset += cell->getWidth() + column_padding; + } + } + // Do not draw if not on screen. + // Only care about horizontal bounds. This draw call wont even occur if this row is entirely off screen. + LLRect clip_rect = LLUI::getRootView()->getRect(); + if (LLGLState::isEnabled()) + { + LLRect scissor = gGL.getScissor(); + scissor.mLeft /= LLUI::getScaleFactor().mV[VX]; + scissor.mTop /= LLUI::getScaleFactor().mV[VY]; + scissor.mRight /= LLUI::getScaleFactor().mV[VX]; + scissor.mBottom /= LLUI::getScaleFactor().mV[VY]; + clip_rect.intersectWith(scissor); + } + if (offset + LLFontGL::sCurOrigin.mX >= clip_rect.mRight) + { + // Went off the right edge of the screen. Don't bother with any more columns. + return false; + } + // Draw if not off the left edge of screen. If it is off the left edge, still return true if other colums remain. + if (offset + LLFontGL::sCurOrigin.mX + cur_cell->getWidth() > clip_rect.mLeft) + { + LLUI::pushMatrix(); + { + LLUI::translate((F32)offset, (F32)rect.mBottom); + cur_cell->draw(fg_color, highlight_color); + } + LLUI::popMatrix(); + } + } + return pass != getNumColumns(); + } + return false; } diff --git a/indra/llui/llscrolllistitem.h b/indra/llui/llscrolllistitem.h index 0d87a0fbf..a1229e034 100644 --- a/indra/llui/llscrolllistitem.h +++ b/indra/llui/llscrolllistitem.h @@ -92,7 +92,7 @@ public: std::string getContentsCSV() const; - virtual void draw(const LLRect& rect, const LLColor4& fg_color, const LLColor4& bg_color, const LLColor4& highlight_color, S32 column_padding); + virtual bool draw(const U32 pass, const LLRect& rect, const LLColor4& fg_color, const LLColor4& bg_color, const LLColor4& highlight_color, S32 column_padding); protected: LLScrollListItem( const Params& ); diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp index 8bae13aac..c983d3a84 100644 --- a/indra/llui/llview.cpp +++ b/indra/llui/llview.cpp @@ -1221,7 +1221,16 @@ void LLView::drawChildren() }*/ if (!mChildList.empty()) { - LLView* rootp = LLUI::getRootView(); + LLRect clip_rect = LLUI::getRootView()->getRect(); + if (LLGLState::isEnabled()) + { + LLRect scissor = gGL.getScissor(); + scissor.mLeft /= LLUI::getScaleFactor().mV[VX]; + scissor.mTop /= LLUI::getScaleFactor().mV[VY]; + scissor.mRight /= LLUI::getScaleFactor().mV[VX]; + scissor.mBottom /= LLUI::getScaleFactor().mV[VY]; + clip_rect.intersectWith(scissor); + } ++sDepth; for (child_list_const_reverse_iter_t child_iter = mChildList.rbegin(); child_iter != mChildList.rend(); ++child_iter) @@ -1235,10 +1244,13 @@ void LLView::drawChildren() if (viewp->getVisible() && /*viewp != focus_view && */viewp->getRect().isValid()) { // Only draw views that are within the root view - LLRect screen_rect = viewp->calcScreenRect(); - if ( rootp->getRect().overlaps(screen_rect) ) + // LLView::calcScreenRect not used due to scrolllist cells containing views that aren't inserted into the view heirarchy. + // Render-time offset is stored in LLFontGL::sCurOrigin, which is valid during the draw call chain (which this method is part of) + // Bonus: Reading LLFontGL::sCurOrigin is way (way way way) faster than calling LLView::calcScreenRect. + LLRect screen_rect = viewp->getRect(); + screen_rect.translate(LLFontGL::sCurOrigin.mX, LLFontGL::sCurOrigin.mY); + if ( clip_rect.overlaps(screen_rect) ) { - //gGL.matrixMode(LLRender::MM_MODELVIEW); LLUI::pushMatrix(); { LLUI::translate((F32)viewp->getRect().mLeft, (F32)viewp->getRect().mBottom, 0.f); @@ -1263,7 +1275,6 @@ void LLView::drawChildren() LLUI::popMatrix(); } } - } --sDepth; }