summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Linden <none@none>2010-07-23 22:07:15 -0700
committerRichard Linden <none@none>2010-07-23 22:07:15 -0700
commit6cc6f816780e64c5fb1e17a22fb5e473e75efe69 (patch)
tree0fb764971547fc3e8e8fad3ec7a1856b77fb1ac9
parent4d2daeed21dfba9d6a40e88ecd92aaaa6df92ae1 (diff)
first pass ui rendering performance improvements
-rw-r--r--indra/llrender/llfontfreetype.cpp6
-rw-r--r--indra/llrender/llfontfreetype.h4
-rw-r--r--indra/llrender/llfontgl.cpp195
-rw-r--r--indra/llrender/llfontgl.h4
-rw-r--r--indra/llrender/llrender.cpp97
-rw-r--r--indra/llrender/llrender.h8
-rw-r--r--indra/llui/lllocalcliprect.cpp42
-rw-r--r--indra/llui/lllocalcliprect.h26
-rw-r--r--indra/llui/lltextbase.cpp15
9 files changed, 242 insertions, 155 deletions
diff --git a/indra/llrender/llfontfreetype.cpp b/indra/llrender/llfontfreetype.cpp
index a86bbbffff..0a16b5120a 100644
--- a/indra/llrender/llfontfreetype.cpp
+++ b/indra/llrender/llfontfreetype.cpp
@@ -259,10 +259,10 @@ F32 LLFontFreetype::getXAdvance(llwchar wch) const
}
else
{
- gi = get_if_there(mCharGlyphInfoMap, (llwchar)0, (LLFontGlyphInfo*)NULL);
- if (gi)
+ char_glyph_info_map_t::iterator found_it = mCharGlyphInfoMap.find((llwchar)0);
+ if (found_it != mCharGlyphInfoMap.end())
{
- return gi->mXAdvance;
+ return found_it->second->mXAdvance;
}
}
diff --git a/indra/llrender/llfontfreetype.h b/indra/llrender/llfontfreetype.h
index f60d09316d..4b4a0bb189 100644
--- a/indra/llrender/llfontfreetype.h
+++ b/indra/llrender/llfontfreetype.h
@@ -33,7 +33,7 @@
#ifndef LL_LLFONTFREETYPE_H
#define LL_LLFONTFREETYPE_H
-#include <map>
+#include <boost/unordered_map.hpp>
#include "llpointer.h"
#include "llstl.h"
@@ -170,7 +170,7 @@ private:
BOOL mValid;
- typedef std::map<llwchar, LLFontGlyphInfo*> char_glyph_info_map_t;
+ typedef boost::unordered_map<llwchar, LLFontGlyphInfo*> char_glyph_info_map_t;
mutable char_glyph_info_map_t mCharGlyphInfoMap; // Information about glyph location in bitmap
mutable LLPointer<LLFontBitmapCache> mFontBitmapCachep;
diff --git a/indra/llrender/llfontgl.cpp b/indra/llrender/llfontgl.cpp
index 6eb5e0eff4..c0297eae3e 100644
--- a/indra/llrender/llfontgl.cpp
+++ b/indra/llrender/llfontgl.cpp
@@ -181,12 +181,17 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
gGL.loadUIIdentity();
- gGL.translateUI(floorf(sCurOrigin.mX*sScaleX), floorf(sCurOrigin.mY*sScaleY), sCurOrigin.mZ);
+ //gGL.translateUI(floorf(sCurOrigin.mX*sScaleX), floorf(sCurOrigin.mY*sScaleY), sCurOrigin.mZ);
// this code snaps the text origin to a pixel grid to start with
- F32 pixel_offset_x = llround((F32)sCurOrigin.mX) - (sCurOrigin.mX);
- F32 pixel_offset_y = llround((F32)sCurOrigin.mY) - (sCurOrigin.mY);
- gGL.translateUI(-pixel_offset_x, -pixel_offset_y, 0.f);
+ //F32 pixel_offset_x = llround((F32)sCurOrigin.mX) - (sCurOrigin.mX);
+ //F32 pixel_offset_y = llround((F32)sCurOrigin.mY) - (sCurOrigin.mY);
+ //gGL.translateUI(-pixel_offset_x, -pixel_offset_y, 0.f);
+
+ LLVector2 origin(floorf(sCurOrigin.mX*sScaleX), floorf(sCurOrigin.mY*sScaleY));
+ // snap the text origin to a pixel grid to start with
+ origin.mV[VX] -= llround((F32)sCurOrigin.mX) - (sCurOrigin.mX);
+ origin.mV[VY] -= llround((F32)sCurOrigin.mY) - (sCurOrigin.mY);
LLFastTimer t(FTM_RENDER_FONTS);
@@ -210,8 +215,8 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
// Not guaranteed to be set correctly
gGL.setSceneBlendType(LLRender::BT_ALPHA);
- cur_x = ((F32)x * sScaleX);
- cur_y = ((F32)y * sScaleY);
+ cur_x = ((F32)x * sScaleX) + origin.mV[VX];
+ cur_y = ((F32)y * sScaleY) + origin.mV[VY];
// Offset y by vertical alignment.
switch (valign)
@@ -276,6 +281,12 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
const LLFontGlyphInfo* next_glyph = NULL;
+ const S32 GLYPH_BATCH_SIZE = 30;
+ LLVector3 vertices[GLYPH_BATCH_SIZE * 4];
+ LLVector2 uvs[GLYPH_BATCH_SIZE * 4];
+ LLColor4U colors[GLYPH_BATCH_SIZE * 4];
+
+ S32 glyph_count = 0;
for (i = begin_offset; i < begin_offset + length; i++)
{
llwchar wch = wstr[i];
@@ -313,7 +324,18 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
llround(cur_render_x + (F32)fgi->mXBearing) + (F32)fgi->mWidth,
llround(cur_render_y + (F32)fgi->mYBearing) - (F32)fgi->mHeight);
- drawGlyph(screen_rect, uv_rect, color, style_to_add, shadow, drop_shadow_strength);
+ if (glyph_count >= GLYPH_BATCH_SIZE)
+ {
+ gGL.begin(LLRender::QUADS);
+ {
+ gGL.vertexBatchPreTransformed(vertices, uvs, colors, glyph_count * 4);
+ }
+ gGL.end();
+
+ glyph_count = 0;
+ }
+
+ drawGlyph(glyph_count, vertices, uvs, colors, screen_rect, uv_rect, color, style_to_add, shadow, drop_shadow_strength);
chars_drawn++;
cur_x += fgi->mXAdvance;
@@ -338,11 +360,19 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
cur_render_y = cur_y;
}
+ gGL.begin(LLRender::QUADS);
+ {
+ gGL.vertexBatchPreTransformed(vertices, uvs, colors, glyph_count * 4);
+ }
+ gGL.end();
+
+
if (right_x)
{
*right_x = cur_x / sScaleX;
}
+ //FIXME: add underline as glyph?
if (style_to_add & UNDERLINE)
{
F32 descender = mFontFreetype->getDescenderHeight();
@@ -1091,95 +1121,96 @@ LLFontGL &LLFontGL::operator=(const LLFontGL &source)
return *this;
}
-void LLFontGL::renderQuad(const LLRectf& screen_rect, const LLRectf& uv_rect, F32 slant_amt) const
+void LLFontGL::renderQuad(LLVector3* vertex_out, LLVector2* uv_out, LLColor4U* colors_out, const LLRectf& screen_rect, const LLRectf& uv_rect, const LLColor4U& color, F32 slant_amt) const
{
- gGL.texCoord2f(uv_rect.mRight, uv_rect.mTop);
- gGL.vertex2f(llfont_round_x(screen_rect.mRight),
- llfont_round_y(screen_rect.mTop));
-
- gGL.texCoord2f(uv_rect.mLeft, uv_rect.mTop);
- gGL.vertex2f(llfont_round_x(screen_rect.mLeft),
- llfont_round_y(screen_rect.mTop));
-
- gGL.texCoord2f(uv_rect.mLeft, uv_rect.mBottom);
- gGL.vertex2f(llfont_round_x(screen_rect.mLeft + slant_amt),
- llfont_round_y(screen_rect.mBottom));
-
- gGL.texCoord2f(uv_rect.mRight, uv_rect.mBottom);
- gGL.vertex2f(llfont_round_x(screen_rect.mRight + slant_amt),
- llfont_round_y(screen_rect.mBottom));
+ S32 index = 0;
+
+ vertex_out[index] = LLVector3(llfont_round_x(screen_rect.mRight), llfont_round_y(screen_rect.mTop), 0.f);
+ uv_out[index] = LLVector2(uv_rect.mRight, uv_rect.mTop);
+ colors_out[index] = color;
+ index++;
+
+ vertex_out[index] = LLVector3(llfont_round_x(screen_rect.mLeft), llfont_round_y(screen_rect.mTop), 0.f);
+ uv_out[index] = LLVector2(uv_rect.mLeft, uv_rect.mTop);
+ colors_out[index] = color;
+ index++;
+
+ vertex_out[index] = LLVector3(llfont_round_x(screen_rect.mLeft), llfont_round_y(screen_rect.mBottom), 0.f);
+ uv_out[index] = LLVector2(uv_rect.mLeft, uv_rect.mBottom);
+ colors_out[index] = color;
+ index++;
+
+ vertex_out[index] = LLVector3(llfont_round_x(screen_rect.mRight), llfont_round_y(screen_rect.mBottom), 0.f);
+ uv_out[index] = LLVector2(uv_rect.mRight, uv_rect.mBottom);
+ colors_out[index] = color;
}
-void LLFontGL::drawGlyph(const LLRectf& screen_rect, const LLRectf& uv_rect, const LLColor4& color, U8 style, ShadowType shadow, F32 drop_shadow_strength) const
+//FIXME: do colors out as well
+void LLFontGL::drawGlyph(S32& glyph_count, LLVector3* vertex_out, LLVector2* uv_out, LLColor4U* colors_out, const LLRectf& screen_rect, const LLRectf& uv_rect, const LLColor4U& color, U8 style, ShadowType shadow, F32 drop_shadow_strength) const
{
F32 slant_offset;
slant_offset = ((style & ITALIC) ? ( -mFontFreetype->getAscenderHeight() * 0.2f) : 0.f);
- gGL.begin(LLRender::QUADS);
+ //FIXME: bold and drop shadow are mutually exclusive only for convenience
+ //Allow both when we need them.
+ if (style & BOLD)
{
- //FIXME: bold and drop shadow are mutually exclusive only for convenience
- //Allow both when we need them.
- if (style & BOLD)
+ for (S32 pass = 0; pass < 2; pass++)
{
- gGL.color4fv(color.mV);
- for (S32 pass = 0; pass < 2; pass++)
- {
- LLRectf screen_rect_offset = screen_rect;
+ LLRectf screen_rect_offset = screen_rect;
- screen_rect_offset.translate((F32)(pass * BOLD_OFFSET), 0.f);
- renderQuad(screen_rect_offset, uv_rect, slant_offset);
- }
+ screen_rect_offset.translate((F32)(pass * BOLD_OFFSET), 0.f);
+ renderQuad(&vertex_out[glyph_count * 4], &uv_out[glyph_count * 4], &colors_out[glyph_count * 4], screen_rect_offset, uv_rect, color, slant_offset);
+ glyph_count++;
}
- else if (shadow == DROP_SHADOW_SOFT)
+ }
+ else if (shadow == DROP_SHADOW_SOFT)
+ {
+ LLColor4U shadow_color = LLFontGL::sShadowColor;
+ shadow_color.mV[VALPHA] = color.mV[VALPHA] * drop_shadow_strength * DROP_SHADOW_SOFT_STRENGTH;
+ for (S32 pass = 0; pass < 5; pass++)
{
- LLColor4 shadow_color = LLFontGL::sShadowColor;
- shadow_color.mV[VALPHA] = color.mV[VALPHA] * drop_shadow_strength * DROP_SHADOW_SOFT_STRENGTH;
- gGL.color4fv(shadow_color.mV);
- for (S32 pass = 0; pass < 5; pass++)
- {
- LLRectf screen_rect_offset = screen_rect;
+ LLRectf screen_rect_offset = screen_rect;
- switch(pass)
- {
- case 0:
- screen_rect_offset.translate(-1.f, -1.f);
- break;
- case 1:
- screen_rect_offset.translate(1.f, -1.f);
- break;
- case 2:
- screen_rect_offset.translate(1.f, 1.f);
- break;
- case 3:
- screen_rect_offset.translate(-1.f, 1.f);
- break;
- case 4:
- screen_rect_offset.translate(0, -2.f);
- break;
- }
-
- renderQuad(screen_rect_offset, uv_rect, slant_offset);
+ switch(pass)
+ {
+ case 0:
+ screen_rect_offset.translate(-1.f, -1.f);
+ break;
+ case 1:
+ screen_rect_offset.translate(1.f, -1.f);
+ break;
+ case 2:
+ screen_rect_offset.translate(1.f, 1.f);
+ break;
+ case 3:
+ screen_rect_offset.translate(-1.f, 1.f);
+ break;
+ case 4:
+ screen_rect_offset.translate(0, -2.f);
+ break;
}
- gGL.color4fv(color.mV);
- renderQuad(screen_rect, uv_rect, slant_offset);
- }
- else if (shadow == DROP_SHADOW)
- {
- LLColor4 shadow_color = LLFontGL::sShadowColor;
- shadow_color.mV[VALPHA] = color.mV[VALPHA] * drop_shadow_strength;
- gGL.color4fv(shadow_color.mV);
- LLRectf screen_rect_shadow = screen_rect;
- screen_rect_shadow.translate(1.f, -1.f);
- renderQuad(screen_rect_shadow, uv_rect, slant_offset);
- gGL.color4fv(color.mV);
- renderQuad(screen_rect, uv_rect, slant_offset);
- }
- else // normal rendering
- {
- gGL.color4fv(color.mV);
- renderQuad(screen_rect, uv_rect, slant_offset);
+
+ renderQuad(&vertex_out[glyph_count * 4], &uv_out[glyph_count * 4], &colors_out[glyph_count * 4], screen_rect_offset, uv_rect, shadow_color, slant_offset);
+ glyph_count++;
}
-
+ renderQuad(&vertex_out[glyph_count * 4], &uv_out[glyph_count * 4], &colors_out[glyph_count * 4], screen_rect, uv_rect, color, slant_offset);
+ glyph_count++;
+ }
+ else if (shadow == DROP_SHADOW)
+ {
+ LLColor4 shadow_color = LLFontGL::sShadowColor;
+ shadow_color.mV[VALPHA] = color.mV[VALPHA] * drop_shadow_strength;
+ LLRectf screen_rect_shadow = screen_rect;
+ screen_rect_shadow.translate(1.f, -1.f);
+ renderQuad(&vertex_out[glyph_count * 4], &uv_out[glyph_count * 4], &colors_out[glyph_count * 4], screen_rect_shadow, uv_rect, shadow_color, slant_offset);
+ glyph_count++;
+ renderQuad(&vertex_out[glyph_count * 4], &uv_out[glyph_count * 4], &colors_out[glyph_count * 4], screen_rect, uv_rect, color, slant_offset);
+ glyph_count++;
+ }
+ else // normal rendering
+ {
+ renderQuad(&vertex_out[glyph_count * 4], &uv_out[glyph_count * 4], &colors_out[glyph_count * 4], screen_rect, uv_rect, color, slant_offset);
+ glyph_count++;
}
- gGL.end();
}
diff --git a/indra/llrender/llfontgl.h b/indra/llrender/llfontgl.h
index f29ac5165c..8bc45fbf74 100644
--- a/indra/llrender/llfontgl.h
+++ b/indra/llrender/llfontgl.h
@@ -217,8 +217,8 @@ private:
LLFontDescriptor mFontDescriptor;
LLPointer<LLFontFreetype> mFontFreetype;
- void renderQuad(const LLRectf& screen_rect, const LLRectf& uv_rect, F32 slant_amt) const;
- void drawGlyph(const LLRectf& screen_rect, const LLRectf& uv_rect, const LLColor4& color, U8 style, ShadowType shadow, F32 drop_shadow_fade) const;
+ void renderQuad(LLVector3* vertex_out, LLVector2* uv_out, LLColor4U* colors_out, const LLRectf& screen_rect, const LLRectf& uv_rect, const LLColor4U& color, F32 slant_amt) const;
+ void drawGlyph(S32& glyph_count, LLVector3* vertex_out, LLVector2* uv_out, LLColor4U* colors_out, const LLRectf& screen_rect, const LLRectf& uv_rect, const LLColor4U& color, U8 style, ShadowType shadow, F32 drop_shadow_fade) const;
// Registry holds all instantiated fonts.
static LLFontRegistry* sFontRegistry;
diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp
index 5597b23c69..64238b2008 100644
--- a/indra/llrender/llrender.cpp
+++ b/indra/llrender/llrender.cpp
@@ -851,9 +851,9 @@ void LLRender::translateUI(F32 x, F32 y, F32 z)
llerrs << "Need to push a UI translation frame before offsetting" << llendl;
}
- mUIOffset.front().mV[0] += x;
- mUIOffset.front().mV[1] += y;
- mUIOffset.front().mV[2] += z;
+ mUIOffset.back().mV[0] += x;
+ mUIOffset.back().mV[1] += y;
+ mUIOffset.back().mV[2] += z;
}
void LLRender::scaleUI(F32 x, F32 y, F32 z)
@@ -863,27 +863,27 @@ void LLRender::scaleUI(F32 x, F32 y, F32 z)
llerrs << "Need to push a UI transformation frame before scaling." << llendl;
}
- mUIScale.front().scaleVec(LLVector3(x,y,z));
+ mUIScale.back().scaleVec(LLVector3(x,y,z));
}
void LLRender::pushUIMatrix()
{
if (mUIOffset.empty())
{
- mUIOffset.push_front(LLVector3(0,0,0));
+ mUIOffset.push_back(LLVector3(0,0,0));
}
else
{
- mUIOffset.push_front(mUIOffset.front());
+ mUIOffset.push_back(mUIOffset.back());
}
if (mUIScale.empty())
{
- mUIScale.push_front(LLVector3(1,1,1));
+ mUIScale.push_back(LLVector3(1,1,1));
}
else
{
- mUIScale.push_front(mUIScale.front());
+ mUIScale.push_back(mUIScale.back());
}
}
@@ -893,8 +893,8 @@ void LLRender::popUIMatrix()
{
llerrs << "UI offset stack blown." << llendl;
}
- mUIOffset.pop_front();
- mUIScale.pop_front();
+ mUIOffset.pop_back();
+ mUIScale.pop_back();
}
LLVector3 LLRender::getUITranslation()
@@ -903,7 +903,7 @@ LLVector3 LLRender::getUITranslation()
{
llerrs << "UI offset stack empty." << llendl;
}
- return mUIOffset.front();
+ return mUIOffset.back();
}
LLVector3 LLRender::getUIScale()
@@ -912,7 +912,7 @@ LLVector3 LLRender::getUIScale()
{
llerrs << "UI scale stack empty." << llendl;
}
- return mUIScale.front();
+ return mUIScale.back();
}
@@ -922,8 +922,8 @@ void LLRender::loadUIIdentity()
{
llerrs << "Need to push UI translation frame before clearing offset." << llendl;
}
- mUIOffset.front().setVec(0,0,0);
- mUIScale.front().setVec(1,1,1);
+ mUIOffset.back().setVec(0,0,0);
+ mUIScale.back().setVec(1,1,1);
}
void LLRender::setColorMask(bool writeColor, bool writeAlpha)
@@ -1210,18 +1210,79 @@ void LLRender::vertex3f(const GLfloat& x, const GLfloat& y, const GLfloat& z)
}
else
{
- LLVector3 vert = (LLVector3(x,y,z)+mUIOffset.front()).scaledVec(mUIScale.front());
+ LLVector3 vert = (LLVector3(x,y,z)+mUIOffset.back()).scaledVec(mUIScale.back());
mVerticesp[mCount] = vert;
}
mCount++;
- if (mCount < 4096)
+ mVerticesp[mCount] = mVerticesp[mCount-1];
+ mColorsp[mCount] = mColorsp[mCount-1];
+ mTexcoordsp[mCount] = mTexcoordsp[mCount-1];
+}
+
+void LLRender::vertexBatchPreTransformed(LLVector3* verts, S32 vert_count)
+{
+ if (mCount + vert_count > 4094)
{
- mVerticesp[mCount] = mVerticesp[mCount-1];
- mColorsp[mCount] = mColorsp[mCount-1];
+ // llwarns << "GL immediate mode overflow. Some geometry not drawn." << llendl;
+ return;
+ }
+
+ for (S32 i = 0; i < vert_count; i++)
+ {
+ mVerticesp[mCount] = verts[i];
+
+ mCount++;
mTexcoordsp[mCount] = mTexcoordsp[mCount-1];
+ mColorsp[mCount] = mColorsp[mCount-1];
}
+
+ mVerticesp[mCount] = mVerticesp[mCount-1];
}
+
+void LLRender::vertexBatchPreTransformed(LLVector3* verts, LLVector2* uvs, S32 vert_count)
+{
+ if (mCount + vert_count > 4094)
+ {
+ // llwarns << "GL immediate mode overflow. Some geometry not drawn." << llendl;
+ return;
+ }
+
+ for (S32 i = 0; i < vert_count; i++)
+ {
+ mVerticesp[mCount] = verts[i];
+ mTexcoordsp[mCount] = uvs[i];
+
+ mCount++;
+ mColorsp[mCount] = mColorsp[mCount-1];
+ }
+
+ mVerticesp[mCount] = mVerticesp[mCount-1];
+ mTexcoordsp[mCount] = mTexcoordsp[mCount-1];
+}
+
+void LLRender::vertexBatchPreTransformed(LLVector3* verts, LLVector2* uvs, LLColor4U* colors, S32 vert_count)
+{
+ if (mCount + vert_count > 4094)
+ {
+ // llwarns << "GL immediate mode overflow. Some geometry not drawn." << llendl;
+ return;
+ }
+
+ for (S32 i = 0; i < vert_count; i++)
+ {
+ mVerticesp[mCount] = verts[i];
+ mTexcoordsp[mCount] = uvs[i];
+ mColorsp[mCount] = colors[i];
+
+ mCount++;
+ }
+
+ mVerticesp[mCount] = mVerticesp[mCount-1];
+ mTexcoordsp[mCount] = mTexcoordsp[mCount-1];
+ mColorsp[mCount] = mColorsp[mCount-1];
+}
+
void LLRender::vertex2i(const GLint& x, const GLint& y)
{
vertex3f((GLfloat) x, (GLfloat) y, 0);
diff --git a/indra/llrender/llrender.h b/indra/llrender/llrender.h
index f6c87aa1db..0fa503182e 100644
--- a/indra/llrender/llrender.h
+++ b/indra/llrender/llrender.h
@@ -317,6 +317,10 @@ public:
void color3fv(const GLfloat* c);
void color4ubv(const GLubyte* c);
+ void vertexBatchPreTransformed(LLVector3* verts, S32 vert_count);
+ void vertexBatchPreTransformed(LLVector3* verts, LLVector2* uvs, S32 vert_count);
+ void vertexBatchPreTransformed(LLVector3* verts, LLVector2* uvs, LLColor4U*, S32 vert_count);
+
void setColorMask(bool writeColor, bool writeAlpha);
void setColorMask(bool writeColorR, bool writeColorG, bool writeColorB, bool writeAlpha);
void setSceneBlendType(eBlendType type);
@@ -373,8 +377,8 @@ private:
F32 mMaxAnisotropy;
- std::list<LLVector3> mUIOffset;
- std::list<LLVector3> mUIScale;
+ std::vector<LLVector3> mUIOffset;
+ std::vector<LLVector3> mUIScale;
};
diff --git a/indra/llui/lllocalcliprect.cpp b/indra/llui/lllocalcliprect.cpp
index 43c21e250c..55329f64e4 100644
--- a/indra/llui/lllocalcliprect.cpp
+++ b/indra/llui/lllocalcliprect.cpp
@@ -33,33 +33,8 @@
#include "lllocalcliprect.h"
#include "llfontgl.h"
-#include "llgl.h"
#include "llui.h"
-#include <stack>
-
-//---------------------------------------------------------------------------
-// LLScreenClipRect
-// implementation class in screen space
-//---------------------------------------------------------------------------
-class LLScreenClipRect
-{
-public:
- LLScreenClipRect(const LLRect& rect, BOOL enabled = TRUE);
- virtual ~LLScreenClipRect();
-
-private:
- static void pushClipRect(const LLRect& rect);
- static void popClipRect();
- static void updateScissorRegion();
-
-private:
- LLGLState mScissorState;
- BOOL mEnabled;
-
- static std::stack<LLRect> sClipRectStack;
-};
-
/*static*/ std::stack<LLRect> LLScreenClipRect::sClipRectStack;
@@ -131,16 +106,11 @@ void LLScreenClipRect::updateScissorRegion()
// LLLocalClipRect
//---------------------------------------------------------------------------
LLLocalClipRect::LLLocalClipRect(const LLRect& rect, BOOL enabled /* = TRUE */)
-{
- LLRect screen(rect.mLeft + LLFontGL::sCurOrigin.mX,
- rect.mTop + LLFontGL::sCurOrigin.mY,
- rect.mRight + LLFontGL::sCurOrigin.mX,
- rect.mBottom + LLFontGL::sCurOrigin.mY);
- mScreenClipRect = new LLScreenClipRect(screen, enabled);
-}
+: LLScreenClipRect(LLRect(rect.mLeft + LLFontGL::sCurOrigin.mX,
+ rect.mTop + LLFontGL::sCurOrigin.mY,
+ rect.mRight + LLFontGL::sCurOrigin.mX,
+ rect.mBottom + LLFontGL::sCurOrigin.mY), enabled)
+{}
LLLocalClipRect::~LLLocalClipRect()
-{
- delete mScreenClipRect;
- mScreenClipRect = NULL;
-}
+{}
diff --git a/indra/llui/lllocalcliprect.h b/indra/llui/lllocalcliprect.h
index cd0c55ca72..36413f1496 100644
--- a/indra/llui/lllocalcliprect.h
+++ b/indra/llui/lllocalcliprect.h
@@ -31,7 +31,9 @@
#ifndef LLLOCALCLIPRECT_H
#define LLLOCALCLIPRECT_H
+#include "llgl.h"
#include "llrect.h" // can't forward declare, it's templated
+#include <stack>
// Clip rendering to a specific rectangle using GL scissor
// Just create one of these on the stack:
@@ -39,15 +41,29 @@
// LLLocalClipRect(rect);
// draw();
// }
-class LLLocalClipRect
+class LLScreenClipRect
{
public:
- LLLocalClipRect(const LLRect& rect, BOOL enabled = TRUE);
- ~LLLocalClipRect();
+ LLScreenClipRect(const LLRect& rect, BOOL enabled = TRUE);
+ virtual ~LLScreenClipRect();
+
+private:
+ static void pushClipRect(const LLRect& rect);
+ static void popClipRect();
+ static void updateScissorRegion();
private:
- // implementation class
- class LLScreenClipRect* mScreenClipRect;
+ LLGLState mScissorState;
+ BOOL mEnabled;
+
+ static std::stack<LLRect> sClipRectStack;
+};
+
+class LLLocalClipRect : public LLScreenClipRect
+{
+public:
+ LLLocalClipRect(const LLRect& rect, BOOL enabled = TRUE);
+ ~LLLocalClipRect();
};
#endif
diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp
index 617c496d6a..0587b3f48d 100644
--- a/indra/llui/lltextbase.cpp
+++ b/indra/llui/lltextbase.cpp
@@ -1012,22 +1012,25 @@ void LLTextBase::draw()
if (mBGVisible)
{
// clip background rect against extents, if we support scrolling
- LLLocalClipRect clip(doc_rect, mScroller != NULL);
-
+ LLRect bg_rect = mVisibleTextRect;
+ if (mScroller)
+ {
+ bg_rect.intersectWith(doc_rect);
+ }
LLColor4 bg_color = mReadOnly
? mReadOnlyBgColor.get()
: hasFocus()
? mFocusBgColor.get()
: mWriteableBgColor.get();
- gl_rect_2d(mVisibleTextRect, bg_color, TRUE);
+ gl_rect_2d(doc_rect, bg_color, TRUE);
}
// draw document view
LLUICtrl::draw();
{
- // only clip if we support scrolling (mScroller != NULL)
- LLLocalClipRect clip(doc_rect, mScroller != NULL);
+ // only clip if we support scrolling or have word wrap turned off
+ LLLocalClipRect clip(doc_rect, !getWordWrap() || mScroller != NULL);
drawSelectionBackground();
drawText();
drawCursor();
@@ -1495,6 +1498,7 @@ LLTextBase::segment_set_t::iterator LLTextBase::getSegIterContaining(S32 index)
// when there are no segments, we return the end iterator, which must be checked by caller
if (mSegments.size() <= 1) { return mSegments.begin(); }
+ //FIXME: avoid operator new somehow (without running into refcount problems)
segment_set_t::iterator it = mSegments.upper_bound(new LLIndexSegment(index));
return it;
}
@@ -2269,6 +2273,7 @@ void LLTextBase::updateRects()
// allow horizontal scrolling?
// if so, use entire width of text contents
// otherwise, stop at width of mVisibleTextRect
+ //FIXME: consider use of getWordWrap() instead
doc_rect.mRight = mScroller
? llmax(mVisibleTextRect.getWidth(), mTextBoundingRect.mRight)
: mVisibleTextRect.getWidth();