summaryrefslogtreecommitdiff
path: root/indra/llrender
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llrender')
-rw-r--r--indra/llrender/llfontfreetype.cpp23
-rw-r--r--indra/llrender/llfontfreetype.h2
-rw-r--r--indra/llrender/llfontgl.cpp85
-rw-r--r--indra/llrender/llrender.cpp131
-rw-r--r--indra/llrender/llrender.h23
5 files changed, 219 insertions, 45 deletions
diff --git a/indra/llrender/llfontfreetype.cpp b/indra/llrender/llfontfreetype.cpp
index 22fad792da..a86bbbffff 100644
--- a/indra/llrender/llfontfreetype.cpp
+++ b/indra/llrender/llfontfreetype.cpp
@@ -270,6 +270,14 @@ F32 LLFontFreetype::getXAdvance(llwchar wch) const
return (F32)mFontBitmapCachep->getMaxCharWidth();
}
+F32 LLFontFreetype::getXAdvance(const LLFontGlyphInfo* glyph) const
+{
+ if (mFTFace == NULL)
+ return 0.0;
+
+ return glyph->mXAdvance;
+}
+
F32 LLFontFreetype::getXKerning(llwchar char_left, llwchar char_right) const
{
if (mFTFace == NULL)
@@ -289,6 +297,21 @@ F32 LLFontFreetype::getXKerning(llwchar char_left, llwchar char_right) const
return delta.x*(1.f/64.f);
}
+F32 LLFontFreetype::getXKerning(const LLFontGlyphInfo* left_glyph_info, const LLFontGlyphInfo* right_glyph_info) const
+{
+ if (mFTFace == NULL)
+ return 0.0;
+
+ U32 left_glyph = left_glyph_info ? left_glyph_info->mGlyphIndex : 0;
+ U32 right_glyph = right_glyph_info ? right_glyph_info->mGlyphIndex : 0;
+
+ FT_Vector delta;
+
+ llverify(!FT_Get_Kerning(mFTFace, left_glyph, right_glyph, ft_kerning_unfitted, &delta));
+
+ return delta.x*(1.f/64.f);
+}
+
BOOL LLFontFreetype::hasGlyph(llwchar wch) const
{
llassert(!mIsFallback);
diff --git a/indra/llrender/llfontfreetype.h b/indra/llrender/llfontfreetype.h
index 7a5d029038..f60d09316d 100644
--- a/indra/llrender/llfontfreetype.h
+++ b/indra/llrender/llfontfreetype.h
@@ -128,7 +128,9 @@ public:
};
F32 getXAdvance(llwchar wc) const;
+ F32 getXAdvance(const LLFontGlyphInfo* glyph) const;
F32 getXKerning(llwchar char_left, llwchar char_right) const; // Get the kerning between the two characters
+ F32 getXKerning(const LLFontGlyphInfo* left_glyph_info, const LLFontGlyphInfo* right_glyph_info) const; // Get the kerning between the two characters
LLFontGlyphInfo* getGlyphInfo(llwchar wch) const;
diff --git a/indra/llrender/llfontgl.cpp b/indra/llrender/llfontgl.cpp
index b6a6b448ee..768f042e69 100644
--- a/indra/llrender/llfontgl.cpp
+++ b/indra/llrender/llfontgl.cpp
@@ -151,14 +151,16 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
}
}
- gGL.pushMatrix();
- glLoadIdentity();
- gGL.translatef(floorf(sCurOrigin.mX*sScaleX), floorf(sCurOrigin.mY*sScaleY), sCurOrigin.mZ);
+ gGL.pushUIMatrix();
+
+ gGL.loadUIIdentity();
+
+ 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.translatef(-pixel_offset_x, -pixel_offset_y, 0.f);
+ gGL.translateUI(-pixel_offset_x, -pixel_offset_y, 0.f);
LLFastTimer t(FTM_RENDER_FONTS);
@@ -246,14 +248,18 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
}
- // Remember last-used texture to avoid unnecesssary bind calls.
- LLImageGL *last_bound_texture = NULL;
+ const LLFontGlyphInfo* next_glyph = NULL;
for (i = begin_offset; i < begin_offset + length; i++)
{
llwchar wch = wstr[i];
- const LLFontGlyphInfo* fgi= mFontFreetype->getGlyphInfo(wch);
+ const LLFontGlyphInfo* fgi = next_glyph;
+ next_glyph = NULL;
+ if(!fgi)
+ {
+ fgi = mFontFreetype->getGlyphInfo(wch);
+ }
if (!fgi)
{
llerrs << "Missing Glyph Info" << llendl;
@@ -261,12 +267,8 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
}
// Per-glyph bitmap texture.
LLImageGL *image_gl = mFontFreetype->getFontBitmapCache()->getImageGL(fgi->mBitmapNum);
- if (last_bound_texture != image_gl)
- {
- gGL.getTexUnit(0)->bind(image_gl);
- last_bound_texture = image_gl;
- }
-
+ gGL.getTexUnit(0)->bind(image_gl);
+
if ((start_x + scaled_max_pixels) < (cur_x + fgi->mXBearing + fgi->mWidth))
{
// Not enough room for this character.
@@ -295,7 +297,8 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
if (next_char && (next_char < LAST_CHARACTER))
{
// Kern this puppy.
- cur_x += mFontFreetype->getXKerning(wch, next_char);
+ next_glyph = mFontFreetype->getGlyphInfo(next_char);
+ cur_x += mFontFreetype->getXKerning(fgi, next_glyph);
}
// Round after kerning.
@@ -330,10 +333,7 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
// recursively render ellipses at end of string
// we've already reserved enough room
- gGL.pushMatrix();
- //glLoadIdentity();
- //gGL.translatef(sCurOrigin.mX, sCurOrigin.mY, 0.0f);
- //glScalef(sScaleX, sScaleY, 1.f);
+ gGL.pushUIMatrix();
renderUTF8(std::string("..."),
0,
cur_x / sScaleX, (F32)y,
@@ -344,10 +344,10 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
S32_MAX, max_pixels,
right_x,
FALSE);
- gGL.popMatrix();
+ gGL.popUIMatrix();
}
- gGL.popMatrix();
+ gGL.popUIMatrix();
return chars_drawn;
}
@@ -435,14 +435,21 @@ F32 LLFontGL::getWidthF32(const llwchar* wchars, S32 begin_offset, S32 max_chars
F32 cur_x = 0;
const S32 max_index = begin_offset + max_chars;
+ const LLFontGlyphInfo* next_glyph = NULL;
+
F32 width_padding = 0.f;
for (S32 i = begin_offset; i < max_index && wchars[i] != 0; i++)
{
llwchar wch = wchars[i];
- const LLFontGlyphInfo* fgi= mFontFreetype->getGlyphInfo(wch);
+ const LLFontGlyphInfo* fgi = next_glyph;
+ next_glyph = NULL;
+ if(!fgi)
+ {
+ fgi = mFontFreetype->getGlyphInfo(wch);
+ }
- F32 advance = mFontFreetype->getXAdvance(wch);
+ F32 advance = mFontFreetype->getXAdvance(fgi);
// for the last character we want to measure the greater of its width and xadvance values
// so keep track of the difference between these values for the each character we measure
@@ -459,7 +466,8 @@ F32 LLFontGL::getWidthF32(const llwchar* wchars, S32 begin_offset, S32 max_chars
&& (next_char < LAST_CHARACTER))
{
// Kern this puppy.
- cur_x += mFontFreetype->getXKerning(wch, next_char);
+ next_glyph = mFontFreetype->getGlyphInfo(next_char);
+ cur_x += mFontFreetype->getXKerning(fgi, next_glyph);
}
// Round after kerning.
cur_x = (F32)llround(cur_x);
@@ -492,6 +500,8 @@ S32 LLFontGL::maxDrawableChars(const llwchar* wchars, F32 max_pixels, S32 max_ch
// avoid S32 overflow when max_pixels == S32_MAX by staying in floating point
F32 scaled_max_pixels = ceil(max_pixels * sScaleX);
F32 width_padding = 0.f;
+
+ LLFontGlyphInfo* next_glyph = NULL;
S32 i;
for (i=0; (i < max_chars); i++)
@@ -534,8 +544,13 @@ S32 LLFontGL::maxDrawableChars(const llwchar* wchars, F32 max_pixels, S32 max_ch
in_word = TRUE;
}
}
-
- LLFontGlyphInfo* fgi = mFontFreetype->getGlyphInfo(wch);
+
+ LLFontGlyphInfo* fgi = next_glyph;
+ next_glyph = NULL;
+ if(!fgi)
+ {
+ fgi = mFontFreetype->getGlyphInfo(wch);
+ }
// account for glyphs that run beyond the starting point for the next glyphs
width_padding = llmax( 0.f, // always use positive padding amount
@@ -554,7 +569,8 @@ S32 LLFontGL::maxDrawableChars(const llwchar* wchars, F32 max_pixels, S32 max_ch
if (((i+1) < max_chars) && wchars[i+1])
{
// Kern this puppy.
- cur_x += mFontFreetype->getXKerning(wch, wchars[i+1]);
+ next_glyph = mFontFreetype->getGlyphInfo(wchars[i+1]);
+ cur_x += mFontFreetype->getXKerning(fgi, next_glyph);
}
// Round after kerning.
@@ -660,6 +676,8 @@ S32 LLFontGL::charFromPixelOffset(const llwchar* wchars, S32 begin_offset, F32 t
const S32 max_index = begin_offset + llmin(S32_MAX - begin_offset, max_chars);
F32 scaled_max_pixels = max_pixels * sScaleX;
+
+ const LLFontGlyphInfo* next_glyph = NULL;
S32 pos;
for (pos = begin_offset; pos < max_index; pos++)
@@ -669,7 +687,15 @@ S32 LLFontGL::charFromPixelOffset(const llwchar* wchars, S32 begin_offset, F32 t
{
break; // done
}
- F32 char_width = mFontFreetype->getXAdvance(wch);
+
+ const LLFontGlyphInfo* glyph = next_glyph;
+ next_glyph = NULL;
+ if(!glyph)
+ {
+ glyph = mFontFreetype->getGlyphInfo(wch);
+ }
+
+ F32 char_width = mFontFreetype->getXAdvance(glyph);
if (round)
{
@@ -695,11 +721,12 @@ S32 LLFontGL::charFromPixelOffset(const llwchar* wchars, S32 begin_offset, F32 t
if (((pos + 1) < max_index)
&& (wchars[(pos + 1)]))
{
- llwchar next_char = wchars[pos + 1];
// Kern this puppy.
- cur_x += mFontFreetype->getXKerning(wch, next_char);
+ next_glyph = mFontFreetype->getGlyphInfo(wchars[pos + 1]);
+ cur_x += mFontFreetype->getXKerning(glyph, next_glyph);
}
+
// Round after kerning.
cur_x = llround(cur_x);
}
diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp
index 595b8577ff..656f690db5 100644
--- a/indra/llrender/llrender.cpp
+++ b/indra/llrender/llrender.cpp
@@ -49,6 +49,9 @@ F64 gGLLastProjection[16];
F64 gGLProjection[16];
S32 gGLViewport[4];
+U32 LLRender::sUICalls = 0;
+U32 LLRender::sUIVerts = 0;
+
static const U32 LL_NUM_TEXTURE_LAYERS = 16;
static GLenum sGLTextureType[] =
@@ -90,7 +93,9 @@ static GLenum sGLBlendFactor[] =
GL_DST_ALPHA,
GL_SRC_ALPHA,
GL_ONE_MINUS_DST_ALPHA,
- GL_ONE_MINUS_SRC_ALPHA
+ GL_ONE_MINUS_SRC_ALPHA,
+
+ GL_ZERO // 'BF_UNDEF'
};
LLTexUnit::LLTexUnit(S32 index)
@@ -255,10 +260,9 @@ bool LLTexUnit::bind(LLImageGL* texture, bool for_rendering, bool forceBind)
return false ;
}
- gGL.flush();
-
if ((mCurrTexture != texture->getTexName()) || forceBind)
{
+ gGL.flush();
activate();
enable(texture->getTarget());
mCurrTexture = texture->getTexName();
@@ -445,6 +449,8 @@ void LLTexUnit::setTextureBlendType(eTextureBlendType type)
return;
}
+ gGL.flush();
+
activate();
mCurrBlendType = type;
S32 scale_amount = 1;
@@ -759,6 +765,8 @@ LLRender::LLRender()
mCurrAlphaFunc = CF_DEFAULT;
mCurrAlphaFuncVal = 0.01f;
+ mCurrBlendSFactor = BF_UNDEF;
+ mCurrBlendDFactor = BF_UNDEF;
}
LLRender::~LLRender()
@@ -821,6 +829,80 @@ void LLRender::popMatrix()
glPopMatrix();
}
+void LLRender::translateUI(F32 x, F32 y, F32 z)
+{
+ if (mUIOffset.empty())
+ {
+ 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;
+}
+
+void LLRender::scaleUI(F32 x, F32 y, F32 z)
+{
+ if (mUIScale.empty())
+ {
+ llerrs << "Need to push a UI transformation frame before scaling." << llendl;
+ }
+
+ mUIScale.front().scaleVec(LLVector3(x,y,z));
+}
+
+void LLRender::pushUIMatrix()
+{
+ mUIOffset.push_front(mUIOffset.front());
+ if (mUIScale.empty())
+ {
+ mUIScale.push_front(LLVector3(1,1,1));
+ }
+ else
+ {
+ mUIScale.push_front(mUIScale.front());
+ }
+}
+
+void LLRender::popUIMatrix()
+{
+ if (mUIOffset.empty())
+ {
+ llerrs << "UI offset stack blown." << llendl;
+ }
+ mUIOffset.pop_front();
+ mUIScale.pop_front();
+}
+
+LLVector3 LLRender::getUITranslation()
+{
+ if (mUIOffset.empty())
+ {
+ llerrs << "UI offset stack empty." << llendl;
+ }
+ return mUIOffset.front();
+}
+
+LLVector3 LLRender::getUIScale()
+{
+ if (mUIScale.empty())
+ {
+ llerrs << "UI scale stack empty." << llendl;
+ }
+ return mUIScale.front();
+}
+
+
+void LLRender::loadUIIdentity()
+{
+ if (mUIOffset.empty())
+ {
+ llerrs << "Need to push UI translation frame before clearing offset." << llendl;
+ }
+ mUIOffset.front().setVec(0,0,0);
+ mUIScale.front().setVec(1,1,1);
+}
+
void LLRender::setColorMask(bool writeColor, bool writeAlpha)
{
setColorMask(writeColor, writeColor, writeColor, writeAlpha);
@@ -843,29 +925,28 @@ void LLRender::setColorMask(bool writeColorR, bool writeColorG, bool writeColorB
void LLRender::setSceneBlendType(eBlendType type)
{
- flush();
switch (type)
{
case BT_ALPHA:
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ blendFunc(BF_SOURCE_ALPHA, BF_ONE_MINUS_SOURCE_ALPHA);
break;
case BT_ADD:
- glBlendFunc(GL_ONE, GL_ONE);
+ blendFunc(BF_ONE, BF_ONE);
break;
case BT_ADD_WITH_ALPHA:
- glBlendFunc(GL_SRC_ALPHA, GL_ONE);
+ blendFunc(BF_SOURCE_ALPHA, BF_ONE);
break;
case BT_MULT:
- glBlendFunc(GL_DST_COLOR, GL_ZERO);
+ blendFunc(BF_DEST_COLOR, BF_ZERO);
break;
case BT_MULT_ALPHA:
- glBlendFunc(GL_DST_ALPHA, GL_ZERO);
+ blendFunc(BF_DEST_ALPHA, BF_ZERO);
break;
case BT_MULT_X2:
- glBlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
+ blendFunc(BF_DEST_COLOR, BF_SOURCE_COLOR);
break;
case BT_REPLACE:
- glBlendFunc(GL_ONE, GL_ZERO);
+ blendFunc(BF_ONE, BF_ZERO);
break;
default:
llerrs << "Unknown Scene Blend Type: " << type << llendl;
@@ -891,8 +972,15 @@ void LLRender::setAlphaRejectSettings(eCompareFunc func, F32 value)
void LLRender::blendFunc(eBlendFactor sfactor, eBlendFactor dfactor)
{
- flush();
- glBlendFunc(sGLBlendFactor[sfactor], sGLBlendFactor[dfactor]);
+ llassert(sfactor < BF_UNDEF);
+ llassert(dfactor < BF_UNDEF);
+ if (mCurrBlendSFactor != sfactor || mCurrBlendDFactor != dfactor)
+ {
+ mCurrBlendSFactor = sfactor;
+ mCurrBlendDFactor = dfactor;
+ flush();
+ glBlendFunc(sGLBlendFactor[sfactor], sGLBlendFactor[dfactor]);
+ }
}
LLTexUnit* LLRender::getTexUnit(U32 index)
@@ -1012,6 +1100,12 @@ void LLRender::flush()
}
#endif
+ if (!mUIOffset.empty())
+ {
+ sUICalls++;
+ sUIVerts += mCount;
+ }
+
mBuffer->setBuffer(immediate_mask);
mBuffer->drawArrays(mMode, 0, mCount);
@@ -1031,7 +1125,16 @@ void LLRender::vertex3f(const GLfloat& x, const GLfloat& y, const GLfloat& z)
return;
}
- mVerticesp[mCount] = LLVector3(x,y,z);
+ if (mUIOffset.empty())
+ {
+ mVerticesp[mCount] = LLVector3(x,y,z);
+ }
+ else
+ {
+ LLVector3 vert = (LLVector3(x,y,z)+mUIOffset.front()).scaledVec(mUIScale.front());
+ mVerticesp[mCount] = vert;
+ }
+
mCount++;
if (mCount < 4096)
{
diff --git a/indra/llrender/llrender.h b/indra/llrender/llrender.h
index 0121a190ee..a90fbd4a5c 100644
--- a/indra/llrender/llrender.h
+++ b/indra/llrender/llrender.h
@@ -270,7 +270,9 @@ public:
BF_DEST_ALPHA,
BF_SOURCE_ALPHA,
BF_ONE_MINUS_DEST_ALPHA,
- BF_ONE_MINUS_SOURCE_ALPHA
+ BF_ONE_MINUS_SOURCE_ALPHA,
+
+ BF_UNDEF
} eBlendFactor;
LLRender();
@@ -286,6 +288,14 @@ public:
void pushMatrix();
void popMatrix();
+ void translateUI(F32 x, F32 y, F32 z);
+ void scaleUI(F32 x, F32 y, F32 z);
+ void pushUIMatrix();
+ void popUIMatrix();
+ void loadUIIdentity();
+ LLVector3 getUITranslation();
+ LLVector3 getUIScale();
+
void flush();
void begin(const GLuint& mode);
@@ -333,7 +343,9 @@ public:
};
public:
-
+ static U32 sUICalls;
+ static U32 sUIVerts;
+
private:
bool mDirty;
U32 mCount;
@@ -350,7 +362,14 @@ private:
std::vector<LLTexUnit*> mTexUnits;
LLTexUnit* mDummyTexUnit;
+ eBlendFactor mCurrBlendSFactor;
+ eBlendFactor mCurrBlendDFactor;
+
F32 mMaxAnisotropy;
+
+ std::list<LLVector3> mUIOffset;
+ std::list<LLVector3> mUIScale;
+
};
extern F64 gGLModelView[16];