summaryrefslogtreecommitdiff
path: root/indra/llrender
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 /indra/llrender
parent4d2daeed21dfba9d6a40e88ecd92aaaa6df92ae1 (diff)
first pass ui rendering performance improvements
Diffstat (limited to 'indra/llrender')
-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
6 files changed, 205 insertions, 109 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;
};