summaryrefslogtreecommitdiff
path: root/indra/llrender
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llrender')
-rw-r--r--indra/llrender/llcubemap.cpp13
-rw-r--r--indra/llrender/llfontbitmapcache.cpp4
-rw-r--r--indra/llrender/llfontfreetype.cpp42
-rw-r--r--indra/llrender/llfontfreetype.h2
-rw-r--r--indra/llrender/llfontgl.cpp111
-rw-r--r--indra/llrender/llfontregistry.cpp2
-rw-r--r--indra/llrender/llgl.cpp4
-rw-r--r--indra/llrender/llglslshader.cpp2
-rw-r--r--indra/llrender/llimagegl.cpp86
-rw-r--r--indra/llrender/llimagegl.h4
-rw-r--r--indra/llrender/llpostprocess.cpp2
-rw-r--r--indra/llrender/llrender.cpp186
-rw-r--r--indra/llrender/llrender.h23
-rw-r--r--indra/llrender/llvertexbuffer.cpp37
14 files changed, 406 insertions, 112 deletions
diff --git a/indra/llrender/llcubemap.cpp b/indra/llrender/llcubemap.cpp
index 08a96b4e31..036714e5cb 100644
--- a/indra/llrender/llcubemap.cpp
+++ b/indra/llrender/llcubemap.cpp
@@ -63,6 +63,12 @@ LLCubeMap::LLCubeMap()
mTextureCoordStage(0),
mMatrixStage(0)
{
+ mTargets[0] = GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB;
+ mTargets[1] = GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB;
+ mTargets[2] = GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB;
+ mTargets[3] = GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB;
+ mTargets[4] = GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB;
+ mTargets[5] = GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB;
}
LLCubeMap::~LLCubeMap()
@@ -75,13 +81,6 @@ void LLCubeMap::initGL()
if (gGLManager.mHasCubeMap && LLCubeMap::sUseCubeMaps)
{
- mTargets[0] = GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB;
- mTargets[1] = GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB;
- mTargets[2] = GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB;
- mTargets[3] = GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB;
- mTargets[4] = GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB;
- mTargets[5] = GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB;
-
// Not initialized, do stuff.
if (mImages[0].isNull())
{
diff --git a/indra/llrender/llfontbitmapcache.cpp b/indra/llrender/llfontbitmapcache.cpp
index f01878642a..fa231c9e6a 100644
--- a/indra/llrender/llfontbitmapcache.cpp
+++ b/indra/llrender/llfontbitmapcache.cpp
@@ -64,7 +64,7 @@ void LLFontBitmapCache::init(S32 num_components,
LLImageRaw *LLFontBitmapCache::getImageRaw(U32 bitmap_num) const
{
- if ((bitmap_num < 0) || (bitmap_num >= mImageRawVec.size()))
+ if (bitmap_num >= mImageRawVec.size())
return NULL;
return mImageRawVec[bitmap_num];
@@ -72,7 +72,7 @@ LLImageRaw *LLFontBitmapCache::getImageRaw(U32 bitmap_num) const
LLImageGL *LLFontBitmapCache::getImageGL(U32 bitmap_num) const
{
- if ((bitmap_num < 0) || (bitmap_num >= mImageGLVec.size()))
+ if (bitmap_num >= mImageGLVec.size())
return NULL;
return mImageGLVec[bitmap_num];
diff --git a/indra/llrender/llfontfreetype.cpp b/indra/llrender/llfontfreetype.cpp
index 786dc64452..a86bbbffff 100644
--- a/indra/llrender/llfontfreetype.cpp
+++ b/indra/llrender/llfontfreetype.cpp
@@ -91,14 +91,15 @@ LLFontManager::~LLFontManager()
LLFontGlyphInfo::LLFontGlyphInfo(U32 index)
: mGlyphIndex(index),
+ mWidth(0), // In pixels
+ mHeight(0), // In pixels
+ mXAdvance(0.f), // In pixels
+ mYAdvance(0.f), // In pixels
mXBitmapOffset(0), // Offset to the origin in the bitmap
mYBitmapOffset(0), // Offset to the origin in the bitmap
mXBearing(0), // Distance from baseline to left in pixels
mYBearing(0), // Distance from baseline to top in pixels
- mWidth(0), // In pixels
- mHeight(0), // In pixels
- mXAdvance(0.f), // In pixels
- mYAdvance(0.f) // In pixels
+ mBitmapNum(0) // Which bitmap in the bitmap cache contains this glyph
{
}
@@ -112,6 +113,7 @@ LLFontFreetype::LLFontFreetype()
mFTFace(NULL),
mRenderGlyphCount(0),
mAddGlyphCount(0),
+ mStyle(0),
mPointSize(0)
{
}
@@ -268,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)
@@ -287,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);
@@ -502,8 +527,13 @@ void LLFontFreetype::resetBitmapCache()
mCharGlyphInfoMap.clear();
mFontBitmapCachep->reset();
- // Add the empty glyph
- addGlyphFromFont(this, 0, 0);
+ // Adding default glyph is skipped for fallback fonts here as well as in loadFace().
+ // This if was added as fix for EXT-4971.
+ if(!mIsFallback)
+ {
+ // Add the empty glyph
+ addGlyphFromFont(this, 0, 0);
+ }
}
void LLFontFreetype::destroyGL()
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 1de1d6ded4..d9e1976341 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.
@@ -601,14 +617,20 @@ S32 LLFontGL::firstDrawableChar(const llwchar* wchars, F32 max_pixels, S32 text_
{
llwchar wch = wchars[i];
- F32 char_width = mFontFreetype->getXAdvance(wch);
+ const LLFontGlyphInfo* fgi= mFontFreetype->getGlyphInfo(wch);
+
+ // last character uses character width, since the whole character needs to be visible
+ // other characters just use advance
+ F32 width = (i == start)
+ ? (F32)(fgi->mWidth + fgi->mXBearing) // use actual width for last character
+ : fgi->mXAdvance; // use advance for all other characters
- if( scaled_max_pixels < (total_width + char_width) )
+ if( scaled_max_pixels < (total_width + width) )
{
break;
}
- total_width += char_width;
+ total_width += width;
drawable_chars++;
if( max_chars >= 0 && drawable_chars >= max_chars )
@@ -626,7 +648,17 @@ S32 LLFontGL::firstDrawableChar(const llwchar* wchars, F32 max_pixels, S32 text_
total_width = llround(total_width);
}
- return start_pos - drawable_chars;
+ if (drawable_chars == 0)
+ {
+ return start_pos; // just draw last character
+ }
+ else
+ {
+ // if only 1 character is drawable, we want to return start_pos as the first character to draw
+ // if 2 are drawable, return start_pos and character before start_pos, etc.
+ return start_pos + 1 - drawable_chars;
+ }
+
}
S32 LLFontGL::charFromPixelOffset(const llwchar* wchars, S32 begin_offset, F32 target_x, F32 max_pixels, S32 max_chars, BOOL round) const
@@ -641,9 +673,11 @@ S32 LLFontGL::charFromPixelOffset(const llwchar* wchars, S32 begin_offset, F32 t
target_x *= sScaleX;
// max_chars is S32_MAX by default, so make sure we don't get overflow
- const S32 max_index = begin_offset + llmin(S32_MAX - begin_offset, max_chars);
+ const S32 max_index = begin_offset + llmin(S32_MAX - begin_offset, max_chars - 1);
F32 scaled_max_pixels = max_pixels * sScaleX;
+
+ const LLFontGlyphInfo* next_glyph = NULL;
S32 pos;
for (pos = begin_offset; pos < max_index; pos++)
@@ -653,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)
{
@@ -679,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/llfontregistry.cpp b/indra/llrender/llfontregistry.cpp
index 7a3d6ec4f2..e619f89e1d 100644
--- a/indra/llrender/llfontregistry.cpp
+++ b/indra/llrender/llfontregistry.cpp
@@ -469,6 +469,8 @@ LLFontGL *LLFontRegistry::createFont(const LLFontDescriptor& desc)
else
{
fontlist.push_back(fontp->mFontFreetype);
+ delete fontp;
+ fontp = NULL;
}
}
}
diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp
index 187a9a984e..a3f7a946ec 100644
--- a/indra/llrender/llgl.cpp
+++ b/indra/llrender/llgl.cpp
@@ -332,6 +332,8 @@ LLGLManager::LLGLManager() :
mHasFragmentShader(FALSE),
mHasOcclusionQuery(FALSE),
mHasPointParameters(FALSE),
+ mHasDrawBuffers(FALSE),
+ mHasTextureRectangle(FALSE),
mHasAnisotropic(FALSE),
mHasARBEnvCombine(FALSE),
@@ -671,7 +673,7 @@ void LLGLManager::initExtensions()
llinfos << "initExtensions() checking shell variables to adjust features..." << llendl;
// Our extension support for the Linux Client is very young with some
// potential driver gotchas, so offer a semi-secret way to turn it off.
- if (getenv("LL_GL_NOEXT")) /* Flawfinder: ignore */
+ if (getenv("LL_GL_NOEXT"))
{
//mHasMultitexture = FALSE; // NEEDED!
mHasARBEnvCombine = FALSE;
diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp
index 830617063b..ca92cb6580 100644
--- a/indra/llrender/llglslshader.cpp
+++ b/indra/llrender/llglslshader.cpp
@@ -70,7 +70,7 @@ hasGamma(false), hasLighting(false), calculatesAtmospherics(false)
// LLGLSL Shader implementation
//===============================
LLGLSLShader::LLGLSLShader()
-: mProgramObject(0), mShaderLevel(0), mShaderGroup(SG_DEFAULT)
+ : mProgramObject(0), mActiveTextureChannels(0), mShaderLevel(0), mShaderGroup(SG_DEFAULT), mUniformsDirty(FALSE)
{
}
diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp
index cd493481d5..ff47c57c70 100644
--- a/indra/llrender/llimagegl.cpp
+++ b/indra/llrender/llimagegl.cpp
@@ -105,9 +105,9 @@ void check_all_images()
}
}
-void LLImageGL::checkTexSize() const
+void LLImageGL::checkTexSize(bool forced) const
{
- if (gDebugGL && mTarget == GL_TEXTURE_2D)
+ if ((forced || gDebugGL) && mTarget == GL_TEXTURE_2D)
{
GLint texname;
glGetIntegerv(GL_TEXTURE_BINDING_2D, &texname);
@@ -129,6 +129,8 @@ void LLImageGL::checkTexSize() const
glGetTexLevelParameteriv(mTarget, 0, GL_TEXTURE_WIDTH, (GLint*)&x);
glGetTexLevelParameteriv(mTarget, 0, GL_TEXTURE_HEIGHT, (GLint*)&y) ;
stop_glerror() ;
+ llcallstacks << "w: " << x << " h: " << y << llcallstacksendl ;
+
if(!x || !y)
{
return ;
@@ -138,11 +140,13 @@ void LLImageGL::checkTexSize() const
error = TRUE;
if (gDebugSession)
{
- gFailLog << "wrong texture size and discard level!" << std::endl;
+ gFailLog << "wrong texture size and discard level!" <<
+ mWidth << " Height: " << mHeight << " Current Level: " << mCurrentDiscardLevel << std::endl;
}
else
{
- llerrs << "wrong texture size and discard level!" << llendl ;
+ llerrs << "wrong texture size and discard level: width: " <<
+ mWidth << " Height: " << mHeight << " Current Level: " << mCurrentDiscardLevel << llendl ;
}
}
@@ -436,6 +440,8 @@ void LLImageGL::init(BOOL usemipmaps)
mLastBindTime = 0.f;
mPickMask = NULL;
+ mPickMaskWidth = 0;
+ mPickMaskHeight = 0;
mUseMipMaps = usemipmaps;
mHasExplicitFormat = FALSE;
mAutoGenMips = FALSE;
@@ -527,7 +533,12 @@ void LLImageGL::setSize(S32 width, S32 height, S32 ncomponents)
// llwarns << "Setting Size of LLImageGL with existing mTexName = " << mTexName << llendl;
destroyGLTexture();
}
-
+
+ // pickmask validity depends on old image size, delete it
+ delete [] mPickMask;
+ mPickMask = NULL;
+ mPickMaskWidth = mPickMaskHeight = 0;
+
mWidth = width;
mHeight = height;
mComponents = ncomponents;
@@ -1037,7 +1048,9 @@ BOOL LLImageGL::setSubImageFromFrameBuffer(S32 fb_x, S32 fb_y, S32 x_pos, S32 y_
{
if (gGL.getTexUnit(0)->bind(this, false, true))
{
- //checkTexSize() ;
+ checkTexSize(true) ;
+ llcallstacks << fb_x << " : " << fb_y << " : " << x_pos << " : " << y_pos << " : " << width << " : " << height << llcallstacksendl ;
+
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, fb_x, fb_y, x_pos, y_pos, width, height);
mGLTextureCreated = true;
stop_glerror();
@@ -1675,24 +1688,25 @@ void LLImageGL::updatePickMask(S32 width, S32 height, const U8* data_in)
return ;
}
+ delete [] mPickMask;
+ mPickMask = NULL;
+ mPickMaskWidth = mPickMaskHeight = 0;
+
if (mFormatType != GL_UNSIGNED_BYTE ||
mFormatPrimary != GL_RGBA)
{
//cannot generate a pick mask for this texture
- delete [] mPickMask;
- mPickMask = NULL;
return;
}
- U32 pick_width = width/2;
- U32 pick_height = height/2;
-
- U32 size = llmax(pick_width, (U32) 1) * llmax(pick_height, (U32) 1);
+ U32 pick_width = width/2 + 1;
+ U32 pick_height = height/2 + 1;
- size = size/8 + 1;
-
- delete[] mPickMask;
+ U32 size = pick_width * pick_height;
+ size = (size + 7) / 8; // pixelcount-to-bits
mPickMask = new U8[size];
+ mPickMaskWidth = pick_width - 1;
+ mPickMaskHeight = pick_height - 1;
memset(mPickMask, 0, sizeof(U8) * size);
@@ -1708,10 +1722,7 @@ void LLImageGL::updatePickMask(S32 width, S32 height, const U8* data_in)
{
U32 pick_idx = pick_bit/8;
U32 pick_offset = pick_bit%8;
- if (pick_idx >= size)
- {
- llerrs << "WTF?" << llendl;
- }
+ llassert(pick_idx < size);
mPickMask[pick_idx] |= 1 << pick_offset;
}
@@ -1727,35 +1738,42 @@ BOOL LLImageGL::getMask(const LLVector2 &tc)
if (mPickMask)
{
- S32 width = getWidth()/2;
- S32 height = getHeight()/2;
-
- F32 u = tc.mV[0] - floorf(tc.mV[0]);
- F32 v = tc.mV[1] - floorf(tc.mV[1]);
+ F32 u,v;
+ if (LL_LIKELY(tc.isFinite()))
+ {
+ u = tc.mV[0] - floorf(tc.mV[0]);
+ v = tc.mV[1] - floorf(tc.mV[1]);
+ }
+ else
+ {
+ LL_WARNS_ONCE("render") << "Ugh, non-finite u/v in mask pick" << LL_ENDL;
+ u = v = 0.f;
+ llassert(false);
+ }
- if (u < 0.f || u > 1.f ||
- v < 0.f || v > 1.f)
+ if (LL_UNLIKELY(u < 0.f || u > 1.f ||
+ v < 0.f || v > 1.f))
{
LL_WARNS_ONCE("render") << "Ugh, u/v out of range in image mask pick" << LL_ENDL;
u = v = 0.f;
llassert(false);
}
-
- S32 x = (S32)(u * width);
- S32 y = (S32)(v * height);
- if (x >= width)
+ S32 x = llfloor(u * mPickMaskWidth);
+ S32 y = llfloor(v * mPickMaskHeight);
+
+ if (LL_UNLIKELY(x > mPickMaskWidth))
{
LL_WARNS_ONCE("render") << "Ooh, width overrun on pick mask read, that coulda been bad." << LL_ENDL;
- x = llmax(0, width-1);
+ x = llmax((U16)0, mPickMaskWidth);
}
- if (y >= height)
+ if (LL_UNLIKELY(y > mPickMaskHeight))
{
LL_WARNS_ONCE("render") << "Ooh, height overrun on pick mask read, that woulda been bad." << LL_ENDL;
- y = llmax(0, height-1);
+ y = llmax((U16)0, mPickMaskHeight);
}
- S32 idx = y*width+x;
+ S32 idx = y*mPickMaskWidth+x;
S32 offset = idx%8;
res = mPickMask[idx/8] & (1 << offset) ? TRUE : FALSE;
diff --git a/indra/llrender/llimagegl.h b/indra/llrender/llimagegl.h
index facfb7bd62..41239d24c8 100644
--- a/indra/llrender/llimagegl.h
+++ b/indra/llrender/llimagegl.h
@@ -157,7 +157,7 @@ public:
void updatePickMask(S32 width, S32 height, const U8* data_in);
BOOL getMask(const LLVector2 &tc);
- void checkTexSize() const ;
+ void checkTexSize(bool forced = false) const ;
// Sets the addressing mode used to sample the texture
// (such as wrapping, mirrored wrapping, and clamp)
@@ -193,6 +193,8 @@ public:
private:
LLPointer<LLImageRaw> mSaveData; // used for destroyGL/restoreGL
U8* mPickMask; //downsampled bitmap approximation of alpha channel. NULL if no alpha channel
+ U16 mPickMaskWidth;
+ U16 mPickMaskHeight;
S8 mUseMipMaps;
S8 mHasExplicitFormat; // If false (default), GL format is f(mComponents)
S8 mAutoGenMips;
diff --git a/indra/llrender/llpostprocess.cpp b/indra/llrender/llpostprocess.cpp
index 7f4be6a866..bc7f30cdef 100644
--- a/indra/llrender/llpostprocess.cpp
+++ b/indra/llrender/llpostprocess.cpp
@@ -59,6 +59,8 @@ LLPostProcess::LLPostProcess(void) :
mSceneRenderTexture = NULL ;
mNoiseTexture = NULL ;
mTempBloomTexture = NULL ;
+
+ noiseTextureScale = 1.0f;
/* Do nothing. Needs to be updated to use our current shader system, and to work with the move into llrender.
std::string pathName(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "windlight", XML_FILENAME));
diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp
index f97d81126e..c3540a717c 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)
@@ -116,6 +121,8 @@ void LLTexUnit::refreshState(void)
// We set dirty to true so that the tex unit knows to ignore caching
// and we reset the cached tex unit state
+ gGL.flush();
+
glActiveTextureARB(GL_TEXTURE0_ARB + mIndex);
if (mCurrTexType != TT_NONE)
{
@@ -145,6 +152,7 @@ void LLTexUnit::activate(void)
if ((S32)gGL.mCurrTextureUnitIndex != mIndex || gGL.mDirty)
{
+ gGL.flush();
glActiveTextureARB(GL_TEXTURE0_ARB + mIndex);
gGL.mCurrTextureUnitIndex = mIndex;
}
@@ -176,6 +184,7 @@ void LLTexUnit::disable(void)
{
activate();
unbind(mCurrTexType);
+ gGL.flush();
glDisable(sGLTextureType[mCurrTexType]);
mCurrTexType = TT_NONE;
}
@@ -255,10 +264,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();
@@ -382,6 +390,8 @@ void LLTexUnit::setTextureAddressMode(eTextureAddressMode mode)
{
if (mIndex < 0 || mCurrTexture == 0) return;
+ gGL.flush();
+
activate();
glTexParameteri (sGLTextureType[mCurrTexType], GL_TEXTURE_WRAP_S, sGLAddressMode[mode]);
@@ -396,6 +406,8 @@ void LLTexUnit::setTextureFilteringOption(LLTexUnit::eTextureFilterOptions optio
{
if (mIndex < 0 || mCurrTexture == 0) return;
+ gGL.flush();
+
if (option == TFO_POINT)
{
glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
@@ -445,6 +457,8 @@ void LLTexUnit::setTextureBlendType(eTextureBlendType type)
return;
}
+ gGL.flush();
+
activate();
mCurrBlendType = type;
S32 scale_amount = 1;
@@ -561,6 +575,7 @@ void LLTexUnit::setTextureCombiner(eTextureBlendOp op, eTextureBlendSrc src1, eT
if (mCurrBlendType != TB_COMBINE || gGL.mDirty)
{
mCurrBlendType = TB_COMBINE;
+ gGL.flush();
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
}
@@ -571,6 +586,8 @@ void LLTexUnit::setTextureCombiner(eTextureBlendOp op, eTextureBlendSrc src1, eT
return;
}
+ gGL.flush();
+
// Get the gl source enums according to the eTextureBlendSrc sources passed in
GLint source1 = getTextureSource(src1);
GLint source2 = getTextureSource(src2);
@@ -703,6 +720,7 @@ void LLTexUnit::setColorScale(S32 scale)
if (mCurrColorScale != scale || gGL.mDirty)
{
mCurrColorScale = scale;
+ gGL.flush();
glTexEnvi( GL_TEXTURE_ENV, GL_RGB_SCALE, scale );
}
}
@@ -712,6 +730,7 @@ void LLTexUnit::setAlphaScale(S32 scale)
if (mCurrAlphaScale != scale || gGL.mDirty)
{
mCurrAlphaScale = scale;
+ gGL.flush();
glTexEnvi( GL_TEXTURE_ENV, GL_ALPHA_SCALE, scale );
}
}
@@ -733,8 +752,11 @@ void LLTexUnit::debugTextureUnit(void)
LLRender::LLRender()
-: mDirty(false), mCount(0), mMode(LLRender::TRIANGLES),
- mMaxAnisotropy(0.f)
+ : mDirty(false),
+ mCount(0),
+ mMode(LLRender::TRIANGLES),
+ mCurrTextureUnitIndex(0),
+ mMaxAnisotropy(0.f)
{
mBuffer = new LLVertexBuffer(immediate_mask, 0);
mBuffer->allocateBuffer(4096, 0, TRUE);
@@ -756,6 +778,8 @@ LLRender::LLRender()
mCurrAlphaFunc = CF_DEFAULT;
mCurrAlphaFuncVal = 0.01f;
+ mCurrBlendSFactor = BF_UNDEF;
+ mCurrBlendDFactor = BF_UNDEF;
}
LLRender::~LLRender()
@@ -818,6 +842,88 @@ 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()
+{
+ if (mUIOffset.empty())
+ {
+ mUIOffset.push_front(LLVector3(0,0,0));
+ }
+ else
+ {
+ 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);
@@ -840,29 +946,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;
@@ -888,8 +993,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)
@@ -1009,6 +1121,39 @@ void LLRender::flush()
}
#endif
+ if (!mUIOffset.empty())
+ {
+ sUICalls++;
+ sUIVerts += mCount;
+ }
+
+ if (gDebugGL)
+ {
+ if (mMode == LLRender::QUADS)
+ {
+ if (mCount%4 != 0)
+ {
+ llerrs << "Incomplete quad rendered." << llendl;
+ }
+ }
+
+ if (mMode == LLRender::TRIANGLES)
+ {
+ if (mCount%3 != 0)
+ {
+ llerrs << "Incomplete triangle rendered." << llendl;
+ }
+ }
+
+ if (mMode == LLRender::LINES)
+ {
+ if (mCount%2 != 0)
+ {
+ llerrs << "Incomplete line rendered." << llendl;
+ }
+ }
+ }
+
mBuffer->setBuffer(immediate_mask);
mBuffer->drawArrays(mMode, 0, mCount);
@@ -1028,7 +1173,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];
diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp
index 572ae13909..bf5eda21eb 100644
--- a/indra/llrender/llvertexbuffer.cpp
+++ b/indra/llrender/llvertexbuffer.cpp
@@ -215,14 +215,18 @@ void LLVertexBuffer::setupClientArrays(U32 data_mask)
void LLVertexBuffer::drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indices_offset) const
{
+ llassert(mRequestedNumVerts >= 0);
+
if (start >= (U32) mRequestedNumVerts ||
- end >= (U32) mRequestedNumVerts)
+ end >= (U32) mRequestedNumVerts)
{
llerrs << "Bad vertex buffer draw range: [" << start << ", " << end << "]" << llendl;
}
+ llassert(mRequestedNumIndices >= 0);
+
if (indices_offset >= (U32) mRequestedNumIndices ||
- indices_offset + count > (U32) mRequestedNumIndices)
+ indices_offset + count > (U32) mRequestedNumIndices)
{
llerrs << "Bad index buffer draw range: [" << indices_offset << ", " << indices_offset+count << "]" << llendl;
}
@@ -237,7 +241,7 @@ void LLVertexBuffer::drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indi
llerrs << "Wrong vertex buffer bound." << llendl;
}
- if (mode > LLRender::NUM_MODES)
+ if (mode >= LLRender::NUM_MODES)
{
llerrs << "Invalid draw mode: " << mode << llendl;
return;
@@ -251,8 +255,9 @@ void LLVertexBuffer::drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indi
void LLVertexBuffer::draw(U32 mode, U32 count, U32 indices_offset) const
{
+ llassert(mRequestedNumIndices >= 0);
if (indices_offset >= (U32) mRequestedNumIndices ||
- indices_offset + count > (U32) mRequestedNumIndices)
+ indices_offset + count > (U32) mRequestedNumIndices)
{
llerrs << "Bad index buffer draw range: [" << indices_offset << ", " << indices_offset+count << "]" << llendl;
}
@@ -267,7 +272,7 @@ void LLVertexBuffer::draw(U32 mode, U32 count, U32 indices_offset) const
llerrs << "Wrong vertex buffer bound." << llendl;
}
- if (mode > LLRender::NUM_MODES)
+ if (mode >= LLRender::NUM_MODES)
{
llerrs << "Invalid draw mode: " << mode << llendl;
return;
@@ -281,8 +286,9 @@ void LLVertexBuffer::draw(U32 mode, U32 count, U32 indices_offset) const
void LLVertexBuffer::drawArrays(U32 mode, U32 first, U32 count) const
{
+ llassert(mRequestedNumVerts >= 0);
if (first >= (U32) mRequestedNumVerts ||
- first + count > (U32) mRequestedNumVerts)
+ first + count > (U32) mRequestedNumVerts)
{
llerrs << "Bad vertex buffer draw range: [" << first << ", " << first+count << "]" << llendl;
}
@@ -292,7 +298,7 @@ void LLVertexBuffer::drawArrays(U32 mode, U32 first, U32 count) const
llerrs << "Wrong vertex buffer bound." << llendl;
}
- if (mode > LLRender::NUM_MODES)
+ if (mode >= LLRender::NUM_MODES)
{
llerrs << "Invalid draw mode: " << mode << llendl;
return;
@@ -354,7 +360,14 @@ void LLVertexBuffer::clientCopy(F64 max_time)
LLVertexBuffer::LLVertexBuffer(U32 typemask, S32 usage) :
LLRefCount(),
- mNumVerts(0), mNumIndices(0), mUsage(usage), mGLBuffer(0), mGLIndices(0),
+
+ mNumVerts(0),
+ mNumIndices(0),
+ mRequestedNumVerts(-1),
+ mRequestedNumIndices(-1),
+ mUsage(usage),
+ mGLBuffer(0),
+ mGLIndices(0),
mMappedData(NULL),
mMappedIndexData(NULL), mLocked(FALSE),
mFinal(FALSE),
@@ -600,6 +613,8 @@ void LLVertexBuffer::updateNumVerts(S32 nverts)
{
LLMemType mt2(LLMemType::MTYPE_VERTEX_UPDATE_VERTS);
+ llassert(nverts >= 0);
+
if (nverts >= 65535)
{
llwarns << "Vertex buffer overflow!" << llendl;
@@ -628,6 +643,9 @@ void LLVertexBuffer::updateNumVerts(S32 nverts)
void LLVertexBuffer::updateNumIndices(S32 nindices)
{
LLMemType mt2(LLMemType::MTYPE_VERTEX_UPDATE_INDICES);
+
+ llassert(nindices >= 0);
+
mRequestedNumIndices = nindices;
if (!mDynamicSize)
{
@@ -668,6 +686,9 @@ void LLVertexBuffer::allocateBuffer(S32 nverts, S32 nindices, bool create)
void LLVertexBuffer::resizeBuffer(S32 newnverts, S32 newnindices)
{
+ llassert(newnverts >= 0);
+ llassert(newnindices >= 0);
+
mRequestedNumVerts = newnverts;
mRequestedNumIndices = newnindices;