summaryrefslogtreecommitdiff
path: root/indra/llrender
diff options
context:
space:
mode:
authorAndrey Lihatskiy <alihatskiy@productengine.com>2024-05-15 11:16:27 +0300
committerAndrey Lihatskiy <alihatskiy@productengine.com>2024-05-15 11:16:27 +0300
commitbccc10db9a90d365c353baebf443fde2030ce970 (patch)
tree2c2e1fd94b29667a809f8d7285d049f5ff5d424d /indra/llrender
parent531cd34f670170ade57f8813fe48012b61a1d3c2 (diff)
parentbb3c36f5cbc0c3b542045fd27255eee24e03da22 (diff)
Merge branch 'main' into marchcat/x-b-merge
# Conflicts: # autobuild.xml # indra/cmake/ConfigurePkgConfig.cmake # indra/cmake/ICU4C.cmake # indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms.cpp # indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms.h # indra/media_plugins/gstreamer010/llmediaimplgstreamertriviallogging.h # indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.cpp # indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.h # indra/media_plugins/gstreamer010/media_plugin_gstreamer010.cpp # indra/newview/llappviewerlinux_api.h # indra/newview/llappviewerlinux_api_dbus.cpp # indra/newview/llappviewerlinux_api_dbus.h # indra/newview/llfloateremojipicker.cpp # indra/newview/lloutfitslist.cpp
Diffstat (limited to 'indra/llrender')
-rw-r--r--indra/llrender/llatmosphere.cpp14
-rw-r--r--indra/llrender/llatmosphere.h12
-rw-r--r--indra/llrender/llcubemap.cpp316
-rw-r--r--indra/llrender/llcubemap.h66
-rw-r--r--indra/llrender/llcubemaparray.cpp20
-rw-r--r--indra/llrender/llcubemaparray.h32
-rw-r--r--indra/llrender/llfontbitmapcache.cpp218
-rw-r--r--indra/llrender/llfontbitmapcache.h68
-rw-r--r--indra/llrender/llfontfreetype.cpp1162
-rw-r--r--indra/llrender/llfontfreetype.h200
-rw-r--r--indra/llrender/llfontfreetypesvg.cpp264
-rw-r--r--indra/llrender/llfontfreetypesvg.h26
-rw-r--r--indra/llrender/llfontgl.cpp1817
-rw-r--r--indra/llrender/llfontgl.h374
-rw-r--r--indra/llrender/llfontregistry.cpp1156
-rw-r--r--indra/llrender/llfontregistry.h170
-rw-r--r--indra/llrender/llgl.cpp1528
-rw-r--r--indra/llrender/llgl.h332
-rw-r--r--indra/llrender/llglcommonfunc.cpp12
-rw-r--r--indra/llrender/llglcommonfunc.h2
-rw-r--r--indra/llrender/llglheaders.h18
-rw-r--r--indra/llrender/llglslshader.cpp60
-rw-r--r--indra/llrender/llglslshader.h10
-rw-r--r--indra/llrender/llglstates.h180
-rw-r--r--indra/llrender/llgltexture.cpp328
-rw-r--r--indra/llrender/llgltexture.h256
-rw-r--r--indra/llrender/llgltypes.h10
-rw-r--r--indra/llrender/llimagegl.cpp2702
-rw-r--r--indra/llrender/llimagegl.h382
-rw-r--r--indra/llrender/llpostprocess.cpp518
-rw-r--r--indra/llrender/llpostprocess.h358
-rw-r--r--indra/llrender/llrender.cpp2666
-rw-r--r--indra/llrender/llrender.h778
-rw-r--r--indra/llrender/llrender2dutils.cpp2328
-rw-r--r--indra/llrender/llrender2dutils.h90
-rw-r--r--indra/llrender/llrendernavprim.cpp20
-rw-r--r--indra/llrender/llrendernavprim.h10
-rw-r--r--indra/llrender/llrendersphere.cpp88
-rw-r--r--indra/llrender/llrendersphere.h20
-rw-r--r--indra/llrender/llrendertarget.cpp60
-rw-r--r--indra/llrender/llrendertarget.h172
-rw-r--r--indra/llrender/llshadermgr.cpp1842
-rw-r--r--indra/llrender/llshadermgr.h50
-rw-r--r--indra/llrender/lltexture.cpp16
-rw-r--r--indra/llrender/lltexture.h54
-rw-r--r--indra/llrender/lltexturemanagerbridge.cpp10
-rw-r--r--indra/llrender/lltexturemanagerbridge.h16
-rw-r--r--indra/llrender/lluiimage.cpp216
-rw-r--r--indra/llrender/lluiimage.h150
-rw-r--r--indra/llrender/lluiimage.inl56
-rw-r--r--indra/llrender/llvertexbuffer.cpp642
-rw-r--r--indra/llrender/llvertexbuffer.h274
52 files changed, 11118 insertions, 11051 deletions
diff --git a/indra/llrender/llatmosphere.cpp b/indra/llrender/llatmosphere.cpp
index 8e37ca9b90..eae5623a3c 100644
--- a/indra/llrender/llatmosphere.cpp
+++ b/indra/llrender/llatmosphere.cpp
@@ -1,25 +1,25 @@
-/**
+/**
* @file llatmosphere.cpp
* @brief LLAtmosphere integration impl
*
* $LicenseInfo:firstyear=2018&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2018, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -175,8 +175,8 @@ bool AtmosphericModelSettings::operator==(const AtmosphericModelSettings& rhs) c
void LLAtmosphere::initClass()
{
if (!gAtmosphere)
- {
- gAtmosphere = new LLAtmosphere;
+ {
+ gAtmosphere = new LLAtmosphere;
}
}
diff --git a/indra/llrender/llatmosphere.h b/indra/llrender/llatmosphere.h
index 572365d864..4b8c7d0819 100644
--- a/indra/llrender/llatmosphere.h
+++ b/indra/llrender/llatmosphere.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file llatmosphere.h
* @brief LLAtmosphere class
*
* $LicenseInfo:firstyear=2018&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2018, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -146,7 +146,7 @@ public:
bool configureAtmosphericModel(AtmosphericModelSettings& settings);
-protected:
+protected:
LLAtmosphere(const LLAtmosphere& rhs)
{
*this = rhs;
diff --git a/indra/llrender/llcubemap.cpp b/indra/llrender/llcubemap.cpp
index 254288a86e..f16d5b6e53 100644
--- a/indra/llrender/llcubemap.cpp
+++ b/indra/llrender/llcubemap.cpp
@@ -1,25 +1,25 @@
-/**
+/**
* @file llcubemap.cpp
* @brief LLCubeMap class implementation
*
* $LicenseInfo:firstyear=2002&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -47,16 +47,16 @@ namespace {
bool LLCubeMap::sUseCubeMaps = true;
LLCubeMap::LLCubeMap(bool init_as_srgb)
- : mTextureStage(0),
- mMatrixStage(0),
- mIssRGB(init_as_srgb)
+ : mTextureStage(0),
+ mMatrixStage(0),
+ mIssRGB(init_as_srgb)
{
- mTargets[0] = GL_TEXTURE_CUBE_MAP_NEGATIVE_X;
- mTargets[1] = GL_TEXTURE_CUBE_MAP_POSITIVE_X;
- mTargets[2] = GL_TEXTURE_CUBE_MAP_NEGATIVE_Y;
- mTargets[3] = GL_TEXTURE_CUBE_MAP_POSITIVE_Y;
- mTargets[4] = GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
- mTargets[5] = GL_TEXTURE_CUBE_MAP_POSITIVE_Z;
+ mTargets[0] = GL_TEXTURE_CUBE_MAP_NEGATIVE_X;
+ mTargets[1] = GL_TEXTURE_CUBE_MAP_POSITIVE_X;
+ mTargets[2] = GL_TEXTURE_CUBE_MAP_NEGATIVE_Y;
+ mTargets[3] = GL_TEXTURE_CUBE_MAP_POSITIVE_Y;
+ mTargets[4] = GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
+ mTargets[5] = GL_TEXTURE_CUBE_MAP_POSITIVE_Z;
}
LLCubeMap::~LLCubeMap()
@@ -65,106 +65,106 @@ LLCubeMap::~LLCubeMap()
void LLCubeMap::initGL()
{
- llassert(gGLManager.mInited);
-
- if (LLCubeMap::sUseCubeMaps)
- {
- // Not initialized, do stuff.
- if (mImages[0].isNull())
- {
- U32 texname = 0;
-
- LLImageGL::generateTextures(1, &texname);
-
- for (int i = 0; i < 6; i++)
- {
- mImages[i] = new LLImageGL(RESOLUTION, RESOLUTION, 4, FALSE);
+ llassert(gGLManager.mInited);
+
+ if (LLCubeMap::sUseCubeMaps)
+ {
+ // Not initialized, do stuff.
+ if (mImages[0].isNull())
+ {
+ U32 texname = 0;
+
+ LLImageGL::generateTextures(1, &texname);
+
+ for (int i = 0; i < 6; i++)
+ {
+ mImages[i] = new LLImageGL(RESOLUTION, RESOLUTION, 4, FALSE);
#if USE_SRGB_DECODE
if (mIssRGB) {
mImages[i]->setExplicitFormat(GL_SRGB8_ALPHA8, GL_RGBA);
}
#endif
- mImages[i]->setTarget(mTargets[i], LLTexUnit::TT_CUBE_MAP);
- mRawImages[i] = new LLImageRaw(RESOLUTION, RESOLUTION, 4);
- mImages[i]->createGLTexture(0, mRawImages[i], texname);
-
- gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_CUBE_MAP, texname);
- mImages[i]->setAddressMode(LLTexUnit::TAM_CLAMP);
- stop_glerror();
- }
- gGL.getTexUnit(0)->disable();
- }
- disable();
- }
- else
- {
- LL_WARNS() << "Using cube map without extension!" << LL_ENDL;
- }
+ mImages[i]->setTarget(mTargets[i], LLTexUnit::TT_CUBE_MAP);
+ mRawImages[i] = new LLImageRaw(RESOLUTION, RESOLUTION, 4);
+ mImages[i]->createGLTexture(0, mRawImages[i], texname);
+
+ gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_CUBE_MAP, texname);
+ mImages[i]->setAddressMode(LLTexUnit::TAM_CLAMP);
+ stop_glerror();
+ }
+ gGL.getTexUnit(0)->disable();
+ }
+ disable();
+ }
+ else
+ {
+ LL_WARNS() << "Using cube map without extension!" << LL_ENDL;
+ }
}
void LLCubeMap::initRawData(const std::vector<LLPointer<LLImageRaw> >& rawimages)
{
- bool flip_x[6] = { false, true, false, false, true, false };
- bool flip_y[6] = { true, true, true, false, true, true };
- bool transpose[6] = { false, false, false, false, true, true };
-
- // Yes, I know that this is inefficient! - djs 08/08/02
- for (int i = 0; i < 6; i++)
- {
- const U8 *sd = rawimages[i]->getData();
- U8 *td = mRawImages[i]->getData();
-
- S32 offset = 0;
- S32 sx, sy, so;
- for (int y = 0; y < 64; y++)
- {
- for (int x = 0; x < 64; x++)
- {
- sx = x;
- sy = y;
- if (flip_y[i])
- {
- sy = 63 - y;
- }
- if (flip_x[i])
- {
- sx = 63 - x;
- }
- if (transpose[i])
- {
- S32 temp = sx;
- sx = sy;
- sy = temp;
- }
-
- so = 64*sy + sx;
- so *= 4;
- *(td + offset++) = *(sd + so++);
- *(td + offset++) = *(sd + so++);
- *(td + offset++) = *(sd + so++);
- *(td + offset++) = *(sd + so++);
- }
- }
- }
+ bool flip_x[6] = { false, true, false, false, true, false };
+ bool flip_y[6] = { true, true, true, false, true, true };
+ bool transpose[6] = { false, false, false, false, true, true };
+
+ // Yes, I know that this is inefficient! - djs 08/08/02
+ for (int i = 0; i < 6; i++)
+ {
+ const U8 *sd = rawimages[i]->getData();
+ U8 *td = mRawImages[i]->getData();
+
+ S32 offset = 0;
+ S32 sx, sy, so;
+ for (int y = 0; y < 64; y++)
+ {
+ for (int x = 0; x < 64; x++)
+ {
+ sx = x;
+ sy = y;
+ if (flip_y[i])
+ {
+ sy = 63 - y;
+ }
+ if (flip_x[i])
+ {
+ sx = 63 - x;
+ }
+ if (transpose[i])
+ {
+ S32 temp = sx;
+ sx = sy;
+ sy = temp;
+ }
+
+ so = 64*sy + sx;
+ so *= 4;
+ *(td + offset++) = *(sd + so++);
+ *(td + offset++) = *(sd + so++);
+ *(td + offset++) = *(sd + so++);
+ *(td + offset++) = *(sd + so++);
+ }
+ }
+ }
}
void LLCubeMap::initGLData()
{
LL_PROFILE_ZONE_SCOPED;
- for (int i = 0; i < 6; i++)
- {
- mImages[i]->setSubImage(mRawImages[i], 0, 0, RESOLUTION, RESOLUTION);
- }
+ for (int i = 0; i < 6; i++)
+ {
+ mImages[i]->setSubImage(mRawImages[i], 0, 0, RESOLUTION, RESOLUTION);
+ }
}
void LLCubeMap::init(const std::vector<LLPointer<LLImageRaw> >& rawimages)
{
- if (!gGLManager.mIsDisabled)
- {
- initGL();
- initRawData(rawimages);
- initGLData();
- }
+ if (!gGLManager.mIsDisabled)
+ {
+ initGL();
+ initRawData(rawimages);
+ initGLData();
+ }
}
void LLCubeMap::initReflectionMap(U32 resolution, U32 components)
@@ -236,99 +236,99 @@ void LLCubeMap::generateMipMaps()
GLuint LLCubeMap::getGLName()
{
- return mImages[0]->getTexName();
+ return mImages[0]->getTexName();
}
void LLCubeMap::bind()
{
- gGL.getTexUnit(mTextureStage)->bind(this);
+ gGL.getTexUnit(mTextureStage)->bind(this);
}
void LLCubeMap::enable(S32 stage)
{
- enableTexture(stage);
+ enableTexture(stage);
}
void LLCubeMap::enableTexture(S32 stage)
{
- mTextureStage = stage;
- if (stage >= 0 && LLCubeMap::sUseCubeMaps)
- {
- gGL.getTexUnit(stage)->enable(LLTexUnit::TT_CUBE_MAP);
- }
+ mTextureStage = stage;
+ if (stage >= 0 && LLCubeMap::sUseCubeMaps)
+ {
+ gGL.getTexUnit(stage)->enable(LLTexUnit::TT_CUBE_MAP);
+ }
}
void LLCubeMap::disable(void)
{
- disableTexture();
+ disableTexture();
}
void LLCubeMap::disableTexture(void)
{
- if (mTextureStage >= 0 && LLCubeMap::sUseCubeMaps)
- {
- gGL.getTexUnit(mTextureStage)->disable();
- if (mTextureStage == 0)
- {
- gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE);
- }
- }
+ if (mTextureStage >= 0 && LLCubeMap::sUseCubeMaps)
+ {
+ gGL.getTexUnit(mTextureStage)->disable();
+ if (mTextureStage == 0)
+ {
+ gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE);
+ }
+ }
}
void LLCubeMap::setMatrix(S32 stage)
{
- mMatrixStage = stage;
-
- if (mMatrixStage < 0) return;
-
- //if (stage > 0)
- {
- gGL.getTexUnit(stage)->activate();
- }
-
- LLVector3 x(gGLModelView+0);
- LLVector3 y(gGLModelView+4);
- LLVector3 z(gGLModelView+8);
-
- LLMatrix3 mat3;
- mat3.setRows(x,y,z);
- LLMatrix4 trans(mat3);
- trans.transpose();
-
- gGL.matrixMode(LLRender::MM_TEXTURE);
- gGL.pushMatrix();
- gGL.loadMatrix((F32 *)trans.mMatrix);
- gGL.matrixMode(LLRender::MM_MODELVIEW);
-
- /*if (stage > 0)
- {
- gGL.getTexUnit(0)->activate();
- }*/
+ mMatrixStage = stage;
+
+ if (mMatrixStage < 0) return;
+
+ //if (stage > 0)
+ {
+ gGL.getTexUnit(stage)->activate();
+ }
+
+ LLVector3 x(gGLModelView+0);
+ LLVector3 y(gGLModelView+4);
+ LLVector3 z(gGLModelView+8);
+
+ LLMatrix3 mat3;
+ mat3.setRows(x,y,z);
+ LLMatrix4 trans(mat3);
+ trans.transpose();
+
+ gGL.matrixMode(LLRender::MM_TEXTURE);
+ gGL.pushMatrix();
+ gGL.loadMatrix((F32 *)trans.mMatrix);
+ gGL.matrixMode(LLRender::MM_MODELVIEW);
+
+ /*if (stage > 0)
+ {
+ gGL.getTexUnit(0)->activate();
+ }*/
}
void LLCubeMap::restoreMatrix()
{
- if (mMatrixStage < 0) return;
-
- //if (mMatrixStage > 0)
- {
- gGL.getTexUnit(mMatrixStage)->activate();
- }
- gGL.matrixMode(LLRender::MM_TEXTURE);
- gGL.popMatrix();
- gGL.matrixMode(LLRender::MM_MODELVIEW);
-
- /*if (mMatrixStage > 0)
- {
- gGL.getTexUnit(0)->activate();
- }*/
+ if (mMatrixStage < 0) return;
+
+ //if (mMatrixStage > 0)
+ {
+ gGL.getTexUnit(mMatrixStage)->activate();
+ }
+ gGL.matrixMode(LLRender::MM_TEXTURE);
+ gGL.popMatrix();
+ gGL.matrixMode(LLRender::MM_MODELVIEW);
+
+ /*if (mMatrixStage > 0)
+ {
+ gGL.getTexUnit(0)->activate();
+ }*/
}
void LLCubeMap::destroyGL()
{
- for (S32 i = 0; i < 6; i++)
- {
- mImages[i] = NULL;
- }
+ for (S32 i = 0; i < 6; i++)
+ {
+ mImages[i] = NULL;
+ }
}
diff --git a/indra/llrender/llcubemap.h b/indra/llrender/llcubemap.h
index b9e081cea3..fa5c0ecbf3 100644
--- a/indra/llrender/llcubemap.h
+++ b/indra/llrender/llcubemap.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file llcubemap.h
* @brief LLCubeMap class definition
*
* $LicenseInfo:firstyear=2002&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -36,10 +36,10 @@ class LLVector3;
// Environment map hack!
class LLCubeMap : public LLRefCount
{
- bool mIssRGB;
+ bool mIssRGB;
public:
- LLCubeMap(bool init_as_srgb);
- void init(const std::vector<LLPointer<LLImageRaw> >& rawimages);
+ LLCubeMap(bool init_as_srgb);
+ void init(const std::vector<LLPointer<LLImageRaw> >& rawimages);
// initialize as an undefined cubemap at the given resolution
// used for render-to-cubemap operations
@@ -51,42 +51,42 @@ public:
// respect the resolution of rawimages
// Raw images must point to array of six square images that are all the same resolution
void initEnvironmentMap(const std::vector<LLPointer<LLImageRaw> >& rawimages);
- void initGL();
- void initRawData(const std::vector<LLPointer<LLImageRaw> >& rawimages);
- void initGLData();
-
- void bind();
- void enable(S32 stage);
-
- void enableTexture(S32 stage);
- S32 getStage(void) { return mTextureStage; }
-
- void disable(void);
- void disableTexture(void);
- void setMatrix(S32 stage);
- void restoreMatrix();
+ void initGL();
+ void initRawData(const std::vector<LLPointer<LLImageRaw> >& rawimages);
+ void initGLData();
+
+ void bind();
+ void enable(S32 stage);
+
+ void enableTexture(S32 stage);
+ S32 getStage(void) { return mTextureStage; }
+
+ void disable(void);
+ void disableTexture(void);
+ void setMatrix(S32 stage);
+ void restoreMatrix();
U32 getResolution() { return mImages[0].notNull() ? mImages[0]->getWidth(0) : 0; }
-
+
// generate mip maps for this Cube Map using GL
// NOTE: Cube Map MUST already be resident in VRAM
void generateMipMaps();
- GLuint getGLName();
+ GLuint getGLName();
- void destroyGL();
+ void destroyGL();
public:
- static bool sUseCubeMaps;
+ static bool sUseCubeMaps;
protected:
- friend class LLTexUnit;
- ~LLCubeMap();
- LLGLenum mTargets[6];
- LLPointer<LLImageGL> mImages[6];
- LLPointer<LLImageRaw> mRawImages[6];
- S32 mTextureStage;
- S32 mMatrixStage;
+ friend class LLTexUnit;
+ ~LLCubeMap();
+ LLGLenum mTargets[6];
+ LLPointer<LLImageGL> mImages[6];
+ LLPointer<LLImageRaw> mRawImages[6];
+ S32 mTextureStage;
+ S32 mMatrixStage;
};
#endif
diff --git a/indra/llrender/llcubemaparray.cpp b/indra/llrender/llcubemaparray.cpp
index 1debd33953..03fbb90bf6 100644
--- a/indra/llrender/llcubemaparray.cpp
+++ b/indra/llrender/llcubemaparray.cpp
@@ -1,25 +1,25 @@
-/**
+/**
* @file llcubemaparray.cpp
* @brief LLCubeMap class implementation
*
* $LicenseInfo:firstyear=2022&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2022, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -63,7 +63,7 @@ LLVector3 LLCubeMapArray::sLookVecs[6] =
LLVector3(0, 0, -1)
};
-LLVector3 LLCubeMapArray::sUpVecs[6] =
+LLVector3 LLCubeMapArray::sUpVecs[6] =
{
LLVector3(0, -1, 0),
LLVector3(0, -1, 0),
@@ -77,7 +77,7 @@ LLVector3 LLCubeMapArray::sClipToCubeLookVecs[6] =
{
LLVector3(0, 0, -1), //GOOD
LLVector3(0, 0, 1), //GOOD
-
+
LLVector3(1, 0, 0), // GOOD
LLVector3(1, 0, 0), // GOOD
@@ -98,9 +98,9 @@ LLVector3 LLCubeMapArray::sClipToCubeUpVecs[6] =
};
LLCubeMapArray::LLCubeMapArray()
- : mTextureStage(0)
+ : mTextureStage(0)
{
-
+
}
LLCubeMapArray::~LLCubeMapArray()
@@ -170,7 +170,7 @@ void LLCubeMapArray::unbind()
GLuint LLCubeMapArray::getGLName()
{
- return mImage->getTexName();
+ return mImage->getTexName();
}
void LLCubeMapArray::destroyGL()
diff --git a/indra/llrender/llcubemaparray.h b/indra/llrender/llcubemaparray.h
index 6c3f7dc890..9d78c5b0d4 100644
--- a/indra/llrender/llcubemaparray.h
+++ b/indra/llrender/llcubemaparray.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file llcubemaparray.h
* @brief LLCubeMap class definition
*
* $LicenseInfo:firstyear=2022&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2022, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -35,10 +35,10 @@ class LLVector3;
class LLCubeMapArray : public LLRefCount
{
public:
- LLCubeMapArray();
+ LLCubeMapArray();
static GLenum sTargets[6];
-
+
// look and up vectors for each cube face (agent space)
static LLVector3 sLookVecs[6];
static LLVector3 sUpVecs[6];
@@ -47,18 +47,18 @@ public:
static LLVector3 sClipToCubeLookVecs[6];
static LLVector3 sClipToCubeUpVecs[6];
- // allocate a cube map array
+ // allocate a cube map array
// res - resolution of each cube face
// components - number of components per pixel
// count - number of cube maps in the array
// use_mips - if TRUE, mipmaps will be allocated for this cube map array and anisotropic filtering will be used
void allocate(U32 res, U32 components, U32 count, BOOL use_mips = TRUE);
- void bind(S32 stage);
+ void bind(S32 stage);
void unbind();
-
- GLuint getGLName();
- void destroyGL();
+ GLuint getGLName();
+
+ void destroyGL();
// get width of cubemaps in array (they're cubes, so this is also the height)
U32 getWidth() const { return mWidth; }
@@ -67,10 +67,10 @@ public:
U32 getCount() const { return mCount; }
protected:
- friend class LLTexUnit;
- ~LLCubeMapArray();
- LLPointer<LLImageGL> mImage;
+ friend class LLTexUnit;
+ ~LLCubeMapArray();
+ LLPointer<LLImageGL> mImage;
U32 mWidth = 0;
U32 mCount = 0;
- S32 mTextureStage;
+ S32 mTextureStage;
};
diff --git a/indra/llrender/llfontbitmapcache.cpp b/indra/llrender/llfontbitmapcache.cpp
index 42b0045cf3..243041945a 100644
--- a/indra/llrender/llfontbitmapcache.cpp
+++ b/indra/llrender/llfontbitmapcache.cpp
@@ -1,25 +1,25 @@
-/**
+/**
* @file llfontbitmapcache.cpp
* @brief Storage for previously rendered glyphs.
*
* $LicenseInfo:firstyear=2008&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -39,60 +39,60 @@ LLFontBitmapCache::~LLFontBitmapCache()
}
void LLFontBitmapCache::init(S32 max_char_width,
- S32 max_char_height)
+ S32 max_char_height)
{
- reset();
-
- mMaxCharWidth = max_char_width;
- mMaxCharHeight = max_char_height;
-
- S32 image_width = mMaxCharWidth * 20;
- S32 pow_iw = 2;
- while (pow_iw < image_width)
- {
- pow_iw <<= 1;
- }
- image_width = pow_iw;
- image_width = llmin(512, image_width); // Don't make bigger than 512x512, ever.
-
- mBitmapWidth = image_width;
- mBitmapHeight = image_width;
+ reset();
+
+ mMaxCharWidth = max_char_width;
+ mMaxCharHeight = max_char_height;
+
+ S32 image_width = mMaxCharWidth * 20;
+ S32 pow_iw = 2;
+ while (pow_iw < image_width)
+ {
+ pow_iw <<= 1;
+ }
+ image_width = pow_iw;
+ image_width = llmin(512, image_width); // Don't make bigger than 512x512, ever.
+
+ mBitmapWidth = image_width;
+ mBitmapHeight = image_width;
}
LLImageRaw *LLFontBitmapCache::getImageRaw(EFontGlyphType bitmap_type, U32 bitmap_num) const
{
- const U32 bitmap_idx = static_cast<U32>(bitmap_type);
- if (bitmap_type >= EFontGlyphType::Count || bitmap_num >= mImageRawVec[bitmap_idx].size())
- return nullptr;
+ const U32 bitmap_idx = static_cast<U32>(bitmap_type);
+ if (bitmap_type >= EFontGlyphType::Count || bitmap_num >= mImageRawVec[bitmap_idx].size())
+ return nullptr;
- return mImageRawVec[bitmap_idx][bitmap_num];
+ return mImageRawVec[bitmap_idx][bitmap_num];
}
LLImageGL *LLFontBitmapCache::getImageGL(EFontGlyphType bitmap_type, U32 bitmap_num) const
{
- const U32 bitmap_idx = static_cast<U32>(bitmap_type);
- if (bitmap_type >= EFontGlyphType::Count || bitmap_num >= mImageGLVec[bitmap_idx].size())
- return nullptr;
+ const U32 bitmap_idx = static_cast<U32>(bitmap_type);
+ if (bitmap_type >= EFontGlyphType::Count || bitmap_num >= mImageGLVec[bitmap_idx].size())
+ return nullptr;
- return mImageGLVec[bitmap_idx][bitmap_num];
+ return mImageGLVec[bitmap_idx][bitmap_num];
}
BOOL LLFontBitmapCache::nextOpenPos(S32 width, S32& pos_x, S32& pos_y, EFontGlyphType bitmap_type, U32& bitmap_num)
{
- if (bitmap_type >= EFontGlyphType::Count)
- {
- return FALSE;
- }
-
- const U32 bitmap_idx = static_cast<U32>(bitmap_type);
- if (mImageRawVec[bitmap_idx].empty() || (mCurrentOffsetX[bitmap_idx] + width + 1) > mBitmapWidth)
- {
- if ((mImageRawVec[bitmap_idx].empty()) || (mCurrentOffsetY[bitmap_idx] + 2*mMaxCharHeight + 2) > mBitmapHeight)
- {
- // We're out of space in the current image, or no image
- // has been allocated yet. Make a new one.
-
+ if (bitmap_type >= EFontGlyphType::Count)
+ {
+ return FALSE;
+ }
+
+ const U32 bitmap_idx = static_cast<U32>(bitmap_type);
+ if (mImageRawVec[bitmap_idx].empty() || (mCurrentOffsetX[bitmap_idx] + width + 1) > mBitmapWidth)
+ {
+ if ((mImageRawVec[bitmap_idx].empty()) || (mCurrentOffsetY[bitmap_idx] + 2*mMaxCharHeight + 2) > mBitmapHeight)
+ {
+ // We're out of space in the current image, or no image
+ // has been allocated yet. Make a new one.
+
S32 image_width = mMaxCharWidth * 20;
S32 pow_iw = 2;
while (pow_iw < image_width)
@@ -102,85 +102,85 @@ BOOL LLFontBitmapCache::nextOpenPos(S32 width, S32& pos_x, S32& pos_y, EFontGlyp
image_width = pow_iw;
image_width = llmin(512, image_width); // Don't make bigger than 512x512, ever.
S32 image_height = image_width;
-
+
mBitmapWidth = image_width;
mBitmapHeight = image_height;
-
- S32 num_components = getNumComponents(bitmap_type);
- mImageRawVec[bitmap_idx].push_back(new LLImageRaw(mBitmapWidth, mBitmapHeight, num_components));
- bitmap_num = mImageRawVec[bitmap_idx].size() - 1;
-
- LLImageRaw* image_raw = getImageRaw(bitmap_type, bitmap_num);
- if (EFontGlyphType::Grayscale == bitmap_type)
- {
- image_raw->clear(255, 0);
- }
-
- // Make corresponding GL image.
- mImageGLVec[bitmap_idx].push_back(new LLImageGL(image_raw, false));
- LLImageGL* image_gl = getImageGL(bitmap_type, bitmap_num);
-
- // Start at beginning of the new image.
- mCurrentOffsetX[bitmap_idx] = 1;
- mCurrentOffsetY[bitmap_idx] = 1;
-
- // Attach corresponding GL texture. (*TODO: is this needed?)
- gGL.getTexUnit(0)->bind(image_gl);
- image_gl->setFilteringOption(LLTexUnit::TFO_POINT); // was setMipFilterNearest(TRUE, TRUE);
- }
- else
- {
- // Move to next row in current image.
- mCurrentOffsetX[bitmap_idx] = 1;
- mCurrentOffsetY[bitmap_idx] += mMaxCharHeight + 1;
- }
- }
-
- pos_x = mCurrentOffsetX[bitmap_idx];
- pos_y = mCurrentOffsetY[bitmap_idx];
- bitmap_num = getNumBitmaps(bitmap_type) - 1;
-
- mCurrentOffsetX[bitmap_idx] += width + 1;
-
- return TRUE;
+
+ S32 num_components = getNumComponents(bitmap_type);
+ mImageRawVec[bitmap_idx].push_back(new LLImageRaw(mBitmapWidth, mBitmapHeight, num_components));
+ bitmap_num = mImageRawVec[bitmap_idx].size() - 1;
+
+ LLImageRaw* image_raw = getImageRaw(bitmap_type, bitmap_num);
+ if (EFontGlyphType::Grayscale == bitmap_type)
+ {
+ image_raw->clear(255, 0);
+ }
+
+ // Make corresponding GL image.
+ mImageGLVec[bitmap_idx].push_back(new LLImageGL(image_raw, false));
+ LLImageGL* image_gl = getImageGL(bitmap_type, bitmap_num);
+
+ // Start at beginning of the new image.
+ mCurrentOffsetX[bitmap_idx] = 1;
+ mCurrentOffsetY[bitmap_idx] = 1;
+
+ // Attach corresponding GL texture. (*TODO: is this needed?)
+ gGL.getTexUnit(0)->bind(image_gl);
+ image_gl->setFilteringOption(LLTexUnit::TFO_POINT); // was setMipFilterNearest(TRUE, TRUE);
+ }
+ else
+ {
+ // Move to next row in current image.
+ mCurrentOffsetX[bitmap_idx] = 1;
+ mCurrentOffsetY[bitmap_idx] += mMaxCharHeight + 1;
+ }
+ }
+
+ pos_x = mCurrentOffsetX[bitmap_idx];
+ pos_y = mCurrentOffsetY[bitmap_idx];
+ bitmap_num = getNumBitmaps(bitmap_type) - 1;
+
+ mCurrentOffsetX[bitmap_idx] += width + 1;
+
+ return TRUE;
}
void LLFontBitmapCache::destroyGL()
{
- for (U32 idx = 0, cnt = static_cast<U32>(EFontGlyphType::Count); idx < cnt; idx++)
- {
- for (LLImageGL* image_gl : mImageGLVec[idx])
- {
- image_gl->destroyGLTexture();
- }
- }
+ for (U32 idx = 0, cnt = static_cast<U32>(EFontGlyphType::Count); idx < cnt; idx++)
+ {
+ for (LLImageGL* image_gl : mImageGLVec[idx])
+ {
+ image_gl->destroyGLTexture();
+ }
+ }
}
void LLFontBitmapCache::reset()
{
- for (U32 idx = 0, cnt = static_cast<U32>(EFontGlyphType::Count); idx < cnt; idx++)
- {
- mImageRawVec[idx].clear();
- mImageGLVec[idx].clear();
- mCurrentOffsetX[idx] = 1;
- mCurrentOffsetY[idx] = 1;
- }
-
- mBitmapWidth = 0;
- mBitmapHeight = 0;
+ for (U32 idx = 0, cnt = static_cast<U32>(EFontGlyphType::Count); idx < cnt; idx++)
+ {
+ mImageRawVec[idx].clear();
+ mImageGLVec[idx].clear();
+ mCurrentOffsetX[idx] = 1;
+ mCurrentOffsetY[idx] = 1;
+ }
+
+ mBitmapWidth = 0;
+ mBitmapHeight = 0;
}
//static
U32 LLFontBitmapCache::getNumComponents(EFontGlyphType bitmap_type)
{
- switch (bitmap_type)
- {
- case EFontGlyphType::Grayscale:
- return 2;
- case EFontGlyphType::Color:
- return 4;
- default:
- llassert(false);
- return 2;
- }
+ switch (bitmap_type)
+ {
+ case EFontGlyphType::Grayscale:
+ return 2;
+ case EFontGlyphType::Color:
+ return 4;
+ default:
+ llassert(false);
+ return 2;
+ }
}
diff --git a/indra/llrender/llfontbitmapcache.h b/indra/llrender/llfontbitmapcache.h
index c63281ab70..8f704df44f 100644
--- a/indra/llrender/llfontbitmapcache.h
+++ b/indra/llrender/llfontbitmapcache.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file llfontbitmapcache.h
* @brief Storage for previously rendered glyphs.
*
* $LicenseInfo:firstyear=2008&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -32,10 +32,10 @@
enum class EFontGlyphType : U32
{
- Grayscale = 0,
- Color,
- Count,
- Unspecified,
+ Grayscale = 0,
+ Color,
+ Count,
+ Unspecified,
};
// Maintain a collection of bitmaps containing rendered glyphs.
@@ -43,39 +43,39 @@ enum class EFontGlyphType : U32
class LLFontBitmapCache
{
public:
- LLFontBitmapCache();
- ~LLFontBitmapCache();
+ LLFontBitmapCache();
+ ~LLFontBitmapCache();
+
+ // Need to call this once, before caching any glyphs.
+ void init(S32 max_char_width,
+ S32 max_char_height);
+
+ void reset();
- // Need to call this once, before caching any glyphs.
- void init(S32 max_char_width,
- S32 max_char_height);
+ BOOL nextOpenPos(S32 width, S32& posX, S32& posY, EFontGlyphType bitmapType, U32& bitmapNum);
- void reset();
+ void destroyGL();
- BOOL nextOpenPos(S32 width, S32& posX, S32& posY, EFontGlyphType bitmapType, U32& bitmapNum);
-
- void destroyGL();
-
- LLImageRaw* getImageRaw(EFontGlyphType bitmapType, U32 bitmapNum) const;
- LLImageGL* getImageGL(EFontGlyphType bitmapType, U32 bitmapNum) const;
+ LLImageRaw* getImageRaw(EFontGlyphType bitmapType, U32 bitmapNum) const;
+ LLImageGL* getImageGL(EFontGlyphType bitmapType, U32 bitmapNum) const;
- S32 getMaxCharWidth() const { return mMaxCharWidth; }
- U32 getNumBitmaps(EFontGlyphType bitmapType) const { return (bitmapType < EFontGlyphType::Count) ? mImageRawVec[static_cast<U32>(bitmapType)].size() : 0; }
- S32 getBitmapWidth() const { return mBitmapWidth; }
- S32 getBitmapHeight() const { return mBitmapHeight; }
+ S32 getMaxCharWidth() const { return mMaxCharWidth; }
+ U32 getNumBitmaps(EFontGlyphType bitmapType) const { return (bitmapType < EFontGlyphType::Count) ? mImageRawVec[static_cast<U32>(bitmapType)].size() : 0; }
+ S32 getBitmapWidth() const { return mBitmapWidth; }
+ S32 getBitmapHeight() const { return mBitmapHeight; }
protected:
- static U32 getNumComponents(EFontGlyphType bitmap_type);
+ static U32 getNumComponents(EFontGlyphType bitmap_type);
private:
- S32 mBitmapWidth = 0;
- S32 mBitmapHeight = 0;
- S32 mCurrentOffsetX[static_cast<U32>(EFontGlyphType::Count)] = { 1 };
- S32 mCurrentOffsetY[static_cast<U32>(EFontGlyphType::Count)] = { 1 };
- S32 mMaxCharWidth = 0;
- S32 mMaxCharHeight = 0;
- std::vector<LLPointer<LLImageRaw>> mImageRawVec[static_cast<U32>(EFontGlyphType::Count)];
- std::vector<LLPointer<LLImageGL>> mImageGLVec[static_cast<U32>(EFontGlyphType::Count)];
+ S32 mBitmapWidth = 0;
+ S32 mBitmapHeight = 0;
+ S32 mCurrentOffsetX[static_cast<U32>(EFontGlyphType::Count)] = { 1 };
+ S32 mCurrentOffsetY[static_cast<U32>(EFontGlyphType::Count)] = { 1 };
+ S32 mMaxCharWidth = 0;
+ S32 mMaxCharHeight = 0;
+ std::vector<LLPointer<LLImageRaw>> mImageRawVec[static_cast<U32>(EFontGlyphType::Count)];
+ std::vector<LLPointer<LLImageGL>> mImageGLVec[static_cast<U32>(EFontGlyphType::Count)];
};
#endif //LL_LLFONTBITMAPCACHE_H
diff --git a/indra/llrender/llfontfreetype.cpp b/indra/llrender/llfontfreetype.cpp
index f9363fe5a8..554e70d6a7 100644
--- a/indra/llrender/llfontfreetype.cpp
+++ b/indra/llrender/llfontfreetype.cpp
@@ -46,14 +46,14 @@
#include "llimage.h"
#include "llimagepng.h"
//#include "llimagej2c.h"
-#include "llmath.h" // Linden math
+#include "llmath.h" // Linden math
#include "llstring.h"
//#include "imdebug.h"
#include "llfontbitmapcache.h"
#include "llgl.h"
#if !defined(LL_NO_OTSVG)
- #define ENABLE_OT_SVG_SUPPORT
+ #define ENABLE_OT_SVG_SUPPORT
#endif
FT_Render_Mode gFontRenderMode = FT_RENDER_MODE_NORMAL;
@@ -65,779 +65,823 @@ FT_Library gFTLibrary = NULL;
//static
void LLFontManager::initClass()
{
- if (!gFontManagerp)
- {
- gFontManagerp = new LLFontManager;
- }
+ if (!gFontManagerp)
+ {
+ gFontManagerp = new LLFontManager;
+ }
}
//static
void LLFontManager::cleanupClass()
{
- delete gFontManagerp;
- gFontManagerp = NULL;
+ delete gFontManagerp;
+ gFontManagerp = NULL;
}
LLFontManager::LLFontManager()
{
- int error;
- error = FT_Init_FreeType(&gFTLibrary);
- if (error)
- {
- // Clean up freetype libs.
- LL_ERRS() << "Freetype initialization failure!" << LL_ENDL;
- FT_Done_FreeType(gFTLibrary);
- }
+ int error;
+ error = FT_Init_FreeType(&gFTLibrary);
+ if (error)
+ {
+ // Clean up freetype libs.
+ LL_ERRS() << "Freetype initialization failure!" << LL_ENDL;
+ FT_Done_FreeType(gFTLibrary);
+ }
#if defined(ENABLE_OT_SVG_SUPPORT)
- SVG_RendererHooks hooks = {
- LLFontFreeTypeSvgRenderer::OnInit,
- LLFontFreeTypeSvgRenderer::OnFree,
- LLFontFreeTypeSvgRenderer::OnRender,
- LLFontFreeTypeSvgRenderer::OnPresetGlypthSlot,
- };
- FT_Property_Set(gFTLibrary, "ot-svg", "svg-hooks", &hooks);
+ SVG_RendererHooks hooks = {
+ LLFontFreeTypeSvgRenderer::OnInit,
+ LLFontFreeTypeSvgRenderer::OnFree,
+ LLFontFreeTypeSvgRenderer::OnRender,
+ LLFontFreeTypeSvgRenderer::OnPresetGlypthSlot,
+ };
+ FT_Property_Set(gFTLibrary, "ot-svg", "svg-hooks", &hooks);
#endif
}
LLFontManager::~LLFontManager()
{
- FT_Done_FreeType(gFTLibrary);
+ FT_Done_FreeType(gFTLibrary);
}
LLFontGlyphInfo::LLFontGlyphInfo(U32 index, EFontGlyphType glyph_type)
-: mGlyphIndex(index),
- mGlyphType(glyph_type),
- 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
- mBitmapEntry(std::make_pair(EFontGlyphType::Unspecified, -1)) // Which bitmap in the bitmap cache contains this glyph
+: mGlyphIndex(index),
+ mGlyphType(glyph_type),
+ 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
+ mBitmapEntry(std::make_pair(EFontGlyphType::Unspecified, -1)) // Which bitmap in the bitmap cache contains this glyph
{
}
LLFontGlyphInfo::LLFontGlyphInfo(const LLFontGlyphInfo& fgi)
- : mGlyphIndex(fgi.mGlyphIndex)
- , mGlyphType(fgi.mGlyphType)
- , mWidth(fgi.mWidth)
- , mHeight(fgi.mHeight)
- , mXAdvance(fgi.mXAdvance)
- , mYAdvance(fgi.mYAdvance)
- , mXBitmapOffset(fgi.mXBitmapOffset)
- , mYBitmapOffset(fgi.mYBitmapOffset)
- , mXBearing(fgi.mXBearing)
- , mYBearing(fgi.mYBearing)
+ : mGlyphIndex(fgi.mGlyphIndex)
+ , mGlyphType(fgi.mGlyphType)
+ , mWidth(fgi.mWidth)
+ , mHeight(fgi.mHeight)
+ , mXAdvance(fgi.mXAdvance)
+ , mYAdvance(fgi.mYAdvance)
+ , mXBitmapOffset(fgi.mXBitmapOffset)
+ , mYBitmapOffset(fgi.mYBitmapOffset)
+ , mXBearing(fgi.mXBearing)
+ , mYBearing(fgi.mYBearing)
{
- mBitmapEntry = fgi.mBitmapEntry;
+ mBitmapEntry = fgi.mBitmapEntry;
}
LLFontFreetype::LLFontFreetype()
-: mFontBitmapCachep(new LLFontBitmapCache),
- mAscender(0.f),
- mDescender(0.f),
- mLineHeight(0.f),
+: mFontBitmapCachep(new LLFontBitmapCache),
+ mAscender(0.f),
+ mDescender(0.f),
+ mLineHeight(0.f),
#ifdef LL_WINDOWS
- pFileStream(NULL),
- pFtStream(NULL),
+ pFileStream(NULL),
+ pFtStream(NULL),
#endif
- mIsFallback(FALSE),
- mFTFace(NULL),
- mRenderGlyphCount(0),
- mAddGlyphCount(0),
- mStyle(0),
- mPointSize(0)
+ mIsFallback(FALSE),
+ mFTFace(NULL),
+ mRenderGlyphCount(0),
+ mAddGlyphCount(0),
+ mStyle(0),
+ mPointSize(0)
{
}
LLFontFreetype::~LLFontFreetype()
{
- // Clean up freetype libs.
- if (mFTFace)
- FT_Done_Face(mFTFace);
- mFTFace = NULL;
+ // Clean up freetype libs.
+ if (mFTFace)
+ FT_Done_Face(mFTFace);
+ mFTFace = NULL;
- // Delete glyph info
- std::for_each(mCharGlyphInfoMap.begin(), mCharGlyphInfoMap.end(), DeletePairedPointer());
- mCharGlyphInfoMap.clear();
+ // Delete glyph info
+ std::for_each(mCharGlyphInfoMap.begin(), mCharGlyphInfoMap.end(), DeletePairedPointer());
+ mCharGlyphInfoMap.clear();
#ifdef LL_WINDOWS
- delete pFileStream; // closed by FT_Done_Face
- delete pFtStream;
+ delete pFileStream; // closed by FT_Done_Face
+ delete pFtStream;
#endif
- delete mFontBitmapCachep;
- // mFallbackFonts cleaned up by LLPointer destructor
+ delete mFontBitmapCachep;
+ // mFallbackFonts cleaned up by LLPointer destructor
}
#ifdef LL_WINDOWS
unsigned long ft_read_cb(FT_Stream stream, unsigned long offset, unsigned char *buffer, unsigned long count) {
- if (count <= 0) return count;
- llifstream *file_stream = static_cast<llifstream *>(stream->descriptor.pointer);
- file_stream->seekg(offset, std::ios::beg);
- file_stream->read((char*)buffer, count);
- return file_stream->gcount();
+ if (count <= 0) return count;
+ llifstream *file_stream = static_cast<llifstream *>(stream->descriptor.pointer);
+ file_stream->seekg(offset, std::ios::beg);
+ file_stream->read((char*)buffer, count);
+ return file_stream->gcount();
}
void ft_close_cb(FT_Stream stream) {
- llifstream *file_stream = static_cast<llifstream *>(stream->descriptor.pointer);
- file_stream->close();
+ llifstream *file_stream = static_cast<llifstream *>(stream->descriptor.pointer);
+ file_stream->close();
}
#endif
BOOL LLFontFreetype::loadFace(const std::string& filename, F32 point_size, F32 vert_dpi, F32 horz_dpi, bool is_fallback, S32 face_n)
{
- // Don't leak face objects. This is also needed to deal with
- // changed font file names.
- if (mFTFace)
- {
- FT_Done_Face(mFTFace);
- mFTFace = NULL;
- }
+ // Don't leak face objects. This is also needed to deal with
+ // changed font file names.
+ if (mFTFace)
+ {
+ FT_Done_Face(mFTFace);
+ mFTFace = NULL;
+ }
- int error;
+ int error;
#ifdef LL_WINDOWS
- error = ftOpenFace(filename, face_n);
+ error = ftOpenFace(filename, face_n);
#else
- error = FT_New_Face( gFTLibrary,
- filename.c_str(),
- 0,
- &mFTFace);
+ error = FT_New_Face( gFTLibrary,
+ filename.c_str(),
+ 0,
+ &mFTFace);
#endif
- if (error)
- {
+ if (error)
+ {
#ifdef LL_WINDOWS
- clearFontStreams();
+ clearFontStreams();
#endif
- return FALSE;
- }
-
- mIsFallback = is_fallback;
- F32 pixels_per_em = (point_size / 72.f)*vert_dpi; // Size in inches * dpi
-
- error = FT_Set_Char_Size(mFTFace, /* handle to face object */
- 0, /* char_width in 1/64th of points */
- (S32)(point_size*64), /* char_height in 1/64th of points */
- (U32)horz_dpi, /* horizontal device resolution */
- (U32)vert_dpi); /* vertical device resolution */
-
- if (error)
- {
- // Clean up freetype libs.
- FT_Done_Face(mFTFace);
+ return FALSE;
+ }
+
+ mIsFallback = is_fallback;
+ F32 pixels_per_em = (point_size / 72.f)*vert_dpi; // Size in inches * dpi
+
+ error = FT_Set_Char_Size(mFTFace, /* handle to face object */
+ 0, /* char_width in 1/64th of points */
+ (S32)(point_size*64), /* char_height in 1/64th of points */
+ (U32)horz_dpi, /* horizontal device resolution */
+ (U32)vert_dpi); /* vertical device resolution */
+
+ if (error)
+ {
+ // Clean up freetype libs.
+ FT_Done_Face(mFTFace);
#ifdef LL_WINDOWS
- clearFontStreams();
+ clearFontStreams();
#endif
- mFTFace = NULL;
- return FALSE;
- }
+ mFTFace = NULL;
+ return FALSE;
+ }
- F32 y_max, y_min, x_max, x_min;
- F32 ems_per_unit = 1.f/ mFTFace->units_per_EM;
- F32 pixels_per_unit = pixels_per_em * ems_per_unit;
+ F32 y_max, y_min, x_max, x_min;
+ F32 ems_per_unit = 1.f/ mFTFace->units_per_EM;
+ F32 pixels_per_unit = pixels_per_em * ems_per_unit;
- // Get size of bbox in pixels
- y_max = mFTFace->bbox.yMax * pixels_per_unit;
- y_min = mFTFace->bbox.yMin * pixels_per_unit;
- x_max = mFTFace->bbox.xMax * pixels_per_unit;
- x_min = mFTFace->bbox.xMin * pixels_per_unit;
- mAscender = mFTFace->ascender * pixels_per_unit;
- mDescender = -mFTFace->descender * pixels_per_unit;
- mLineHeight = mFTFace->height * pixels_per_unit;
+ // Get size of bbox in pixels
+ y_max = mFTFace->bbox.yMax * pixels_per_unit;
+ y_min = mFTFace->bbox.yMin * pixels_per_unit;
+ x_max = mFTFace->bbox.xMax * pixels_per_unit;
+ x_min = mFTFace->bbox.xMin * pixels_per_unit;
+ mAscender = mFTFace->ascender * pixels_per_unit;
+ mDescender = -mFTFace->descender * pixels_per_unit;
+ mLineHeight = mFTFace->height * pixels_per_unit;
- S32 max_char_width = ll_round(0.5f + (x_max - x_min));
- S32 max_char_height = ll_round(0.5f + (y_max - y_min));
+ S32 max_char_width = ll_round(0.5f + (x_max - x_min));
+ S32 max_char_height = ll_round(0.5f + (y_max - y_min));
- mFontBitmapCachep->init(max_char_width, max_char_height);
+ mFontBitmapCachep->init(max_char_width, max_char_height);
- if (!mFTFace->charmap)
- {
- //LL_INFOS() << " no unicode encoding, set whatever encoding there is..." << LL_ENDL;
- FT_Set_Charmap(mFTFace, mFTFace->charmaps[0]);
- }
+ if (!mFTFace->charmap)
+ {
+ //LL_INFOS() << " no unicode encoding, set whatever encoding there is..." << LL_ENDL;
+ FT_Set_Charmap(mFTFace, mFTFace->charmaps[0]);
+ }
- if (!mIsFallback)
- {
- // Add the default glyph
- addGlyphFromFont(this, 0, 0, EFontGlyphType::Grayscale);
- }
+ if (!mIsFallback)
+ {
+ // Add the default glyph
+ addGlyphFromFont(this, 0, 0, EFontGlyphType::Grayscale);
+ }
- mName = filename;
- mPointSize = point_size;
+ mName = filename;
+ mPointSize = point_size;
- mStyle = LLFontGL::NORMAL;
- if(mFTFace->style_flags & FT_STYLE_FLAG_BOLD)
- {
- mStyle |= LLFontGL::BOLD;
- }
+ mStyle = LLFontGL::NORMAL;
+ if(mFTFace->style_flags & FT_STYLE_FLAG_BOLD)
+ {
+ mStyle |= LLFontGL::BOLD;
+ }
- if(mFTFace->style_flags & FT_STYLE_FLAG_ITALIC)
- {
- mStyle |= LLFontGL::ITALIC;
- }
+ if(mFTFace->style_flags & FT_STYLE_FLAG_ITALIC)
+ {
+ mStyle |= LLFontGL::ITALIC;
+ }
- return TRUE;
+ return TRUE;
}
S32 LLFontFreetype::getNumFaces(const std::string& filename)
{
- if (mFTFace)
- {
- FT_Done_Face(mFTFace);
- mFTFace = NULL;
- }
+ if (mFTFace)
+ {
+ FT_Done_Face(mFTFace);
+ mFTFace = NULL;
+ }
- S32 num_faces = 1;
+ S32 num_faces = 1;
#ifdef LL_WINDOWS
- int error = ftOpenFace(filename, 0);
-
- if (error)
- {
- return 0;
- }
- else
- {
- num_faces = mFTFace->num_faces;
- }
-
- FT_Done_Face(mFTFace);
- clearFontStreams();
- mFTFace = NULL;
+ int error = ftOpenFace(filename, 0);
+
+ if (error)
+ {
+ return 0;
+ }
+ else
+ {
+ num_faces = mFTFace->num_faces;
+ }
+
+ FT_Done_Face(mFTFace);
+ clearFontStreams();
+ mFTFace = NULL;
#endif
- return num_faces;
+ return num_faces;
}
#ifdef LL_WINDOWS
S32 LLFontFreetype::ftOpenFace(const std::string& filename, S32 face_n)
{
- S32 error = -1;
- pFileStream = new llifstream(filename, std::ios::binary);
- if (pFileStream->is_open())
- {
- std::streampos beg = pFileStream->tellg();
- pFileStream->seekg(0, std::ios::end);
- std::streampos end = pFileStream->tellg();
- std::size_t file_size = end - beg;
- pFileStream->seekg(0, std::ios::beg);
-
- pFtStream = new LLFT_Stream();
- pFtStream->base = 0;
- pFtStream->pos = 0;
- pFtStream->size = file_size;
- pFtStream->descriptor.pointer = pFileStream;
- pFtStream->read = ft_read_cb;
- pFtStream->close = ft_close_cb;
-
- FT_Open_Args args;
- args.flags = FT_OPEN_STREAM;
- args.stream = (FT_StreamRec*)pFtStream;
- error = FT_Open_Face(gFTLibrary, &args, face_n, &mFTFace);
- }
- return error;
+ S32 error = -1;
+ pFileStream = new llifstream(filename, std::ios::binary);
+ if (pFileStream->is_open())
+ {
+ std::streampos beg = pFileStream->tellg();
+ pFileStream->seekg(0, std::ios::end);
+ std::streampos end = pFileStream->tellg();
+ std::size_t file_size = end - beg;
+ pFileStream->seekg(0, std::ios::beg);
+
+ pFtStream = new LLFT_Stream();
+ pFtStream->base = 0;
+ pFtStream->pos = 0;
+ pFtStream->size = file_size;
+ pFtStream->descriptor.pointer = pFileStream;
+ pFtStream->read = ft_read_cb;
+ pFtStream->close = ft_close_cb;
+
+ FT_Open_Args args;
+ args.flags = FT_OPEN_STREAM;
+ args.stream = (FT_StreamRec*)pFtStream;
+ error = FT_Open_Face(gFTLibrary, &args, face_n, &mFTFace);
+ }
+ return error;
}
void LLFontFreetype::clearFontStreams()
{
- if (pFileStream)
- {
- pFileStream->close();
- }
- delete pFileStream;
- delete pFtStream;
- pFileStream = NULL;
- pFtStream = NULL;
+ if (pFileStream)
+ {
+ pFileStream->close();
+ }
+ delete pFileStream;
+ delete pFtStream;
+ pFileStream = NULL;
+ pFtStream = NULL;
}
#endif
-void LLFontFreetype::addFallbackFont(const LLPointer<LLFontFreetype>& fallback_font, const char_functor_t& functor)
+void LLFontFreetype::addFallbackFont(const LLPointer<LLFontFreetype>& fallback_font,
+ const char_functor_t& functor)
{
- // Insert functor fallbacks before generic fallbacks
- mFallbackFonts.insert((functor) ? std::find_if(mFallbackFonts.begin(), mFallbackFonts.end(), [](const fallback_font_t& fe) { return !fe.second; }) : mFallbackFonts.end(),
- std::make_pair(fallback_font, functor));
+ mFallbackFonts.emplace_back(fallback_font, functor);
}
F32 LLFontFreetype::getLineHeight() const
{
- return mLineHeight;
+ return mLineHeight;
}
F32 LLFontFreetype::getAscenderHeight() const
{
- return mAscender;
+ return mAscender;
}
F32 LLFontFreetype::getDescenderHeight() const
{
- return mDescender;
+ return mDescender;
}
F32 LLFontFreetype::getXAdvance(llwchar wch) const
{
- if (mFTFace == NULL)
- return 0.0;
+ if (mFTFace == NULL)
+ return 0.0;
- // Return existing info only if it is current
- LLFontGlyphInfo* gi = getGlyphInfo(wch, EFontGlyphType::Unspecified);
- if (gi)
- {
- return gi->mXAdvance;
- }
- else
- {
- char_glyph_info_map_t::iterator found_it = mCharGlyphInfoMap.find((llwchar)0);
- if (found_it != mCharGlyphInfoMap.end())
- {
- return found_it->second->mXAdvance;
- }
- }
+ // Return existing info only if it is current
+ LLFontGlyphInfo* gi = getGlyphInfo(wch, EFontGlyphType::Unspecified);
+ if (gi)
+ {
+ return gi->mXAdvance;
+ }
+ else
+ {
+ char_glyph_info_map_t::iterator found_it = mCharGlyphInfoMap.find((llwchar)0);
+ if (found_it != mCharGlyphInfoMap.end())
+ {
+ return found_it->second->mXAdvance;
+ }
+ }
- // Last ditch fallback - no glyphs defined at all.
- return (F32)mFontBitmapCachep->getMaxCharWidth();
+ // Last ditch fallback - no glyphs defined at all.
+ return (F32)mFontBitmapCachep->getMaxCharWidth();
}
F32 LLFontFreetype::getXAdvance(const LLFontGlyphInfo* glyph) const
{
- if (mFTFace == NULL)
- return 0.0;
+ if (mFTFace == NULL)
+ return 0.0;
- return glyph->mXAdvance;
+ return glyph->mXAdvance;
}
F32 LLFontFreetype::getXKerning(llwchar char_left, llwchar char_right) const
{
- if (mFTFace == NULL)
- return 0.0;
+ if (mFTFace == NULL)
+ return 0.0;
- //llassert(!mIsFallback);
- LLFontGlyphInfo* left_glyph_info = getGlyphInfo(char_left, EFontGlyphType::Unspecified);;
- U32 left_glyph = left_glyph_info ? left_glyph_info->mGlyphIndex : 0;
- // Kern this puppy.
- LLFontGlyphInfo* right_glyph_info = getGlyphInfo(char_right, EFontGlyphType::Unspecified);
- U32 right_glyph = right_glyph_info ? right_glyph_info->mGlyphIndex : 0;
+ //llassert(!mIsFallback);
+ LLFontGlyphInfo* left_glyph_info = getGlyphInfo(char_left, EFontGlyphType::Unspecified);;
+ U32 left_glyph = left_glyph_info ? left_glyph_info->mGlyphIndex : 0;
+ // Kern this puppy.
+ LLFontGlyphInfo* right_glyph_info = getGlyphInfo(char_right, EFontGlyphType::Unspecified);
+ U32 right_glyph = right_glyph_info ? right_glyph_info->mGlyphIndex : 0;
- FT_Vector delta;
+ FT_Vector delta;
- llverify(!FT_Get_Kerning(mFTFace, left_glyph, right_glyph, ft_kerning_unfitted, &delta));
+ llverify(!FT_Get_Kerning(mFTFace, left_glyph, right_glyph, ft_kerning_unfitted, &delta));
- return delta.x*(1.f/64.f);
+ 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;
+ 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;
+ 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;
+ FT_Vector delta;
- llverify(!FT_Get_Kerning(mFTFace, left_glyph, right_glyph, ft_kerning_unfitted, &delta));
+ llverify(!FT_Get_Kerning(mFTFace, left_glyph, right_glyph, ft_kerning_unfitted, &delta));
- return delta.x*(1.f/64.f);
+ return delta.x*(1.f/64.f);
}
BOOL LLFontFreetype::hasGlyph(llwchar wch) const
{
- llassert(!mIsFallback);
- return(mCharGlyphInfoMap.find(wch) != mCharGlyphInfoMap.end());
+ llassert(!mIsFallback);
+ return(mCharGlyphInfoMap.find(wch) != mCharGlyphInfoMap.end());
}
LLFontGlyphInfo* LLFontFreetype::addGlyph(llwchar wch, EFontGlyphType glyph_type) const
{
- if (mFTFace == NULL)
- return FALSE;
-
- llassert(!mIsFallback);
- llassert(glyph_type < EFontGlyphType::Count);
- //LL_DEBUGS() << "Adding new glyph for " << wch << " to font" << LL_ENDL;
-
- FT_UInt glyph_index;
-
- // Fallback fonts with a functor have precedence over everything else
- fallback_font_vector_t::const_iterator it_fallback = mFallbackFonts.cbegin();
- /* This leads to a bug SL-19831 "Check marks in the menu are less visible."
- ** Also, LLFontRegistry::createFont() says: "Fallback fonts don't render"
- for (; it_fallback != mFallbackFonts.cend() && it_fallback->second; ++it_fallback)
- {
- if (it_fallback->second(wch))
- {
- glyph_index = FT_Get_Char_Index(it_fallback->first->mFTFace, wch);
- if (glyph_index)
- {
- return addGlyphFromFont(it_fallback->first, wch, glyph_index, glyph_type);
- }
- }
- }
- */
-
- // Initialize char to glyph map
- glyph_index = FT_Get_Char_Index(mFTFace, wch);
- if (glyph_index == 0)
- {
- //LL_INFOS() << "Trying to add glyph from fallback font!" << LL_ENDL;
- for (; it_fallback != mFallbackFonts.cend(); ++it_fallback)
- {
- glyph_index = FT_Get_Char_Index(it_fallback->first->mFTFace, wch);
- if (glyph_index)
- {
- return addGlyphFromFont(it_fallback->first, wch, glyph_index, glyph_type);
- }
- }
- }
-
- std::pair<char_glyph_info_map_t::iterator, char_glyph_info_map_t::iterator> range_it = mCharGlyphInfoMap.equal_range(wch);
- char_glyph_info_map_t::iterator iter =
- std::find_if(range_it.first, range_it.second, [&glyph_type](const char_glyph_info_map_t::value_type& entry) { return entry.second->mGlyphType == glyph_type; });
- if (iter == range_it.second)
- {
- return addGlyphFromFont(this, wch, glyph_index, glyph_type);
- }
- return NULL;
+ if (!mFTFace)
+ {
+ return NULL;
+ }
+
+ llassert(!mIsFallback);
+ llassert(glyph_type < EFontGlyphType::Count);
+ //LL_DEBUGS() << "Adding new glyph for " << wch << " to font" << LL_ENDL;
+
+ // Initialize char to glyph map
+ FT_UInt glyph_index = FT_Get_Char_Index(mFTFace, wch);
+ if (glyph_index == 0)
+ {
+ // No corresponding glyph in this font: look for a glyph in fallback
+ // fonts.
+ size_t count = mFallbackFonts.size();
+ if (LLStringOps::isEmoji(wch))
+ {
+ // This is a "genuine" emoji (in the range 0x1f000-0x20000): print
+ // it using the emoji font(s) if possible. HB
+ for (size_t i = 0; i < count; ++i)
+ {
+ const fallback_font_t& pair = mFallbackFonts[i];
+ if (!pair.second || !pair.second(wch))
+ {
+ // If this font does not have a functor, or the character
+ // does not pass the functor, reject it. Note: we keep the
+ // functor test (despite the fact we already tested for
+ // LLStringOps::isEmoji(wch) above), in case we would use
+ // different, more restrictive or partionned functors in
+ // the future with several different emoji fonts. HB
+ continue;
+ }
+ glyph_index = FT_Get_Char_Index(pair.first->mFTFace, wch);
+ if (glyph_index)
+ {
+ return addGlyphFromFont(pair.first, wch, glyph_index,
+ glyph_type);
+ }
+ }
+ }
+ // Then try and find a monochrome fallback font that could print this
+ // glyph: such fonts do *not* have a functor. We give priority to
+ // monochrome fonts for non-genuine emojis so that UI elements which
+ // used to render with them before the emojis font introduction (e.g.
+ // check marks in menus, or LSL dialogs text and buttons) do render the
+ // same way as they always did. HB
+ std::vector<size_t> emoji_fonts_idx;
+ for (size_t i = 0; i < count; ++i)
+ {
+ const fallback_font_t& pair = mFallbackFonts[i];
+ if (pair.second)
+ {
+ // If this font got a functor, remember the index for later and
+ // try the next fallback font. HB
+ emoji_fonts_idx.push_back(i);
+ continue;
+ }
+ glyph_index = FT_Get_Char_Index(pair.first->mFTFace, wch);
+ if (glyph_index)
+ {
+ return addGlyphFromFont(pair.first, wch, glyph_index,
+ glyph_type);
+ }
+ }
+ // Everything failed so far: this character is not a genuine emoji,
+ // neither a special character known from our monochrome fallback
+ // fonts: make a last try, using the emoji font(s), but ignoring the
+ // functor to render using whatever (colorful) glyph that might be
+ // available in such fonts for this character. HB
+ for (size_t j = 0, count2 = emoji_fonts_idx.size(); j < count2; ++j)
+ {
+ const fallback_font_t& pair = mFallbackFonts[emoji_fonts_idx[j]];
+ glyph_index = FT_Get_Char_Index(pair.first->mFTFace, wch);
+ if (glyph_index)
+ {
+ return addGlyphFromFont(pair.first, wch, glyph_index,
+ glyph_type);
+ }
+ }
+ }
+
+ auto range_it = mCharGlyphInfoMap.equal_range(wch);
+ char_glyph_info_map_t::iterator iter =
+ std::find_if(range_it.first, range_it.second,
+ [&glyph_type](const char_glyph_info_map_t::value_type& entry)
+ {
+ return entry.second->mGlyphType == glyph_type;
+ });
+ if (iter == range_it.second)
+ {
+ return addGlyphFromFont(this, wch, glyph_index, glyph_type);
+ }
+ return NULL;
}
LLFontGlyphInfo* LLFontFreetype::addGlyphFromFont(const LLFontFreetype *fontp, llwchar wch, U32 glyph_index, EFontGlyphType requested_glyph_type) const
{
LL_PROFILE_ZONE_SCOPED;
- if (mFTFace == NULL)
- return NULL;
-
- llassert(!mIsFallback);
- fontp->renderGlyph(requested_glyph_type, glyph_index);
-
- EFontGlyphType bitmap_glyph_type = EFontGlyphType::Unspecified;
- switch (fontp->mFTFace->glyph->bitmap.pixel_mode)
- {
- case FT_PIXEL_MODE_MONO:
- case FT_PIXEL_MODE_GRAY:
- bitmap_glyph_type = EFontGlyphType::Grayscale;
- break;
- case FT_PIXEL_MODE_BGRA:
- bitmap_glyph_type = EFontGlyphType::Color;
- break;
- default:
- llassert_always(true);
- break;
- }
- S32 width = fontp->mFTFace->glyph->bitmap.width;
- S32 height = fontp->mFTFace->glyph->bitmap.rows;
-
- S32 pos_x, pos_y;
- U32 bitmap_num;
- mFontBitmapCachep->nextOpenPos(width, pos_x, pos_y, bitmap_glyph_type, bitmap_num);
- mAddGlyphCount++;
-
- LLFontGlyphInfo* gi = new LLFontGlyphInfo(glyph_index, requested_glyph_type);
- gi->mXBitmapOffset = pos_x;
- gi->mYBitmapOffset = pos_y;
- gi->mBitmapEntry = std::make_pair(bitmap_glyph_type, bitmap_num);
- gi->mWidth = width;
- gi->mHeight = height;
- gi->mXBearing = fontp->mFTFace->glyph->bitmap_left;
- gi->mYBearing = fontp->mFTFace->glyph->bitmap_top;
- // Convert these from 26.6 units to float pixels.
- gi->mXAdvance = fontp->mFTFace->glyph->advance.x / 64.f;
- gi->mYAdvance = fontp->mFTFace->glyph->advance.y / 64.f;
-
- insertGlyphInfo(wch, gi);
-
- if (requested_glyph_type != bitmap_glyph_type)
- {
- LLFontGlyphInfo* gi_temp = new LLFontGlyphInfo(*gi);
- gi_temp->mGlyphType = bitmap_glyph_type;
- insertGlyphInfo(wch, gi_temp);
- }
-
- if (fontp->mFTFace->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_MONO
- || fontp->mFTFace->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_GRAY)
- {
- U8 *buffer_data = fontp->mFTFace->glyph->bitmap.buffer;
- S32 buffer_row_stride = fontp->mFTFace->glyph->bitmap.pitch;
- U8 *tmp_graydata = NULL;
-
- if (fontp->mFTFace->glyph->bitmap.pixel_mode
- == FT_PIXEL_MODE_MONO)
- {
- // need to expand 1-bit bitmap to 8-bit graymap.
- tmp_graydata = new U8[width * height];
- S32 xpos, ypos;
- for (ypos = 0; ypos < height; ++ypos)
- {
- S32 bm_row_offset = buffer_row_stride * ypos;
- for (xpos = 0; xpos < width; ++xpos)
- {
- U32 bm_col_offsetbyte = xpos / 8;
- U32 bm_col_offsetbit = 7 - (xpos % 8);
- U32 bit =
- !!(buffer_data[bm_row_offset
- + bm_col_offsetbyte
- ] & (1 << bm_col_offsetbit) );
- tmp_graydata[width*ypos + xpos] =
- 255 * bit;
- }
- }
- // use newly-built graymap.
- buffer_data = tmp_graydata;
- buffer_row_stride = width;
- }
-
- setSubImageLuminanceAlpha(pos_x,
- pos_y,
- bitmap_num,
- width,
- height,
- buffer_data,
- buffer_row_stride);
-
- if (tmp_graydata)
- delete[] tmp_graydata;
- }
- else if (fontp->mFTFace->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_BGRA)
- {
- setSubImageBGRA(pos_x,
- pos_y,
- bitmap_num,
- fontp->mFTFace->glyph->bitmap.width,
- fontp->mFTFace->glyph->bitmap.rows,
- fontp->mFTFace->glyph->bitmap.buffer,
- llabs(fontp->mFTFace->glyph->bitmap.pitch));
- } else {
- llassert(false);
- }
-
- LLImageGL *image_gl = mFontBitmapCachep->getImageGL(bitmap_glyph_type, bitmap_num);
- LLImageRaw *image_raw = mFontBitmapCachep->getImageRaw(bitmap_glyph_type, bitmap_num);
- image_gl->setSubImage(image_raw, 0, 0, image_gl->getWidth(), image_gl->getHeight());
-
- return gi;
+ if (mFTFace == NULL)
+ return NULL;
+
+ llassert(!mIsFallback);
+ fontp->renderGlyph(requested_glyph_type, glyph_index);
+
+ EFontGlyphType bitmap_glyph_type = EFontGlyphType::Unspecified;
+ switch (fontp->mFTFace->glyph->bitmap.pixel_mode)
+ {
+ case FT_PIXEL_MODE_MONO:
+ case FT_PIXEL_MODE_GRAY:
+ bitmap_glyph_type = EFontGlyphType::Grayscale;
+ break;
+ case FT_PIXEL_MODE_BGRA:
+ bitmap_glyph_type = EFontGlyphType::Color;
+ break;
+ default:
+ llassert_always(true);
+ break;
+ }
+ S32 width = fontp->mFTFace->glyph->bitmap.width;
+ S32 height = fontp->mFTFace->glyph->bitmap.rows;
+
+ S32 pos_x, pos_y;
+ U32 bitmap_num;
+ mFontBitmapCachep->nextOpenPos(width, pos_x, pos_y, bitmap_glyph_type, bitmap_num);
+ mAddGlyphCount++;
+
+ LLFontGlyphInfo* gi = new LLFontGlyphInfo(glyph_index, requested_glyph_type);
+ gi->mXBitmapOffset = pos_x;
+ gi->mYBitmapOffset = pos_y;
+ gi->mBitmapEntry = std::make_pair(bitmap_glyph_type, bitmap_num);
+ gi->mWidth = width;
+ gi->mHeight = height;
+ gi->mXBearing = fontp->mFTFace->glyph->bitmap_left;
+ gi->mYBearing = fontp->mFTFace->glyph->bitmap_top;
+ // Convert these from 26.6 units to float pixels.
+ gi->mXAdvance = fontp->mFTFace->glyph->advance.x / 64.f;
+ gi->mYAdvance = fontp->mFTFace->glyph->advance.y / 64.f;
+
+ insertGlyphInfo(wch, gi);
+
+ if (requested_glyph_type != bitmap_glyph_type)
+ {
+ LLFontGlyphInfo* gi_temp = new LLFontGlyphInfo(*gi);
+ gi_temp->mGlyphType = bitmap_glyph_type;
+ insertGlyphInfo(wch, gi_temp);
+ }
+
+ if (fontp->mFTFace->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_MONO
+ || fontp->mFTFace->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_GRAY)
+ {
+ U8 *buffer_data = fontp->mFTFace->glyph->bitmap.buffer;
+ S32 buffer_row_stride = fontp->mFTFace->glyph->bitmap.pitch;
+ U8 *tmp_graydata = NULL;
+
+ if (fontp->mFTFace->glyph->bitmap.pixel_mode
+ == FT_PIXEL_MODE_MONO)
+ {
+ // need to expand 1-bit bitmap to 8-bit graymap.
+ tmp_graydata = new U8[width * height];
+ S32 xpos, ypos;
+ for (ypos = 0; ypos < height; ++ypos)
+ {
+ S32 bm_row_offset = buffer_row_stride * ypos;
+ for (xpos = 0; xpos < width; ++xpos)
+ {
+ U32 bm_col_offsetbyte = xpos / 8;
+ U32 bm_col_offsetbit = 7 - (xpos % 8);
+ U32 bit =
+ !!(buffer_data[bm_row_offset
+ + bm_col_offsetbyte
+ ] & (1 << bm_col_offsetbit) );
+ tmp_graydata[width*ypos + xpos] =
+ 255 * bit;
+ }
+ }
+ // use newly-built graymap.
+ buffer_data = tmp_graydata;
+ buffer_row_stride = width;
+ }
+
+ setSubImageLuminanceAlpha(pos_x,
+ pos_y,
+ bitmap_num,
+ width,
+ height,
+ buffer_data,
+ buffer_row_stride);
+
+ if (tmp_graydata)
+ delete[] tmp_graydata;
+ }
+ else if (fontp->mFTFace->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_BGRA)
+ {
+ setSubImageBGRA(pos_x,
+ pos_y,
+ bitmap_num,
+ fontp->mFTFace->glyph->bitmap.width,
+ fontp->mFTFace->glyph->bitmap.rows,
+ fontp->mFTFace->glyph->bitmap.buffer,
+ llabs(fontp->mFTFace->glyph->bitmap.pitch));
+ } else {
+ llassert(false);
+ }
+
+ LLImageGL *image_gl = mFontBitmapCachep->getImageGL(bitmap_glyph_type, bitmap_num);
+ LLImageRaw *image_raw = mFontBitmapCachep->getImageRaw(bitmap_glyph_type, bitmap_num);
+ image_gl->setSubImage(image_raw, 0, 0, image_gl->getWidth(), image_gl->getHeight());
+
+ return gi;
}
LLFontGlyphInfo* LLFontFreetype::getGlyphInfo(llwchar wch, EFontGlyphType glyph_type) const
{
- std::pair<char_glyph_info_map_t::iterator, char_glyph_info_map_t::iterator> range_it = mCharGlyphInfoMap.equal_range(wch);
+ std::pair<char_glyph_info_map_t::iterator, char_glyph_info_map_t::iterator> range_it = mCharGlyphInfoMap.equal_range(wch);
- char_glyph_info_map_t::iterator iter = (EFontGlyphType::Unspecified != glyph_type)
- ? std::find_if(range_it.first, range_it.second, [&glyph_type](const char_glyph_info_map_t::value_type& entry) { return entry.second->mGlyphType == glyph_type; })
- : range_it.first;
- if (iter != range_it.second)
- {
- return iter->second;
- }
- else
- {
- // this glyph doesn't yet exist, so render it and return the result
- return addGlyph(wch, (EFontGlyphType::Unspecified != glyph_type) ? glyph_type : EFontGlyphType::Grayscale);
- }
+ char_glyph_info_map_t::iterator iter = (EFontGlyphType::Unspecified != glyph_type)
+ ? std::find_if(range_it.first, range_it.second, [&glyph_type](const char_glyph_info_map_t::value_type& entry) { return entry.second->mGlyphType == glyph_type; })
+ : range_it.first;
+ if (iter != range_it.second)
+ {
+ return iter->second;
+ }
+ else
+ {
+ // this glyph doesn't yet exist, so render it and return the result
+ return addGlyph(wch, (EFontGlyphType::Unspecified != glyph_type) ? glyph_type : EFontGlyphType::Grayscale);
+ }
}
void LLFontFreetype::insertGlyphInfo(llwchar wch, LLFontGlyphInfo* gi) const
{
- llassert(gi->mGlyphType < EFontGlyphType::Count);
- std::pair<char_glyph_info_map_t::iterator, char_glyph_info_map_t::iterator> range_it = mCharGlyphInfoMap.equal_range(wch);
+ llassert(gi->mGlyphType < EFontGlyphType::Count);
+ std::pair<char_glyph_info_map_t::iterator, char_glyph_info_map_t::iterator> range_it = mCharGlyphInfoMap.equal_range(wch);
- char_glyph_info_map_t::iterator iter =
- std::find_if(range_it.first, range_it.second, [&gi](const char_glyph_info_map_t::value_type& entry) { return entry.second->mGlyphType == gi->mGlyphType; });
- if (iter != range_it.second)
- {
- delete iter->second;
- iter->second = gi;
- }
- else
- {
- mCharGlyphInfoMap.insert(std::make_pair(wch, gi));
- }
+ char_glyph_info_map_t::iterator iter =
+ std::find_if(range_it.first, range_it.second, [&gi](const char_glyph_info_map_t::value_type& entry) { return entry.second->mGlyphType == gi->mGlyphType; });
+ if (iter != range_it.second)
+ {
+ delete iter->second;
+ iter->second = gi;
+ }
+ else
+ {
+ mCharGlyphInfoMap.insert(std::make_pair(wch, gi));
+ }
}
void LLFontFreetype::renderGlyph(EFontGlyphType bitmap_type, U32 glyph_index) const
{
- if (mFTFace == NULL)
- return;
+ if (mFTFace == NULL)
+ return;
- FT_Int32 load_flags = FT_LOAD_FORCE_AUTOHINT;
- if (EFontGlyphType::Color == bitmap_type)
- {
- // We may not actually get a color render so our caller should always examine mFTFace->glyph->bitmap.pixel_mode
- load_flags |= FT_LOAD_COLOR;
- }
+ FT_Int32 load_flags = FT_LOAD_FORCE_AUTOHINT;
+ if (EFontGlyphType::Color == bitmap_type)
+ {
+ // We may not actually get a color render so our caller should always examine mFTFace->glyph->bitmap.pixel_mode
+ load_flags |= FT_LOAD_COLOR;
+ }
- FT_Error error = FT_Load_Glyph(mFTFace, glyph_index, load_flags);
- if (FT_Err_Ok != error)
- {
- std::string message = llformat(
- "Error %d (%s) loading glyph %u: bitmap_type=%u, load_flags=%d",
- error, FT_Error_String(error), glyph_index, bitmap_type, load_flags);
- LL_WARNS_ONCE() << message << LL_ENDL;
- error = FT_Load_Glyph(mFTFace, glyph_index, load_flags ^ FT_LOAD_COLOR);
- llassert_always_msg(FT_Err_Ok == error, message.c_str());
- }
+ FT_Error error = FT_Load_Glyph(mFTFace, glyph_index, load_flags);
+ if (FT_Err_Ok != error)
+ {
+ std::string message = llformat(
+ "Error %d (%s) loading glyph %u: bitmap_type=%u, load_flags=%d",
+ error, FT_Error_String(error), glyph_index, bitmap_type, load_flags);
+ LL_WARNS_ONCE() << message << LL_ENDL;
+ error = FT_Load_Glyph(mFTFace, glyph_index, load_flags ^ FT_LOAD_COLOR);
+ llassert_always_msg(FT_Err_Ok == error, message.c_str());
+ }
- llassert_always(! FT_Render_Glyph(mFTFace->glyph, gFontRenderMode) );
+ llassert_always(! FT_Render_Glyph(mFTFace->glyph, gFontRenderMode) );
- mRenderGlyphCount++;
+ mRenderGlyphCount++;
}
void LLFontFreetype::reset(F32 vert_dpi, F32 horz_dpi)
{
- resetBitmapCache();
- loadFace(mName, mPointSize, vert_dpi ,horz_dpi, mIsFallback, 0);
- if (!mIsFallback)
- {
- // This is the head of the list - need to rebuild ourself and all fallbacks.
- if (mFallbackFonts.empty())
- {
- LL_WARNS() << "LLFontGL::reset(), no fallback fonts present" << LL_ENDL;
- }
- else
- {
- for (fallback_font_vector_t::iterator it = mFallbackFonts.begin(); it != mFallbackFonts.end(); ++it)
- {
- it->first->reset(vert_dpi, horz_dpi);
- }
- }
- }
+ resetBitmapCache();
+ loadFace(mName, mPointSize, vert_dpi ,horz_dpi, mIsFallback, 0);
+ if (!mIsFallback)
+ {
+ // This is the head of the list - need to rebuild ourself and all fallbacks.
+ if (mFallbackFonts.empty())
+ {
+ LL_WARNS() << "LLFontGL::reset(), no fallback fonts present" << LL_ENDL;
+ }
+ else
+ {
+ for (fallback_font_vector_t::iterator it = mFallbackFonts.begin(); it != mFallbackFonts.end(); ++it)
+ {
+ it->first->reset(vert_dpi, horz_dpi);
+ }
+ }
+ }
}
void LLFontFreetype::resetBitmapCache()
{
- for (char_glyph_info_map_t::iterator it = mCharGlyphInfoMap.begin(), end_it = mCharGlyphInfoMap.end();
- it != end_it;
- ++it)
- {
- delete it->second;
- }
- mCharGlyphInfoMap.clear();
- mFontBitmapCachep->reset();
+ for (char_glyph_info_map_t::iterator it = mCharGlyphInfoMap.begin(), end_it = mCharGlyphInfoMap.end();
+ it != end_it;
+ ++it)
+ {
+ delete it->second;
+ }
+ mCharGlyphInfoMap.clear();
+ mFontBitmapCachep->reset();
- // 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, EFontGlyphType::Grayscale);
- }
+ // 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, EFontGlyphType::Grayscale);
+ }
}
void LLFontFreetype::destroyGL()
{
- mFontBitmapCachep->destroyGL();
+ mFontBitmapCachep->destroyGL();
}
const std::string &LLFontFreetype::getName() const
{
- return mName;
+ return mName;
}
static void dumpFontBitmap(const LLImageRaw* image_raw, const std::string& file_name)
{
- LLPointer<LLImagePNG> tmpImage = new LLImagePNG();
- if ( (tmpImage->encode(image_raw, 0.0f)) && (tmpImage->save(gDirUtilp->getExpandedFilename(LL_PATH_LOGS, file_name))) )
- {
- LL_INFOS("Font") << "Successfully saved " << file_name << LL_ENDL;
- }
- else
- {
- LL_WARNS("Font") << "Failed to save " << file_name << LL_ENDL;
- }
+ LLPointer<LLImagePNG> tmpImage = new LLImagePNG();
+ if ( (tmpImage->encode(image_raw, 0.0f)) && (tmpImage->save(gDirUtilp->getExpandedFilename(LL_PATH_LOGS, file_name))) )
+ {
+ LL_INFOS("Font") << "Successfully saved " << file_name << LL_ENDL;
+ }
+ else
+ {
+ LL_WARNS("Font") << "Failed to save " << file_name << LL_ENDL;
+ }
}
void LLFontFreetype::dumpFontBitmaps() const
{
- // Dump all the regular bitmaps (if any)
- for (int idx = 0, cnt = mFontBitmapCachep->getNumBitmaps(EFontGlyphType::Grayscale); idx < cnt; idx++)
- {
- dumpFontBitmap(mFontBitmapCachep->getImageRaw(EFontGlyphType::Grayscale, idx), llformat("%s_%d_%d_%d.png", mFTFace->family_name, (int)(mPointSize * 10), mStyle, idx));
- }
+ // Dump all the regular bitmaps (if any)
+ for (int idx = 0, cnt = mFontBitmapCachep->getNumBitmaps(EFontGlyphType::Grayscale); idx < cnt; idx++)
+ {
+ dumpFontBitmap(mFontBitmapCachep->getImageRaw(EFontGlyphType::Grayscale, idx), llformat("%s_%d_%d_%d.png", mFTFace->family_name, (int)(mPointSize * 10), mStyle, idx));
+ }
- // Dump all the color bitmaps (if any)
- for (int idx = 0, cnt = mFontBitmapCachep->getNumBitmaps(EFontGlyphType::Color); idx < cnt; idx++)
- {
- dumpFontBitmap(mFontBitmapCachep->getImageRaw(EFontGlyphType::Color, idx), llformat("%s_%d_%d_%d_clr.png", mFTFace->family_name, (int)(mPointSize * 10), mStyle, idx));
- }
+ // Dump all the color bitmaps (if any)
+ for (int idx = 0, cnt = mFontBitmapCachep->getNumBitmaps(EFontGlyphType::Color); idx < cnt; idx++)
+ {
+ dumpFontBitmap(mFontBitmapCachep->getImageRaw(EFontGlyphType::Color, idx), llformat("%s_%d_%d_%d_clr.png", mFTFace->family_name, (int)(mPointSize * 10), mStyle, idx));
+ }
}
const LLFontBitmapCache* LLFontFreetype::getFontBitmapCache() const
{
- return mFontBitmapCachep;
+ return mFontBitmapCachep;
}
void LLFontFreetype::setStyle(U8 style)
{
- mStyle = style;
+ mStyle = style;
}
U8 LLFontFreetype::getStyle() const
{
- return mStyle;
+ return mStyle;
}
bool LLFontFreetype::setSubImageBGRA(U32 x, U32 y, U32 bitmap_num, U16 width, U16 height, const U8* data, U32 stride) const
{
- LLImageRaw* image_raw = mFontBitmapCachep->getImageRaw(EFontGlyphType::Color, bitmap_num);
- llassert(!mIsFallback);
- llassert(image_raw && (image_raw->getComponents() == 4));
+ LLImageRaw* image_raw = mFontBitmapCachep->getImageRaw(EFontGlyphType::Color, bitmap_num);
+ llassert(!mIsFallback);
+ llassert(image_raw && (image_raw->getComponents() == 4));
- // NOTE: inspired by LLImageRaw::setSubImage()
- U32* image_data = (U32*)image_raw->getData();
- if (!image_data)
- {
- return false;
- }
+ // NOTE: inspired by LLImageRaw::setSubImage()
+ U32* image_data = (U32*)image_raw->getData();
+ if (!image_data)
+ {
+ return false;
+ }
- for (U32 idxRow = 0; idxRow < height; idxRow++)
- {
- const U32 nSrcRow = height - 1 - idxRow;
- const U32 nSrcOffset = nSrcRow * width * image_raw->getComponents();
- const U32 nDstOffset = (y + idxRow) * image_raw->getWidth() + x;
+ for (U32 idxRow = 0; idxRow < height; idxRow++)
+ {
+ const U32 nSrcRow = height - 1 - idxRow;
+ const U32 nSrcOffset = nSrcRow * width * image_raw->getComponents();
+ const U32 nDstOffset = (y + idxRow) * image_raw->getWidth() + x;
- for (U32 idxCol = 0; idxCol < width; idxCol++)
- {
- U32 nTemp = nSrcOffset + idxCol * 4;
- image_data[nDstOffset + idxCol] = data[nTemp + 3] << 24 | data[nTemp] << 16 | data[nTemp + 1] << 8 | data[nTemp + 2];
- }
- }
+ for (U32 idxCol = 0; idxCol < width; idxCol++)
+ {
+ U32 nTemp = nSrcOffset + idxCol * 4;
+ image_data[nDstOffset + idxCol] = data[nTemp + 3] << 24 | data[nTemp] << 16 | data[nTemp + 1] << 8 | data[nTemp + 2];
+ }
+ }
- return true;
+ return true;
}
void LLFontFreetype::setSubImageLuminanceAlpha(U32 x, U32 y, U32 bitmap_num, U32 width, U32 height, U8 *data, S32 stride) const
{
- LLImageRaw *image_raw = mFontBitmapCachep->getImageRaw(EFontGlyphType::Grayscale, bitmap_num);
+ LLImageRaw *image_raw = mFontBitmapCachep->getImageRaw(EFontGlyphType::Grayscale, bitmap_num);
- llassert(!mIsFallback);
- llassert(image_raw && (image_raw->getComponents() == 2));
+ llassert(!mIsFallback);
+ llassert(image_raw && (image_raw->getComponents() == 2));
- U8 *target = image_raw->getData();
+ U8 *target = image_raw->getData();
llassert(target);
- if (!data || !target)
- {
- return;
- }
-
- if (0 == stride)
- stride = width;
-
- U32 i, j;
- U32 to_offset;
- U32 from_offset;
- U32 target_width = image_raw->getWidth();
- for (i = 0; i < height; i++)
- {
- to_offset = (y + i)*target_width + x;
- from_offset = (height - 1 - i)*stride;
- for (j = 0; j < width; j++)
- {
- *(target + to_offset*2 + 1) = *(data + from_offset);
- to_offset++;
- from_offset++;
- }
- }
+ if (!data || !target)
+ {
+ return;
+ }
+
+ if (0 == stride)
+ stride = width;
+
+ U32 i, j;
+ U32 to_offset;
+ U32 from_offset;
+ U32 target_width = image_raw->getWidth();
+ for (i = 0; i < height; i++)
+ {
+ to_offset = (y + i)*target_width + x;
+ from_offset = (height - 1 - i)*stride;
+ for (j = 0; j < width; j++)
+ {
+ *(target + to_offset*2 + 1) = *(data + from_offset);
+ to_offset++;
+ from_offset++;
+ }
+ }
}
diff --git a/indra/llrender/llfontfreetype.h b/indra/llrender/llfontfreetype.h
index b036d337ba..19112830a4 100644
--- a/indra/llrender/llfontfreetype.h
+++ b/indra/llrender/llfontfreetype.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file llfontfreetype.h
* @brief Font library wrapper
*
* $LicenseInfo:firstyear=2002&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -35,8 +35,8 @@
#include "llfontbitmapcache.h"
// Hack. FT_Face is just a typedef for a pointer to a struct,
-// but there's no simple forward declarations file for FreeType,
-// and the main include file is 200K.
+// but there's no simple forward declarations file for FreeType,
+// and the main include file is 200K.
// We'll forward declare the struct here. JC
struct FT_FaceRec_;
typedef struct FT_FaceRec_* LLFT_Face;
@@ -46,34 +46,34 @@ typedef struct FT_StreamRec_ LLFT_Stream;
class LLFontManager
{
public:
- static void initClass();
- static void cleanupClass();
+ static void initClass();
+ static void cleanupClass();
private:
- LLFontManager();
- ~LLFontManager();
+ LLFontManager();
+ ~LLFontManager();
};
struct LLFontGlyphInfo
{
- LLFontGlyphInfo(U32 index, EFontGlyphType glyph_type);
- LLFontGlyphInfo(const LLFontGlyphInfo& fgi);
-
- U32 mGlyphIndex;
- EFontGlyphType mGlyphType;
-
- // Metrics
- S32 mWidth; // In pixels
- S32 mHeight; // In pixels
- F32 mXAdvance; // In pixels
- F32 mYAdvance; // In pixels
-
- // Information for actually rendering
- S32 mXBitmapOffset; // Offset to the origin in the bitmap
- S32 mYBitmapOffset; // Offset to the origin in the bitmap
- S32 mXBearing; // Distance from baseline to left in pixels
- S32 mYBearing; // Distance from baseline to top in pixels
- std::pair<EFontGlyphType, S32> mBitmapEntry; // Which bitmap in the bitmap cache contains this glyph
+ LLFontGlyphInfo(U32 index, EFontGlyphType glyph_type);
+ LLFontGlyphInfo(const LLFontGlyphInfo& fgi);
+
+ U32 mGlyphIndex;
+ EFontGlyphType mGlyphType;
+
+ // Metrics
+ S32 mWidth; // In pixels
+ S32 mHeight; // In pixels
+ F32 mXAdvance; // In pixels
+ F32 mYAdvance; // In pixels
+
+ // Information for actually rendering
+ S32 mXBitmapOffset; // Offset to the origin in the bitmap
+ S32 mYBitmapOffset; // Offset to the origin in the bitmap
+ S32 mXBearing; // Distance from baseline to left in pixels
+ S32 mYBearing; // Distance from baseline to top in pixels
+ std::pair<EFontGlyphType, S32> mBitmapEntry; // Which bitmap in the bitmap cache contains this glyph
};
extern LLFontManager *gFontManagerp;
@@ -81,113 +81,113 @@ extern LLFontManager *gFontManagerp;
class LLFontFreetype : public LLRefCount
{
public:
- LLFontFreetype();
- ~LLFontFreetype();
+ LLFontFreetype();
+ ~LLFontFreetype();
- // is_fallback should be true for fallback fonts that aren't used
- // to render directly (Unicode backup, primarily)
- BOOL loadFace(const std::string& filename, F32 point_size, F32 vert_dpi, F32 horz_dpi, bool is_fallback, S32 face_n);
+ // is_fallback should be true for fallback fonts that aren't used
+ // to render directly (Unicode backup, primarily)
+ BOOL loadFace(const std::string& filename, F32 point_size, F32 vert_dpi, F32 horz_dpi, bool is_fallback, S32 face_n);
- S32 getNumFaces(const std::string& filename);
+ S32 getNumFaces(const std::string& filename);
#ifdef LL_WINDOWS
- S32 ftOpenFace(const std::string& filename, S32 face_n);
- void clearFontStreams();
+ S32 ftOpenFace(const std::string& filename, S32 face_n);
+ void clearFontStreams();
#endif
- typedef std::function<bool(llwchar)> char_functor_t;
- void addFallbackFont(const LLPointer<LLFontFreetype>& fallback_font, const char_functor_t& functor = nullptr);
+ typedef std::function<bool(llwchar)> char_functor_t;
+ void addFallbackFont(const LLPointer<LLFontFreetype>& fallback_font, const char_functor_t& functor = nullptr);
- // Global font metrics - in units of pixels
- F32 getLineHeight() const;
- F32 getAscenderHeight() const;
- F32 getDescenderHeight() const;
+ // Global font metrics - in units of pixels
+ F32 getLineHeight() const;
+ F32 getAscenderHeight() const;
+ F32 getDescenderHeight() const;
// For a lowercase "g":
//
-// ------------------------------
-// ^ ^
-// | |
-// xxx x |Ascender
-// x x v |
-// --------- xxxx-------------- Baseline
-// ^ x |
+// ------------------------------
+// ^ ^
+// | |
+// xxx x |Ascender
+// x x v |
+// --------- xxxx-------------- Baseline
+// ^ x |
// | Descender x |
-// v xxxx |LineHeight
+// v xxxx |LineHeight
// ----------------------- |
// v
-// ------------------------------
+// ------------------------------
- enum
- {
- FIRST_CHAR = 32,
- NUM_CHARS = 127 - 32,
- LAST_CHAR_BASIC = 127,
+ enum
+ {
+ FIRST_CHAR = 32,
+ NUM_CHARS = 127 - 32,
+ LAST_CHAR_BASIC = 127,
- // Need full 8-bit ascii range for spanish
- NUM_CHARS_FULL = 255 - 32,
- LAST_CHAR_FULL = 255
- };
+ // Need full 8-bit ascii range for spanish
+ NUM_CHARS_FULL = 255 - 32,
+ LAST_CHAR_FULL = 255
+ };
- 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
+ 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, EFontGlyphType glyph_type) const;
+ LLFontGlyphInfo* getGlyphInfo(llwchar wch, EFontGlyphType glyph_type) const;
- void reset(F32 vert_dpi, F32 horz_dpi);
+ void reset(F32 vert_dpi, F32 horz_dpi);
- void destroyGL();
+ void destroyGL();
- const std::string& getName() const;
+ const std::string& getName() const;
- void dumpFontBitmaps() const;
- const LLFontBitmapCache* getFontBitmapCache() const;
+ void dumpFontBitmaps() const;
+ const LLFontBitmapCache* getFontBitmapCache() const;
- void setStyle(U8 style);
- U8 getStyle() const;
+ void setStyle(U8 style);
+ U8 getStyle() const;
private:
- void resetBitmapCache();
- void setSubImageLuminanceAlpha(U32 x, U32 y, U32 bitmap_num, U32 width, U32 height, U8 *data, S32 stride = 0) const;
- bool setSubImageBGRA(U32 x, U32 y, U32 bitmap_num, U16 width, U16 height, const U8* data, U32 stride) const;
- BOOL hasGlyph(llwchar wch) const; // Has a glyph for this character
- LLFontGlyphInfo* addGlyph(llwchar wch, EFontGlyphType glyph_type) const; // Add a new character to the font if necessary
- LLFontGlyphInfo* addGlyphFromFont(const LLFontFreetype *fontp, llwchar wch, U32 glyph_index, EFontGlyphType bitmap_type) const; // Add a glyph from this font to the other (returns the glyph_index, 0 if not found)
- void renderGlyph(EFontGlyphType bitmap_type, U32 glyph_index) const;
- void insertGlyphInfo(llwchar wch, LLFontGlyphInfo* gi) const;
+ void resetBitmapCache();
+ void setSubImageLuminanceAlpha(U32 x, U32 y, U32 bitmap_num, U32 width, U32 height, U8 *data, S32 stride = 0) const;
+ bool setSubImageBGRA(U32 x, U32 y, U32 bitmap_num, U16 width, U16 height, const U8* data, U32 stride) const;
+ BOOL hasGlyph(llwchar wch) const; // Has a glyph for this character
+ LLFontGlyphInfo* addGlyph(llwchar wch, EFontGlyphType glyph_type) const; // Add a new character to the font if necessary
+ LLFontGlyphInfo* addGlyphFromFont(const LLFontFreetype *fontp, llwchar wch, U32 glyph_index, EFontGlyphType bitmap_type) const; // Add a glyph from this font to the other (returns the glyph_index, 0 if not found)
+ void renderGlyph(EFontGlyphType bitmap_type, U32 glyph_index) const;
+ void insertGlyphInfo(llwchar wch, LLFontGlyphInfo* gi) const;
- std::string mName;
+ std::string mName;
- U8 mStyle;
+ U8 mStyle;
- F32 mPointSize;
- F32 mAscender;
- F32 mDescender;
- F32 mLineHeight;
+ F32 mPointSize;
+ F32 mAscender;
+ F32 mDescender;
+ F32 mLineHeight;
- LLFT_Face mFTFace;
+ LLFT_Face mFTFace;
#ifdef LL_WINDOWS
- llifstream *pFileStream;
- LLFT_Stream *pFtStream;
+ llifstream *pFileStream;
+ LLFT_Stream *pFtStream;
#endif
- BOOL mIsFallback;
- typedef std::pair<LLPointer<LLFontFreetype>, char_functor_t> fallback_font_t;
- typedef std::vector<fallback_font_t> fallback_font_vector_t;
- fallback_font_vector_t mFallbackFonts; // A list of fallback fonts to look for glyphs in (for Unicode chars)
+ BOOL mIsFallback;
+ typedef std::pair<LLPointer<LLFontFreetype>, char_functor_t> fallback_font_t;
+ typedef std::vector<fallback_font_t> fallback_font_vector_t;
+ fallback_font_vector_t mFallbackFonts; // A list of fallback fonts to look for glyphs in (for Unicode chars)
- // *NOTE: the same glyph can be present with multiple representations (but the pointer is always unique)
- typedef boost::unordered_multimap<llwchar, LLFontGlyphInfo*> char_glyph_info_map_t;
- mutable char_glyph_info_map_t mCharGlyphInfoMap; // Information about glyph location in bitmap
+ // *NOTE: the same glyph can be present with multiple representations (but the pointer is always unique)
+ typedef boost::unordered_multimap<llwchar, LLFontGlyphInfo*> char_glyph_info_map_t;
+ mutable char_glyph_info_map_t mCharGlyphInfoMap; // Information about glyph location in bitmap
- mutable LLFontBitmapCache* mFontBitmapCachep;
+ mutable LLFontBitmapCache* mFontBitmapCachep;
- mutable S32 mRenderGlyphCount;
- mutable S32 mAddGlyphCount;
+ mutable S32 mRenderGlyphCount;
+ mutable S32 mAddGlyphCount;
};
#endif // LL_FONTFREETYPE_H
diff --git a/indra/llrender/llfontfreetypesvg.cpp b/indra/llrender/llfontfreetypesvg.cpp
index 6c44fdd150..e33da7cf86 100644
--- a/indra/llrender/llfontfreetypesvg.cpp
+++ b/indra/llrender/llfontfreetypesvg.cpp
@@ -44,21 +44,21 @@
struct LLSvgRenderData
{
- FT_UInt GlyphIndex = 0;
- FT_Error Error = FT_Err_Ok; // FreeType currently (@2.12.1) ignores the error value returned by the preset glyph slot callback so we return it at render time
- // (See https://github.com/freetype/freetype/blob/5faa1df8b93ebecf0f8fd5fe8fda7b9082eddced/src/base/ftobjs.c#L1170)
- NSVGimage* pNSvgImage = nullptr;
- float Scale = 0.f;
+ FT_UInt GlyphIndex = 0;
+ FT_Error Error = FT_Err_Ok; // FreeType currently (@2.12.1) ignores the error value returned by the preset glyph slot callback so we return it at render time
+ // (See https://github.com/freetype/freetype/blob/5faa1df8b93ebecf0f8fd5fe8fda7b9082eddced/src/base/ftobjs.c#L1170)
+ NSVGimage* pNSvgImage = nullptr;
+ float Scale = 0.f;
};
// static
FT_Error LLFontFreeTypeSvgRenderer::OnInit(FT_Pointer* state)
{
- // The SVG driver hook state is shared across all callback invocations; since our state is lightweight
- // we store it in the glyph instead.
- *state = nullptr;
+ // The SVG driver hook state is shared across all callback invocations; since our state is lightweight
+ // we store it in the glyph instead.
+ *state = nullptr;
- return FT_Err_Ok;
+ return FT_Err_Ok;
}
// static
@@ -69,141 +69,141 @@ void LLFontFreeTypeSvgRenderer::OnFree(FT_Pointer* state)
// static
void LLFontFreeTypeSvgRenderer::OnDataFinalizer(void* objectp)
{
- FT_GlyphSlot glyph_slot = static_cast<FT_GlyphSlot>(objectp);
+ FT_GlyphSlot glyph_slot = static_cast<FT_GlyphSlot>(objectp);
- LLSvgRenderData* pData = static_cast<LLSvgRenderData*>(glyph_slot->generic.data);
- glyph_slot->generic.data = nullptr;
- glyph_slot->generic.finalizer = nullptr;
- delete(pData);
+ LLSvgRenderData* pData = static_cast<LLSvgRenderData*>(glyph_slot->generic.data);
+ glyph_slot->generic.data = nullptr;
+ glyph_slot->generic.finalizer = nullptr;
+ delete(pData);
}
//static
FT_Error LLFontFreeTypeSvgRenderer::OnPresetGlypthSlot(FT_GlyphSlot glyph_slot, FT_Bool cache, FT_Pointer*)
{
#ifndef LL_NO_OTSVG
- FT_SVG_Document document = static_cast<FT_SVG_Document>(glyph_slot->other);
-
- llassert(!glyph_slot->generic.data || !cache || glyph_slot->glyph_index == ((LLSvgRenderData*)glyph_slot->generic.data)->GlyphIndex);
- if (!glyph_slot->generic.data)
- {
- glyph_slot->generic.data = new LLSvgRenderData();
- glyph_slot->generic.finalizer = LLFontFreeTypeSvgRenderer::OnDataFinalizer;
- }
- LLSvgRenderData* datap = static_cast<LLSvgRenderData*>(glyph_slot->generic.data);
- if (!cache)
- {
- datap->GlyphIndex = glyph_slot->glyph_index;
- datap->Error = FT_Err_Ok;
- }
-
- // NOTE: nsvgParse modifies the input string so we need a temporary copy
- llassert(!datap->pNSvgImage || cache);
- if (!datap->pNSvgImage)
- {
- char* document_buffer = new char[document->svg_document_length + 1];
- memcpy(document_buffer, document->svg_document, document->svg_document_length);
- document_buffer[document->svg_document_length] = '\0';
-
- datap->pNSvgImage = nsvgParse(document_buffer, "px", 0.);
-
- delete[] document_buffer;
- }
-
- if (!datap->pNSvgImage)
- {
- datap->Error = FT_Err_Invalid_SVG_Document;
- return FT_Err_Invalid_SVG_Document;
- }
-
- // We don't (currently) support transformations so test for an identity rotation matrix + zero translation
- if (document->transform.xx != 1 << 16 || document->transform.yx != 0 ||
- document->transform.xy != 0 || document->transform.yy != 1 << 16 ||
- document->delta.x > 0 || document->delta.y > 0)
- {
- datap->Error = FT_Err_Unimplemented_Feature;
- return FT_Err_Unimplemented_Feature;
- }
-
- float svg_width = datap->pNSvgImage->width;
- float svg_height = datap->pNSvgImage->height;
- if (svg_width == 0.f || svg_height == 0.f)
- {
- svg_width = document->units_per_EM;
- svg_height = document->units_per_EM;
- }
-
- float svg_x_scale = (float)document->metrics.x_ppem / floorf(svg_width);
- float svg_y_scale = (float)document->metrics.y_ppem / floorf(svg_height);
- float svg_scale = llmin(svg_x_scale, svg_y_scale);
- datap->Scale = svg_scale;
-
- glyph_slot->bitmap.width = floorf(svg_width) * svg_scale;
- glyph_slot->bitmap.rows = floorf(svg_height) * svg_scale;
- glyph_slot->bitmap_left = (document->metrics.x_ppem - glyph_slot->bitmap.width) / 2;
- glyph_slot->bitmap_top = glyph_slot->face->size->metrics.ascender / 64.f;
- glyph_slot->bitmap.pitch = glyph_slot->bitmap.width * 4;
- glyph_slot->bitmap.pixel_mode = FT_PIXEL_MODE_BGRA;
-
- /* Copied as-is from fcft (MIT license) */
-
- // Compute all the bearings and set them correctly. The outline is scaled already, we just need to use the bounding box.
- float horiBearingX = 0.;
- float horiBearingY = -glyph_slot->bitmap_top;
-
- // XXX parentheses correct?
- float vertBearingX = glyph_slot->metrics.horiBearingX / 64.0f - glyph_slot->metrics.horiAdvance / 64.0f / 2;
- float vertBearingY = (glyph_slot->metrics.vertAdvance / 64.0f - glyph_slot->metrics.height / 64.0f) / 2;
-
- // Do conversion in two steps to avoid 'bad function cast' warning
- glyph_slot->metrics.width = glyph_slot->bitmap.width * 64;
- glyph_slot->metrics.height = glyph_slot->bitmap.rows * 64;
- glyph_slot->metrics.horiBearingX = horiBearingX * 64;
- glyph_slot->metrics.horiBearingY = horiBearingY * 64;
- glyph_slot->metrics.vertBearingX = vertBearingX * 64;
- glyph_slot->metrics.vertBearingY = vertBearingY * 64;
- if (glyph_slot->metrics.vertAdvance == 0)
- {
- glyph_slot->metrics.vertAdvance = glyph_slot->bitmap.rows * 1.2f * 64;
- }
-
- return FT_Err_Ok;
+ FT_SVG_Document document = static_cast<FT_SVG_Document>(glyph_slot->other);
+
+ llassert(!glyph_slot->generic.data || !cache || glyph_slot->glyph_index == ((LLSvgRenderData*)glyph_slot->generic.data)->GlyphIndex);
+ if (!glyph_slot->generic.data)
+ {
+ glyph_slot->generic.data = new LLSvgRenderData();
+ glyph_slot->generic.finalizer = LLFontFreeTypeSvgRenderer::OnDataFinalizer;
+ }
+ LLSvgRenderData* datap = static_cast<LLSvgRenderData*>(glyph_slot->generic.data);
+ if (!cache)
+ {
+ datap->GlyphIndex = glyph_slot->glyph_index;
+ datap->Error = FT_Err_Ok;
+ }
+
+ // NOTE: nsvgParse modifies the input string so we need a temporary copy
+ llassert(!datap->pNSvgImage || cache);
+ if (!datap->pNSvgImage)
+ {
+ char* document_buffer = new char[document->svg_document_length + 1];
+ memcpy(document_buffer, document->svg_document, document->svg_document_length);
+ document_buffer[document->svg_document_length] = '\0';
+
+ datap->pNSvgImage = nsvgParse(document_buffer, "px", 0.);
+
+ delete[] document_buffer;
+ }
+
+ if (!datap->pNSvgImage)
+ {
+ datap->Error = FT_Err_Invalid_SVG_Document;
+ return FT_Err_Invalid_SVG_Document;
+ }
+
+ // We don't (currently) support transformations so test for an identity rotation matrix + zero translation
+ if (document->transform.xx != 1 << 16 || document->transform.yx != 0 ||
+ document->transform.xy != 0 || document->transform.yy != 1 << 16 ||
+ document->delta.x > 0 || document->delta.y > 0)
+ {
+ datap->Error = FT_Err_Unimplemented_Feature;
+ return FT_Err_Unimplemented_Feature;
+ }
+
+ float svg_width = datap->pNSvgImage->width;
+ float svg_height = datap->pNSvgImage->height;
+ if (svg_width == 0.f || svg_height == 0.f)
+ {
+ svg_width = document->units_per_EM;
+ svg_height = document->units_per_EM;
+ }
+
+ float svg_x_scale = (float)document->metrics.x_ppem / floorf(svg_width);
+ float svg_y_scale = (float)document->metrics.y_ppem / floorf(svg_height);
+ float svg_scale = llmin(svg_x_scale, svg_y_scale);
+ datap->Scale = svg_scale;
+
+ glyph_slot->bitmap.width = floorf(svg_width) * svg_scale;
+ glyph_slot->bitmap.rows = floorf(svg_height) * svg_scale;
+ glyph_slot->bitmap_left = (document->metrics.x_ppem - glyph_slot->bitmap.width) / 2;
+ glyph_slot->bitmap_top = glyph_slot->face->size->metrics.ascender / 64.f;
+ glyph_slot->bitmap.pitch = glyph_slot->bitmap.width * 4;
+ glyph_slot->bitmap.pixel_mode = FT_PIXEL_MODE_BGRA;
+
+ /* Copied as-is from fcft (MIT license) */
+
+ // Compute all the bearings and set them correctly. The outline is scaled already, we just need to use the bounding box.
+ float horiBearingX = 0.;
+ float horiBearingY = -glyph_slot->bitmap_top;
+
+ // XXX parentheses correct?
+ float vertBearingX = glyph_slot->metrics.horiBearingX / 64.0f - glyph_slot->metrics.horiAdvance / 64.0f / 2;
+ float vertBearingY = (glyph_slot->metrics.vertAdvance / 64.0f - glyph_slot->metrics.height / 64.0f) / 2;
+
+ // Do conversion in two steps to avoid 'bad function cast' warning
+ glyph_slot->metrics.width = glyph_slot->bitmap.width * 64;
+ glyph_slot->metrics.height = glyph_slot->bitmap.rows * 64;
+ glyph_slot->metrics.horiBearingX = horiBearingX * 64;
+ glyph_slot->metrics.horiBearingY = horiBearingY * 64;
+ glyph_slot->metrics.vertBearingX = vertBearingX * 64;
+ glyph_slot->metrics.vertBearingY = vertBearingY * 64;
+ if (glyph_slot->metrics.vertAdvance == 0)
+ {
+ glyph_slot->metrics.vertAdvance = glyph_slot->bitmap.rows * 1.2f * 64;
+ }
+
+ return FT_Err_Ok;
#else
- return FT_Err_Unimplemented_Feature;
+ return FT_Err_Unimplemented_Feature;
#endif
}
// static
FT_Error LLFontFreeTypeSvgRenderer::OnRender(FT_GlyphSlot glyph_slot, FT_Pointer*)
{
- LLSvgRenderData* datap = static_cast<LLSvgRenderData*>(glyph_slot->generic.data);
- llassert(FT_Err_Ok == datap->Error);
- if (FT_Err_Ok != datap->Error)
- {
- return datap->Error;
- }
-
- // Render to glyph bitmap
- NSVGrasterizer* nsvgRasterizer = nsvgCreateRasterizer();
- nsvgRasterize(nsvgRasterizer, datap->pNSvgImage, 0, 0, datap->Scale, glyph_slot->bitmap.buffer, glyph_slot->bitmap.width, glyph_slot->bitmap.rows, glyph_slot->bitmap.pitch);
- nsvgDeleteRasterizer(nsvgRasterizer);
- nsvgDelete(datap->pNSvgImage);
- datap->pNSvgImage = nullptr;
-
- // Convert from RGBA to BGRA
- U32* pixel_buffer = (U32*)glyph_slot->bitmap.buffer; U8* byte_buffer = glyph_slot->bitmap.buffer;
- for (size_t y = 0, h = glyph_slot->bitmap.rows; y < h; y++)
- {
- for (size_t x = 0, w = glyph_slot->bitmap.pitch / 4; x < w; x++)
- {
- size_t pixel_idx = y * w + x;
- size_t byte_idx = pixel_idx * 4;
- U8 alpha = byte_buffer[byte_idx + 3];
- // Store as ARGB (*TODO - do we still have to care about endianness?)
- pixel_buffer[y * w + x] = alpha << 24 | (byte_buffer[byte_idx] * alpha / 0xFF) << 16 | (byte_buffer[byte_idx + 1] * alpha / 0xFF) << 8 | (byte_buffer[byte_idx + 2] * alpha / 0xFF);
- }
- }
-
- glyph_slot->format = FT_GLYPH_FORMAT_BITMAP;
- glyph_slot->bitmap.pixel_mode = FT_PIXEL_MODE_BGRA;
- return FT_Err_Ok;
+ LLSvgRenderData* datap = static_cast<LLSvgRenderData*>(glyph_slot->generic.data);
+ llassert(FT_Err_Ok == datap->Error);
+ if (FT_Err_Ok != datap->Error)
+ {
+ return datap->Error;
+ }
+
+ // Render to glyph bitmap
+ NSVGrasterizer* nsvgRasterizer = nsvgCreateRasterizer();
+ nsvgRasterize(nsvgRasterizer, datap->pNSvgImage, 0, 0, datap->Scale, glyph_slot->bitmap.buffer, glyph_slot->bitmap.width, glyph_slot->bitmap.rows, glyph_slot->bitmap.pitch);
+ nsvgDeleteRasterizer(nsvgRasterizer);
+ nsvgDelete(datap->pNSvgImage);
+ datap->pNSvgImage = nullptr;
+
+ // Convert from RGBA to BGRA
+ U32* pixel_buffer = (U32*)glyph_slot->bitmap.buffer; U8* byte_buffer = glyph_slot->bitmap.buffer;
+ for (size_t y = 0, h = glyph_slot->bitmap.rows; y < h; y++)
+ {
+ for (size_t x = 0, w = glyph_slot->bitmap.pitch / 4; x < w; x++)
+ {
+ size_t pixel_idx = y * w + x;
+ size_t byte_idx = pixel_idx * 4;
+ U8 alpha = byte_buffer[byte_idx + 3];
+ // Store as ARGB (*TODO - do we still have to care about endianness?)
+ pixel_buffer[y * w + x] = alpha << 24 | (byte_buffer[byte_idx] * alpha / 0xFF) << 16 | (byte_buffer[byte_idx + 1] * alpha / 0xFF) << 8 | (byte_buffer[byte_idx + 2] * alpha / 0xFF);
+ }
+ }
+
+ glyph_slot->format = FT_GLYPH_FORMAT_BITMAP;
+ glyph_slot->bitmap.pixel_mode = FT_PIXEL_MODE_BGRA;
+ return FT_Err_Ok;
}
diff --git a/indra/llrender/llfontfreetypesvg.h b/indra/llrender/llfontfreetypesvg.h
index 26a533682e..62aefd10b5 100644
--- a/indra/llrender/llfontfreetypesvg.h
+++ b/indra/llrender/llfontfreetypesvg.h
@@ -30,7 +30,7 @@
#include FT_TYPES_H
#include FT_MODULE_H
#ifdef FT_OTSVG_H
- #include FT_OTSVG_H
+ #include FT_OTSVG_H
#else
#define LL_NO_OTSVG
#endif
@@ -39,20 +39,20 @@
class LLFontFreeTypeSvgRenderer
{
public:
- // Called when the very first OT-SVG glyph is rendered (across the entire lifetime of our FT_Library object)
- static FT_Error OnInit(FT_Pointer* state);
+ // Called when the very first OT-SVG glyph is rendered (across the entire lifetime of our FT_Library object)
+ static FT_Error OnInit(FT_Pointer* state);
- // Called when the ot-svg module is being freed (but only called if the init hook was called previously)
- static void OnFree(FT_Pointer* state);
+ // Called when the ot-svg module is being freed (but only called if the init hook was called previously)
+ static void OnFree(FT_Pointer* state);
- // Called to preset the glyph slot, twice per glyph:
- // - when FT_Load_Glyph needs to preset the glyph slot (with cache == false)
- // - right before the svg module calls the render callback hook. (with cache == true)
- static FT_Error OnPresetGlypthSlot(FT_GlyphSlot glyph_slot, FT_Bool cache, FT_Pointer* state);
+ // Called to preset the glyph slot, twice per glyph:
+ // - when FT_Load_Glyph needs to preset the glyph slot (with cache == false)
+ // - right before the svg module calls the render callback hook. (with cache == true)
+ static FT_Error OnPresetGlypthSlot(FT_GlyphSlot glyph_slot, FT_Bool cache, FT_Pointer* state);
- // Called to render an OT-SVG glyph (right after the preset hook OnPresetGlypthSlot was called with cache set to TRUE)
- static FT_Error OnRender(FT_GlyphSlot glyph_slot, FT_Pointer* state);
+ // Called to render an OT-SVG glyph (right after the preset hook OnPresetGlypthSlot was called with cache set to TRUE)
+ static FT_Error OnRender(FT_GlyphSlot glyph_slot, FT_Pointer* state);
- // Called to deallocate our per glyph slot data
- static void OnDataFinalizer(void* objectp);
+ // Called to deallocate our per glyph slot data
+ static void OnDataFinalizer(void* objectp);
};
diff --git a/indra/llrender/llfontgl.cpp b/indra/llrender/llfontgl.cpp
index 53661b6a63..3714bb1883 100644
--- a/indra/llrender/llfontgl.cpp
+++ b/indra/llrender/llfontgl.cpp
@@ -1,25 +1,25 @@
-/**
+/**
* @file llfontgl.cpp
* @brief Wrapper around FreeType
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -81,32 +81,32 @@ LLFontGL::~LLFontGL()
void LLFontGL::reset()
{
- mFontFreetype->reset(sVertDPI, sHorizDPI);
+ mFontFreetype->reset(sVertDPI, sHorizDPI);
}
void LLFontGL::destroyGL()
{
- mFontFreetype->destroyGL();
+ mFontFreetype->destroyGL();
}
BOOL LLFontGL::loadFace(const std::string& filename, F32 point_size, const F32 vert_dpi, const F32 horz_dpi, bool is_fallback, S32 face_n)
{
- if(mFontFreetype == reinterpret_cast<LLFontFreetype*>(NULL))
- {
- mFontFreetype = new LLFontFreetype;
- }
+ if(mFontFreetype == reinterpret_cast<LLFontFreetype*>(NULL))
+ {
+ mFontFreetype = new LLFontFreetype;
+ }
- return mFontFreetype->loadFace(filename, point_size, vert_dpi, horz_dpi, is_fallback, face_n);
+ return mFontFreetype->loadFace(filename, point_size, vert_dpi, horz_dpi, is_fallback, face_n);
}
S32 LLFontGL::getNumFaces(const std::string& filename)
{
- if (mFontFreetype == reinterpret_cast<LLFontFreetype*>(NULL))
- {
- mFontFreetype = new LLFontFreetype;
- }
+ if (mFontFreetype == reinterpret_cast<LLFontFreetype*>(NULL))
+ {
+ mFontFreetype = new LLFontFreetype;
+ }
- return mFontFreetype->getNumFaces(filename);
+ return mFontFreetype->getNumFaces(filename);
}
S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, const LLRect& rect, const LLColor4 &color, HAlign halign, VAlign valign, U8 style,
@@ -116,439 +116,446 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, const LLRect& rect
return render(wstr, begin_offset, rect_float, color, halign, valign, style, shadow, max_chars, right_x, use_ellipses, use_color);
}
-S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, const LLRectf& rect, const LLColor4 &color, HAlign halign, VAlign valign, U8 style,
- ShadowType shadow, S32 max_chars, F32* right_x, BOOL use_ellipses, BOOL use_color) const
+S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, const LLRectf& rect, const LLColor4 &color, HAlign halign, VAlign valign, U8 style,
+ ShadowType shadow, S32 max_chars, F32* right_x, BOOL use_ellipses, BOOL use_color) const
{
- F32 x = rect.mLeft;
- F32 y = 0.f;
+ F32 x = rect.mLeft;
+ F32 y = 0.f;
- switch(valign)
- {
- case TOP:
- y = rect.mTop;
- break;
- case VCENTER:
- y = rect.getCenterY();
- break;
- case BASELINE:
- case BOTTOM:
- y = rect.mBottom;
- break;
- default:
- y = rect.mBottom;
- break;
- }
- return render(wstr, begin_offset, x, y, color, halign, valign, style, shadow, max_chars, rect.getWidth(), right_x, use_ellipses, use_color);
+ switch(valign)
+ {
+ case TOP:
+ y = rect.mTop;
+ break;
+ case VCENTER:
+ y = rect.getCenterY();
+ break;
+ case BASELINE:
+ case BOTTOM:
+ y = rect.mBottom;
+ break;
+ default:
+ y = rect.mBottom;
+ break;
+ }
+ return render(wstr, begin_offset, x, y, color, halign, valign, style, shadow, max_chars, rect.getWidth(), right_x, use_ellipses, use_color);
}
-S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, const LLColor4 &color, HAlign halign, VAlign valign, U8 style,
- ShadowType shadow, S32 max_chars, S32 max_pixels, F32* right_x, BOOL use_ellipses, BOOL use_color) const
+S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, const LLColor4 &color, HAlign halign, VAlign valign, U8 style,
+ ShadowType shadow, S32 max_chars, S32 max_pixels, F32* right_x, BOOL use_ellipses, BOOL use_color) const
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_UI;
- if(!sDisplayFont) //do not display texts
- {
- return wstr.length() ;
- }
-
- if (wstr.empty())
- {
- return 0;
- }
-
- gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE);
-
- S32 scaled_max_pixels = max_pixels == S32_MAX ? S32_MAX : llceil((F32)max_pixels * sScaleX);
-
- // determine which style flags need to be added programmatically by stripping off the
- // style bits that are drawn by the underlying Freetype font
- U8 style_to_add = (style | mFontDescriptor.getStyle()) & ~mFontFreetype->getStyle();
-
- F32 drop_shadow_strength = 0.f;
- if (shadow != NO_SHADOW)
- {
- F32 luminance;
- color.calcHSL(NULL, NULL, &luminance);
- drop_shadow_strength = clamp_rescale(luminance, 0.35f, 0.6f, 0.f, 1.f);
- if (luminance < 0.35f)
- {
- shadow = NO_SHADOW;
- }
- }
-
- gGL.pushUIMatrix();
-
- gGL.loadUIIdentity();
-
- LLVector2 origin(floorf(sCurOrigin.mX*sScaleX), floorf(sCurOrigin.mY*sScaleY));
-
- // Depth translation, so that floating text appears 'in-world'
- // and is correctly occluded.
- gGL.translatef(0.f,0.f,sCurDepth);
-
- S32 chars_drawn = 0;
- S32 i;
- S32 length;
-
- if (-1 == max_chars)
- {
- max_chars = length = (S32)wstr.length() - begin_offset;
- }
- else
- {
- length = llmin((S32)wstr.length() - begin_offset, max_chars );
- }
-
- F32 cur_x, cur_y, cur_render_x, cur_render_y;
-
- // Not guaranteed to be set correctly
- gGL.setSceneBlendType(LLRender::BT_ALPHA);
-
- cur_x = ((F32)x * sScaleX) + origin.mV[VX];
- cur_y = ((F32)y * sScaleY) + origin.mV[VY];
-
- // Offset y by vertical alignment.
- // use unscaled font metrics here
- switch (valign)
- {
- case TOP:
- cur_y -= llceil(mFontFreetype->getAscenderHeight());
- break;
- case BOTTOM:
- cur_y += llceil(mFontFreetype->getDescenderHeight());
- break;
- case VCENTER:
- cur_y -= llceil((llceil(mFontFreetype->getAscenderHeight()) - llceil(mFontFreetype->getDescenderHeight())) / 2.f);
- break;
- case BASELINE:
- // Baseline, do nothing.
- break;
- default:
- break;
- }
-
- switch (halign)
- {
- case LEFT:
- break;
- case RIGHT:
- cur_x -= llmin(scaled_max_pixels, ll_round(getWidthF32(wstr.c_str(), begin_offset, length) * sScaleX));
- break;
- case HCENTER:
- cur_x -= llmin(scaled_max_pixels, ll_round(getWidthF32(wstr.c_str(), begin_offset, length) * sScaleX)) / 2;
- break;
- default:
- break;
- }
-
- cur_render_y = cur_y;
- cur_render_x = cur_x;
-
- F32 start_x = (F32)ll_round(cur_x);
-
- const LLFontBitmapCache* font_bitmap_cache = mFontFreetype->getFontBitmapCache();
-
- F32 inv_width = 1.f / font_bitmap_cache->getBitmapWidth();
- F32 inv_height = 1.f / font_bitmap_cache->getBitmapHeight();
-
- const S32 LAST_CHARACTER = LLFontFreetype::LAST_CHAR_FULL;
-
- BOOL draw_ellipses = FALSE;
- if (use_ellipses)
- {
- // check for too long of a string
- S32 string_width = ll_round(getWidthF32(wstr.c_str(), begin_offset, max_chars) * sScaleX);
- if (string_width > scaled_max_pixels)
- {
- // use four dots for ellipsis width to generate padding
- const LLWString dots(utf8str_to_wstring(std::string("....")));
- scaled_max_pixels = llmax(0, scaled_max_pixels - ll_round(getWidthF32(dots.c_str())));
- draw_ellipses = TRUE;
- }
- }
-
- 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];
-
- LLColor4U text_color(color);
-
- std::pair<EFontGlyphType, S32> bitmap_entry = std::make_pair(EFontGlyphType::Grayscale, -1);
- S32 glyph_count = 0;
- for (i = begin_offset; i < begin_offset + length; i++)
- {
- llwchar wch = wstr[i];
-
- const LLFontGlyphInfo* fgi = next_glyph;
- next_glyph = NULL;
- if(!fgi)
- {
- fgi = mFontFreetype->getGlyphInfo(wch, (!use_color) ? EFontGlyphType::Grayscale : EFontGlyphType::Color);
- }
- if (!fgi)
- {
- LL_ERRS() << "Missing Glyph Info" << LL_ENDL;
- break;
- }
- // Per-glyph bitmap texture.
- std::pair<EFontGlyphType, S32> next_bitmap_entry = fgi->mBitmapEntry;
- if (next_bitmap_entry != bitmap_entry)
- {
- // Actually draw the queued glyphs before switching their texture;
- // otherwise the queued glyphs will be taken from wrong textures.
- if (glyph_count > 0)
- {
- gGL.begin(LLRender::QUADS);
- {
- gGL.vertexBatchPreTransformed(vertices, uvs, colors, glyph_count * 4);
- }
- gGL.end();
- glyph_count = 0;
- }
-
- bitmap_entry = next_bitmap_entry;
- LLImageGL* font_image = font_bitmap_cache->getImageGL(bitmap_entry.first, bitmap_entry.second);
- gGL.getTexUnit(0)->bind(font_image);
- }
-
- if ((start_x + scaled_max_pixels) < (cur_x + fgi->mXBearing + fgi->mWidth))
- {
- // Not enough room for this character.
- break;
- }
-
- // Draw the text at the appropriate location
- //Specify vertices and texture coordinates
- LLRectf uv_rect((fgi->mXBitmapOffset) * inv_width,
- (fgi->mYBitmapOffset + fgi->mHeight + PAD_UVY) * inv_height,
- (fgi->mXBitmapOffset + fgi->mWidth) * inv_width,
- (fgi->mYBitmapOffset - PAD_UVY) * inv_height);
- // snap glyph origin to whole screen pixel
- LLRectf screen_rect((F32)ll_round(cur_render_x + (F32)fgi->mXBearing),
- (F32)ll_round(cur_render_y + (F32)fgi->mYBearing),
- (F32)ll_round(cur_render_x + (F32)fgi->mXBearing) + (F32)fgi->mWidth,
- (F32)ll_round(cur_render_y + (F32)fgi->mYBearing) - (F32)fgi->mHeight);
-
- 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, (bitmap_entry.first == EFontGlyphType::Grayscale) ? text_color : LLColor4U::white, style_to_add, shadow, drop_shadow_strength);
-
- chars_drawn++;
- cur_x += fgi->mXAdvance;
- cur_y += fgi->mYAdvance;
-
- llwchar next_char = wstr[i+1];
- if (next_char && (next_char < LAST_CHARACTER))
- {
- // Kern this puppy.
- next_glyph = mFontFreetype->getGlyphInfo(next_char, (!use_color) ? EFontGlyphType::Grayscale : EFontGlyphType::Color);
- cur_x += mFontFreetype->getXKerning(fgi, next_glyph);
- }
-
- // Round after kerning.
- // Must do this to cur_x, not just to cur_render_x, otherwise you
- // will squish sub-pixel kerned characters too close together.
- // For example, "CCCCC" looks bad.
- cur_x = (F32)ll_round(cur_x);
- //cur_y = (F32)ll_round(cur_y);
-
- cur_render_x = cur_x;
- 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 - origin.mV[VX]) / sScaleX;
- }
-
- //FIXME: add underline as glyph?
- if (style_to_add & UNDERLINE)
- {
- F32 descender = (F32)llfloor(mFontFreetype->getDescenderHeight());
-
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
- gGL.begin(LLRender::LINES);
- gGL.vertex2f(start_x, cur_y - descender);
- gGL.vertex2f(cur_x, cur_y - descender);
- gGL.end();
- }
-
- if (draw_ellipses)
- {
-
- // recursively render ellipses at end of string
- // we've already reserved enough room
- gGL.pushUIMatrix();
- renderUTF8(std::string("..."),
- 0,
- (cur_x - origin.mV[VX]) / sScaleX, (F32)y,
- color,
- LEFT, valign,
- style_to_add,
- shadow,
- S32_MAX, max_pixels,
- right_x,
- FALSE,
- use_color);
- gGL.popUIMatrix();
- }
-
- gGL.popUIMatrix();
-
- return chars_drawn;
+ if(!sDisplayFont) //do not display texts
+ {
+ return wstr.length() ;
+ }
+
+ if (wstr.empty())
+ {
+ return 0;
+ }
+
+ gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE);
+
+ S32 scaled_max_pixels = max_pixels == S32_MAX ? S32_MAX : llceil((F32)max_pixels * sScaleX);
+
+ // determine which style flags need to be added programmatically by stripping off the
+ // style bits that are drawn by the underlying Freetype font
+ U8 style_to_add = (style | mFontDescriptor.getStyle()) & ~mFontFreetype->getStyle();
+
+ F32 drop_shadow_strength = 0.f;
+ if (shadow != NO_SHADOW)
+ {
+ F32 luminance;
+ color.calcHSL(NULL, NULL, &luminance);
+ drop_shadow_strength = clamp_rescale(luminance, 0.35f, 0.6f, 0.f, 1.f);
+ if (luminance < 0.35f)
+ {
+ shadow = NO_SHADOW;
+ }
+ }
+
+ gGL.pushUIMatrix();
+
+ gGL.loadUIIdentity();
+
+ LLVector2 origin(floorf(sCurOrigin.mX*sScaleX), floorf(sCurOrigin.mY*sScaleY));
+
+ // Depth translation, so that floating text appears 'in-world'
+ // and is correctly occluded.
+ gGL.translatef(0.f,0.f,sCurDepth);
+
+ S32 chars_drawn = 0;
+ S32 i;
+ S32 length;
+
+ if (-1 == max_chars)
+ {
+ max_chars = length = (S32)wstr.length() - begin_offset;
+ }
+ else
+ {
+ length = llmin((S32)wstr.length() - begin_offset, max_chars );
+ }
+
+ F32 cur_x, cur_y, cur_render_x, cur_render_y;
+
+ // Not guaranteed to be set correctly
+ gGL.setSceneBlendType(LLRender::BT_ALPHA);
+
+ cur_x = ((F32)x * sScaleX) + origin.mV[VX];
+ cur_y = ((F32)y * sScaleY) + origin.mV[VY];
+
+ // Offset y by vertical alignment.
+ // use unscaled font metrics here
+ switch (valign)
+ {
+ case TOP:
+ cur_y -= llceil(mFontFreetype->getAscenderHeight());
+ break;
+ case BOTTOM:
+ cur_y += llceil(mFontFreetype->getDescenderHeight());
+ break;
+ case VCENTER:
+ cur_y -= llceil((llceil(mFontFreetype->getAscenderHeight()) - llceil(mFontFreetype->getDescenderHeight())) / 2.f);
+ break;
+ case BASELINE:
+ // Baseline, do nothing.
+ break;
+ default:
+ break;
+ }
+
+ switch (halign)
+ {
+ case LEFT:
+ break;
+ case RIGHT:
+ cur_x -= llmin(scaled_max_pixels, ll_round(getWidthF32(wstr.c_str(), begin_offset, length) * sScaleX));
+ break;
+ case HCENTER:
+ cur_x -= llmin(scaled_max_pixels, ll_round(getWidthF32(wstr.c_str(), begin_offset, length) * sScaleX)) / 2;
+ break;
+ default:
+ break;
+ }
+
+ cur_render_y = cur_y;
+ cur_render_x = cur_x;
+
+ F32 start_x = (F32)ll_round(cur_x);
+
+ const LLFontBitmapCache* font_bitmap_cache = mFontFreetype->getFontBitmapCache();
+
+ F32 inv_width = 1.f / font_bitmap_cache->getBitmapWidth();
+ F32 inv_height = 1.f / font_bitmap_cache->getBitmapHeight();
+
+ const S32 LAST_CHARACTER = LLFontFreetype::LAST_CHAR_FULL;
+
+ BOOL draw_ellipses = FALSE;
+ if (use_ellipses)
+ {
+ // check for too long of a string
+ S32 string_width = ll_round(getWidthF32(wstr.c_str(), begin_offset, max_chars) * sScaleX);
+ if (string_width > scaled_max_pixels)
+ {
+ // use four dots for ellipsis width to generate padding
+ const LLWString dots(utf8str_to_wstring(std::string("....")));
+ scaled_max_pixels = llmax(0, scaled_max_pixels - ll_round(getWidthF32(dots.c_str())));
+ draw_ellipses = TRUE;
+ }
+ }
+
+ 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];
+
+ LLColor4U text_color(color);
+ // Preserve the transparency to render fading emojis in fading text (e.g.
+ // for the chat console)... HB
+ LLColor4U emoji_color(255, 255, 255, text_color.mV[VW]);
+
+ std::pair<EFontGlyphType, S32> bitmap_entry = std::make_pair(EFontGlyphType::Grayscale, -1);
+ S32 glyph_count = 0;
+ for (i = begin_offset; i < begin_offset + length; i++)
+ {
+ llwchar wch = wstr[i];
+
+ const LLFontGlyphInfo* fgi = next_glyph;
+ next_glyph = NULL;
+ if(!fgi)
+ {
+ fgi = mFontFreetype->getGlyphInfo(wch, (!use_color) ? EFontGlyphType::Grayscale : EFontGlyphType::Color);
+ }
+ if (!fgi)
+ {
+ LL_ERRS() << "Missing Glyph Info" << LL_ENDL;
+ break;
+ }
+ // Per-glyph bitmap texture.
+ std::pair<EFontGlyphType, S32> next_bitmap_entry = fgi->mBitmapEntry;
+ if (next_bitmap_entry != bitmap_entry)
+ {
+ // Actually draw the queued glyphs before switching their texture;
+ // otherwise the queued glyphs will be taken from wrong textures.
+ if (glyph_count > 0)
+ {
+ gGL.begin(LLRender::QUADS);
+ {
+ gGL.vertexBatchPreTransformed(vertices, uvs, colors, glyph_count * 4);
+ }
+ gGL.end();
+ glyph_count = 0;
+ }
+
+ bitmap_entry = next_bitmap_entry;
+ LLImageGL* font_image = font_bitmap_cache->getImageGL(bitmap_entry.first, bitmap_entry.second);
+ gGL.getTexUnit(0)->bind(font_image);
+ }
+
+ if ((start_x + scaled_max_pixels) < (cur_x + fgi->mXBearing + fgi->mWidth))
+ {
+ // Not enough room for this character.
+ break;
+ }
+
+ // Draw the text at the appropriate location
+ //Specify vertices and texture coordinates
+ LLRectf uv_rect((fgi->mXBitmapOffset) * inv_width,
+ (fgi->mYBitmapOffset + fgi->mHeight + PAD_UVY) * inv_height,
+ (fgi->mXBitmapOffset + fgi->mWidth) * inv_width,
+ (fgi->mYBitmapOffset - PAD_UVY) * inv_height);
+ // snap glyph origin to whole screen pixel
+ LLRectf screen_rect((F32)ll_round(cur_render_x + (F32)fgi->mXBearing),
+ (F32)ll_round(cur_render_y + (F32)fgi->mYBearing),
+ (F32)ll_round(cur_render_x + (F32)fgi->mXBearing) + (F32)fgi->mWidth,
+ (F32)ll_round(cur_render_y + (F32)fgi->mYBearing) - (F32)fgi->mHeight);
+
+ if (glyph_count >= GLYPH_BATCH_SIZE)
+ {
+ gGL.begin(LLRender::QUADS);
+ {
+ gGL.vertexBatchPreTransformed(vertices, uvs, colors, glyph_count * 4);
+ }
+ gGL.end();
+
+ glyph_count = 0;
+ }
+
+ const LLColor4U& col =
+ bitmap_entry.first == EFontGlyphType::Grayscale ? text_color
+ : emoji_color;
+ drawGlyph(glyph_count, vertices, uvs, colors, screen_rect, uv_rect,
+ col, style_to_add, shadow, drop_shadow_strength);
+
+ chars_drawn++;
+ cur_x += fgi->mXAdvance;
+ cur_y += fgi->mYAdvance;
+
+ llwchar next_char = wstr[i+1];
+ if (next_char && (next_char < LAST_CHARACTER))
+ {
+ // Kern this puppy.
+ next_glyph = mFontFreetype->getGlyphInfo(next_char, (!use_color) ? EFontGlyphType::Grayscale : EFontGlyphType::Color);
+ cur_x += mFontFreetype->getXKerning(fgi, next_glyph);
+ }
+
+ // Round after kerning.
+ // Must do this to cur_x, not just to cur_render_x, otherwise you
+ // will squish sub-pixel kerned characters too close together.
+ // For example, "CCCCC" looks bad.
+ cur_x = (F32)ll_round(cur_x);
+ //cur_y = (F32)ll_round(cur_y);
+
+ cur_render_x = cur_x;
+ 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 - origin.mV[VX]) / sScaleX;
+ }
+
+ //FIXME: add underline as glyph?
+ if (style_to_add & UNDERLINE)
+ {
+ F32 descender = (F32)llfloor(mFontFreetype->getDescenderHeight());
+
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+ gGL.begin(LLRender::LINES);
+ gGL.vertex2f(start_x, cur_y - descender);
+ gGL.vertex2f(cur_x, cur_y - descender);
+ gGL.end();
+ }
+
+ if (draw_ellipses)
+ {
+
+ // recursively render ellipses at end of string
+ // we've already reserved enough room
+ gGL.pushUIMatrix();
+ renderUTF8(std::string("..."),
+ 0,
+ (cur_x - origin.mV[VX]) / sScaleX, (F32)y,
+ color,
+ LEFT, valign,
+ style_to_add,
+ shadow,
+ S32_MAX, max_pixels,
+ right_x,
+ FALSE,
+ use_color);
+ gGL.popUIMatrix();
+ }
+
+ gGL.popUIMatrix();
+
+ return chars_drawn;
}
S32 LLFontGL::render(const LLWString &text, S32 begin_offset, F32 x, F32 y, const LLColor4 &color) const
{
- return render(text, begin_offset, x, y, color, LEFT, BASELINE, NORMAL, NO_SHADOW);
+ return render(text, begin_offset, x, y, color, LEFT, BASELINE, NORMAL, NO_SHADOW);
}
S32 LLFontGL::renderUTF8(const std::string &text, S32 begin_offset, F32 x, F32 y, const LLColor4 &color, HAlign halign, VAlign valign, U8 style, ShadowType shadow, S32 max_chars, S32 max_pixels, F32* right_x, BOOL use_ellipses, BOOL use_color) const
{
- return render(utf8str_to_wstring(text), begin_offset, x, y, color, halign, valign, style, shadow, max_chars, max_pixels, right_x, use_ellipses, use_color);
+ return render(utf8str_to_wstring(text), begin_offset, x, y, color, halign, valign, style, shadow, max_chars, max_pixels, right_x, use_ellipses, use_color);
}
S32 LLFontGL::renderUTF8(const std::string &text, S32 begin_offset, S32 x, S32 y, const LLColor4 &color) const
{
- return renderUTF8(text, begin_offset, (F32)x, (F32)y, color, LEFT, BASELINE, NORMAL, NO_SHADOW);
+ return renderUTF8(text, begin_offset, (F32)x, (F32)y, color, LEFT, BASELINE, NORMAL, NO_SHADOW);
}
S32 LLFontGL::renderUTF8(const std::string &text, S32 begin_offset, S32 x, S32 y, const LLColor4 &color, HAlign halign, VAlign valign, U8 style, ShadowType shadow) const
{
- return renderUTF8(text, begin_offset, (F32)x, (F32)y, color, halign, valign, style, shadow);
+ return renderUTF8(text, begin_offset, (F32)x, (F32)y, color, halign, valign, style, shadow);
}
// font metrics - override for LLFontFreetype that returns units of virtual pixels
F32 LLFontGL::getAscenderHeight() const
-{
- return mFontFreetype->getAscenderHeight() / sScaleY;
+{
+ return mFontFreetype->getAscenderHeight() / sScaleY;
}
F32 LLFontGL::getDescenderHeight() const
-{
- return mFontFreetype->getDescenderHeight() / sScaleY;
+{
+ return mFontFreetype->getDescenderHeight() / sScaleY;
}
S32 LLFontGL::getLineHeight() const
-{
- return llceil(mFontFreetype->getAscenderHeight() / sScaleY) + llceil(mFontFreetype->getDescenderHeight() / sScaleY);
+{
+ return llceil(mFontFreetype->getAscenderHeight() / sScaleY) + llceil(mFontFreetype->getDescenderHeight() / sScaleY);
}
S32 LLFontGL::getWidth(const std::string& utf8text) const
{
- LLWString wtext = utf8str_to_wstring(utf8text);
- return getWidth(wtext.c_str(), 0, S32_MAX);
+ LLWString wtext = utf8str_to_wstring(utf8text);
+ return getWidth(wtext.c_str(), 0, S32_MAX);
}
S32 LLFontGL::getWidth(const llwchar* wchars) const
{
- return getWidth(wchars, 0, S32_MAX);
+ return getWidth(wchars, 0, S32_MAX);
}
S32 LLFontGL::getWidth(const std::string& utf8text, S32 begin_offset, S32 max_chars) const
{
- LLWString wtext = utf8str_to_wstring(utf8text);
- return getWidth(wtext.c_str(), begin_offset, max_chars);
+ LLWString wtext = utf8str_to_wstring(utf8text);
+ return getWidth(wtext.c_str(), begin_offset, max_chars);
}
S32 LLFontGL::getWidth(const llwchar* wchars, S32 begin_offset, S32 max_chars) const
{
- F32 width = getWidthF32(wchars, begin_offset, max_chars);
- return ll_round(width);
+ F32 width = getWidthF32(wchars, begin_offset, max_chars);
+ return ll_round(width);
}
F32 LLFontGL::getWidthF32(const std::string& utf8text) const
{
- LLWString wtext = utf8str_to_wstring(utf8text);
- return getWidthF32(wtext.c_str(), 0, S32_MAX);
+ LLWString wtext = utf8str_to_wstring(utf8text);
+ return getWidthF32(wtext.c_str(), 0, S32_MAX);
}
F32 LLFontGL::getWidthF32(const llwchar* wchars) const
{
- return getWidthF32(wchars, 0, S32_MAX);
+ return getWidthF32(wchars, 0, S32_MAX);
}
F32 LLFontGL::getWidthF32(const std::string& utf8text, S32 begin_offset, S32 max_chars) const
{
- LLWString wtext = utf8str_to_wstring(utf8text);
- return getWidthF32(wtext.c_str(), begin_offset, max_chars);
+ LLWString wtext = utf8str_to_wstring(utf8text);
+ return getWidthF32(wtext.c_str(), begin_offset, max_chars);
}
F32 LLFontGL::getWidthF32(const llwchar* wchars, S32 begin_offset, S32 max_chars, bool no_padding) const
{
- const S32 LAST_CHARACTER = LLFontFreetype::LAST_CHAR_FULL;
-
- 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 = next_glyph;
- next_glyph = NULL;
- if(!fgi)
- {
- fgi = mFontFreetype->getGlyphInfo(wch, EFontGlyphType::Unspecified);
- }
-
- F32 advance = mFontFreetype->getXAdvance(fgi);
-
- if (!no_padding)
- {
- // 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
- // so we can fix things up at the end
- width_padding = llmax(0.f, // always use positive padding amount
- width_padding - advance, // previous padding left over after advance of current character
- (F32)(fgi->mWidth + fgi->mXBearing) - advance); // difference between width of this character and advance to next character
- }
-
- cur_x += advance;
- llwchar next_char = wchars[i+1];
-
- if (((i + 1) < begin_offset + max_chars)
- && next_char
- && (next_char < LAST_CHARACTER))
- {
- // Kern this puppy.
- next_glyph = mFontFreetype->getGlyphInfo(next_char, EFontGlyphType::Unspecified);
- cur_x += mFontFreetype->getXKerning(fgi, next_glyph);
- }
- // Round after kerning.
- cur_x = (F32)ll_round(cur_x);
- }
-
- if (!no_padding)
- {
- // add in extra pixels for last character's width past its xadvance
- cur_x += width_padding;
- }
-
- return cur_x / sScaleX;
+ const S32 LAST_CHARACTER = LLFontFreetype::LAST_CHAR_FULL;
+
+ 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 = next_glyph;
+ next_glyph = NULL;
+ if(!fgi)
+ {
+ fgi = mFontFreetype->getGlyphInfo(wch, EFontGlyphType::Unspecified);
+ }
+
+ F32 advance = mFontFreetype->getXAdvance(fgi);
+
+ if (!no_padding)
+ {
+ // 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
+ // so we can fix things up at the end
+ width_padding = llmax(0.f, // always use positive padding amount
+ width_padding - advance, // previous padding left over after advance of current character
+ (F32)(fgi->mWidth + fgi->mXBearing) - advance); // difference between width of this character and advance to next character
+ }
+
+ cur_x += advance;
+ llwchar next_char = wchars[i+1];
+
+ if (((i + 1) < begin_offset + max_chars)
+ && next_char
+ && (next_char < LAST_CHARACTER))
+ {
+ // Kern this puppy.
+ next_glyph = mFontFreetype->getGlyphInfo(next_char, EFontGlyphType::Unspecified);
+ cur_x += mFontFreetype->getXKerning(fgi, next_glyph);
+ }
+ // Round after kerning.
+ cur_x = (F32)ll_round(cur_x);
+ }
+
+ if (!no_padding)
+ {
+ // add in extra pixels for last character's width past its xadvance
+ cur_x += width_padding;
+ }
+
+ return cur_x / sScaleX;
}
void LLFontGL::generateASCIIglyphs()
@@ -563,308 +570,308 @@ void LLFontGL::generateASCIIglyphs()
// Returns the max number of complete characters from text (up to max_chars) that can be drawn in max_pixels
S32 LLFontGL::maxDrawableChars(const llwchar* wchars, F32 max_pixels, S32 max_chars, EWordWrapStyle end_on_word_boundary) const
{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_UI
- if (!wchars || !wchars[0] || max_chars == 0)
- {
- return 0;
- }
-
- llassert(max_pixels >= 0.f);
- llassert(max_chars >= 0);
-
- BOOL clip = FALSE;
- F32 cur_x = 0;
-
- S32 start_of_last_word = 0;
- BOOL in_word = FALSE;
-
- // avoid S32 overflow when max_pixels == S32_MAX by staying in floating point
- F32 scaled_max_pixels = max_pixels * sScaleX;
- F32 width_padding = 0.f;
-
- LLFontGlyphInfo* next_glyph = NULL;
-
- S32 i;
- for (i=0; (i < max_chars); i++)
- {
- llwchar wch = wchars[i];
-
- if(wch == 0)
- {
- // Null terminator. We're done.
- break;
- }
-
- if (in_word)
- {
- if (iswspace(wch))
- {
- if(wch !=(0x00A0))
- {
- in_word = FALSE;
- }
- }
- if (iswindividual(wch))
- {
- if (iswpunct(wchars[i+1]))
- {
- in_word=TRUE;
- }
- else
- {
- in_word=FALSE;
- start_of_last_word = i;
- }
- }
- }
- else
- {
- start_of_last_word = i;
- if (!iswspace(wch)||!iswindividual(wch))
- {
- in_word = TRUE;
- }
- }
-
- LLFontGlyphInfo* fgi = next_glyph;
- next_glyph = NULL;
- if(!fgi)
- {
- fgi = mFontFreetype->getGlyphInfo(wch, EFontGlyphType::Unspecified);
-
- if (NULL == fgi)
- {
- return 0;
- }
- }
-
- // account for glyphs that run beyond the starting point for the next glyphs
- width_padding = llmax( 0.f, // always use positive padding amount
- width_padding - fgi->mXAdvance, // previous padding left over after advance of current character
- (F32)(fgi->mWidth + fgi->mXBearing) - fgi->mXAdvance); // difference between width of this character and advance to next character
-
- cur_x += fgi->mXAdvance;
-
- // clip if current character runs past scaled_max_pixels (using width_padding)
- if (scaled_max_pixels < cur_x + width_padding)
- {
- clip = TRUE;
- break;
- }
-
- if (((i+1) < max_chars) && wchars[i+1])
- {
- // Kern this puppy.
- next_glyph = mFontFreetype->getGlyphInfo(wchars[i+1], EFontGlyphType::Unspecified);
- cur_x += mFontFreetype->getXKerning(fgi, next_glyph);
- }
-
- // Round after kerning.
- cur_x = (F32)ll_round(cur_x);
- }
-
- if( clip )
- {
- switch (end_on_word_boundary)
- {
- case ONLY_WORD_BOUNDARIES:
- i = start_of_last_word;
- break;
- case WORD_BOUNDARY_IF_POSSIBLE:
- if (start_of_last_word != 0)
- {
- i = start_of_last_word;
- }
- break;
- default:
- case ANYWHERE:
- // do nothing
- break;
- }
- }
- return i;
-}
-
-S32 LLFontGL::firstDrawableChar(const llwchar* wchars, F32 max_pixels, S32 text_len, S32 start_pos, S32 max_chars) const
-{
- if (!wchars || !wchars[0] || max_chars == 0)
- {
- return 0;
- }
-
- F32 total_width = 0.0;
- S32 drawable_chars = 0;
-
- F32 scaled_max_pixels = max_pixels * sScaleX;
-
- S32 start = llmin(start_pos, text_len - 1);
- for (S32 i = start; i >= 0; i--)
- {
- llwchar wch = wchars[i];
-
- const LLFontGlyphInfo* fgi= mFontFreetype->getGlyphInfo(wch, EFontGlyphType::Unspecified);
-
- // 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 + width) )
- {
- break;
- }
-
- total_width += width;
- drawable_chars++;
-
- if( max_chars >= 0 && drawable_chars >= max_chars )
- {
- break;
- }
-
- if ( i > 0 )
- {
- // kerning
- total_width += mFontFreetype->getXKerning(wchars[i-1], wch);
- }
-
- // Round after kerning.
- total_width = (F32)ll_round(total_width);
- }
-
- 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;
- }
-
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_UI
+ if (!wchars || !wchars[0] || max_chars == 0)
+ {
+ return 0;
+ }
+
+ llassert(max_pixels >= 0.f);
+ llassert(max_chars >= 0);
+
+ BOOL clip = FALSE;
+ F32 cur_x = 0;
+
+ S32 start_of_last_word = 0;
+ BOOL in_word = FALSE;
+
+ // avoid S32 overflow when max_pixels == S32_MAX by staying in floating point
+ F32 scaled_max_pixels = max_pixels * sScaleX;
+ F32 width_padding = 0.f;
+
+ LLFontGlyphInfo* next_glyph = NULL;
+
+ S32 i;
+ for (i=0; (i < max_chars); i++)
+ {
+ llwchar wch = wchars[i];
+
+ if(wch == 0)
+ {
+ // Null terminator. We're done.
+ break;
+ }
+
+ if (in_word)
+ {
+ if (iswspace(wch))
+ {
+ if(wch !=(0x00A0))
+ {
+ in_word = FALSE;
+ }
+ }
+ if (iswindividual(wch))
+ {
+ if (iswpunct(wchars[i+1]))
+ {
+ in_word=TRUE;
+ }
+ else
+ {
+ in_word=FALSE;
+ start_of_last_word = i;
+ }
+ }
+ }
+ else
+ {
+ start_of_last_word = i;
+ if (!iswspace(wch)||!iswindividual(wch))
+ {
+ in_word = TRUE;
+ }
+ }
+
+ LLFontGlyphInfo* fgi = next_glyph;
+ next_glyph = NULL;
+ if(!fgi)
+ {
+ fgi = mFontFreetype->getGlyphInfo(wch, EFontGlyphType::Unspecified);
+
+ if (NULL == fgi)
+ {
+ return 0;
+ }
+ }
+
+ // account for glyphs that run beyond the starting point for the next glyphs
+ width_padding = llmax( 0.f, // always use positive padding amount
+ width_padding - fgi->mXAdvance, // previous padding left over after advance of current character
+ (F32)(fgi->mWidth + fgi->mXBearing) - fgi->mXAdvance); // difference between width of this character and advance to next character
+
+ cur_x += fgi->mXAdvance;
+
+ // clip if current character runs past scaled_max_pixels (using width_padding)
+ if (scaled_max_pixels < cur_x + width_padding)
+ {
+ clip = TRUE;
+ break;
+ }
+
+ if (((i+1) < max_chars) && wchars[i+1])
+ {
+ // Kern this puppy.
+ next_glyph = mFontFreetype->getGlyphInfo(wchars[i+1], EFontGlyphType::Unspecified);
+ cur_x += mFontFreetype->getXKerning(fgi, next_glyph);
+ }
+
+ // Round after kerning.
+ cur_x = (F32)ll_round(cur_x);
+ }
+
+ if( clip )
+ {
+ switch (end_on_word_boundary)
+ {
+ case ONLY_WORD_BOUNDARIES:
+ i = start_of_last_word;
+ break;
+ case WORD_BOUNDARY_IF_POSSIBLE:
+ if (start_of_last_word != 0)
+ {
+ i = start_of_last_word;
+ }
+ break;
+ default:
+ case ANYWHERE:
+ // do nothing
+ break;
+ }
+ }
+ return i;
+}
+
+S32 LLFontGL::firstDrawableChar(const llwchar* wchars, F32 max_pixels, S32 text_len, S32 start_pos, S32 max_chars) const
+{
+ if (!wchars || !wchars[0] || max_chars == 0)
+ {
+ return 0;
+ }
+
+ F32 total_width = 0.0;
+ S32 drawable_chars = 0;
+
+ F32 scaled_max_pixels = max_pixels * sScaleX;
+
+ S32 start = llmin(start_pos, text_len - 1);
+ for (S32 i = start; i >= 0; i--)
+ {
+ llwchar wch = wchars[i];
+
+ const LLFontGlyphInfo* fgi= mFontFreetype->getGlyphInfo(wch, EFontGlyphType::Unspecified);
+
+ // 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 + width) )
+ {
+ break;
+ }
+
+ total_width += width;
+ drawable_chars++;
+
+ if( max_chars >= 0 && drawable_chars >= max_chars )
+ {
+ break;
+ }
+
+ if ( i > 0 )
+ {
+ // kerning
+ total_width += mFontFreetype->getXKerning(wchars[i-1], wch);
+ }
+
+ // Round after kerning.
+ total_width = (F32)ll_round(total_width);
+ }
+
+ 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
{
- if (!wchars || !wchars[0] || max_chars == 0)
- {
- return 0;
- }
-
- F32 cur_x = 0;
-
- 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 - 1);
-
- F32 scaled_max_pixels = max_pixels * sScaleX;
-
- const LLFontGlyphInfo* next_glyph = NULL;
-
- S32 pos;
- for (pos = begin_offset; pos < max_index; pos++)
- {
- llwchar wch = wchars[pos];
- if (!wch)
- {
- break; // done
- }
-
- const LLFontGlyphInfo* glyph = next_glyph;
- next_glyph = NULL;
- if(!glyph)
- {
- glyph = mFontFreetype->getGlyphInfo(wch, EFontGlyphType::Unspecified);
- }
-
- F32 char_width = mFontFreetype->getXAdvance(glyph);
-
- if (round)
- {
- // Note: if the mouse is on the left half of the character, the pick is to the character's left
- // If it's on the right half, the pick is to the right.
- if (target_x < cur_x + char_width*0.5f)
- {
- break;
- }
- }
- else if (target_x < cur_x + char_width)
- {
- break;
- }
-
- if (scaled_max_pixels < cur_x + char_width)
- {
- break;
- }
-
- cur_x += char_width;
-
- if (((pos + 1) < max_index)
- && (wchars[(pos + 1)]))
- {
- // Kern this puppy.
- next_glyph = mFontFreetype->getGlyphInfo(wchars[pos + 1], EFontGlyphType::Unspecified);
- cur_x += mFontFreetype->getXKerning(glyph, next_glyph);
- }
-
-
- // Round after kerning.
- cur_x = (F32)ll_round(cur_x);
- }
-
- return llmin(max_chars, pos - begin_offset);
+ if (!wchars || !wchars[0] || max_chars == 0)
+ {
+ return 0;
+ }
+
+ F32 cur_x = 0;
+
+ 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 - 1);
+
+ F32 scaled_max_pixels = max_pixels * sScaleX;
+
+ const LLFontGlyphInfo* next_glyph = NULL;
+
+ S32 pos;
+ for (pos = begin_offset; pos < max_index; pos++)
+ {
+ llwchar wch = wchars[pos];
+ if (!wch)
+ {
+ break; // done
+ }
+
+ const LLFontGlyphInfo* glyph = next_glyph;
+ next_glyph = NULL;
+ if(!glyph)
+ {
+ glyph = mFontFreetype->getGlyphInfo(wch, EFontGlyphType::Unspecified);
+ }
+
+ F32 char_width = mFontFreetype->getXAdvance(glyph);
+
+ if (round)
+ {
+ // Note: if the mouse is on the left half of the character, the pick is to the character's left
+ // If it's on the right half, the pick is to the right.
+ if (target_x < cur_x + char_width*0.5f)
+ {
+ break;
+ }
+ }
+ else if (target_x < cur_x + char_width)
+ {
+ break;
+ }
+
+ if (scaled_max_pixels < cur_x + char_width)
+ {
+ break;
+ }
+
+ cur_x += char_width;
+
+ if (((pos + 1) < max_index)
+ && (wchars[(pos + 1)]))
+ {
+ // Kern this puppy.
+ next_glyph = mFontFreetype->getGlyphInfo(wchars[pos + 1], EFontGlyphType::Unspecified);
+ cur_x += mFontFreetype->getXKerning(glyph, next_glyph);
+ }
+
+
+ // Round after kerning.
+ cur_x = (F32)ll_round(cur_x);
+ }
+
+ return llmin(max_chars, pos - begin_offset);
}
const LLFontDescriptor& LLFontGL::getFontDesc() const
{
- return mFontDescriptor;
+ return mFontDescriptor;
}
// static
void LLFontGL::initClass(F32 screen_dpi, F32 x_scale, F32 y_scale, const std::string& app_dir, bool create_gl_textures)
{
- sVertDPI = (F32)llfloor(screen_dpi * y_scale);
- sHorizDPI = (F32)llfloor(screen_dpi * x_scale);
- sScaleX = x_scale;
- sScaleY = y_scale;
- sAppDir = app_dir;
-
- // Font registry init
- if (!sFontRegistry)
- {
- sFontRegistry = new LLFontRegistry(create_gl_textures);
- sFontRegistry->parseFontInfo("fonts.xml");
- }
- else
- {
- sFontRegistry->reset();
- }
+ sVertDPI = (F32)llfloor(screen_dpi * y_scale);
+ sHorizDPI = (F32)llfloor(screen_dpi * x_scale);
+ sScaleX = x_scale;
+ sScaleY = y_scale;
+ sAppDir = app_dir;
+
+ // Font registry init
+ if (!sFontRegistry)
+ {
+ sFontRegistry = new LLFontRegistry(create_gl_textures);
+ sFontRegistry->parseFontInfo("fonts.xml");
+ }
+ else
+ {
+ sFontRegistry->reset();
+ }
- LLFontGL::loadDefaultFonts();
+ LLFontGL::loadDefaultFonts();
}
void LLFontGL::dumpTextures()
{
- if (mFontFreetype.notNull())
- {
- mFontFreetype->dumpFontBitmaps();
- }
+ if (mFontFreetype.notNull())
+ {
+ mFontFreetype->dumpFontBitmaps();
+ }
}
// static
void LLFontGL::dumpFonts()
{
- sFontRegistry->dump();
+ sFontRegistry->dump();
}
// static
void LLFontGL::dumpFontTextures()
{
- sFontRegistry->dumpTextures();
+ sFontRegistry->dumpTextures();
}
// Force standard fonts to get generated up front.
@@ -874,15 +881,15 @@ void LLFontGL::dumpFontTextures()
// static
bool LLFontGL::loadDefaultFonts()
{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_UI
- bool succ = true;
- succ &= (NULL != getFontSansSerifSmall());
- succ &= (NULL != getFontSansSerif());
- succ &= (NULL != getFontSansSerifBig());
- succ &= (NULL != getFontSansSerifHuge());
- succ &= (NULL != getFontSansSerifBold());
- succ &= (NULL != getFontMonospace());
- return succ;
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_UI
+ bool succ = true;
+ succ &= (NULL != getFontSansSerifSmall());
+ succ &= (NULL != getFontSansSerif());
+ succ &= (NULL != getFontSansSerifBig());
+ succ &= (NULL != getFontSansSerifHuge());
+ succ &= (NULL != getFontSansSerifBold());
+ succ &= (NULL != getFontMonospace());
+ return succ;
}
void LLFontGL::loadCommonFonts()
@@ -897,164 +904,178 @@ void LLFontGL::loadCommonFonts()
// static
void LLFontGL::destroyDefaultFonts()
{
- // Remove the actual fonts.
- delete sFontRegistry;
- sFontRegistry = NULL;
+ // Remove the actual fonts.
+ delete sFontRegistry;
+ sFontRegistry = NULL;
}
-//static
+//static
void LLFontGL::destroyAllGL()
{
- if (sFontRegistry)
- {
- sFontRegistry->destroyGL();
- }
+ if (sFontRegistry)
+ {
+ sFontRegistry->destroyGL();
+ }
}
// static
U8 LLFontGL::getStyleFromString(const std::string &style)
{
- S32 ret = 0;
- if (style.find("BOLD") != style.npos)
- {
- ret |= BOLD;
- }
- if (style.find("ITALIC") != style.npos)
- {
- ret |= ITALIC;
- }
- if (style.find("UNDERLINE") != style.npos)
- {
- ret |= UNDERLINE;
- }
- return ret;
+ S32 ret = 0;
+ if (style.find("BOLD") != style.npos)
+ {
+ ret |= BOLD;
+ }
+ if (style.find("ITALIC") != style.npos)
+ {
+ ret |= ITALIC;
+ }
+ if (style.find("UNDERLINE") != style.npos)
+ {
+ ret |= UNDERLINE;
+ }
+ return ret;
}
// static
std::string LLFontGL::getStringFromStyle(U8 style)
{
- std::string style_string;
- if (style == NORMAL)
- {
- style_string += "|NORMAL";
- }
- if (style & BOLD)
- {
- style_string += "|BOLD";
- }
- if (style & ITALIC)
- {
- style_string += "|ITALIC";
- }
- if (style & UNDERLINE)
- {
- style_string += "|UNDERLINE";
- }
- return style_string;
+ std::string style_string;
+ if (style == NORMAL)
+ {
+ style_string += "|NORMAL";
+ }
+ if (style & BOLD)
+ {
+ style_string += "|BOLD";
+ }
+ if (style & ITALIC)
+ {
+ style_string += "|ITALIC";
+ }
+ if (style & UNDERLINE)
+ {
+ style_string += "|UNDERLINE";
+ }
+ return style_string;
}
// static
std::string LLFontGL::nameFromFont(const LLFontGL* fontp)
{
- return fontp->mFontDescriptor.getName();
+ return fontp->mFontDescriptor.getName();
}
// static
std::string LLFontGL::sizeFromFont(const LLFontGL* fontp)
{
- return fontp->mFontDescriptor.getSize();
+ return fontp->mFontDescriptor.getSize();
}
// static
std::string LLFontGL::nameFromHAlign(LLFontGL::HAlign align)
{
- if (align == LEFT) return std::string("left");
- else if (align == RIGHT) return std::string("right");
- else if (align == HCENTER) return std::string("center");
- else return std::string();
+ if (align == LEFT) return std::string("left");
+ else if (align == RIGHT) return std::string("right");
+ else if (align == HCENTER) return std::string("center");
+ else return std::string();
}
// static
LLFontGL::HAlign LLFontGL::hAlignFromName(const std::string& name)
{
- LLFontGL::HAlign gl_hfont_align = LLFontGL::LEFT;
- if (name == "left")
- {
- gl_hfont_align = LLFontGL::LEFT;
- }
- else if (name == "right")
- {
- gl_hfont_align = LLFontGL::RIGHT;
- }
- else if (name == "center")
- {
- gl_hfont_align = LLFontGL::HCENTER;
- }
- //else leave left
- return gl_hfont_align;
+ LLFontGL::HAlign gl_hfont_align = LLFontGL::LEFT;
+ if (name == "left")
+ {
+ gl_hfont_align = LLFontGL::LEFT;
+ }
+ else if (name == "right")
+ {
+ gl_hfont_align = LLFontGL::RIGHT;
+ }
+ else if (name == "center")
+ {
+ gl_hfont_align = LLFontGL::HCENTER;
+ }
+ //else leave left
+ return gl_hfont_align;
}
// static
std::string LLFontGL::nameFromVAlign(LLFontGL::VAlign align)
{
- if (align == TOP) return std::string("top");
- else if (align == VCENTER) return std::string("center");
- else if (align == BASELINE) return std::string("baseline");
- else if (align == BOTTOM) return std::string("bottom");
- else return std::string();
+ if (align == TOP) return std::string("top");
+ else if (align == VCENTER) return std::string("center");
+ else if (align == BASELINE) return std::string("baseline");
+ else if (align == BOTTOM) return std::string("bottom");
+ else return std::string();
}
// static
LLFontGL::VAlign LLFontGL::vAlignFromName(const std::string& name)
{
- LLFontGL::VAlign gl_vfont_align = LLFontGL::BASELINE;
- if (name == "top")
- {
- gl_vfont_align = LLFontGL::TOP;
- }
- else if (name == "center")
- {
- gl_vfont_align = LLFontGL::VCENTER;
- }
- else if (name == "baseline")
- {
- gl_vfont_align = LLFontGL::BASELINE;
- }
- else if (name == "bottom")
- {
- gl_vfont_align = LLFontGL::BOTTOM;
- }
- //else leave baseline
- return gl_vfont_align;
+ LLFontGL::VAlign gl_vfont_align = LLFontGL::BASELINE;
+ if (name == "top")
+ {
+ gl_vfont_align = LLFontGL::TOP;
+ }
+ else if (name == "center")
+ {
+ gl_vfont_align = LLFontGL::VCENTER;
+ }
+ else if (name == "baseline")
+ {
+ gl_vfont_align = LLFontGL::BASELINE;
+ }
+ else if (name == "bottom")
+ {
+ gl_vfont_align = LLFontGL::BOTTOM;
+ }
+ //else leave baseline
+ return gl_vfont_align;
}
//static
-LLFontGL* LLFontGL::getFontEmoji()
+LLFontGL* LLFontGL::getFontEmojiSmall()
{
- static LLFontGL* fontp = getFont(LLFontDescriptor("Emoji", "Large", 0));
- return fontp;;
+ static LLFontGL* fontp = getFont(LLFontDescriptor("Emoji", "Small", 0));
+ return fontp;;
+}
+
+//static
+LLFontGL* LLFontGL::getFontEmojiMedium()
+{
+ static LLFontGL* fontp = getFont(LLFontDescriptor("Emoji", "Medium", 0));
+ return fontp;;
+}
+
+//static
+LLFontGL* LLFontGL::getFontEmojiLarge()
+{
+ static LLFontGL* fontp = getFont(LLFontDescriptor("Emoji", "Large", 0));
+ return fontp;;
}
//static
LLFontGL* LLFontGL::getFontEmojiHuge()
{
- static LLFontGL* fontp = getFont(LLFontDescriptor("Emoji", "Huge", 0));
- return fontp;;
+ static LLFontGL* fontp = getFont(LLFontDescriptor("Emoji", "Huge", 0));
+ return fontp;;
}
//static
LLFontGL* LLFontGL::getFontMonospace()
{
- static LLFontGL* fontp = getFont(LLFontDescriptor("Monospace","Monospace",0));
- return fontp;
+ static LLFontGL* fontp = getFont(LLFontDescriptor("Monospace","Monospace",0));
+ return fontp;
}
//static
LLFontGL* LLFontGL::getFontSansSerifSmall()
{
- static LLFontGL* fontp = getFont(LLFontDescriptor("SansSerif","Small",0));
- return fontp;
+ static LLFontGL* fontp = getFont(LLFontDescriptor("SansSerif","Small",0));
+ return fontp;
}
//static
@@ -1074,73 +1095,73 @@ LLFontGL* LLFontGL::getFontSansSerifSmallItalic()
//static
LLFontGL* LLFontGL::getFontSansSerif()
{
- static LLFontGL* fontp = getFont(LLFontDescriptor("SansSerif","Medium",0));
- return fontp;
+ static LLFontGL* fontp = getFont(LLFontDescriptor("SansSerif","Medium",0));
+ return fontp;
}
//static
LLFontGL* LLFontGL::getFontSansSerifBig()
{
- static LLFontGL* fontp = getFont(LLFontDescriptor("SansSerif","Large",0));
- return fontp;
+ static LLFontGL* fontp = getFont(LLFontDescriptor("SansSerif","Large",0));
+ return fontp;
}
-//static
+//static
LLFontGL* LLFontGL::getFontSansSerifHuge()
{
- static LLFontGL* fontp = getFont(LLFontDescriptor("SansSerif","Huge",0));
- return fontp;
+ static LLFontGL* fontp = getFont(LLFontDescriptor("SansSerif","Huge",0));
+ return fontp;
}
-//static
+//static
LLFontGL* LLFontGL::getFontSansSerifBold()
{
- static LLFontGL* fontp = getFont(LLFontDescriptor("SansSerif","Medium",BOLD));
- return fontp;
+ static LLFontGL* fontp = getFont(LLFontDescriptor("SansSerif","Medium",BOLD));
+ return fontp;
}
-//static
+//static
LLFontGL* LLFontGL::getFont(const LLFontDescriptor& desc)
{
- return sFontRegistry->getFont(desc);
+ return sFontRegistry->getFont(desc);
}
//static
LLFontGL* LLFontGL::getFontByName(const std::string& name)
{
- // check for most common fonts first
- if (name == "SANSSERIF")
- {
- return getFontSansSerif();
- }
- else if (name == "SANSSERIF_SMALL")
- {
- return getFontSansSerifSmall();
- }
- else if (name == "SANSSERIF_BIG")
- {
- return getFontSansSerifBig();
- }
- else if (name == "SMALL" || name == "OCRA")
- {
- // *BUG: Should this be "MONOSPACE"? Do we use "OCRA" anymore?
- // Does "SMALL" mean "SERIF"?
- return getFontMonospace();
- }
- else
- {
- return NULL;
- }
+ // check for most common fonts first
+ if (name == "SANSSERIF")
+ {
+ return getFontSansSerif();
+ }
+ else if (name == "SANSSERIF_SMALL")
+ {
+ return getFontSansSerifSmall();
+ }
+ else if (name == "SANSSERIF_BIG")
+ {
+ return getFontSansSerifBig();
+ }
+ else if (name == "SMALL" || name == "OCRA")
+ {
+ // *BUG: Should this be "MONOSPACE"? Do we use "OCRA" anymore?
+ // Does "SMALL" mean "SERIF"?
+ return getFontMonospace();
+ }
+ else
+ {
+ return NULL;
+ }
}
//static
LLFontGL* LLFontGL::getFontDefault()
{
- return getFontSansSerif(); // Fallback to sans serif as default font
+ return getFontSansSerif(); // Fallback to sans serif as default font
}
-// static
+// static
std::string LLFontGL::getFontPathSystem()
{
#if LL_DARWIN
@@ -1173,127 +1194,127 @@ std::string LLFontGL::getFontPathSystem()
}
-// static
+// static
std::string LLFontGL::getFontPathLocal()
{
- std::string local_path;
+ std::string local_path;
- // Backup files if we can't load from system fonts directory.
- // We could store this in an end-user writable directory to allow
- // end users to switch fonts.
- if (LLFontGL::sAppDir.length())
- {
- // use specified application dir to look for fonts
- local_path = LLFontGL::sAppDir + "/fonts/";
- }
- else
- {
- // assume working directory is executable directory
- local_path = "./fonts/";
- }
- return local_path;
+ // Backup files if we can't load from system fonts directory.
+ // We could store this in an end-user writable directory to allow
+ // end users to switch fonts.
+ if (LLFontGL::sAppDir.length())
+ {
+ // use specified application dir to look for fonts
+ local_path = LLFontGL::sAppDir + "/fonts/";
+ }
+ else
+ {
+ // assume working directory is executable directory
+ local_path = "./fonts/";
+ }
+ return local_path;
}
LLFontGL::LLFontGL(const LLFontGL &source)
{
- LL_ERRS() << "Not implemented!" << LL_ENDL;
+ LL_ERRS() << "Not implemented!" << LL_ENDL;
}
LLFontGL &LLFontGL::operator=(const LLFontGL &source)
{
- LL_ERRS() << "Not implemented" << LL_ENDL;
- return *this;
+ LL_ERRS() << "Not implemented" << LL_ENDL;
+ return *this;
}
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
{
- S32 index = 0;
+ S32 index = 0;
- vertex_out[index] = LLVector3(screen_rect.mRight, screen_rect.mTop, 0.f);
- uv_out[index] = LLVector2(uv_rect.mRight, uv_rect.mTop);
- colors_out[index] = color;
- index++;
+ vertex_out[index] = LLVector3(screen_rect.mRight, screen_rect.mTop, 0.f);
+ uv_out[index] = LLVector2(uv_rect.mRight, uv_rect.mTop);
+ colors_out[index] = color;
+ index++;
- vertex_out[index] = LLVector3(screen_rect.mLeft, screen_rect.mTop, 0.f);
- uv_out[index] = LLVector2(uv_rect.mLeft, uv_rect.mTop);
- colors_out[index] = color;
- index++;
+ vertex_out[index] = LLVector3(screen_rect.mLeft, screen_rect.mTop, 0.f);
+ uv_out[index] = LLVector2(uv_rect.mLeft, uv_rect.mTop);
+ colors_out[index] = color;
+ index++;
- vertex_out[index] = LLVector3(screen_rect.mLeft, screen_rect.mBottom, 0.f);
- uv_out[index] = LLVector2(uv_rect.mLeft, uv_rect.mBottom);
- colors_out[index] = color;
- index++;
+ vertex_out[index] = LLVector3(screen_rect.mLeft, screen_rect.mBottom, 0.f);
+ uv_out[index] = LLVector2(uv_rect.mLeft, uv_rect.mBottom);
+ colors_out[index] = color;
+ index++;
- vertex_out[index] = LLVector3(screen_rect.mRight, screen_rect.mBottom, 0.f);
- uv_out[index] = LLVector2(uv_rect.mRight, uv_rect.mBottom);
- colors_out[index] = color;
+ vertex_out[index] = LLVector3(screen_rect.mRight, screen_rect.mBottom, 0.f);
+ uv_out[index] = LLVector2(uv_rect.mRight, uv_rect.mBottom);
+ colors_out[index] = color;
}
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);
-
- //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++)
- {
- LLRectf screen_rect_offset = screen_rect;
-
- 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)
- {
- LLColor4U shadow_color = LLFontGL::sShadowColor;
- shadow_color.mV[VALPHA] = U8(color.mV[VALPHA] * drop_shadow_strength * DROP_SHADOW_SOFT_STRENGTH);
- for (S32 pass = 0; pass < 5; pass++)
- {
- 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(&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)
- {
- LLColor4U shadow_color = LLFontGL::sShadowColor;
- shadow_color.mV[VALPHA] = U8(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++;
- }
+ F32 slant_offset;
+ slant_offset = ((style & ITALIC) ? ( -mFontFreetype->getAscenderHeight() * 0.2f) : 0.f);
+
+ //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++)
+ {
+ LLRectf screen_rect_offset = screen_rect;
+
+ 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)
+ {
+ LLColor4U shadow_color = LLFontGL::sShadowColor;
+ shadow_color.mV[VALPHA] = U8(color.mV[VALPHA] * drop_shadow_strength * DROP_SHADOW_SOFT_STRENGTH);
+ for (S32 pass = 0; pass < 5; pass++)
+ {
+ 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(&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)
+ {
+ LLColor4U shadow_color = LLFontGL::sShadowColor;
+ shadow_color.mV[VALPHA] = U8(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++;
+ }
}
diff --git a/indra/llrender/llfontgl.h b/indra/llrender/llfontgl.h
index f6ec416c8b..65f0a8cbfd 100644
--- a/indra/llrender/llfontgl.h
+++ b/indra/llrender/llfontgl.h
@@ -1,4 +1,4 @@
-/**
+/**
* @file llfontgl.h
* @author Doug Soo
* @brief Wrapper around FreeType
@@ -6,21 +6,21 @@
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -46,201 +46,203 @@ class LLFontRegistry;
class LLFontGL
{
public:
- enum HAlign
- {
- // Horizontal location of x,y coord to render.
- LEFT = 0, // Left align
- RIGHT = 1, // Right align
- HCENTER = 2, // Center
- };
-
- enum VAlign
- {
- // Vertical location of x,y coord to render.
- TOP = 3, // Top align
- VCENTER = 4, // Center
- BASELINE = 5, // Baseline
- BOTTOM = 6 // Bottom
- };
-
- enum StyleFlags
- {
- // text style to render. May be combined (these are bit flags)
- NORMAL = 0x00,
- BOLD = 0x01,
- ITALIC = 0x02,
- UNDERLINE = 0x04
- };
-
- enum ShadowType
- {
- NO_SHADOW,
- DROP_SHADOW,
- DROP_SHADOW_SOFT
- };
-
- LLFontGL();
- ~LLFontGL();
-
-
- void reset(); // Reset a font after GL cleanup. ONLY works on an already loaded font.
-
- void destroyGL();
-
- BOOL loadFace(const std::string& filename, F32 point_size, const F32 vert_dpi, const F32 horz_dpi, bool is_fallback, S32 face_n);
-
- S32 getNumFaces(const std::string& filename);
-
- S32 render(const LLWString &text, S32 begin_offset,
- const LLRect& rect,
- const LLColor4 &color,
- HAlign halign = LEFT, VAlign valign = BASELINE,
- U8 style = NORMAL, ShadowType shadow = NO_SHADOW,
- S32 max_chars = S32_MAX,
- F32* right_x=NULL,
- BOOL use_ellipses = FALSE,
- BOOL use_color = TRUE) const;
-
- S32 render(const LLWString &text, S32 begin_offset,
- const LLRectf& rect,
- const LLColor4 &color,
- HAlign halign = LEFT, VAlign valign = BASELINE,
- U8 style = NORMAL, ShadowType shadow = NO_SHADOW,
- S32 max_chars = S32_MAX,
- F32* right_x=NULL,
- BOOL use_ellipses = FALSE,
- BOOL use_color = TRUE) const;
-
- S32 render(const LLWString &text, S32 begin_offset,
- F32 x, F32 y,
- const LLColor4 &color,
- HAlign halign = LEFT, VAlign valign = BASELINE,
- U8 style = NORMAL, ShadowType shadow = NO_SHADOW,
- S32 max_chars = S32_MAX, S32 max_pixels = S32_MAX,
- F32* right_x=NULL,
- BOOL use_ellipses = FALSE,
- BOOL use_color = TRUE) const;
-
- S32 render(const LLWString &text, S32 begin_offset, F32 x, F32 y, const LLColor4 &color) const;
-
- // renderUTF8 does a conversion, so is slower!
- S32 renderUTF8(const std::string &text, S32 begin_offset, F32 x, F32 y, const LLColor4 &color, HAlign halign, VAlign valign, U8 style, ShadowType shadow, S32 max_chars = S32_MAX, S32 max_pixels = S32_MAX, F32* right_x = NULL, BOOL use_ellipses = FALSE, BOOL use_color = TRUE) const;
- S32 renderUTF8(const std::string &text, S32 begin_offset, S32 x, S32 y, const LLColor4 &color) const;
- S32 renderUTF8(const std::string &text, S32 begin_offset, S32 x, S32 y, const LLColor4 &color, HAlign halign, VAlign valign, U8 style = NORMAL, ShadowType shadow = NO_SHADOW) const;
-
- // font metrics - override for LLFontFreetype that returns units of virtual pixels
- F32 getAscenderHeight() const;
- F32 getDescenderHeight() const;
- S32 getLineHeight() const;
-
- S32 getWidth(const std::string& utf8text) const;
- S32 getWidth(const llwchar* wchars) const;
- S32 getWidth(const std::string& utf8text, S32 offset, S32 max_chars) const;
- S32 getWidth(const llwchar* wchars, S32 offset, S32 max_chars) const;
-
- F32 getWidthF32(const std::string& utf8text) const;
- F32 getWidthF32(const llwchar* wchars) const;
- F32 getWidthF32(const std::string& text, S32 offset, S32 max_chars) const;
- F32 getWidthF32(const llwchar* wchars, S32 offset, S32 max_chars, bool no_padding = false) const;
-
- // The following are called often, frequently with large buffers, so do not use a string interface
-
- // Returns the max number of complete characters from text (up to max_chars) that can be drawn in max_pixels
- typedef enum e_word_wrap_style
- {
- ONLY_WORD_BOUNDARIES,
- WORD_BOUNDARY_IF_POSSIBLE,
- ANYWHERE
- } EWordWrapStyle ;
- S32 maxDrawableChars(const llwchar* wchars, F32 max_pixels, S32 max_chars = S32_MAX, EWordWrapStyle end_on_word_boundary = ANYWHERE) const;
-
- // Returns the index of the first complete characters from text that can be drawn in max_pixels
- // given that the character at start_pos should be the last character (or as close to last as possible).
- S32 firstDrawableChar(const llwchar* wchars, F32 max_pixels, S32 text_len, S32 start_pos=S32_MAX, S32 max_chars = S32_MAX) const;
-
- // Returns the index of the character closest to pixel position x (ignoring text to the right of max_pixels and max_chars)
- S32 charFromPixelOffset(const llwchar* wchars, S32 char_offset, F32 x, F32 max_pixels=F32_MAX, S32 max_chars = S32_MAX, BOOL round = TRUE) const;
-
- const LLFontDescriptor& getFontDesc() const;
-
- void generateASCIIglyphs();
-
-
- static void initClass(F32 screen_dpi, F32 x_scale, F32 y_scale, const std::string& app_dir, bool create_gl_textures = true);
-
- void dumpTextures();
- static void dumpFonts();
- static void dumpFontTextures();
-
- // Load sans-serif, sans-serif-small, etc.
- // Slow, requires multiple seconds to load fonts.
- static bool loadDefaultFonts();
+ enum HAlign
+ {
+ // Horizontal location of x,y coord to render.
+ LEFT = 0, // Left align
+ RIGHT = 1, // Right align
+ HCENTER = 2, // Center
+ };
+
+ enum VAlign
+ {
+ // Vertical location of x,y coord to render.
+ TOP = 3, // Top align
+ VCENTER = 4, // Center
+ BASELINE = 5, // Baseline
+ BOTTOM = 6 // Bottom
+ };
+
+ enum StyleFlags
+ {
+ // text style to render. May be combined (these are bit flags)
+ NORMAL = 0x00,
+ BOLD = 0x01,
+ ITALIC = 0x02,
+ UNDERLINE = 0x04
+ };
+
+ enum ShadowType
+ {
+ NO_SHADOW,
+ DROP_SHADOW,
+ DROP_SHADOW_SOFT
+ };
+
+ LLFontGL();
+ ~LLFontGL();
+
+
+ void reset(); // Reset a font after GL cleanup. ONLY works on an already loaded font.
+
+ void destroyGL();
+
+ BOOL loadFace(const std::string& filename, F32 point_size, const F32 vert_dpi, const F32 horz_dpi, bool is_fallback, S32 face_n);
+
+ S32 getNumFaces(const std::string& filename);
+
+ S32 render(const LLWString &text, S32 begin_offset,
+ const LLRect& rect,
+ const LLColor4 &color,
+ HAlign halign = LEFT, VAlign valign = BASELINE,
+ U8 style = NORMAL, ShadowType shadow = NO_SHADOW,
+ S32 max_chars = S32_MAX,
+ F32* right_x=NULL,
+ BOOL use_ellipses = FALSE,
+ BOOL use_color = TRUE) const;
+
+ S32 render(const LLWString &text, S32 begin_offset,
+ const LLRectf& rect,
+ const LLColor4 &color,
+ HAlign halign = LEFT, VAlign valign = BASELINE,
+ U8 style = NORMAL, ShadowType shadow = NO_SHADOW,
+ S32 max_chars = S32_MAX,
+ F32* right_x=NULL,
+ BOOL use_ellipses = FALSE,
+ BOOL use_color = TRUE) const;
+
+ S32 render(const LLWString &text, S32 begin_offset,
+ F32 x, F32 y,
+ const LLColor4 &color,
+ HAlign halign = LEFT, VAlign valign = BASELINE,
+ U8 style = NORMAL, ShadowType shadow = NO_SHADOW,
+ S32 max_chars = S32_MAX, S32 max_pixels = S32_MAX,
+ F32* right_x=NULL,
+ BOOL use_ellipses = FALSE,
+ BOOL use_color = TRUE) const;
+
+ S32 render(const LLWString &text, S32 begin_offset, F32 x, F32 y, const LLColor4 &color) const;
+
+ // renderUTF8 does a conversion, so is slower!
+ S32 renderUTF8(const std::string &text, S32 begin_offset, F32 x, F32 y, const LLColor4 &color, HAlign halign, VAlign valign, U8 style, ShadowType shadow, S32 max_chars = S32_MAX, S32 max_pixels = S32_MAX, F32* right_x = NULL, BOOL use_ellipses = FALSE, BOOL use_color = TRUE) const;
+ S32 renderUTF8(const std::string &text, S32 begin_offset, S32 x, S32 y, const LLColor4 &color) const;
+ S32 renderUTF8(const std::string &text, S32 begin_offset, S32 x, S32 y, const LLColor4 &color, HAlign halign, VAlign valign, U8 style = NORMAL, ShadowType shadow = NO_SHADOW) const;
+
+ // font metrics - override for LLFontFreetype that returns units of virtual pixels
+ F32 getAscenderHeight() const;
+ F32 getDescenderHeight() const;
+ S32 getLineHeight() const;
+
+ S32 getWidth(const std::string& utf8text) const;
+ S32 getWidth(const llwchar* wchars) const;
+ S32 getWidth(const std::string& utf8text, S32 offset, S32 max_chars) const;
+ S32 getWidth(const llwchar* wchars, S32 offset, S32 max_chars) const;
+
+ F32 getWidthF32(const std::string& utf8text) const;
+ F32 getWidthF32(const llwchar* wchars) const;
+ F32 getWidthF32(const std::string& text, S32 offset, S32 max_chars) const;
+ F32 getWidthF32(const llwchar* wchars, S32 offset, S32 max_chars, bool no_padding = false) const;
+
+ // The following are called often, frequently with large buffers, so do not use a string interface
+
+ // Returns the max number of complete characters from text (up to max_chars) that can be drawn in max_pixels
+ typedef enum e_word_wrap_style
+ {
+ ONLY_WORD_BOUNDARIES,
+ WORD_BOUNDARY_IF_POSSIBLE,
+ ANYWHERE
+ } EWordWrapStyle ;
+ S32 maxDrawableChars(const llwchar* wchars, F32 max_pixels, S32 max_chars = S32_MAX, EWordWrapStyle end_on_word_boundary = ANYWHERE) const;
+
+ // Returns the index of the first complete characters from text that can be drawn in max_pixels
+ // given that the character at start_pos should be the last character (or as close to last as possible).
+ S32 firstDrawableChar(const llwchar* wchars, F32 max_pixels, S32 text_len, S32 start_pos=S32_MAX, S32 max_chars = S32_MAX) const;
+
+ // Returns the index of the character closest to pixel position x (ignoring text to the right of max_pixels and max_chars)
+ S32 charFromPixelOffset(const llwchar* wchars, S32 char_offset, F32 x, F32 max_pixels=F32_MAX, S32 max_chars = S32_MAX, BOOL round = TRUE) const;
+
+ const LLFontDescriptor& getFontDesc() const;
+
+ void generateASCIIglyphs();
+
+
+ static void initClass(F32 screen_dpi, F32 x_scale, F32 y_scale, const std::string& app_dir, bool create_gl_textures = true);
+
+ void dumpTextures();
+ static void dumpFonts();
+ static void dumpFontTextures();
+
+ // Load sans-serif, sans-serif-small, etc.
+ // Slow, requires multiple seconds to load fonts.
+ static bool loadDefaultFonts();
static void loadCommonFonts();
- static void destroyDefaultFonts();
- static void destroyAllGL();
+ static void destroyDefaultFonts();
+ static void destroyAllGL();
+
+ // Takes a string with potentially several flags, i.e. "NORMAL|BOLD|ITALIC"
+ static U8 getStyleFromString(const std::string &style);
+ static std::string getStringFromStyle(U8 style);
- // Takes a string with potentially several flags, i.e. "NORMAL|BOLD|ITALIC"
- static U8 getStyleFromString(const std::string &style);
- static std::string getStringFromStyle(U8 style);
+ static std::string nameFromFont(const LLFontGL* fontp);
+ static std::string sizeFromFont(const LLFontGL* fontp);
- static std::string nameFromFont(const LLFontGL* fontp);
- static std::string sizeFromFont(const LLFontGL* fontp);
+ static std::string nameFromHAlign(LLFontGL::HAlign align);
+ static LLFontGL::HAlign hAlignFromName(const std::string& name);
- static std::string nameFromHAlign(LLFontGL::HAlign align);
- static LLFontGL::HAlign hAlignFromName(const std::string& name);
+ static std::string nameFromVAlign(LLFontGL::VAlign align);
+ static LLFontGL::VAlign vAlignFromName(const std::string& name);
- static std::string nameFromVAlign(LLFontGL::VAlign align);
- static LLFontGL::VAlign vAlignFromName(const std::string& name);
+ static void setFontDisplay(BOOL flag) { sDisplayFont = flag; }
- static void setFontDisplay(BOOL flag) { sDisplayFont = flag; }
-
- static LLFontGL* getFontEmoji();
- static LLFontGL* getFontEmojiHuge();
- static LLFontGL* getFontMonospace();
- static LLFontGL* getFontSansSerifSmall();
+ static LLFontGL* getFontEmojiSmall();
+ static LLFontGL* getFontEmojiMedium();
+ static LLFontGL* getFontEmojiLarge();
+ static LLFontGL* getFontEmojiHuge();
+ static LLFontGL* getFontMonospace();
+ static LLFontGL* getFontSansSerifSmall();
static LLFontGL* getFontSansSerifSmallBold();
static LLFontGL* getFontSansSerifSmallItalic();
- static LLFontGL* getFontSansSerif();
- static LLFontGL* getFontSansSerifBig();
- static LLFontGL* getFontSansSerifHuge();
- static LLFontGL* getFontSansSerifBold();
- static LLFontGL* getFont(const LLFontDescriptor& desc);
- // Use with legacy names like "SANSSERIF_SMALL" or "OCRA"
- static LLFontGL* getFontByName(const std::string& name);
- static LLFontGL* getFontDefault(); // default fallback font
-
- static std::string getFontPathLocal();
- static std::string getFontPathSystem();
-
- static LLCoordGL sCurOrigin;
- static F32 sCurDepth;
- static std::vector<std::pair<LLCoordGL, F32> > sOriginStack;
-
- static LLColor4 sShadowColor;
-
- static F32 sVertDPI;
- static F32 sHorizDPI;
- static F32 sScaleX;
- static F32 sScaleY;
- static BOOL sDisplayFont ;
- static std::string sAppDir; // For loading fonts
+ static LLFontGL* getFontSansSerif();
+ static LLFontGL* getFontSansSerifBig();
+ static LLFontGL* getFontSansSerifHuge();
+ static LLFontGL* getFontSansSerifBold();
+ static LLFontGL* getFont(const LLFontDescriptor& desc);
+ // Use with legacy names like "SANSSERIF_SMALL" or "OCRA"
+ static LLFontGL* getFontByName(const std::string& name);
+ static LLFontGL* getFontDefault(); // default fallback font
+
+ static std::string getFontPathLocal();
+ static std::string getFontPathSystem();
+
+ static LLCoordGL sCurOrigin;
+ static F32 sCurDepth;
+ static std::vector<std::pair<LLCoordGL, F32> > sOriginStack;
+
+ static LLColor4 sShadowColor;
+
+ static F32 sVertDPI;
+ static F32 sHorizDPI;
+ static F32 sScaleX;
+ static F32 sScaleY;
+ static BOOL sDisplayFont ;
+ static std::string sAppDir; // For loading fonts
private:
- friend class LLFontRegistry;
- friend class LLTextBillboard;
- friend class LLHUDText;
+ friend class LLFontRegistry;
+ friend class LLTextBillboard;
+ friend class LLHUDText;
- LLFontGL(const LLFontGL &source);
- LLFontGL &operator=(const LLFontGL &source);
+ LLFontGL(const LLFontGL &source);
+ LLFontGL &operator=(const LLFontGL &source);
- LLFontDescriptor mFontDescriptor;
- LLPointer<LLFontFreetype> mFontFreetype;
+ LLFontDescriptor mFontDescriptor;
+ LLPointer<LLFontFreetype> mFontFreetype;
- 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;
+ 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;
+ // Registry holds all instantiated fonts.
+ static LLFontRegistry* sFontRegistry;
};
#endif
diff --git a/indra/llrender/llfontregistry.cpp b/indra/llrender/llfontregistry.cpp
index d2c7e466e6..546211aac8 100644
--- a/indra/llrender/llfontregistry.cpp
+++ b/indra/llrender/llfontregistry.cpp
@@ -1,4 +1,4 @@
-/**
+/**
* @file llfontregistry.cpp
* @author Brad Payne
* @brief Storage for fonts.
@@ -6,21 +6,21 @@
* $LicenseInfo:firstyear=2008&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -48,90 +48,90 @@ const std::string MACOSX_FONT_PATH_LIBRARY = "/Library/Fonts/";
const std::string MACOSX_FONT_SUPPLEMENTAL = "Supplemental/";
LLFontDescriptor::char_functor_map_t LLFontDescriptor::mCharFunctors({
- { "is_emoji", LLStringOps::isEmoji }
+ { "is_emoji", LLStringOps::isEmoji }
});
LLFontDescriptor::LLFontDescriptor():
- mStyle(0)
+ mStyle(0)
{
}
LLFontDescriptor::LLFontDescriptor(const std::string& name,
- const std::string& size,
- const U8 style,
- const font_file_info_vec_t& font_files):
- mName(name),
- mSize(size),
- mStyle(style),
- mFontFiles(font_files)
+ const std::string& size,
+ const U8 style,
+ const font_file_info_vec_t& font_files):
+ mName(name),
+ mSize(size),
+ mStyle(style),
+ mFontFiles(font_files)
{
}
LLFontDescriptor::LLFontDescriptor(const std::string& name,
- const std::string& size,
- const U8 style,
- const font_file_info_vec_t& font_list,
- const font_file_info_vec_t& font_collection_files) :
- LLFontDescriptor(name, size, style, font_list)
+ const std::string& size,
+ const U8 style,
+ const font_file_info_vec_t& font_list,
+ const font_file_info_vec_t& font_collection_files) :
+ LLFontDescriptor(name, size, style, font_list)
{
- mFontCollectionFiles = font_collection_files;
+ mFontCollectionFiles = font_collection_files;
}
LLFontDescriptor::LLFontDescriptor(const std::string& name,
- const std::string& size,
- const U8 style):
- mName(name),
- mSize(size),
- mStyle(style)
+ const std::string& size,
+ const U8 style):
+ mName(name),
+ mSize(size),
+ mStyle(style)
{
}
bool LLFontDescriptor::operator<(const LLFontDescriptor& b) const
{
- if (mName < b.mName)
- return true;
- else if (mName > b.mName)
- return false;
-
- if (mStyle < b.mStyle)
- return true;
- else if (mStyle > b.mStyle)
- return false;
-
- if (mSize < b.mSize)
- return true;
- else
- return false;
+ if (mName < b.mName)
+ return true;
+ else if (mName > b.mName)
+ return false;
+
+ if (mStyle < b.mStyle)
+ return true;
+ else if (mStyle > b.mStyle)
+ return false;
+
+ if (mSize < b.mSize)
+ return true;
+ else
+ return false;
}
static const std::string s_template_string("TEMPLATE");
bool LLFontDescriptor::isTemplate() const
{
- return getSize() == s_template_string;
+ return getSize() == s_template_string;
}
// Look for substring match and remove substring if matched.
bool removeSubString(std::string& str, const std::string& substr)
{
- size_t pos = str.find(substr);
- if (pos != string::npos)
- {
- str.erase(pos, substr.size());
- return true;
- }
- return false;
+ size_t pos = str.find(substr);
+ if (pos != string::npos)
+ {
+ str.erase(pos, substr.size());
+ return true;
+ }
+ return false;
}
// Check for substring match without modifying the source string.
bool findSubString(std::string& str, const std::string& substr)
{
- size_t pos = str.find(substr);
- if (pos != string::npos)
- {
- return true;
- }
- return false;
+ size_t pos = str.find(substr);
+ if (pos != string::npos)
+ {
+ return true;
+ }
+ return false;
}
@@ -145,618 +145,618 @@ bool findSubString(std::string& str, const std::string& substr)
// - "SansSerifBold" would normalize to { "SansSerifBold", "Medium", BOLD }
LLFontDescriptor LLFontDescriptor::normalize() const
{
- std::string new_name(mName);
- std::string new_size(mSize);
- U8 new_style(mStyle);
-
- // Only care about style to extent it can be picked up by font.
- new_style &= (LLFontGL::BOLD | LLFontGL::ITALIC);
-
- // All these transformations are to support old-style font specifications.
- if (removeSubString(new_name,"Small"))
- new_size = "Small";
- if (removeSubString(new_name,"Big"))
- new_size = "Large";
- if (removeSubString(new_name,"Medium"))
- new_size = "Medium";
- if (removeSubString(new_name,"Large"))
- new_size = "Large";
- if (removeSubString(new_name,"Huge"))
- new_size = "Huge";
-
- // HACK - Monospace is the only one we don't remove, so
- // name "Monospace" doesn't get taken down to ""
- // For other fonts, there's no ambiguity between font name and size specifier.
- if (new_size != s_template_string && new_size.empty() && findSubString(new_name,"Monospace"))
- new_size = "Monospace";
- if (new_size.empty())
- new_size = "Medium";
-
- if (removeSubString(new_name,"Bold"))
- new_style |= LLFontGL::BOLD;
-
- if (removeSubString(new_name,"Italic"))
- new_style |= LLFontGL::ITALIC;
-
- return LLFontDescriptor(new_name,new_size,new_style, getFontFiles(), getFontCollectionFiles());
+ std::string new_name(mName);
+ std::string new_size(mSize);
+ U8 new_style(mStyle);
+
+ // Only care about style to extent it can be picked up by font.
+ new_style &= (LLFontGL::BOLD | LLFontGL::ITALIC);
+
+ // All these transformations are to support old-style font specifications.
+ if (removeSubString(new_name,"Small"))
+ new_size = "Small";
+ if (removeSubString(new_name,"Big"))
+ new_size = "Large";
+ if (removeSubString(new_name,"Medium"))
+ new_size = "Medium";
+ if (removeSubString(new_name,"Large"))
+ new_size = "Large";
+ if (removeSubString(new_name,"Huge"))
+ new_size = "Huge";
+
+ // HACK - Monospace is the only one we don't remove, so
+ // name "Monospace" doesn't get taken down to ""
+ // For other fonts, there's no ambiguity between font name and size specifier.
+ if (new_size != s_template_string && new_size.empty() && findSubString(new_name,"Monospace"))
+ new_size = "Monospace";
+ if (new_size.empty())
+ new_size = "Medium";
+
+ if (removeSubString(new_name,"Bold"))
+ new_style |= LLFontGL::BOLD;
+
+ if (removeSubString(new_name,"Italic"))
+ new_style |= LLFontGL::ITALIC;
+
+ return LLFontDescriptor(new_name,new_size,new_style, getFontFiles(), getFontCollectionFiles());
}
void LLFontDescriptor::addFontFile(const std::string& file_name, const std::string& char_functor)
{
- char_functor_map_t::const_iterator it = mCharFunctors.find(char_functor);
- mFontFiles.push_back(LLFontFileInfo(file_name, (mCharFunctors.end() != it) ? it->second : nullptr));
+ char_functor_map_t::const_iterator it = mCharFunctors.find(char_functor);
+ mFontFiles.push_back(LLFontFileInfo(file_name, (mCharFunctors.end() != it) ? it->second : nullptr));
}
void LLFontDescriptor::addFontCollectionFile(const std::string& file_name, const std::string& char_functor)
{
- char_functor_map_t::const_iterator it = mCharFunctors.find(char_functor);
- mFontCollectionFiles.push_back(LLFontFileInfo(file_name, (mCharFunctors.end() != it) ? it->second : nullptr));
+ char_functor_map_t::const_iterator it = mCharFunctors.find(char_functor);
+ mFontCollectionFiles.push_back(LLFontFileInfo(file_name, (mCharFunctors.end() != it) ? it->second : nullptr));
}
LLFontRegistry::LLFontRegistry(bool create_gl_textures)
-: mCreateGLTextures(create_gl_textures)
+: mCreateGLTextures(create_gl_textures)
{
- // This is potentially a slow directory traversal, so we want to
- // cache the result.
- mUltimateFallbackList = LLWindow::getDynamicFallbackFontList();
+ // This is potentially a slow directory traversal, so we want to
+ // cache the result.
+ mUltimateFallbackList = LLWindow::getDynamicFallbackFontList();
}
LLFontRegistry::~LLFontRegistry()
{
- clear();
+ clear();
}
bool LLFontRegistry::parseFontInfo(const std::string& xml_filename)
{
- bool success = false; // Succeed if we find and read at least one XUI file
- const string_vec_t xml_paths = gDirUtilp->findSkinnedFilenames(LLDir::XUI, xml_filename);
- if (xml_paths.empty())
- {
- // We didn't even find one single XUI file
- return false;
- }
-
- for (string_vec_t::const_iterator path_it = xml_paths.begin();
- path_it != xml_paths.end();
- ++path_it)
- {
- LLXMLNodePtr root;
- bool parsed_file = LLXMLNode::parseFile(*path_it, root, NULL);
-
- if (!parsed_file)
- continue;
-
- if ( root.isNull() || ! root->hasName( "fonts" ) )
- {
- LL_WARNS() << "Bad font info file: " << *path_it << LL_ENDL;
- continue;
- }
-
- std::string root_name;
- root->getAttributeString("name",root_name);
- if (root->hasName("fonts"))
- {
- // Expect a collection of children consisting of "font" or "font_size" entries
- bool init_succ = init_from_xml(this, root);
- success = success || init_succ;
- }
- }
-
- //if (success)
- // dump();
-
- return success;
+ bool success = false; // Succeed if we find and read at least one XUI file
+ const string_vec_t xml_paths = gDirUtilp->findSkinnedFilenames(LLDir::XUI, xml_filename);
+ if (xml_paths.empty())
+ {
+ // We didn't even find one single XUI file
+ return false;
+ }
+
+ for (string_vec_t::const_iterator path_it = xml_paths.begin();
+ path_it != xml_paths.end();
+ ++path_it)
+ {
+ LLXMLNodePtr root;
+ bool parsed_file = LLXMLNode::parseFile(*path_it, root, NULL);
+
+ if (!parsed_file)
+ continue;
+
+ if ( root.isNull() || ! root->hasName( "fonts" ) )
+ {
+ LL_WARNS() << "Bad font info file: " << *path_it << LL_ENDL;
+ continue;
+ }
+
+ std::string root_name;
+ root->getAttributeString("name",root_name);
+ if (root->hasName("fonts"))
+ {
+ // Expect a collection of children consisting of "font" or "font_size" entries
+ bool init_succ = init_from_xml(this, root);
+ success = success || init_succ;
+ }
+ }
+
+ //if (success)
+ // dump();
+
+ return success;
}
std::string currentOsName()
{
#if LL_WINDOWS
- return "Windows";
+ return "Windows";
#elif LL_DARWIN
- return "Mac";
+ return "Mac";
#elif LL_LINUX
- return "Linux";
+ return "Linux";
#else
- return "";
+ return "";
#endif
}
bool font_desc_init_from_xml(LLXMLNodePtr node, LLFontDescriptor& desc)
{
- if (node->hasName("font"))
- {
- std::string attr_name;
- if (node->getAttributeString("name",attr_name))
- {
- desc.setName(attr_name);
- }
-
- std::string attr_style;
- if (node->getAttributeString("font_style",attr_style))
- {
- desc.setStyle(LLFontGL::getStyleFromString(attr_style));
- }
-
- desc.setSize(s_template_string);
- }
-
- LLXMLNodePtr child;
- for (child = node->getFirstChild(); child.notNull(); child = child->getNextSibling())
- {
- std::string child_name;
- child->getAttributeString("name",child_name);
- if (child->hasName("file"))
- {
- std::string font_file_name = child->getTextContents();
- std::string char_functor;
-
- if (child->hasAttribute("functor"))
- {
- child->getAttributeString("functor", char_functor);
- }
-
- if (child->hasAttribute("load_collection"))
- {
- BOOL col = FALSE;
- child->getAttributeBOOL("load_collection", col);
- if (col)
- {
- desc.addFontCollectionFile(font_file_name, char_functor);
- }
- }
-
- desc.addFontFile(font_file_name, char_functor);
- }
- else if (child->hasName("os"))
- {
- if (child_name == currentOsName())
- {
- font_desc_init_from_xml(child, desc);
- }
- }
- }
- return true;
+ if (node->hasName("font"))
+ {
+ std::string attr_name;
+ if (node->getAttributeString("name",attr_name))
+ {
+ desc.setName(attr_name);
+ }
+
+ std::string attr_style;
+ if (node->getAttributeString("font_style",attr_style))
+ {
+ desc.setStyle(LLFontGL::getStyleFromString(attr_style));
+ }
+
+ desc.setSize(s_template_string);
+ }
+
+ LLXMLNodePtr child;
+ for (child = node->getFirstChild(); child.notNull(); child = child->getNextSibling())
+ {
+ std::string child_name;
+ child->getAttributeString("name",child_name);
+ if (child->hasName("file"))
+ {
+ std::string font_file_name = child->getTextContents();
+ std::string char_functor;
+
+ if (child->hasAttribute("functor"))
+ {
+ child->getAttributeString("functor", char_functor);
+ }
+
+ if (child->hasAttribute("load_collection"))
+ {
+ BOOL col = FALSE;
+ child->getAttributeBOOL("load_collection", col);
+ if (col)
+ {
+ desc.addFontCollectionFile(font_file_name, char_functor);
+ }
+ }
+
+ desc.addFontFile(font_file_name, char_functor);
+ }
+ else if (child->hasName("os"))
+ {
+ if (child_name == currentOsName())
+ {
+ font_desc_init_from_xml(child, desc);
+ }
+ }
+ }
+ return true;
}
bool init_from_xml(LLFontRegistry* registry, LLXMLNodePtr node)
{
- LLXMLNodePtr child;
-
- for (child = node->getFirstChild(); child.notNull(); child = child->getNextSibling())
- {
- std::string child_name;
- child->getAttributeString("name",child_name);
- if (child->hasName("font"))
- {
- LLFontDescriptor desc;
- bool font_succ = font_desc_init_from_xml(child, desc);
- LLFontDescriptor norm_desc = desc.normalize();
- if (font_succ)
- {
- // if this is the first time we've seen this font name,
- // create a new template map entry for it.
- const LLFontDescriptor *match_desc = registry->getMatchingFontDesc(desc);
- if (match_desc == NULL)
- {
- // Create a new entry (with no corresponding font).
- registry->mFontMap[norm_desc] = NULL;
- }
- // otherwise, find the existing entry and combine data.
- else
- {
- // Prepend files from desc.
- // A little roundabout because the map key is const,
- // so we have to fetch it, make a new map key, and
- // replace the old entry.
- font_file_info_vec_t font_files = match_desc->getFontFiles();
- font_files.insert(font_files.begin(),
- desc.getFontFiles().begin(),
- desc.getFontFiles().end());
-
- font_file_info_vec_t font_collection_files = match_desc->getFontCollectionFiles();
- font_collection_files.insert(font_collection_files.begin(),
- desc.getFontCollectionFiles().begin(),
- desc.getFontCollectionFiles().end());
-
- LLFontDescriptor new_desc = *match_desc;
- new_desc.setFontFiles(font_files);
- new_desc.setFontCollectionFiles(font_collection_files);
- registry->mFontMap.erase(*match_desc);
- registry->mFontMap[new_desc] = NULL;
- }
- }
- }
- else if (child->hasName("font_size"))
- {
- std::string size_name;
- F32 size_value;
- if (child->getAttributeString("name",size_name) &&
- child->getAttributeF32("size",size_value))
- {
- registry->mFontSizes[size_name] = size_value;
- }
-
- }
- }
- return true;
+ LLXMLNodePtr child;
+
+ for (child = node->getFirstChild(); child.notNull(); child = child->getNextSibling())
+ {
+ std::string child_name;
+ child->getAttributeString("name",child_name);
+ if (child->hasName("font"))
+ {
+ LLFontDescriptor desc;
+ bool font_succ = font_desc_init_from_xml(child, desc);
+ LLFontDescriptor norm_desc = desc.normalize();
+ if (font_succ)
+ {
+ // if this is the first time we've seen this font name,
+ // create a new template map entry for it.
+ const LLFontDescriptor *match_desc = registry->getMatchingFontDesc(desc);
+ if (match_desc == NULL)
+ {
+ // Create a new entry (with no corresponding font).
+ registry->mFontMap[norm_desc] = NULL;
+ }
+ // otherwise, find the existing entry and combine data.
+ else
+ {
+ // Prepend files from desc.
+ // A little roundabout because the map key is const,
+ // so we have to fetch it, make a new map key, and
+ // replace the old entry.
+ font_file_info_vec_t font_files = match_desc->getFontFiles();
+ font_files.insert(font_files.begin(),
+ desc.getFontFiles().begin(),
+ desc.getFontFiles().end());
+
+ font_file_info_vec_t font_collection_files = match_desc->getFontCollectionFiles();
+ font_collection_files.insert(font_collection_files.begin(),
+ desc.getFontCollectionFiles().begin(),
+ desc.getFontCollectionFiles().end());
+
+ LLFontDescriptor new_desc = *match_desc;
+ new_desc.setFontFiles(font_files);
+ new_desc.setFontCollectionFiles(font_collection_files);
+ registry->mFontMap.erase(*match_desc);
+ registry->mFontMap[new_desc] = NULL;
+ }
+ }
+ }
+ else if (child->hasName("font_size"))
+ {
+ std::string size_name;
+ F32 size_value;
+ if (child->getAttributeString("name",size_name) &&
+ child->getAttributeF32("size",size_value))
+ {
+ registry->mFontSizes[size_name] = size_value;
+ }
+
+ }
+ }
+ return true;
}
bool LLFontRegistry::nameToSize(const std::string& size_name, F32& size)
{
- font_size_map_t::iterator it = mFontSizes.find(size_name);
- if (it != mFontSizes.end())
- {
- size = it->second;
- return true;
- }
- return false;
+ font_size_map_t::iterator it = mFontSizes.find(size_name);
+ if (it != mFontSizes.end())
+ {
+ size = it->second;
+ return true;
+ }
+ return false;
}
LLFontGL *LLFontRegistry::createFont(const LLFontDescriptor& desc)
{
- // Name should hold a font name recognized as a setting; the value
- // of the setting should be a list of font files.
- // Size should be a recognized string value
- // Style should be a set of flags including any implied by the font name.
-
- // First decipher the requested size.
- LLFontDescriptor norm_desc = desc.normalize();
- F32 point_size;
- bool found_size = nameToSize(norm_desc.getSize(),point_size);
- if (!found_size)
- {
- LL_WARNS() << "createFont unrecognized size " << norm_desc.getSize() << LL_ENDL;
- return NULL;
- }
- LL_INFOS() << "createFont " << norm_desc.getName() << " size " << norm_desc.getSize() << " style " << ((S32) norm_desc.getStyle()) << LL_ENDL;
- F32 fallback_scale = 1.0;
-
- // Find corresponding font template (based on same descriptor with no size specified)
- LLFontDescriptor template_desc(norm_desc);
- template_desc.setSize(s_template_string);
- const LLFontDescriptor *match_desc = getClosestFontTemplate(template_desc);
- if (!match_desc)
- {
- LL_WARNS() << "createFont failed, no template found for "
- << norm_desc.getName() << " style [" << ((S32)norm_desc.getStyle()) << "]" << LL_ENDL;
- return NULL;
- }
-
- // See whether this best-match font has already been instantiated in the requested size.
- LLFontDescriptor nearest_exact_desc = *match_desc;
- nearest_exact_desc.setSize(norm_desc.getSize());
- font_reg_map_t::iterator it = mFontMap.find(nearest_exact_desc);
- // If we fail to find a font in the fonts directory, it->second might be NULL.
- // We shouldn't construcnt a font with a NULL mFontFreetype.
- // This may not be the best solution, but it at least prevents a crash.
- if (it != mFontMap.end() && it->second != NULL)
- {
- LL_INFOS() << "-- matching font exists: " << nearest_exact_desc.getName() << " size " << nearest_exact_desc.getSize() << " style " << ((S32) nearest_exact_desc.getStyle()) << LL_ENDL;
-
- // copying underlying Freetype font, and storing in LLFontGL with requested font descriptor
- LLFontGL *font = new LLFontGL;
- font->mFontDescriptor = desc;
- font->mFontFreetype = it->second->mFontFreetype;
- mFontMap[desc] = font;
-
- return font;
- }
-
- // Build list of font names to look for.
- // Files specified for this font come first, followed by those from the default descriptor.
- font_file_info_vec_t font_files = match_desc->getFontFiles();
- font_file_info_vec_t font_collection_files = match_desc->getFontCollectionFiles();
- LLFontDescriptor default_desc("default",s_template_string,0);
- const LLFontDescriptor *match_default_desc = getMatchingFontDesc(default_desc);
- if (match_default_desc)
- {
- font_files.insert(font_files.end(),
- match_default_desc->getFontFiles().begin(),
- match_default_desc->getFontFiles().end());
- font_collection_files.insert(font_collection_files.end(),
- match_default_desc->getFontCollectionFiles().begin(),
- match_default_desc->getFontCollectionFiles().end());
- }
-
- // Add ultimate fallback list - generated dynamically on linux,
- // null elsewhere.
- std::transform(getUltimateFallbackList().begin(), getUltimateFallbackList().end(), std::back_inserter(font_files),
- [](const std::string& file_name) { return LLFontFileInfo(file_name); });
-
- // Load fonts based on names.
- if (font_files.empty())
- {
- LL_WARNS() << "createFont failed, no file names specified" << LL_ENDL;
- return NULL;
- }
-
- LLFontGL *result = NULL;
-
- // The first font will get pulled will be the "head" font, set to non-fallback.
- // Rest will consitute the fallback list.
- BOOL is_first_found = TRUE;
-
- string_vec_t font_search_paths;
- font_search_paths.push_back(LLFontGL::getFontPathLocal());
- font_search_paths.push_back(LLFontGL::getFontPathSystem());
+ // Name should hold a font name recognized as a setting; the value
+ // of the setting should be a list of font files.
+ // Size should be a recognized string value
+ // Style should be a set of flags including any implied by the font name.
+
+ // First decipher the requested size.
+ LLFontDescriptor norm_desc = desc.normalize();
+ F32 point_size;
+ bool found_size = nameToSize(norm_desc.getSize(),point_size);
+ if (!found_size)
+ {
+ LL_WARNS() << "createFont unrecognized size " << norm_desc.getSize() << LL_ENDL;
+ return NULL;
+ }
+ LL_INFOS() << "createFont " << norm_desc.getName() << " size " << norm_desc.getSize() << " style " << ((S32) norm_desc.getStyle()) << LL_ENDL;
+ F32 fallback_scale = 1.0;
+
+ // Find corresponding font template (based on same descriptor with no size specified)
+ LLFontDescriptor template_desc(norm_desc);
+ template_desc.setSize(s_template_string);
+ const LLFontDescriptor *match_desc = getClosestFontTemplate(template_desc);
+ if (!match_desc)
+ {
+ LL_WARNS() << "createFont failed, no template found for "
+ << norm_desc.getName() << " style [" << ((S32)norm_desc.getStyle()) << "]" << LL_ENDL;
+ return NULL;
+ }
+
+ // See whether this best-match font has already been instantiated in the requested size.
+ LLFontDescriptor nearest_exact_desc = *match_desc;
+ nearest_exact_desc.setSize(norm_desc.getSize());
+ font_reg_map_t::iterator it = mFontMap.find(nearest_exact_desc);
+ // If we fail to find a font in the fonts directory, it->second might be NULL.
+ // We shouldn't construcnt a font with a NULL mFontFreetype.
+ // This may not be the best solution, but it at least prevents a crash.
+ if (it != mFontMap.end() && it->second != NULL)
+ {
+ LL_INFOS() << "-- matching font exists: " << nearest_exact_desc.getName() << " size " << nearest_exact_desc.getSize() << " style " << ((S32) nearest_exact_desc.getStyle()) << LL_ENDL;
+
+ // copying underlying Freetype font, and storing in LLFontGL with requested font descriptor
+ LLFontGL *font = new LLFontGL;
+ font->mFontDescriptor = desc;
+ font->mFontFreetype = it->second->mFontFreetype;
+ mFontMap[desc] = font;
+
+ return font;
+ }
+
+ // Build list of font names to look for.
+ // Files specified for this font come first, followed by those from the default descriptor.
+ font_file_info_vec_t font_files = match_desc->getFontFiles();
+ font_file_info_vec_t font_collection_files = match_desc->getFontCollectionFiles();
+ LLFontDescriptor default_desc("default",s_template_string,0);
+ const LLFontDescriptor *match_default_desc = getMatchingFontDesc(default_desc);
+ if (match_default_desc)
+ {
+ font_files.insert(font_files.end(),
+ match_default_desc->getFontFiles().begin(),
+ match_default_desc->getFontFiles().end());
+ font_collection_files.insert(font_collection_files.end(),
+ match_default_desc->getFontCollectionFiles().begin(),
+ match_default_desc->getFontCollectionFiles().end());
+ }
+
+ // Add ultimate fallback list - generated dynamically on linux,
+ // null elsewhere.
+ std::transform(getUltimateFallbackList().begin(), getUltimateFallbackList().end(), std::back_inserter(font_files),
+ [](const std::string& file_name) { return LLFontFileInfo(file_name); });
+
+ // Load fonts based on names.
+ if (font_files.empty())
+ {
+ LL_WARNS() << "createFont failed, no file names specified" << LL_ENDL;
+ return NULL;
+ }
+
+ LLFontGL *result = NULL;
+
+ // The first font will get pulled will be the "head" font, set to non-fallback.
+ // Rest will consitute the fallback list.
+ BOOL is_first_found = TRUE;
+
+ string_vec_t font_search_paths;
+ font_search_paths.push_back(LLFontGL::getFontPathLocal());
+ font_search_paths.push_back(LLFontGL::getFontPathSystem());
#if LL_DARWIN
- font_search_paths.push_back(MACOSX_FONT_PATH_LIBRARY);
- font_search_paths.push_back(MACOSX_FONT_PATH_LIBRARY + MACOSX_FONT_SUPPLEMENTAL);
- font_search_paths.push_back(LLFontGL::getFontPathSystem() + MACOSX_FONT_SUPPLEMENTAL);
+ font_search_paths.push_back(MACOSX_FONT_PATH_LIBRARY);
+ font_search_paths.push_back(MACOSX_FONT_PATH_LIBRARY + MACOSX_FONT_SUPPLEMENTAL);
+ font_search_paths.push_back(LLFontGL::getFontPathSystem() + MACOSX_FONT_SUPPLEMENTAL);
#endif
- // The fontname string may contain multiple font file names separated by semicolons.
- // Break it apart and try loading each one, in order.
- for(font_file_info_vec_t::iterator font_file_it = font_files.begin();
- font_file_it != font_files.end();
- ++font_file_it)
- {
- LLFontGL *fontp = NULL;
-
- bool is_ft_collection = (std::find_if(font_collection_files.begin(), font_collection_files.end(),
- [&font_file_it](const LLFontFileInfo& ffi) { return font_file_it->FileName == ffi.FileName; }) != font_collection_files.end());
-
- // *HACK: Fallback fonts don't render, so we can use that to suppress
- // creation of OpenGL textures for test apps. JC
- BOOL is_fallback = !is_first_found || !mCreateGLTextures;
- F32 extra_scale = (is_fallback)?fallback_scale:1.0;
- F32 point_size_scale = extra_scale * point_size;
- bool is_font_loaded = false;
- for(string_vec_t::iterator font_search_path_it = font_search_paths.begin();
- font_search_path_it != font_search_paths.end();
- ++font_search_path_it)
- {
- const std::string font_path = *font_search_path_it + font_file_it->FileName;
-
- fontp = new LLFontGL;
- S32 num_faces = is_ft_collection ? fontp->getNumFaces(font_path) : 1;
- for (S32 i = 0; i < num_faces; i++)
- {
- if (fontp == NULL)
- {
- fontp = new LLFontGL;
- }
- if (fontp->loadFace(font_path, point_size_scale,
- LLFontGL::sVertDPI, LLFontGL::sHorizDPI, is_fallback, i))
- {
- is_font_loaded = true;
- if (is_first_found)
- {
- result = fontp;
- is_first_found = false;
- }
- else
- {
- result->mFontFreetype->addFallbackFont(fontp->mFontFreetype, font_file_it->CharFunctor);
-
- delete fontp;
- fontp = NULL;
- }
- }
- else
- {
- delete fontp;
- fontp = NULL;
- }
- }
- if (is_font_loaded) break;
- }
- if(!is_font_loaded)
- {
- LL_INFOS_ONCE("LLFontRegistry") << "Couldn't load font " << font_file_it->FileName << LL_ENDL;
- delete fontp;
- fontp = NULL;
- }
- }
-
- if (result)
- {
- result->mFontDescriptor = desc;
- }
- else
- {
- LL_WARNS() << "createFont failed in some way" << LL_ENDL;
- }
-
- mFontMap[desc] = result;
- return result;
+ // The fontname string may contain multiple font file names separated by semicolons.
+ // Break it apart and try loading each one, in order.
+ for(font_file_info_vec_t::iterator font_file_it = font_files.begin();
+ font_file_it != font_files.end();
+ ++font_file_it)
+ {
+ LLFontGL *fontp = NULL;
+
+ bool is_ft_collection = (std::find_if(font_collection_files.begin(), font_collection_files.end(),
+ [&font_file_it](const LLFontFileInfo& ffi) { return font_file_it->FileName == ffi.FileName; }) != font_collection_files.end());
+
+ // *HACK: Fallback fonts don't render, so we can use that to suppress
+ // creation of OpenGL textures for test apps. JC
+ BOOL is_fallback = !is_first_found || !mCreateGLTextures;
+ F32 extra_scale = (is_fallback)?fallback_scale:1.0;
+ F32 point_size_scale = extra_scale * point_size;
+ bool is_font_loaded = false;
+ for(string_vec_t::iterator font_search_path_it = font_search_paths.begin();
+ font_search_path_it != font_search_paths.end();
+ ++font_search_path_it)
+ {
+ const std::string font_path = *font_search_path_it + font_file_it->FileName;
+
+ fontp = new LLFontGL;
+ S32 num_faces = is_ft_collection ? fontp->getNumFaces(font_path) : 1;
+ for (S32 i = 0; i < num_faces; i++)
+ {
+ if (fontp == NULL)
+ {
+ fontp = new LLFontGL;
+ }
+ if (fontp->loadFace(font_path, point_size_scale,
+ LLFontGL::sVertDPI, LLFontGL::sHorizDPI, is_fallback, i))
+ {
+ is_font_loaded = true;
+ if (is_first_found)
+ {
+ result = fontp;
+ is_first_found = false;
+ }
+ else
+ {
+ result->mFontFreetype->addFallbackFont(fontp->mFontFreetype, font_file_it->CharFunctor);
+
+ delete fontp;
+ fontp = NULL;
+ }
+ }
+ else
+ {
+ delete fontp;
+ fontp = NULL;
+ }
+ }
+ if (is_font_loaded) break;
+ }
+ if(!is_font_loaded)
+ {
+ LL_INFOS_ONCE("LLFontRegistry") << "Couldn't load font " << font_file_it->FileName << LL_ENDL;
+ delete fontp;
+ fontp = NULL;
+ }
+ }
+
+ if (result)
+ {
+ result->mFontDescriptor = desc;
+ }
+ else
+ {
+ LL_WARNS() << "createFont failed in some way" << LL_ENDL;
+ }
+
+ mFontMap[desc] = result;
+ return result;
}
void LLFontRegistry::reset()
{
- for (font_reg_map_t::iterator it = mFontMap.begin();
- it != mFontMap.end();
- ++it)
- {
- // Reset the corresponding font but preserve the entry.
- if (it->second)
- it->second->reset();
- }
+ for (font_reg_map_t::iterator it = mFontMap.begin();
+ it != mFontMap.end();
+ ++it)
+ {
+ // Reset the corresponding font but preserve the entry.
+ if (it->second)
+ it->second->reset();
+ }
}
void LLFontRegistry::clear()
{
- for (font_reg_map_t::iterator it = mFontMap.begin();
- it != mFontMap.end();
- ++it)
- {
- LLFontGL *fontp = it->second;
- delete fontp;
- }
- mFontMap.clear();
+ for (font_reg_map_t::iterator it = mFontMap.begin();
+ it != mFontMap.end();
+ ++it)
+ {
+ LLFontGL *fontp = it->second;
+ delete fontp;
+ }
+ mFontMap.clear();
}
void LLFontRegistry::destroyGL()
{
- for (font_reg_map_t::iterator it = mFontMap.begin();
- it != mFontMap.end();
- ++it)
- {
- // Reset the corresponding font but preserve the entry.
- if (it->second)
- it->second->destroyGL();
- }
+ for (font_reg_map_t::iterator it = mFontMap.begin();
+ it != mFontMap.end();
+ ++it)
+ {
+ // Reset the corresponding font but preserve the entry.
+ if (it->second)
+ it->second->destroyGL();
+ }
}
LLFontGL *LLFontRegistry::getFont(const LLFontDescriptor& desc)
{
- font_reg_map_t::iterator it = mFontMap.find(desc);
- if (it != mFontMap.end())
- return it->second;
- else
- {
- LLFontGL *fontp = createFont(desc);
- if (!fontp)
- {
- LL_WARNS() << "getFont failed, name " << desc.getName()
- <<" style=[" << ((S32) desc.getStyle()) << "]"
- << " size=[" << desc.getSize() << "]" << LL_ENDL;
- }
- else
- {
- //generate glyphs for ASCII chars to avoid stalls later
- fontp->generateASCIIglyphs();
- }
- return fontp;
- }
+ font_reg_map_t::iterator it = mFontMap.find(desc);
+ if (it != mFontMap.end())
+ return it->second;
+ else
+ {
+ LLFontGL *fontp = createFont(desc);
+ if (!fontp)
+ {
+ LL_WARNS() << "getFont failed, name " << desc.getName()
+ <<" style=[" << ((S32) desc.getStyle()) << "]"
+ << " size=[" << desc.getSize() << "]" << LL_ENDL;
+ }
+ else
+ {
+ //generate glyphs for ASCII chars to avoid stalls later
+ fontp->generateASCIIglyphs();
+ }
+ return fontp;
+ }
}
const LLFontDescriptor *LLFontRegistry::getMatchingFontDesc(const LLFontDescriptor& desc)
{
- LLFontDescriptor norm_desc = desc.normalize();
+ LLFontDescriptor norm_desc = desc.normalize();
- font_reg_map_t::iterator it = mFontMap.find(norm_desc);
- if (it != mFontMap.end())
- return &(it->first);
- else
- return NULL;
+ font_reg_map_t::iterator it = mFontMap.find(norm_desc);
+ if (it != mFontMap.end())
+ return &(it->first);
+ else
+ return NULL;
}
static U32 bitCount(U8 c)
{
- U32 count = 0;
- if (c & 1)
- count++;
- if (c & 2)
- count++;
- if (c & 4)
- count++;
- if (c & 8)
- count++;
- if (c & 16)
- count++;
- if (c & 32)
- count++;
- if (c & 64)
- count++;
- if (c & 128)
- count++;
- return count;
+ U32 count = 0;
+ if (c & 1)
+ count++;
+ if (c & 2)
+ count++;
+ if (c & 4)
+ count++;
+ if (c & 8)
+ count++;
+ if (c & 16)
+ count++;
+ if (c & 32)
+ count++;
+ if (c & 64)
+ count++;
+ if (c & 128)
+ count++;
+ return count;
}
// Find nearest match for the requested descriptor.
const LLFontDescriptor *LLFontRegistry::getClosestFontTemplate(const LLFontDescriptor& desc)
{
- const LLFontDescriptor *exact_match_desc = getMatchingFontDesc(desc);
- if (exact_match_desc)
- {
- return exact_match_desc;
- }
-
- LLFontDescriptor norm_desc = desc.normalize();
-
- const LLFontDescriptor *best_match_desc = NULL;
- for (font_reg_map_t::iterator it = mFontMap.begin();
- it != mFontMap.end();
- ++it)
- {
- const LLFontDescriptor* curr_desc = &(it->first);
-
- // Ignore if not a template.
- if (!curr_desc->isTemplate())
- continue;
-
- // Ignore if font name is wrong.
- if (curr_desc->getName() != norm_desc.getName())
- continue;
-
- // Reject font if it matches any bits we don't want
- if (curr_desc->getStyle() & ~norm_desc.getStyle())
- {
- continue;
- }
-
- // Take if it's the first plausible candidate we've found.
- if (!best_match_desc)
- {
- best_match_desc = curr_desc;
- continue;
- }
-
- // Take if it matches more bits than anything before.
- U8 best_style_match_bits =
- norm_desc.getStyle() & best_match_desc->getStyle();
- U8 curr_style_match_bits =
- norm_desc.getStyle() & curr_desc->getStyle();
- if (bitCount(curr_style_match_bits) > bitCount(best_style_match_bits))
- {
- best_match_desc = curr_desc;
- continue;
- }
-
- // Tie-breaker: take if it matches bold.
- if (curr_style_match_bits & LLFontGL::BOLD) // Bold is requested and this descriptor matches it.
- {
- best_match_desc = curr_desc;
- continue;
- }
- }
-
- // Nothing matched.
- return best_match_desc;
+ const LLFontDescriptor *exact_match_desc = getMatchingFontDesc(desc);
+ if (exact_match_desc)
+ {
+ return exact_match_desc;
+ }
+
+ LLFontDescriptor norm_desc = desc.normalize();
+
+ const LLFontDescriptor *best_match_desc = NULL;
+ for (font_reg_map_t::iterator it = mFontMap.begin();
+ it != mFontMap.end();
+ ++it)
+ {
+ const LLFontDescriptor* curr_desc = &(it->first);
+
+ // Ignore if not a template.
+ if (!curr_desc->isTemplate())
+ continue;
+
+ // Ignore if font name is wrong.
+ if (curr_desc->getName() != norm_desc.getName())
+ continue;
+
+ // Reject font if it matches any bits we don't want
+ if (curr_desc->getStyle() & ~norm_desc.getStyle())
+ {
+ continue;
+ }
+
+ // Take if it's the first plausible candidate we've found.
+ if (!best_match_desc)
+ {
+ best_match_desc = curr_desc;
+ continue;
+ }
+
+ // Take if it matches more bits than anything before.
+ U8 best_style_match_bits =
+ norm_desc.getStyle() & best_match_desc->getStyle();
+ U8 curr_style_match_bits =
+ norm_desc.getStyle() & curr_desc->getStyle();
+ if (bitCount(curr_style_match_bits) > bitCount(best_style_match_bits))
+ {
+ best_match_desc = curr_desc;
+ continue;
+ }
+
+ // Tie-breaker: take if it matches bold.
+ if (curr_style_match_bits & LLFontGL::BOLD) // Bold is requested and this descriptor matches it.
+ {
+ best_match_desc = curr_desc;
+ continue;
+ }
+ }
+
+ // Nothing matched.
+ return best_match_desc;
}
void LLFontRegistry::dump()
{
- LL_INFOS() << "LLFontRegistry dump: " << LL_ENDL;
- for (font_size_map_t::iterator size_it = mFontSizes.begin();
- size_it != mFontSizes.end();
- ++size_it)
- {
- LL_INFOS() << "Size: " << size_it->first << " => " << size_it->second << LL_ENDL;
- }
- for (font_reg_map_t::iterator font_it = mFontMap.begin();
- font_it != mFontMap.end();
- ++font_it)
- {
- const LLFontDescriptor& desc = font_it->first;
- LL_INFOS() << "Font: name=" << desc.getName()
- << " style=[" << ((S32)desc.getStyle()) << "]"
- << " size=[" << desc.getSize() << "]"
- << " fileNames="
- << LL_ENDL;
- for (font_file_info_vec_t::const_iterator file_it=desc.getFontFiles().begin();
- file_it != desc.getFontFiles().end();
- ++file_it)
- {
- LL_INFOS() << " file: " << file_it->FileName << LL_ENDL;
- }
- }
+ LL_INFOS() << "LLFontRegistry dump: " << LL_ENDL;
+ for (font_size_map_t::iterator size_it = mFontSizes.begin();
+ size_it != mFontSizes.end();
+ ++size_it)
+ {
+ LL_INFOS() << "Size: " << size_it->first << " => " << size_it->second << LL_ENDL;
+ }
+ for (font_reg_map_t::iterator font_it = mFontMap.begin();
+ font_it != mFontMap.end();
+ ++font_it)
+ {
+ const LLFontDescriptor& desc = font_it->first;
+ LL_INFOS() << "Font: name=" << desc.getName()
+ << " style=[" << ((S32)desc.getStyle()) << "]"
+ << " size=[" << desc.getSize() << "]"
+ << " fileNames="
+ << LL_ENDL;
+ for (font_file_info_vec_t::const_iterator file_it=desc.getFontFiles().begin();
+ file_it != desc.getFontFiles().end();
+ ++file_it)
+ {
+ LL_INFOS() << " file: " << file_it->FileName << LL_ENDL;
+ }
+ }
}
void LLFontRegistry::dumpTextures()
{
- for (const auto& fontEntry : mFontMap)
- {
- if (fontEntry.second)
- {
- fontEntry.second->dumpTextures();
- }
- }
+ for (const auto& fontEntry : mFontMap)
+ {
+ if (fontEntry.second)
+ {
+ fontEntry.second->dumpTextures();
+ }
+ }
}
-const string_vec_t& LLFontRegistry::getUltimateFallbackList() const
-{
- return mUltimateFallbackList;
+const string_vec_t& LLFontRegistry::getUltimateFallbackList() const
+{
+ return mUltimateFallbackList;
}
diff --git a/indra/llrender/llfontregistry.h b/indra/llrender/llfontregistry.h
index b0ef72c5de..8bbf5aa30c 100644
--- a/indra/llrender/llfontregistry.h
+++ b/indra/llrender/llfontregistry.h
@@ -1,4 +1,4 @@
-/**
+/**
* @file llfontregistry.h
* @author Brad Payne
* @brief Storage for fonts.
@@ -6,21 +6,21 @@
* $LicenseInfo:firstyear=2008&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -36,107 +36,107 @@ typedef std::vector<std::string> string_vec_t;
struct LLFontFileInfo
{
- LLFontFileInfo(const std::string& file_name, const std::function<bool(llwchar)>& char_functor = nullptr)
- : FileName(file_name)
- , CharFunctor(char_functor)
- {
- }
-
- LLFontFileInfo(const LLFontFileInfo& ffi)
- : FileName(ffi.FileName)
- , CharFunctor(ffi.CharFunctor)
- {
- }
-
- std::string FileName;
- std::function<bool(llwchar)> CharFunctor;
+ LLFontFileInfo(const std::string& file_name, const std::function<bool(llwchar)>& char_functor = nullptr)
+ : FileName(file_name)
+ , CharFunctor(char_functor)
+ {
+ }
+
+ LLFontFileInfo(const LLFontFileInfo& ffi)
+ : FileName(ffi.FileName)
+ , CharFunctor(ffi.CharFunctor)
+ {
+ }
+
+ std::string FileName;
+ std::function<bool(llwchar)> CharFunctor;
};
typedef std::vector<LLFontFileInfo> font_file_info_vec_t;
class LLFontDescriptor
{
public:
- LLFontDescriptor();
- LLFontDescriptor(const std::string& name, const std::string& size, const U8 style);
- LLFontDescriptor(const std::string& name, const std::string& size, const U8 style, const font_file_info_vec_t& font_list);
- LLFontDescriptor(const std::string& name, const std::string& size, const U8 style, const font_file_info_vec_t& font_list, const font_file_info_vec_t& font_collection_list);
- LLFontDescriptor normalize() const;
-
- bool operator<(const LLFontDescriptor& b) const;
-
- bool isTemplate() const;
-
- const std::string& getName() const { return mName; }
- void setName(const std::string& name) { mName = name; }
- const std::string& getSize() const { return mSize; }
- void setSize(const std::string& size) { mSize = size; }
-
- void addFontFile(const std::string& file_name, const std::string& char_functor = LLStringUtil::null);
- const font_file_info_vec_t & getFontFiles() const { return mFontFiles; }
- void setFontFiles(const font_file_info_vec_t& font_files) { mFontFiles = font_files; }
- void addFontCollectionFile(const std::string& file_name, const std::string& char_functor = LLStringUtil::null);
- const font_file_info_vec_t& getFontCollectionFiles() const { return mFontCollectionFiles; }
- void setFontCollectionFiles(const font_file_info_vec_t& font_collection_files) { mFontCollectionFiles = font_collection_files; }
-
- const U8 getStyle() const { return mStyle; }
- void setStyle(U8 style) { mStyle = style; }
+ LLFontDescriptor();
+ LLFontDescriptor(const std::string& name, const std::string& size, const U8 style);
+ LLFontDescriptor(const std::string& name, const std::string& size, const U8 style, const font_file_info_vec_t& font_list);
+ LLFontDescriptor(const std::string& name, const std::string& size, const U8 style, const font_file_info_vec_t& font_list, const font_file_info_vec_t& font_collection_list);
+ LLFontDescriptor normalize() const;
+
+ bool operator<(const LLFontDescriptor& b) const;
+
+ bool isTemplate() const;
+
+ const std::string& getName() const { return mName; }
+ void setName(const std::string& name) { mName = name; }
+ const std::string& getSize() const { return mSize; }
+ void setSize(const std::string& size) { mSize = size; }
+
+ void addFontFile(const std::string& file_name, const std::string& char_functor = LLStringUtil::null);
+ const font_file_info_vec_t & getFontFiles() const { return mFontFiles; }
+ void setFontFiles(const font_file_info_vec_t& font_files) { mFontFiles = font_files; }
+ void addFontCollectionFile(const std::string& file_name, const std::string& char_functor = LLStringUtil::null);
+ const font_file_info_vec_t& getFontCollectionFiles() const { return mFontCollectionFiles; }
+ void setFontCollectionFiles(const font_file_info_vec_t& font_collection_files) { mFontCollectionFiles = font_collection_files; }
+
+ const U8 getStyle() const { return mStyle; }
+ void setStyle(U8 style) { mStyle = style; }
private:
- std::string mName;
- std::string mSize;
- font_file_info_vec_t mFontFiles;
- font_file_info_vec_t mFontCollectionFiles;
- U8 mStyle;
-
- typedef std::map<std::string, std::function<bool(llwchar)>> char_functor_map_t;
- static char_functor_map_t mCharFunctors;
+ std::string mName;
+ std::string mSize;
+ font_file_info_vec_t mFontFiles;
+ font_file_info_vec_t mFontCollectionFiles;
+ U8 mStyle;
+
+ typedef std::map<std::string, std::function<bool(llwchar)>> char_functor_map_t;
+ static char_functor_map_t mCharFunctors;
};
class LLFontRegistry
{
public:
- friend bool init_from_xml(LLFontRegistry*, LLPointer<class LLXMLNode>);
- // create_gl_textures - set to false for test apps with no OpenGL window,
- // such as llui_libtest
- LLFontRegistry(bool create_gl_textures);
- ~LLFontRegistry();
+ friend bool init_from_xml(LLFontRegistry*, LLPointer<class LLXMLNode>);
+ // create_gl_textures - set to false for test apps with no OpenGL window,
+ // such as llui_libtest
+ LLFontRegistry(bool create_gl_textures);
+ ~LLFontRegistry();
+
+ // Load standard font info from XML file(s).
+ bool parseFontInfo(const std::string& xml_filename);
+
+ // Clear cached glyphs for all fonts.
+ void reset();
- // Load standard font info from XML file(s).
- bool parseFontInfo(const std::string& xml_filename);
+ // Destroy all fonts.
+ void clear();
- // Clear cached glyphs for all fonts.
- void reset();
+ // GL cleanup
+ void destroyGL();
- // Destroy all fonts.
- void clear();
+ LLFontGL *getFont(const LLFontDescriptor& desc);
+ const LLFontDescriptor *getMatchingFontDesc(const LLFontDescriptor& desc);
+ const LLFontDescriptor *getClosestFontTemplate(const LLFontDescriptor& desc);
- // GL cleanup
- void destroyGL();
-
- LLFontGL *getFont(const LLFontDescriptor& desc);
- const LLFontDescriptor *getMatchingFontDesc(const LLFontDescriptor& desc);
- const LLFontDescriptor *getClosestFontTemplate(const LLFontDescriptor& desc);
+ bool nameToSize(const std::string& size_name, F32& size);
- bool nameToSize(const std::string& size_name, F32& size);
+ void dump();
+ void dumpTextures();
- void dump();
- void dumpTextures();
-
- const string_vec_t& getUltimateFallbackList() const;
+ const string_vec_t& getUltimateFallbackList() const;
private:
- LLFontRegistry(const LLFontRegistry& other); // no-copy
- LLFontGL *createFont(const LLFontDescriptor& desc);
- typedef std::map<LLFontDescriptor,LLFontGL*> font_reg_map_t;
- typedef std::map<std::string,F32> font_size_map_t;
-
- // Given a descriptor, look up specific font instantiation.
- font_reg_map_t mFontMap;
- // Given a size name, look up the point size.
- font_size_map_t mFontSizes;
-
- string_vec_t mUltimateFallbackList;
- bool mCreateGLTextures;
+ LLFontRegistry(const LLFontRegistry& other); // no-copy
+ LLFontGL *createFont(const LLFontDescriptor& desc);
+ typedef std::map<LLFontDescriptor,LLFontGL*> font_reg_map_t;
+ typedef std::map<std::string,F32> font_size_map_t;
+
+ // Given a descriptor, look up specific font instantiation.
+ font_reg_map_t mFontMap;
+ // Given a size name, look up the point size.
+ font_size_map_t mFontSizes;
+
+ string_vec_t mUltimateFallbackList;
+ bool mCreateGLTextures;
};
#endif // LL_LLFONTREGISTRY_H
diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp
index 53b65a5b99..a34efe24d3 100644
--- a/indra/llrender/llgl.cpp
+++ b/indra/llrender/llgl.cpp
@@ -172,37 +172,37 @@ void parse_glsl_version(S32& major, S32& minor);
void ll_init_fail_log(std::string filename)
{
- gFailLog.open(filename.c_str());
+ gFailLog.open(filename.c_str());
}
void ll_fail(std::string msg)
{
- if (gDebugSession)
- {
- std::vector<std::string> lines;
+ if (gDebugSession)
+ {
+ std::vector<std::string> lines;
- gFailLog << LLError::utcTime() << " " << msg << std::endl;
+ gFailLog << LLError::utcTime() << " " << msg << std::endl;
- gFailLog << "Stack Trace:" << std::endl;
+ gFailLog << "Stack Trace:" << std::endl;
- ll_get_stack_trace(lines);
+ ll_get_stack_trace(lines);
- for(size_t i = 0; i < lines.size(); ++i)
- {
- gFailLog << lines[i] << std::endl;
- }
+ for(size_t i = 0; i < lines.size(); ++i)
+ {
+ gFailLog << lines[i] << std::endl;
+ }
- gFailLog << "End of Stack Trace." << std::endl << std::endl;
+ gFailLog << "End of Stack Trace." << std::endl << std::endl;
- gFailLog.flush();
- }
+ gFailLog.flush();
+ }
};
void ll_close_fail_log()
{
- gFailLog.close();
+ gFailLog.close();
}
LLMatrix4 gGLObliqueProjectionInverse;
@@ -979,30 +979,30 @@ PFNGLPOLYGONOFFSETCLAMPPROC glPolygonOffsetClamp = nullptr;
LLGLManager gGLManager;
LLGLManager::LLGLManager() :
- mInited(FALSE),
- mIsDisabled(FALSE),
- mMaxSamples(0),
- mNumTextureImageUnits(1),
- mMaxSampleMaskWords(0),
- mMaxColorTextureSamples(0),
- mMaxDepthTextureSamples(0),
- mMaxIntegerSamples(0),
- mIsAMD(FALSE),
- mIsNVIDIA(FALSE),
- mIsIntel(FALSE),
+ mInited(FALSE),
+ mIsDisabled(FALSE),
+ mMaxSamples(0),
+ mNumTextureImageUnits(1),
+ mMaxSampleMaskWords(0),
+ mMaxColorTextureSamples(0),
+ mMaxDepthTextureSamples(0),
+ mMaxIntegerSamples(0),
+ mIsAMD(FALSE),
+ mIsNVIDIA(FALSE),
+ mIsIntel(FALSE),
#if LL_DARWIN
- mIsMobileGF(FALSE),
+ mIsMobileGF(FALSE),
#endif
- mHasRequirements(TRUE),
- mDriverVersionMajor(1),
- mDriverVersionMinor(0),
- mDriverVersionRelease(0),
- mGLVersion(1.0f),
- mGLSLVersionMajor(0),
- mGLSLVersionMinor(0),
- mVRAM(0),
- mGLMaxVertexRange(0),
- mGLMaxIndexRange(0)
+ mHasRequirements(TRUE),
+ mDriverVersionMajor(1),
+ mDriverVersionMinor(0),
+ mDriverVersionRelease(0),
+ mGLVersion(1.0f),
+ mGLSLVersionMajor(0),
+ mGLSLVersionMinor(0),
+ mVRAM(0),
+ mGLMaxVertexRange(0),
+ mGLMaxIndexRange(0)
{
}
@@ -1012,227 +1012,227 @@ LLGLManager::LLGLManager() :
void LLGLManager::initWGL()
{
#if LL_WINDOWS && !LL_MESA_HEADLESS
- if (!glh_init_extensions("WGL_ARB_pixel_format"))
- {
- LL_WARNS("RenderInit") << "No ARB pixel format extensions" << LL_ENDL;
- }
-
- if (ExtensionExists("WGL_ARB_create_context",gGLHExts.mSysExts))
- {
- GLH_EXT_NAME(wglCreateContextAttribsARB) = (PFNWGLCREATECONTEXTATTRIBSARBPROC)GLH_EXT_GET_PROC_ADDRESS("wglCreateContextAttribsARB");
- }
- else
- {
- LL_WARNS("RenderInit") << "No ARB create context extensions" << LL_ENDL;
- }
-
- // For retreiving information per AMD adapter,
- // because we can't trust curently selected/default one when there are multiple
- mHasAMDAssociations = ExtensionExists("WGL_AMD_gpu_association", gGLHExts.mSysExts);
- if (mHasAMDAssociations)
- {
- GLH_EXT_NAME(wglGetGPUIDsAMD) = (PFNWGLGETGPUIDSAMDPROC)GLH_EXT_GET_PROC_ADDRESS("wglGetGPUIDsAMD");
- GLH_EXT_NAME(wglGetGPUInfoAMD) = (PFNWGLGETGPUINFOAMDPROC)GLH_EXT_GET_PROC_ADDRESS("wglGetGPUInfoAMD");
- }
-
- if (ExtensionExists("WGL_EXT_swap_control", gGLHExts.mSysExts))
- {
+ if (!glh_init_extensions("WGL_ARB_pixel_format"))
+ {
+ LL_WARNS("RenderInit") << "No ARB pixel format extensions" << LL_ENDL;
+ }
+
+ if (ExtensionExists("WGL_ARB_create_context",gGLHExts.mSysExts))
+ {
+ GLH_EXT_NAME(wglCreateContextAttribsARB) = (PFNWGLCREATECONTEXTATTRIBSARBPROC)GLH_EXT_GET_PROC_ADDRESS("wglCreateContextAttribsARB");
+ }
+ else
+ {
+ LL_WARNS("RenderInit") << "No ARB create context extensions" << LL_ENDL;
+ }
+
+ // For retreiving information per AMD adapter,
+ // because we can't trust curently selected/default one when there are multiple
+ mHasAMDAssociations = ExtensionExists("WGL_AMD_gpu_association", gGLHExts.mSysExts);
+ if (mHasAMDAssociations)
+ {
+ GLH_EXT_NAME(wglGetGPUIDsAMD) = (PFNWGLGETGPUIDSAMDPROC)GLH_EXT_GET_PROC_ADDRESS("wglGetGPUIDsAMD");
+ GLH_EXT_NAME(wglGetGPUInfoAMD) = (PFNWGLGETGPUINFOAMDPROC)GLH_EXT_GET_PROC_ADDRESS("wglGetGPUInfoAMD");
+ }
+
+ if (ExtensionExists("WGL_EXT_swap_control", gGLHExts.mSysExts))
+ {
GLH_EXT_NAME(wglSwapIntervalEXT) = (PFNWGLSWAPINTERVALEXTPROC)GLH_EXT_GET_PROC_ADDRESS("wglSwapIntervalEXT");
- }
+ }
- if( !glh_init_extensions("WGL_ARB_pbuffer") )
- {
- LL_WARNS("RenderInit") << "No ARB WGL PBuffer extensions" << LL_ENDL;
- }
+ if( !glh_init_extensions("WGL_ARB_pbuffer") )
+ {
+ LL_WARNS("RenderInit") << "No ARB WGL PBuffer extensions" << LL_ENDL;
+ }
- if( !glh_init_extensions("WGL_ARB_render_texture") )
- {
- LL_WARNS("RenderInit") << "No ARB WGL render texture extensions" << LL_ENDL;
- }
+ if( !glh_init_extensions("WGL_ARB_render_texture") )
+ {
+ LL_WARNS("RenderInit") << "No ARB WGL render texture extensions" << LL_ENDL;
+ }
#endif
}
// return false if unable (or unwilling due to old drivers) to init GL
bool LLGLManager::initGL()
{
- if (mInited)
- {
- LL_ERRS("RenderInit") << "Calling init on LLGLManager after already initialized!" << LL_ENDL;
- }
+ if (mInited)
+ {
+ LL_ERRS("RenderInit") << "Calling init on LLGLManager after already initialized!" << LL_ENDL;
+ }
#if 0 && LL_WINDOWS
- if (!glGetStringi)
- {
- glGetStringi = (PFNGLGETSTRINGIPROC) GLH_EXT_GET_PROC_ADDRESS("glGetStringi");
- }
-
- //reload extensions string (may have changed after using wglCreateContextAttrib)
- if (glGetStringi)
- {
- std::stringstream str;
-
- GLint count = 0;
- glGetIntegerv(GL_NUM_EXTENSIONS, &count);
- for (GLint i = 0; i < count; ++i)
- {
- std::string ext = ll_safe_string((const char*) glGetStringi(GL_EXTENSIONS, i));
- str << ext << " ";
- LL_DEBUGS("GLExtensions") << ext << LL_ENDL;
- }
-
- {
- PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetExtensionsStringARB = 0;
- wglGetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC)wglGetProcAddress("wglGetExtensionsStringARB");
- if(wglGetExtensionsStringARB)
- {
- str << (const char*) wglGetExtensionsStringARB(wglGetCurrentDC());
- }
- }
-
- free(gGLHExts.mSysExts);
- std::string extensions = str.str();
- gGLHExts.mSysExts = strdup(extensions.c_str());
- }
+ if (!glGetStringi)
+ {
+ glGetStringi = (PFNGLGETSTRINGIPROC) GLH_EXT_GET_PROC_ADDRESS("glGetStringi");
+ }
+
+ //reload extensions string (may have changed after using wglCreateContextAttrib)
+ if (glGetStringi)
+ {
+ std::stringstream str;
+
+ GLint count = 0;
+ glGetIntegerv(GL_NUM_EXTENSIONS, &count);
+ for (GLint i = 0; i < count; ++i)
+ {
+ std::string ext = ll_safe_string((const char*) glGetStringi(GL_EXTENSIONS, i));
+ str << ext << " ";
+ LL_DEBUGS("GLExtensions") << ext << LL_ENDL;
+ }
+
+ {
+ PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetExtensionsStringARB = 0;
+ wglGetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC)wglGetProcAddress("wglGetExtensionsStringARB");
+ if(wglGetExtensionsStringARB)
+ {
+ str << (const char*) wglGetExtensionsStringARB(wglGetCurrentDC());
+ }
+ }
+
+ free(gGLHExts.mSysExts);
+ std::string extensions = str.str();
+ gGLHExts.mSysExts = strdup(extensions.c_str());
+ }
#endif
- // Extract video card strings and convert to upper case to
- // work around driver-to-driver variation in capitalization.
- mGLVendor = ll_safe_string((const char *)glGetString(GL_VENDOR));
- LLStringUtil::toUpper(mGLVendor);
+ // Extract video card strings and convert to upper case to
+ // work around driver-to-driver variation in capitalization.
+ mGLVendor = ll_safe_string((const char *)glGetString(GL_VENDOR));
+ LLStringUtil::toUpper(mGLVendor);
- mGLRenderer = ll_safe_string((const char *)glGetString(GL_RENDERER));
- LLStringUtil::toUpper(mGLRenderer);
+ mGLRenderer = ll_safe_string((const char *)glGetString(GL_RENDERER));
+ LLStringUtil::toUpper(mGLRenderer);
- parse_gl_version( &mDriverVersionMajor,
- &mDriverVersionMinor,
- &mDriverVersionRelease,
- &mDriverVersionVendorString,
- &mGLVersionString);
+ parse_gl_version( &mDriverVersionMajor,
+ &mDriverVersionMinor,
+ &mDriverVersionRelease,
+ &mDriverVersionVendorString,
+ &mGLVersionString);
- mGLVersion = mDriverVersionMajor + mDriverVersionMinor * .1f;
+ mGLVersion = mDriverVersionMajor + mDriverVersionMinor * .1f;
- if (mGLVersion >= 2.f)
- {
- parse_glsl_version(mGLSLVersionMajor, mGLSLVersionMinor);
+ if (mGLVersion >= 2.f)
+ {
+ parse_glsl_version(mGLSLVersionMajor, mGLSLVersionMinor);
#if 0 && LL_DARWIN
- // TODO maybe switch to using a core profile for GL 3.2?
- // https://stackoverflow.com/a/19868861
- //never use GLSL greater than 1.20 on OSX
- if (mGLSLVersionMajor > 1 || mGLSLVersionMinor > 30)
- {
- mGLSLVersionMajor = 1;
- mGLSLVersionMinor = 30;
- }
+ // TODO maybe switch to using a core profile for GL 3.2?
+ // https://stackoverflow.com/a/19868861
+ //never use GLSL greater than 1.20 on OSX
+ if (mGLSLVersionMajor > 1 || mGLSLVersionMinor > 30)
+ {
+ mGLSLVersionMajor = 1;
+ mGLSLVersionMinor = 30;
+ }
#endif
- }
-
- if (mGLVersion >= 2.1f && LLImageGL::sCompressTextures)
- { //use texture compression
- glHint(GL_TEXTURE_COMPRESSION_HINT, GL_NICEST);
- }
- else
- { //GL version is < 3.0, always disable texture compression
- LLImageGL::sCompressTextures = false;
- }
-
- // Trailing space necessary to keep "nVidia Corpor_ati_on" cards
- // from being recognized as ATI.
+ }
+
+ if (mGLVersion >= 2.1f && LLImageGL::sCompressTextures)
+ { //use texture compression
+ glHint(GL_TEXTURE_COMPRESSION_HINT, GL_NICEST);
+ }
+ else
+ { //GL version is < 3.0, always disable texture compression
+ LLImageGL::sCompressTextures = false;
+ }
+
+ // Trailing space necessary to keep "nVidia Corpor_ati_on" cards
+ // from being recognized as ATI.
// NOTE: AMD has been pretty good about not breaking this check, do not rename without good reason
- if (mGLVendor.substr(0,4) == "ATI ")
- {
- mGLVendorShort = "AMD";
- // *TODO: Fix this?
- mIsAMD = TRUE;
- }
- else if (mGLVendor.find("NVIDIA ") != std::string::npos)
- {
- mGLVendorShort = "NVIDIA";
- mIsNVIDIA = TRUE;
- }
- else if (mGLVendor.find("INTEL") != std::string::npos
+ if (mGLVendor.substr(0,4) == "ATI ")
+ {
+ mGLVendorShort = "AMD";
+ // *TODO: Fix this?
+ mIsAMD = TRUE;
+ }
+ else if (mGLVendor.find("NVIDIA ") != std::string::npos)
+ {
+ mGLVendorShort = "NVIDIA";
+ mIsNVIDIA = TRUE;
+ }
+ else if (mGLVendor.find("INTEL") != std::string::npos
#if LL_LINUX
- // The Mesa-based drivers put this in the Renderer string,
- // not the Vendor string.
- || mGLRenderer.find("INTEL") != std::string::npos
+ // The Mesa-based drivers put this in the Renderer string,
+ // not the Vendor string.
+ || mGLRenderer.find("INTEL") != std::string::npos
#endif //LL_LINUX
- )
- {
- mGLVendorShort = "INTEL";
- mIsIntel = TRUE;
- }
- else
- {
- mGLVendorShort = "MISC";
- }
-
- // This is called here because it depends on the setting of mIsGF2or4MX, and sets up mHasMultitexture.
- initExtensions();
-
- S32 old_vram = mVRAM;
- mVRAM = 0;
+ )
+ {
+ mGLVendorShort = "INTEL";
+ mIsIntel = TRUE;
+ }
+ else
+ {
+ mGLVendorShort = "MISC";
+ }
+
+ // This is called here because it depends on the setting of mIsGF2or4MX, and sets up mHasMultitexture.
+ initExtensions();
+
+ S32 old_vram = mVRAM;
+ mVRAM = 0;
#if LL_WINDOWS
- if (mHasAMDAssociations)
- {
- GLuint gl_gpus_count = wglGetGPUIDsAMD(0, 0);
- if (gl_gpus_count > 0)
- {
- GLuint* ids = new GLuint[gl_gpus_count];
- wglGetGPUIDsAMD(gl_gpus_count, ids);
-
- GLuint mem_mb = 0;
- for (U32 i = 0; i < gl_gpus_count; i++)
- {
- wglGetGPUInfoAMD(ids[i],
- WGL_GPU_RAM_AMD,
- GL_UNSIGNED_INT,
- sizeof(GLuint),
- &mem_mb);
- if (mVRAM < mem_mb)
- {
- // basically pick the best AMD and trust driver/OS to know to switch
- mVRAM = mem_mb;
- }
- }
- }
- if (mVRAM != 0)
- {
- LL_WARNS("RenderInit") << "VRAM Detected (AMDAssociations):" << mVRAM << LL_ENDL;
- }
- }
+ if (mHasAMDAssociations)
+ {
+ GLuint gl_gpus_count = wglGetGPUIDsAMD(0, 0);
+ if (gl_gpus_count > 0)
+ {
+ GLuint* ids = new GLuint[gl_gpus_count];
+ wglGetGPUIDsAMD(gl_gpus_count, ids);
+
+ GLuint mem_mb = 0;
+ for (U32 i = 0; i < gl_gpus_count; i++)
+ {
+ wglGetGPUInfoAMD(ids[i],
+ WGL_GPU_RAM_AMD,
+ GL_UNSIGNED_INT,
+ sizeof(GLuint),
+ &mem_mb);
+ if (mVRAM < mem_mb)
+ {
+ // basically pick the best AMD and trust driver/OS to know to switch
+ mVRAM = mem_mb;
+ }
+ }
+ }
+ if (mVRAM != 0)
+ {
+ LL_WARNS("RenderInit") << "VRAM Detected (AMDAssociations):" << mVRAM << LL_ENDL;
+ }
+ }
#endif
#if LL_WINDOWS
- if (mVRAM < 256)
- {
- // Something likely went wrong using the above extensions
- // try WMI first and fall back to old method (from dxdiag) if all else fails
- // Function will check all GPUs WMI knows of and will pick up the one with most
- // memory. We need to check all GPUs because system can switch active GPU to
- // weaker one, to preserve power when not under load.
- S32 mem = LLDXHardware::getMBVideoMemoryViaWMI();
- if (mem != 0)
- {
- mVRAM = mem;
- LL_WARNS("RenderInit") << "VRAM Detected (WMI):" << mVRAM<< LL_ENDL;
- }
- }
+ if (mVRAM < 256)
+ {
+ // Something likely went wrong using the above extensions
+ // try WMI first and fall back to old method (from dxdiag) if all else fails
+ // Function will check all GPUs WMI knows of and will pick up the one with most
+ // memory. We need to check all GPUs because system can switch active GPU to
+ // weaker one, to preserve power when not under load.
+ S32 mem = LLDXHardware::getMBVideoMemoryViaWMI();
+ if (mem != 0)
+ {
+ mVRAM = mem;
+ LL_WARNS("RenderInit") << "VRAM Detected (WMI):" << mVRAM<< LL_ENDL;
+ }
+ }
#endif
- if (mVRAM < 256 && old_vram > 0)
- {
- // fall back to old method
- // Note: on Windows value will be from LLDXHardware.
- // Either received via dxdiag or via WMI by id from dxdiag.
- mVRAM = old_vram;
- }
-
- glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &mNumTextureImageUnits);
- glGetIntegerv(GL_MAX_COLOR_TEXTURE_SAMPLES, &mMaxColorTextureSamples);
- glGetIntegerv(GL_MAX_DEPTH_TEXTURE_SAMPLES, &mMaxDepthTextureSamples);
- glGetIntegerv(GL_MAX_INTEGER_SAMPLES, &mMaxIntegerSamples);
- glGetIntegerv(GL_MAX_SAMPLE_MASK_WORDS, &mMaxSampleMaskWords);
+ if (mVRAM < 256 && old_vram > 0)
+ {
+ // fall back to old method
+ // Note: on Windows value will be from LLDXHardware.
+ // Either received via dxdiag or via WMI by id from dxdiag.
+ mVRAM = old_vram;
+ }
+
+ glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &mNumTextureImageUnits);
+ glGetIntegerv(GL_MAX_COLOR_TEXTURE_SAMPLES, &mMaxColorTextureSamples);
+ glGetIntegerv(GL_MAX_DEPTH_TEXTURE_SAMPLES, &mMaxDepthTextureSamples);
+ glGetIntegerv(GL_MAX_INTEGER_SAMPLES, &mMaxIntegerSamples);
+ glGetIntegerv(GL_MAX_SAMPLE_MASK_WORDS, &mMaxSampleMaskWords);
glGetIntegerv(GL_MAX_SAMPLES, &mMaxSamples);
if (mGLVersion >= 4.59f)
@@ -1240,136 +1240,136 @@ bool LLGLManager::initGL()
glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY, &mMaxAnisotropy);
}
- initGLStates();
+ initGLStates();
- return true;
+ return true;
}
void LLGLManager::getGLInfo(LLSD& info)
{
- if (gHeadlessClient)
- {
- info["GLInfo"]["GLVendor"] = HEADLESS_VENDOR_STRING;
- info["GLInfo"]["GLRenderer"] = HEADLESS_RENDERER_STRING;
- info["GLInfo"]["GLVersion"] = HEADLESS_VERSION_STRING;
- return;
- }
- else
- {
- info["GLInfo"]["GLVendor"] = ll_safe_string((const char *)glGetString(GL_VENDOR));
- info["GLInfo"]["GLRenderer"] = ll_safe_string((const char *)glGetString(GL_RENDERER));
- info["GLInfo"]["GLVersion"] = ll_safe_string((const char *)glGetString(GL_VERSION));
- }
+ if (gHeadlessClient)
+ {
+ info["GLInfo"]["GLVendor"] = HEADLESS_VENDOR_STRING;
+ info["GLInfo"]["GLRenderer"] = HEADLESS_RENDERER_STRING;
+ info["GLInfo"]["GLVersion"] = HEADLESS_VERSION_STRING;
+ return;
+ }
+ else
+ {
+ info["GLInfo"]["GLVendor"] = ll_safe_string((const char *)glGetString(GL_VENDOR));
+ info["GLInfo"]["GLRenderer"] = ll_safe_string((const char *)glGetString(GL_RENDERER));
+ info["GLInfo"]["GLVersion"] = ll_safe_string((const char *)glGetString(GL_VERSION));
+ }
#if !LL_MESA_HEADLESS
- std::string all_exts = ll_safe_string((const char *)gGLHExts.mSysExts);
- boost::char_separator<char> sep(" ");
- boost::tokenizer<boost::char_separator<char> > tok(all_exts, sep);
- for(boost::tokenizer<boost::char_separator<char> >::iterator i = tok.begin(); i != tok.end(); ++i)
- {
- info["GLInfo"]["GLExtensions"].append(*i);
- }
+ std::string all_exts = ll_safe_string((const char *)gGLHExts.mSysExts);
+ boost::char_separator<char> sep(" ");
+ boost::tokenizer<boost::char_separator<char> > tok(all_exts, sep);
+ for(boost::tokenizer<boost::char_separator<char> >::iterator i = tok.begin(); i != tok.end(); ++i)
+ {
+ info["GLInfo"]["GLExtensions"].append(*i);
+ }
#endif
}
std::string LLGLManager::getGLInfoString()
{
- std::string info_str;
-
- if (gHeadlessClient)
- {
- info_str += std::string("GL_VENDOR ") + HEADLESS_VENDOR_STRING + std::string("\n");
- info_str += std::string("GL_RENDERER ") + HEADLESS_RENDERER_STRING + std::string("\n");
- info_str += std::string("GL_VERSION ") + HEADLESS_VERSION_STRING + std::string("\n");
- }
- else
- {
- info_str += std::string("GL_VENDOR ") + ll_safe_string((const char *)glGetString(GL_VENDOR)) + std::string("\n");
- info_str += std::string("GL_RENDERER ") + ll_safe_string((const char *)glGetString(GL_RENDERER)) + std::string("\n");
- info_str += std::string("GL_VERSION ") + ll_safe_string((const char *)glGetString(GL_VERSION)) + std::string("\n");
- }
+ std::string info_str;
+
+ if (gHeadlessClient)
+ {
+ info_str += std::string("GL_VENDOR ") + HEADLESS_VENDOR_STRING + std::string("\n");
+ info_str += std::string("GL_RENDERER ") + HEADLESS_RENDERER_STRING + std::string("\n");
+ info_str += std::string("GL_VERSION ") + HEADLESS_VERSION_STRING + std::string("\n");
+ }
+ else
+ {
+ info_str += std::string("GL_VENDOR ") + ll_safe_string((const char *)glGetString(GL_VENDOR)) + std::string("\n");
+ info_str += std::string("GL_RENDERER ") + ll_safe_string((const char *)glGetString(GL_RENDERER)) + std::string("\n");
+ info_str += std::string("GL_VERSION ") + ll_safe_string((const char *)glGetString(GL_VERSION)) + std::string("\n");
+ }
#if !LL_MESA_HEADLESS
- std::string all_exts= ll_safe_string(((const char *)gGLHExts.mSysExts));
- LLStringUtil::replaceChar(all_exts, ' ', '\n');
- info_str += std::string("GL_EXTENSIONS:\n") + all_exts + std::string("\n");
+ std::string all_exts= ll_safe_string(((const char *)gGLHExts.mSysExts));
+ LLStringUtil::replaceChar(all_exts, ' ', '\n');
+ info_str += std::string("GL_EXTENSIONS:\n") + all_exts + std::string("\n");
#endif
- return info_str;
+ return info_str;
}
void LLGLManager::printGLInfoString()
{
- if (gHeadlessClient)
- {
- LL_INFOS("RenderInit") << "GL_VENDOR: " << HEADLESS_VENDOR_STRING << LL_ENDL;
- LL_INFOS("RenderInit") << "GL_RENDERER: " << HEADLESS_RENDERER_STRING << LL_ENDL;
- LL_INFOS("RenderInit") << "GL_VERSION: " << HEADLESS_VERSION_STRING << LL_ENDL;
- }
- else
- {
- LL_INFOS("RenderInit") << "GL_VENDOR: " << ll_safe_string((const char *)glGetString(GL_VENDOR)) << LL_ENDL;
- LL_INFOS("RenderInit") << "GL_RENDERER: " << ll_safe_string((const char *)glGetString(GL_RENDERER)) << LL_ENDL;
- LL_INFOS("RenderInit") << "GL_VERSION: " << ll_safe_string((const char *)glGetString(GL_VERSION)) << LL_ENDL;
- }
+ if (gHeadlessClient)
+ {
+ LL_INFOS("RenderInit") << "GL_VENDOR: " << HEADLESS_VENDOR_STRING << LL_ENDL;
+ LL_INFOS("RenderInit") << "GL_RENDERER: " << HEADLESS_RENDERER_STRING << LL_ENDL;
+ LL_INFOS("RenderInit") << "GL_VERSION: " << HEADLESS_VERSION_STRING << LL_ENDL;
+ }
+ else
+ {
+ LL_INFOS("RenderInit") << "GL_VENDOR: " << ll_safe_string((const char *)glGetString(GL_VENDOR)) << LL_ENDL;
+ LL_INFOS("RenderInit") << "GL_RENDERER: " << ll_safe_string((const char *)glGetString(GL_RENDERER)) << LL_ENDL;
+ LL_INFOS("RenderInit") << "GL_VERSION: " << ll_safe_string((const char *)glGetString(GL_VERSION)) << LL_ENDL;
+ }
#if !LL_MESA_HEADLESS
- std::string all_exts= ll_safe_string(((const char *)gGLHExts.mSysExts));
- LLStringUtil::replaceChar(all_exts, ' ', '\n');
- LL_DEBUGS("RenderInit") << "GL_EXTENSIONS:\n" << all_exts << LL_ENDL;
+ std::string all_exts= ll_safe_string(((const char *)gGLHExts.mSysExts));
+ LLStringUtil::replaceChar(all_exts, ' ', '\n');
+ LL_DEBUGS("RenderInit") << "GL_EXTENSIONS:\n" << all_exts << LL_ENDL;
#endif
}
std::string LLGLManager::getRawGLString()
{
- std::string gl_string;
- if (gHeadlessClient)
- {
- gl_string = HEADLESS_VENDOR_STRING + " " + HEADLESS_RENDERER_STRING;
- }
- else
- {
- gl_string = ll_safe_string((char*)glGetString(GL_VENDOR)) + " " + ll_safe_string((char*)glGetString(GL_RENDERER));
- }
- return gl_string;
+ std::string gl_string;
+ if (gHeadlessClient)
+ {
+ gl_string = HEADLESS_VENDOR_STRING + " " + HEADLESS_RENDERER_STRING;
+ }
+ else
+ {
+ gl_string = ll_safe_string((char*)glGetString(GL_VENDOR)) + " " + ll_safe_string((char*)glGetString(GL_RENDERER));
+ }
+ return gl_string;
}
void LLGLManager::asLLSD(LLSD& info)
{
- // Currently these are duplicates of fields in "system".
- info["gpu_vendor"] = mGLVendorShort;
- info["gpu_version"] = mDriverVersionVendorString;
- info["opengl_version"] = mGLVersionString;
-
- info["vram"] = mVRAM;
-
- // OpenGL limits
- info["max_samples"] = mMaxSamples;
- info["num_texture_image_units"] = mNumTextureImageUnits;
- info["max_sample_mask_words"] = mMaxSampleMaskWords;
- info["max_color_texture_samples"] = mMaxColorTextureSamples;
- info["max_depth_texture_samples"] = mMaxDepthTextureSamples;
- info["max_integer_samples"] = mMaxIntegerSamples;
+ // Currently these are duplicates of fields in "system".
+ info["gpu_vendor"] = mGLVendorShort;
+ info["gpu_version"] = mDriverVersionVendorString;
+ info["opengl_version"] = mGLVersionString;
+
+ info["vram"] = mVRAM;
+
+ // OpenGL limits
+ info["max_samples"] = mMaxSamples;
+ info["num_texture_image_units"] = mNumTextureImageUnits;
+ info["max_sample_mask_words"] = mMaxSampleMaskWords;
+ info["max_color_texture_samples"] = mMaxColorTextureSamples;
+ info["max_depth_texture_samples"] = mMaxDepthTextureSamples;
+ info["max_integer_samples"] = mMaxIntegerSamples;
info["max_vertex_range"] = mGLMaxVertexRange;
info["max_index_range"] = mGLMaxIndexRange;
info["max_texture_size"] = mGLMaxTextureSize;
- // Which vendor
- info["is_ati"] = mIsAMD; // note, do not rename is_ati to is_amd without coordinating with DW
- info["is_nvidia"] = mIsNVIDIA;
- info["is_intel"] = mIsIntel;
+ // Which vendor
+ info["is_ati"] = mIsAMD; // note, do not rename is_ati to is_amd without coordinating with DW
+ info["is_nvidia"] = mIsNVIDIA;
+ info["is_intel"] = mIsIntel;
- info["gl_renderer"] = mGLRenderer;
+ info["gl_renderer"] = mGLRenderer;
}
void LLGLManager::shutdownGL()
{
- if (mInited)
- {
- glFinish();
- stop_glerror();
- mInited = FALSE;
- }
+ if (mInited)
+ {
+ glFinish();
+ stop_glerror();
+ mInited = FALSE;
+ }
}
// these are used to turn software blending on. They appear in the Debug/Avatar menu
@@ -1378,7 +1378,7 @@ void LLGLManager::shutdownGL()
void LLGLManager::initExtensions()
{
#if LL_LINUX
- glh_init_extensions("");
+ glh_init_extensions("");
#endif
#if LL_DARWIN
GLint num_extensions = 0;
@@ -1404,14 +1404,14 @@ void LLGLManager::initExtensions()
mHasDebugOutput = mGLVersion >= 4.29f;
// Misc
- glGetIntegerv(GL_MAX_ELEMENTS_VERTICES, (GLint*) &mGLMaxVertexRange);
- glGetIntegerv(GL_MAX_ELEMENTS_INDICES, (GLint*) &mGLMaxIndexRange);
- glGetIntegerv(GL_MAX_TEXTURE_SIZE, (GLint*) &mGLMaxTextureSize);
+ glGetIntegerv(GL_MAX_ELEMENTS_VERTICES, (GLint*) &mGLMaxVertexRange);
+ glGetIntegerv(GL_MAX_ELEMENTS_INDICES, (GLint*) &mGLMaxIndexRange);
+ glGetIntegerv(GL_MAX_TEXTURE_SIZE, (GLint*) &mGLMaxTextureSize);
mInited = TRUE;
#if LL_WINDOWS
- LL_DEBUGS("RenderInit") << "GL Probe: Getting symbols" << LL_ENDL;
+ LL_DEBUGS("RenderInit") << "GL Probe: Getting symbols" << LL_ENDL;
// WGL_AMD_gpu_association
wglGetGPUIDsAMD = (PFNWGLGETGPUIDSAMDPROC)GLH_EXT_GET_PROC_ADDRESS("wglGetGPUIDsAMD");
@@ -2251,117 +2251,117 @@ void LLGLManager::initExtensions()
void rotate_quat(LLQuaternion& rotation)
{
- F32 angle_radians, x, y, z;
- rotation.getAngleAxis(&angle_radians, &x, &y, &z);
- gGL.rotatef(angle_radians * RAD_TO_DEG, x, y, z);
+ F32 angle_radians, x, y, z;
+ rotation.getAngleAxis(&angle_radians, &x, &y, &z);
+ gGL.rotatef(angle_radians * RAD_TO_DEG, x, y, z);
}
void flush_glerror()
{
- glGetError();
+ glGetError();
}
//this function outputs gl error to the log file, does not crash the code.
void log_glerror()
{
- if (LL_UNLIKELY(!gGLManager.mInited))
- {
- return ;
- }
- // Create or update texture to be used with this data
- GLenum error;
- error = glGetError();
- while (LL_UNLIKELY(error))
- {
- GLubyte const * gl_error_msg = gluErrorString(error);
- if (NULL != gl_error_msg)
- {
- LL_WARNS() << "GL Error: " << error << " GL Error String: " << gl_error_msg << LL_ENDL ;
- }
- else
- {
- // gluErrorString returns NULL for some extensions' error codes.
- // you'll probably have to grep for the number in glext.h.
- LL_WARNS() << "GL Error: UNKNOWN 0x" << std::hex << error << std::dec << LL_ENDL;
- }
- error = glGetError();
- }
+ if (LL_UNLIKELY(!gGLManager.mInited))
+ {
+ return ;
+ }
+ // Create or update texture to be used with this data
+ GLenum error;
+ error = glGetError();
+ while (LL_UNLIKELY(error))
+ {
+ GLubyte const * gl_error_msg = gluErrorString(error);
+ if (NULL != gl_error_msg)
+ {
+ LL_WARNS() << "GL Error: " << error << " GL Error String: " << gl_error_msg << LL_ENDL ;
+ }
+ else
+ {
+ // gluErrorString returns NULL for some extensions' error codes.
+ // you'll probably have to grep for the number in glext.h.
+ LL_WARNS() << "GL Error: UNKNOWN 0x" << std::hex << error << std::dec << LL_ENDL;
+ }
+ error = glGetError();
+ }
}
void do_assert_glerror()
{
- // Create or update texture to be used with this data
- GLenum error;
- error = glGetError();
- BOOL quit = FALSE;
- if (LL_UNLIKELY(error))
- {
- quit = TRUE;
- GLubyte const * gl_error_msg = gluErrorString(error);
- if (NULL != gl_error_msg)
- {
- LL_WARNS("RenderState") << "GL Error:" << error<< LL_ENDL;
- LL_WARNS("RenderState") << "GL Error String:" << gl_error_msg << LL_ENDL;
-
- if (gDebugSession)
- {
- gFailLog << "GL Error:" << gl_error_msg << std::endl;
- }
- }
- else
- {
- // gluErrorString returns NULL for some extensions' error codes.
- // you'll probably have to grep for the number in glext.h.
- LL_WARNS("RenderState") << "GL Error: UNKNOWN 0x" << std::hex << error << std::dec << LL_ENDL;
-
- if (gDebugSession)
- {
- gFailLog << "GL Error: UNKNOWN 0x" << std::hex << error << std::dec << std::endl;
- }
- }
- }
-
- if (quit)
- {
- if (gDebugSession)
- {
- ll_fail("assert_glerror failed");
- }
- else
- {
- LL_ERRS() << "One or more unhandled GL errors." << LL_ENDL;
- }
- }
+ // Create or update texture to be used with this data
+ GLenum error;
+ error = glGetError();
+ BOOL quit = FALSE;
+ if (LL_UNLIKELY(error))
+ {
+ quit = TRUE;
+ GLubyte const * gl_error_msg = gluErrorString(error);
+ if (NULL != gl_error_msg)
+ {
+ LL_WARNS("RenderState") << "GL Error:" << error<< LL_ENDL;
+ LL_WARNS("RenderState") << "GL Error String:" << gl_error_msg << LL_ENDL;
+
+ if (gDebugSession)
+ {
+ gFailLog << "GL Error:" << gl_error_msg << std::endl;
+ }
+ }
+ else
+ {
+ // gluErrorString returns NULL for some extensions' error codes.
+ // you'll probably have to grep for the number in glext.h.
+ LL_WARNS("RenderState") << "GL Error: UNKNOWN 0x" << std::hex << error << std::dec << LL_ENDL;
+
+ if (gDebugSession)
+ {
+ gFailLog << "GL Error: UNKNOWN 0x" << std::hex << error << std::dec << std::endl;
+ }
+ }
+ }
+
+ if (quit)
+ {
+ if (gDebugSession)
+ {
+ ll_fail("assert_glerror failed");
+ }
+ else
+ {
+ LL_ERRS() << "One or more unhandled GL errors." << LL_ENDL;
+ }
+ }
}
void assert_glerror()
{
-/* if (!gGLActive)
- {
- //LL_WARNS() << "GL used while not active!" << LL_ENDL;
-
- if (gDebugSession)
- {
- //ll_fail("GL used while not active");
- }
- }
+/* if (!gGLActive)
+ {
+ //LL_WARNS() << "GL used while not active!" << LL_ENDL;
+
+ if (gDebugSession)
+ {
+ //ll_fail("GL used while not active");
+ }
+ }
*/
- if (!gDebugGL)
- {
- //funny looking if for branch prediction -- gDebugGL is almost always false and assert_glerror is called often
- }
- else
- {
- do_assert_glerror();
- }
+ if (!gDebugGL)
+ {
+ //funny looking if for branch prediction -- gDebugGL is almost always false and assert_glerror is called often
+ }
+ else
+ {
+ do_assert_glerror();
+ }
}
void clear_glerror()
{
- glGetError();
- glGetError();
+ glGetError();
+ glGetError();
}
///////////////////////////////////////////////////////////////
@@ -2379,58 +2379,58 @@ GLboolean LLGLDepthTest::sWriteEnabled = GL_TRUE; // OpenGL default
//static
void LLGLState::initClass()
{
- sStateMap[GL_DITHER] = GL_TRUE;
- // sStateMap[GL_TEXTURE_2D] = GL_TRUE;
+ sStateMap[GL_DITHER] = GL_TRUE;
+ // sStateMap[GL_TEXTURE_2D] = GL_TRUE;
- //make sure multisample defaults to disabled
- sStateMap[GL_MULTISAMPLE] = GL_FALSE;
- glDisable(GL_MULTISAMPLE);
+ //make sure multisample defaults to disabled
+ sStateMap[GL_MULTISAMPLE] = GL_FALSE;
+ glDisable(GL_MULTISAMPLE);
}
//static
void LLGLState::restoreGL()
{
- sStateMap.clear();
- initClass();
+ sStateMap.clear();
+ initClass();
}
//static
// Really shouldn't be needed, but seems we sometimes do.
void LLGLState::resetTextureStates()
{
- gGL.flush();
- GLint maxTextureUnits;
-
- glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &maxTextureUnits);
- for (S32 j = maxTextureUnits-1; j >=0; j--)
- {
- gGL.getTexUnit(j)->activate();
- glClientActiveTexture(GL_TEXTURE0+j);
- j == 0 ? gGL.getTexUnit(j)->enable(LLTexUnit::TT_TEXTURE) : gGL.getTexUnit(j)->disable();
- }
+ gGL.flush();
+ GLint maxTextureUnits;
+
+ glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &maxTextureUnits);
+ for (S32 j = maxTextureUnits-1; j >=0; j--)
+ {
+ gGL.getTexUnit(j)->activate();
+ glClientActiveTexture(GL_TEXTURE0+j);
+ j == 0 ? gGL.getTexUnit(j)->enable(LLTexUnit::TT_TEXTURE) : gGL.getTexUnit(j)->disable();
+ }
}
void LLGLState::dumpStates()
{
- LL_INFOS("RenderState") << "GL States:" << LL_ENDL;
- for (boost::unordered_map<LLGLenum, LLGLboolean>::iterator iter = sStateMap.begin();
- iter != sStateMap.end(); ++iter)
- {
- LL_INFOS("RenderState") << llformat(" 0x%04x : %s",(S32)iter->first,iter->second?"TRUE":"FALSE") << LL_ENDL;
- }
+ LL_INFOS("RenderState") << "GL States:" << LL_ENDL;
+ for (boost::unordered_map<LLGLenum, LLGLboolean>::iterator iter = sStateMap.begin();
+ iter != sStateMap.end(); ++iter)
+ {
+ LL_INFOS("RenderState") << llformat(" 0x%04x : %s",(S32)iter->first,iter->second?"TRUE":"FALSE") << LL_ENDL;
+ }
}
void LLGLState::checkStates(GLboolean writeAlpha)
{
- if (!gDebugGL)
- {
- return;
- }
-
- GLint src;
- GLint dst;
- glGetIntegerv(GL_BLEND_SRC, &src);
- glGetIntegerv(GL_BLEND_DST, &dst);
+ if (!gDebugGL)
+ {
+ return;
+ }
+
+ GLint src;
+ GLint dst;
+ glGetIntegerv(GL_BLEND_SRC, &src);
+ glGetIntegerv(GL_BLEND_DST, &dst);
llassert_always(src == GL_SRC_ALPHA);
llassert_always(dst == GL_ONE_MINUS_SRC_ALPHA);
@@ -2442,269 +2442,269 @@ void LLGLState::checkStates(GLboolean writeAlpha)
//llassert_always(colorMask[2]);
// llassert_always(colorMask[3] == writeAlpha);
- for (boost::unordered_map<LLGLenum, LLGLboolean>::iterator iter = sStateMap.begin();
- iter != sStateMap.end(); ++iter)
- {
- LLGLenum state = iter->first;
- LLGLboolean cur_state = iter->second;
- LLGLboolean gl_state = glIsEnabled(state);
- if(cur_state != gl_state)
- {
- dumpStates();
- LL_GL_ERRS << llformat("LLGLState error. State: 0x%04x",state) << LL_ENDL;
- }
- }
+ for (boost::unordered_map<LLGLenum, LLGLboolean>::iterator iter = sStateMap.begin();
+ iter != sStateMap.end(); ++iter)
+ {
+ LLGLenum state = iter->first;
+ LLGLboolean cur_state = iter->second;
+ LLGLboolean gl_state = glIsEnabled(state);
+ if(cur_state != gl_state)
+ {
+ dumpStates();
+ LL_GL_ERRS << llformat("LLGLState error. State: 0x%04x",state) << LL_ENDL;
+ }
+ }
}
///////////////////////////////////////////////////////////////////////
LLGLState::LLGLState(LLGLenum state, S32 enabled) :
- mState(state), mWasEnabled(FALSE), mIsEnabled(FALSE)
+ mState(state), mWasEnabled(FALSE), mIsEnabled(FALSE)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE;
- if (mState)
- {
- mWasEnabled = sStateMap[state];
- setEnabled(enabled);
- }
+ if (mState)
+ {
+ mWasEnabled = sStateMap[state];
+ setEnabled(enabled);
+ }
}
void LLGLState::setEnabled(S32 enabled)
{
- if (!mState)
- {
- return;
- }
- if (enabled == CURRENT_STATE)
- {
- enabled = sStateMap[mState] == GL_TRUE ? TRUE : FALSE;
- }
- else if (enabled == TRUE && sStateMap[mState] != GL_TRUE)
- {
- gGL.flush();
- glEnable(mState);
- sStateMap[mState] = GL_TRUE;
- }
- else if (enabled == FALSE && sStateMap[mState] != GL_FALSE)
- {
- gGL.flush();
- glDisable(mState);
- sStateMap[mState] = GL_FALSE;
- }
- mIsEnabled = enabled;
+ if (!mState)
+ {
+ return;
+ }
+ if (enabled == CURRENT_STATE)
+ {
+ enabled = sStateMap[mState] == GL_TRUE ? TRUE : FALSE;
+ }
+ else if (enabled == TRUE && sStateMap[mState] != GL_TRUE)
+ {
+ gGL.flush();
+ glEnable(mState);
+ sStateMap[mState] = GL_TRUE;
+ }
+ else if (enabled == FALSE && sStateMap[mState] != GL_FALSE)
+ {
+ gGL.flush();
+ glDisable(mState);
+ sStateMap[mState] = GL_FALSE;
+ }
+ mIsEnabled = enabled;
}
LLGLState::~LLGLState()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE;
- if (mState)
- {
- if (gDebugGL)
- {
- if (!gDebugSession)
- {
- llassert_always(sStateMap[mState] == glIsEnabled(mState));
- }
- else
- {
- if (sStateMap[mState] != glIsEnabled(mState))
- {
- ll_fail("GL enabled state does not match expected");
- }
- }
- }
-
- if (mIsEnabled != mWasEnabled)
- {
- gGL.flush();
- if (mWasEnabled)
- {
- glEnable(mState);
- sStateMap[mState] = GL_TRUE;
- }
- else
- {
- glDisable(mState);
- sStateMap[mState] = GL_FALSE;
- }
- }
- }
+ if (mState)
+ {
+ if (gDebugGL)
+ {
+ if (!gDebugSession)
+ {
+ llassert_always(sStateMap[mState] == glIsEnabled(mState));
+ }
+ else
+ {
+ if (sStateMap[mState] != glIsEnabled(mState))
+ {
+ ll_fail("GL enabled state does not match expected");
+ }
+ }
+ }
+
+ if (mIsEnabled != mWasEnabled)
+ {
+ gGL.flush();
+ if (mWasEnabled)
+ {
+ glEnable(mState);
+ sStateMap[mState] = GL_TRUE;
+ }
+ else
+ {
+ glDisable(mState);
+ sStateMap[mState] = GL_FALSE;
+ }
+ }
+ }
}
////////////////////////////////////////////////////////////////////////////////
void LLGLManager::initGLStates()
{
- //gl states moved to classes in llglstates.h
- LLGLState::initClass();
+ //gl states moved to classes in llglstates.h
+ LLGLState::initClass();
}
////////////////////////////////////////////////////////////////////////////////
void parse_gl_version( S32* major, S32* minor, S32* release, std::string* vendor_specific, std::string* version_string )
{
- // GL_VERSION returns a null-terminated string with the format:
- // <major>.<minor>[.<release>] [<vendor specific>]
-
- const char* version = (const char*) glGetString(GL_VERSION);
- *major = 0;
- *minor = 0;
- *release = 0;
- vendor_specific->assign("");
-
- if( !version )
- {
- return;
- }
+ // GL_VERSION returns a null-terminated string with the format:
+ // <major>.<minor>[.<release>] [<vendor specific>]
+
+ const char* version = (const char*) glGetString(GL_VERSION);
+ *major = 0;
+ *minor = 0;
+ *release = 0;
+ vendor_specific->assign("");
+
+ if( !version )
+ {
+ return;
+ }
LL_INFOS() << "GL: " << version << LL_ENDL;
- version_string->assign(version);
-
- std::string ver_copy( version );
- S32 len = (S32)strlen( version ); /* Flawfinder: ignore */
- S32 i = 0;
- S32 start;
- // Find the major version
- start = i;
- for( ; i < len; i++ )
- {
- if( '.' == version[i] )
- {
- break;
- }
- }
- std::string major_str = ver_copy.substr(start,i-start);
- LLStringUtil::convertToS32(major_str, *major);
-
- if( '.' == version[i] )
- {
- i++;
- }
-
- // Find the minor version
- start = i;
- for( ; i < len; i++ )
- {
- if( ('.' == version[i]) || isspace(version[i]) )
- {
- break;
- }
- }
- std::string minor_str = ver_copy.substr(start,i-start);
- LLStringUtil::convertToS32(minor_str, *minor);
-
- // Find the release number (optional)
- if( '.' == version[i] )
- {
- i++;
-
- start = i;
- for( ; i < len; i++ )
- {
- if( isspace(version[i]) )
- {
- break;
- }
- }
-
- std::string release_str = ver_copy.substr(start,i-start);
- LLStringUtil::convertToS32(release_str, *release);
- }
-
- // Skip over any white space
- while( version[i] && isspace( version[i] ) )
- {
- i++;
- }
-
- // Copy the vendor-specific string (optional)
- if( version[i] )
- {
- vendor_specific->assign( version + i );
- }
+ version_string->assign(version);
+
+ std::string ver_copy( version );
+ S32 len = (S32)strlen( version ); /* Flawfinder: ignore */
+ S32 i = 0;
+ S32 start;
+ // Find the major version
+ start = i;
+ for( ; i < len; i++ )
+ {
+ if( '.' == version[i] )
+ {
+ break;
+ }
+ }
+ std::string major_str = ver_copy.substr(start,i-start);
+ LLStringUtil::convertToS32(major_str, *major);
+
+ if( '.' == version[i] )
+ {
+ i++;
+ }
+
+ // Find the minor version
+ start = i;
+ for( ; i < len; i++ )
+ {
+ if( ('.' == version[i]) || isspace(version[i]) )
+ {
+ break;
+ }
+ }
+ std::string minor_str = ver_copy.substr(start,i-start);
+ LLStringUtil::convertToS32(minor_str, *minor);
+
+ // Find the release number (optional)
+ if( '.' == version[i] )
+ {
+ i++;
+
+ start = i;
+ for( ; i < len; i++ )
+ {
+ if( isspace(version[i]) )
+ {
+ break;
+ }
+ }
+
+ std::string release_str = ver_copy.substr(start,i-start);
+ LLStringUtil::convertToS32(release_str, *release);
+ }
+
+ // Skip over any white space
+ while( version[i] && isspace( version[i] ) )
+ {
+ i++;
+ }
+
+ // Copy the vendor-specific string (optional)
+ if( version[i] )
+ {
+ vendor_specific->assign( version + i );
+ }
}
void parse_glsl_version(S32& major, S32& minor)
{
- // GL_SHADING_LANGUAGE_VERSION returns a null-terminated string with the format:
- // <major>.<minor>[.<release>] [<vendor specific>]
-
- const char* version = (const char*) glGetString(GL_SHADING_LANGUAGE_VERSION);
- major = 0;
- minor = 0;
-
- if( !version )
- {
- return;
- }
-
- std::string ver_copy( version );
- S32 len = (S32)strlen( version ); /* Flawfinder: ignore */
- S32 i = 0;
- S32 start;
- // Find the major version
- start = i;
- for( ; i < len; i++ )
- {
- if( '.' == version[i] )
- {
- break;
- }
- }
- std::string major_str = ver_copy.substr(start,i-start);
- LLStringUtil::convertToS32(major_str, major);
-
- if( '.' == version[i] )
- {
- i++;
- }
-
- // Find the minor version
- start = i;
- for( ; i < len; i++ )
- {
- if( ('.' == version[i]) || isspace(version[i]) )
- {
- break;
- }
- }
- std::string minor_str = ver_copy.substr(start,i-start);
- LLStringUtil::convertToS32(minor_str, minor);
+ // GL_SHADING_LANGUAGE_VERSION returns a null-terminated string with the format:
+ // <major>.<minor>[.<release>] [<vendor specific>]
+
+ const char* version = (const char*) glGetString(GL_SHADING_LANGUAGE_VERSION);
+ major = 0;
+ minor = 0;
+
+ if( !version )
+ {
+ return;
+ }
+
+ std::string ver_copy( version );
+ S32 len = (S32)strlen( version ); /* Flawfinder: ignore */
+ S32 i = 0;
+ S32 start;
+ // Find the major version
+ start = i;
+ for( ; i < len; i++ )
+ {
+ if( '.' == version[i] )
+ {
+ break;
+ }
+ }
+ std::string major_str = ver_copy.substr(start,i-start);
+ LLStringUtil::convertToS32(major_str, major);
+
+ if( '.' == version[i] )
+ {
+ i++;
+ }
+
+ // Find the minor version
+ start = i;
+ for( ; i < len; i++ )
+ {
+ if( ('.' == version[i]) || isspace(version[i]) )
+ {
+ break;
+ }
+ }
+ std::string minor_str = ver_copy.substr(start,i-start);
+ LLStringUtil::convertToS32(minor_str, minor);
}
LLGLUserClipPlane::LLGLUserClipPlane(const LLPlane& p, const glh::matrix4f& modelview, const glh::matrix4f& projection, bool apply)
{
- mApply = apply;
+ mApply = apply;
- if (mApply)
- {
- mModelview = modelview;
- mProjection = projection;
+ if (mApply)
+ {
+ mModelview = modelview;
+ mProjection = projection;
//flip incoming LLPlane to get consistent behavior compared to frustum culling
- setPlane(-p[0], -p[1], -p[2], -p[3]);
- }
+ setPlane(-p[0], -p[1], -p[2], -p[3]);
+ }
}
void LLGLUserClipPlane::disable()
{
if (mApply)
- {
- gGL.matrixMode(LLRender::MM_PROJECTION);
- gGL.popMatrix();
- gGL.matrixMode(LLRender::MM_MODELVIEW);
- }
+ {
+ gGL.matrixMode(LLRender::MM_PROJECTION);
+ gGL.popMatrix();
+ gGL.matrixMode(LLRender::MM_MODELVIEW);
+ }
mApply = false;
}
void LLGLUserClipPlane::setPlane(F32 a, F32 b, F32 c, F32 d)
{
- glh::matrix4f& P = mProjection;
- glh::matrix4f& M = mModelview;
+ glh::matrix4f& P = mProjection;
+ glh::matrix4f& M = mModelview;
- glh::matrix4f invtrans_MVP = (P * M).inverse().transpose();
+ glh::matrix4f invtrans_MVP = (P * M).inverse().transpose();
glh::vec4f oplane(a,b,c,d);
glh::vec4f cplane;
invtrans_MVP.mult_matrix_vec(oplane, cplane);
@@ -2719,100 +2719,100 @@ void LLGLUserClipPlane::setPlane(F32 a, F32 b, F32 c, F32 d)
suffix.set_row(2, cplane);
glh::matrix4f newP = suffix * P;
gGL.matrixMode(LLRender::MM_PROJECTION);
- gGL.pushMatrix();
+ gGL.pushMatrix();
gGL.loadMatrix(newP.m);
- gGLObliqueProjectionInverse = LLMatrix4(newP.inverse().transpose().m);
+ gGLObliqueProjectionInverse = LLMatrix4(newP.inverse().transpose().m);
gGL.matrixMode(LLRender::MM_MODELVIEW);
}
LLGLUserClipPlane::~LLGLUserClipPlane()
{
- disable();
+ disable();
}
LLGLDepthTest::LLGLDepthTest(GLboolean depth_enabled, GLboolean write_enabled, GLenum depth_func)
: mPrevDepthEnabled(sDepthEnabled), mPrevDepthFunc(sDepthFunc), mPrevWriteEnabled(sWriteEnabled)
{
- stop_glerror();
-
- checkState();
-
- if (!depth_enabled)
- { // always disable depth writes if depth testing is disabled
- // GL spec defines this as a requirement, but some implementations allow depth writes with testing disabled
- // The proper way to write to depth buffer with testing disabled is to enable testing and use a depth_func of GL_ALWAYS
- write_enabled = FALSE;
- }
-
- if (depth_enabled != sDepthEnabled)
- {
- gGL.flush();
- if (depth_enabled) glEnable(GL_DEPTH_TEST);
- else glDisable(GL_DEPTH_TEST);
- sDepthEnabled = depth_enabled;
- }
- if (depth_func != sDepthFunc)
- {
- gGL.flush();
- glDepthFunc(depth_func);
- sDepthFunc = depth_func;
- }
- if (write_enabled != sWriteEnabled)
- {
- gGL.flush();
- glDepthMask(write_enabled);
- sWriteEnabled = write_enabled;
- }
+ stop_glerror();
+
+ checkState();
+
+ if (!depth_enabled)
+ { // always disable depth writes if depth testing is disabled
+ // GL spec defines this as a requirement, but some implementations allow depth writes with testing disabled
+ // The proper way to write to depth buffer with testing disabled is to enable testing and use a depth_func of GL_ALWAYS
+ write_enabled = FALSE;
+ }
+
+ if (depth_enabled != sDepthEnabled)
+ {
+ gGL.flush();
+ if (depth_enabled) glEnable(GL_DEPTH_TEST);
+ else glDisable(GL_DEPTH_TEST);
+ sDepthEnabled = depth_enabled;
+ }
+ if (depth_func != sDepthFunc)
+ {
+ gGL.flush();
+ glDepthFunc(depth_func);
+ sDepthFunc = depth_func;
+ }
+ if (write_enabled != sWriteEnabled)
+ {
+ gGL.flush();
+ glDepthMask(write_enabled);
+ sWriteEnabled = write_enabled;
+ }
}
LLGLDepthTest::~LLGLDepthTest()
{
- checkState();
- if (sDepthEnabled != mPrevDepthEnabled )
- {
- gGL.flush();
- if (mPrevDepthEnabled) glEnable(GL_DEPTH_TEST);
- else glDisable(GL_DEPTH_TEST);
- sDepthEnabled = mPrevDepthEnabled;
- }
- if (sDepthFunc != mPrevDepthFunc)
- {
- gGL.flush();
- glDepthFunc(mPrevDepthFunc);
- sDepthFunc = mPrevDepthFunc;
- }
- if (sWriteEnabled != mPrevWriteEnabled )
- {
- gGL.flush();
- glDepthMask(mPrevWriteEnabled);
- sWriteEnabled = mPrevWriteEnabled;
- }
+ checkState();
+ if (sDepthEnabled != mPrevDepthEnabled )
+ {
+ gGL.flush();
+ if (mPrevDepthEnabled) glEnable(GL_DEPTH_TEST);
+ else glDisable(GL_DEPTH_TEST);
+ sDepthEnabled = mPrevDepthEnabled;
+ }
+ if (sDepthFunc != mPrevDepthFunc)
+ {
+ gGL.flush();
+ glDepthFunc(mPrevDepthFunc);
+ sDepthFunc = mPrevDepthFunc;
+ }
+ if (sWriteEnabled != mPrevWriteEnabled )
+ {
+ gGL.flush();
+ glDepthMask(mPrevWriteEnabled);
+ sWriteEnabled = mPrevWriteEnabled;
+ }
}
void LLGLDepthTest::checkState()
{
- if (gDebugGL)
- {
- GLint func = 0;
- GLboolean mask = FALSE;
-
- glGetIntegerv(GL_DEPTH_FUNC, &func);
- glGetBooleanv(GL_DEPTH_WRITEMASK, &mask);
-
- if (glIsEnabled(GL_DEPTH_TEST) != sDepthEnabled ||
- sWriteEnabled != mask ||
- sDepthFunc != func)
- {
- if (gDebugSession)
- {
- gFailLog << "Unexpected depth testing state." << std::endl;
- }
- else
- {
- LL_GL_ERRS << "Unexpected depth testing state." << LL_ENDL;
- }
- }
- }
+ if (gDebugGL)
+ {
+ GLint func = 0;
+ GLboolean mask = FALSE;
+
+ glGetIntegerv(GL_DEPTH_FUNC, &func);
+ glGetBooleanv(GL_DEPTH_WRITEMASK, &mask);
+
+ if (glIsEnabled(GL_DEPTH_TEST) != sDepthEnabled ||
+ sWriteEnabled != mask ||
+ sDepthFunc != func)
+ {
+ if (gDebugSession)
+ {
+ gFailLog << "Unexpected depth testing state." << std::endl;
+ }
+ else
+ {
+ LL_GL_ERRS << "Unexpected depth testing state." << LL_ENDL;
+ }
+ }
+ }
}
LLGLSquashToFarClip::LLGLSquashToFarClip()
@@ -2830,78 +2830,78 @@ LLGLSquashToFarClip::LLGLSquashToFarClip(glh::matrix4f& P, U32 layer)
void LLGLSquashToFarClip::setProjectionMatrix(glh::matrix4f& projection, U32 layer)
{
- F32 depth = 0.99999f - 0.0001f * layer;
+ F32 depth = 0.99999f - 0.0001f * layer;
- for (U32 i = 0; i < 4; i++)
- {
- projection.element(2, i) = projection.element(3, i) * depth;
- }
+ for (U32 i = 0; i < 4; i++)
+ {
+ projection.element(2, i) = projection.element(3, i) * depth;
+ }
LLRender::eMatrixMode last_matrix_mode = gGL.getMatrixMode();
- gGL.matrixMode(LLRender::MM_PROJECTION);
- gGL.pushMatrix();
- gGL.loadMatrix(projection.m);
+ gGL.matrixMode(LLRender::MM_PROJECTION);
+ gGL.pushMatrix();
+ gGL.loadMatrix(projection.m);
- gGL.matrixMode(last_matrix_mode);
+ gGL.matrixMode(last_matrix_mode);
}
LLGLSquashToFarClip::~LLGLSquashToFarClip()
{
LLRender::eMatrixMode last_matrix_mode = gGL.getMatrixMode();
- gGL.matrixMode(LLRender::MM_PROJECTION);
- gGL.popMatrix();
+ gGL.matrixMode(LLRender::MM_PROJECTION);
+ gGL.popMatrix();
- gGL.matrixMode(last_matrix_mode);
+ gGL.matrixMode(last_matrix_mode);
}
LLGLSyncFence::LLGLSyncFence()
{
- mSync = 0;
+ mSync = 0;
}
LLGLSyncFence::~LLGLSyncFence()
{
- if (mSync)
- {
- glDeleteSync(mSync);
- }
+ if (mSync)
+ {
+ glDeleteSync(mSync);
+ }
}
void LLGLSyncFence::placeFence()
{
- if (mSync)
- {
- glDeleteSync(mSync);
- }
- mSync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
+ if (mSync)
+ {
+ glDeleteSync(mSync);
+ }
+ mSync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
}
bool LLGLSyncFence::isCompleted()
{
- bool ret = true;
- if (mSync)
- {
- GLenum status = glClientWaitSync(mSync, 0, 1);
- if (status == GL_TIMEOUT_EXPIRED)
- {
- ret = false;
- }
- }
- return ret;
+ bool ret = true;
+ if (mSync)
+ {
+ GLenum status = glClientWaitSync(mSync, 0, 1);
+ if (status == GL_TIMEOUT_EXPIRED)
+ {
+ ret = false;
+ }
+ }
+ return ret;
}
void LLGLSyncFence::wait()
{
- if (mSync)
- {
- while (glClientWaitSync(mSync, 0, FENCE_WAIT_TIME_NANOSECONDS) == GL_TIMEOUT_EXPIRED)
- { //track the number of times we've waited here
- }
- }
+ if (mSync)
+ {
+ while (glClientWaitSync(mSync, 0, FENCE_WAIT_TIME_NANOSECONDS) == GL_TIMEOUT_EXPIRED)
+ { //track the number of times we've waited here
+ }
+ }
}
LLGLSPipelineSkyBox::LLGLSPipelineSkyBox()
diff --git a/indra/llrender/llgl.h b/indra/llrender/llgl.h
index 4b0fbc0466..5a7ad943df 100644
--- a/indra/llrender/llgl.h
+++ b/indra/llrender/llgl.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file llgl.h
* @brief LLGL definition
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -64,81 +64,81 @@ class LLSD;
class LLGLManager
{
public:
- LLGLManager();
+ LLGLManager();
- bool initGL();
- void shutdownGL();
+ bool initGL();
+ void shutdownGL();
- void initWGL(); // Initializes stupid WGL extensions
+ void initWGL(); // Initializes stupid WGL extensions
- std::string getRawGLString(); // For sending to simulator
+ std::string getRawGLString(); // For sending to simulator
- BOOL mInited;
- BOOL mIsDisabled;
+ BOOL mInited;
+ BOOL mIsDisabled;
- // OpenGL limits
- S32 mMaxSamples;
- S32 mNumTextureImageUnits;
- S32 mMaxSampleMaskWords;
- S32 mMaxColorTextureSamples;
- S32 mMaxDepthTextureSamples;
- S32 mMaxIntegerSamples;
+ // OpenGL limits
+ S32 mMaxSamples;
+ S32 mNumTextureImageUnits;
+ S32 mMaxSampleMaskWords;
+ S32 mMaxColorTextureSamples;
+ S32 mMaxDepthTextureSamples;
+ S32 mMaxIntegerSamples;
S32 mGLMaxVertexRange;
S32 mGLMaxIndexRange;
S32 mGLMaxTextureSize;
F32 mMaxAnisotropy = 0.f;
- // GL 4.x capabilities
- bool mHasCubeMapArray = false;
- bool mHasDebugOutput = false;
+ // GL 4.x capabilities
+ bool mHasCubeMapArray = false;
+ bool mHasDebugOutput = false;
bool mHasTransformFeedback = false;
bool mHasAnisotropic = false;
-
- // Vendor-specific extensions
+
+ // Vendor-specific extensions
bool mHasAMDAssociations = false;
- BOOL mIsAMD;
- BOOL mIsNVIDIA;
- BOOL mIsIntel;
+ BOOL mIsAMD;
+ BOOL mIsNVIDIA;
+ BOOL mIsIntel;
#if LL_DARWIN
- // Needed to distinguish problem cards on older Macs that break with Materials
- BOOL mIsMobileGF;
+ // Needed to distinguish problem cards on older Macs that break with Materials
+ BOOL mIsMobileGF;
#endif
-
- // Whether this version of GL is good enough for SL to use
- BOOL mHasRequirements;
- S32 mDriverVersionMajor;
- S32 mDriverVersionMinor;
- S32 mDriverVersionRelease;
- F32 mGLVersion; // e.g = 1.4
- S32 mGLSLVersionMajor;
- S32 mGLSLVersionMinor;
- std::string mDriverVersionVendorString;
- std::string mGLVersionString;
+ // Whether this version of GL is good enough for SL to use
+ BOOL mHasRequirements;
+
+ S32 mDriverVersionMajor;
+ S32 mDriverVersionMinor;
+ S32 mDriverVersionRelease;
+ F32 mGLVersion; // e.g = 1.4
+ S32 mGLSLVersionMajor;
+ S32 mGLSLVersionMinor;
+ std::string mDriverVersionVendorString;
+ std::string mGLVersionString;
- S32 mVRAM; // VRAM in MB
-
- void getPixelFormat(); // Get the best pixel format
+ S32 mVRAM; // VRAM in MB
- std::string getGLInfoString();
- void printGLInfoString();
- void getGLInfo(LLSD& info);
+ void getPixelFormat(); // Get the best pixel format
- void asLLSD(LLSD& info);
+ std::string getGLInfoString();
+ void printGLInfoString();
+ void getGLInfo(LLSD& info);
- // In ALL CAPS
- std::string mGLVendor;
- std::string mGLVendorShort;
+ void asLLSD(LLSD& info);
- // In ALL CAPS
- std::string mGLRenderer;
+ // In ALL CAPS
+ std::string mGLVendor;
+ std::string mGLVendorShort;
+
+ // In ALL CAPS
+ std::string mGLRenderer;
private:
- void initExtensions();
- void initGLStates();
- void initGLImages();
+ void initExtensions();
+ void initGLStates();
+ void initGLImages();
};
extern LLGLManager gGLManager;
@@ -173,51 +173,51 @@ void clear_glerror();
// This is a class for GL state management
/*
- GL STATE MANAGEMENT DESCRIPTION
+ GL STATE MANAGEMENT DESCRIPTION
- LLGLState and its two subclasses, LLGLEnable and LLGLDisable, manage the current
- enable/disable states of the GL to prevent redundant setting of state within a
- render path or the accidental corruption of what state the next path expects.
+ LLGLState and its two subclasses, LLGLEnable and LLGLDisable, manage the current
+ enable/disable states of the GL to prevent redundant setting of state within a
+ render path or the accidental corruption of what state the next path expects.
- Essentially, wherever you would call glEnable set a state and then
- subsequently reset it by calling glDisable (or vice versa), make an instance of
- LLGLEnable with the state you want to set, and assume it will be restored to its
- original state when that instance of LLGLEnable is destroyed. It is good practice
- to exploit stack frame controls for optimal setting/unsetting and readability of
- code. In llglstates.h, there are a collection of helper classes that define groups
- of enables/disables that can cause multiple states to be set with the creation of
- one instance.
+ Essentially, wherever you would call glEnable set a state and then
+ subsequently reset it by calling glDisable (or vice versa), make an instance of
+ LLGLEnable with the state you want to set, and assume it will be restored to its
+ original state when that instance of LLGLEnable is destroyed. It is good practice
+ to exploit stack frame controls for optimal setting/unsetting and readability of
+ code. In llglstates.h, there are a collection of helper classes that define groups
+ of enables/disables that can cause multiple states to be set with the creation of
+ one instance.
- Sample usage:
+ Sample usage:
- //disable lighting for rendering hud objects
- //INCORRECT USAGE
- LLGLEnable blend(GL_BLEND);
- renderHUD();
- LLGLDisable blend(GL_BLEND);
+ //disable lighting for rendering hud objects
+ //INCORRECT USAGE
+ LLGLEnable blend(GL_BLEND);
+ renderHUD();
+ LLGLDisable blend(GL_BLEND);
- //CORRECT USAGE
- {
- LLGLEnable blend(GL_BLEND);
- renderHUD();
- }
+ //CORRECT USAGE
+ {
+ LLGLEnable blend(GL_BLEND);
+ renderHUD();
+ }
- If a state is to be set on a conditional, the following mechanism
- is useful:
+ If a state is to be set on a conditional, the following mechanism
+ is useful:
- {
- LLGLEnable blend(blend_hud ? GL_GL_BLEND: 0);
- renderHUD();
- }
+ {
+ LLGLEnable blend(blend_hud ? GL_GL_BLEND: 0);
+ renderHUD();
+ }
- A LLGLState initialized with a parameter of 0 does nothing.
+ A LLGLState initialized with a parameter of 0 does nothing.
- LLGLState works by maintaining a map of the current GL states, and ignoring redundant
- enables/disables. If a redundant call is attempted, it becomes a noop, otherwise,
- it is set in the constructor and reset in the destructor.
+ LLGLState works by maintaining a map of the current GL states, and ignoring redundant
+ enables/disables. If a redundant call is attempted, it becomes a noop, otherwise,
+ it is set in the constructor and reset in the destructor.
- For debugging GL state corruption, running with debug enabled will trigger asserts
- if the existing GL state does not match the expected GL state.
+ For debugging GL state corruption, running with debug enabled will trigger asserts
+ if the existing GL state does not match the expected GL state.
*/
@@ -226,79 +226,79 @@ void clear_glerror();
class LLGLState
{
public:
- static void initClass();
- static void restoreGL();
+ static void initClass();
+ static void restoreGL();
- static void resetTextureStates();
- static void dumpStates();
+ static void resetTextureStates();
+ static void dumpStates();
// make sure GL blend function, GL states, and GL color mask match
- // what we expect
+ // what we expect
// writeAlpha - whether or not writing to alpha channel is expected
- static void checkStates(GLboolean writeAlpha = GL_TRUE);
+ static void checkStates(GLboolean writeAlpha = GL_TRUE);
protected:
- static boost::unordered_map<LLGLenum, LLGLboolean> sStateMap;
-
+ static boost::unordered_map<LLGLenum, LLGLboolean> sStateMap;
+
public:
- enum { CURRENT_STATE = -2 };
- LLGLState(LLGLenum state, S32 enabled = CURRENT_STATE);
- ~LLGLState();
- void setEnabled(S32 enabled);
- void enable() { setEnabled(TRUE); }
- void disable() { setEnabled(FALSE); }
+ enum { CURRENT_STATE = -2 };
+ LLGLState(LLGLenum state, S32 enabled = CURRENT_STATE);
+ ~LLGLState();
+ void setEnabled(S32 enabled);
+ void enable() { setEnabled(TRUE); }
+ void disable() { setEnabled(FALSE); }
protected:
- LLGLenum mState;
- BOOL mWasEnabled;
- BOOL mIsEnabled;
+ LLGLenum mState;
+ BOOL mWasEnabled;
+ BOOL mIsEnabled;
};
// New LLGLState class wrappers that don't depend on actual GL flags.
class LLGLEnableBlending : public LLGLState
{
public:
- LLGLEnableBlending(bool enable);
+ LLGLEnableBlending(bool enable);
};
class LLGLEnableAlphaReject : public LLGLState
{
public:
- LLGLEnableAlphaReject(bool enable);
+ LLGLEnableAlphaReject(bool enable);
};
// Enable with functor
class LLGLEnableFunc : LLGLState
{
public:
- LLGLEnableFunc(LLGLenum state, bool enable, boost::function<void()> func)
- : LLGLState(state, enable)
- {
- if (enable)
- {
- func();
- }
- }
+ LLGLEnableFunc(LLGLenum state, bool enable, boost::function<void()> func)
+ : LLGLState(state, enable)
+ {
+ if (enable)
+ {
+ func();
+ }
+ }
};
/// TODO: Being deprecated.
class LLGLEnable : public LLGLState
{
public:
- LLGLEnable(LLGLenum state) : LLGLState(state, TRUE) {}
+ LLGLEnable(LLGLenum state) : LLGLState(state, TRUE) {}
};
/// TODO: Being deprecated.
class LLGLDisable : public LLGLState
{
public:
- LLGLDisable(LLGLenum state) : LLGLState(state, FALSE) {}
+ LLGLDisable(LLGLenum state) : LLGLState(state, FALSE) {}
};
/*
Store and modify projection matrix to create an oblique
projection that clips to the specified plane. Oblique
projections alter values in the depth buffer, so this
- class should not be used mid-renderpass.
+ class should not be used mid-renderpass.
Restores projection matrix on destruction.
GL_MODELVIEW_MATRIX is active whenever program execution
@@ -306,21 +306,21 @@ public:
Does not stack.
Caches inverse of projection matrix used in gGLObliqueProjectionInverse
*/
-class LLGLUserClipPlane
+class LLGLUserClipPlane
{
public:
-
- LLGLUserClipPlane(const LLPlane& plane, const glh::matrix4f& modelview, const glh::matrix4f& projection, bool apply = true);
- ~LLGLUserClipPlane();
- void setPlane(F32 a, F32 b, F32 c, F32 d);
+ LLGLUserClipPlane(const LLPlane& plane, const glh::matrix4f& modelview, const glh::matrix4f& projection, bool apply = true);
+ ~LLGLUserClipPlane();
+
+ void setPlane(F32 a, F32 b, F32 c, F32 d);
void disable();
private:
- bool mApply;
+ bool mApply;
- glh::matrix4f mProjection;
- glh::matrix4f mModelview;
+ glh::matrix4f mProjection;
+ glh::matrix4f mModelview;
};
/*
@@ -334,40 +334,40 @@ class LLGLSquashToFarClip
{
public:
LLGLSquashToFarClip();
- LLGLSquashToFarClip(glh::matrix4f& projection, U32 layer = 0);
+ LLGLSquashToFarClip(glh::matrix4f& projection, U32 layer = 0);
void setProjectionMatrix(glh::matrix4f& projection, U32 layer);
- ~LLGLSquashToFarClip();
+ ~LLGLSquashToFarClip();
};
/*
- Interface for objects that need periodic GL updates applied to them.
- Used to synchronize GL updates with GL thread.
+ Interface for objects that need periodic GL updates applied to them.
+ Used to synchronize GL updates with GL thread.
*/
class LLGLUpdate
{
public:
- static std::list<LLGLUpdate*> sGLQ;
-
- BOOL mInQ;
- LLGLUpdate()
- : mInQ(FALSE)
- {
- }
- virtual ~LLGLUpdate()
- {
- if (mInQ)
- {
- std::list<LLGLUpdate*>::iterator iter = std::find(sGLQ.begin(), sGLQ.end(), this);
- if (iter != sGLQ.end())
- {
- sGLQ.erase(iter);
- }
- }
- }
- virtual void updateGL() = 0;
+ static std::list<LLGLUpdate*> sGLQ;
+
+ BOOL mInQ;
+ LLGLUpdate()
+ : mInQ(FALSE)
+ {
+ }
+ virtual ~LLGLUpdate()
+ {
+ if (mInQ)
+ {
+ std::list<LLGLUpdate*>::iterator iter = std::find(sGLQ.begin(), sGLQ.end(), this);
+ if (iter != sGLQ.end())
+ {
+ sGLQ.erase(iter);
+ }
+ }
+ }
+ virtual void updateGL() = 0;
};
const U32 FENCE_WAIT_TIME_NANOSECONDS = 1000; //1 ms
@@ -375,26 +375,26 @@ const U32 FENCE_WAIT_TIME_NANOSECONDS = 1000; //1 ms
class LLGLFence
{
public:
- virtual ~LLGLFence()
- {
- }
+ virtual ~LLGLFence()
+ {
+ }
- virtual void placeFence() = 0;
- virtual bool isCompleted() = 0;
- virtual void wait() = 0;
+ virtual void placeFence() = 0;
+ virtual bool isCompleted() = 0;
+ virtual void wait() = 0;
};
class LLGLSyncFence : public LLGLFence
{
public:
- GLsync mSync;
-
- LLGLSyncFence();
- virtual ~LLGLSyncFence();
-
- void placeFence();
- bool isCompleted();
- void wait();
+ GLsync mSync;
+
+ LLGLSyncFence();
+ virtual ~LLGLSyncFence();
+
+ void placeFence();
+ bool isCompleted();
+ void wait();
};
extern LLMatrix4 gGLObliqueProjectionInverse;
@@ -471,6 +471,6 @@ extern BOOL gGLActive;
#ifndef GL_DEPTH24_STENCIL8
#define GL_DEPTH24_STENCIL8 GL_DEPTH24_STENCIL8_EXT
-#endif
+#endif
#endif // LL_LLGL_H
diff --git a/indra/llrender/llglcommonfunc.cpp b/indra/llrender/llglcommonfunc.cpp
index 04d29b9430..13b08de7cc 100644
--- a/indra/llrender/llglcommonfunc.cpp
+++ b/indra/llrender/llglcommonfunc.cpp
@@ -27,12 +27,12 @@
#include "llglheaders.h"
#include "llglcommonfunc.h"
-namespace LLGLCommonFunc
+namespace LLGLCommonFunc
{
- void selected_stencil_test()
- {
+ void selected_stencil_test()
+ {
// deprecated
- //glStencilFunc(GL_ALWAYS, 2, 0xffff);
- //glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
- }
+ //glStencilFunc(GL_ALWAYS, 2, 0xffff);
+ //glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
+ }
}
diff --git a/indra/llrender/llglcommonfunc.h b/indra/llrender/llglcommonfunc.h
index e6d3755755..bb995fc199 100644
--- a/indra/llrender/llglcommonfunc.h
+++ b/indra/llrender/llglcommonfunc.h
@@ -26,5 +26,5 @@
namespace LLGLCommonFunc
{
- void selected_stencil_test();
+ void selected_stencil_test();
}
diff --git a/indra/llrender/llglheaders.h b/indra/llrender/llglheaders.h
index fe7625236d..df23a9da1d 100644
--- a/indra/llrender/llglheaders.h
+++ b/indra/llrender/llglheaders.h
@@ -871,7 +871,7 @@ extern void glGenerateMipmapEXT(GLenum target) AVAILABLE_MAC_OS_X_VERSION_10_4_A
#ifndef GL_ARB_framebuffer_object
#define glGenerateMipmap glGenerateMipmapEXT
-#define GL_MAX_SAMPLES 0x8D57
+#define GL_MAX_SAMPLES 0x8D57
#endif
#ifdef __cplusplus
@@ -953,7 +953,7 @@ extern "C" {
#define GL_DYNAMIC_READ_ARB 0x88E9
#define GL_DYNAMIC_COPY_ARB 0x88EA
#endif
-
+
#ifndef GL_ARB_vertex_buffer_object
@@ -973,7 +973,7 @@ typedef GLboolean (* glIsBufferARBProcPtr) (GLuint buffer);
typedef void (* glBufferDataARBProcPtr) (GLenum target, GLsizeiptrARB size, const GLvoid *data, GLenum usage);
typedef void (* glBufferSubDataARBProcPtr) (GLenum target, GLintptrARB offset, GLsizeiptrARB size, const GLvoid *data);
typedef void (* glGetBufferSubDataARBProcPtr) (GLenum target, GLintptrARB offset, GLsizeiptrARB size, GLvoid *data);
-typedef GLvoid* (* glMapBufferARBProcPtr) (GLenum target, GLenum access); /* Flawfinder: ignore */
+typedef GLvoid* (* glMapBufferARBProcPtr) (GLenum target, GLenum access); /* Flawfinder: ignore */
typedef GLboolean (* glUnmapBufferARBProcPtr) (GLenum target);
typedef void (* glGetBufferParameterivARBProcPtr) (GLenum target, GLenum pname, GLint *params);
typedef void (* glGetBufferPointervARBProcPtr) (GLenum target, GLenum pname, GLvoid* *params);
@@ -1080,11 +1080,11 @@ extern void glGetBufferPointervARB (GLenum, GLenum, GLvoid* *);
//GL_NVX_gpu_memory_info constants
#ifndef GL_NVX_gpu_memory_info
#define GL_NVX_gpu_memory_info
-#define GL_GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX 0x9047
-#define GL_GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX 0x9048
-#define GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX 0x9049
-#define GL_GPU_MEMORY_INFO_EVICTION_COUNT_NVX 0x904A
-#define GL_GPU_MEMORY_INFO_EVICTED_MEMORY_NVX 0x904B
+#define GL_GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX 0x9047
+#define GL_GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX 0x9048
+#define GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX 0x9049
+#define GL_GPU_MEMORY_INFO_EVICTION_COUNT_NVX 0x904A
+#define GL_GPU_MEMORY_INFO_EVICTED_MEMORY_NVX 0x904B
#endif
//GL_ATI_meminfo constants
@@ -1098,6 +1098,6 @@ extern void glGetBufferPointervARB (GLenum, GLenum, GLvoid* *);
#if defined(TRACY_ENABLE) && LL_PROFILER_ENABLE_TRACY_OPENGL
#include <tracy/TracyOpenGL.hpp>
#endif
-
+
#endif // LL_LLGLHEADERS_H
diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp
index 8749976921..faa1cd096c 100644
--- a/indra/llrender/llglslshader.cpp
+++ b/indra/llrender/llglslshader.cpp
@@ -422,27 +422,27 @@ BOOL LLGLSLShader::createShader(std::vector<LLStaticHashedString>* attributes,
mUsingBinaryProgram = LLShaderMgr::instance()->loadCachedProgramBinary(this);
- if (!mUsingBinaryProgram)
- {
+ if (!mUsingBinaryProgram)
+ {
#if DEBUG_SHADER_INCLUDES
- fprintf(stderr, "--- %s ---\n", mName.c_str());
+ fprintf(stderr, "--- %s ---\n", mName.c_str());
#endif // DEBUG_SHADER_INCLUDES
//compile new source
- vector< pair<string, GLenum> >::iterator fileIter = mShaderFiles.begin();
- for (; fileIter != mShaderFiles.end(); fileIter++)
- {
- GLuint shaderhandle = LLShaderMgr::instance()->loadShaderFile((*fileIter).first, mShaderLevel, (*fileIter).second, &mDefines, mFeatures.mIndexedTextureChannels);
- LL_DEBUGS("ShaderLoading") << "SHADER FILE: " << (*fileIter).first << " mShaderLevel=" << mShaderLevel << LL_ENDL;
- if (shaderhandle)
- {
- attachObject(shaderhandle);
- }
- else
- {
- success = FALSE;
- }
- }
+ vector< pair<string, GLenum> >::iterator fileIter = mShaderFiles.begin();
+ for (; fileIter != mShaderFiles.end(); fileIter++)
+ {
+ GLuint shaderhandle = LLShaderMgr::instance()->loadShaderFile((*fileIter).first, mShaderLevel, (*fileIter).second, &mDefines, mFeatures.mIndexedTextureChannels);
+ LL_DEBUGS("ShaderLoading") << "SHADER FILE: " << (*fileIter).first << " mShaderLevel=" << mShaderLevel << LL_ENDL;
+ if (shaderhandle)
+ {
+ attachObject(shaderhandle);
+ }
+ else
+ {
+ success = FALSE;
+ }
+ }
}
// Attach existing objects
@@ -606,19 +606,19 @@ BOOL LLGLSLShader::mapAttributes(const std::vector<LLStaticHashedString>* attrib
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
- BOOL res = TRUE;
- if (!mUsingBinaryProgram)
- {
- //before linking, make sure reserved attributes always have consistent locations
- for (U32 i = 0; i < LLShaderMgr::instance()->mReservedAttribs.size(); i++)
- {
- const char* name = LLShaderMgr::instance()->mReservedAttribs[i].c_str();
- glBindAttribLocation(mProgramObject, i, (const GLchar*)name);
- }
-
- //link the program
- res = link();
- }
+ BOOL res = TRUE;
+ if (!mUsingBinaryProgram)
+ {
+ //before linking, make sure reserved attributes always have consistent locations
+ for (U32 i = 0; i < LLShaderMgr::instance()->mReservedAttribs.size(); i++)
+ {
+ const char* name = LLShaderMgr::instance()->mReservedAttribs[i].c_str();
+ glBindAttribLocation(mProgramObject, i, (const GLchar*)name);
+ }
+
+ //link the program
+ res = link();
+ }
mAttribute.clear();
U32 numAttributes = (attributes == NULL) ? 0 : attributes->size();
diff --git a/indra/llrender/llglslshader.h b/indra/llrender/llglslshader.h
index 43d095f73a..df568bfea5 100644
--- a/indra/llrender/llglslshader.h
+++ b/indra/llrender/llglslshader.h
@@ -233,7 +233,7 @@ public:
void addConstant(const LLGLSLShader::eShaderConsts shader_const);
//enable/disable texture channel for specified uniform
- //if given texture uniform is active in the shader,
+ //if given texture uniform is active in the shader,
//the corresponding channel will be active upon return
//returns channel texture is enabled in from [0-MAX)
S32 enableTexture(S32 uniform, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE, LLTexUnit::eTextureColorSpace space = LLTexUnit::TCS_LINEAR);
@@ -255,7 +255,7 @@ public:
void bind();
//helper to conditionally bind mRiggedVariant instead of this
void bind(bool rigged);
-
+
bool isComplete() const { return mProgramObject != 0; }
LLUUID hash();
@@ -329,11 +329,11 @@ private:
};
//UI shader (declared here so llui_libtest will link properly)
-extern LLGLSLShader gUIProgram;
+extern LLGLSLShader gUIProgram;
//output vec4(color.rgb,color.a*tex0[tc0].a)
-extern LLGLSLShader gSolidColorProgram;
+extern LLGLSLShader gSolidColorProgram;
//Alpha mask shader (declared here so llappearance can access properly)
-extern LLGLSLShader gAlphaMaskProgram;
+extern LLGLSLShader gAlphaMaskProgram;
#ifdef LL_PROFILER_ENABLE_RENDER_DOC
#define LL_SET_SHADER_LABEL(shader) shader.setLabel(#shader)
diff --git a/indra/llrender/llglstates.h b/indra/llrender/llglstates.h
index 930c5e3ed7..9bb980d7ad 100644
--- a/indra/llrender/llglstates.h
+++ b/indra/llrender/llglstates.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file llglstates.h
* @brief LLGL states definitions
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -34,21 +34,21 @@
class LLGLDepthTest
{
- // Enabled by default
+ // Enabled by default
public:
- LLGLDepthTest(GLboolean depth_enabled, GLboolean write_enabled = GL_TRUE, GLenum depth_func = GL_LEQUAL);
-
- ~LLGLDepthTest();
-
- void checkState();
-
- GLboolean mPrevDepthEnabled;
- GLenum mPrevDepthFunc;
- GLboolean mPrevWriteEnabled;
+ LLGLDepthTest(GLboolean depth_enabled, GLboolean write_enabled = GL_TRUE, GLenum depth_func = GL_LEQUAL);
+
+ ~LLGLDepthTest();
+
+ void checkState();
+
+ GLboolean mPrevDepthEnabled;
+ GLenum mPrevDepthFunc;
+ GLboolean mPrevWriteEnabled;
private:
- static GLboolean sDepthEnabled; // defaults to GL_FALSE
- static GLenum sDepthFunc; // defaults to GL_LESS
- static GLboolean sWriteEnabled; // defaults to GL_TRUE
+ static GLboolean sDepthEnabled; // defaults to GL_FALSE
+ static GLenum sDepthFunc; // defaults to GL_LESS
+ static GLboolean sWriteEnabled; // defaults to GL_TRUE
};
//----------------------------------------------------------------------------
@@ -58,110 +58,110 @@ class LLGLSDefault
protected:
LLGLDisable mBlend, mCullFace;
public:
- LLGLSDefault()
- :
- // Disable
- mBlend(GL_BLEND),
- mCullFace(GL_CULL_FACE)
- { }
+ LLGLSDefault()
+ :
+ // Disable
+ mBlend(GL_BLEND),
+ mCullFace(GL_CULL_FACE)
+ { }
};
class LLGLSObjectSelect
-{
+{
protected:
- LLGLDisable mBlend;
- LLGLEnable mCullFace;
+ LLGLDisable mBlend;
+ LLGLEnable mCullFace;
public:
- LLGLSObjectSelect()
- : mBlend(GL_BLEND),
- mCullFace(GL_CULL_FACE)
- { }
+ LLGLSObjectSelect()
+ : mBlend(GL_BLEND),
+ mCullFace(GL_CULL_FACE)
+ { }
};
//----------------------------------------------------------------------------
class LLGLSUIDefault
-{
+{
protected:
- LLGLEnable mBlend;
- LLGLDisable mCullFace;
- LLGLDepthTest mDepthTest;
+ LLGLEnable mBlend;
+ LLGLDisable mCullFace;
+ LLGLDepthTest mDepthTest;
public:
- LLGLSUIDefault()
- : mBlend(GL_BLEND),
- mCullFace(GL_CULL_FACE),
- mDepthTest(GL_FALSE, GL_TRUE, GL_LEQUAL)
- {}
+ LLGLSUIDefault()
+ : mBlend(GL_BLEND),
+ mCullFace(GL_CULL_FACE),
+ mDepthTest(GL_FALSE, GL_TRUE, GL_LEQUAL)
+ {}
};
//----------------------------------------------------------------------------
class LLGLSPipeline
-{
+{
protected:
- LLGLEnable mCullFace;
- LLGLDepthTest mDepthTest;
+ LLGLEnable mCullFace;
+ LLGLDepthTest mDepthTest;
public:
- LLGLSPipeline()
- : mCullFace(GL_CULL_FACE),
- mDepthTest(GL_TRUE, GL_TRUE, GL_LEQUAL)
- { }
+ LLGLSPipeline()
+ : mCullFace(GL_CULL_FACE),
+ mDepthTest(GL_TRUE, GL_TRUE, GL_LEQUAL)
+ { }
};
class LLGLSPipelineAlpha // : public LLGLSPipeline
-{
+{
protected:
- LLGLEnable mBlend;
+ LLGLEnable mBlend;
public:
- LLGLSPipelineAlpha()
- : mBlend(GL_BLEND)
- { }
+ LLGLSPipelineAlpha()
+ : mBlend(GL_BLEND)
+ { }
};
class LLGLSPipelineSelection
-{
+{
protected:
- LLGLDisable mCullFace;
+ LLGLDisable mCullFace;
public:
- LLGLSPipelineSelection()
- : mCullFace(GL_CULL_FACE)
- {}
+ LLGLSPipelineSelection()
+ : mCullFace(GL_CULL_FACE)
+ {}
};
class LLGLSPipelineSkyBox
-{
+{
protected:
LLGLDisable mCullFace;
LLGLSquashToFarClip mSquashClip;
public:
- LLGLSPipelineSkyBox();
+ LLGLSPipelineSkyBox();
~LLGLSPipelineSkyBox();
};
class LLGLSPipelineDepthTestSkyBox : public LLGLSPipelineSkyBox
-{
+{
public:
- LLGLSPipelineDepthTestSkyBox(bool depth_test, bool depth_write);
+ LLGLSPipelineDepthTestSkyBox(bool depth_test, bool depth_write);
LLGLDepthTest mDepth;
};
-class LLGLSPipelineBlendSkyBox : public LLGLSPipelineDepthTestSkyBox
-{
+class LLGLSPipelineBlendSkyBox : public LLGLSPipelineDepthTestSkyBox
+{
public:
- LLGLSPipelineBlendSkyBox(bool depth_test, bool depth_write);
- LLGLEnable mBlend;
+ LLGLSPipelineBlendSkyBox(bool depth_test, bool depth_write);
+ LLGLEnable mBlend;
};
class LLGLSTracker
{
protected:
- LLGLEnable mCullFace, mBlend;
+ LLGLEnable mCullFace, mBlend;
public:
- LLGLSTracker() :
- mCullFace(GL_CULL_FACE),
- mBlend(GL_BLEND)
- { }
+ LLGLSTracker() :
+ mCullFace(GL_CULL_FACE),
+ mBlend(GL_BLEND)
+ { }
};
//----------------------------------------------------------------------------
@@ -169,26 +169,26 @@ public:
class LLGLSSpecular
{
public:
- F32 mShininess;
- LLGLSSpecular(const LLColor4& color, F32 shininess)
- {
- mShininess = shininess;
- if (mShininess > 0.0f)
- {
- glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, color.mV);
- S32 shiny = (S32)(shininess*128.f);
- shiny = llclamp(shiny,0,128);
- glMateriali(GL_FRONT_AND_BACK, GL_SHININESS, shiny);
- }
- }
- ~LLGLSSpecular()
- {
- if (mShininess > 0.f)
- {
- glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, LLColor4(0.f,0.f,0.f,0.f).mV);
- glMateriali(GL_FRONT_AND_BACK, GL_SHININESS, 0);
- }
- }
+ F32 mShininess;
+ LLGLSSpecular(const LLColor4& color, F32 shininess)
+ {
+ mShininess = shininess;
+ if (mShininess > 0.0f)
+ {
+ glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, color.mV);
+ S32 shiny = (S32)(shininess*128.f);
+ shiny = llclamp(shiny,0,128);
+ glMateriali(GL_FRONT_AND_BACK, GL_SHININESS, shiny);
+ }
+ }
+ ~LLGLSSpecular()
+ {
+ if (mShininess > 0.f)
+ {
+ glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, LLColor4(0.f,0.f,0.f,0.f).mV);
+ glMateriali(GL_FRONT_AND_BACK, GL_SHININESS, 0);
+ }
+ }
};
//----------------------------------------------------------------------------
diff --git a/indra/llrender/llgltexture.cpp b/indra/llrender/llgltexture.cpp
index b616002b49..944a3d0235 100644
--- a/indra/llrender/llgltexture.cpp
+++ b/indra/llrender/llgltexture.cpp
@@ -1,25 +1,25 @@
-/**
+/**
* @file llgltexture.cpp
* @brief Opengl texture implementation
*
* $LicenseInfo:firstyear=2000&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -29,365 +29,365 @@
LLGLTexture::LLGLTexture(BOOL usemipmaps)
{
- init();
- mUseMipMaps = usemipmaps;
+ init();
+ mUseMipMaps = usemipmaps;
}
LLGLTexture::LLGLTexture(const U32 width, const U32 height, const U8 components, BOOL usemipmaps)
{
- init();
- mFullWidth = width ;
- mFullHeight = height ;
- mUseMipMaps = usemipmaps;
- mComponents = components ;
- setTexelsPerImage();
+ init();
+ mFullWidth = width ;
+ mFullHeight = height ;
+ mUseMipMaps = usemipmaps;
+ mComponents = components ;
+ setTexelsPerImage();
}
LLGLTexture::LLGLTexture(const LLImageRaw* raw, BOOL usemipmaps)
{
- init();
- mUseMipMaps = usemipmaps ;
- // Create an empty image of the specified size and width
- mGLTexturep = new LLImageGL(raw, usemipmaps) ;
+ init();
+ mUseMipMaps = usemipmaps ;
+ // Create an empty image of the specified size and width
+ mGLTexturep = new LLImageGL(raw, usemipmaps) ;
}
LLGLTexture::~LLGLTexture()
{
- cleanup();
+ cleanup();
}
void LLGLTexture::init()
{
- mBoostLevel = LLGLTexture::BOOST_NONE;
+ mBoostLevel = LLGLTexture::BOOST_NONE;
- mFullWidth = 0;
- mFullHeight = 0;
- mTexelsPerImage = 0 ;
- mUseMipMaps = FALSE ;
- mComponents = 0 ;
+ mFullWidth = 0;
+ mFullHeight = 0;
+ mTexelsPerImage = 0 ;
+ mUseMipMaps = FALSE ;
+ mComponents = 0 ;
- mTextureState = NO_DELETE ;
- mDontDiscard = FALSE;
- mNeedsGLTexture = FALSE ;
+ mTextureState = NO_DELETE ;
+ mDontDiscard = FALSE;
+ mNeedsGLTexture = FALSE ;
}
void LLGLTexture::cleanup()
{
- if(mGLTexturep)
- {
- mGLTexturep->cleanup();
- }
+ if(mGLTexturep)
+ {
+ mGLTexturep->cleanup();
+ }
}
// virtual
void LLGLTexture::dump()
{
- if(mGLTexturep)
- {
- mGLTexturep->dump();
- }
+ if(mGLTexturep)
+ {
+ mGLTexturep->dump();
+ }
}
void LLGLTexture::setBoostLevel(S32 level)
{
- if(mBoostLevel != level)
- {
- mBoostLevel = level ;
- if(mBoostLevel != LLGLTexture::BOOST_NONE
- && mBoostLevel != LLGLTexture::BOOST_ICON
+ if(mBoostLevel != level)
+ {
+ mBoostLevel = level ;
+ if(mBoostLevel != LLGLTexture::BOOST_NONE
+ && mBoostLevel != LLGLTexture::BOOST_ICON
&& mBoostLevel != LLGLTexture::BOOST_THUMBNAIL)
- {
- setNoDelete() ;
- }
- }
+ {
+ setNoDelete() ;
+ }
+ }
}
void LLGLTexture::forceActive()
{
- mTextureState = ACTIVE ;
+ mTextureState = ACTIVE ;
}
-void LLGLTexture::setActive()
-{
- if(mTextureState != NO_DELETE)
- {
- mTextureState = ACTIVE ;
- }
+void LLGLTexture::setActive()
+{
+ if(mTextureState != NO_DELETE)
+ {
+ mTextureState = ACTIVE ;
+ }
}
//set the texture to stay in memory
-void LLGLTexture::setNoDelete()
-{
- mTextureState = NO_DELETE ;
+void LLGLTexture::setNoDelete()
+{
+ mTextureState = NO_DELETE ;
}
-void LLGLTexture::generateGLTexture()
-{
- if(mGLTexturep.isNull())
- {
- mGLTexturep = new LLImageGL(mFullWidth, mFullHeight, mComponents, mUseMipMaps) ;
- }
+void LLGLTexture::generateGLTexture()
+{
+ if(mGLTexturep.isNull())
+ {
+ mGLTexturep = new LLImageGL(mFullWidth, mFullHeight, mComponents, mUseMipMaps) ;
+ }
}
LLImageGL* LLGLTexture::getGLTexture() const
{
- llassert(mGLTexturep.notNull()) ;
+ llassert(mGLTexturep.notNull()) ;
- return mGLTexturep ;
+ return mGLTexturep ;
}
-BOOL LLGLTexture::createGLTexture()
+BOOL LLGLTexture::createGLTexture()
{
- if(mGLTexturep.isNull())
- {
- generateGLTexture() ;
- }
+ if(mGLTexturep.isNull())
+ {
+ generateGLTexture() ;
+ }
- return mGLTexturep->createGLTexture() ;
+ return mGLTexturep->createGLTexture() ;
}
BOOL LLGLTexture::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename, BOOL to_create, S32 category, bool defer_copy, LLGLuint* tex_name)
{
- llassert(mGLTexturep.notNull());
+ llassert(mGLTexturep.notNull());
- BOOL ret = mGLTexturep->createGLTexture(discard_level, imageraw, usename, to_create, category, defer_copy, tex_name) ;
+ BOOL ret = mGLTexturep->createGLTexture(discard_level, imageraw, usename, to_create, category, defer_copy, tex_name) ;
- if(ret)
- {
- mFullWidth = mGLTexturep->getCurrentWidth() ;
- mFullHeight = mGLTexturep->getCurrentHeight() ;
- mComponents = mGLTexturep->getComponents() ;
- setTexelsPerImage();
- }
+ if(ret)
+ {
+ mFullWidth = mGLTexturep->getCurrentWidth() ;
+ mFullHeight = mGLTexturep->getCurrentHeight() ;
+ mComponents = mGLTexturep->getComponents() ;
+ setTexelsPerImage();
+ }
- return ret ;
+ return ret ;
}
void LLGLTexture::setExplicitFormat(LLGLint internal_format, LLGLenum primary_format, LLGLenum type_format, BOOL swap_bytes)
{
- llassert(mGLTexturep.notNull()) ;
-
- mGLTexturep->setExplicitFormat(internal_format, primary_format, type_format, swap_bytes) ;
+ llassert(mGLTexturep.notNull()) ;
+
+ mGLTexturep->setExplicitFormat(internal_format, primary_format, type_format, swap_bytes) ;
}
void LLGLTexture::setAddressMode(LLTexUnit::eTextureAddressMode mode)
{
- llassert(mGLTexturep.notNull()) ;
- mGLTexturep->setAddressMode(mode) ;
+ llassert(mGLTexturep.notNull()) ;
+ mGLTexturep->setAddressMode(mode) ;
}
void LLGLTexture::setFilteringOption(LLTexUnit::eTextureFilterOptions option)
{
- llassert(mGLTexturep.notNull()) ;
- mGLTexturep->setFilteringOption(option) ;
+ llassert(mGLTexturep.notNull()) ;
+ mGLTexturep->setFilteringOption(option) ;
}
//virtual
-S32 LLGLTexture::getWidth(S32 discard_level) const
+S32 LLGLTexture::getWidth(S32 discard_level) const
{
- llassert(mGLTexturep.notNull()) ;
- return mGLTexturep->getWidth(discard_level) ;
+ llassert(mGLTexturep.notNull()) ;
+ return mGLTexturep->getWidth(discard_level) ;
}
//virtual
-S32 LLGLTexture::getHeight(S32 discard_level) const
+S32 LLGLTexture::getHeight(S32 discard_level) const
{
- llassert(mGLTexturep.notNull()) ;
- return mGLTexturep->getHeight(discard_level) ;
+ llassert(mGLTexturep.notNull()) ;
+ return mGLTexturep->getHeight(discard_level) ;
}
S32 LLGLTexture::getMaxDiscardLevel() const
{
- llassert(mGLTexturep.notNull()) ;
- return mGLTexturep->getMaxDiscardLevel() ;
+ llassert(mGLTexturep.notNull()) ;
+ return mGLTexturep->getMaxDiscardLevel() ;
}
S32 LLGLTexture::getDiscardLevel() const
{
- llassert(mGLTexturep.notNull()) ;
- return mGLTexturep->getDiscardLevel() ;
+ llassert(mGLTexturep.notNull()) ;
+ return mGLTexturep->getDiscardLevel() ;
}
-S8 LLGLTexture::getComponents() const
-{
- llassert(mGLTexturep.notNull()) ;
-
- return mGLTexturep->getComponents() ;
+S8 LLGLTexture::getComponents() const
+{
+ llassert(mGLTexturep.notNull()) ;
+
+ return mGLTexturep->getComponents() ;
}
-LLGLuint LLGLTexture::getTexName() const
-{
- llassert(mGLTexturep.notNull()) ;
+LLGLuint LLGLTexture::getTexName() const
+{
+ llassert(mGLTexturep.notNull()) ;
- return mGLTexturep->getTexName() ;
+ return mGLTexturep->getTexName() ;
}
-BOOL LLGLTexture::hasGLTexture() const
+BOOL LLGLTexture::hasGLTexture() const
{
- if(mGLTexturep.notNull())
- {
- return mGLTexturep->getHasGLTexture() ;
- }
- return FALSE ;
+ if(mGLTexturep.notNull())
+ {
+ return mGLTexturep->getHasGLTexture() ;
+ }
+ return FALSE ;
}
BOOL LLGLTexture::getBoundRecently() const
{
- if(mGLTexturep.notNull())
- {
- return mGLTexturep->getBoundRecently() ;
- }
- return FALSE ;
+ if(mGLTexturep.notNull())
+ {
+ return mGLTexturep->getBoundRecently() ;
+ }
+ return FALSE ;
}
LLTexUnit::eTextureType LLGLTexture::getTarget(void) const
{
- llassert(mGLTexturep.notNull()) ;
- return mGLTexturep->getTarget() ;
+ llassert(mGLTexturep.notNull()) ;
+ return mGLTexturep->getTarget() ;
}
BOOL LLGLTexture::setSubImage(const LLImageRaw* imageraw, S32 x_pos, S32 y_pos, S32 width, S32 height, LLGLuint use_name)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
- llassert(mGLTexturep.notNull()) ;
+ llassert(mGLTexturep.notNull()) ;
- return mGLTexturep->setSubImage(imageraw, x_pos, y_pos, width, height, 0, use_name) ;
+ return mGLTexturep->setSubImage(imageraw, x_pos, y_pos, width, height, 0, use_name) ;
}
BOOL LLGLTexture::setSubImage(const U8* datap, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height, LLGLuint use_name)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
- llassert(mGLTexturep.notNull()) ;
+ llassert(mGLTexturep.notNull()) ;
- return mGLTexturep->setSubImage(datap, data_width, data_height, x_pos, y_pos, width, height, 0, use_name) ;
+ return mGLTexturep->setSubImage(datap, data_width, data_height, x_pos, y_pos, width, height, 0, use_name) ;
}
void LLGLTexture::setGLTextureCreated (bool initialized)
{
- llassert(mGLTexturep.notNull()) ;
+ llassert(mGLTexturep.notNull()) ;
- mGLTexturep->setGLTextureCreated (initialized) ;
+ mGLTexturep->setGLTextureCreated (initialized) ;
}
-void LLGLTexture::setCategory(S32 category)
+void LLGLTexture::setCategory(S32 category)
{
- llassert(mGLTexturep.notNull()) ;
+ llassert(mGLTexturep.notNull()) ;
- mGLTexturep->setCategory(category) ;
+ mGLTexturep->setCategory(category) ;
}
void LLGLTexture::setTexName(LLGLuint texName)
{
llassert(mGLTexturep.notNull());
- return mGLTexturep->setTexName(texName);
+ return mGLTexturep->setTexName(texName);
}
void LLGLTexture::setTarget(const LLGLenum target, const LLTexUnit::eTextureType bind_target)
{
llassert(mGLTexturep.notNull());
- return mGLTexturep->setTarget(target, bind_target);
+ return mGLTexturep->setTarget(target, bind_target);
}
LLTexUnit::eTextureAddressMode LLGLTexture::getAddressMode(void) const
{
- llassert(mGLTexturep.notNull()) ;
+ llassert(mGLTexturep.notNull()) ;
- return mGLTexturep->getAddressMode() ;
+ return mGLTexturep->getAddressMode() ;
}
S32Bytes LLGLTexture::getTextureMemory() const
{
- llassert(mGLTexturep.notNull()) ;
+ llassert(mGLTexturep.notNull()) ;
- return mGLTexturep->mTextureMemory ;
+ return mGLTexturep->mTextureMemory ;
}
LLGLenum LLGLTexture::getPrimaryFormat() const
{
- llassert(mGLTexturep.notNull()) ;
+ llassert(mGLTexturep.notNull()) ;
- return mGLTexturep->getPrimaryFormat() ;
+ return mGLTexturep->getPrimaryFormat() ;
}
BOOL LLGLTexture::getIsAlphaMask() const
{
- llassert(mGLTexturep.notNull()) ;
+ llassert(mGLTexturep.notNull()) ;
- return mGLTexturep->getIsAlphaMask() ;
+ return mGLTexturep->getIsAlphaMask() ;
}
BOOL LLGLTexture::getMask(const LLVector2 &tc)
{
- llassert(mGLTexturep.notNull()) ;
+ llassert(mGLTexturep.notNull()) ;
- return mGLTexturep->getMask(tc) ;
+ return mGLTexturep->getMask(tc) ;
}
F32 LLGLTexture::getTimePassedSinceLastBound()
{
- llassert(mGLTexturep.notNull()) ;
+ llassert(mGLTexturep.notNull()) ;
- return mGLTexturep->getTimePassedSinceLastBound() ;
+ return mGLTexturep->getTimePassedSinceLastBound() ;
}
-BOOL LLGLTexture::getMissed() const
+BOOL LLGLTexture::getMissed() const
{
- llassert(mGLTexturep.notNull()) ;
+ llassert(mGLTexturep.notNull()) ;
- return mGLTexturep->getMissed() ;
+ return mGLTexturep->getMissed() ;
}
BOOL LLGLTexture::isJustBound() const
{
- llassert(mGLTexturep.notNull()) ;
+ llassert(mGLTexturep.notNull()) ;
- return mGLTexturep->isJustBound() ;
+ return mGLTexturep->isJustBound() ;
}
void LLGLTexture::forceUpdateBindStats(void) const
{
- llassert(mGLTexturep.notNull()) ;
+ llassert(mGLTexturep.notNull()) ;
- return mGLTexturep->forceUpdateBindStats() ;
+ return mGLTexturep->forceUpdateBindStats() ;
}
U32 LLGLTexture::getTexelsInAtlas() const
{
- llassert(mGLTexturep.notNull()) ;
+ llassert(mGLTexturep.notNull()) ;
- return mGLTexturep->getTexelsInAtlas() ;
+ return mGLTexturep->getTexelsInAtlas() ;
}
U32 LLGLTexture::getTexelsInGLTexture() const
{
- llassert(mGLTexturep.notNull()) ;
+ llassert(mGLTexturep.notNull()) ;
- return mGLTexturep->getTexelsInGLTexture() ;
+ return mGLTexturep->getTexelsInGLTexture() ;
}
BOOL LLGLTexture::isGLTextureCreated() const
{
- llassert(mGLTexturep.notNull()) ;
+ llassert(mGLTexturep.notNull()) ;
- return mGLTexturep->isGLTextureCreated() ;
+ return mGLTexturep->isGLTextureCreated() ;
}
S32 LLGLTexture::getDiscardLevelInAtlas() const
{
- llassert(mGLTexturep.notNull()) ;
+ llassert(mGLTexturep.notNull()) ;
- return mGLTexturep->getDiscardLevelInAtlas() ;
+ return mGLTexturep->getDiscardLevelInAtlas() ;
}
-void LLGLTexture::destroyGLTexture()
+void LLGLTexture::destroyGLTexture()
{
- if(mGLTexturep.notNull() && mGLTexturep->getHasGLTexture())
- {
- mGLTexturep->destroyGLTexture() ;
- mTextureState = DELETED ;
- }
+ if(mGLTexturep.notNull() && mGLTexturep->getHasGLTexture())
+ {
+ mGLTexturep->destroyGLTexture() ;
+ mTextureState = DELETED ;
+ }
}
void LLGLTexture::setTexelsPerImage()
{
- U32 fullwidth = llmin(mFullWidth,U32(MAX_IMAGE_SIZE_DEFAULT));
- U32 fullheight = llmin(mFullHeight,U32(MAX_IMAGE_SIZE_DEFAULT));
- mTexelsPerImage = (U32)fullwidth * fullheight;
+ U32 fullwidth = llmin(mFullWidth,U32(MAX_IMAGE_SIZE_DEFAULT));
+ U32 fullheight = llmin(mFullHeight,U32(MAX_IMAGE_SIZE_DEFAULT));
+ mTexelsPerImage = (U32)fullwidth * fullheight;
}
static LLUUID sStubUUID;
diff --git a/indra/llrender/llgltexture.h b/indra/llrender/llgltexture.h
index 24849d1d1b..88057d7920 100644
--- a/indra/llrender/llgltexture.h
+++ b/indra/llrender/llgltexture.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file llgltexture.h
* @brief Object for managing opengl textures
*
* $LicenseInfo:firstyear=2012&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -40,86 +40,86 @@ class LLImageRaw;
class LLGLTexture : public LLTexture
{
public:
- enum
- {
- MAX_IMAGE_SIZE_DEFAULT = 1024,
- INVALID_DISCARD_LEVEL = 0x7fff
- };
-
- enum EBoostLevel
- {
- BOOST_NONE = 0,
- BOOST_AVATAR ,
+ enum
+ {
+ MAX_IMAGE_SIZE_DEFAULT = 1024,
+ INVALID_DISCARD_LEVEL = 0x7fff
+ };
+
+ enum EBoostLevel
+ {
+ BOOST_NONE = 0,
+ BOOST_AVATAR ,
BOOST_AVATAR_BAKED ,
- BOOST_SCULPTED ,
-
- BOOST_HIGH = 10,
- BOOST_BUMP ,
- BOOST_TERRAIN , // has to be high priority for minimap / low detail
- BOOST_SELECTED ,
- BOOST_AVATAR_BAKED_SELF ,
- BOOST_AVATAR_SELF , // needed for baking avatar
- BOOST_SUPER_HIGH , //textures higher than this need to be downloaded at the required resolution without delay.
- BOOST_HUD ,
- BOOST_ICON ,
- BOOST_THUMBNAIL ,
- BOOST_UI ,
- BOOST_PREVIEW ,
- BOOST_MAP ,
- BOOST_MAP_VISIBLE ,
- BOOST_MAX_LEVEL,
-
- //other texture Categories
- LOCAL = BOOST_MAX_LEVEL,
- AVATAR_SCRATCH_TEX,
- DYNAMIC_TEX,
- MEDIA,
- ATLAS,
- OTHER,
- MAX_GL_IMAGE_CATEGORY
- };
-
- typedef enum
- {
- DELETED = 0, //removed from memory
- DELETION_CANDIDATE, //ready to be removed from memory
- INACTIVE, //not be used for the last certain period (i.e., 30 seconds).
- ACTIVE, //just being used, can become inactive if not being used for a certain time (10 seconds).
- NO_DELETE = 99 //stay in memory, can not be removed.
- } LLGLTextureState;
+ BOOST_SCULPTED ,
+
+ BOOST_HIGH = 10,
+ BOOST_BUMP ,
+ BOOST_TERRAIN , // has to be high priority for minimap / low detail
+ BOOST_SELECTED ,
+ BOOST_AVATAR_BAKED_SELF ,
+ BOOST_AVATAR_SELF , // needed for baking avatar
+ BOOST_SUPER_HIGH , //textures higher than this need to be downloaded at the required resolution without delay.
+ BOOST_HUD ,
+ BOOST_ICON ,
+ BOOST_THUMBNAIL ,
+ BOOST_UI ,
+ BOOST_PREVIEW ,
+ BOOST_MAP ,
+ BOOST_MAP_VISIBLE ,
+ BOOST_MAX_LEVEL,
+
+ //other texture Categories
+ LOCAL = BOOST_MAX_LEVEL,
+ AVATAR_SCRATCH_TEX,
+ DYNAMIC_TEX,
+ MEDIA,
+ ATLAS,
+ OTHER,
+ MAX_GL_IMAGE_CATEGORY
+ };
+
+ typedef enum
+ {
+ DELETED = 0, //removed from memory
+ DELETION_CANDIDATE, //ready to be removed from memory
+ INACTIVE, //not be used for the last certain period (i.e., 30 seconds).
+ ACTIVE, //just being used, can become inactive if not being used for a certain time (10 seconds).
+ NO_DELETE = 99 //stay in memory, can not be removed.
+ } LLGLTextureState;
protected:
- virtual ~LLGLTexture();
- LOG_CLASS(LLGLTexture);
+ virtual ~LLGLTexture();
+ LOG_CLASS(LLGLTexture);
public:
- LLGLTexture(BOOL usemipmaps = TRUE);
- LLGLTexture(const LLImageRaw* raw, BOOL usemipmaps) ;
- LLGLTexture(const U32 width, const U32 height, const U8 components, BOOL usemipmaps) ;
+ LLGLTexture(BOOL usemipmaps = TRUE);
+ LLGLTexture(const LLImageRaw* raw, BOOL usemipmaps) ;
+ LLGLTexture(const U32 width, const U32 height, const U8 components, BOOL usemipmaps) ;
+
+ virtual void dump(); // debug info to LL_INFOS()
- virtual void dump(); // debug info to LL_INFOS()
+ virtual const LLUUID& getID() const;
- virtual const LLUUID& getID() const;
+ void setBoostLevel(S32 level);
+ S32 getBoostLevel() { return mBoostLevel; }
- void setBoostLevel(S32 level);
- S32 getBoostLevel() { return mBoostLevel; }
+ S32 getFullWidth() const { return mFullWidth; }
+ S32 getFullHeight() const { return mFullHeight; }
- S32 getFullWidth() const { return mFullWidth; }
- S32 getFullHeight() const { return mFullHeight; }
+ void generateGLTexture() ;
+ void destroyGLTexture() ;
- void generateGLTexture() ;
- void destroyGLTexture() ;
+ //---------------------------------------------------------------------------------------------
+ //functions to access LLImageGL
+ //---------------------------------------------------------------------------------------------
+ /*virtual*/S32 getWidth(S32 discard_level = -1) const;
+ /*virtual*/S32 getHeight(S32 discard_level = -1) const;
- //---------------------------------------------------------------------------------------------
- //functions to access LLImageGL
- //---------------------------------------------------------------------------------------------
- /*virtual*/S32 getWidth(S32 discard_level = -1) const;
- /*virtual*/S32 getHeight(S32 discard_level = -1) const;
+ BOOL hasGLTexture() const ;
+ LLGLuint getTexName() const ;
+ BOOL createGLTexture() ;
- BOOL hasGLTexture() const ;
- LLGLuint getTexName() const ;
- BOOL createGLTexture() ;
-
// Create a GL Texture from an image raw
// discard_level - mip level, 0 for highest resultion mip
// imageraw - the image to copy from
@@ -130,74 +130,74 @@ public:
// tex_name - if not null, will be set to the GL name of the texture created
BOOL createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename = 0, BOOL to_create = TRUE, S32 category = LLGLTexture::OTHER, bool defer_copy = false, LLGLuint* tex_name = nullptr);
- void setFilteringOption(LLTexUnit::eTextureFilterOptions option);
- void setExplicitFormat(LLGLint internal_format, LLGLenum primary_format, LLGLenum type_format = 0, BOOL swap_bytes = FALSE);
- void setAddressMode(LLTexUnit::eTextureAddressMode mode);
- BOOL setSubImage(const LLImageRaw* imageraw, S32 x_pos, S32 y_pos, S32 width, S32 height, LLGLuint use_name = 0);
- BOOL setSubImage(const U8* datap, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height, LLGLuint use_name = 0);
- void setGLTextureCreated (bool initialized);
- void setCategory(S32 category) ;
+ void setFilteringOption(LLTexUnit::eTextureFilterOptions option);
+ void setExplicitFormat(LLGLint internal_format, LLGLenum primary_format, LLGLenum type_format = 0, BOOL swap_bytes = FALSE);
+ void setAddressMode(LLTexUnit::eTextureAddressMode mode);
+ BOOL setSubImage(const LLImageRaw* imageraw, S32 x_pos, S32 y_pos, S32 width, S32 height, LLGLuint use_name = 0);
+ BOOL setSubImage(const U8* datap, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height, LLGLuint use_name = 0);
+ void setGLTextureCreated (bool initialized);
+ void setCategory(S32 category) ;
void setTexName(LLGLuint); // for forcing w/ externally created textures only
void setTarget(const LLGLenum target, const LLTexUnit::eTextureType bind_target);
- LLTexUnit::eTextureAddressMode getAddressMode(void) const ;
- S32 getMaxDiscardLevel() const;
- S32 getDiscardLevel() const;
- S8 getComponents() const;
- BOOL getBoundRecently() const;
- S32Bytes getTextureMemory() const ;
- LLGLenum getPrimaryFormat() const;
- BOOL getIsAlphaMask() const ;
- LLTexUnit::eTextureType getTarget(void) const ;
- BOOL getMask(const LLVector2 &tc);
- F32 getTimePassedSinceLastBound();
- BOOL getMissed() const ;
- BOOL isJustBound()const ;
- void forceUpdateBindStats(void) const;
-
- U32 getTexelsInAtlas() const ;
- U32 getTexelsInGLTexture() const ;
- BOOL isGLTextureCreated() const ;
- S32 getDiscardLevelInAtlas() const ;
- LLGLTextureState getTextureState() const { return mTextureState; }
-
- //---------------------------------------------------------------------------------------------
- //end of functions to access LLImageGL
- //---------------------------------------------------------------------------------------------
-
- //-----------------
- /*virtual*/ void setActive() ;
- void forceActive() ;
- void setNoDelete() ;
- void dontDiscard() { mDontDiscard = 1; mTextureState = NO_DELETE; }
- BOOL getDontDiscard() const { return mDontDiscard; }
- //-----------------
+ LLTexUnit::eTextureAddressMode getAddressMode(void) const ;
+ S32 getMaxDiscardLevel() const;
+ S32 getDiscardLevel() const;
+ S8 getComponents() const;
+ BOOL getBoundRecently() const;
+ S32Bytes getTextureMemory() const ;
+ LLGLenum getPrimaryFormat() const;
+ BOOL getIsAlphaMask() const ;
+ LLTexUnit::eTextureType getTarget(void) const ;
+ BOOL getMask(const LLVector2 &tc);
+ F32 getTimePassedSinceLastBound();
+ BOOL getMissed() const ;
+ BOOL isJustBound()const ;
+ void forceUpdateBindStats(void) const;
+
+ U32 getTexelsInAtlas() const ;
+ U32 getTexelsInGLTexture() const ;
+ BOOL isGLTextureCreated() const ;
+ S32 getDiscardLevelInAtlas() const ;
+ LLGLTextureState getTextureState() const { return mTextureState; }
+
+ //---------------------------------------------------------------------------------------------
+ //end of functions to access LLImageGL
+ //---------------------------------------------------------------------------------------------
+
+ //-----------------
+ /*virtual*/ void setActive() ;
+ void forceActive() ;
+ void setNoDelete() ;
+ void dontDiscard() { mDontDiscard = 1; mTextureState = NO_DELETE; }
+ BOOL getDontDiscard() const { return mDontDiscard; }
+ //-----------------
private:
- void cleanup();
- void init();
+ void cleanup();
+ void init();
protected:
- void setTexelsPerImage();
+ void setTexelsPerImage();
public:
- /*virtual*/ LLImageGL* getGLTexture() const ;
+ /*virtual*/ LLImageGL* getGLTexture() const ;
protected:
- S32 mBoostLevel; // enum describing priority level
- U32 mFullWidth;
- U32 mFullHeight;
- BOOL mUseMipMaps;
- S8 mComponents;
- U32 mTexelsPerImage; // Texels per image.
- mutable S8 mNeedsGLTexture;
-
- //GL texture
- LLPointer<LLImageGL> mGLTexturep ;
- S8 mDontDiscard; // Keep full res version of this image (for UI, etc)
+ S32 mBoostLevel; // enum describing priority level
+ U32 mFullWidth;
+ U32 mFullHeight;
+ BOOL mUseMipMaps;
+ S8 mComponents;
+ U32 mTexelsPerImage; // Texels per image.
+ mutable S8 mNeedsGLTexture;
+
+ //GL texture
+ LLPointer<LLImageGL> mGLTexturep ;
+ S8 mDontDiscard; // Keep full res version of this image (for UI, etc)
protected:
- LLGLTextureState mTextureState ;
+ LLGLTextureState mTextureState ;
};
diff --git a/indra/llrender/llgltypes.h b/indra/llrender/llgltypes.h
index 6c217ef727..b593a0532f 100644
--- a/indra/llrender/llgltypes.h
+++ b/indra/llrender/llgltypes.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file llgltypes.h
* @brief LLGL definition
*
* $LicenseInfo:firstyear=2006&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp
index 56a12b07b1..1609afb7ef 100644
--- a/indra/llrender/llimagegl.cpp
+++ b/indra/llrender/llimagegl.cpp
@@ -1,25 +1,25 @@
-/**
+/**
* @file llimagegl.cpp
* @brief Generic GL image handler
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -114,7 +114,7 @@ static void free_cur_tex_image()
free_tex_image(texName);
}
-// static
+// static
U64 LLImageGL::getTextureBytesAllocated()
{
return sTextureBytes;
@@ -122,12 +122,12 @@ U64 LLImageGL::getTextureBytesAllocated()
//statics
-U32 LLImageGL::sUniqueCount = 0;
-U32 LLImageGL::sBindCount = 0;
-S32 LLImageGL::sCount = 0;
+U32 LLImageGL::sUniqueCount = 0;
+U32 LLImageGL::sBindCount = 0;
+S32 LLImageGL::sCount = 0;
-BOOL LLImageGL::sGlobalUseAnisotropic = FALSE;
-F32 LLImageGL::sLastFrameTime = 0.f;
+BOOL LLImageGL::sGlobalUseAnisotropic = FALSE;
+F32 LLImageGL::sLastFrameTime = 0.f;
BOOL LLImageGL::sAllowReadBackRaw = FALSE ;
LLImageGL* LLImageGL::sDefaultGLTexture = NULL ;
bool LLImageGL::sCompressTextures = false;
@@ -159,78 +159,78 @@ BOOL LLImageGL::sSkipAnalyzeAlpha;
//do not delete them even though they are not currently being used.
void check_all_images()
{
- for (std::set<LLImageGL*>::iterator iter = LLImageGL::sImageList.begin();
- iter != LLImageGL::sImageList.end(); iter++)
- {
- LLImageGL* glimage = *iter;
- if (glimage->getTexName() && glimage->isGLTextureCreated())
- {
- gGL.getTexUnit(0)->bind(glimage) ;
- glimage->checkTexSize() ;
- gGL.getTexUnit(0)->unbind(glimage->getTarget()) ;
- }
- }
+ for (std::set<LLImageGL*>::iterator iter = LLImageGL::sImageList.begin();
+ iter != LLImageGL::sImageList.end(); iter++)
+ {
+ LLImageGL* glimage = *iter;
+ if (glimage->getTexName() && glimage->isGLTextureCreated())
+ {
+ gGL.getTexUnit(0)->bind(glimage) ;
+ glimage->checkTexSize() ;
+ gGL.getTexUnit(0)->unbind(glimage->getTarget()) ;
+ }
+ }
}
void LLImageGL::checkTexSize(bool forced) const
{
- if ((forced || gDebugGL) && mTarget == GL_TEXTURE_2D)
- {
- {
- //check viewport
- GLint vp[4] ;
- glGetIntegerv(GL_VIEWPORT, vp) ;
- llcallstacks << "viewport: " << vp[0] << " : " << vp[1] << " : " << vp[2] << " : " << vp[3] << llcallstacksendl ;
- }
-
- GLint texname;
- glGetIntegerv(GL_TEXTURE_BINDING_2D, &texname);
- BOOL error = FALSE;
- if (texname != mTexName)
- {
- LL_INFOS() << "Bound: " << texname << " Should bind: " << mTexName << " Default: " << LLImageGL::sDefaultGLTexture->getTexName() << LL_ENDL;
-
- error = TRUE;
- if (gDebugSession)
- {
- gFailLog << "Invalid texture bound!" << std::endl;
- }
- else
- {
- LL_ERRS() << "Invalid texture bound!" << LL_ENDL;
- }
- }
- stop_glerror() ;
- LLGLint x = 0, y = 0 ;
- 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 ;
- }
- if(x != (mWidth >> mCurrentDiscardLevel) || y != (mHeight >> mCurrentDiscardLevel))
- {
- error = TRUE;
- if (gDebugSession)
- {
- gFailLog << "wrong texture size and discard level!" <<
- mWidth << " Height: " << mHeight << " Current Level: " << (S32)mCurrentDiscardLevel << std::endl;
- }
- else
- {
- LL_ERRS() << "wrong texture size and discard level: width: " <<
- mWidth << " Height: " << mHeight << " Current Level: " << (S32)mCurrentDiscardLevel << LL_ENDL ;
- }
- }
-
- if (error)
- {
- ll_fail("LLImageGL::checkTexSize failed.");
- }
- }
+ if ((forced || gDebugGL) && mTarget == GL_TEXTURE_2D)
+ {
+ {
+ //check viewport
+ GLint vp[4] ;
+ glGetIntegerv(GL_VIEWPORT, vp) ;
+ llcallstacks << "viewport: " << vp[0] << " : " << vp[1] << " : " << vp[2] << " : " << vp[3] << llcallstacksendl ;
+ }
+
+ GLint texname;
+ glGetIntegerv(GL_TEXTURE_BINDING_2D, &texname);
+ BOOL error = FALSE;
+ if (texname != mTexName)
+ {
+ LL_INFOS() << "Bound: " << texname << " Should bind: " << mTexName << " Default: " << LLImageGL::sDefaultGLTexture->getTexName() << LL_ENDL;
+
+ error = TRUE;
+ if (gDebugSession)
+ {
+ gFailLog << "Invalid texture bound!" << std::endl;
+ }
+ else
+ {
+ LL_ERRS() << "Invalid texture bound!" << LL_ENDL;
+ }
+ }
+ stop_glerror() ;
+ LLGLint x = 0, y = 0 ;
+ 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 ;
+ }
+ if(x != (mWidth >> mCurrentDiscardLevel) || y != (mHeight >> mCurrentDiscardLevel))
+ {
+ error = TRUE;
+ if (gDebugSession)
+ {
+ gFailLog << "wrong texture size and discard level!" <<
+ mWidth << " Height: " << mHeight << " Current Level: " << (S32)mCurrentDiscardLevel << std::endl;
+ }
+ else
+ {
+ LL_ERRS() << "wrong texture size and discard level: width: " <<
+ mWidth << " Height: " << mHeight << " Current Level: " << (S32)mCurrentDiscardLevel << LL_ENDL ;
+ }
+ }
+
+ if (error)
+ {
+ ll_fail("LLImageGL::checkTexSize failed.");
+ }
+ }
}
//end of debug functions
//**************************************************************************************
@@ -238,17 +238,17 @@ void LLImageGL::checkTexSize(bool forced) const
//----------------------------------------------------------------------------
BOOL is_little_endian()
{
- S32 a = 0x12345678;
+ S32 a = 0x12345678;
U8 *c = (U8*)(&a);
-
- return (*c == 0x78) ;
+
+ return (*c == 0x78) ;
}
-//static
+//static
void LLImageGL::initClass(LLWindow* window, S32 num_catagories, BOOL skip_analyze_alpha /* = false */, bool thread_texture_loads /* = false */, bool thread_media_updates /* = false */)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
- sSkipAnalyzeAlpha = skip_analyze_alpha;
+ sSkipAnalyzeAlpha = skip_analyze_alpha;
if (thread_texture_loads || thread_media_updates)
{
@@ -258,8 +258,8 @@ void LLImageGL::initClass(LLWindow* window, S32 num_catagories, BOOL skip_analyz
}
}
-//static
-void LLImageGL::cleanupClass()
+//static
+void LLImageGL::cleanupClass()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
LLImageGLThread::deleteSingleton();
@@ -271,23 +271,23 @@ S32 LLImageGL::dataFormatBits(S32 dataformat)
{
switch (dataformat)
{
- case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: return 4;
+ case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: return 4;
case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: return 4;
- case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: return 8;
+ case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: return 8;
case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT: return 8;
- case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: return 8;
+ case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: return 8;
case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: return 8;
- case GL_LUMINANCE: return 8;
- case GL_ALPHA: return 8;
+ case GL_LUMINANCE: return 8;
+ case GL_ALPHA: return 8;
case GL_RED: return 8;
- case GL_COLOR_INDEX: return 8;
- case GL_LUMINANCE_ALPHA: return 16;
- case GL_RGB: return 24;
- case GL_SRGB: return 24;
- case GL_RGB8: return 24;
- case GL_RGBA: return 32;
- case GL_SRGB_ALPHA: return 32;
- case GL_BGRA: return 32; // Used for QuickTime media textures on the Mac
+ case GL_COLOR_INDEX: return 8;
+ case GL_LUMINANCE_ALPHA: return 16;
+ case GL_RGB: return 24;
+ case GL_SRGB: return 24;
+ case GL_RGB8: return 24;
+ case GL_RGBA: return 32;
+ case GL_SRGB_ALPHA: return 32;
+ case GL_BGRA: return 32; // Used for QuickTime media textures on the Mac
case GL_DEPTH_COMPONENT: return 24;
default:
LL_ERRS() << "LLImageGL::Unknown format: " << dataformat << LL_ENDL;
@@ -312,36 +312,36 @@ S64 LLImageGL::dataFormatBytes(S32 dataformat, S32 width, S32 height)
default:
break;
}
- S64 bytes (((S64)width * (S64)height * (S64)dataFormatBits(dataformat)+7)>>3);
- S64 aligned = (bytes+3)&~3;
- return aligned;
+ S64 bytes (((S64)width * (S64)height * (S64)dataFormatBits(dataformat)+7)>>3);
+ S64 aligned = (bytes+3)&~3;
+ return aligned;
}
//static
S32 LLImageGL::dataFormatComponents(S32 dataformat)
{
- switch (dataformat)
- {
- case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: return 3;
- case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: return 3;
- case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: return 4;
- case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT: return 4;
- case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: return 4;
- case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: return 4;
- case GL_LUMINANCE: return 1;
- case GL_ALPHA: return 1;
+ switch (dataformat)
+ {
+ case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: return 3;
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: return 3;
+ case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: return 4;
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT: return 4;
+ case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: return 4;
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: return 4;
+ case GL_LUMINANCE: return 1;
+ case GL_ALPHA: return 1;
case GL_RED: return 1;
- case GL_COLOR_INDEX: return 1;
- case GL_LUMINANCE_ALPHA: return 2;
- case GL_RGB: return 3;
- case GL_SRGB: return 3;
- case GL_RGBA: return 4;
- case GL_SRGB_ALPHA: return 4;
- case GL_BGRA: return 4; // Used for QuickTime media textures on the Mac
- default:
- LL_ERRS() << "LLImageGL::Unknown format: " << dataformat << LL_ENDL;
- return 0;
- }
+ case GL_COLOR_INDEX: return 1;
+ case GL_LUMINANCE_ALPHA: return 2;
+ case GL_RGB: return 3;
+ case GL_SRGB: return 3;
+ case GL_RGBA: return 4;
+ case GL_SRGB_ALPHA: return 4;
+ case GL_BGRA: return 4; // Used for QuickTime media textures on the Mac
+ default:
+ LL_ERRS() << "LLImageGL::Unknown format: " << dataformat << LL_ENDL;
+ return 0;
+ }
}
//----------------------------------------------------------------------------
@@ -350,131 +350,131 @@ S32 LLImageGL::dataFormatComponents(S32 dataformat)
void LLImageGL::updateStats(F32 current_time)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
- sLastFrameTime = current_time;
+ sLastFrameTime = current_time;
}
//----------------------------------------------------------------------------
-//static
+//static
void LLImageGL::destroyGL(BOOL save_state)
{
- for (S32 stage = 0; stage < gGLManager.mNumTextureImageUnits; stage++)
- {
- gGL.getTexUnit(stage)->unbind(LLTexUnit::TT_TEXTURE);
- }
-
- sAllowReadBackRaw = true ;
- for (std::set<LLImageGL*>::iterator iter = sImageList.begin();
- iter != sImageList.end(); iter++)
- {
- LLImageGL* glimage = *iter;
- if (glimage->mTexName)
- {
- if (save_state && glimage->isGLTextureCreated() && glimage->mComponents)
- {
- glimage->mSaveData = new LLImageRaw;
- if(!glimage->readBackRaw(glimage->mCurrentDiscardLevel, glimage->mSaveData, false)) //necessary, keep it.
- {
- glimage->mSaveData = NULL ;
- }
- }
-
- glimage->destroyGLTexture();
- stop_glerror();
- }
- }
- sAllowReadBackRaw = false ;
-}
-
-//static
+ for (S32 stage = 0; stage < gGLManager.mNumTextureImageUnits; stage++)
+ {
+ gGL.getTexUnit(stage)->unbind(LLTexUnit::TT_TEXTURE);
+ }
+
+ sAllowReadBackRaw = true ;
+ for (std::set<LLImageGL*>::iterator iter = sImageList.begin();
+ iter != sImageList.end(); iter++)
+ {
+ LLImageGL* glimage = *iter;
+ if (glimage->mTexName)
+ {
+ if (save_state && glimage->isGLTextureCreated() && glimage->mComponents)
+ {
+ glimage->mSaveData = new LLImageRaw;
+ if(!glimage->readBackRaw(glimage->mCurrentDiscardLevel, glimage->mSaveData, false)) //necessary, keep it.
+ {
+ glimage->mSaveData = NULL ;
+ }
+ }
+
+ glimage->destroyGLTexture();
+ stop_glerror();
+ }
+ }
+ sAllowReadBackRaw = false ;
+}
+
+//static
void LLImageGL::restoreGL()
{
- for (std::set<LLImageGL*>::iterator iter = sImageList.begin();
- iter != sImageList.end(); iter++)
- {
- LLImageGL* glimage = *iter;
- if(glimage->getTexName())
- {
- LL_ERRS() << "tex name is not 0." << LL_ENDL ;
- }
- if (glimage->mSaveData.notNull())
- {
- if (glimage->getComponents() && glimage->mSaveData->getComponents())
- {
- glimage->createGLTexture(glimage->mCurrentDiscardLevel, glimage->mSaveData, 0, TRUE, glimage->getCategory());
- stop_glerror();
- }
- glimage->mSaveData = NULL; // deletes data
- }
- }
-}
-
-//static
+ for (std::set<LLImageGL*>::iterator iter = sImageList.begin();
+ iter != sImageList.end(); iter++)
+ {
+ LLImageGL* glimage = *iter;
+ if(glimage->getTexName())
+ {
+ LL_ERRS() << "tex name is not 0." << LL_ENDL ;
+ }
+ if (glimage->mSaveData.notNull())
+ {
+ if (glimage->getComponents() && glimage->mSaveData->getComponents())
+ {
+ glimage->createGLTexture(glimage->mCurrentDiscardLevel, glimage->mSaveData, 0, TRUE, glimage->getCategory());
+ stop_glerror();
+ }
+ glimage->mSaveData = NULL; // deletes data
+ }
+ }
+}
+
+//static
void LLImageGL::dirtyTexOptions()
{
- for (std::set<LLImageGL*>::iterator iter = sImageList.begin();
- iter != sImageList.end(); iter++)
- {
- LLImageGL* glimage = *iter;
- glimage->mTexOptionsDirty = true;
- stop_glerror();
- }
-
+ for (std::set<LLImageGL*>::iterator iter = sImageList.begin();
+ iter != sImageList.end(); iter++)
+ {
+ LLImageGL* glimage = *iter;
+ glimage->mTexOptionsDirty = true;
+ stop_glerror();
+ }
+
}
//----------------------------------------------------------------------------
//for server side use only.
-//static
+//static
BOOL LLImageGL::create(LLPointer<LLImageGL>& dest, BOOL usemipmaps)
{
- dest = new LLImageGL(usemipmaps);
- return TRUE;
+ dest = new LLImageGL(usemipmaps);
+ return TRUE;
}
//for server side use only.
BOOL LLImageGL::create(LLPointer<LLImageGL>& dest, U32 width, U32 height, U8 components, BOOL usemipmaps)
{
- dest = new LLImageGL(width, height, components, usemipmaps);
- return TRUE;
+ dest = new LLImageGL(width, height, components, usemipmaps);
+ return TRUE;
}
//for server side use only.
BOOL LLImageGL::create(LLPointer<LLImageGL>& dest, const LLImageRaw* imageraw, BOOL usemipmaps)
{
- dest = new LLImageGL(imageraw, usemipmaps);
- return TRUE;
+ dest = new LLImageGL(imageraw, usemipmaps);
+ return TRUE;
}
//----------------------------------------------------------------------------
LLImageGL::LLImageGL(BOOL usemipmaps)
-: mSaveData(0), mExternalTexture(FALSE)
+: mSaveData(0), mExternalTexture(FALSE)
{
- init(usemipmaps);
- setSize(0, 0, 0);
- sImageList.insert(this);
- sCount++;
+ init(usemipmaps);
+ setSize(0, 0, 0);
+ sImageList.insert(this);
+ sCount++;
}
LLImageGL::LLImageGL(U32 width, U32 height, U8 components, BOOL usemipmaps)
-: mSaveData(0), mExternalTexture(FALSE)
+: mSaveData(0), mExternalTexture(FALSE)
{
- llassert( components <= 4 );
- init(usemipmaps);
- setSize(width, height, components);
- sImageList.insert(this);
- sCount++;
+ llassert( components <= 4 );
+ init(usemipmaps);
+ setSize(width, height, components);
+ sImageList.insert(this);
+ sCount++;
}
LLImageGL::LLImageGL(const LLImageRaw* imageraw, BOOL usemipmaps)
-: mSaveData(0), mExternalTexture(FALSE)
+: mSaveData(0), mExternalTexture(FALSE)
{
- init(usemipmaps);
- setSize(0, 0, 0);
- sImageList.insert(this);
- sCount++;
+ init(usemipmaps);
+ setSize(0, 0, 0);
+ sImageList.insert(this);
+ sCount++;
- createGLTexture(0, imageraw);
+ createGLTexture(0, imageraw);
}
LLImageGL::LLImageGL(
@@ -501,10 +501,10 @@ LLImageGL::~LLImageGL()
{
if (!mExternalTexture && gGLManager.mInited)
{
- LLImageGL::cleanup();
- sImageList.erase(this);
- freePickMask();
- sCount--;
+ LLImageGL::cleanup();
+ sImageList.erase(this);
+ freePickMask();
+ sCount--;
}
}
@@ -514,74 +514,74 @@ void LLImageGL::init(BOOL usemipmaps)
mActiveThread = LLThread::currentID();
#endif
- // keep these members in the same order as declared in llimagehl.h
- // so that it is obvious by visual inspection if we forgot to
- // init a field.
-
- mTextureMemory = S64Bytes(0);
- mLastBindTime = 0.f;
-
- mPickMask = NULL;
- mPickMaskWidth = 0;
- mPickMaskHeight = 0;
- mUseMipMaps = usemipmaps;
- mHasExplicitFormat = FALSE;
-
- mIsMask = FALSE;
- mNeedsAlphaAndPickMask = TRUE ;
- mAlphaStride = 0 ;
- mAlphaOffset = 0 ;
-
- mGLTextureCreated = FALSE ;
- mTexName = 0;
- mWidth = 0;
- mHeight = 0;
- mCurrentDiscardLevel = -1;
-
- mDiscardLevelInAtlas = -1 ;
- mTexelsInAtlas = 0 ;
- mTexelsInGLTexture = 0 ;
-
- mAllowCompression = true;
-
- mTarget = GL_TEXTURE_2D;
- mBindTarget = LLTexUnit::TT_TEXTURE;
- mHasMipMaps = false;
- mMipLevels = -1;
-
- mIsResident = 0;
-
- mComponents = 0;
- mMaxDiscardLevel = MAX_DISCARD_LEVEL;
-
- mTexOptionsDirty = true;
- mAddressMode = LLTexUnit::TAM_WRAP;
- mFilterOption = LLTexUnit::TFO_ANISOTROPIC;
-
- mFormatInternal = -1;
- mFormatPrimary = (LLGLenum) 0;
- mFormatType = GL_UNSIGNED_BYTE;
- mFormatSwapBytes = FALSE;
+ // keep these members in the same order as declared in llimagehl.h
+ // so that it is obvious by visual inspection if we forgot to
+ // init a field.
+
+ mTextureMemory = S64Bytes(0);
+ mLastBindTime = 0.f;
+
+ mPickMask = NULL;
+ mPickMaskWidth = 0;
+ mPickMaskHeight = 0;
+ mUseMipMaps = usemipmaps;
+ mHasExplicitFormat = FALSE;
+
+ mIsMask = FALSE;
+ mNeedsAlphaAndPickMask = TRUE ;
+ mAlphaStride = 0 ;
+ mAlphaOffset = 0 ;
+
+ mGLTextureCreated = FALSE ;
+ mTexName = 0;
+ mWidth = 0;
+ mHeight = 0;
+ mCurrentDiscardLevel = -1;
+
+ mDiscardLevelInAtlas = -1 ;
+ mTexelsInAtlas = 0 ;
+ mTexelsInGLTexture = 0 ;
+
+ mAllowCompression = true;
+
+ mTarget = GL_TEXTURE_2D;
+ mBindTarget = LLTexUnit::TT_TEXTURE;
+ mHasMipMaps = false;
+ mMipLevels = -1;
+
+ mIsResident = 0;
+
+ mComponents = 0;
+ mMaxDiscardLevel = MAX_DISCARD_LEVEL;
+
+ mTexOptionsDirty = true;
+ mAddressMode = LLTexUnit::TAM_WRAP;
+ mFilterOption = LLTexUnit::TFO_ANISOTROPIC;
+
+ mFormatInternal = -1;
+ mFormatPrimary = (LLGLenum) 0;
+ mFormatType = GL_UNSIGNED_BYTE;
+ mFormatSwapBytes = FALSE;
#ifdef DEBUG_MISS
- mMissed = FALSE;
+ mMissed = FALSE;
#endif
- mCategory = -1;
+ mCategory = -1;
- // Sometimes we have to post work for the main thread.
- mMainQueue = LL::WorkQueue::getInstance("mainloop");
+ // Sometimes we have to post work for the main thread.
+ mMainQueue = LL::WorkQueue::getInstance("mainloop");
}
void LLImageGL::cleanup()
{
- if (!gGLManager.mIsDisabled)
- {
- destroyGLTexture();
- }
- freePickMask();
+ if (!gGLManager.mIsDisabled)
+ {
+ destroyGLTexture();
+ }
+ freePickMask();
- mSaveData = NULL; // deletes data
+ mSaveData = NULL; // deletes data
}
//----------------------------------------------------------------------------
@@ -590,62 +590,62 @@ void LLImageGL::cleanup()
//so dim should be a positive number
static bool check_power_of_two(S32 dim)
{
- if(dim < 0)
- {
- return false ;
- }
- if(!dim)//0 is a power-of-two number
- {
- return true ;
- }
- return !(dim & (dim - 1)) ;
+ if(dim < 0)
+ {
+ return false ;
+ }
+ if(!dim)//0 is a power-of-two number
+ {
+ return true ;
+ }
+ return !(dim & (dim - 1)) ;
}
//static
bool LLImageGL::checkSize(S32 width, S32 height)
{
- return check_power_of_two(width) && check_power_of_two(height);
+ return check_power_of_two(width) && check_power_of_two(height);
}
bool LLImageGL::setSize(S32 width, S32 height, S32 ncomponents, S32 discard_level)
{
- if (width != mWidth || height != mHeight || ncomponents != mComponents)
- {
- // Check if dimensions are a power of two!
- if (!checkSize(width, height))
- {
- LL_WARNS() << llformat("Texture has non power of two dimension: %dx%d",width,height) << LL_ENDL;
- return false;
- }
-
- // pickmask validity depends on old image size, delete it
- freePickMask();
-
- mWidth = width;
- mHeight = height;
- mComponents = ncomponents;
- if (ncomponents > 0)
- {
- mMaxDiscardLevel = 0;
- while (width > 1 && height > 1 && mMaxDiscardLevel < MAX_DISCARD_LEVEL)
- {
- mMaxDiscardLevel++;
- width >>= 1;
- height >>= 1;
- }
-
- if(discard_level > 0)
- {
- mMaxDiscardLevel = llmax(mMaxDiscardLevel, (S8)discard_level);
- }
- }
- else
- {
- mMaxDiscardLevel = MAX_DISCARD_LEVEL;
- }
- }
-
- return true;
+ if (width != mWidth || height != mHeight || ncomponents != mComponents)
+ {
+ // Check if dimensions are a power of two!
+ if (!checkSize(width, height))
+ {
+ LL_WARNS() << llformat("Texture has non power of two dimension: %dx%d",width,height) << LL_ENDL;
+ return false;
+ }
+
+ // pickmask validity depends on old image size, delete it
+ freePickMask();
+
+ mWidth = width;
+ mHeight = height;
+ mComponents = ncomponents;
+ if (ncomponents > 0)
+ {
+ mMaxDiscardLevel = 0;
+ while (width > 1 && height > 1 && mMaxDiscardLevel < MAX_DISCARD_LEVEL)
+ {
+ mMaxDiscardLevel++;
+ width >>= 1;
+ height >>= 1;
+ }
+
+ if(discard_level > 0)
+ {
+ mMaxDiscardLevel = llmax(mMaxDiscardLevel, (S8)discard_level);
+ }
+ }
+ else
+ {
+ mMaxDiscardLevel = MAX_DISCARD_LEVEL;
+ }
+ }
+
+ return true;
}
//----------------------------------------------------------------------------
@@ -653,74 +653,74 @@ bool LLImageGL::setSize(S32 width, S32 height, S32 ncomponents, S32 discard_leve
// virtual
void LLImageGL::dump()
{
- LL_INFOS() << "mMaxDiscardLevel " << S32(mMaxDiscardLevel)
- << " mLastBindTime " << mLastBindTime
- << " mTarget " << S32(mTarget)
- << " mBindTarget " << S32(mBindTarget)
- << " mUseMipMaps " << S32(mUseMipMaps)
- << " mHasMipMaps " << S32(mHasMipMaps)
- << " mCurrentDiscardLevel " << S32(mCurrentDiscardLevel)
- << " mFormatInternal " << S32(mFormatInternal)
- << " mFormatPrimary " << S32(mFormatPrimary)
- << " mFormatType " << S32(mFormatType)
- << " mFormatSwapBytes " << S32(mFormatSwapBytes)
- << " mHasExplicitFormat " << S32(mHasExplicitFormat)
+ LL_INFOS() << "mMaxDiscardLevel " << S32(mMaxDiscardLevel)
+ << " mLastBindTime " << mLastBindTime
+ << " mTarget " << S32(mTarget)
+ << " mBindTarget " << S32(mBindTarget)
+ << " mUseMipMaps " << S32(mUseMipMaps)
+ << " mHasMipMaps " << S32(mHasMipMaps)
+ << " mCurrentDiscardLevel " << S32(mCurrentDiscardLevel)
+ << " mFormatInternal " << S32(mFormatInternal)
+ << " mFormatPrimary " << S32(mFormatPrimary)
+ << " mFormatType " << S32(mFormatType)
+ << " mFormatSwapBytes " << S32(mFormatSwapBytes)
+ << " mHasExplicitFormat " << S32(mHasExplicitFormat)
#if DEBUG_MISS
- << " mMissed " << mMissed
+ << " mMissed " << mMissed
#endif
- << LL_ENDL;
+ << LL_ENDL;
- LL_INFOS() << " mTextureMemory " << mTextureMemory
- << " mTexNames " << mTexName
- << " mIsResident " << S32(mIsResident)
- << LL_ENDL;
+ LL_INFOS() << " mTextureMemory " << mTextureMemory
+ << " mTexNames " << mTexName
+ << " mIsResident " << S32(mIsResident)
+ << LL_ENDL;
}
//----------------------------------------------------------------------------
void LLImageGL::forceUpdateBindStats(void) const
{
- mLastBindTime = sLastFrameTime;
+ mLastBindTime = sLastFrameTime;
}
BOOL LLImageGL::updateBindStats() const
-{
- if (mTexName != 0)
- {
+{
+ if (mTexName != 0)
+ {
#ifdef DEBUG_MISS
- mMissed = ! getIsResident(TRUE);
+ mMissed = ! getIsResident(TRUE);
#endif
- sBindCount++;
- if (mLastBindTime != sLastFrameTime)
- {
- // we haven't accounted for this texture yet this frame
- sUniqueCount++;
- mLastBindTime = sLastFrameTime;
+ sBindCount++;
+ if (mLastBindTime != sLastFrameTime)
+ {
+ // we haven't accounted for this texture yet this frame
+ sUniqueCount++;
+ mLastBindTime = sLastFrameTime;
- return TRUE ;
- }
- }
- return FALSE ;
+ return TRUE ;
+ }
+ }
+ return FALSE ;
}
F32 LLImageGL::getTimePassedSinceLastBound()
{
- return sLastFrameTime - mLastBindTime ;
+ return sLastFrameTime - mLastBindTime ;
}
void LLImageGL::setExplicitFormat( LLGLint internal_format, LLGLenum primary_format, LLGLenum type_format, BOOL swap_bytes )
{
- // Note: must be called before createTexture()
- // Note: it's up to the caller to ensure that the format matches the number of components.
- mHasExplicitFormat = TRUE;
- mFormatInternal = internal_format;
- mFormatPrimary = primary_format;
- if(type_format == 0)
- mFormatType = GL_UNSIGNED_BYTE;
- else
- mFormatType = type_format;
- mFormatSwapBytes = swap_bytes;
+ // Note: must be called before createTexture()
+ // Note: it's up to the caller to ensure that the format matches the number of components.
+ mHasExplicitFormat = TRUE;
+ mFormatInternal = internal_format;
+ mFormatPrimary = primary_format;
+ if(type_format == 0)
+ mFormatType = GL_UNSIGNED_BYTE;
+ else
+ mFormatType = type_format;
+ mFormatSwapBytes = swap_bytes;
- calcAlphaChannelOffsetAndStride() ;
+ calcAlphaChannelOffsetAndStride() ;
}
//----------------------------------------------------------------------------
@@ -728,33 +728,33 @@ void LLImageGL::setExplicitFormat( LLGLint internal_format, LLGLenum primary_for
void LLImageGL::setImage(const LLImageRaw* imageraw)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
- llassert((imageraw->getWidth() == getWidth(mCurrentDiscardLevel)) &&
- (imageraw->getHeight() == getHeight(mCurrentDiscardLevel)) &&
- (imageraw->getComponents() == getComponents()));
- const U8* rawdata = imageraw->getData();
- setImage(rawdata, FALSE);
+ llassert((imageraw->getWidth() == getWidth(mCurrentDiscardLevel)) &&
+ (imageraw->getHeight() == getHeight(mCurrentDiscardLevel)) &&
+ (imageraw->getComponents() == getComponents()));
+ const U8* rawdata = imageraw->getData();
+ setImage(rawdata, FALSE);
}
BOOL LLImageGL::setImage(const U8* data_in, BOOL data_hasmips /* = FALSE */, S32 usename /* = 0 */)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
- const bool is_compressed = isCompressed();
-
- if (mUseMipMaps)
- {
- //set has mip maps to true before binding image so tex parameters get set properly
+ const bool is_compressed = isCompressed();
+
+ if (mUseMipMaps)
+ {
+ //set has mip maps to true before binding image so tex parameters get set properly
gGL.getTexUnit(0)->unbind(mBindTarget);
-
- mHasMipMaps = true;
- mTexOptionsDirty = true;
- setFilteringOption(LLTexUnit::TFO_ANISOTROPIC);
- }
- else
- {
- mHasMipMaps = false;
- }
-
+
+ mHasMipMaps = true;
+ mTexOptionsDirty = true;
+ setFilteringOption(LLTexUnit::TFO_ANISOTROPIC);
+ }
+ else
+ {
+ mHasMipMaps = false;
+ }
+
gGL.getTexUnit(0)->bind(this, false, false, usename);
if (data_in == nullptr)
@@ -765,291 +765,291 @@ BOOL LLImageGL::setImage(const U8* data_in, BOOL data_hasmips /* = FALSE */, S32
mFormatPrimary, mFormatType, (GLvoid*)data_in, mAllowCompression);
}
else if (mUseMipMaps)
- {
- if (data_hasmips)
- {
- // NOTE: data_in points to largest image; smaller images
- // are stored BEFORE the largest image
- for (S32 d=mCurrentDiscardLevel; d<=mMaxDiscardLevel; d++)
- {
-
- S32 w = getWidth(d);
- S32 h = getHeight(d);
- S32 gl_level = d-mCurrentDiscardLevel;
-
- mMipLevels = llmax(mMipLevels, gl_level);
-
- if (d > mCurrentDiscardLevel)
- {
- data_in -= dataFormatBytes(mFormatPrimary, w, h); // see above comment
- }
- if (is_compressed)
- {
- S32 tex_size = dataFormatBytes(mFormatPrimary, w, h);
- glCompressedTexImage2D(mTarget, gl_level, mFormatPrimary, w, h, 0, tex_size, (GLvoid *)data_in);
- stop_glerror();
- }
- else
- {
- if(mFormatSwapBytes)
- {
- glPixelStorei(GL_UNPACK_SWAP_BYTES, 1);
- stop_glerror();
- }
-
- LLImageGL::setManualImage(mTarget, gl_level, mFormatInternal, w, h, mFormatPrimary, GL_UNSIGNED_BYTE, (GLvoid*)data_in, mAllowCompression);
- if (gl_level == 0)
- {
- analyzeAlpha(data_in, w, h);
- }
- updatePickMask(w, h, data_in);
-
- if(mFormatSwapBytes)
- {
- glPixelStorei(GL_UNPACK_SWAP_BYTES, 0);
- stop_glerror();
- }
-
- stop_glerror();
- }
- stop_glerror();
- }
- }
- else if (!is_compressed)
- {
- if (mAutoGenMips)
- {
- stop_glerror();
- {
- if(mFormatSwapBytes)
- {
- glPixelStorei(GL_UNPACK_SWAP_BYTES, 1);
- stop_glerror();
- }
-
- S32 w = getWidth(mCurrentDiscardLevel);
- S32 h = getHeight(mCurrentDiscardLevel);
-
- mMipLevels = wpo2(llmax(w, h));
-
- //use legacy mipmap generation mode (note: making this condional can cause rendering issues)
- // -- but making it not conditional triggers deprecation warnings when core profile is enabled
- // (some rendering issues while core profile is enabled are acceptable at this point in time)
- if (!LLRender::sGLCoreProfile)
- {
- glTexParameteri(mTarget, GL_GENERATE_MIPMAP, GL_TRUE);
- }
+ {
+ if (data_hasmips)
+ {
+ // NOTE: data_in points to largest image; smaller images
+ // are stored BEFORE the largest image
+ for (S32 d=mCurrentDiscardLevel; d<=mMaxDiscardLevel; d++)
+ {
+
+ S32 w = getWidth(d);
+ S32 h = getHeight(d);
+ S32 gl_level = d-mCurrentDiscardLevel;
+
+ mMipLevels = llmax(mMipLevels, gl_level);
+
+ if (d > mCurrentDiscardLevel)
+ {
+ data_in -= dataFormatBytes(mFormatPrimary, w, h); // see above comment
+ }
+ if (is_compressed)
+ {
+ S32 tex_size = dataFormatBytes(mFormatPrimary, w, h);
+ glCompressedTexImage2D(mTarget, gl_level, mFormatPrimary, w, h, 0, tex_size, (GLvoid *)data_in);
+ stop_glerror();
+ }
+ else
+ {
+ if(mFormatSwapBytes)
+ {
+ glPixelStorei(GL_UNPACK_SWAP_BYTES, 1);
+ stop_glerror();
+ }
+
+ LLImageGL::setManualImage(mTarget, gl_level, mFormatInternal, w, h, mFormatPrimary, GL_UNSIGNED_BYTE, (GLvoid*)data_in, mAllowCompression);
+ if (gl_level == 0)
+ {
+ analyzeAlpha(data_in, w, h);
+ }
+ updatePickMask(w, h, data_in);
+
+ if(mFormatSwapBytes)
+ {
+ glPixelStorei(GL_UNPACK_SWAP_BYTES, 0);
+ stop_glerror();
+ }
+
+ stop_glerror();
+ }
+ stop_glerror();
+ }
+ }
+ else if (!is_compressed)
+ {
+ if (mAutoGenMips)
+ {
+ stop_glerror();
+ {
+ if(mFormatSwapBytes)
+ {
+ glPixelStorei(GL_UNPACK_SWAP_BYTES, 1);
+ stop_glerror();
+ }
+
+ S32 w = getWidth(mCurrentDiscardLevel);
+ S32 h = getHeight(mCurrentDiscardLevel);
+
+ mMipLevels = wpo2(llmax(w, h));
+
+ //use legacy mipmap generation mode (note: making this condional can cause rendering issues)
+ // -- but making it not conditional triggers deprecation warnings when core profile is enabled
+ // (some rendering issues while core profile is enabled are acceptable at this point in time)
+ if (!LLRender::sGLCoreProfile)
+ {
+ glTexParameteri(mTarget, GL_GENERATE_MIPMAP, GL_TRUE);
+ }
LLImageGL::setManualImage(mTarget, 0, mFormatInternal,
- w, h,
- mFormatPrimary, mFormatType,
- data_in, mAllowCompression);
- analyzeAlpha(data_in, w, h);
- stop_glerror();
-
- updatePickMask(w, h, data_in);
-
- if(mFormatSwapBytes)
- {
- glPixelStorei(GL_UNPACK_SWAP_BYTES, 0);
- stop_glerror();
- }
-
- if (LLRender::sGLCoreProfile)
- {
+ w, h,
+ mFormatPrimary, mFormatType,
+ data_in, mAllowCompression);
+ analyzeAlpha(data_in, w, h);
+ stop_glerror();
+
+ updatePickMask(w, h, data_in);
+
+ if(mFormatSwapBytes)
+ {
+ glPixelStorei(GL_UNPACK_SWAP_BYTES, 0);
+ stop_glerror();
+ }
+
+ if (LLRender::sGLCoreProfile)
+ {
LL_PROFILE_GPU_ZONE("generate mip map");
- glGenerateMipmap(mTarget);
- }
- stop_glerror();
- }
- }
- else
- {
- // Create mips by hand
- // ~4x faster than gluBuild2DMipmaps
- S32 width = getWidth(mCurrentDiscardLevel);
- S32 height = getHeight(mCurrentDiscardLevel);
- S32 nummips = mMaxDiscardLevel - mCurrentDiscardLevel + 1;
- S32 w = width, h = height;
-
-
- const U8* new_data = 0;
- (void)new_data;
-
- const U8* prev_mip_data = 0;
- const U8* cur_mip_data = 0;
+ glGenerateMipmap(mTarget);
+ }
+ stop_glerror();
+ }
+ }
+ else
+ {
+ // Create mips by hand
+ // ~4x faster than gluBuild2DMipmaps
+ S32 width = getWidth(mCurrentDiscardLevel);
+ S32 height = getHeight(mCurrentDiscardLevel);
+ S32 nummips = mMaxDiscardLevel - mCurrentDiscardLevel + 1;
+ S32 w = width, h = height;
+
+
+ const U8* new_data = 0;
+ (void)new_data;
+
+ const U8* prev_mip_data = 0;
+ const U8* cur_mip_data = 0;
#ifdef SHOW_ASSERT
- S32 cur_mip_size = 0;
+ S32 cur_mip_size = 0;
#endif
- mMipLevels = nummips;
+ mMipLevels = nummips;
- for (int m=0; m<nummips; m++)
- {
- if (m==0)
- {
- cur_mip_data = data_in;
+ for (int m=0; m<nummips; m++)
+ {
+ if (m==0)
+ {
+ cur_mip_data = data_in;
#ifdef SHOW_ASSERT
- cur_mip_size = width * height * mComponents;
+ cur_mip_size = width * height * mComponents;
#endif
- }
- else
- {
- S32 bytes = w * h * mComponents;
+ }
+ else
+ {
+ S32 bytes = w * h * mComponents;
#ifdef SHOW_ASSERT
- llassert(prev_mip_data);
- llassert(cur_mip_size == bytes*4);
+ llassert(prev_mip_data);
+ llassert(cur_mip_size == bytes*4);
#endif
- U8* new_data = new(std::nothrow) U8[bytes];
- if (!new_data)
- {
- stop_glerror();
-
- if (prev_mip_data)
- {
- if (prev_mip_data != cur_mip_data)
- delete[] prev_mip_data;
- prev_mip_data = nullptr;
- }
- if (cur_mip_data)
- {
- delete[] cur_mip_data;
- cur_mip_data = nullptr;
- }
-
- mGLTextureCreated = false;
- return FALSE;
- }
- else
- {
+ U8* new_data = new(std::nothrow) U8[bytes];
+ if (!new_data)
+ {
+ stop_glerror();
+
+ if (prev_mip_data)
+ {
+ if (prev_mip_data != cur_mip_data)
+ delete[] prev_mip_data;
+ prev_mip_data = nullptr;
+ }
+ if (cur_mip_data)
+ {
+ delete[] cur_mip_data;
+ cur_mip_data = nullptr;
+ }
+
+ mGLTextureCreated = false;
+ return FALSE;
+ }
+ else
+ {
#ifdef SHOW_ASSERT
- llassert(prev_mip_data);
- llassert(cur_mip_size == bytes * 4);
+ llassert(prev_mip_data);
+ llassert(cur_mip_size == bytes * 4);
#endif
- LLImageBase::generateMip(prev_mip_data, new_data, w, h, mComponents);
- cur_mip_data = new_data;
+ LLImageBase::generateMip(prev_mip_data, new_data, w, h, mComponents);
+ cur_mip_data = new_data;
#ifdef SHOW_ASSERT
- cur_mip_size = bytes;
+ cur_mip_size = bytes;
#endif
- }
-
- }
- llassert(w > 0 && h > 0 && cur_mip_data);
- (void)cur_mip_data;
- {
- if(mFormatSwapBytes)
- {
- glPixelStorei(GL_UNPACK_SWAP_BYTES, 1);
- stop_glerror();
- }
+ }
+
+ }
+ llassert(w > 0 && h > 0 && cur_mip_data);
+ (void)cur_mip_data;
+ {
+ if(mFormatSwapBytes)
+ {
+ glPixelStorei(GL_UNPACK_SWAP_BYTES, 1);
+ stop_glerror();
+ }
LLImageGL::setManualImage(mTarget, m, mFormatInternal, w, h, mFormatPrimary, mFormatType, cur_mip_data, mAllowCompression);
- if (m == 0)
- {
- analyzeAlpha(data_in, w, h);
- }
- stop_glerror();
- if (m == 0)
- {
- updatePickMask(w, h, cur_mip_data);
- }
-
- if(mFormatSwapBytes)
- {
- glPixelStorei(GL_UNPACK_SWAP_BYTES, 0);
- stop_glerror();
- }
- }
- if (prev_mip_data && prev_mip_data != data_in)
- {
- delete[] prev_mip_data;
- }
- prev_mip_data = cur_mip_data;
- w >>= 1;
- h >>= 1;
- }
- if (prev_mip_data && prev_mip_data != data_in)
- {
- delete[] prev_mip_data;
- prev_mip_data = NULL;
- }
- }
- }
- else
- {
- LL_ERRS() << "Compressed Image has mipmaps but data does not (can not auto generate compressed mips)" << LL_ENDL;
- }
- }
- else
- {
- mMipLevels = 0;
- S32 w = getWidth();
- S32 h = getHeight();
- if (is_compressed)
- {
- S32 tex_size = dataFormatBytes(mFormatPrimary, w, h);
- glCompressedTexImage2D(mTarget, 0, mFormatPrimary, w, h, 0, tex_size, (GLvoid *)data_in);
- stop_glerror();
- }
- else
- {
- if(mFormatSwapBytes)
- {
- glPixelStorei(GL_UNPACK_SWAP_BYTES, 1);
- stop_glerror();
- }
-
- LLImageGL::setManualImage(mTarget, 0, mFormatInternal, w, h,
- mFormatPrimary, mFormatType, (GLvoid *)data_in, mAllowCompression);
- analyzeAlpha(data_in, w, h);
-
- updatePickMask(w, h, data_in);
-
- stop_glerror();
-
- if(mFormatSwapBytes)
- {
- glPixelStorei(GL_UNPACK_SWAP_BYTES, 0);
- stop_glerror();
- }
-
- }
- }
- stop_glerror();
- mGLTextureCreated = true;
- return TRUE;
+ if (m == 0)
+ {
+ analyzeAlpha(data_in, w, h);
+ }
+ stop_glerror();
+ if (m == 0)
+ {
+ updatePickMask(w, h, cur_mip_data);
+ }
+
+ if(mFormatSwapBytes)
+ {
+ glPixelStorei(GL_UNPACK_SWAP_BYTES, 0);
+ stop_glerror();
+ }
+ }
+ if (prev_mip_data && prev_mip_data != data_in)
+ {
+ delete[] prev_mip_data;
+ }
+ prev_mip_data = cur_mip_data;
+ w >>= 1;
+ h >>= 1;
+ }
+ if (prev_mip_data && prev_mip_data != data_in)
+ {
+ delete[] prev_mip_data;
+ prev_mip_data = NULL;
+ }
+ }
+ }
+ else
+ {
+ LL_ERRS() << "Compressed Image has mipmaps but data does not (can not auto generate compressed mips)" << LL_ENDL;
+ }
+ }
+ else
+ {
+ mMipLevels = 0;
+ S32 w = getWidth();
+ S32 h = getHeight();
+ if (is_compressed)
+ {
+ S32 tex_size = dataFormatBytes(mFormatPrimary, w, h);
+ glCompressedTexImage2D(mTarget, 0, mFormatPrimary, w, h, 0, tex_size, (GLvoid *)data_in);
+ stop_glerror();
+ }
+ else
+ {
+ if(mFormatSwapBytes)
+ {
+ glPixelStorei(GL_UNPACK_SWAP_BYTES, 1);
+ stop_glerror();
+ }
+
+ LLImageGL::setManualImage(mTarget, 0, mFormatInternal, w, h,
+ mFormatPrimary, mFormatType, (GLvoid *)data_in, mAllowCompression);
+ analyzeAlpha(data_in, w, h);
+
+ updatePickMask(w, h, data_in);
+
+ stop_glerror();
+
+ if(mFormatSwapBytes)
+ {
+ glPixelStorei(GL_UNPACK_SWAP_BYTES, 0);
+ stop_glerror();
+ }
+
+ }
+ }
+ stop_glerror();
+ mGLTextureCreated = true;
+ return TRUE;
}
BOOL LLImageGL::preAddToAtlas(S32 discard_level, const LLImageRaw* raw_image)
{
- //not compatible with core GL profile
- llassert(!LLRender::sGLCoreProfile);
-
- if (gGLManager.mIsDisabled)
- {
- LL_WARNS() << "Trying to create a texture while GL is disabled!" << LL_ENDL;
- return FALSE;
- }
- llassert(gGLManager.mInited);
- stop_glerror();
-
- if (discard_level < 0)
- {
- llassert(mCurrentDiscardLevel >= 0);
- discard_level = mCurrentDiscardLevel;
- }
-
- // Actual image width/height = raw image width/height * 2^discard_level
- S32 w = raw_image->getWidth() << discard_level;
- S32 h = raw_image->getHeight() << discard_level;
-
- // setSize may call destroyGLTexture if the size does not match
- if (!setSize(w, h, raw_image->getComponents(), discard_level))
- {
- LL_WARNS() << "Trying to create a texture with incorrect dimensions!" << LL_ENDL;
- return FALSE;
- }
+ //not compatible with core GL profile
+ llassert(!LLRender::sGLCoreProfile);
+
+ if (gGLManager.mIsDisabled)
+ {
+ LL_WARNS() << "Trying to create a texture while GL is disabled!" << LL_ENDL;
+ return FALSE;
+ }
+ llassert(gGLManager.mInited);
+ stop_glerror();
+
+ if (discard_level < 0)
+ {
+ llassert(mCurrentDiscardLevel >= 0);
+ discard_level = mCurrentDiscardLevel;
+ }
+
+ // Actual image width/height = raw image width/height * 2^discard_level
+ S32 w = raw_image->getWidth() << discard_level;
+ S32 h = raw_image->getHeight() << discard_level;
+
+ // setSize may call destroyGLTexture if the size does not match
+ if (!setSize(w, h, raw_image->getComponents(), discard_level))
+ {
+ LL_WARNS() << "Trying to create a texture with incorrect dimensions!" << LL_ENDL;
+ return FALSE;
+ }
if (!mHasExplicitFormat)
{
@@ -1082,35 +1082,35 @@ BOOL LLImageGL::preAddToAtlas(S32 discard_level, const LLImageRaw* raw_image)
}
}
- mCurrentDiscardLevel = discard_level;
- mDiscardLevelInAtlas = discard_level;
- mTexelsInAtlas = raw_image->getWidth() * raw_image->getHeight() ;
- mLastBindTime = sLastFrameTime;
- mGLTextureCreated = false ;
-
- glPixelStorei(GL_UNPACK_ROW_LENGTH, raw_image->getWidth());
- stop_glerror();
+ mCurrentDiscardLevel = discard_level;
+ mDiscardLevelInAtlas = discard_level;
+ mTexelsInAtlas = raw_image->getWidth() * raw_image->getHeight() ;
+ mLastBindTime = sLastFrameTime;
+ mGLTextureCreated = false ;
+
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, raw_image->getWidth());
+ stop_glerror();
- if(mFormatSwapBytes)
- {
- glPixelStorei(GL_UNPACK_SWAP_BYTES, 1);
- stop_glerror();
- }
+ if(mFormatSwapBytes)
+ {
+ glPixelStorei(GL_UNPACK_SWAP_BYTES, 1);
+ stop_glerror();
+ }
- return TRUE ;
+ return TRUE ;
}
void LLImageGL::postAddToAtlas()
{
- if(mFormatSwapBytes)
- {
- glPixelStorei(GL_UNPACK_SWAP_BYTES, 0);
- stop_glerror();
- }
+ if(mFormatSwapBytes)
+ {
+ glPixelStorei(GL_UNPACK_SWAP_BYTES, 0);
+ stop_glerror();
+ }
- glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
- gGL.getTexUnit(0)->setTextureFilteringOption(mFilterOption);
- stop_glerror();
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
+ gGL.getTexUnit(0)->setTextureFilteringOption(mFilterOption);
+ stop_glerror();
}
U32 type_width_from_pixtype(U32 pixtype)
@@ -1170,82 +1170,82 @@ void sub_image_lines(U32 target, S32 miplevel, S32 x_offset, S32 y_offset, S32 w
BOOL LLImageGL::setSubImage(const U8* datap, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height, BOOL force_fast_update /* = FALSE */, LLGLuint use_name)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
- if (!width || !height)
- {
- return TRUE;
- }
+ if (!width || !height)
+ {
+ return TRUE;
+ }
LLGLuint tex_name = use_name != 0 ? use_name : mTexName;
- if (0 == tex_name)
- {
- // *TODO: Re-enable warning? Ran into thread locking issues? DK 2011-02-18
- //LL_WARNS() << "Setting subimage on image without GL texture" << LL_ENDL;
- return FALSE;
- }
- if (datap == NULL)
- {
- // *TODO: Re-enable warning? Ran into thread locking issues? DK 2011-02-18
- //LL_WARNS() << "Setting subimage on image with NULL datap" << LL_ENDL;
- return FALSE;
- }
-
- // HACK: allow the caller to explicitly force the fast path (i.e. using glTexSubImage2D here instead of calling setImage) even when updating the full texture.
- if (!force_fast_update && x_pos == 0 && y_pos == 0 && width == getWidth() && height == getHeight() && data_width == width && data_height == height)
- {
- setImage(datap, FALSE, tex_name);
- }
- else
- {
- if (mUseMipMaps)
- {
- dump();
- LL_ERRS() << "setSubImage called with mipmapped image (not supported)" << LL_ENDL;
- }
- llassert_always(mCurrentDiscardLevel == 0);
- llassert_always(x_pos >= 0 && y_pos >= 0);
-
- if (((x_pos + width) > getWidth()) ||
- (y_pos + height) > getHeight())
- {
- dump();
- LL_ERRS() << "Subimage not wholly in target image!"
- << " x_pos " << x_pos
- << " y_pos " << y_pos
- << " width " << width
- << " height " << height
- << " getWidth() " << getWidth()
- << " getHeight() " << getHeight()
- << LL_ENDL;
- }
-
- if ((x_pos + width) > data_width ||
- (y_pos + height) > data_height)
- {
- dump();
- LL_ERRS() << "Subimage not wholly in source image!"
- << " x_pos " << x_pos
- << " y_pos " << y_pos
- << " width " << width
- << " height " << height
- << " source_width " << data_width
- << " source_height " << data_height
- << LL_ENDL;
- }
-
-
- glPixelStorei(GL_UNPACK_ROW_LENGTH, data_width);
- stop_glerror();
-
- if(mFormatSwapBytes)
- {
- glPixelStorei(GL_UNPACK_SWAP_BYTES, 1);
- stop_glerror();
- }
-
- const U8* sub_datap = datap + (y_pos * data_width + x_pos) * getComponents();
- // Update the GL texture
- BOOL res = gGL.getTexUnit(0)->bindManual(mBindTarget, tex_name);
- if (!res) LL_ERRS() << "LLImageGL::setSubImage(): bindTexture failed" << LL_ENDL;
- stop_glerror();
+ if (0 == tex_name)
+ {
+ // *TODO: Re-enable warning? Ran into thread locking issues? DK 2011-02-18
+ //LL_WARNS() << "Setting subimage on image without GL texture" << LL_ENDL;
+ return FALSE;
+ }
+ if (datap == NULL)
+ {
+ // *TODO: Re-enable warning? Ran into thread locking issues? DK 2011-02-18
+ //LL_WARNS() << "Setting subimage on image with NULL datap" << LL_ENDL;
+ return FALSE;
+ }
+
+ // HACK: allow the caller to explicitly force the fast path (i.e. using glTexSubImage2D here instead of calling setImage) even when updating the full texture.
+ if (!force_fast_update && x_pos == 0 && y_pos == 0 && width == getWidth() && height == getHeight() && data_width == width && data_height == height)
+ {
+ setImage(datap, FALSE, tex_name);
+ }
+ else
+ {
+ if (mUseMipMaps)
+ {
+ dump();
+ LL_ERRS() << "setSubImage called with mipmapped image (not supported)" << LL_ENDL;
+ }
+ llassert_always(mCurrentDiscardLevel == 0);
+ llassert_always(x_pos >= 0 && y_pos >= 0);
+
+ if (((x_pos + width) > getWidth()) ||
+ (y_pos + height) > getHeight())
+ {
+ dump();
+ LL_ERRS() << "Subimage not wholly in target image!"
+ << " x_pos " << x_pos
+ << " y_pos " << y_pos
+ << " width " << width
+ << " height " << height
+ << " getWidth() " << getWidth()
+ << " getHeight() " << getHeight()
+ << LL_ENDL;
+ }
+
+ if ((x_pos + width) > data_width ||
+ (y_pos + height) > data_height)
+ {
+ dump();
+ LL_ERRS() << "Subimage not wholly in source image!"
+ << " x_pos " << x_pos
+ << " y_pos " << y_pos
+ << " width " << width
+ << " height " << height
+ << " source_width " << data_width
+ << " source_height " << data_height
+ << LL_ENDL;
+ }
+
+
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, data_width);
+ stop_glerror();
+
+ if(mFormatSwapBytes)
+ {
+ glPixelStorei(GL_UNPACK_SWAP_BYTES, 1);
+ stop_glerror();
+ }
+
+ const U8* sub_datap = datap + (y_pos * data_width + x_pos) * getComponents();
+ // Update the GL texture
+ BOOL res = gGL.getTexUnit(0)->bindManual(mBindTarget, tex_name);
+ if (!res) LL_ERRS() << "LLImageGL::setSubImage(): bindTexture failed" << LL_ENDL;
+ stop_glerror();
const bool use_sub_image = should_stagger_image_set(isCompressed());
if (!use_sub_image)
@@ -1260,42 +1260,42 @@ BOOL LLImageGL::setSubImage(const U8* datap, S32 data_width, S32 data_height, S3
{
sub_image_lines(mTarget, 0, x_pos, y_pos, width, height, mFormatPrimary, mFormatType, sub_datap, data_width);
}
- gGL.getTexUnit(0)->disable();
- stop_glerror();
+ gGL.getTexUnit(0)->disable();
+ stop_glerror();
- if(mFormatSwapBytes)
- {
- glPixelStorei(GL_UNPACK_SWAP_BYTES, 0);
- stop_glerror();
- }
+ if(mFormatSwapBytes)
+ {
+ glPixelStorei(GL_UNPACK_SWAP_BYTES, 0);
+ stop_glerror();
+ }
- glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
- stop_glerror();
- mGLTextureCreated = true;
- }
- return TRUE;
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
+ stop_glerror();
+ mGLTextureCreated = true;
+ }
+ return TRUE;
}
BOOL LLImageGL::setSubImage(const LLImageRaw* imageraw, S32 x_pos, S32 y_pos, S32 width, S32 height, BOOL force_fast_update /* = FALSE */, LLGLuint use_name)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
- return setSubImage(imageraw->getData(), imageraw->getWidth(), imageraw->getHeight(), x_pos, y_pos, width, height, force_fast_update, use_name);
+ return setSubImage(imageraw->getData(), imageraw->getWidth(), imageraw->getHeight(), x_pos, y_pos, width, height, force_fast_update, use_name);
}
// Copy sub image from frame buffer
BOOL LLImageGL::setSubImageFromFrameBuffer(S32 fb_x, S32 fb_y, S32 x_pos, S32 y_pos, S32 width, S32 height)
{
- if (gGL.getTexUnit(0)->bind(this, false, true))
- {
- glCopyTexSubImage2D(GL_TEXTURE_2D, 0, fb_x, fb_y, x_pos, y_pos, width, height);
- mGLTextureCreated = true;
- stop_glerror();
- return TRUE;
- }
- else
- {
- return FALSE;
- }
+ if (gGL.getTexUnit(0)->bind(this, false, true))
+ {
+ glCopyTexSubImage2D(GL_TEXTURE_2D, 0, fb_x, fb_y, x_pos, y_pos, width, height);
+ mGLTextureCreated = true;
+ stop_glerror();
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
}
// static
@@ -1330,11 +1330,11 @@ void LLImageGL::generateTextures(S32 numTextures, U32 *textures)
// static
void LLImageGL::deleteTextures(S32 numTextures, const U32 *textures)
{
- if (gGLManager.mInited)
- {
+ if (gGLManager.mInited)
+ {
free_tex_images(numTextures, textures);
- glDeleteTextures(numTextures, textures);
- }
+ glDeleteTextures(numTextures, textures);
+ }
}
// static
@@ -1516,33 +1516,33 @@ BOOL LLImageGL::createGLTexture()
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
checkActiveThread();
- if (gGLManager.mIsDisabled)
- {
- LL_WARNS() << "Trying to create a texture while GL is disabled!" << LL_ENDL;
- return FALSE;
- }
-
- mGLTextureCreated = false ; //do not save this texture when gl is destroyed.
+ if (gGLManager.mIsDisabled)
+ {
+ LL_WARNS() << "Trying to create a texture while GL is disabled!" << LL_ENDL;
+ return FALSE;
+ }
+
+ mGLTextureCreated = false ; //do not save this texture when gl is destroyed.
- llassert(gGLManager.mInited);
- stop_glerror();
+ llassert(gGLManager.mInited);
+ stop_glerror();
- if(mTexName)
- {
- LLImageGL::deleteTextures(1, (reinterpret_cast<GLuint*>(&mTexName))) ;
+ if(mTexName)
+ {
+ LLImageGL::deleteTextures(1, (reinterpret_cast<GLuint*>(&mTexName))) ;
mTexName = 0;
- }
-
+ }
- LLImageGL::generateTextures(1, &mTexName);
- stop_glerror();
- if (!mTexName)
- {
- LL_WARNS() << "LLImageGL::createGLTexture failed to make an empty texture" << LL_ENDL;
- return FALSE;
- }
- return TRUE ;
+ LLImageGL::generateTextures(1, &mTexName);
+ stop_glerror();
+ if (!mTexName)
+ {
+ LL_WARNS() << "LLImageGL::createGLTexture failed to make an empty texture" << LL_ENDL;
+ return FALSE;
+ }
+
+ return TRUE ;
}
BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename/*=0*/, BOOL to_create, S32 category, bool defer_copy, LLGLuint* tex_name)
@@ -1550,54 +1550,54 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
checkActiveThread();
- if (gGLManager.mIsDisabled)
- {
- LL_WARNS() << "Trying to create a texture while GL is disabled!" << LL_ENDL;
- return FALSE;
- }
+ if (gGLManager.mIsDisabled)
+ {
+ LL_WARNS() << "Trying to create a texture while GL is disabled!" << LL_ENDL;
+ return FALSE;
+ }
- llassert(gGLManager.mInited);
- stop_glerror();
+ llassert(gGLManager.mInited);
+ stop_glerror();
- if (!imageraw || imageraw->isBufferInvalid())
- {
- LL_WARNS() << "Trying to create a texture from invalid image data" << LL_ENDL;
+ if (!imageraw || imageraw->isBufferInvalid())
+ {
+ LL_WARNS() << "Trying to create a texture from invalid image data" << LL_ENDL;
mGLTextureCreated = false;
- return FALSE;
- }
-
- if (discard_level < 0)
- {
- llassert(mCurrentDiscardLevel >= 0);
- discard_level = mCurrentDiscardLevel;
- }
-
- // Actual image width/height = raw image width/height * 2^discard_level
- S32 raw_w = imageraw->getWidth() ;
- S32 raw_h = imageraw->getHeight() ;
-
- S32 w = raw_w << discard_level;
- S32 h = raw_h << discard_level;
-
- // setSize may call destroyGLTexture if the size does not match
- if (!setSize(w, h, imageraw->getComponents(), discard_level))
- {
- LL_WARNS() << "Trying to create a texture with incorrect dimensions!" << LL_ENDL;
+ return FALSE;
+ }
+
+ if (discard_level < 0)
+ {
+ llassert(mCurrentDiscardLevel >= 0);
+ discard_level = mCurrentDiscardLevel;
+ }
+
+ // Actual image width/height = raw image width/height * 2^discard_level
+ S32 raw_w = imageraw->getWidth() ;
+ S32 raw_h = imageraw->getHeight() ;
+
+ S32 w = raw_w << discard_level;
+ S32 h = raw_h << discard_level;
+
+ // setSize may call destroyGLTexture if the size does not match
+ if (!setSize(w, h, imageraw->getComponents(), discard_level))
+ {
+ LL_WARNS() << "Trying to create a texture with incorrect dimensions!" << LL_ENDL;
mGLTextureCreated = false;
- return FALSE;
- }
+ return FALSE;
+ }
- if (mHasExplicitFormat &&
- ((mFormatPrimary == GL_RGBA && mComponents < 4) ||
- (mFormatPrimary == GL_RGB && mComponents < 3)))
+ if (mHasExplicitFormat &&
+ ((mFormatPrimary == GL_RGBA && mComponents < 4) ||
+ (mFormatPrimary == GL_RGB && mComponents < 3)))
- {
- LL_WARNS() << "Incorrect format: " << std::hex << mFormatPrimary << " components: " << (U32)mComponents << LL_ENDL;
- mHasExplicitFormat = FALSE;
- }
+ {
+ LL_WARNS() << "Incorrect format: " << std::hex << mFormatPrimary << " components: " << (U32)mComponents << LL_ENDL;
+ mHasExplicitFormat = FALSE;
+ }
- if( !mHasExplicitFormat )
- {
+ if( !mHasExplicitFormat )
+ {
switch (mComponents)
{
case 1:
@@ -1626,21 +1626,21 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S
LL_ERRS() << "Bad number of components for texture: " << (U32)getComponents() << LL_ENDL;
}
- calcAlphaChannelOffsetAndStride() ;
- }
+ calcAlphaChannelOffsetAndStride() ;
+ }
- if(!to_create) //not create a gl texture
- {
- destroyGLTexture();
- mCurrentDiscardLevel = discard_level;
- mLastBindTime = sLastFrameTime;
+ if(!to_create) //not create a gl texture
+ {
+ destroyGLTexture();
+ mCurrentDiscardLevel = discard_level;
+ mLastBindTime = sLastFrameTime;
mGLTextureCreated = false;
- return TRUE ;
- }
+ return TRUE ;
+ }
- setCategory(category);
- const U8* rawdata = imageraw->getData();
- return createGLTexture(discard_level, rawdata, FALSE, usename, defer_copy, tex_name);
+ setCategory(category);
+ const U8* rawdata = imageraw->getData();
+ return createGLTexture(discard_level, rawdata, FALSE, usename, defer_copy, tex_name);
}
BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_hasmips, S32 usename, bool defer_copy, LLGLuint* tex_name)
@@ -1746,7 +1746,7 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_
}
}
-
+
mTextureMemory = (S64Bytes)getMipBytes(mCurrentDiscardLevel);
mTexelsInGLTexture = getWidth() * getHeight();
@@ -1826,302 +1826,302 @@ void LLImageGL::syncTexName(LLGLuint texname)
BOOL LLImageGL::readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compressed_ok) const
{
- llassert_always(sAllowReadBackRaw) ;
- //LL_ERRS() << "should not call this function!" << LL_ENDL ;
-
- if (discard_level < 0)
- {
- discard_level = mCurrentDiscardLevel;
- }
-
- if (mTexName == 0 || discard_level < mCurrentDiscardLevel || discard_level > mMaxDiscardLevel )
- {
- return FALSE;
- }
-
- S32 gl_discard = discard_level - mCurrentDiscardLevel;
-
- //explicitly unbind texture
- gGL.getTexUnit(0)->unbind(mBindTarget);
- llverify(gGL.getTexUnit(0)->bindManual(mBindTarget, mTexName));
-
- //debug code, leave it there commented.
- //checkTexSize() ;
-
- LLGLint glwidth = 0;
- glGetTexLevelParameteriv(mTarget, gl_discard, GL_TEXTURE_WIDTH, (GLint*)&glwidth);
- if (glwidth == 0)
- {
- // No mip data smaller than current discard level
- return FALSE;
- }
-
- S32 width = getWidth(discard_level);
- S32 height = getHeight(discard_level);
- S32 ncomponents = getComponents();
- if (ncomponents == 0)
- {
- return FALSE;
- }
- if(width < glwidth)
- {
- LL_WARNS() << "texture size is smaller than it should be." << LL_ENDL ;
- LL_WARNS() << "width: " << width << " glwidth: " << glwidth << " mWidth: " << mWidth <<
- " mCurrentDiscardLevel: " << (S32)mCurrentDiscardLevel << " discard_level: " << (S32)discard_level << LL_ENDL ;
- return FALSE ;
- }
-
- if (width <= 0 || width > 2048 || height <= 0 || height > 2048 || ncomponents < 1 || ncomponents > 4)
- {
- LL_ERRS() << llformat("LLImageGL::readBackRaw: bogus params: %d x %d x %d",width,height,ncomponents) << LL_ENDL;
- }
-
- LLGLint is_compressed = 0;
- if (compressed_ok)
- {
- glGetTexLevelParameteriv(mTarget, is_compressed, GL_TEXTURE_COMPRESSED, (GLint*)&is_compressed);
- }
-
- //-----------------------------------------------------------------------------------------------
- GLenum error ;
- while((error = glGetError()) != GL_NO_ERROR)
- {
- LL_WARNS() << "GL Error happens before reading back texture. Error code: " << error << LL_ENDL ;
- }
- //-----------------------------------------------------------------------------------------------
-
- if (is_compressed)
- {
- LLGLint glbytes;
- glGetTexLevelParameteriv(mTarget, gl_discard, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, (GLint*)&glbytes);
- if(!imageraw->allocateDataSize(width, height, ncomponents, glbytes))
- {
- LL_WARNS() << "Memory allocation failed for reading back texture. Size is: " << glbytes << LL_ENDL ;
- LL_WARNS() << "width: " << width << "height: " << height << "components: " << ncomponents << LL_ENDL ;
- return FALSE ;
- }
-
- glGetCompressedTexImage(mTarget, gl_discard, (GLvoid*)(imageraw->getData()));
- //stop_glerror();
- }
- else
- {
- if(!imageraw->allocateDataSize(width, height, ncomponents))
- {
- LL_WARNS() << "Memory allocation failed for reading back texture." << LL_ENDL ;
- LL_WARNS() << "width: " << width << "height: " << height << "components: " << ncomponents << LL_ENDL ;
- return FALSE ;
- }
-
- glGetTexImage(GL_TEXTURE_2D, gl_discard, mFormatPrimary, mFormatType, (GLvoid*)(imageraw->getData()));
- //stop_glerror();
- }
-
- //-----------------------------------------------------------------------------------------------
- if((error = glGetError()) != GL_NO_ERROR)
- {
- LL_WARNS() << "GL Error happens after reading back texture. Error code: " << error << LL_ENDL ;
- imageraw->deleteData() ;
-
- while((error = glGetError()) != GL_NO_ERROR)
- {
- LL_WARNS() << "GL Error happens after reading back texture. Error code: " << error << LL_ENDL ;
- }
-
- return FALSE ;
- }
- //-----------------------------------------------------------------------------------------------
-
- return TRUE ;
+ llassert_always(sAllowReadBackRaw) ;
+ //LL_ERRS() << "should not call this function!" << LL_ENDL ;
+
+ if (discard_level < 0)
+ {
+ discard_level = mCurrentDiscardLevel;
+ }
+
+ if (mTexName == 0 || discard_level < mCurrentDiscardLevel || discard_level > mMaxDiscardLevel )
+ {
+ return FALSE;
+ }
+
+ S32 gl_discard = discard_level - mCurrentDiscardLevel;
+
+ //explicitly unbind texture
+ gGL.getTexUnit(0)->unbind(mBindTarget);
+ llverify(gGL.getTexUnit(0)->bindManual(mBindTarget, mTexName));
+
+ //debug code, leave it there commented.
+ //checkTexSize() ;
+
+ LLGLint glwidth = 0;
+ glGetTexLevelParameteriv(mTarget, gl_discard, GL_TEXTURE_WIDTH, (GLint*)&glwidth);
+ if (glwidth == 0)
+ {
+ // No mip data smaller than current discard level
+ return FALSE;
+ }
+
+ S32 width = getWidth(discard_level);
+ S32 height = getHeight(discard_level);
+ S32 ncomponents = getComponents();
+ if (ncomponents == 0)
+ {
+ return FALSE;
+ }
+ if(width < glwidth)
+ {
+ LL_WARNS() << "texture size is smaller than it should be." << LL_ENDL ;
+ LL_WARNS() << "width: " << width << " glwidth: " << glwidth << " mWidth: " << mWidth <<
+ " mCurrentDiscardLevel: " << (S32)mCurrentDiscardLevel << " discard_level: " << (S32)discard_level << LL_ENDL ;
+ return FALSE ;
+ }
+
+ if (width <= 0 || width > 2048 || height <= 0 || height > 2048 || ncomponents < 1 || ncomponents > 4)
+ {
+ LL_ERRS() << llformat("LLImageGL::readBackRaw: bogus params: %d x %d x %d",width,height,ncomponents) << LL_ENDL;
+ }
+
+ LLGLint is_compressed = 0;
+ if (compressed_ok)
+ {
+ glGetTexLevelParameteriv(mTarget, is_compressed, GL_TEXTURE_COMPRESSED, (GLint*)&is_compressed);
+ }
+
+ //-----------------------------------------------------------------------------------------------
+ GLenum error ;
+ while((error = glGetError()) != GL_NO_ERROR)
+ {
+ LL_WARNS() << "GL Error happens before reading back texture. Error code: " << error << LL_ENDL ;
+ }
+ //-----------------------------------------------------------------------------------------------
+
+ if (is_compressed)
+ {
+ LLGLint glbytes;
+ glGetTexLevelParameteriv(mTarget, gl_discard, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, (GLint*)&glbytes);
+ if(!imageraw->allocateDataSize(width, height, ncomponents, glbytes))
+ {
+ LL_WARNS() << "Memory allocation failed for reading back texture. Size is: " << glbytes << LL_ENDL ;
+ LL_WARNS() << "width: " << width << "height: " << height << "components: " << ncomponents << LL_ENDL ;
+ return FALSE ;
+ }
+
+ glGetCompressedTexImage(mTarget, gl_discard, (GLvoid*)(imageraw->getData()));
+ //stop_glerror();
+ }
+ else
+ {
+ if(!imageraw->allocateDataSize(width, height, ncomponents))
+ {
+ LL_WARNS() << "Memory allocation failed for reading back texture." << LL_ENDL ;
+ LL_WARNS() << "width: " << width << "height: " << height << "components: " << ncomponents << LL_ENDL ;
+ return FALSE ;
+ }
+
+ glGetTexImage(GL_TEXTURE_2D, gl_discard, mFormatPrimary, mFormatType, (GLvoid*)(imageraw->getData()));
+ //stop_glerror();
+ }
+
+ //-----------------------------------------------------------------------------------------------
+ if((error = glGetError()) != GL_NO_ERROR)
+ {
+ LL_WARNS() << "GL Error happens after reading back texture. Error code: " << error << LL_ENDL ;
+ imageraw->deleteData() ;
+
+ while((error = glGetError()) != GL_NO_ERROR)
+ {
+ LL_WARNS() << "GL Error happens after reading back texture. Error code: " << error << LL_ENDL ;
+ }
+
+ return FALSE ;
+ }
+ //-----------------------------------------------------------------------------------------------
+
+ return TRUE ;
}
void LLImageGL::destroyGLTexture()
{
checkActiveThread();
- if (mTexName != 0)
- {
- if(mTextureMemory != S64Bytes(0))
- {
- mTextureMemory = (S64Bytes)0;
- }
-
- LLImageGL::deleteTextures(1, &mTexName);
- mCurrentDiscardLevel = -1 ; //invalidate mCurrentDiscardLevel.
- mTexName = 0;
- mGLTextureCreated = FALSE ;
- }
+ if (mTexName != 0)
+ {
+ if(mTextureMemory != S64Bytes(0))
+ {
+ mTextureMemory = (S64Bytes)0;
+ }
+
+ LLImageGL::deleteTextures(1, &mTexName);
+ mCurrentDiscardLevel = -1 ; //invalidate mCurrentDiscardLevel.
+ mTexName = 0;
+ mGLTextureCreated = FALSE ;
+ }
}
//force to invalidate the gl texture, most likely a sculpty texture
void LLImageGL::forceToInvalidateGLTexture()
{
checkActiveThread();
- if (mTexName != 0)
- {
- destroyGLTexture();
- }
- else
- {
- mCurrentDiscardLevel = -1 ; //invalidate mCurrentDiscardLevel.
- }
+ if (mTexName != 0)
+ {
+ destroyGLTexture();
+ }
+ else
+ {
+ mCurrentDiscardLevel = -1 ; //invalidate mCurrentDiscardLevel.
+ }
}
//----------------------------------------------------------------------------
void LLImageGL::setAddressMode(LLTexUnit::eTextureAddressMode mode)
{
- if (mAddressMode != mode)
- {
- mTexOptionsDirty = true;
- mAddressMode = mode;
- }
+ if (mAddressMode != mode)
+ {
+ mTexOptionsDirty = true;
+ mAddressMode = mode;
+ }
- if (gGL.getTexUnit(gGL.getCurrentTexUnitIndex())->getCurrTexture() == mTexName)
- {
- gGL.getTexUnit(gGL.getCurrentTexUnitIndex())->setTextureAddressMode(mode);
- mTexOptionsDirty = false;
- }
+ if (gGL.getTexUnit(gGL.getCurrentTexUnitIndex())->getCurrTexture() == mTexName)
+ {
+ gGL.getTexUnit(gGL.getCurrentTexUnitIndex())->setTextureAddressMode(mode);
+ mTexOptionsDirty = false;
+ }
}
void LLImageGL::setFilteringOption(LLTexUnit::eTextureFilterOptions option)
{
- if (mFilterOption != option)
- {
- mTexOptionsDirty = true;
- mFilterOption = option;
- }
+ if (mFilterOption != option)
+ {
+ mTexOptionsDirty = true;
+ mFilterOption = option;
+ }
- if (mTexName != 0 && gGL.getTexUnit(gGL.getCurrentTexUnitIndex())->getCurrTexture() == mTexName)
- {
- gGL.getTexUnit(gGL.getCurrentTexUnitIndex())->setTextureFilteringOption(option);
- mTexOptionsDirty = false;
- stop_glerror();
- }
+ if (mTexName != 0 && gGL.getTexUnit(gGL.getCurrentTexUnitIndex())->getCurrTexture() == mTexName)
+ {
+ gGL.getTexUnit(gGL.getCurrentTexUnitIndex())->setTextureFilteringOption(option);
+ mTexOptionsDirty = false;
+ stop_glerror();
+ }
}
BOOL LLImageGL::getIsResident(BOOL test_now)
{
- if (test_now)
- {
- if (mTexName != 0)
- {
- glAreTexturesResident(1, (GLuint*)&mTexName, &mIsResident);
- }
- else
- {
- mIsResident = FALSE;
- }
- }
+ if (test_now)
+ {
+ if (mTexName != 0)
+ {
+ glAreTexturesResident(1, (GLuint*)&mTexName, &mIsResident);
+ }
+ else
+ {
+ mIsResident = FALSE;
+ }
+ }
- return mIsResident;
+ return mIsResident;
}
S32 LLImageGL::getHeight(S32 discard_level) const
{
- if (discard_level < 0)
- {
- discard_level = mCurrentDiscardLevel;
- }
- S32 height = mHeight >> discard_level;
- if (height < 1) height = 1;
- return height;
+ if (discard_level < 0)
+ {
+ discard_level = mCurrentDiscardLevel;
+ }
+ S32 height = mHeight >> discard_level;
+ if (height < 1) height = 1;
+ return height;
}
S32 LLImageGL::getWidth(S32 discard_level) const
{
- if (discard_level < 0)
- {
- discard_level = mCurrentDiscardLevel;
- }
- S32 width = mWidth >> discard_level;
- if (width < 1) width = 1;
- return width;
+ if (discard_level < 0)
+ {
+ discard_level = mCurrentDiscardLevel;
+ }
+ S32 width = mWidth >> discard_level;
+ if (width < 1) width = 1;
+ return width;
}
S64 LLImageGL::getBytes(S32 discard_level) const
{
- if (discard_level < 0)
- {
- discard_level = mCurrentDiscardLevel;
- }
- S32 w = mWidth>>discard_level;
- S32 h = mHeight>>discard_level;
- if (w == 0) w = 1;
- if (h == 0) h = 1;
- return dataFormatBytes(mFormatPrimary, w, h);
+ if (discard_level < 0)
+ {
+ discard_level = mCurrentDiscardLevel;
+ }
+ S32 w = mWidth>>discard_level;
+ S32 h = mHeight>>discard_level;
+ if (w == 0) w = 1;
+ if (h == 0) h = 1;
+ return dataFormatBytes(mFormatPrimary, w, h);
}
S64 LLImageGL::getMipBytes(S32 discard_level) const
{
- if (discard_level < 0)
- {
- discard_level = mCurrentDiscardLevel;
- }
- S32 w = mWidth>>discard_level;
- S32 h = mHeight>>discard_level;
- S64 res = dataFormatBytes(mFormatPrimary, w, h);
- if (mUseMipMaps)
- {
- while (w > 1 && h > 1)
- {
- w >>= 1; if (w == 0) w = 1;
- h >>= 1; if (h == 0) h = 1;
- res += dataFormatBytes(mFormatPrimary, w, h);
- }
- }
- return res;
+ if (discard_level < 0)
+ {
+ discard_level = mCurrentDiscardLevel;
+ }
+ S32 w = mWidth>>discard_level;
+ S32 h = mHeight>>discard_level;
+ S64 res = dataFormatBytes(mFormatPrimary, w, h);
+ if (mUseMipMaps)
+ {
+ while (w > 1 && h > 1)
+ {
+ w >>= 1; if (w == 0) w = 1;
+ h >>= 1; if (h == 0) h = 1;
+ res += dataFormatBytes(mFormatPrimary, w, h);
+ }
+ }
+ return res;
}
BOOL LLImageGL::isJustBound() const
{
- return (BOOL)(sLastFrameTime - mLastBindTime < 0.5f);
+ return (BOOL)(sLastFrameTime - mLastBindTime < 0.5f);
}
BOOL LLImageGL::getBoundRecently() const
{
- return (BOOL)(sLastFrameTime - mLastBindTime < MIN_TEXTURE_LIFETIME);
+ return (BOOL)(sLastFrameTime - mLastBindTime < MIN_TEXTURE_LIFETIME);
}
BOOL LLImageGL::getIsAlphaMask() const
{
- llassert_always(!sSkipAnalyzeAlpha);
- return mIsMask;
+ llassert_always(!sSkipAnalyzeAlpha);
+ return mIsMask;
}
void LLImageGL::setTarget(const LLGLenum target, const LLTexUnit::eTextureType bind_target)
{
- mTarget = target;
- mBindTarget = bind_target;
+ mTarget = target;
+ mBindTarget = bind_target;
}
const S8 INVALID_OFFSET = -99 ;
-void LLImageGL::setNeedsAlphaAndPickMask(BOOL need_mask)
+void LLImageGL::setNeedsAlphaAndPickMask(BOOL need_mask)
{
- if(mNeedsAlphaAndPickMask != need_mask)
- {
- mNeedsAlphaAndPickMask = need_mask;
+ if(mNeedsAlphaAndPickMask != need_mask)
+ {
+ mNeedsAlphaAndPickMask = need_mask;
- if(mNeedsAlphaAndPickMask)
- {
- mAlphaOffset = 0 ;
- }
- else //do not need alpha mask
- {
- mAlphaOffset = INVALID_OFFSET ;
- mIsMask = FALSE;
- }
- }
+ if(mNeedsAlphaAndPickMask)
+ {
+ mAlphaOffset = 0 ;
+ }
+ else //do not need alpha mask
+ {
+ mAlphaOffset = INVALID_OFFSET ;
+ mIsMask = FALSE;
+ }
+ }
}
void LLImageGL::calcAlphaChannelOffsetAndStride()
{
- if(mAlphaOffset == INVALID_OFFSET)//do not need alpha mask
- {
- return ;
- }
+ if(mAlphaOffset == INVALID_OFFSET)//do not need alpha mask
+ {
+ return ;
+ }
- mAlphaStride = -1 ;
+ mAlphaStride = -1 ;
switch (mFormatPrimary)
{
case GL_LUMINANCE:
@@ -2148,173 +2148,173 @@ void LLImageGL::calcAlphaChannelOffsetAndStride()
break;
}
- mAlphaOffset = -1 ;
- if (mFormatType == GL_UNSIGNED_BYTE)
- {
- mAlphaOffset = mAlphaStride - 1 ;
- }
- else if(is_little_endian())
- {
- if (mFormatType == GL_UNSIGNED_INT_8_8_8_8)
- {
- mAlphaOffset = 0 ;
- }
- else if (mFormatType == GL_UNSIGNED_INT_8_8_8_8_REV)
- {
- mAlphaOffset = 3 ;
- }
- }
- else //big endian
- {
- if (mFormatType == GL_UNSIGNED_INT_8_8_8_8)
- {
- mAlphaOffset = 3 ;
- }
- else if (mFormatType == GL_UNSIGNED_INT_8_8_8_8_REV)
- {
- mAlphaOffset = 0 ;
- }
- }
-
- if( mAlphaStride < 1 || //unsupported format
- mAlphaOffset < 0 || //unsupported type
- (mFormatPrimary == GL_BGRA_EXT && mFormatType != GL_UNSIGNED_BYTE)) //unknown situation
- {
- LL_WARNS() << "Cannot analyze alpha for image with format type " << std::hex << mFormatType << std::dec << LL_ENDL;
-
- mNeedsAlphaAndPickMask = FALSE ;
- mIsMask = FALSE;
- }
+ mAlphaOffset = -1 ;
+ if (mFormatType == GL_UNSIGNED_BYTE)
+ {
+ mAlphaOffset = mAlphaStride - 1 ;
+ }
+ else if(is_little_endian())
+ {
+ if (mFormatType == GL_UNSIGNED_INT_8_8_8_8)
+ {
+ mAlphaOffset = 0 ;
+ }
+ else if (mFormatType == GL_UNSIGNED_INT_8_8_8_8_REV)
+ {
+ mAlphaOffset = 3 ;
+ }
+ }
+ else //big endian
+ {
+ if (mFormatType == GL_UNSIGNED_INT_8_8_8_8)
+ {
+ mAlphaOffset = 3 ;
+ }
+ else if (mFormatType == GL_UNSIGNED_INT_8_8_8_8_REV)
+ {
+ mAlphaOffset = 0 ;
+ }
+ }
+
+ if( mAlphaStride < 1 || //unsupported format
+ mAlphaOffset < 0 || //unsupported type
+ (mFormatPrimary == GL_BGRA_EXT && mFormatType != GL_UNSIGNED_BYTE)) //unknown situation
+ {
+ LL_WARNS() << "Cannot analyze alpha for image with format type " << std::hex << mFormatType << std::dec << LL_ENDL;
+
+ mNeedsAlphaAndPickMask = FALSE ;
+ mIsMask = FALSE;
+ }
}
void LLImageGL::analyzeAlpha(const void* data_in, U32 w, U32 h)
{
- if(sSkipAnalyzeAlpha || !mNeedsAlphaAndPickMask)
- {
- return ;
- }
-
- U32 length = w * h;
- U32 alphatotal = 0;
-
- U32 sample[16];
- memset(sample, 0, sizeof(U32)*16);
-
- // generate histogram of quantized alpha.
- // also add-in the histogram of a 2x2 box-sampled version. The idea is
- // this will mid-skew the data (and thus increase the chances of not
- // being used as a mask) from high-frequency alpha maps which
- // suffer the worst from aliasing when used as alpha masks.
- if (w >= 2 && h >= 2)
- {
- llassert(w%2 == 0);
- llassert(h%2 == 0);
- const GLubyte* rowstart = ((const GLubyte*) data_in) + mAlphaOffset;
- for (U32 y = 0; y < h; y+=2)
- {
- const GLubyte* current = rowstart;
- for (U32 x = 0; x < w; x+=2)
- {
- const U32 s1 = current[0];
- alphatotal += s1;
- const U32 s2 = current[w * mAlphaStride];
- alphatotal += s2;
- current += mAlphaStride;
- const U32 s3 = current[0];
- alphatotal += s3;
- const U32 s4 = current[w * mAlphaStride];
- alphatotal += s4;
- current += mAlphaStride;
-
- ++sample[s1/16];
- ++sample[s2/16];
- ++sample[s3/16];
- ++sample[s4/16];
-
- const U32 asum = (s1+s2+s3+s4);
- alphatotal += asum;
- sample[asum/(16*4)] += 4;
- }
-
-
- rowstart += 2 * w * mAlphaStride;
- }
- length *= 2; // we sampled everything twice, essentially
- }
- else
- {
- const GLubyte* current = ((const GLubyte*) data_in) + mAlphaOffset;
- for (U32 i = 0; i < length; i++)
- {
- const U32 s1 = *current;
- alphatotal += s1;
- ++sample[s1/16];
- current += mAlphaStride;
- }
- }
-
- // if more than 1/16th of alpha samples are mid-range, this
- // shouldn't be treated as a 1-bit mask
-
- // also, if all of the alpha samples are clumped on one half
- // of the range (but not at an absolute extreme), then consider
- // this to be an intentional effect and don't treat as a mask.
-
- U32 midrangetotal = 0;
- for (U32 i = 2; i < 13; i++)
- {
- midrangetotal += sample[i];
- }
- U32 lowerhalftotal = 0;
- for (U32 i = 0; i < 8; i++)
- {
- lowerhalftotal += sample[i];
- }
- U32 upperhalftotal = 0;
- for (U32 i = 8; i < 16; i++)
- {
- upperhalftotal += sample[i];
- }
-
- if (midrangetotal > length/48 || // lots of midrange, or
- (lowerhalftotal == length && alphatotal != 0) || // all close to transparent but not all totally transparent, or
- (upperhalftotal == length && alphatotal != 255*length)) // all close to opaque but not all totally opaque
- {
- mIsMask = FALSE; // not suitable for masking
- }
- else
- {
- mIsMask = TRUE;
- }
+ if(sSkipAnalyzeAlpha || !mNeedsAlphaAndPickMask)
+ {
+ return ;
+ }
+
+ U32 length = w * h;
+ U32 alphatotal = 0;
+
+ U32 sample[16];
+ memset(sample, 0, sizeof(U32)*16);
+
+ // generate histogram of quantized alpha.
+ // also add-in the histogram of a 2x2 box-sampled version. The idea is
+ // this will mid-skew the data (and thus increase the chances of not
+ // being used as a mask) from high-frequency alpha maps which
+ // suffer the worst from aliasing when used as alpha masks.
+ if (w >= 2 && h >= 2)
+ {
+ llassert(w%2 == 0);
+ llassert(h%2 == 0);
+ const GLubyte* rowstart = ((const GLubyte*) data_in) + mAlphaOffset;
+ for (U32 y = 0; y < h; y+=2)
+ {
+ const GLubyte* current = rowstart;
+ for (U32 x = 0; x < w; x+=2)
+ {
+ const U32 s1 = current[0];
+ alphatotal += s1;
+ const U32 s2 = current[w * mAlphaStride];
+ alphatotal += s2;
+ current += mAlphaStride;
+ const U32 s3 = current[0];
+ alphatotal += s3;
+ const U32 s4 = current[w * mAlphaStride];
+ alphatotal += s4;
+ current += mAlphaStride;
+
+ ++sample[s1/16];
+ ++sample[s2/16];
+ ++sample[s3/16];
+ ++sample[s4/16];
+
+ const U32 asum = (s1+s2+s3+s4);
+ alphatotal += asum;
+ sample[asum/(16*4)] += 4;
+ }
+
+
+ rowstart += 2 * w * mAlphaStride;
+ }
+ length *= 2; // we sampled everything twice, essentially
+ }
+ else
+ {
+ const GLubyte* current = ((const GLubyte*) data_in) + mAlphaOffset;
+ for (U32 i = 0; i < length; i++)
+ {
+ const U32 s1 = *current;
+ alphatotal += s1;
+ ++sample[s1/16];
+ current += mAlphaStride;
+ }
+ }
+
+ // if more than 1/16th of alpha samples are mid-range, this
+ // shouldn't be treated as a 1-bit mask
+
+ // also, if all of the alpha samples are clumped on one half
+ // of the range (but not at an absolute extreme), then consider
+ // this to be an intentional effect and don't treat as a mask.
+
+ U32 midrangetotal = 0;
+ for (U32 i = 2; i < 13; i++)
+ {
+ midrangetotal += sample[i];
+ }
+ U32 lowerhalftotal = 0;
+ for (U32 i = 0; i < 8; i++)
+ {
+ lowerhalftotal += sample[i];
+ }
+ U32 upperhalftotal = 0;
+ for (U32 i = 8; i < 16; i++)
+ {
+ upperhalftotal += sample[i];
+ }
+
+ if (midrangetotal > length/48 || // lots of midrange, or
+ (lowerhalftotal == length && alphatotal != 0) || // all close to transparent but not all totally transparent, or
+ (upperhalftotal == length && alphatotal != 255*length)) // all close to opaque but not all totally opaque
+ {
+ mIsMask = FALSE; // not suitable for masking
+ }
+ else
+ {
+ mIsMask = TRUE;
+ }
}
//----------------------------------------------------------------------------
U32 LLImageGL::createPickMask(S32 pWidth, S32 pHeight)
{
- U32 pick_width = pWidth/2 + 1;
- U32 pick_height = pHeight/2 + 1;
+ U32 pick_width = pWidth/2 + 1;
+ U32 pick_height = pHeight/2 + 1;
- 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;
+ 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);
+ memset(mPickMask, 0, sizeof(U8) * size);
- return size;
+ return size;
}
//----------------------------------------------------------------------------
void LLImageGL::freePickMask()
{
- // pickmask validity depends on old image size, delete it
- if (mPickMask != NULL)
- {
- delete [] mPickMask;
- }
- mPickMask = NULL;
- mPickMaskWidth = mPickMaskHeight = 0;
+ // pickmask validity depends on old image size, delete it
+ if (mPickMask != NULL)
+ {
+ delete [] mPickMask;
+ }
+ mPickMask = NULL;
+ mPickMaskWidth = mPickMaskHeight = 0;
}
bool LLImageGL::isCompressed()
@@ -2341,12 +2341,12 @@ bool LLImageGL::isCompressed()
//----------------------------------------------------------------------------
void LLImageGL::updatePickMask(S32 width, S32 height, const U8* data_in)
{
- if(!mNeedsAlphaAndPickMask)
- {
- return ;
- }
+ if(!mNeedsAlphaAndPickMask)
+ {
+ return ;
+ }
- freePickMask();
+ freePickMask();
if (mFormatType != GL_UNSIGNED_BYTE ||
((mFormatPrimary != GL_RGBA)
@@ -2357,102 +2357,102 @@ void LLImageGL::updatePickMask(S32 width, S32 height, const U8* data_in)
}
#ifdef SHOW_ASSERT
- const U32 pickSize = createPickMask(width, height);
+ const U32 pickSize = createPickMask(width, height);
#else // SHOW_ASSERT
- createPickMask(width, height);
+ createPickMask(width, height);
#endif // SHOW_ASSERT
- U32 pick_bit = 0;
-
- for (S32 y = 0; y < height; y += 2)
- {
- for (S32 x = 0; x < width; x += 2)
- {
- U8 alpha = data_in[(y*width+x)*4+3];
+ U32 pick_bit = 0;
- if (alpha > 32)
- {
- U32 pick_idx = pick_bit/8;
- U32 pick_offset = pick_bit%8;
- llassert(pick_idx < pickSize);
+ for (S32 y = 0; y < height; y += 2)
+ {
+ for (S32 x = 0; x < width; x += 2)
+ {
+ U8 alpha = data_in[(y*width+x)*4+3];
+
+ if (alpha > 32)
+ {
+ U32 pick_idx = pick_bit/8;
+ U32 pick_offset = pick_bit%8;
+ llassert(pick_idx < pickSize);
- mPickMask[pick_idx] |= 1 << pick_offset;
- }
-
- ++pick_bit;
- }
- }
+ mPickMask[pick_idx] |= 1 << pick_offset;
+ }
+
+ ++pick_bit;
+ }
+ }
}
BOOL LLImageGL::getMask(const LLVector2 &tc)
{
- BOOL res = TRUE;
-
- if (mPickMask)
- {
- 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;
- // removing assert per EXT-4388
- // llassert(false);
- }
-
- 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;
- // removing assert per EXT-4388
- // llassert(false);
- }
-
- 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((U16)0, mPickMaskWidth);
- }
- if (LL_UNLIKELY(y > mPickMaskHeight))
- {
- LL_WARNS_ONCE("render") << "Ooh, height overrun on pick mask read, that woulda been bad." << LL_ENDL;
- y = llmax((U16)0, mPickMaskHeight);
- }
-
- S32 idx = y*mPickMaskWidth+x;
- S32 offset = idx%8;
-
- res = mPickMask[idx/8] & (1 << offset) ? TRUE : FALSE;
- }
-
- return res;
+ BOOL res = TRUE;
+
+ if (mPickMask)
+ {
+ 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;
+ // removing assert per EXT-4388
+ // llassert(false);
+ }
+
+ 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;
+ // removing assert per EXT-4388
+ // llassert(false);
+ }
+
+ 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((U16)0, mPickMaskWidth);
+ }
+ if (LL_UNLIKELY(y > mPickMaskHeight))
+ {
+ LL_WARNS_ONCE("render") << "Ooh, height overrun on pick mask read, that woulda been bad." << LL_ENDL;
+ y = llmax((U16)0, mPickMaskHeight);
+ }
+
+ S32 idx = y*mPickMaskWidth+x;
+ S32 offset = idx%8;
+
+ res = mPickMask[idx/8] & (1 << offset) ? TRUE : FALSE;
+ }
+
+ return res;
}
void LLImageGL::setCurTexSizebar(S32 index, BOOL set_pick_size)
{
- sCurTexSizeBar = index ;
+ sCurTexSizeBar = index ;
- if(set_pick_size)
- {
- sCurTexPickSize = (1 << index) ;
- }
- else
- {
- sCurTexPickSize = -1 ;
- }
+ if(set_pick_size)
+ {
+ sCurTexPickSize = (1 << index) ;
+ }
+ else
+ {
+ sCurTexPickSize = -1 ;
+ }
}
void LLImageGL::resetCurTexSizebar()
{
- sCurTexSizeBar = -1 ;
- sCurTexPickSize = -1 ;
+ sCurTexSizeBar = -1 ;
+ sCurTexPickSize = -1 ;
}
//----------------------------------------------------------------------------
#if LL_IMAGEGL_THREAD_CHECK
@@ -2467,53 +2467,53 @@ void LLImageGL::checkActiveThread()
// Manual Mip Generation
/*
- S32 width = getWidth(discard_level);
- S32 height = getHeight(discard_level);
- S32 w = width, h = height;
- S32 nummips = 1;
- while (w > 4 && h > 4)
- {
- w >>= 1; h >>= 1;
- nummips++;
- }
- stop_glerror();
- w = width, h = height;
- const U8* prev_mip_data = 0;
- const U8* cur_mip_data = 0;
- for (int m=0; m<nummips; m++)
- {
- if (m==0)
- {
- cur_mip_data = rawdata;
- }
- else
- {
- S32 bytes = w * h * mComponents;
- U8* new_data = new U8[bytes];
- LLImageBase::generateMip(prev_mip_data, new_data, w, h, mComponents);
- cur_mip_data = new_data;
- }
- llassert(w > 0 && h > 0 && cur_mip_data);
- U8 test = cur_mip_data[w*h*mComponents-1];
- {
- LLImageGL::setManualImage(mTarget, m, mFormatInternal, w, h, mFormatPrimary, mFormatType, cur_mip_data);
- stop_glerror();
- }
- if (prev_mip_data && prev_mip_data != rawdata)
- {
- delete prev_mip_data;
- }
- prev_mip_data = cur_mip_data;
- w >>= 1;
- h >>= 1;
- }
- if (prev_mip_data && prev_mip_data != rawdata)
- {
- delete prev_mip_data;
- }
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, nummips);
-*/
+ S32 width = getWidth(discard_level);
+ S32 height = getHeight(discard_level);
+ S32 w = width, h = height;
+ S32 nummips = 1;
+ while (w > 4 && h > 4)
+ {
+ w >>= 1; h >>= 1;
+ nummips++;
+ }
+ stop_glerror();
+ w = width, h = height;
+ const U8* prev_mip_data = 0;
+ const U8* cur_mip_data = 0;
+ for (int m=0; m<nummips; m++)
+ {
+ if (m==0)
+ {
+ cur_mip_data = rawdata;
+ }
+ else
+ {
+ S32 bytes = w * h * mComponents;
+ U8* new_data = new U8[bytes];
+ LLImageBase::generateMip(prev_mip_data, new_data, w, h, mComponents);
+ cur_mip_data = new_data;
+ }
+ llassert(w > 0 && h > 0 && cur_mip_data);
+ U8 test = cur_mip_data[w*h*mComponents-1];
+ {
+ LLImageGL::setManualImage(mTarget, m, mFormatInternal, w, h, mFormatPrimary, mFormatType, cur_mip_data);
+ stop_glerror();
+ }
+ if (prev_mip_data && prev_mip_data != rawdata)
+ {
+ delete prev_mip_data;
+ }
+ prev_mip_data = cur_mip_data;
+ w >>= 1;
+ h >>= 1;
+ }
+ if (prev_mip_data && prev_mip_data != rawdata)
+ {
+ delete prev_mip_data;
+ }
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, nummips);
+*/
LLImageGLThread::LLImageGLThread(LLWindow* window)
// We want exactly one thread.
diff --git a/indra/llrender/llimagegl.h b/indra/llrender/llimagegl.h
index a9a6b93cb3..89e35d2226 100644
--- a/indra/llrender/llimagegl.h
+++ b/indra/llrender/llimagegl.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file llimagegl.h
* @brief Object for managing images and their textures
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -50,7 +50,7 @@ class LLWindow;
//============================================================================
class LLImageGL : public LLRefCount
{
- friend class LLTexUnit;
+ friend class LLTexUnit;
public:
// Get an estimate of how many bytes have been allocated in vram for textures.
@@ -59,146 +59,146 @@ public:
// video memory usage based on testing in lagland against an NVIDIA GPU.
static U64 getTextureBytesAllocated();
- // These 2 functions replace glGenTextures() and glDeleteTextures()
- static void generateTextures(S32 numTextures, U32 *textures);
- static void deleteTextures(S32 numTextures, const U32 *textures);
+ // These 2 functions replace glGenTextures() and glDeleteTextures()
+ static void generateTextures(S32 numTextures, U32 *textures);
+ static void deleteTextures(S32 numTextures, const U32 *textures);
+
+ // Size calculation
+ static S32 dataFormatBits(S32 dataformat);
+ static S64 dataFormatBytes(S32 dataformat, S32 width, S32 height);
+ static S32 dataFormatComponents(S32 dataformat);
- // Size calculation
- static S32 dataFormatBits(S32 dataformat);
- static S64 dataFormatBytes(S32 dataformat, S32 width, S32 height);
- static S32 dataFormatComponents(S32 dataformat);
+ BOOL updateBindStats() const ;
+ F32 getTimePassedSinceLastBound();
+ void forceUpdateBindStats(void) const;
- BOOL updateBindStats() const ;
- F32 getTimePassedSinceLastBound();
- void forceUpdateBindStats(void) const;
+ // needs to be called every frame
+ static void updateStats(F32 current_time);
- // needs to be called every frame
- static void updateStats(F32 current_time);
+ // Save off / restore GL textures
+ static void destroyGL(BOOL save_state = TRUE);
+ static void restoreGL();
+ static void dirtyTexOptions();
- // Save off / restore GL textures
- static void destroyGL(BOOL save_state = TRUE);
- static void restoreGL();
- static void dirtyTexOptions();
+ static bool checkSize(S32 width, S32 height);
- static bool checkSize(S32 width, S32 height);
+ //for server side use only.
+ // Not currently necessary for LLImageGL, but required in some derived classes,
+ // so include for compatability
+ static BOOL create(LLPointer<LLImageGL>& dest, BOOL usemipmaps = TRUE);
+ static BOOL create(LLPointer<LLImageGL>& dest, U32 width, U32 height, U8 components, BOOL usemipmaps = TRUE);
+ static BOOL create(LLPointer<LLImageGL>& dest, const LLImageRaw* imageraw, BOOL usemipmaps = TRUE);
- //for server side use only.
- // Not currently necessary for LLImageGL, but required in some derived classes,
- // so include for compatability
- static BOOL create(LLPointer<LLImageGL>& dest, BOOL usemipmaps = TRUE);
- static BOOL create(LLPointer<LLImageGL>& dest, U32 width, U32 height, U8 components, BOOL usemipmaps = TRUE);
- static BOOL create(LLPointer<LLImageGL>& dest, const LLImageRaw* imageraw, BOOL usemipmaps = TRUE);
-
public:
- LLImageGL(BOOL usemipmaps = TRUE);
- LLImageGL(U32 width, U32 height, U8 components, BOOL usemipmaps = TRUE);
- LLImageGL(const LLImageRaw* imageraw, BOOL usemipmaps = TRUE);
+ LLImageGL(BOOL usemipmaps = TRUE);
+ LLImageGL(U32 width, U32 height, U8 components, BOOL usemipmaps = TRUE);
+ LLImageGL(const LLImageRaw* imageraw, BOOL usemipmaps = TRUE);
// For wrapping textures created via GL elsewhere with our API only. Use with caution.
LLImageGL(LLGLuint mTexName, U32 components, LLGLenum target, LLGLint formatInternal, LLGLenum formatPrimary, LLGLenum formatType, LLTexUnit::eTextureAddressMode addressMode);
protected:
- virtual ~LLImageGL();
+ virtual ~LLImageGL();
- void analyzeAlpha(const void* data_in, U32 w, U32 h);
- void calcAlphaChannelOffsetAndStride();
+ void analyzeAlpha(const void* data_in, U32 w, U32 h);
+ void calcAlphaChannelOffsetAndStride();
public:
- virtual void dump(); // debugging info to LL_INFOS()
-
- bool setSize(S32 width, S32 height, S32 ncomponents, S32 discard_level = -1);
- void setComponents(S32 ncomponents) { mComponents = (S8)ncomponents ;}
- void setAllowCompression(bool allow) { mAllowCompression = allow; }
-
- static void setManualImage(U32 target, S32 miplevel, S32 intformat, S32 width, S32 height, U32 pixformat, U32 pixtype, const void *pixels, bool allow_compression = true);
-
- BOOL createGLTexture() ;
- BOOL createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename = 0, BOOL to_create = TRUE,
- S32 category = sMaxCategories-1, bool defer_copy = false, LLGLuint* tex_name = nullptr);
- BOOL createGLTexture(S32 discard_level, const U8* data, BOOL data_hasmips = FALSE, S32 usename = 0, bool defer_copy = false, LLGLuint* tex_name = nullptr);
- void setImage(const LLImageRaw* imageraw);
- BOOL setImage(const U8* data_in, BOOL data_hasmips = FALSE, S32 usename = 0);
+ virtual void dump(); // debugging info to LL_INFOS()
+
+ bool setSize(S32 width, S32 height, S32 ncomponents, S32 discard_level = -1);
+ void setComponents(S32 ncomponents) { mComponents = (S8)ncomponents ;}
+ void setAllowCompression(bool allow) { mAllowCompression = allow; }
+
+ static void setManualImage(U32 target, S32 miplevel, S32 intformat, S32 width, S32 height, U32 pixformat, U32 pixtype, const void *pixels, bool allow_compression = true);
+
+ BOOL createGLTexture() ;
+ BOOL createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename = 0, BOOL to_create = TRUE,
+ S32 category = sMaxCategories-1, bool defer_copy = false, LLGLuint* tex_name = nullptr);
+ BOOL createGLTexture(S32 discard_level, const U8* data, BOOL data_hasmips = FALSE, S32 usename = 0, bool defer_copy = false, LLGLuint* tex_name = nullptr);
+ void setImage(const LLImageRaw* imageraw);
+ BOOL setImage(const U8* data_in, BOOL data_hasmips = FALSE, S32 usename = 0);
// *TODO: This function may not work if the textures is compressed (i.e.
// RenderCompressTextures is 0). Partial image updates do not work on
// compressed textures.
- BOOL setSubImage(const LLImageRaw* imageraw, S32 x_pos, S32 y_pos, S32 width, S32 height, BOOL force_fast_update = FALSE, LLGLuint use_name = 0);
- BOOL setSubImage(const U8* datap, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height, BOOL force_fast_update = FALSE, LLGLuint use_name = 0);
- BOOL setSubImageFromFrameBuffer(S32 fb_x, S32 fb_y, S32 x_pos, S32 y_pos, S32 width, S32 height);
+ BOOL setSubImage(const LLImageRaw* imageraw, S32 x_pos, S32 y_pos, S32 width, S32 height, BOOL force_fast_update = FALSE, LLGLuint use_name = 0);
+ BOOL setSubImage(const U8* datap, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height, BOOL force_fast_update = FALSE, LLGLuint use_name = 0);
+ BOOL setSubImageFromFrameBuffer(S32 fb_x, S32 fb_y, S32 x_pos, S32 y_pos, S32 width, S32 height);
// wait for gl commands to finish on current thread and push
// a lambda to main thread to swap mNewTexName and mTexName
void syncToMainThread(LLGLuint new_tex_name);
- // Read back a raw image for this discard level, if it exists
- BOOL readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compressed_ok) const;
- void destroyGLTexture();
- void forceToInvalidateGLTexture();
+ // Read back a raw image for this discard level, if it exists
+ BOOL readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compressed_ok) const;
+ void destroyGLTexture();
+ void forceToInvalidateGLTexture();
- void setExplicitFormat(LLGLint internal_format, LLGLenum primary_format, LLGLenum type_format = 0, BOOL swap_bytes = FALSE);
- void setComponents(S8 ncomponents) { mComponents = ncomponents; }
+ void setExplicitFormat(LLGLint internal_format, LLGLenum primary_format, LLGLenum type_format = 0, BOOL swap_bytes = FALSE);
+ void setComponents(S8 ncomponents) { mComponents = ncomponents; }
- S32 getDiscardLevel() const { return mCurrentDiscardLevel; }
- S32 getMaxDiscardLevel() const { return mMaxDiscardLevel; }
+ S32 getDiscardLevel() const { return mCurrentDiscardLevel; }
+ S32 getMaxDiscardLevel() const { return mMaxDiscardLevel; }
- S32 getCurrentWidth() const { return mWidth ;}
- S32 getCurrentHeight() const { return mHeight ;}
- S32 getWidth(S32 discard_level = -1) const;
- S32 getHeight(S32 discard_level = -1) const;
- U8 getComponents() const { return mComponents; }
- S64 getBytes(S32 discard_level = -1) const;
- S64 getMipBytes(S32 discard_level = -1) const;
- BOOL getBoundRecently() const;
- BOOL isJustBound() const;
- BOOL getHasExplicitFormat() const { return mHasExplicitFormat; }
- LLGLenum getPrimaryFormat() const { return mFormatPrimary; }
- LLGLenum getFormatType() const { return mFormatType; }
+ S32 getCurrentWidth() const { return mWidth ;}
+ S32 getCurrentHeight() const { return mHeight ;}
+ S32 getWidth(S32 discard_level = -1) const;
+ S32 getHeight(S32 discard_level = -1) const;
+ U8 getComponents() const { return mComponents; }
+ S64 getBytes(S32 discard_level = -1) const;
+ S64 getMipBytes(S32 discard_level = -1) const;
+ BOOL getBoundRecently() const;
+ BOOL isJustBound() const;
+ BOOL getHasExplicitFormat() const { return mHasExplicitFormat; }
+ LLGLenum getPrimaryFormat() const { return mFormatPrimary; }
+ LLGLenum getFormatType() const { return mFormatType; }
- BOOL getHasGLTexture() const { return mTexName != 0; }
- LLGLuint getTexName() const { return mTexName; }
+ BOOL getHasGLTexture() const { return mTexName != 0; }
+ LLGLuint getTexName() const { return mTexName; }
- BOOL getIsAlphaMask() const;
+ BOOL getIsAlphaMask() const;
- BOOL getIsResident(BOOL test_now = FALSE); // not const
+ BOOL getIsResident(BOOL test_now = FALSE); // not const
- void setTarget(const LLGLenum target, const LLTexUnit::eTextureType bind_target);
+ void setTarget(const LLGLenum target, const LLTexUnit::eTextureType bind_target);
- LLTexUnit::eTextureType getTarget(void) const { return mBindTarget; }
- bool isGLTextureCreated(void) const { return mGLTextureCreated ; }
- void setGLTextureCreated (bool initialized) { mGLTextureCreated = initialized; }
+ LLTexUnit::eTextureType getTarget(void) const { return mBindTarget; }
+ bool isGLTextureCreated(void) const { return mGLTextureCreated ; }
+ void setGLTextureCreated (bool initialized) { mGLTextureCreated = initialized; }
- BOOL getUseMipMaps() const { return mUseMipMaps; }
- void setUseMipMaps(BOOL usemips) { mUseMipMaps = usemips; }
+ BOOL getUseMipMaps() const { return mUseMipMaps; }
+ void setUseMipMaps(BOOL usemips) { mUseMipMaps = usemips; }
void setHasMipMaps(BOOL hasmips) { mHasMipMaps = hasmips; }
- void updatePickMask(S32 width, S32 height, const U8* data_in);
- BOOL getMask(const LLVector2 &tc);
+ void updatePickMask(S32 width, S32 height, const U8* data_in);
+ BOOL getMask(const LLVector2 &tc);
void checkTexSize(bool forced = false) const ;
-
- // Sets the addressing mode used to sample the texture
- // (such as wrapping, mirrored wrapping, and clamp)
- // Note: this actually gets set the next time the texture is bound.
- void setAddressMode(LLTexUnit::eTextureAddressMode mode);
- LLTexUnit::eTextureAddressMode getAddressMode(void) const { return mAddressMode; }
- // Sets the filtering options used to sample the texture
- // (such as point sampling, bilinear interpolation, mipmapping, and anisotropic filtering)
- // Note: this actually gets set the next time the texture is bound.
- void setFilteringOption(LLTexUnit::eTextureFilterOptions option);
- LLTexUnit::eTextureFilterOptions getFilteringOption(void) const { return mFilterOption; }
+ // Sets the addressing mode used to sample the texture
+ // (such as wrapping, mirrored wrapping, and clamp)
+ // Note: this actually gets set the next time the texture is bound.
+ void setAddressMode(LLTexUnit::eTextureAddressMode mode);
+ LLTexUnit::eTextureAddressMode getAddressMode(void) const { return mAddressMode; }
+
+ // Sets the filtering options used to sample the texture
+ // (such as point sampling, bilinear interpolation, mipmapping, and anisotropic filtering)
+ // Note: this actually gets set the next time the texture is bound.
+ void setFilteringOption(LLTexUnit::eTextureFilterOptions option);
+ LLTexUnit::eTextureFilterOptions getFilteringOption(void) const { return mFilterOption; }
- LLGLenum getTexTarget()const { return mTarget ;}
- S8 getDiscardLevelInAtlas()const {return mDiscardLevelInAtlas;}
- U32 getTexelsInAtlas()const { return mTexelsInAtlas ;}
- U32 getTexelsInGLTexture()const {return mTexelsInGLTexture;}
+ LLGLenum getTexTarget()const { return mTarget ;}
+ S8 getDiscardLevelInAtlas()const {return mDiscardLevelInAtlas;}
+ U32 getTexelsInAtlas()const { return mTexelsInAtlas ;}
+ U32 getTexelsInGLTexture()const {return mTexelsInGLTexture;}
-
- void init(BOOL usemipmaps);
- virtual void cleanup(); // Clean up the LLImageGL so it can be reinitialized. Be careful when using this in derived class destructors
- void setNeedsAlphaAndPickMask(BOOL need_mask);
+ void init(BOOL usemipmaps);
+ virtual void cleanup(); // Clean up the LLImageGL so it can be reinitialized. Be careful when using this in derived class destructors
- BOOL preAddToAtlas(S32 discard_level, const LLImageRaw* raw_image);
- void postAddToAtlas() ;
+ void setNeedsAlphaAndPickMask(BOOL need_mask);
+
+ BOOL preAddToAtlas(S32 discard_level, const LLImageRaw* raw_image);
+ void postAddToAtlas() ;
#if LL_IMAGEGL_THREAD_CHECK
// thread debugging
@@ -207,118 +207,118 @@ public:
#endif
public:
- // Various GL/Rendering options
- S64Bytes mTextureMemory;
- mutable F32 mLastBindTime; // last time this was bound, by discard level
-
+ // Various GL/Rendering options
+ S64Bytes mTextureMemory;
+ mutable F32 mLastBindTime; // last time this was bound, by discard level
+
private:
- U32 createPickMask(S32 pWidth, S32 pHeight);
- void freePickMask();
+ U32 createPickMask(S32 pWidth, S32 pHeight);
+ void freePickMask();
bool isCompressed();
- LLPointer<LLImageRaw> mSaveData; // used for destroyGL/restoreGL
- LL::WorkQueue::weak_t mMainQueue;
- U8* mPickMask; //downsampled bitmap approximation of alpha channel. NULL if no alpha channel
- U16 mPickMaskWidth;
- U16 mPickMaskHeight;
- S8 mUseMipMaps;
- BOOL mHasExplicitFormat; // If false (default), GL format is f(mComponents)
- bool mAutoGenMips = false;
-
- BOOL mIsMask;
- BOOL mNeedsAlphaAndPickMask;
- S8 mAlphaStride ;
- S8 mAlphaOffset ;
-
- bool mGLTextureCreated ;
- LLGLuint mTexName;
+ LLPointer<LLImageRaw> mSaveData; // used for destroyGL/restoreGL
+ LL::WorkQueue::weak_t mMainQueue;
+ U8* mPickMask; //downsampled bitmap approximation of alpha channel. NULL if no alpha channel
+ U16 mPickMaskWidth;
+ U16 mPickMaskHeight;
+ S8 mUseMipMaps;
+ BOOL mHasExplicitFormat; // If false (default), GL format is f(mComponents)
+ bool mAutoGenMips = false;
+
+ BOOL mIsMask;
+ BOOL mNeedsAlphaAndPickMask;
+ S8 mAlphaStride ;
+ S8 mAlphaOffset ;
+
+ bool mGLTextureCreated ;
+ LLGLuint mTexName;
//LLGLuint mNewTexName = 0; // tex name set by background thread to be applied in main thread
- U16 mWidth;
- U16 mHeight;
- S8 mCurrentDiscardLevel;
-
- S8 mDiscardLevelInAtlas;
- U32 mTexelsInAtlas ;
- U32 mTexelsInGLTexture;
+ U16 mWidth;
+ U16 mHeight;
+ S8 mCurrentDiscardLevel;
- bool mAllowCompression;
+ S8 mDiscardLevelInAtlas;
+ U32 mTexelsInAtlas ;
+ U32 mTexelsInGLTexture;
+
+ bool mAllowCompression;
protected:
- LLGLenum mTarget; // Normally GL_TEXTURE2D, sometimes something else (ex. cube maps)
- LLTexUnit::eTextureType mBindTarget; // Normally TT_TEXTURE, sometimes something else (ex. cube maps)
- bool mHasMipMaps;
- S32 mMipLevels;
-
- LLGLboolean mIsResident;
-
- S8 mComponents;
- S8 mMaxDiscardLevel;
-
- bool mTexOptionsDirty;
- LLTexUnit::eTextureAddressMode mAddressMode; // Defaults to TAM_WRAP
- LLTexUnit::eTextureFilterOptions mFilterOption; // Defaults to TFO_ANISOTROPIC
-
- LLGLint mFormatInternal; // = GL internalformat
- LLGLenum mFormatPrimary; // = GL format (pixel data format)
- LLGLenum mFormatType;
- BOOL mFormatSwapBytes;// if true, use glPixelStorei(GL_UNPACK_SWAP_BYTES, 1)
-
+ LLGLenum mTarget; // Normally GL_TEXTURE2D, sometimes something else (ex. cube maps)
+ LLTexUnit::eTextureType mBindTarget; // Normally TT_TEXTURE, sometimes something else (ex. cube maps)
+ bool mHasMipMaps;
+ S32 mMipLevels;
+
+ LLGLboolean mIsResident;
+
+ S8 mComponents;
+ S8 mMaxDiscardLevel;
+
+ bool mTexOptionsDirty;
+ LLTexUnit::eTextureAddressMode mAddressMode; // Defaults to TAM_WRAP
+ LLTexUnit::eTextureFilterOptions mFilterOption; // Defaults to TFO_ANISOTROPIC
+
+ LLGLint mFormatInternal; // = GL internalformat
+ LLGLenum mFormatPrimary; // = GL format (pixel data format)
+ LLGLenum mFormatType;
+ BOOL mFormatSwapBytes;// if true, use glPixelStorei(GL_UNPACK_SWAP_BYTES, 1)
+
BOOL mExternalTexture;
- // STATICS
-public:
- static std::set<LLImageGL*> sImageList;
- static S32 sCount;
-
- static F32 sLastFrameTime;
-
- // Global memory statistics
- static U32 sBindCount; // Tracks number of texture binds for current frame
- static U32 sUniqueCount; // Tracks number of unique texture binds for current frame
- static BOOL sGlobalUseAnisotropic;
- static LLImageGL* sDefaultGLTexture ;
- static BOOL sAutomatedTest;
- static bool sCompressTextures; //use GL texture compression
+ // STATICS
+public:
+ static std::set<LLImageGL*> sImageList;
+ static S32 sCount;
+
+ static F32 sLastFrameTime;
+
+ // Global memory statistics
+ static U32 sBindCount; // Tracks number of texture binds for current frame
+ static U32 sUniqueCount; // Tracks number of unique texture binds for current frame
+ static BOOL sGlobalUseAnisotropic;
+ static LLImageGL* sDefaultGLTexture ;
+ static BOOL sAutomatedTest;
+ static bool sCompressTextures; //use GL texture compression
#if DEBUG_MISS
- BOOL mMissed; // Missed on last bind?
- BOOL getMissed() const { return mMissed; };
+ BOOL mMissed; // Missed on last bind?
+ BOOL getMissed() const { return mMissed; };
#else
- BOOL getMissed() const { return FALSE; };
+ BOOL getMissed() const { return FALSE; };
#endif
public:
- static void initClass(LLWindow* window, S32 num_catagories, BOOL skip_analyze_alpha = false, bool thread_texture_loads = false, bool thread_media_updates = false);
- static void cleanupClass() ;
+ static void initClass(LLWindow* window, S32 num_catagories, BOOL skip_analyze_alpha = false, bool thread_texture_loads = false, bool thread_media_updates = false);
+ static void cleanupClass() ;
private:
- static S32 sMaxCategories;
- static BOOL sSkipAnalyzeAlpha;
-
- //the flag to allow to call readBackRaw(...).
- //can be removed if we do not use that function at all.
- static BOOL sAllowReadBackRaw ;
+ static S32 sMaxCategories;
+ static BOOL sSkipAnalyzeAlpha;
+
+ //the flag to allow to call readBackRaw(...).
+ //can be removed if we do not use that function at all.
+ static BOOL sAllowReadBackRaw ;
//
//****************************************************************************************************
//The below for texture auditing use only
//****************************************************************************************************
private:
- S32 mCategory ;
+ S32 mCategory ;
public:
- void setCategory(S32 category) {mCategory = category;}
- S32 getCategory()const {return mCategory;}
-
+ void setCategory(S32 category) {mCategory = category;}
+ S32 getCategory()const {return mCategory;}
+
void setTexName(GLuint texName) { mTexName = texName; }
//similar to setTexName, but will call deleteTextures on mTexName if mTexName is not 0 or texname
void syncTexName(LLGLuint texname);
- //for debug use: show texture size distribution
- //----------------------------------------
- static S32 sCurTexSizeBar ;
- static S32 sCurTexPickSize ;
+ //for debug use: show texture size distribution
+ //----------------------------------------
+ static S32 sCurTexSizeBar ;
+ static S32 sCurTexPickSize ;
- static void setCurTexSizebar(S32 index, BOOL set_pick_size = TRUE) ;
- static void resetCurTexSizebar();
+ static void setCurTexSizebar(S32 index, BOOL set_pick_size = TRUE) ;
+ static void resetCurTexSizebar();
//****************************************************************************************************
//End of definitions for texture auditing use only
@@ -333,7 +333,7 @@ public:
static bool sEnabledTextures;
// follows gSavedSettings "RenderGLMultiThreadedMedia"
static bool sEnabledMedia;
-
+
LLImageGLThread(LLWindow* window);
// post a function to be executed on the LLImageGL background thread
diff --git a/indra/llrender/llpostprocess.cpp b/indra/llrender/llpostprocess.cpp
index 0f8655132b..4242e330f4 100644
--- a/indra/llrender/llpostprocess.cpp
+++ b/indra/llrender/llpostprocess.cpp
@@ -1,25 +1,25 @@
-/**
+/**
* @file llpostprocess.cpp
* @brief LLPostProcess class implementation
*
* $LicenseInfo:firstyear=2007&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -51,214 +51,214 @@ LLPostProcess * gPostProcess = NULL;
static const unsigned int NOISE_SIZE = 512;
-LLPostProcess::LLPostProcess(void) :
- initialized(false),
- mAllEffects(LLSD::emptyMap()),
- screenW(1), screenH(1)
+LLPostProcess::LLPostProcess(void) :
+ initialized(false),
+ mAllEffects(LLSD::emptyMap()),
+ screenW(1), screenH(1)
{
- 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));
- LL_DEBUGS("AppInit", "Shaders") << "Loading PostProcess Effects settings from " << pathName << LL_ENDL;
-
- llifstream effectsXML(pathName);
-
- if (effectsXML)
- {
- LLPointer<LLSDParser> parser = new LLSDXMLParser();
-
- parser->parse(effectsXML, mAllEffects, LLSDSerialize::SIZE_UNLIMITED);
- }
-
- if (!mAllEffects.has("default"))
- {
- LLSD & defaultEffect = (mAllEffects["default"] = LLSD::emptyMap());
-
- defaultEffect["enable_night_vision"] = LLSD::Boolean(false);
- defaultEffect["enable_bloom"] = LLSD::Boolean(false);
- defaultEffect["enable_color_filter"] = LLSD::Boolean(false);
-
- /// NVG Defaults
- defaultEffect["brightness_multiplier"] = 3.0;
- defaultEffect["noise_size"] = 25.0;
- defaultEffect["noise_strength"] = 0.4;
-
- // TODO BTest potentially add this to tweaks?
- noiseTextureScale = 1.0f;
-
- /// Bloom Defaults
- defaultEffect["extract_low"] = 0.95;
- defaultEffect["extract_high"] = 1.0;
- defaultEffect["bloom_width"] = 2.25;
- defaultEffect["bloom_strength"] = 1.5;
-
- /// Color Filter Defaults
- defaultEffect["brightness"] = 1.0;
- defaultEffect["contrast"] = 1.0;
- defaultEffect["saturation"] = 1.0;
-
- LLSD& contrastBase = (defaultEffect["contrast_base"] = LLSD::emptyArray());
- contrastBase.append(1.0);
- contrastBase.append(1.0);
- contrastBase.append(1.0);
- contrastBase.append(0.5);
- }
-
- setSelectedEffect("default");
- */
+ 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));
+ LL_DEBUGS("AppInit", "Shaders") << "Loading PostProcess Effects settings from " << pathName << LL_ENDL;
+
+ llifstream effectsXML(pathName);
+
+ if (effectsXML)
+ {
+ LLPointer<LLSDParser> parser = new LLSDXMLParser();
+
+ parser->parse(effectsXML, mAllEffects, LLSDSerialize::SIZE_UNLIMITED);
+ }
+
+ if (!mAllEffects.has("default"))
+ {
+ LLSD & defaultEffect = (mAllEffects["default"] = LLSD::emptyMap());
+
+ defaultEffect["enable_night_vision"] = LLSD::Boolean(false);
+ defaultEffect["enable_bloom"] = LLSD::Boolean(false);
+ defaultEffect["enable_color_filter"] = LLSD::Boolean(false);
+
+ /// NVG Defaults
+ defaultEffect["brightness_multiplier"] = 3.0;
+ defaultEffect["noise_size"] = 25.0;
+ defaultEffect["noise_strength"] = 0.4;
+
+ // TODO BTest potentially add this to tweaks?
+ noiseTextureScale = 1.0f;
+
+ /// Bloom Defaults
+ defaultEffect["extract_low"] = 0.95;
+ defaultEffect["extract_high"] = 1.0;
+ defaultEffect["bloom_width"] = 2.25;
+ defaultEffect["bloom_strength"] = 1.5;
+
+ /// Color Filter Defaults
+ defaultEffect["brightness"] = 1.0;
+ defaultEffect["contrast"] = 1.0;
+ defaultEffect["saturation"] = 1.0;
+
+ LLSD& contrastBase = (defaultEffect["contrast_base"] = LLSD::emptyArray());
+ contrastBase.append(1.0);
+ contrastBase.append(1.0);
+ contrastBase.append(1.0);
+ contrastBase.append(0.5);
+ }
+
+ setSelectedEffect("default");
+ */
}
LLPostProcess::~LLPostProcess(void)
{
- invalidate() ;
+ invalidate() ;
}
// static
void LLPostProcess::initClass(void)
{
- //this will cause system to crash at second time login
- //if first time login fails due to network connection --- bao
- //***llassert_always(gPostProcess == NULL);
- //replaced by the following line:
- if(gPostProcess)
- return ;
-
-
- gPostProcess = new LLPostProcess();
+ //this will cause system to crash at second time login
+ //if first time login fails due to network connection --- bao
+ //***llassert_always(gPostProcess == NULL);
+ //replaced by the following line:
+ if(gPostProcess)
+ return ;
+
+
+ gPostProcess = new LLPostProcess();
}
// static
void LLPostProcess::cleanupClass()
{
- delete gPostProcess;
- gPostProcess = NULL;
+ delete gPostProcess;
+ gPostProcess = NULL;
}
void LLPostProcess::setSelectedEffect(std::string const & effectName)
{
- mSelectedEffectName = effectName;
- static_cast<LLSD &>(tweaks) = mAllEffects[effectName];
+ mSelectedEffectName = effectName;
+ static_cast<LLSD &>(tweaks) = mAllEffects[effectName];
}
void LLPostProcess::saveEffect(std::string const & effectName)
{
- /* Do nothing. Needs to be updated to use our current shader system, and to work with the move into llrender.
- mAllEffects[effectName] = tweaks;
+ /* Do nothing. Needs to be updated to use our current shader system, and to work with the move into llrender.
+ mAllEffects[effectName] = tweaks;
- std::string pathName(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "windlight", XML_FILENAME));
- //LL_INFOS() << "Saving PostProcess Effects settings to " << pathName << LL_ENDL;
+ std::string pathName(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "windlight", XML_FILENAME));
+ //LL_INFOS() << "Saving PostProcess Effects settings to " << pathName << LL_ENDL;
- llofstream effectsXML(pathName);
+ llofstream effectsXML(pathName);
- LLPointer<LLSDFormatter> formatter = new LLSDXMLFormatter();
+ LLPointer<LLSDFormatter> formatter = new LLSDXMLFormatter();
- formatter->format(mAllEffects, effectsXML);
- */
+ formatter->format(mAllEffects, effectsXML);
+ */
}
void LLPostProcess::invalidate()
{
- mSceneRenderTexture = NULL ;
- mNoiseTexture = NULL ;
- mTempBloomTexture = NULL ;
- initialized = FALSE ;
+ mSceneRenderTexture = NULL ;
+ mNoiseTexture = NULL ;
+ mTempBloomTexture = NULL ;
+ initialized = FALSE ;
}
void LLPostProcess::apply(unsigned int width, unsigned int height)
{
- if (!initialized || width != screenW || height != screenH){
- initialize(width, height);
- }
- if (shadersEnabled()){
- doEffects();
- }
+ if (!initialized || width != screenW || height != screenH){
+ initialize(width, height);
+ }
+ if (shadersEnabled()){
+ doEffects();
+ }
}
void LLPostProcess::initialize(unsigned int width, unsigned int height)
{
- screenW = width;
- screenH = height;
- createTexture(mSceneRenderTexture, screenW, screenH);
- initialized = true;
-
- checkError();
- createNightVisionShader();
- createBloomShader();
- createColorFilterShader();
- checkError();
+ screenW = width;
+ screenH = height;
+ createTexture(mSceneRenderTexture, screenW, screenH);
+ initialized = true;
+
+ checkError();
+ createNightVisionShader();
+ createBloomShader();
+ createColorFilterShader();
+ checkError();
}
inline bool LLPostProcess::shadersEnabled(void)
{
- return (tweaks.useColorFilter().asBoolean() ||
- tweaks.useNightVisionShader().asBoolean() ||
- tweaks.useBloomShader().asBoolean() );
+ return (tweaks.useColorFilter().asBoolean() ||
+ tweaks.useNightVisionShader().asBoolean() ||
+ tweaks.useBloomShader().asBoolean() );
}
void LLPostProcess::applyShaders(void)
{
- if (tweaks.useColorFilter()){
- applyColorFilterShader();
- checkError();
- }
- if (tweaks.useNightVisionShader()){
- /// If any of the above shaders have been called update the frame buffer;
- if (tweaks.useColorFilter())
- {
- U32 tex = mSceneRenderTexture->getTexName() ;
- copyFrameBuffer(tex, screenW, screenH);
- }
- applyNightVisionShader();
- checkError();
- }
- if (tweaks.useBloomShader()){
- /// If any of the above shaders have been called update the frame buffer;
- if (tweaks.useColorFilter().asBoolean() || tweaks.useNightVisionShader().asBoolean())
- {
- U32 tex = mSceneRenderTexture->getTexName() ;
- copyFrameBuffer(tex, screenW, screenH);
- }
- applyBloomShader();
- checkError();
- }
+ if (tweaks.useColorFilter()){
+ applyColorFilterShader();
+ checkError();
+ }
+ if (tweaks.useNightVisionShader()){
+ /// If any of the above shaders have been called update the frame buffer;
+ if (tweaks.useColorFilter())
+ {
+ U32 tex = mSceneRenderTexture->getTexName() ;
+ copyFrameBuffer(tex, screenW, screenH);
+ }
+ applyNightVisionShader();
+ checkError();
+ }
+ if (tweaks.useBloomShader()){
+ /// If any of the above shaders have been called update the frame buffer;
+ if (tweaks.useColorFilter().asBoolean() || tweaks.useNightVisionShader().asBoolean())
+ {
+ U32 tex = mSceneRenderTexture->getTexName() ;
+ copyFrameBuffer(tex, screenW, screenH);
+ }
+ applyBloomShader();
+ checkError();
+ }
}
void LLPostProcess::applyColorFilterShader(void)
-{
-
+{
+
}
void LLPostProcess::createColorFilterShader(void)
{
- /// Define uniform names
- colorFilterUniforms[sRenderTexture] = 0;
- colorFilterUniforms[sBrightness] = 0;
- colorFilterUniforms[sContrast] = 0;
- colorFilterUniforms[sContrastBase] = 0;
- colorFilterUniforms[sSaturation] = 0;
- colorFilterUniforms[sLumWeights] = 0;
+ /// Define uniform names
+ colorFilterUniforms[sRenderTexture] = 0;
+ colorFilterUniforms[sBrightness] = 0;
+ colorFilterUniforms[sContrast] = 0;
+ colorFilterUniforms[sContrastBase] = 0;
+ colorFilterUniforms[sSaturation] = 0;
+ colorFilterUniforms[sLumWeights] = 0;
}
void LLPostProcess::applyNightVisionShader(void)
-{
-
+{
+
}
void LLPostProcess::createNightVisionShader(void)
{
- /// Define uniform names
- nightVisionUniforms[sRenderTexture] = 0;
- nightVisionUniforms[sNoiseTexture] = 0;
- nightVisionUniforms[sBrightMult] = 0;
- nightVisionUniforms[sNoiseStrength] = 0;
- nightVisionUniforms[sLumWeights] = 0;
-
- createNoiseTexture(mNoiseTexture);
+ /// Define uniform names
+ nightVisionUniforms[sRenderTexture] = 0;
+ nightVisionUniforms[sNoiseTexture] = 0;
+ nightVisionUniforms[sBrightMult] = 0;
+ nightVisionUniforms[sNoiseStrength] = 0;
+ nightVisionUniforms[sLumWeights] = 0;
+
+ createNoiseTexture(mNoiseTexture);
}
void LLPostProcess::applyBloomShader(void)
@@ -268,69 +268,69 @@ void LLPostProcess::applyBloomShader(void)
void LLPostProcess::createBloomShader(void)
{
- createTexture(mTempBloomTexture, unsigned(screenW * 0.5), unsigned(screenH * 0.5));
-
- /// Create Bloom Extract Shader
- bloomExtractUniforms[sRenderTexture] = 0;
- bloomExtractUniforms[sExtractLow] = 0;
- bloomExtractUniforms[sExtractHigh] = 0;
- bloomExtractUniforms[sLumWeights] = 0;
-
- /// Create Bloom Blur Shader
- bloomBlurUniforms[sRenderTexture] = 0;
- bloomBlurUniforms[sBloomStrength] = 0;
- bloomBlurUniforms[sTexelSize] = 0;
- bloomBlurUniforms[sBlurDirection] = 0;
- bloomBlurUniforms[sBlurWidth] = 0;
+ createTexture(mTempBloomTexture, unsigned(screenW * 0.5), unsigned(screenH * 0.5));
+
+ /// Create Bloom Extract Shader
+ bloomExtractUniforms[sRenderTexture] = 0;
+ bloomExtractUniforms[sExtractLow] = 0;
+ bloomExtractUniforms[sExtractHigh] = 0;
+ bloomExtractUniforms[sLumWeights] = 0;
+
+ /// Create Bloom Blur Shader
+ bloomBlurUniforms[sRenderTexture] = 0;
+ bloomBlurUniforms[sBloomStrength] = 0;
+ bloomBlurUniforms[sTexelSize] = 0;
+ bloomBlurUniforms[sBlurDirection] = 0;
+ bloomBlurUniforms[sBlurWidth] = 0;
}
void LLPostProcess::getShaderUniforms(glslUniforms & uniforms, GLuint & prog)
{
- /// Find uniform locations and insert into map
- glslUniforms::iterator i;
- for (i = uniforms.begin(); i != uniforms.end(); ++i){
- i->second = glGetUniformLocation(prog, i->first.String().c_str());
- }
+ /// Find uniform locations and insert into map
+ glslUniforms::iterator i;
+ for (i = uniforms.begin(); i != uniforms.end(); ++i){
+ i->second = glGetUniformLocation(prog, i->first.String().c_str());
+ }
}
void LLPostProcess::doEffects(void)
{
- /// Save GL State
- glPushAttrib(GL_ALL_ATTRIB_BITS);
- glPushClientAttrib(GL_ALL_ATTRIB_BITS);
-
- /// Copy the screen buffer to the render texture
- {
- U32 tex = mSceneRenderTexture->getTexName() ;
- copyFrameBuffer(tex, screenW, screenH);
- }
-
- /// Clear the frame buffer.
- glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
- glClear(GL_COLOR_BUFFER_BIT);
-
- /// Change to an orthogonal view
- viewOrthogonal(screenW, screenH);
-
- checkError();
- applyShaders();
-
- LLGLSLShader::unbind();
- checkError();
-
- /// Change to a perspective view
- viewPerspective();
-
- /// Reset GL State
- glPopClientAttrib();
- glPopAttrib();
- checkError();
+ /// Save GL State
+ glPushAttrib(GL_ALL_ATTRIB_BITS);
+ glPushClientAttrib(GL_ALL_ATTRIB_BITS);
+
+ /// Copy the screen buffer to the render texture
+ {
+ U32 tex = mSceneRenderTexture->getTexName() ;
+ copyFrameBuffer(tex, screenW, screenH);
+ }
+
+ /// Clear the frame buffer.
+ glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ /// Change to an orthogonal view
+ viewOrthogonal(screenW, screenH);
+
+ checkError();
+ applyShaders();
+
+ LLGLSLShader::unbind();
+ checkError();
+
+ /// Change to a perspective view
+ viewPerspective();
+
+ /// Reset GL State
+ glPopClientAttrib();
+ glPopAttrib();
+ checkError();
}
void LLPostProcess::copyFrameBuffer(U32 & texture, unsigned int width, unsigned int height)
{
- gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, texture);
- glCopyTexImage2D(GL_TEXTURE_RECTANGLE, 0, GL_RGBA, 0, 0, width, height, 0);
+ gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, texture);
+ glCopyTexImage2D(GL_TEXTURE_RECTANGLE, 0, GL_RGBA, 0, 0, width, height, 0);
}
void LLPostProcess::drawOrthoQuad(unsigned int width, unsigned int height, QuadType type)
@@ -340,84 +340,84 @@ void LLPostProcess::drawOrthoQuad(unsigned int width, unsigned int height, QuadT
void LLPostProcess::viewOrthogonal(unsigned int width, unsigned int height)
{
- gGL.matrixMode(LLRender::MM_PROJECTION);
- gGL.pushMatrix();
- gGL.loadIdentity();
- gGL.ortho( 0.f, (GLdouble) width , (GLdouble) height , 0.f, -1.f, 1.f );
- gGL.matrixMode(LLRender::MM_MODELVIEW);
- gGL.pushMatrix();
- gGL.loadIdentity();
+ gGL.matrixMode(LLRender::MM_PROJECTION);
+ gGL.pushMatrix();
+ gGL.loadIdentity();
+ gGL.ortho( 0.f, (GLdouble) width , (GLdouble) height , 0.f, -1.f, 1.f );
+ gGL.matrixMode(LLRender::MM_MODELVIEW);
+ gGL.pushMatrix();
+ gGL.loadIdentity();
}
void LLPostProcess::viewPerspective(void)
{
- gGL.matrixMode(LLRender::MM_PROJECTION);
- gGL.popMatrix();
- gGL.matrixMode(LLRender::MM_MODELVIEW);
- gGL.popMatrix();
+ gGL.matrixMode(LLRender::MM_PROJECTION);
+ gGL.popMatrix();
+ gGL.matrixMode(LLRender::MM_MODELVIEW);
+ gGL.popMatrix();
}
void LLPostProcess::changeOrthogonal(unsigned int width, unsigned int height)
{
- viewPerspective();
- viewOrthogonal(width, height);
+ viewPerspective();
+ viewOrthogonal(width, height);
}
void LLPostProcess::createTexture(LLPointer<LLImageGL>& texture, unsigned int width, unsigned int height)
{
- std::vector<GLubyte> data(width * height * 4, 0) ;
-
- texture = new LLImageGL(FALSE) ;
- if(texture->createGLTexture())
- {
- gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, texture->getTexName());
- glTexImage2D(GL_TEXTURE_RECTANGLE, 0, 4, width, height, 0,
- GL_RGBA, GL_UNSIGNED_BYTE, &data[0]);
- gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
- gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
- }
+ std::vector<GLubyte> data(width * height * 4, 0) ;
+
+ texture = new LLImageGL(FALSE) ;
+ if(texture->createGLTexture())
+ {
+ gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, texture->getTexName());
+ glTexImage2D(GL_TEXTURE_RECTANGLE, 0, 4, width, height, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, &data[0]);
+ gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
+ gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
+ }
}
void LLPostProcess::createNoiseTexture(LLPointer<LLImageGL>& texture)
-{
- std::vector<GLubyte> buffer(NOISE_SIZE * NOISE_SIZE);
- for (unsigned int i = 0; i < NOISE_SIZE; i++){
- for (unsigned int k = 0; k < NOISE_SIZE; k++){
- buffer[(i * NOISE_SIZE) + k] = (GLubyte)((double) rand() / ((double) RAND_MAX + 1.f) * 255.f);
- }
- }
-
- texture = new LLImageGL(FALSE) ;
- if(texture->createGLTexture())
- {
- gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, texture->getTexName());
- LLImageGL::setManualImage(GL_TEXTURE_2D, 0, GL_LUMINANCE, NOISE_SIZE, NOISE_SIZE, GL_LUMINANCE, GL_UNSIGNED_BYTE, &buffer[0]);
- gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
- gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_WRAP);
- }
+{
+ std::vector<GLubyte> buffer(NOISE_SIZE * NOISE_SIZE);
+ for (unsigned int i = 0; i < NOISE_SIZE; i++){
+ for (unsigned int k = 0; k < NOISE_SIZE; k++){
+ buffer[(i * NOISE_SIZE) + k] = (GLubyte)((double) rand() / ((double) RAND_MAX + 1.f) * 255.f);
+ }
+ }
+
+ texture = new LLImageGL(FALSE) ;
+ if(texture->createGLTexture())
+ {
+ gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, texture->getTexName());
+ LLImageGL::setManualImage(GL_TEXTURE_2D, 0, GL_LUMINANCE, NOISE_SIZE, NOISE_SIZE, GL_LUMINANCE, GL_UNSIGNED_BYTE, &buffer[0]);
+ gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
+ gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_WRAP);
+ }
}
bool LLPostProcess::checkError(void)
{
- GLenum glErr;
+ GLenum glErr;
bool retCode = false;
glErr = glGetError();
while (glErr != GL_NO_ERROR)
{
- // shaderErrorLog << (const char *) gluErrorString(glErr) << std::endl;
- char const * err_str_raw = (const char *) gluErrorString(glErr);
-
- if(err_str_raw == NULL)
- {
- std::ostringstream err_builder;
- err_builder << "unknown error number " << glErr;
- mShaderErrorString = err_builder.str();
- }
- else
- {
- mShaderErrorString = err_str_raw;
- }
+ // shaderErrorLog << (const char *) gluErrorString(glErr) << std::endl;
+ char const * err_str_raw = (const char *) gluErrorString(glErr);
+
+ if(err_str_raw == NULL)
+ {
+ std::ostringstream err_builder;
+ err_builder << "unknown error number " << glErr;
+ mShaderErrorString = err_builder.str();
+ }
+ else
+ {
+ mShaderErrorString = err_str_raw;
+ }
retCode = true;
glErr = glGetError();
@@ -446,8 +446,8 @@ void LLPostProcess::checkShaderError(GLuint shader)
return;
}
glGetProgramInfoLog(shader, infologLength, &charsWritten, infoLog);
- // shaderErrorLog << (char *) infoLog << std::endl;
- mShaderErrorString = (char *) infoLog;
+ // shaderErrorLog << (char *) infoLog << std::endl;
+ mShaderErrorString = (char *) infoLog;
free(infoLog);
}
checkError(); // Check for OpenGL errors
diff --git a/indra/llrender/llpostprocess.h b/indra/llrender/llpostprocess.h
index bdfc632831..b5b7549efb 100644
--- a/indra/llrender/llpostprocess.h
+++ b/indra/llrender/llpostprocess.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file llpostprocess.h
* @brief LLPostProcess class definition
*
* $LicenseInfo:firstyear=2007&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -33,232 +33,232 @@
#include "llglheaders.h"
#include "llstaticstringtable.h"
-class LLPostProcess
+class LLPostProcess
{
public:
- typedef enum _QuadType {
- QUAD_NORMAL,
- QUAD_NOISE,
- QUAD_BLOOM_EXTRACT,
- QUAD_BLOOM_COMBINE
- } QuadType;
+ typedef enum _QuadType {
+ QUAD_NORMAL,
+ QUAD_NOISE,
+ QUAD_BLOOM_EXTRACT,
+ QUAD_BLOOM_COMBINE
+ } QuadType;
+
+ /// GLSL Shader Encapsulation Struct
+ typedef LLStaticStringTable<GLuint> glslUniforms;
- /// GLSL Shader Encapsulation Struct
- typedef LLStaticStringTable<GLuint> glslUniforms;
+ struct PostProcessTweaks : public LLSD {
+ inline PostProcessTweaks() : LLSD(LLSD::emptyMap())
+ {
+ }
- struct PostProcessTweaks : public LLSD {
- inline PostProcessTweaks() : LLSD(LLSD::emptyMap())
- {
- }
+ inline LLSD & brightMult() {
+ return (*this)["brightness_multiplier"];
+ }
- inline LLSD & brightMult() {
- return (*this)["brightness_multiplier"];
- }
+ inline LLSD & noiseStrength() {
+ return (*this)["noise_strength"];
+ }
- inline LLSD & noiseStrength() {
- return (*this)["noise_strength"];
- }
+ inline LLSD & noiseSize() {
+ return (*this)["noise_size"];
+ }
- inline LLSD & noiseSize() {
- return (*this)["noise_size"];
- }
+ inline LLSD & extractLow() {
+ return (*this)["extract_low"];
+ }
- inline LLSD & extractLow() {
- return (*this)["extract_low"];
- }
+ inline LLSD & extractHigh() {
+ return (*this)["extract_high"];
+ }
- inline LLSD & extractHigh() {
- return (*this)["extract_high"];
- }
+ inline LLSD & bloomWidth() {
+ return (*this)["bloom_width"];
+ }
- inline LLSD & bloomWidth() {
- return (*this)["bloom_width"];
- }
+ inline LLSD & bloomStrength() {
+ return (*this)["bloom_strength"];
+ }
- inline LLSD & bloomStrength() {
- return (*this)["bloom_strength"];
- }
+ inline LLSD & brightness() {
+ return (*this)["brightness"];
+ }
- inline LLSD & brightness() {
- return (*this)["brightness"];
- }
+ inline LLSD & contrast() {
+ return (*this)["contrast"];
+ }
- inline LLSD & contrast() {
- return (*this)["contrast"];
- }
+ inline LLSD & contrastBaseR() {
+ return (*this)["contrast_base"][0];
+ }
- inline LLSD & contrastBaseR() {
- return (*this)["contrast_base"][0];
- }
+ inline LLSD & contrastBaseG() {
+ return (*this)["contrast_base"][1];
+ }
- inline LLSD & contrastBaseG() {
- return (*this)["contrast_base"][1];
- }
+ inline LLSD & contrastBaseB() {
+ return (*this)["contrast_base"][2];
+ }
- inline LLSD & contrastBaseB() {
- return (*this)["contrast_base"][2];
- }
+ inline LLSD & contrastBaseIntensity() {
+ return (*this)["contrast_base"][3];
+ }
- inline LLSD & contrastBaseIntensity() {
- return (*this)["contrast_base"][3];
- }
+ inline LLSD & saturation() {
+ return (*this)["saturation"];
+ }
- inline LLSD & saturation() {
- return (*this)["saturation"];
- }
+ inline LLSD & useNightVisionShader() {
+ return (*this)["enable_night_vision"];
+ }
- inline LLSD & useNightVisionShader() {
- return (*this)["enable_night_vision"];
- }
+ inline LLSD & useBloomShader() {
+ return (*this)["enable_bloom"];
+ }
- inline LLSD & useBloomShader() {
- return (*this)["enable_bloom"];
- }
+ inline LLSD & useColorFilter() {
+ return (*this)["enable_color_filter"];
+ }
- inline LLSD & useColorFilter() {
- return (*this)["enable_color_filter"];
- }
+ inline F32 getBrightMult() const {
+ return F32((*this)["brightness_multiplier"].asReal());
+ }
- inline F32 getBrightMult() const {
- return F32((*this)["brightness_multiplier"].asReal());
- }
+ inline F32 getNoiseStrength() const {
+ return F32((*this)["noise_strength"].asReal());
+ }
- inline F32 getNoiseStrength() const {
- return F32((*this)["noise_strength"].asReal());
- }
+ inline F32 getNoiseSize() const {
+ return F32((*this)["noise_size"].asReal());
+ }
- inline F32 getNoiseSize() const {
- return F32((*this)["noise_size"].asReal());
- }
+ inline F32 getExtractLow() const {
+ return F32((*this)["extract_low"].asReal());
+ }
- inline F32 getExtractLow() const {
- return F32((*this)["extract_low"].asReal());
- }
+ inline F32 getExtractHigh() const {
+ return F32((*this)["extract_high"].asReal());
+ }
- inline F32 getExtractHigh() const {
- return F32((*this)["extract_high"].asReal());
- }
+ inline F32 getBloomWidth() const {
+ return F32((*this)["bloom_width"].asReal());
+ }
- inline F32 getBloomWidth() const {
- return F32((*this)["bloom_width"].asReal());
- }
+ inline F32 getBloomStrength() const {
+ return F32((*this)["bloom_strength"].asReal());
+ }
- inline F32 getBloomStrength() const {
- return F32((*this)["bloom_strength"].asReal());
- }
+ inline F32 getBrightness() const {
+ return F32((*this)["brightness"].asReal());
+ }
- inline F32 getBrightness() const {
- return F32((*this)["brightness"].asReal());
- }
+ inline F32 getContrast() const {
+ return F32((*this)["contrast"].asReal());
+ }
- inline F32 getContrast() const {
- return F32((*this)["contrast"].asReal());
- }
+ inline F32 getContrastBaseR() const {
+ return F32((*this)["contrast_base"][0].asReal());
+ }
- inline F32 getContrastBaseR() const {
- return F32((*this)["contrast_base"][0].asReal());
- }
+ inline F32 getContrastBaseG() const {
+ return F32((*this)["contrast_base"][1].asReal());
+ }
- inline F32 getContrastBaseG() const {
- return F32((*this)["contrast_base"][1].asReal());
- }
+ inline F32 getContrastBaseB() const {
+ return F32((*this)["contrast_base"][2].asReal());
+ }
- inline F32 getContrastBaseB() const {
- return F32((*this)["contrast_base"][2].asReal());
- }
+ inline F32 getContrastBaseIntensity() const {
+ return F32((*this)["contrast_base"][3].asReal());
+ }
- inline F32 getContrastBaseIntensity() const {
- return F32((*this)["contrast_base"][3].asReal());
- }
+ inline F32 getSaturation() const {
+ return F32((*this)["saturation"].asReal());
+ }
- inline F32 getSaturation() const {
- return F32((*this)["saturation"].asReal());
- }
+ };
- };
-
- bool initialized;
- PostProcessTweaks tweaks;
+ bool initialized;
+ PostProcessTweaks tweaks;
- // the map of all availible effects
- LLSD mAllEffects;
+ // the map of all availible effects
+ LLSD mAllEffects;
private:
- LLPointer<LLImageGL> mSceneRenderTexture ;
- LLPointer<LLImageGL> mNoiseTexture ;
- LLPointer<LLImageGL> mTempBloomTexture ;
+ LLPointer<LLImageGL> mSceneRenderTexture ;
+ LLPointer<LLImageGL> mNoiseTexture ;
+ LLPointer<LLImageGL> mTempBloomTexture ;
public:
- LLPostProcess(void);
+ LLPostProcess(void);
- ~LLPostProcess(void);
+ ~LLPostProcess(void);
- void apply(unsigned int width, unsigned int height);
- void invalidate() ;
+ void apply(unsigned int width, unsigned int height);
+ void invalidate() ;
- /// Perform global initialization for this class.
- static void initClass(void);
+ /// Perform global initialization for this class.
+ static void initClass(void);
- // Cleanup of global data that's only inited once per class.
- static void cleanupClass();
+ // Cleanup of global data that's only inited once per class.
+ static void cleanupClass();
- void setSelectedEffect(std::string const & effectName);
+ void setSelectedEffect(std::string const & effectName);
- inline std::string const & getSelectedEffect(void) const {
- return mSelectedEffectName;
- }
+ inline std::string const & getSelectedEffect(void) const {
+ return mSelectedEffectName;
+ }
- void saveEffect(std::string const & effectName);
+ void saveEffect(std::string const & effectName);
private:
- /// read in from file
- std::string mShaderErrorString;
- unsigned int screenW;
- unsigned int screenH;
-
- float noiseTextureScale;
-
- /// Shader Uniforms
- glslUniforms nightVisionUniforms;
- glslUniforms bloomExtractUniforms;
- glslUniforms bloomBlurUniforms;
- glslUniforms colorFilterUniforms;
-
- // the name of currently selected effect in mAllEffects
- // invariant: tweaks == mAllEffects[mSelectedEffectName]
- std::string mSelectedEffectName;
-
- /// General functions
- void initialize(unsigned int width, unsigned int height);
- void doEffects(void);
- void applyShaders(void);
- bool shadersEnabled(void);
-
- /// Night Vision Functions
- void createNightVisionShader(void);
- void applyNightVisionShader(void);
-
- /// Bloom Functions
- void createBloomShader(void);
- void applyBloomShader(void);
-
- /// Color Filter Functions
- void createColorFilterShader(void);
- void applyColorFilterShader(void);
-
- /// OpenGL Helper Functions
- void getShaderUniforms(glslUniforms & uniforms, GLuint & prog);
- void createTexture(LLPointer<LLImageGL>& texture, unsigned int width, unsigned int height);
- void copyFrameBuffer(U32 & texture, unsigned int width, unsigned int height);
- void createNoiseTexture(LLPointer<LLImageGL>& texture);
- bool checkError(void);
- void checkShaderError(GLuint shader);
- void drawOrthoQuad(unsigned int width, unsigned int height, QuadType type);
- void viewOrthogonal(unsigned int width, unsigned int height);
- void changeOrthogonal(unsigned int width, unsigned int height);
- void viewPerspective(void);
+ /// read in from file
+ std::string mShaderErrorString;
+ unsigned int screenW;
+ unsigned int screenH;
+
+ float noiseTextureScale;
+
+ /// Shader Uniforms
+ glslUniforms nightVisionUniforms;
+ glslUniforms bloomExtractUniforms;
+ glslUniforms bloomBlurUniforms;
+ glslUniforms colorFilterUniforms;
+
+ // the name of currently selected effect in mAllEffects
+ // invariant: tweaks == mAllEffects[mSelectedEffectName]
+ std::string mSelectedEffectName;
+
+ /// General functions
+ void initialize(unsigned int width, unsigned int height);
+ void doEffects(void);
+ void applyShaders(void);
+ bool shadersEnabled(void);
+
+ /// Night Vision Functions
+ void createNightVisionShader(void);
+ void applyNightVisionShader(void);
+
+ /// Bloom Functions
+ void createBloomShader(void);
+ void applyBloomShader(void);
+
+ /// Color Filter Functions
+ void createColorFilterShader(void);
+ void applyColorFilterShader(void);
+
+ /// OpenGL Helper Functions
+ void getShaderUniforms(glslUniforms & uniforms, GLuint & prog);
+ void createTexture(LLPointer<LLImageGL>& texture, unsigned int width, unsigned int height);
+ void copyFrameBuffer(U32 & texture, unsigned int width, unsigned int height);
+ void createNoiseTexture(LLPointer<LLImageGL>& texture);
+ bool checkError(void);
+ void checkShaderError(GLuint shader);
+ void drawOrthoQuad(unsigned int width, unsigned int height, QuadType type);
+ void viewOrthogonal(unsigned int width, unsigned int height);
+ void changeOrthogonal(unsigned int width, unsigned int height);
+ void viewPerspective(void);
};
extern LLPostProcess * gPostProcess;
diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp
index 4d64dc9e10..1073db3bfd 100644
--- a/indra/llrender/llrender.cpp
+++ b/indra/llrender/llrender.cpp
@@ -1,25 +1,25 @@
- /**
+ /**
* @file llrender.cpp
* @brief LLRender implementation
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -51,8 +51,8 @@ extern void APIENTRY gl_debug_callback(GLenum source,
thread_local LLRender gGL;
// Handy copies of last good GL matrices
-F32 gGLModelView[16];
-F32 gGLLastModelView[16];
+F32 gGLModelView[16];
+F32 gGLLastModelView[16];
F32 gGLLastProjection[16];
F32 gGLProjection[16];
@@ -60,7 +60,7 @@ F32 gGLProjection[16];
F32 gGLDeltaModelView[16];
F32 gGLInverseDeltaModelView[16];
-S32 gGLViewport[4];
+S32 gGLViewport[4];
U32 LLRender::sUICalls = 0;
@@ -80,113 +80,113 @@ static std::unordered_map<U64, LLVBCache> sVBCache;
static const GLenum sGLTextureType[] =
{
- GL_TEXTURE_2D,
- GL_TEXTURE_RECTANGLE,
- GL_TEXTURE_CUBE_MAP,
+ GL_TEXTURE_2D,
+ GL_TEXTURE_RECTANGLE,
+ GL_TEXTURE_CUBE_MAP,
GL_TEXTURE_CUBE_MAP_ARRAY,
- GL_TEXTURE_2D_MULTISAMPLE,
+ GL_TEXTURE_2D_MULTISAMPLE,
GL_TEXTURE_3D
};
static const GLint sGLAddressMode[] =
-{
- GL_REPEAT,
- GL_MIRRORED_REPEAT,
- GL_CLAMP_TO_EDGE
+{
+ GL_REPEAT,
+ GL_MIRRORED_REPEAT,
+ GL_CLAMP_TO_EDGE
};
const U32 immediate_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_COLOR | LLVertexBuffer::MAP_TEXCOORD0;
static const GLenum sGLBlendFactor[] =
{
- GL_ONE,
- GL_ZERO,
- GL_DST_COLOR,
- GL_SRC_COLOR,
- GL_ONE_MINUS_DST_COLOR,
- GL_ONE_MINUS_SRC_COLOR,
- GL_DST_ALPHA,
- GL_SRC_ALPHA,
- GL_ONE_MINUS_DST_ALPHA,
- GL_ONE_MINUS_SRC_ALPHA,
-
- GL_ZERO // 'BF_UNDEF'
+ GL_ONE,
+ GL_ZERO,
+ GL_DST_COLOR,
+ GL_SRC_COLOR,
+ GL_ONE_MINUS_DST_COLOR,
+ GL_ONE_MINUS_SRC_COLOR,
+ GL_DST_ALPHA,
+ GL_SRC_ALPHA,
+ GL_ONE_MINUS_DST_ALPHA,
+ GL_ONE_MINUS_SRC_ALPHA,
+
+ GL_ZERO // 'BF_UNDEF'
};
LLTexUnit::LLTexUnit(S32 index)
- : mCurrTexType(TT_NONE),
+ : mCurrTexType(TT_NONE),
mCurrColorScale(1), mCurrAlphaScale(1), mCurrTexture(0), mTexColorSpace(TCS_LINEAR),
- mHasMipMaps(false),
- mIndex(index)
+ mHasMipMaps(false),
+ mIndex(index)
{
- llassert_always(index < (S32)LL_NUM_TEXTURE_LAYERS);
+ llassert_always(index < (S32)LL_NUM_TEXTURE_LAYERS);
}
//static
U32 LLTexUnit::getInternalType(eTextureType type)
{
- return sGLTextureType[type];
+ return sGLTextureType[type];
}
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
+ // We set dirty to true so that the tex unit knows to ignore caching
+ // and we reset the cached tex unit state
- gGL.flush();
-
- glActiveTexture(GL_TEXTURE0 + mIndex);
+ gGL.flush();
- if (mCurrTexType != TT_NONE)
- {
- glBindTexture(sGLTextureType[mCurrTexType], mCurrTexture);
- }
- else
- {
- glBindTexture(GL_TEXTURE_2D, 0);
- }
+ glActiveTexture(GL_TEXTURE0 + mIndex);
+
+ if (mCurrTexType != TT_NONE)
+ {
+ glBindTexture(sGLTextureType[mCurrTexType], mCurrTexture);
+ }
+ else
+ {
+ glBindTexture(GL_TEXTURE_2D, 0);
+ }
setTextureColorSpace(mTexColorSpace);
}
void LLTexUnit::activate(void)
{
- if (mIndex < 0) return;
+ if (mIndex < 0) return;
- if ((S32)gGL.mCurrTextureUnitIndex != mIndex || gGL.mDirty)
- {
- gGL.flush();
- glActiveTexture(GL_TEXTURE0 + mIndex);
- gGL.mCurrTextureUnitIndex = mIndex;
- }
+ if ((S32)gGL.mCurrTextureUnitIndex != mIndex || gGL.mDirty)
+ {
+ gGL.flush();
+ glActiveTexture(GL_TEXTURE0 + mIndex);
+ gGL.mCurrTextureUnitIndex = mIndex;
+ }
}
void LLTexUnit::enable(eTextureType type)
{
- if (mIndex < 0) return;
+ if (mIndex < 0) return;
- if ( (mCurrTexType != type || gGL.mDirty) && (type != TT_NONE) )
- {
- activate();
- if (mCurrTexType != TT_NONE && !gGL.mDirty)
- {
- disable(); // Force a disable of a previous texture type if it's enabled.
- }
- mCurrTexType = type;
+ if ( (mCurrTexType != type || gGL.mDirty) && (type != TT_NONE) )
+ {
+ activate();
+ if (mCurrTexType != TT_NONE && !gGL.mDirty)
+ {
+ disable(); // Force a disable of a previous texture type if it's enabled.
+ }
+ mCurrTexType = type;
- gGL.flush();
- }
+ gGL.flush();
+ }
}
void LLTexUnit::disable(void)
{
- if (mIndex < 0) return;
+ if (mIndex < 0) return;
- if (mCurrTexType != TT_NONE)
- {
- unbind(mCurrTexType);
- mCurrTexType = TT_NONE;
- }
+ if (mCurrTexType != TT_NONE)
+ {
+ unbind(mCurrTexType);
+ mCurrTexType = TT_NONE;
+ }
}
void LLTexUnit::bindFast(LLTexture* texture)
@@ -211,231 +211,231 @@ void LLTexUnit::bindFast(LLTexture* texture)
bool LLTexUnit::bind(LLTexture* texture, bool for_rendering, bool forceBind)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE;
- stop_glerror();
- if (mIndex >= 0)
- {
- gGL.flush();
-
- LLImageGL* gl_tex = NULL ;
-
- if (texture != NULL && (gl_tex = texture->getGLTexture()))
- {
- if (gl_tex->getTexName()) //if texture exists
- {
- //in audit, replace the selected texture by the default one.
- if ((mCurrTexture != gl_tex->getTexName()) || forceBind)
- {
- activate();
- enable(gl_tex->getTarget());
- mCurrTexture = gl_tex->getTexName();
- glBindTexture(sGLTextureType[gl_tex->getTarget()], mCurrTexture);
- if(gl_tex->updateBindStats())
- {
- texture->setActive() ;
- texture->updateBindStatsForTester() ;
- }
- mHasMipMaps = gl_tex->mHasMipMaps;
- if (gl_tex->mTexOptionsDirty)
- {
- gl_tex->mTexOptionsDirty = false;
- setTextureAddressMode(gl_tex->mAddressMode);
- setTextureFilteringOption(gl_tex->mFilterOption);
+ stop_glerror();
+ if (mIndex >= 0)
+ {
+ gGL.flush();
+
+ LLImageGL* gl_tex = NULL ;
+
+ if (texture != NULL && (gl_tex = texture->getGLTexture()))
+ {
+ if (gl_tex->getTexName()) //if texture exists
+ {
+ //in audit, replace the selected texture by the default one.
+ if ((mCurrTexture != gl_tex->getTexName()) || forceBind)
+ {
+ activate();
+ enable(gl_tex->getTarget());
+ mCurrTexture = gl_tex->getTexName();
+ glBindTexture(sGLTextureType[gl_tex->getTarget()], mCurrTexture);
+ if(gl_tex->updateBindStats())
+ {
+ texture->setActive() ;
+ texture->updateBindStatsForTester() ;
+ }
+ mHasMipMaps = gl_tex->mHasMipMaps;
+ if (gl_tex->mTexOptionsDirty)
+ {
+ gl_tex->mTexOptionsDirty = false;
+ setTextureAddressMode(gl_tex->mAddressMode);
+ setTextureFilteringOption(gl_tex->mFilterOption);
}
setTextureColorSpace(mTexColorSpace);
- }
- }
- else
- {
- //if deleted, will re-generate it immediately
- texture->forceImmediateUpdate() ;
-
- gl_tex->forceUpdateBindStats() ;
- return texture->bindDefaultImage(mIndex);
- }
- }
- else
- {
- if (texture)
- {
- LL_DEBUGS() << "NULL LLTexUnit::bind GL image" << LL_ENDL;
- }
- else
- {
- LL_DEBUGS() << "NULL LLTexUnit::bind texture" << LL_ENDL;
- }
- return false;
- }
- }
- else
- { // mIndex < 0
- return false;
- }
-
- return true;
+ }
+ }
+ else
+ {
+ //if deleted, will re-generate it immediately
+ texture->forceImmediateUpdate() ;
+
+ gl_tex->forceUpdateBindStats() ;
+ return texture->bindDefaultImage(mIndex);
+ }
+ }
+ else
+ {
+ if (texture)
+ {
+ LL_DEBUGS() << "NULL LLTexUnit::bind GL image" << LL_ENDL;
+ }
+ else
+ {
+ LL_DEBUGS() << "NULL LLTexUnit::bind texture" << LL_ENDL;
+ }
+ return false;
+ }
+ }
+ else
+ { // mIndex < 0
+ return false;
+ }
+
+ return true;
}
bool LLTexUnit::bind(LLImageGL* texture, bool for_rendering, bool forceBind, S32 usename)
{
- stop_glerror();
- if (mIndex < 0) return false;
+ stop_glerror();
+ if (mIndex < 0) return false;
U32 texname = usename ? usename : texture->getTexName();
- if(!texture)
- {
- LL_DEBUGS() << "NULL LLTexUnit::bind texture" << LL_ENDL;
- return false;
- }
-
- if(!texname)
- {
- if(LLImageGL::sDefaultGLTexture && LLImageGL::sDefaultGLTexture->getTexName())
- {
- return bind(LLImageGL::sDefaultGLTexture) ;
- }
- stop_glerror();
- return false ;
- }
-
- if ((mCurrTexture != texname) || forceBind)
- {
- gGL.flush();
- stop_glerror();
- activate();
- stop_glerror();
- enable(texture->getTarget());
- stop_glerror();
- mCurrTexture = texname;
- glBindTexture(sGLTextureType[texture->getTarget()], mCurrTexture);
- stop_glerror();
+ if(!texture)
+ {
+ LL_DEBUGS() << "NULL LLTexUnit::bind texture" << LL_ENDL;
+ return false;
+ }
+
+ if(!texname)
+ {
+ if(LLImageGL::sDefaultGLTexture && LLImageGL::sDefaultGLTexture->getTexName())
+ {
+ return bind(LLImageGL::sDefaultGLTexture) ;
+ }
+ stop_glerror();
+ return false ;
+ }
+
+ if ((mCurrTexture != texname) || forceBind)
+ {
+ gGL.flush();
+ stop_glerror();
+ activate();
+ stop_glerror();
+ enable(texture->getTarget());
+ stop_glerror();
+ mCurrTexture = texname;
+ glBindTexture(sGLTextureType[texture->getTarget()], mCurrTexture);
+ stop_glerror();
texture->updateBindStats();
- mHasMipMaps = texture->mHasMipMaps;
- if (texture->mTexOptionsDirty)
- {
- stop_glerror();
- texture->mTexOptionsDirty = false;
- setTextureAddressMode(texture->mAddressMode);
- setTextureFilteringOption(texture->mFilterOption);
- stop_glerror();
- }
+ mHasMipMaps = texture->mHasMipMaps;
+ if (texture->mTexOptionsDirty)
+ {
+ stop_glerror();
+ texture->mTexOptionsDirty = false;
+ setTextureAddressMode(texture->mAddressMode);
+ setTextureFilteringOption(texture->mFilterOption);
+ stop_glerror();
+ }
setTextureColorSpace(mTexColorSpace);
- }
+ }
- stop_glerror();
+ stop_glerror();
- return true;
+ return true;
}
bool LLTexUnit::bind(LLCubeMap* cubeMap)
{
- if (mIndex < 0) return false;
+ if (mIndex < 0) return false;
- gGL.flush();
+ gGL.flush();
- if (cubeMap == NULL)
- {
- LL_WARNS() << "NULL LLTexUnit::bind cubemap" << LL_ENDL;
- return false;
- }
+ if (cubeMap == NULL)
+ {
+ LL_WARNS() << "NULL LLTexUnit::bind cubemap" << LL_ENDL;
+ return false;
+ }
- if (mCurrTexture != cubeMap->mImages[0]->getTexName())
- {
- if (LLCubeMap::sUseCubeMaps)
- {
- activate();
- enable(LLTexUnit::TT_CUBE_MAP);
+ if (mCurrTexture != cubeMap->mImages[0]->getTexName())
+ {
+ if (LLCubeMap::sUseCubeMaps)
+ {
+ activate();
+ enable(LLTexUnit::TT_CUBE_MAP);
mCurrTexture = cubeMap->mImages[0]->getTexName();
- glBindTexture(GL_TEXTURE_CUBE_MAP, mCurrTexture);
- mHasMipMaps = cubeMap->mImages[0]->mHasMipMaps;
- cubeMap->mImages[0]->updateBindStats();
- if (cubeMap->mImages[0]->mTexOptionsDirty)
- {
- cubeMap->mImages[0]->mTexOptionsDirty = false;
- setTextureAddressMode(cubeMap->mImages[0]->mAddressMode);
- setTextureFilteringOption(cubeMap->mImages[0]->mFilterOption);
+ glBindTexture(GL_TEXTURE_CUBE_MAP, mCurrTexture);
+ mHasMipMaps = cubeMap->mImages[0]->mHasMipMaps;
+ cubeMap->mImages[0]->updateBindStats();
+ if (cubeMap->mImages[0]->mTexOptionsDirty)
+ {
+ cubeMap->mImages[0]->mTexOptionsDirty = false;
+ setTextureAddressMode(cubeMap->mImages[0]->mAddressMode);
+ setTextureFilteringOption(cubeMap->mImages[0]->mFilterOption);
}
setTextureColorSpace(mTexColorSpace);
- return true;
- }
- else
- {
- LL_WARNS() << "Using cube map without extension!" << LL_ENDL;
- return false;
- }
- }
- return true;
+ return true;
+ }
+ else
+ {
+ LL_WARNS() << "Using cube map without extension!" << LL_ENDL;
+ return false;
+ }
+ }
+ return true;
}
// LLRenderTarget is unavailible on the mapserver since it uses FBOs.
bool LLTexUnit::bind(LLRenderTarget* renderTarget, bool bindDepth)
{
- if (mIndex < 0) return false;
+ if (mIndex < 0) return false;
- gGL.flush();
+ gGL.flush();
- if (bindDepth)
- {
+ if (bindDepth)
+ {
llassert(renderTarget->getDepth()); // target MUST have a depth buffer attachment
- bindManual(renderTarget->getUsage(), renderTarget->getDepth());
- }
- else
- {
- bindManual(renderTarget->getUsage(), renderTarget->getTexture());
- }
+ bindManual(renderTarget->getUsage(), renderTarget->getDepth());
+ }
+ else
+ {
+ bindManual(renderTarget->getUsage(), renderTarget->getTexture());
+ }
- return true;
+ return true;
}
bool LLTexUnit::bindManual(eTextureType type, U32 texture, bool hasMips)
{
- if (mIndex < 0)
- {
- return false;
- }
-
- if(mCurrTexture != texture)
- {
- gGL.flush();
-
- activate();
- enable(type);
- mCurrTexture = texture;
- glBindTexture(sGLTextureType[type], texture);
+ if (mIndex < 0)
+ {
+ return false;
+ }
+
+ if(mCurrTexture != texture)
+ {
+ gGL.flush();
+
+ activate();
+ enable(type);
+ mCurrTexture = texture;
+ glBindTexture(sGLTextureType[type], texture);
mHasMipMaps = hasMips;
setTextureColorSpace(mTexColorSpace);
- }
- return true;
+ }
+ return true;
}
void LLTexUnit::unbind(eTextureType type)
{
- stop_glerror();
+ stop_glerror();
- if (mIndex < 0) return;
+ if (mIndex < 0) return;
- //always flush and activate for consistency
- // some code paths assume unbind always flushes and sets the active texture
- gGL.flush();
- activate();
+ //always flush and activate for consistency
+ // some code paths assume unbind always flushes and sets the active texture
+ gGL.flush();
+ activate();
- // Disabled caching of binding state.
- if (mCurrTexType == type)
- {
- mCurrTexture = 0;
+ // Disabled caching of binding state.
+ if (mCurrTexType == type)
+ {
+ mCurrTexture = 0;
// Always make sure our texture color space is reset to linear. SRGB sampling should be opt-in in the vast majority of cases. Also prevents color space "popping".
mTexColorSpace = TCS_LINEAR;
- if (type == LLTexUnit::TT_TEXTURE)
- {
- glBindTexture(sGLTextureType[type], sWhiteTexture);
- }
- else
- {
- glBindTexture(sGLTextureType[type], 0);
- }
- stop_glerror();
- }
+ if (type == LLTexUnit::TT_TEXTURE)
+ {
+ glBindTexture(sGLTextureType[type], sWhiteTexture);
+ }
+ else
+ {
+ glBindTexture(sGLTextureType[type], 0);
+ }
+ stop_glerror();
+ }
}
void LLTexUnit::unbindFast(eTextureType type)
@@ -462,184 +462,184 @@ void LLTexUnit::unbindFast(eTextureType type)
void LLTexUnit::setTextureAddressMode(eTextureAddressMode mode)
{
- if (mIndex < 0 || mCurrTexture == 0) return;
+ if (mIndex < 0 || mCurrTexture == 0) return;
- gGL.flush();
+ gGL.flush();
- activate();
+ activate();
- glTexParameteri (sGLTextureType[mCurrTexType], GL_TEXTURE_WRAP_S, sGLAddressMode[mode]);
- glTexParameteri (sGLTextureType[mCurrTexType], GL_TEXTURE_WRAP_T, sGLAddressMode[mode]);
- if (mCurrTexType == TT_CUBE_MAP)
- {
- glTexParameteri (GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, sGLAddressMode[mode]);
- }
+ glTexParameteri (sGLTextureType[mCurrTexType], GL_TEXTURE_WRAP_S, sGLAddressMode[mode]);
+ glTexParameteri (sGLTextureType[mCurrTexType], GL_TEXTURE_WRAP_T, sGLAddressMode[mode]);
+ if (mCurrTexType == TT_CUBE_MAP)
+ {
+ glTexParameteri (GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, sGLAddressMode[mode]);
+ }
}
void LLTexUnit::setTextureFilteringOption(LLTexUnit::eTextureFilterOptions option)
{
- if (mIndex < 0 || mCurrTexture == 0 || mCurrTexType == LLTexUnit::TT_MULTISAMPLE_TEXTURE) return;
-
- gGL.flush();
-
- if (option == TFO_POINT)
- {
- glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- }
- else
- {
- glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- }
-
- if (option >= TFO_TRILINEAR && mHasMipMaps)
- {
- glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
- }
- else if (option >= TFO_BILINEAR)
- {
- if (mHasMipMaps)
- {
- glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
- }
- else
- {
- glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- }
- }
- else
- {
- if (mHasMipMaps)
- {
- glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
- }
- else
- {
- glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- }
- }
-
- if (gGLManager.mGLVersion >= 4.59f)
- {
- if (LLImageGL::sGlobalUseAnisotropic && option == TFO_ANISOTROPIC)
- {
- glTexParameterf(sGLTextureType[mCurrTexType], GL_TEXTURE_MAX_ANISOTROPY, gGLManager.mMaxAnisotropy);
- }
- else
- {
- glTexParameterf(sGLTextureType[mCurrTexType], GL_TEXTURE_MAX_ANISOTROPY, 1.f);
- }
- }
+ if (mIndex < 0 || mCurrTexture == 0 || mCurrTexType == LLTexUnit::TT_MULTISAMPLE_TEXTURE) return;
+
+ gGL.flush();
+
+ if (option == TFO_POINT)
+ {
+ glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ }
+ else
+ {
+ glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ }
+
+ if (option >= TFO_TRILINEAR && mHasMipMaps)
+ {
+ glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
+ }
+ else if (option >= TFO_BILINEAR)
+ {
+ if (mHasMipMaps)
+ {
+ glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
+ }
+ else
+ {
+ glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ }
+ }
+ else
+ {
+ if (mHasMipMaps)
+ {
+ glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
+ }
+ else
+ {
+ glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ }
+ }
+
+ if (gGLManager.mGLVersion >= 4.59f)
+ {
+ if (LLImageGL::sGlobalUseAnisotropic && option == TFO_ANISOTROPIC)
+ {
+ glTexParameterf(sGLTextureType[mCurrTexType], GL_TEXTURE_MAX_ANISOTROPY, gGLManager.mMaxAnisotropy);
+ }
+ else
+ {
+ glTexParameterf(sGLTextureType[mCurrTexType], GL_TEXTURE_MAX_ANISOTROPY, 1.f);
+ }
+ }
}
GLint LLTexUnit::getTextureSource(eTextureBlendSrc src)
{
- switch(src)
- {
- // All four cases should return the same value.
- case TBS_PREV_COLOR:
- case TBS_PREV_ALPHA:
- case TBS_ONE_MINUS_PREV_COLOR:
- case TBS_ONE_MINUS_PREV_ALPHA:
- return GL_PREVIOUS;
-
- // All four cases should return the same value.
- case TBS_TEX_COLOR:
- case TBS_TEX_ALPHA:
- case TBS_ONE_MINUS_TEX_COLOR:
- case TBS_ONE_MINUS_TEX_ALPHA:
- return GL_TEXTURE;
-
- // All four cases should return the same value.
- case TBS_VERT_COLOR:
- case TBS_VERT_ALPHA:
- case TBS_ONE_MINUS_VERT_COLOR:
- case TBS_ONE_MINUS_VERT_ALPHA:
- return GL_PRIMARY_COLOR;
-
- // All four cases should return the same value.
- case TBS_CONST_COLOR:
- case TBS_CONST_ALPHA:
- case TBS_ONE_MINUS_CONST_COLOR:
- case TBS_ONE_MINUS_CONST_ALPHA:
- return GL_CONSTANT;
-
- default:
- LL_WARNS() << "Unknown eTextureBlendSrc: " << src << ". Using Vertex Color instead." << LL_ENDL;
- return GL_PRIMARY_COLOR;
- }
+ switch(src)
+ {
+ // All four cases should return the same value.
+ case TBS_PREV_COLOR:
+ case TBS_PREV_ALPHA:
+ case TBS_ONE_MINUS_PREV_COLOR:
+ case TBS_ONE_MINUS_PREV_ALPHA:
+ return GL_PREVIOUS;
+
+ // All four cases should return the same value.
+ case TBS_TEX_COLOR:
+ case TBS_TEX_ALPHA:
+ case TBS_ONE_MINUS_TEX_COLOR:
+ case TBS_ONE_MINUS_TEX_ALPHA:
+ return GL_TEXTURE;
+
+ // All four cases should return the same value.
+ case TBS_VERT_COLOR:
+ case TBS_VERT_ALPHA:
+ case TBS_ONE_MINUS_VERT_COLOR:
+ case TBS_ONE_MINUS_VERT_ALPHA:
+ return GL_PRIMARY_COLOR;
+
+ // All four cases should return the same value.
+ case TBS_CONST_COLOR:
+ case TBS_CONST_ALPHA:
+ case TBS_ONE_MINUS_CONST_COLOR:
+ case TBS_ONE_MINUS_CONST_ALPHA:
+ return GL_CONSTANT;
+
+ default:
+ LL_WARNS() << "Unknown eTextureBlendSrc: " << src << ". Using Vertex Color instead." << LL_ENDL;
+ return GL_PRIMARY_COLOR;
+ }
}
GLint LLTexUnit::getTextureSourceType(eTextureBlendSrc src, bool isAlpha)
{
- switch(src)
- {
- // All four cases should return the same value.
- case TBS_PREV_COLOR:
- case TBS_TEX_COLOR:
- case TBS_VERT_COLOR:
- case TBS_CONST_COLOR:
- return (isAlpha) ? GL_SRC_ALPHA: GL_SRC_COLOR;
-
- // All four cases should return the same value.
- case TBS_PREV_ALPHA:
- case TBS_TEX_ALPHA:
- case TBS_VERT_ALPHA:
- case TBS_CONST_ALPHA:
- return GL_SRC_ALPHA;
-
- // All four cases should return the same value.
- case TBS_ONE_MINUS_PREV_COLOR:
- case TBS_ONE_MINUS_TEX_COLOR:
- case TBS_ONE_MINUS_VERT_COLOR:
- case TBS_ONE_MINUS_CONST_COLOR:
- return (isAlpha) ? GL_ONE_MINUS_SRC_ALPHA : GL_ONE_MINUS_SRC_COLOR;
-
- // All four cases should return the same value.
- case TBS_ONE_MINUS_PREV_ALPHA:
- case TBS_ONE_MINUS_TEX_ALPHA:
- case TBS_ONE_MINUS_VERT_ALPHA:
- case TBS_ONE_MINUS_CONST_ALPHA:
- return GL_ONE_MINUS_SRC_ALPHA;
-
- default:
- LL_WARNS() << "Unknown eTextureBlendSrc: " << src << ". Using Source Color or Alpha instead." << LL_ENDL;
- return (isAlpha) ? GL_SRC_ALPHA: GL_SRC_COLOR;
- }
+ switch(src)
+ {
+ // All four cases should return the same value.
+ case TBS_PREV_COLOR:
+ case TBS_TEX_COLOR:
+ case TBS_VERT_COLOR:
+ case TBS_CONST_COLOR:
+ return (isAlpha) ? GL_SRC_ALPHA: GL_SRC_COLOR;
+
+ // All four cases should return the same value.
+ case TBS_PREV_ALPHA:
+ case TBS_TEX_ALPHA:
+ case TBS_VERT_ALPHA:
+ case TBS_CONST_ALPHA:
+ return GL_SRC_ALPHA;
+
+ // All four cases should return the same value.
+ case TBS_ONE_MINUS_PREV_COLOR:
+ case TBS_ONE_MINUS_TEX_COLOR:
+ case TBS_ONE_MINUS_VERT_COLOR:
+ case TBS_ONE_MINUS_CONST_COLOR:
+ return (isAlpha) ? GL_ONE_MINUS_SRC_ALPHA : GL_ONE_MINUS_SRC_COLOR;
+
+ // All four cases should return the same value.
+ case TBS_ONE_MINUS_PREV_ALPHA:
+ case TBS_ONE_MINUS_TEX_ALPHA:
+ case TBS_ONE_MINUS_VERT_ALPHA:
+ case TBS_ONE_MINUS_CONST_ALPHA:
+ return GL_ONE_MINUS_SRC_ALPHA;
+
+ default:
+ LL_WARNS() << "Unknown eTextureBlendSrc: " << src << ". Using Source Color or Alpha instead." << LL_ENDL;
+ return (isAlpha) ? GL_SRC_ALPHA: GL_SRC_COLOR;
+ }
}
void LLTexUnit::setColorScale(S32 scale)
{
- if (mCurrColorScale != scale || gGL.mDirty)
- {
- mCurrColorScale = scale;
- gGL.flush();
- glTexEnvi( GL_TEXTURE_ENV, GL_RGB_SCALE, scale );
- }
+ if (mCurrColorScale != scale || gGL.mDirty)
+ {
+ mCurrColorScale = scale;
+ gGL.flush();
+ glTexEnvi( GL_TEXTURE_ENV, GL_RGB_SCALE, scale );
+ }
}
void LLTexUnit::setAlphaScale(S32 scale)
{
- if (mCurrAlphaScale != scale || gGL.mDirty)
- {
- mCurrAlphaScale = scale;
- gGL.flush();
- glTexEnvi( GL_TEXTURE_ENV, GL_ALPHA_SCALE, scale );
- }
+ if (mCurrAlphaScale != scale || gGL.mDirty)
+ {
+ mCurrAlphaScale = scale;
+ gGL.flush();
+ glTexEnvi( GL_TEXTURE_ENV, GL_ALPHA_SCALE, scale );
+ }
}
-// Useful for debugging that you've manually assigned a texture operation to the correct
+// Useful for debugging that you've manually assigned a texture operation to the correct
// texture unit based on the currently set active texture in opengl.
void LLTexUnit::debugTextureUnit(void)
{
- if (mIndex < 0) return;
+ if (mIndex < 0) return;
- GLint activeTexture;
- glGetIntegerv(GL_ACTIVE_TEXTURE, &activeTexture);
- if ((GL_TEXTURE0 + mIndex) != activeTexture)
- {
- U32 set_unit = (activeTexture - GL_TEXTURE0);
- LL_WARNS() << "Incorrect Texture Unit! Expected: " << set_unit << " Actual: " << mIndex << LL_ENDL;
- }
+ GLint activeTexture;
+ glGetIntegerv(GL_ACTIVE_TEXTURE, &activeTexture);
+ if ((GL_TEXTURE0 + mIndex) != activeTexture)
+ {
+ U32 set_unit = (activeTexture - GL_TEXTURE0);
+ LL_WARNS() << "Incorrect Texture Unit! Expected: " << set_unit << " Actual: " << mIndex << LL_ENDL;
+ }
}
void LLTexUnit::setTextureColorSpace(eTextureColorSpace space)
@@ -656,46 +656,46 @@ LLLightState::LLLightState(S32 index)
mSpotExponent(0.f),
mSpotCutoff(180.f)
{
- if (mIndex == 0)
- {
- mDiffuse.set(1,1,1,1);
+ if (mIndex == 0)
+ {
+ mDiffuse.set(1,1,1,1);
mDiffuseB.set(0,0,0,0);
- mSpecular.set(1,1,1,1);
- }
+ mSpecular.set(1,1,1,1);
+ }
mSunIsPrimary = true;
- mAmbient.set(0,0,0,1);
- mPosition.set(0,0,1,0);
- mSpotDirection.set(0,0,-1);
+ mAmbient.set(0,0,0,1);
+ mPosition.set(0,0,1,0);
+ mSpotDirection.set(0,0,-1);
}
void LLLightState::enable()
{
- mEnabled = true;
+ mEnabled = true;
}
void LLLightState::disable()
{
- mEnabled = false;
+ mEnabled = false;
}
void LLLightState::setDiffuse(const LLColor4& diffuse)
{
- if (mDiffuse != diffuse)
- {
- ++gGL.mLightHash;
- mDiffuse = diffuse;
- }
+ if (mDiffuse != diffuse)
+ {
+ ++gGL.mLightHash;
+ mDiffuse = diffuse;
+ }
}
void LLLightState::setDiffuseB(const LLColor4& diffuse)
{
if (mDiffuseB != diffuse)
- {
- ++gGL.mLightHash;
- mDiffuseB = diffuse;
- }
+ {
+ ++gGL.mLightHash;
+ mDiffuseB = diffuse;
+ }
}
void LLLightState::setSunPrimary(bool v)
@@ -703,7 +703,7 @@ void LLLightState::setSunPrimary(bool v)
if (mSunIsPrimary != v)
{
++gGL.mLightHash;
- mSunIsPrimary = v;
+ mSunIsPrimary = v;
}
}
@@ -727,134 +727,134 @@ void LLLightState::setFalloff(F32 v)
void LLLightState::setAmbient(const LLColor4& ambient)
{
- if (mAmbient != ambient)
- {
- ++gGL.mLightHash;
- mAmbient = ambient;
- }
+ if (mAmbient != ambient)
+ {
+ ++gGL.mLightHash;
+ mAmbient = ambient;
+ }
}
void LLLightState::setSpecular(const LLColor4& specular)
{
- if (mSpecular != specular)
- {
- ++gGL.mLightHash;
- mSpecular = specular;
- }
+ if (mSpecular != specular)
+ {
+ ++gGL.mLightHash;
+ mSpecular = specular;
+ }
}
void LLLightState::setPosition(const LLVector4& position)
{
- //always set position because modelview matrix may have changed
- ++gGL.mLightHash;
- mPosition = position;
- //transform position by current modelview matrix
- glh::vec4f pos(position.mV);
- const glh::matrix4f& mat = gGL.getModelviewMatrix();
- mat.mult_matrix_vec(pos);
- mPosition.set(pos.v);
+ //always set position because modelview matrix may have changed
+ ++gGL.mLightHash;
+ mPosition = position;
+ //transform position by current modelview matrix
+ glh::vec4f pos(position.mV);
+ const glh::matrix4f& mat = gGL.getModelviewMatrix();
+ mat.mult_matrix_vec(pos);
+ mPosition.set(pos.v);
}
void LLLightState::setConstantAttenuation(const F32& atten)
{
- if (mConstantAtten != atten)
- {
- mConstantAtten = atten;
- ++gGL.mLightHash;
- }
+ if (mConstantAtten != atten)
+ {
+ mConstantAtten = atten;
+ ++gGL.mLightHash;
+ }
}
void LLLightState::setLinearAttenuation(const F32& atten)
{
- if (mLinearAtten != atten)
- {
- ++gGL.mLightHash;
- mLinearAtten = atten;
- }
+ if (mLinearAtten != atten)
+ {
+ ++gGL.mLightHash;
+ mLinearAtten = atten;
+ }
}
void LLLightState::setQuadraticAttenuation(const F32& atten)
{
- if (mQuadraticAtten != atten)
- {
- ++gGL.mLightHash;
- mQuadraticAtten = atten;
- }
+ if (mQuadraticAtten != atten)
+ {
+ ++gGL.mLightHash;
+ mQuadraticAtten = atten;
+ }
}
void LLLightState::setSpotExponent(const F32& exponent)
{
- if (mSpotExponent != exponent)
- {
- ++gGL.mLightHash;
- mSpotExponent = exponent;
- }
+ if (mSpotExponent != exponent)
+ {
+ ++gGL.mLightHash;
+ mSpotExponent = exponent;
+ }
}
void LLLightState::setSpotCutoff(const F32& cutoff)
{
- if (mSpotCutoff != cutoff)
- {
- ++gGL.mLightHash;
- mSpotCutoff = cutoff;
- }
+ if (mSpotCutoff != cutoff)
+ {
+ ++gGL.mLightHash;
+ mSpotCutoff = cutoff;
+ }
}
void LLLightState::setSpotDirection(const LLVector3& direction)
{
- //always set direction because modelview matrix may have changed
- ++gGL.mLightHash;
- mSpotDirection = direction;
- //transform direction by current modelview matrix
- glh::vec3f dir(direction.mV);
- const glh::matrix4f& mat = gGL.getModelviewMatrix();
- mat.mult_matrix_dir(dir);
+ //always set direction because modelview matrix may have changed
+ ++gGL.mLightHash;
+ mSpotDirection = direction;
+ //transform direction by current modelview matrix
+ glh::vec3f dir(direction.mV);
+ const glh::matrix4f& mat = gGL.getModelviewMatrix();
+ mat.mult_matrix_dir(dir);
- mSpotDirection.set(dir.v);
+ mSpotDirection.set(dir.v);
}
LLRender::LLRender()
: mDirty(false),
mCount(0),
- mQuadCycle(0),
+ mQuadCycle(0),
mMode(LLRender::TRIANGLES),
mCurrTextureUnitIndex(0)
-{
- for (U32 i = 0; i < LL_NUM_TEXTURE_LAYERS; i++)
- {
+{
+ for (U32 i = 0; i < LL_NUM_TEXTURE_LAYERS; i++)
+ {
mTexUnits[i].mIndex = i;
- }
+ }
- for (U32 i = 0; i < LL_NUM_LIGHT_UNITS; ++i)
- {
+ for (U32 i = 0; i < LL_NUM_LIGHT_UNITS; ++i)
+ {
mLightState[i].mIndex = i;
- }
+ }
- for (U32 i = 0; i < 4; i++)
- {
- mCurrColorMask[i] = true;
- }
+ for (U32 i = 0; i < 4; i++)
+ {
+ mCurrColorMask[i] = true;
+ }
- mCurrBlendColorSFactor = BF_UNDEF;
- mCurrBlendAlphaSFactor = BF_UNDEF;
- mCurrBlendColorDFactor = BF_UNDEF;
- mCurrBlendAlphaDFactor = BF_UNDEF;
+ mCurrBlendColorSFactor = BF_UNDEF;
+ mCurrBlendAlphaSFactor = BF_UNDEF;
+ mCurrBlendColorDFactor = BF_UNDEF;
+ mCurrBlendAlphaDFactor = BF_UNDEF;
- mMatrixMode = LLRender::MM_MODELVIEW;
-
- for (U32 i = 0; i < NUM_MATRIX_MODES; ++i)
- {
- mMatIdx[i] = 0;
- mMatHash[i] = 0;
- mCurMatHash[i] = 0xFFFFFFFF;
- }
+ mMatrixMode = LLRender::MM_MODELVIEW;
- mLightHash = 0;
+ for (U32 i = 0; i < NUM_MATRIX_MODES; ++i)
+ {
+ mMatIdx[i] = 0;
+ mMatHash[i] = 0;
+ mCurMatHash[i] = 0xFFFFFFFF;
+ }
+
+ mLightHash = 0;
}
LLRender::~LLRender()
{
- shutdown();
+ shutdown();
}
bool LLRender::init(bool needs_vertex_buffer)
@@ -923,22 +923,22 @@ void LLRender::shutdown()
void LLRender::refreshState(void)
{
- mDirty = true;
+ mDirty = true;
+
+ U32 active_unit = mCurrTextureUnitIndex;
- U32 active_unit = mCurrTextureUnitIndex;
+ for (U32 i = 0; i < mTexUnits.size(); i++)
+ {
+ mTexUnits[i].refreshState();
+ }
- for (U32 i = 0; i < mTexUnits.size(); i++)
- {
- mTexUnits[i].refreshState();
- }
-
- mTexUnits[active_unit].activate();
+ mTexUnits[active_unit].activate();
+
+ setColorMask(mCurrColorMask[0], mCurrColorMask[1], mCurrColorMask[2], mCurrColorMask[3]);
- setColorMask(mCurrColorMask[0], mCurrColorMask[1], mCurrColorMask[2], mCurrColorMask[3]);
-
flush();
- mDirty = false;
+ mDirty = false;
}
void LLRender::syncLightState()
@@ -990,36 +990,36 @@ void LLRender::syncLightState()
void LLRender::syncMatrices()
{
- static const U32 name[] =
- {
- LLShaderMgr::MODELVIEW_MATRIX,
- LLShaderMgr::PROJECTION_MATRIX,
- LLShaderMgr::TEXTURE_MATRIX0,
- LLShaderMgr::TEXTURE_MATRIX1,
- LLShaderMgr::TEXTURE_MATRIX2,
- LLShaderMgr::TEXTURE_MATRIX3,
- };
+ static const U32 name[] =
+ {
+ LLShaderMgr::MODELVIEW_MATRIX,
+ LLShaderMgr::PROJECTION_MATRIX,
+ LLShaderMgr::TEXTURE_MATRIX0,
+ LLShaderMgr::TEXTURE_MATRIX1,
+ LLShaderMgr::TEXTURE_MATRIX2,
+ LLShaderMgr::TEXTURE_MATRIX3,
+ };
- LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr;
+ LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr;
- static glh::matrix4f cached_mvp;
+ static glh::matrix4f cached_mvp;
static glh::matrix4f cached_inv_mdv;
- static U32 cached_mvp_mdv_hash = 0xFFFFFFFF;
- static U32 cached_mvp_proj_hash = 0xFFFFFFFF;
-
- static glh::matrix4f cached_normal;
- static U32 cached_normal_hash = 0xFFFFFFFF;
+ static U32 cached_mvp_mdv_hash = 0xFFFFFFFF;
+ static U32 cached_mvp_proj_hash = 0xFFFFFFFF;
+
+ static glh::matrix4f cached_normal;
+ static U32 cached_normal_hash = 0xFFFFFFFF;
- if (shader)
- {
- //llassert(shader);
+ if (shader)
+ {
+ //llassert(shader);
- bool mvp_done = false;
+ bool mvp_done = false;
- U32 i = MM_MODELVIEW;
- if (mMatHash[MM_MODELVIEW] != shader->mMatHash[MM_MODELVIEW])
- { //update modelview, normal, and MVP
- glh::matrix4f& mat = mMatrix[MM_MODELVIEW][mMatIdx[MM_MODELVIEW]];
+ U32 i = MM_MODELVIEW;
+ if (mMatHash[MM_MODELVIEW] != shader->mMatHash[MM_MODELVIEW])
+ { //update modelview, normal, and MVP
+ glh::matrix4f& mat = mMatrix[MM_MODELVIEW][mMatIdx[MM_MODELVIEW]];
// if MDV has changed, update the cached inverse as well
if (cached_mvp_mdv_hash != mMatHash[MM_MODELVIEW])
@@ -1027,240 +1027,240 @@ void LLRender::syncMatrices()
cached_inv_mdv = mat.inverse();
}
- shader->uniformMatrix4fv(name[MM_MODELVIEW], 1, GL_FALSE, mat.m);
- shader->mMatHash[MM_MODELVIEW] = mMatHash[MM_MODELVIEW];
+ shader->uniformMatrix4fv(name[MM_MODELVIEW], 1, GL_FALSE, mat.m);
+ shader->mMatHash[MM_MODELVIEW] = mMatHash[MM_MODELVIEW];
- //update normal matrix
- S32 loc = shader->getUniformLocation(LLShaderMgr::NORMAL_MATRIX);
- if (loc > -1)
- {
- if (cached_normal_hash != mMatHash[i])
- {
- cached_normal = cached_inv_mdv.transpose();
- cached_normal_hash = mMatHash[i];
- }
+ //update normal matrix
+ S32 loc = shader->getUniformLocation(LLShaderMgr::NORMAL_MATRIX);
+ if (loc > -1)
+ {
+ if (cached_normal_hash != mMatHash[i])
+ {
+ cached_normal = cached_inv_mdv.transpose();
+ cached_normal_hash = mMatHash[i];
+ }
- glh::matrix4f& norm = cached_normal;
+ glh::matrix4f& norm = cached_normal;
- F32 norm_mat[] =
- {
- norm.m[0], norm.m[1], norm.m[2],
- norm.m[4], norm.m[5], norm.m[6],
- norm.m[8], norm.m[9], norm.m[10]
- };
+ F32 norm_mat[] =
+ {
+ norm.m[0], norm.m[1], norm.m[2],
+ norm.m[4], norm.m[5], norm.m[6],
+ norm.m[8], norm.m[9], norm.m[10]
+ };
- shader->uniformMatrix3fv(LLShaderMgr::NORMAL_MATRIX, 1, GL_FALSE, norm_mat);
- }
+ shader->uniformMatrix3fv(LLShaderMgr::NORMAL_MATRIX, 1, GL_FALSE, norm_mat);
+ }
if (shader->getUniformLocation(LLShaderMgr::INVERSE_MODELVIEW_MATRIX))
- {
- shader->uniformMatrix4fv(LLShaderMgr::INVERSE_MODELVIEW_MATRIX, 1, GL_FALSE, cached_inv_mdv.m);
+ {
+ shader->uniformMatrix4fv(LLShaderMgr::INVERSE_MODELVIEW_MATRIX, 1, GL_FALSE, cached_inv_mdv.m);
}
- //update MVP matrix
- mvp_done = true;
- loc = shader->getUniformLocation(LLShaderMgr::MODELVIEW_PROJECTION_MATRIX);
- if (loc > -1)
- {
- U32 proj = MM_PROJECTION;
-
- if (cached_mvp_mdv_hash != mMatHash[i] || cached_mvp_proj_hash != mMatHash[MM_PROJECTION])
- {
- cached_mvp = mat;
- cached_mvp.mult_left(mMatrix[proj][mMatIdx[proj]]);
- cached_mvp_mdv_hash = mMatHash[i];
- cached_mvp_proj_hash = mMatHash[MM_PROJECTION];
- }
-
- shader->uniformMatrix4fv(LLShaderMgr::MODELVIEW_PROJECTION_MATRIX, 1, GL_FALSE, cached_mvp.m);
- }
- }
-
- i = MM_PROJECTION;
- if (mMatHash[MM_PROJECTION] != shader->mMatHash[MM_PROJECTION])
- { //update projection matrix, normal, and MVP
- glh::matrix4f& mat = mMatrix[MM_PROJECTION][mMatIdx[MM_PROJECTION]];
+ //update MVP matrix
+ mvp_done = true;
+ loc = shader->getUniformLocation(LLShaderMgr::MODELVIEW_PROJECTION_MATRIX);
+ if (loc > -1)
+ {
+ U32 proj = MM_PROJECTION;
+
+ if (cached_mvp_mdv_hash != mMatHash[i] || cached_mvp_proj_hash != mMatHash[MM_PROJECTION])
+ {
+ cached_mvp = mat;
+ cached_mvp.mult_left(mMatrix[proj][mMatIdx[proj]]);
+ cached_mvp_mdv_hash = mMatHash[i];
+ cached_mvp_proj_hash = mMatHash[MM_PROJECTION];
+ }
+
+ shader->uniformMatrix4fv(LLShaderMgr::MODELVIEW_PROJECTION_MATRIX, 1, GL_FALSE, cached_mvp.m);
+ }
+ }
+
+ i = MM_PROJECTION;
+ if (mMatHash[MM_PROJECTION] != shader->mMatHash[MM_PROJECTION])
+ { //update projection matrix, normal, and MVP
+ glh::matrix4f& mat = mMatrix[MM_PROJECTION][mMatIdx[MM_PROJECTION]];
// GZ: This was previously disabled seemingly due to a bug involving the deferred renderer's regular pushing and popping of mats.
- // We're reenabling this and cleaning up the code around that - that would've been the appropriate course initially.
- // Anything beyond the standard proj and inv proj mats are special cases. Please setup special uniforms accordingly in the future.
+ // We're reenabling this and cleaning up the code around that - that would've been the appropriate course initially.
+ // Anything beyond the standard proj and inv proj mats are special cases. Please setup special uniforms accordingly in the future.
if (shader->getUniformLocation(LLShaderMgr::INVERSE_PROJECTION_MATRIX))
{
- glh::matrix4f inv_proj = mat.inverse();
- shader->uniformMatrix4fv(LLShaderMgr::INVERSE_PROJECTION_MATRIX, 1, FALSE, inv_proj.m);
+ glh::matrix4f inv_proj = mat.inverse();
+ shader->uniformMatrix4fv(LLShaderMgr::INVERSE_PROJECTION_MATRIX, 1, FALSE, inv_proj.m);
}
- // Used by some full screen effects - such as full screen lights, glow, etc.
+ // Used by some full screen effects - such as full screen lights, glow, etc.
if (shader->getUniformLocation(LLShaderMgr::IDENTITY_MATRIX))
{
shader->uniformMatrix4fv(LLShaderMgr::IDENTITY_MATRIX, 1, GL_FALSE, glh::matrix4f::identity().m);
}
- shader->uniformMatrix4fv(name[MM_PROJECTION], 1, GL_FALSE, mat.m);
- shader->mMatHash[MM_PROJECTION] = mMatHash[MM_PROJECTION];
-
- if (!mvp_done)
- {
- //update MVP matrix
- S32 loc = shader->getUniformLocation(LLShaderMgr::MODELVIEW_PROJECTION_MATRIX);
- if (loc > -1)
- {
- if (cached_mvp_mdv_hash != mMatHash[MM_PROJECTION] || cached_mvp_proj_hash != mMatHash[MM_PROJECTION])
- {
- U32 mdv = MM_MODELVIEW;
- cached_mvp = mat;
- cached_mvp.mult_right(mMatrix[mdv][mMatIdx[mdv]]);
- cached_mvp_mdv_hash = mMatHash[MM_MODELVIEW];
- cached_mvp_proj_hash = mMatHash[MM_PROJECTION];
- }
-
- shader->uniformMatrix4fv(LLShaderMgr::MODELVIEW_PROJECTION_MATRIX, 1, GL_FALSE, cached_mvp.m);
- }
- }
- }
-
- for (i = MM_TEXTURE0; i < NUM_MATRIX_MODES; ++i)
- {
- if (mMatHash[i] != shader->mMatHash[i])
- {
- shader->uniformMatrix4fv(name[i], 1, GL_FALSE, mMatrix[i][mMatIdx[i]].m);
- shader->mMatHash[i] = mMatHash[i];
- }
- }
-
-
- if (shader->mFeatures.hasLighting || shader->mFeatures.calculatesLighting || shader->mFeatures.calculatesAtmospherics)
- { //also sync light state
- syncLightState();
- }
- }
+ shader->uniformMatrix4fv(name[MM_PROJECTION], 1, GL_FALSE, mat.m);
+ shader->mMatHash[MM_PROJECTION] = mMatHash[MM_PROJECTION];
+
+ if (!mvp_done)
+ {
+ //update MVP matrix
+ S32 loc = shader->getUniformLocation(LLShaderMgr::MODELVIEW_PROJECTION_MATRIX);
+ if (loc > -1)
+ {
+ if (cached_mvp_mdv_hash != mMatHash[MM_PROJECTION] || cached_mvp_proj_hash != mMatHash[MM_PROJECTION])
+ {
+ U32 mdv = MM_MODELVIEW;
+ cached_mvp = mat;
+ cached_mvp.mult_right(mMatrix[mdv][mMatIdx[mdv]]);
+ cached_mvp_mdv_hash = mMatHash[MM_MODELVIEW];
+ cached_mvp_proj_hash = mMatHash[MM_PROJECTION];
+ }
+
+ shader->uniformMatrix4fv(LLShaderMgr::MODELVIEW_PROJECTION_MATRIX, 1, GL_FALSE, cached_mvp.m);
+ }
+ }
+ }
+
+ for (i = MM_TEXTURE0; i < NUM_MATRIX_MODES; ++i)
+ {
+ if (mMatHash[i] != shader->mMatHash[i])
+ {
+ shader->uniformMatrix4fv(name[i], 1, GL_FALSE, mMatrix[i][mMatIdx[i]].m);
+ shader->mMatHash[i] = mMatHash[i];
+ }
+ }
+
+
+ if (shader->mFeatures.hasLighting || shader->mFeatures.calculatesLighting || shader->mFeatures.calculatesAtmospherics)
+ { //also sync light state
+ syncLightState();
+ }
+ }
}
void LLRender::translatef(const GLfloat& x, const GLfloat& y, const GLfloat& z)
{
- flush();
+ flush();
- {
- glh::matrix4f trans_mat(1,0,0,x,
- 0,1,0,y,
- 0,0,1,z,
- 0,0,0,1);
-
- mMatrix[mMatrixMode][mMatIdx[mMatrixMode]].mult_right(trans_mat);
- mMatHash[mMatrixMode]++;
- }
+ {
+ glh::matrix4f trans_mat(1,0,0,x,
+ 0,1,0,y,
+ 0,0,1,z,
+ 0,0,0,1);
+
+ mMatrix[mMatrixMode][mMatIdx[mMatrixMode]].mult_right(trans_mat);
+ mMatHash[mMatrixMode]++;
+ }
}
void LLRender::scalef(const GLfloat& x, const GLfloat& y, const GLfloat& z)
{
- flush();
-
- {
- glh::matrix4f scale_mat(x,0,0,0,
- 0,y,0,0,
- 0,0,z,0,
- 0,0,0,1);
-
- mMatrix[mMatrixMode][mMatIdx[mMatrixMode]].mult_right(scale_mat);
- mMatHash[mMatrixMode]++;
- }
+ flush();
+
+ {
+ glh::matrix4f scale_mat(x,0,0,0,
+ 0,y,0,0,
+ 0,0,z,0,
+ 0,0,0,1);
+
+ mMatrix[mMatrixMode][mMatIdx[mMatrixMode]].mult_right(scale_mat);
+ mMatHash[mMatrixMode]++;
+ }
}
void LLRender::ortho(F32 left, F32 right, F32 bottom, F32 top, F32 zNear, F32 zFar)
{
- flush();
+ flush();
+
+ {
- {
+ glh::matrix4f ortho_mat(2.f/(right-left),0,0, -(right+left)/(right-left),
+ 0,2.f/(top-bottom),0, -(top+bottom)/(top-bottom),
+ 0,0,-2.f/(zFar-zNear), -(zFar+zNear)/(zFar-zNear),
+ 0,0,0,1);
- glh::matrix4f ortho_mat(2.f/(right-left),0,0, -(right+left)/(right-left),
- 0,2.f/(top-bottom),0, -(top+bottom)/(top-bottom),
- 0,0,-2.f/(zFar-zNear), -(zFar+zNear)/(zFar-zNear),
- 0,0,0,1);
-
- mMatrix[mMatrixMode][mMatIdx[mMatrixMode]].mult_right(ortho_mat);
- mMatHash[mMatrixMode]++;
- }
+ mMatrix[mMatrixMode][mMatIdx[mMatrixMode]].mult_right(ortho_mat);
+ mMatHash[mMatrixMode]++;
+ }
}
void LLRender::rotatef(const GLfloat& a, const GLfloat& x, const GLfloat& y, const GLfloat& z)
{
- flush();
+ flush();
+
+ {
+ F32 r = a * DEG_TO_RAD;
- {
- F32 r = a * DEG_TO_RAD;
+ F32 c = cosf(r);
+ F32 s = sinf(r);
- F32 c = cosf(r);
- F32 s = sinf(r);
+ F32 ic = 1.f-c;
- F32 ic = 1.f-c;
+ glh::matrix4f rot_mat(x*x*ic+c, x*y*ic-z*s, x*z*ic+y*s, 0,
+ x*y*ic+z*s, y*y*ic+c, y*z*ic-x*s, 0,
+ x*z*ic-y*s, y*z*ic+x*s, z*z*ic+c, 0,
+ 0,0,0,1);
- glh::matrix4f rot_mat(x*x*ic+c, x*y*ic-z*s, x*z*ic+y*s, 0,
- x*y*ic+z*s, y*y*ic+c, y*z*ic-x*s, 0,
- x*z*ic-y*s, y*z*ic+x*s, z*z*ic+c, 0,
- 0,0,0,1);
-
- mMatrix[mMatrixMode][mMatIdx[mMatrixMode]].mult_right(rot_mat);
- mMatHash[mMatrixMode]++;
- }
+ mMatrix[mMatrixMode][mMatIdx[mMatrixMode]].mult_right(rot_mat);
+ mMatHash[mMatrixMode]++;
+ }
}
void LLRender::pushMatrix()
{
- flush();
-
- {
- if (mMatIdx[mMatrixMode] < LL_MATRIX_STACK_DEPTH-1)
- {
- mMatrix[mMatrixMode][mMatIdx[mMatrixMode]+1] = mMatrix[mMatrixMode][mMatIdx[mMatrixMode]];
- ++mMatIdx[mMatrixMode];
- }
- else
- {
- LL_WARNS() << "Matrix stack overflow." << LL_ENDL;
- }
- }
+ flush();
+
+ {
+ if (mMatIdx[mMatrixMode] < LL_MATRIX_STACK_DEPTH-1)
+ {
+ mMatrix[mMatrixMode][mMatIdx[mMatrixMode]+1] = mMatrix[mMatrixMode][mMatIdx[mMatrixMode]];
+ ++mMatIdx[mMatrixMode];
+ }
+ else
+ {
+ LL_WARNS() << "Matrix stack overflow." << LL_ENDL;
+ }
+ }
}
void LLRender::popMatrix()
{
- flush();
- {
- if (mMatIdx[mMatrixMode] > 0)
- {
- --mMatIdx[mMatrixMode];
- mMatHash[mMatrixMode]++;
- }
- else
- {
- LL_WARNS() << "Matrix stack underflow." << LL_ENDL;
- }
- }
+ flush();
+ {
+ if (mMatIdx[mMatrixMode] > 0)
+ {
+ --mMatIdx[mMatrixMode];
+ mMatHash[mMatrixMode]++;
+ }
+ else
+ {
+ LL_WARNS() << "Matrix stack underflow." << LL_ENDL;
+ }
+ }
}
void LLRender::loadMatrix(const GLfloat* m)
{
- flush();
- {
- mMatrix[mMatrixMode][mMatIdx[mMatrixMode]].set_value((GLfloat*) m);
- mMatHash[mMatrixMode]++;
- }
+ flush();
+ {
+ mMatrix[mMatrixMode][mMatIdx[mMatrixMode]].set_value((GLfloat*) m);
+ mMatHash[mMatrixMode]++;
+ }
}
void LLRender::multMatrix(const GLfloat* m)
{
- flush();
- {
- glh::matrix4f mat((GLfloat*) m);
-
- mMatrix[mMatrixMode][mMatIdx[mMatrixMode]].mult_right(mat);
- mMatHash[mMatrixMode]++;
- }
+ flush();
+ {
+ glh::matrix4f mat((GLfloat*) m);
+
+ mMatrix[mMatrixMode][mMatIdx[mMatrixMode]].mult_right(mat);
+ mMatHash[mMatrixMode]++;
+ }
}
void LLRender::matrixMode(eMatrixMode mode)
{
- if (mode == MM_TEXTURE)
- {
+ if (mode == MM_TEXTURE)
+ {
U32 tex_index = gGL.getCurrentTexUnitIndex();
// the shaders don't actually reference anything beyond texture_matrix0/1 outside of terrain rendering
llassert(tex_index <= 3);
@@ -1272,360 +1272,360 @@ void LLRender::matrixMode(eMatrixMode mode)
LL_WARNS_ONCE() << "Attempted to assign matrix mode out of bounds: " << mode << LL_ENDL;
mode = MM_TEXTURE0;
}
- }
+ }
- mMatrixMode = mode;
+ mMatrixMode = mode;
}
LLRender::eMatrixMode LLRender::getMatrixMode()
{
- if (mMatrixMode >= MM_TEXTURE0 && mMatrixMode <= MM_TEXTURE3)
- { //always return MM_TEXTURE if current matrix mode points at any texture matrix
- return MM_TEXTURE;
- }
+ if (mMatrixMode >= MM_TEXTURE0 && mMatrixMode <= MM_TEXTURE3)
+ { //always return MM_TEXTURE if current matrix mode points at any texture matrix
+ return MM_TEXTURE;
+ }
- return mMatrixMode;
+ return mMatrixMode;
}
void LLRender::loadIdentity()
{
- flush();
+ flush();
- {
- llassert_always(mMatrixMode < NUM_MATRIX_MODES) ;
+ {
+ llassert_always(mMatrixMode < NUM_MATRIX_MODES) ;
- mMatrix[mMatrixMode][mMatIdx[mMatrixMode]].make_identity();
- mMatHash[mMatrixMode]++;
- }
+ mMatrix[mMatrixMode][mMatIdx[mMatrixMode]].make_identity();
+ mMatHash[mMatrixMode]++;
+ }
}
const glh::matrix4f& LLRender::getModelviewMatrix()
{
- return mMatrix[MM_MODELVIEW][mMatIdx[MM_MODELVIEW]];
+ return mMatrix[MM_MODELVIEW][mMatIdx[MM_MODELVIEW]];
}
const glh::matrix4f& LLRender::getProjectionMatrix()
{
- return mMatrix[MM_PROJECTION][mMatIdx[MM_PROJECTION]];
+ return mMatrix[MM_PROJECTION][mMatIdx[MM_PROJECTION]];
}
void LLRender::translateUI(F32 x, F32 y, F32 z)
{
- if (mUIOffset.empty())
- {
- LL_ERRS() << "Need to push a UI translation frame before offsetting" << LL_ENDL;
- }
+ if (mUIOffset.empty())
+ {
+ LL_ERRS() << "Need to push a UI translation frame before offsetting" << LL_ENDL;
+ }
- mUIOffset.back().mV[0] += x;
- mUIOffset.back().mV[1] += y;
- mUIOffset.back().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)
{
- if (mUIScale.empty())
- {
- LL_ERRS() << "Need to push a UI transformation frame before scaling." << LL_ENDL;
- }
+ if (mUIScale.empty())
+ {
+ LL_ERRS() << "Need to push a UI transformation frame before scaling." << LL_ENDL;
+ }
- mUIScale.back().scaleVec(LLVector3(x,y,z));
+ mUIScale.back().scaleVec(LLVector3(x,y,z));
}
void LLRender::pushUIMatrix()
{
- if (mUIOffset.empty())
- {
- mUIOffset.push_back(LLVector3(0,0,0));
- }
- else
- {
- mUIOffset.push_back(mUIOffset.back());
- }
-
- if (mUIScale.empty())
- {
- mUIScale.push_back(LLVector3(1,1,1));
- }
- else
- {
- mUIScale.push_back(mUIScale.back());
- }
+ if (mUIOffset.empty())
+ {
+ mUIOffset.push_back(LLVector3(0,0,0));
+ }
+ else
+ {
+ mUIOffset.push_back(mUIOffset.back());
+ }
+
+ if (mUIScale.empty())
+ {
+ mUIScale.push_back(LLVector3(1,1,1));
+ }
+ else
+ {
+ mUIScale.push_back(mUIScale.back());
+ }
}
void LLRender::popUIMatrix()
{
- if (mUIOffset.empty())
- {
- LL_ERRS() << "UI offset stack blown." << LL_ENDL;
- }
- mUIOffset.pop_back();
- mUIScale.pop_back();
+ if (mUIOffset.empty())
+ {
+ LL_ERRS() << "UI offset stack blown." << LL_ENDL;
+ }
+ mUIOffset.pop_back();
+ mUIScale.pop_back();
}
LLVector3 LLRender::getUITranslation()
{
- if (mUIOffset.empty())
- {
- return LLVector3(0,0,0);
- }
- return mUIOffset.back();
+ if (mUIOffset.empty())
+ {
+ return LLVector3(0,0,0);
+ }
+ return mUIOffset.back();
}
LLVector3 LLRender::getUIScale()
{
- if (mUIScale.empty())
- {
- return LLVector3(1,1,1);
- }
- return mUIScale.back();
+ if (mUIScale.empty())
+ {
+ return LLVector3(1,1,1);
+ }
+ return mUIScale.back();
}
void LLRender::loadUIIdentity()
{
- if (mUIOffset.empty())
- {
- LL_ERRS() << "Need to push UI translation frame before clearing offset." << LL_ENDL;
- }
- mUIOffset.back().setVec(0,0,0);
- mUIScale.back().setVec(1,1,1);
+ if (mUIOffset.empty())
+ {
+ LL_ERRS() << "Need to push UI translation frame before clearing offset." << LL_ENDL;
+ }
+ mUIOffset.back().setVec(0,0,0);
+ mUIScale.back().setVec(1,1,1);
}
void LLRender::setColorMask(bool writeColor, bool writeAlpha)
{
- setColorMask(writeColor, writeColor, writeColor, writeAlpha);
+ setColorMask(writeColor, writeColor, writeColor, writeAlpha);
}
void LLRender::setColorMask(bool writeColorR, bool writeColorG, bool writeColorB, bool writeAlpha)
{
- flush();
-
- if (mCurrColorMask[0] != writeColorR ||
- mCurrColorMask[1] != writeColorG ||
- mCurrColorMask[2] != writeColorB ||
- mCurrColorMask[3] != writeAlpha)
- {
- mCurrColorMask[0] = writeColorR;
- mCurrColorMask[1] = writeColorG;
- mCurrColorMask[2] = writeColorB;
- mCurrColorMask[3] = writeAlpha;
+ flush();
- glColorMask(writeColorR ? GL_TRUE : GL_FALSE,
- writeColorG ? GL_TRUE : GL_FALSE,
- writeColorB ? GL_TRUE : GL_FALSE,
- writeAlpha ? GL_TRUE : GL_FALSE);
- }
+ if (mCurrColorMask[0] != writeColorR ||
+ mCurrColorMask[1] != writeColorG ||
+ mCurrColorMask[2] != writeColorB ||
+ mCurrColorMask[3] != writeAlpha)
+ {
+ mCurrColorMask[0] = writeColorR;
+ mCurrColorMask[1] = writeColorG;
+ mCurrColorMask[2] = writeColorB;
+ mCurrColorMask[3] = writeAlpha;
+
+ glColorMask(writeColorR ? GL_TRUE : GL_FALSE,
+ writeColorG ? GL_TRUE : GL_FALSE,
+ writeColorB ? GL_TRUE : GL_FALSE,
+ writeAlpha ? GL_TRUE : GL_FALSE);
+ }
}
void LLRender::setSceneBlendType(eBlendType type)
{
- switch (type)
- {
- case BT_ALPHA:
- blendFunc(BF_SOURCE_ALPHA, BF_ONE_MINUS_SOURCE_ALPHA);
- break;
- case BT_ADD:
- blendFunc(BF_ONE, BF_ONE);
- break;
- case BT_ADD_WITH_ALPHA:
- blendFunc(BF_SOURCE_ALPHA, BF_ONE);
- break;
- case BT_MULT:
- blendFunc(BF_DEST_COLOR, BF_ZERO);
- break;
- case BT_MULT_ALPHA:
- blendFunc(BF_DEST_ALPHA, BF_ZERO);
- break;
- case BT_MULT_X2:
- blendFunc(BF_DEST_COLOR, BF_SOURCE_COLOR);
- break;
- case BT_REPLACE:
- blendFunc(BF_ONE, BF_ZERO);
- break;
- default:
- LL_ERRS() << "Unknown Scene Blend Type: " << type << LL_ENDL;
- break;
- }
+ switch (type)
+ {
+ case BT_ALPHA:
+ blendFunc(BF_SOURCE_ALPHA, BF_ONE_MINUS_SOURCE_ALPHA);
+ break;
+ case BT_ADD:
+ blendFunc(BF_ONE, BF_ONE);
+ break;
+ case BT_ADD_WITH_ALPHA:
+ blendFunc(BF_SOURCE_ALPHA, BF_ONE);
+ break;
+ case BT_MULT:
+ blendFunc(BF_DEST_COLOR, BF_ZERO);
+ break;
+ case BT_MULT_ALPHA:
+ blendFunc(BF_DEST_ALPHA, BF_ZERO);
+ break;
+ case BT_MULT_X2:
+ blendFunc(BF_DEST_COLOR, BF_SOURCE_COLOR);
+ break;
+ case BT_REPLACE:
+ blendFunc(BF_ONE, BF_ZERO);
+ break;
+ default:
+ LL_ERRS() << "Unknown Scene Blend Type: " << type << LL_ENDL;
+ break;
+ }
}
void LLRender::blendFunc(eBlendFactor sfactor, eBlendFactor dfactor)
{
- llassert(sfactor < BF_UNDEF);
- llassert(dfactor < BF_UNDEF);
- if (mCurrBlendColorSFactor != sfactor || mCurrBlendColorDFactor != dfactor ||
- mCurrBlendAlphaSFactor != sfactor || mCurrBlendAlphaDFactor != dfactor)
- {
- mCurrBlendColorSFactor = sfactor;
- mCurrBlendAlphaSFactor = sfactor;
- mCurrBlendColorDFactor = dfactor;
- mCurrBlendAlphaDFactor = dfactor;
- flush();
- glBlendFunc(sGLBlendFactor[sfactor], sGLBlendFactor[dfactor]);
- }
+ llassert(sfactor < BF_UNDEF);
+ llassert(dfactor < BF_UNDEF);
+ if (mCurrBlendColorSFactor != sfactor || mCurrBlendColorDFactor != dfactor ||
+ mCurrBlendAlphaSFactor != sfactor || mCurrBlendAlphaDFactor != dfactor)
+ {
+ mCurrBlendColorSFactor = sfactor;
+ mCurrBlendAlphaSFactor = sfactor;
+ mCurrBlendColorDFactor = dfactor;
+ mCurrBlendAlphaDFactor = dfactor;
+ flush();
+ glBlendFunc(sGLBlendFactor[sfactor], sGLBlendFactor[dfactor]);
+ }
}
void LLRender::blendFunc(eBlendFactor color_sfactor, eBlendFactor color_dfactor,
- eBlendFactor alpha_sfactor, eBlendFactor alpha_dfactor)
-{
- llassert(color_sfactor < BF_UNDEF);
- llassert(color_dfactor < BF_UNDEF);
- llassert(alpha_sfactor < BF_UNDEF);
- llassert(alpha_dfactor < BF_UNDEF);
-
- if (mCurrBlendColorSFactor != color_sfactor || mCurrBlendColorDFactor != color_dfactor ||
- mCurrBlendAlphaSFactor != alpha_sfactor || mCurrBlendAlphaDFactor != alpha_dfactor)
- {
- mCurrBlendColorSFactor = color_sfactor;
- mCurrBlendAlphaSFactor = alpha_sfactor;
- mCurrBlendColorDFactor = color_dfactor;
- mCurrBlendAlphaDFactor = alpha_dfactor;
- flush();
-
+ eBlendFactor alpha_sfactor, eBlendFactor alpha_dfactor)
+{
+ llassert(color_sfactor < BF_UNDEF);
+ llassert(color_dfactor < BF_UNDEF);
+ llassert(alpha_sfactor < BF_UNDEF);
+ llassert(alpha_dfactor < BF_UNDEF);
+
+ if (mCurrBlendColorSFactor != color_sfactor || mCurrBlendColorDFactor != color_dfactor ||
+ mCurrBlendAlphaSFactor != alpha_sfactor || mCurrBlendAlphaDFactor != alpha_dfactor)
+ {
+ mCurrBlendColorSFactor = color_sfactor;
+ mCurrBlendAlphaSFactor = alpha_sfactor;
+ mCurrBlendColorDFactor = color_dfactor;
+ mCurrBlendAlphaDFactor = alpha_dfactor;
+ flush();
+
glBlendFuncSeparate(sGLBlendFactor[color_sfactor], sGLBlendFactor[color_dfactor],
sGLBlendFactor[alpha_sfactor], sGLBlendFactor[alpha_dfactor]);
- }
+ }
}
LLTexUnit* LLRender::getTexUnit(U32 index)
{
- if (index < mTexUnits.size())
- {
- return &mTexUnits[index];
- }
- else
- {
- LL_DEBUGS() << "Non-existing texture unit layer requested: " << index << LL_ENDL;
- return &mDummyTexUnit;
- }
+ if (index < mTexUnits.size())
+ {
+ return &mTexUnits[index];
+ }
+ else
+ {
+ LL_DEBUGS() << "Non-existing texture unit layer requested: " << index << LL_ENDL;
+ return &mDummyTexUnit;
+ }
}
LLLightState* LLRender::getLight(U32 index)
{
- if (index < mLightState.size())
- {
- return &mLightState[index];
- }
-
- return NULL;
+ if (index < mLightState.size())
+ {
+ return &mLightState[index];
+ }
+
+ return NULL;
}
void LLRender::setAmbientLightColor(const LLColor4& color)
{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE
- if (color != mAmbientLightColor)
- {
- ++mLightHash;
- mAmbientLightColor = color;
- }
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE
+ if (color != mAmbientLightColor)
+ {
+ ++mLightHash;
+ mAmbientLightColor = color;
+ }
}
bool LLRender::verifyTexUnitActive(U32 unitToVerify)
{
- if (mCurrTextureUnitIndex == unitToVerify)
- {
- return true;
- }
- else
- {
- LL_WARNS() << "TexUnit currently active: " << mCurrTextureUnitIndex << " (expecting " << unitToVerify << ")" << LL_ENDL;
- return false;
- }
+ if (mCurrTextureUnitIndex == unitToVerify)
+ {
+ return true;
+ }
+ else
+ {
+ LL_WARNS() << "TexUnit currently active: " << mCurrTextureUnitIndex << " (expecting " << unitToVerify << ")" << LL_ENDL;
+ return false;
+ }
}
void LLRender::clearErrors()
{
- while (glGetError())
- {
- //loop until no more error flags left
- }
+ while (glGetError())
+ {
+ //loop until no more error flags left
+ }
}
void LLRender::begin(const GLuint& mode)
{
- if (mode != mMode)
- {
- if (mode == LLRender::QUADS)
- {
- mQuadCycle = 1;
- }
-
- if (mMode == LLRender::QUADS ||
- mMode == LLRender::LINES ||
- mMode == LLRender::TRIANGLES ||
- mMode == LLRender::POINTS)
- {
- flush();
- }
- else if (mCount != 0)
- {
- LL_ERRS() << "gGL.begin() called redundantly." << LL_ENDL;
- }
-
- mMode = mode;
- }
+ if (mode != mMode)
+ {
+ if (mode == LLRender::QUADS)
+ {
+ mQuadCycle = 1;
+ }
+
+ if (mMode == LLRender::QUADS ||
+ mMode == LLRender::LINES ||
+ mMode == LLRender::TRIANGLES ||
+ mMode == LLRender::POINTS)
+ {
+ flush();
+ }
+ else if (mCount != 0)
+ {
+ LL_ERRS() << "gGL.begin() called redundantly." << LL_ENDL;
+ }
+
+ mMode = mode;
+ }
}
void LLRender::end()
-{
- if (mCount == 0)
- {
- return;
- //IMM_ERRS << "GL begin and end called with no vertices specified." << LL_ENDL;
- }
-
- if ((mMode != LLRender::QUADS &&
- mMode != LLRender::LINES &&
- mMode != LLRender::TRIANGLES &&
- mMode != LLRender::POINTS) ||
- mCount > 2048)
- {
- flush();
- }
+{
+ if (mCount == 0)
+ {
+ return;
+ //IMM_ERRS << "GL begin and end called with no vertices specified." << LL_ENDL;
+ }
+
+ if ((mMode != LLRender::QUADS &&
+ mMode != LLRender::LINES &&
+ mMode != LLRender::TRIANGLES &&
+ mMode != LLRender::POINTS) ||
+ mCount > 2048)
+ {
+ flush();
+ }
}
void LLRender::flush()
{
- if (mCount > 0)
- {
+ if (mCount > 0)
+ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE;
llassert(LLGLSLShader::sCurBoundShaderPtr != nullptr);
- if (!mUIOffset.empty())
- {
- sUICalls++;
- sUIVerts += mCount;
- }
-
- //store mCount in a local variable to avoid re-entrance (drawArrays may call flush)
- U32 count = mCount;
-
- if (mMode == LLRender::QUADS && !sGLCoreProfile)
- {
- if (mCount%4 != 0)
- {
- count -= (mCount % 4);
- LL_WARNS() << "Incomplete quad requested." << LL_ENDL;
- }
- }
-
- if (mMode == LLRender::TRIANGLES)
- {
- if (mCount%3 != 0)
- {
- count -= (mCount % 3);
- LL_WARNS() << "Incomplete triangle requested." << LL_ENDL;
- }
- }
-
- if (mMode == LLRender::LINES)
- {
- if (mCount%2 != 0)
- {
- count -= (mCount % 2);
- LL_WARNS() << "Incomplete line requested." << LL_ENDL;
- }
- }
-
- mCount = 0;
+ if (!mUIOffset.empty())
+ {
+ sUICalls++;
+ sUIVerts += mCount;
+ }
+
+ //store mCount in a local variable to avoid re-entrance (drawArrays may call flush)
+ U32 count = mCount;
+
+ if (mMode == LLRender::QUADS && !sGLCoreProfile)
+ {
+ if (mCount%4 != 0)
+ {
+ count -= (mCount % 4);
+ LL_WARNS() << "Incomplete quad requested." << LL_ENDL;
+ }
+ }
+
+ if (mMode == LLRender::TRIANGLES)
+ {
+ if (mCount%3 != 0)
+ {
+ count -= (mCount % 3);
+ LL_WARNS() << "Incomplete triangle requested." << LL_ENDL;
+ }
+ }
+
+ if (mMode == LLRender::LINES)
+ {
+ if (mCount%2 != 0)
+ {
+ count -= (mCount % 2);
+ LL_WARNS() << "Incomplete line requested." << LL_ENDL;
+ }
+ }
+
+ mCount = 0;
if (mBuffer)
{
@@ -1649,8 +1649,8 @@ void LLRender::flush()
hash.finalize();
}
-
-
+
+
U64 vhash = hash.digest();
// check the VB cache before making a new vertex buffer
@@ -1660,7 +1660,7 @@ void LLRender::flush()
// Most of our usage of the "immediate mode" style draw calls is actually
// sending the same geometry over and over again.
// To leverage this, we maintain a running hash of the vertex stream being
- // built up before a flush, and then check that hash against a VB
+ // built up before a flush, and then check that hash against a VB
// cache just before creating a vertex buffer in VRAM
std::unordered_map<U64, LLVBCache>::iterator cache = sVBCache.find(vhash);
@@ -1739,528 +1739,528 @@ void LLRender::flush()
LL_ERRS() << "A flush call from outside main rendering thread" << LL_ENDL;
}
-
- mVerticesp[0] = mVerticesp[count];
- mTexcoordsp[0] = mTexcoordsp[count];
- mColorsp[0] = mColorsp[count];
-
- mCount = 0;
- }
+
+ mVerticesp[0] = mVerticesp[count];
+ mTexcoordsp[0] = mTexcoordsp[count];
+ mColorsp[0] = mColorsp[count];
+
+ mCount = 0;
+ }
}
void LLRender::vertex3f(const GLfloat& x, const GLfloat& y, const GLfloat& z)
-{
- //the range of mVerticesp, mColorsp and mTexcoordsp is [0, 4095]
- if (mCount > 2048)
- { //break when buffer gets reasonably full to keep GL command buffers happy and avoid overflow below
- switch (mMode)
- {
- case LLRender::POINTS: flush(); break;
- case LLRender::TRIANGLES: if (mCount%3==0) flush(); break;
- case LLRender::QUADS: if(mCount%4 == 0) flush(); break;
- case LLRender::LINES: if (mCount%2 == 0) flush(); break;
- }
- }
-
- if (mCount > 4094)
- {
- // LL_WARNS() << "GL immediate mode overflow. Some geometry not drawn." << LL_ENDL;
- return;
- }
-
- if (mUIOffset.empty())
- {
- mVerticesp[mCount] = LLVector3(x,y,z);
- }
- else
- {
- LLVector3 vert = (LLVector3(x,y,z)+mUIOffset.back()).scaledVec(mUIScale.back());
- mVerticesp[mCount] = vert;
- }
-
- if (mMode == LLRender::QUADS && LLRender::sGLCoreProfile)
- {
- mQuadCycle++;
- if (mQuadCycle == 4)
- { //copy two vertices so fourth quad element will add a triangle
- mQuadCycle = 0;
-
- mCount++;
- mVerticesp[mCount] = mVerticesp[mCount-3];
- mColorsp[mCount] = mColorsp[mCount-3];
- mTexcoordsp[mCount] = mTexcoordsp[mCount-3];
-
- mCount++;
- mVerticesp[mCount] = mVerticesp[mCount-2];
- mColorsp[mCount] = mColorsp[mCount-2];
- mTexcoordsp[mCount] = mTexcoordsp[mCount-2];
- }
- }
-
- mCount++;
- mVerticesp[mCount] = mVerticesp[mCount-1];
- mColorsp[mCount] = mColorsp[mCount-1];
- mTexcoordsp[mCount] = mTexcoordsp[mCount-1];
+{
+ //the range of mVerticesp, mColorsp and mTexcoordsp is [0, 4095]
+ if (mCount > 2048)
+ { //break when buffer gets reasonably full to keep GL command buffers happy and avoid overflow below
+ switch (mMode)
+ {
+ case LLRender::POINTS: flush(); break;
+ case LLRender::TRIANGLES: if (mCount%3==0) flush(); break;
+ case LLRender::QUADS: if(mCount%4 == 0) flush(); break;
+ case LLRender::LINES: if (mCount%2 == 0) flush(); break;
+ }
+ }
+
+ if (mCount > 4094)
+ {
+ // LL_WARNS() << "GL immediate mode overflow. Some geometry not drawn." << LL_ENDL;
+ return;
+ }
+
+ if (mUIOffset.empty())
+ {
+ mVerticesp[mCount] = LLVector3(x,y,z);
+ }
+ else
+ {
+ LLVector3 vert = (LLVector3(x,y,z)+mUIOffset.back()).scaledVec(mUIScale.back());
+ mVerticesp[mCount] = vert;
+ }
+
+ if (mMode == LLRender::QUADS && LLRender::sGLCoreProfile)
+ {
+ mQuadCycle++;
+ if (mQuadCycle == 4)
+ { //copy two vertices so fourth quad element will add a triangle
+ mQuadCycle = 0;
+
+ mCount++;
+ mVerticesp[mCount] = mVerticesp[mCount-3];
+ mColorsp[mCount] = mColorsp[mCount-3];
+ mTexcoordsp[mCount] = mTexcoordsp[mCount-3];
+
+ mCount++;
+ mVerticesp[mCount] = mVerticesp[mCount-2];
+ mColorsp[mCount] = mColorsp[mCount-2];
+ mTexcoordsp[mCount] = mTexcoordsp[mCount-2];
+ }
+ }
+
+ mCount++;
+ 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)
- {
- // LL_WARNS() << "GL immediate mode overflow. Some geometry not drawn." << LL_ENDL;
- return;
- }
-
- if (sGLCoreProfile && mMode == LLRender::QUADS)
- { //quads are deprecated, convert to triangle list
- S32 i = 0;
-
- while (i < vert_count)
- {
- //read first three
- mVerticesp[mCount++] = verts[i++];
- mTexcoordsp[mCount] = mTexcoordsp[mCount-1];
- mColorsp[mCount] = mColorsp[mCount-1];
-
- mVerticesp[mCount++] = verts[i++];
- mTexcoordsp[mCount] = mTexcoordsp[mCount-1];
- mColorsp[mCount] = mColorsp[mCount-1];
-
- mVerticesp[mCount++] = verts[i++];
- mTexcoordsp[mCount] = mTexcoordsp[mCount-1];
- mColorsp[mCount] = mColorsp[mCount-1];
-
- //copy two
- mVerticesp[mCount++] = verts[i-3];
- mTexcoordsp[mCount] = mTexcoordsp[mCount-1];
- mColorsp[mCount] = mColorsp[mCount-1];
-
- mVerticesp[mCount++] = verts[i-1];
- mTexcoordsp[mCount] = mTexcoordsp[mCount-1];
- mColorsp[mCount] = mColorsp[mCount-1];
-
- //copy last one
- mVerticesp[mCount++] = verts[i++];
- mTexcoordsp[mCount] = mTexcoordsp[mCount-1];
- mColorsp[mCount] = mColorsp[mCount-1];
- }
- }
- else
- {
- for (S32 i = 0; i < vert_count; i++)
- {
- mVerticesp[mCount] = verts[i];
-
- mCount++;
- mTexcoordsp[mCount] = mTexcoordsp[mCount-1];
- mColorsp[mCount] = mColorsp[mCount-1];
- }
- }
-
- if( mCount > 0 ) // ND: Guard against crashes if mCount is zero, yes it can happen
- mVerticesp[mCount] = mVerticesp[mCount-1];
+ if (mCount + vert_count > 4094)
+ {
+ // LL_WARNS() << "GL immediate mode overflow. Some geometry not drawn." << LL_ENDL;
+ return;
+ }
+
+ if (sGLCoreProfile && mMode == LLRender::QUADS)
+ { //quads are deprecated, convert to triangle list
+ S32 i = 0;
+
+ while (i < vert_count)
+ {
+ //read first three
+ mVerticesp[mCount++] = verts[i++];
+ mTexcoordsp[mCount] = mTexcoordsp[mCount-1];
+ mColorsp[mCount] = mColorsp[mCount-1];
+
+ mVerticesp[mCount++] = verts[i++];
+ mTexcoordsp[mCount] = mTexcoordsp[mCount-1];
+ mColorsp[mCount] = mColorsp[mCount-1];
+
+ mVerticesp[mCount++] = verts[i++];
+ mTexcoordsp[mCount] = mTexcoordsp[mCount-1];
+ mColorsp[mCount] = mColorsp[mCount-1];
+
+ //copy two
+ mVerticesp[mCount++] = verts[i-3];
+ mTexcoordsp[mCount] = mTexcoordsp[mCount-1];
+ mColorsp[mCount] = mColorsp[mCount-1];
+
+ mVerticesp[mCount++] = verts[i-1];
+ mTexcoordsp[mCount] = mTexcoordsp[mCount-1];
+ mColorsp[mCount] = mColorsp[mCount-1];
+
+ //copy last one
+ mVerticesp[mCount++] = verts[i++];
+ mTexcoordsp[mCount] = mTexcoordsp[mCount-1];
+ mColorsp[mCount] = mColorsp[mCount-1];
+ }
+ }
+ else
+ {
+ for (S32 i = 0; i < vert_count; i++)
+ {
+ mVerticesp[mCount] = verts[i];
+
+ mCount++;
+ mTexcoordsp[mCount] = mTexcoordsp[mCount-1];
+ mColorsp[mCount] = mColorsp[mCount-1];
+ }
+ }
+
+ if( mCount > 0 ) // ND: Guard against crashes if mCount is zero, yes it can happen
+ mVerticesp[mCount] = mVerticesp[mCount-1];
}
void LLRender::vertexBatchPreTransformed(LLVector3* verts, LLVector2* uvs, S32 vert_count)
{
- if (mCount + vert_count > 4094)
- {
- // LL_WARNS() << "GL immediate mode overflow. Some geometry not drawn." << LL_ENDL;
- return;
- }
-
- if (sGLCoreProfile && mMode == LLRender::QUADS)
- { //quads are deprecated, convert to triangle list
- S32 i = 0;
-
- while (i < vert_count)
- {
- //read first three
- mVerticesp[mCount] = verts[i];
- mTexcoordsp[mCount++] = uvs[i++];
- mColorsp[mCount] = mColorsp[mCount-1];
-
- mVerticesp[mCount] = verts[i];
- mTexcoordsp[mCount++] = uvs[i++];
- mColorsp[mCount] = mColorsp[mCount-1];
-
- mVerticesp[mCount] = verts[i];
- mTexcoordsp[mCount++] = uvs[i++];
- mColorsp[mCount] = mColorsp[mCount-1];
-
- //copy last two
- mVerticesp[mCount] = verts[i-3];
- mTexcoordsp[mCount++] = uvs[i-3];
- mColorsp[mCount] = mColorsp[mCount-1];
-
- mVerticesp[mCount] = verts[i-1];
- mTexcoordsp[mCount++] = uvs[i-1];
- mColorsp[mCount] = mColorsp[mCount-1];
-
- //copy last one
- mVerticesp[mCount] = verts[i];
- mTexcoordsp[mCount++] = uvs[i++];
- mColorsp[mCount] = mColorsp[mCount-1];
- }
- }
- else
- {
- for (S32 i = 0; i < vert_count; i++)
- {
- mVerticesp[mCount] = verts[i];
- mTexcoordsp[mCount] = uvs[i];
-
- mCount++;
- mColorsp[mCount] = mColorsp[mCount-1];
- }
- }
-
- if (mCount > 0)
- {
- mVerticesp[mCount] = mVerticesp[mCount - 1];
- mTexcoordsp[mCount] = mTexcoordsp[mCount - 1];
- }
+ if (mCount + vert_count > 4094)
+ {
+ // LL_WARNS() << "GL immediate mode overflow. Some geometry not drawn." << LL_ENDL;
+ return;
+ }
+
+ if (sGLCoreProfile && mMode == LLRender::QUADS)
+ { //quads are deprecated, convert to triangle list
+ S32 i = 0;
+
+ while (i < vert_count)
+ {
+ //read first three
+ mVerticesp[mCount] = verts[i];
+ mTexcoordsp[mCount++] = uvs[i++];
+ mColorsp[mCount] = mColorsp[mCount-1];
+
+ mVerticesp[mCount] = verts[i];
+ mTexcoordsp[mCount++] = uvs[i++];
+ mColorsp[mCount] = mColorsp[mCount-1];
+
+ mVerticesp[mCount] = verts[i];
+ mTexcoordsp[mCount++] = uvs[i++];
+ mColorsp[mCount] = mColorsp[mCount-1];
+
+ //copy last two
+ mVerticesp[mCount] = verts[i-3];
+ mTexcoordsp[mCount++] = uvs[i-3];
+ mColorsp[mCount] = mColorsp[mCount-1];
+
+ mVerticesp[mCount] = verts[i-1];
+ mTexcoordsp[mCount++] = uvs[i-1];
+ mColorsp[mCount] = mColorsp[mCount-1];
+
+ //copy last one
+ mVerticesp[mCount] = verts[i];
+ mTexcoordsp[mCount++] = uvs[i++];
+ mColorsp[mCount] = mColorsp[mCount-1];
+ }
+ }
+ else
+ {
+ for (S32 i = 0; i < vert_count; i++)
+ {
+ mVerticesp[mCount] = verts[i];
+ mTexcoordsp[mCount] = uvs[i];
+
+ mCount++;
+ mColorsp[mCount] = mColorsp[mCount-1];
+ }
+ }
+
+ if (mCount > 0)
+ {
+ 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)
- {
- // LL_WARNS() << "GL immediate mode overflow. Some geometry not drawn." << LL_ENDL;
- return;
- }
-
-
- if (sGLCoreProfile && mMode == LLRender::QUADS)
- { //quads are deprecated, convert to triangle list
- S32 i = 0;
-
- while (i < vert_count)
- {
- //read first three
- mVerticesp[mCount] = verts[i];
- mTexcoordsp[mCount] = uvs[i];
- mColorsp[mCount++] = colors[i++];
-
- mVerticesp[mCount] = verts[i];
- mTexcoordsp[mCount] = uvs[i];
- mColorsp[mCount++] = colors[i++];
-
- mVerticesp[mCount] = verts[i];
- mTexcoordsp[mCount] = uvs[i];
- mColorsp[mCount++] = colors[i++];
-
- //copy last two
- mVerticesp[mCount] = verts[i-3];
- mTexcoordsp[mCount] = uvs[i-3];
- mColorsp[mCount++] = colors[i-3];
-
- mVerticesp[mCount] = verts[i-1];
- mTexcoordsp[mCount] = uvs[i-1];
- mColorsp[mCount++] = colors[i-1];
-
- //copy last one
- mVerticesp[mCount] = verts[i];
- mTexcoordsp[mCount] = uvs[i];
- mColorsp[mCount++] = colors[i++];
- }
- }
- else
- {
- for (S32 i = 0; i < vert_count; i++)
- {
- mVerticesp[mCount] = verts[i];
- mTexcoordsp[mCount] = uvs[i];
- mColorsp[mCount] = colors[i];
-
- mCount++;
- }
- }
-
- if (mCount > 0)
- {
- mVerticesp[mCount] = mVerticesp[mCount - 1];
- mTexcoordsp[mCount] = mTexcoordsp[mCount - 1];
- mColorsp[mCount] = mColorsp[mCount - 1];
- }
+ if (mCount + vert_count > 4094)
+ {
+ // LL_WARNS() << "GL immediate mode overflow. Some geometry not drawn." << LL_ENDL;
+ return;
+ }
+
+
+ if (sGLCoreProfile && mMode == LLRender::QUADS)
+ { //quads are deprecated, convert to triangle list
+ S32 i = 0;
+
+ while (i < vert_count)
+ {
+ //read first three
+ mVerticesp[mCount] = verts[i];
+ mTexcoordsp[mCount] = uvs[i];
+ mColorsp[mCount++] = colors[i++];
+
+ mVerticesp[mCount] = verts[i];
+ mTexcoordsp[mCount] = uvs[i];
+ mColorsp[mCount++] = colors[i++];
+
+ mVerticesp[mCount] = verts[i];
+ mTexcoordsp[mCount] = uvs[i];
+ mColorsp[mCount++] = colors[i++];
+
+ //copy last two
+ mVerticesp[mCount] = verts[i-3];
+ mTexcoordsp[mCount] = uvs[i-3];
+ mColorsp[mCount++] = colors[i-3];
+
+ mVerticesp[mCount] = verts[i-1];
+ mTexcoordsp[mCount] = uvs[i-1];
+ mColorsp[mCount++] = colors[i-1];
+
+ //copy last one
+ mVerticesp[mCount] = verts[i];
+ mTexcoordsp[mCount] = uvs[i];
+ mColorsp[mCount++] = colors[i++];
+ }
+ }
+ else
+ {
+ for (S32 i = 0; i < vert_count; i++)
+ {
+ mVerticesp[mCount] = verts[i];
+ mTexcoordsp[mCount] = uvs[i];
+ mColorsp[mCount] = colors[i];
+
+ mCount++;
+ }
+ }
+
+ if (mCount > 0)
+ {
+ 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);
+ vertex3f((GLfloat) x, (GLfloat) y, 0);
}
void LLRender::vertex2f(const GLfloat& x, const GLfloat& y)
-{
- vertex3f(x,y,0);
+{
+ vertex3f(x,y,0);
}
void LLRender::vertex2fv(const GLfloat* v)
-{
- vertex3f(v[0], v[1], 0);
+{
+ vertex3f(v[0], v[1], 0);
}
void LLRender::vertex3fv(const GLfloat* v)
{
- vertex3f(v[0], v[1], v[2]);
+ vertex3f(v[0], v[1], v[2]);
}
void LLRender::texCoord2f(const GLfloat& x, const GLfloat& y)
-{
- mTexcoordsp[mCount] = LLVector2(x,y);
+{
+ mTexcoordsp[mCount] = LLVector2(x,y);
}
void LLRender::texCoord2i(const GLint& x, const GLint& y)
-{
- texCoord2f((GLfloat) x, (GLfloat) y);
+{
+ texCoord2f((GLfloat) x, (GLfloat) y);
}
void LLRender::texCoord2fv(const GLfloat* tc)
-{
- texCoord2f(tc[0], tc[1]);
+{
+ texCoord2f(tc[0], tc[1]);
}
void LLRender::color4ub(const GLubyte& r, const GLubyte& g, const GLubyte& b, const GLubyte& a)
{
- if (!LLGLSLShader::sCurBoundShaderPtr || LLGLSLShader::sCurBoundShaderPtr->mAttributeMask & LLVertexBuffer::MAP_COLOR)
- {
- mColorsp[mCount] = LLColor4U(r,g,b,a);
- }
- else
- { //not using shaders or shader reads color from a uniform
- diffuseColor4ub(r,g,b,a);
- }
+ if (!LLGLSLShader::sCurBoundShaderPtr || LLGLSLShader::sCurBoundShaderPtr->mAttributeMask & LLVertexBuffer::MAP_COLOR)
+ {
+ mColorsp[mCount] = LLColor4U(r,g,b,a);
+ }
+ else
+ { //not using shaders or shader reads color from a uniform
+ diffuseColor4ub(r,g,b,a);
+ }
}
void LLRender::color4ubv(const GLubyte* c)
{
- color4ub(c[0], c[1], c[2], c[3]);
+ color4ub(c[0], c[1], c[2], c[3]);
}
void LLRender::color4f(const GLfloat& r, const GLfloat& g, const GLfloat& b, const GLfloat& a)
{
- color4ub((GLubyte) (llclamp(r, 0.f, 1.f)*255),
- (GLubyte) (llclamp(g, 0.f, 1.f)*255),
- (GLubyte) (llclamp(b, 0.f, 1.f)*255),
- (GLubyte) (llclamp(a, 0.f, 1.f)*255));
+ color4ub((GLubyte) (llclamp(r, 0.f, 1.f)*255),
+ (GLubyte) (llclamp(g, 0.f, 1.f)*255),
+ (GLubyte) (llclamp(b, 0.f, 1.f)*255),
+ (GLubyte) (llclamp(a, 0.f, 1.f)*255));
}
void LLRender::color4fv(const GLfloat* c)
-{
- color4f(c[0],c[1],c[2],c[3]);
+{
+ color4f(c[0],c[1],c[2],c[3]);
}
void LLRender::color3f(const GLfloat& r, const GLfloat& g, const GLfloat& b)
-{
- color4f(r,g,b,1);
+{
+ color4f(r,g,b,1);
}
void LLRender::color3fv(const GLfloat* c)
-{
- color4f(c[0],c[1],c[2],1);
+{
+ color4f(c[0],c[1],c[2],1);
}
void LLRender::diffuseColor3f(F32 r, F32 g, F32 b)
{
- LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr;
- llassert(shader != NULL);
+ LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr;
+ llassert(shader != NULL);
- if (shader)
- {
- shader->uniform4f(LLShaderMgr::DIFFUSE_COLOR, r,g,b,1.f);
- }
- else
- {
- glColor3f(r,g,b);
- }
+ if (shader)
+ {
+ shader->uniform4f(LLShaderMgr::DIFFUSE_COLOR, r,g,b,1.f);
+ }
+ else
+ {
+ glColor3f(r,g,b);
+ }
}
void LLRender::diffuseColor3fv(const F32* c)
{
- LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr;
- llassert(shader != NULL);
+ LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr;
+ llassert(shader != NULL);
- if (shader)
- {
- shader->uniform4f(LLShaderMgr::DIFFUSE_COLOR, c[0], c[1], c[2], 1.f);
- }
- else
- {
- glColor3fv(c);
- }
+ if (shader)
+ {
+ shader->uniform4f(LLShaderMgr::DIFFUSE_COLOR, c[0], c[1], c[2], 1.f);
+ }
+ else
+ {
+ glColor3fv(c);
+ }
}
void LLRender::diffuseColor4f(F32 r, F32 g, F32 b, F32 a)
{
- LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr;
- llassert(shader != NULL);
+ LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr;
+ llassert(shader != NULL);
- if (shader)
- {
- shader->uniform4f(LLShaderMgr::DIFFUSE_COLOR, r,g,b,a);
- }
- else
- {
- glColor4f(r,g,b,a);
- }
+ if (shader)
+ {
+ shader->uniform4f(LLShaderMgr::DIFFUSE_COLOR, r,g,b,a);
+ }
+ else
+ {
+ glColor4f(r,g,b,a);
+ }
}
void LLRender::diffuseColor4fv(const F32* c)
{
- LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr;
- llassert(shader != NULL);
+ LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr;
+ llassert(shader != NULL);
- if (shader)
- {
- shader->uniform4fv(LLShaderMgr::DIFFUSE_COLOR, 1, c);
- }
- else
- {
- glColor4fv(c);
- }
+ if (shader)
+ {
+ shader->uniform4fv(LLShaderMgr::DIFFUSE_COLOR, 1, c);
+ }
+ else
+ {
+ glColor4fv(c);
+ }
}
void LLRender::diffuseColor4ubv(const U8* c)
{
- LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr;
- llassert(shader != NULL);
+ LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr;
+ llassert(shader != NULL);
- if (shader)
- {
- shader->uniform4f(LLShaderMgr::DIFFUSE_COLOR, c[0]/255.f, c[1]/255.f, c[2]/255.f, c[3]/255.f);
- }
- else
- {
- glColor4ubv(c);
- }
+ if (shader)
+ {
+ shader->uniform4f(LLShaderMgr::DIFFUSE_COLOR, c[0]/255.f, c[1]/255.f, c[2]/255.f, c[3]/255.f);
+ }
+ else
+ {
+ glColor4ubv(c);
+ }
}
void LLRender::diffuseColor4ub(U8 r, U8 g, U8 b, U8 a)
{
- LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr;
- llassert(shader != NULL);
+ LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr;
+ llassert(shader != NULL);
- if (shader)
- {
- shader->uniform4f(LLShaderMgr::DIFFUSE_COLOR, r/255.f, g/255.f, b/255.f, a/255.f);
- }
- else
- {
- glColor4ub(r,g,b,a);
- }
+ if (shader)
+ {
+ shader->uniform4f(LLShaderMgr::DIFFUSE_COLOR, r/255.f, g/255.f, b/255.f, a/255.f);
+ }
+ else
+ {
+ glColor4ub(r,g,b,a);
+ }
}
void LLRender::debugTexUnits(void)
{
- LL_INFOS("TextureUnit") << "Active TexUnit: " << mCurrTextureUnitIndex << LL_ENDL;
- std::string active_enabled = "false";
- for (U32 i = 0; i < mTexUnits.size(); i++)
- {
- if (getTexUnit(i)->mCurrTexType != LLTexUnit::TT_NONE)
- {
- if (i == mCurrTextureUnitIndex) active_enabled = "true";
- LL_INFOS("TextureUnit") << "TexUnit: " << i << " Enabled" << LL_ENDL;
- LL_INFOS("TextureUnit") << "Enabled As: " ;
- switch (getTexUnit(i)->mCurrTexType)
- {
- case LLTexUnit::TT_TEXTURE:
- LL_CONT << "Texture 2D";
- break;
- case LLTexUnit::TT_RECT_TEXTURE:
- LL_CONT << "Texture Rectangle";
- break;
- case LLTexUnit::TT_CUBE_MAP:
- LL_CONT << "Cube Map";
- break;
- default:
- LL_CONT << "ARGH!!! NONE!";
- break;
- }
- LL_CONT << ", Texture Bound: " << getTexUnit(i)->mCurrTexture << LL_ENDL;
- }
- }
- LL_INFOS("TextureUnit") << "Active TexUnit Enabled : " << active_enabled << LL_ENDL;
+ LL_INFOS("TextureUnit") << "Active TexUnit: " << mCurrTextureUnitIndex << LL_ENDL;
+ std::string active_enabled = "false";
+ for (U32 i = 0; i < mTexUnits.size(); i++)
+ {
+ if (getTexUnit(i)->mCurrTexType != LLTexUnit::TT_NONE)
+ {
+ if (i == mCurrTextureUnitIndex) active_enabled = "true";
+ LL_INFOS("TextureUnit") << "TexUnit: " << i << " Enabled" << LL_ENDL;
+ LL_INFOS("TextureUnit") << "Enabled As: " ;
+ switch (getTexUnit(i)->mCurrTexType)
+ {
+ case LLTexUnit::TT_TEXTURE:
+ LL_CONT << "Texture 2D";
+ break;
+ case LLTexUnit::TT_RECT_TEXTURE:
+ LL_CONT << "Texture Rectangle";
+ break;
+ case LLTexUnit::TT_CUBE_MAP:
+ LL_CONT << "Cube Map";
+ break;
+ default:
+ LL_CONT << "ARGH!!! NONE!";
+ break;
+ }
+ LL_CONT << ", Texture Bound: " << getTexUnit(i)->mCurrTexture << LL_ENDL;
+ }
+ }
+ LL_INFOS("TextureUnit") << "Active TexUnit Enabled : " << active_enabled << LL_ENDL;
}
glh::matrix4f copy_matrix(F32* src)
{
- glh::matrix4f ret;
- ret.set_value(src);
- return ret;
+ glh::matrix4f ret;
+ ret.set_value(src);
+ return ret;
}
glh::matrix4f get_current_modelview()
{
- return copy_matrix(gGLModelView);
+ return copy_matrix(gGLModelView);
}
glh::matrix4f get_current_projection()
{
- return copy_matrix(gGLProjection);
+ return copy_matrix(gGLProjection);
}
glh::matrix4f get_last_modelview()
{
- return copy_matrix(gGLLastModelView);
+ return copy_matrix(gGLLastModelView);
}
glh::matrix4f get_last_projection()
{
- return copy_matrix(gGLLastProjection);
+ return copy_matrix(gGLLastProjection);
}
void copy_matrix(const glh::matrix4f& src, F32* dst)
{
- for (U32 i = 0; i < 16; i++)
- {
- dst[i] = src.m[i];
- }
+ for (U32 i = 0; i < 16; i++)
+ {
+ dst[i] = src.m[i];
+ }
}
void set_current_modelview(const glh::matrix4f& mat)
{
- copy_matrix(mat, gGLModelView);
+ copy_matrix(mat, gGLModelView);
}
void set_current_projection(glh::matrix4f& mat)
{
- copy_matrix(mat, gGLProjection);
+ copy_matrix(mat, gGLProjection);
}
glh::matrix4f gl_ortho(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat znear, GLfloat zfar)
{
- glh::matrix4f ret(
- 2.f/(right-left), 0.f, 0.f, -(right+left)/(right-left),
- 0.f, 2.f/(top-bottom), 0.f, -(top+bottom)/(top-bottom),
- 0.f, 0.f, -2.f/(zfar-znear), -(zfar+znear)/(zfar-znear),
- 0.f, 0.f, 0.f, 1.f);
+ glh::matrix4f ret(
+ 2.f/(right-left), 0.f, 0.f, -(right+left)/(right-left),
+ 0.f, 2.f/(top-bottom), 0.f, -(top+bottom)/(top-bottom),
+ 0.f, 0.f, -2.f/(zfar-znear), -(zfar+znear)/(zfar-znear),
+ 0.f, 0.f, 0.f, 1.f);
- return ret;
+ return ret;
}
glh::matrix4f gl_perspective(GLfloat fovy, GLfloat aspect, GLfloat zNear, GLfloat zFar)
{
- GLfloat f = 1.f/tanf(DEG_TO_RAD*fovy/2.f);
+ GLfloat f = 1.f/tanf(DEG_TO_RAD*fovy/2.f);
- return glh::matrix4f(f/aspect, 0, 0, 0,
- 0, f, 0, 0,
- 0, 0, (zFar+zNear)/(zNear-zFar), (2.f*zFar*zNear)/(zNear-zFar),
- 0, 0, -1.f, 0);
+ return glh::matrix4f(f/aspect, 0, 0, 0,
+ 0, f, 0, 0,
+ 0, 0, (zFar+zNear)/(zNear-zFar), (2.f*zFar*zNear)/(zNear-zFar),
+ 0, 0, -1.f, 0);
}
glh::matrix4f gl_lookat(LLVector3 eye, LLVector3 center, LLVector3 up)
{
- LLVector3 f = center-eye;
- f.normVec();
- up.normVec();
- LLVector3 s = f % up;
- LLVector3 u = s % f;
-
- return glh::matrix4f(s[0], s[1], s[2], 0,
- u[0], u[1], u[2], 0,
- -f[0], -f[1], -f[2], 0,
- 0, 0, 0, 1);
-
+ LLVector3 f = center-eye;
+ f.normVec();
+ up.normVec();
+ LLVector3 s = f % up;
+ LLVector3 u = s % f;
+
+ return glh::matrix4f(s[0], s[1], s[2], 0,
+ u[0], u[1], u[2], 0,
+ -f[0], -f[1], -f[2], 0,
+ 0, 0, 0, 1);
+
}
diff --git a/indra/llrender/llrender.h b/indra/llrender/llrender.h
index 716b52354d..ebdc9e751d 100644
--- a/indra/llrender/llrender.h
+++ b/indra/llrender/llrender.h
@@ -1,30 +1,30 @@
-/**
+/**
* @file llrender.h
* @brief LLRender definition
*
- * This class acts as a wrapper for OpenGL calls.
- * The goal of this class is to minimize the number of api calls due to legacy rendering
- * code, to define an interface for a multiple rendering API abstraction of the UI
- * rendering, and to abstract out direct rendering calls in a way that is cleaner and easier to maintain.
+ * This class acts as a wrapper for OpenGL calls.
+ * The goal of this class is to minimize the number of api calls due to legacy rendering
+ * code, to define an interface for a multiple rendering API abstraction of the UI
+ * rendering, and to abstract out direct rendering calls in a way that is cleaner and easier to maintain.
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -57,89 +57,89 @@ class LLTexture ;
constexpr U32 LL_NUM_TEXTURE_LAYERS = 32;
constexpr U32 LL_NUM_LIGHT_UNITS = 8;
-class LLTexUnit
+class LLTexUnit
{
- friend class LLRender;
+ friend class LLRender;
public:
- static U32 sWhiteTexture;
-
- typedef enum
- {
- TT_TEXTURE = 0, // Standard 2D Texture
- TT_RECT_TEXTURE, // Non power of 2 texture
- TT_CUBE_MAP, // 6-sided cube map texture
- TT_CUBE_MAP_ARRAY, // Array of cube maps
- TT_MULTISAMPLE_TEXTURE, // see GL_ARB_texture_multisample
+ static U32 sWhiteTexture;
+
+ typedef enum
+ {
+ TT_TEXTURE = 0, // Standard 2D Texture
+ TT_RECT_TEXTURE, // Non power of 2 texture
+ TT_CUBE_MAP, // 6-sided cube map texture
+ TT_CUBE_MAP_ARRAY, // Array of cube maps
+ TT_MULTISAMPLE_TEXTURE, // see GL_ARB_texture_multisample
TT_TEXTURE_3D, // standard 3D Texture
- TT_NONE, // No texture type is currently enabled
- } eTextureType;
-
- typedef enum
- {
- TAM_WRAP = 0, // Standard 2D Texture
- TAM_MIRROR, // Non power of 2 texture
- TAM_CLAMP // No texture type is currently enabled
- } eTextureAddressMode;
-
- typedef enum
- { // Note: If mipmapping or anisotropic are not enabled or supported it should fall back gracefully
- TFO_POINT = 0, // Equal to: min=point, mag=point, mip=none.
- TFO_BILINEAR, // Equal to: min=linear, mag=linear, mip=point.
- TFO_TRILINEAR, // Equal to: min=linear, mag=linear, mip=linear.
- TFO_ANISOTROPIC // Equal to: min=anisotropic, max=anisotropic, mip=linear.
- } eTextureFilterOptions;
-
- typedef enum
- {
- TMG_NONE = 0, // Mipmaps are not automatically generated for this texture.
- TMG_AUTO, // Mipmaps are automatically generated for this texture.
- TMG_MANUAL // Mipmaps are manually generated for this texture.
- } eTextureMipGeneration;
-
- typedef enum
- {
- TB_REPLACE = 0,
- TB_ADD,
- TB_MULT,
- TB_MULT_X2,
- TB_ALPHA_BLEND,
- TB_COMBINE // Doesn't need to be set directly, setTexture___Blend() set TB_COMBINE automatically
- } eTextureBlendType;
-
- typedef enum
- {
- TBO_REPLACE = 0, // Use Source 1
- TBO_MULT, // Multiply: ( Source1 * Source2 )
- TBO_MULT_X2, // Multiply then scale by 2: ( 2.0 * ( Source1 * Source2 ) )
- TBO_MULT_X4, // Multiply then scale by 4: ( 4.0 * ( Source1 * Source2 ) )
- TBO_ADD, // Add: ( Source1 + Source2 )
- TBO_ADD_SIGNED, // Add then subtract 0.5: ( ( Source1 + Source2 ) - 0.5 )
- TBO_SUBTRACT, // Subtract Source2 from Source1: ( Source1 - Source2 )
- TBO_LERP_VERT_ALPHA, // Interpolate based on Vertex Alpha (VA): ( Source1 * VA + Source2 * (1-VA) )
- TBO_LERP_TEX_ALPHA, // Interpolate based on Texture Alpha (TA): ( Source1 * TA + Source2 * (1-TA) )
- TBO_LERP_PREV_ALPHA, // Interpolate based on Previous Alpha (PA): ( Source1 * PA + Source2 * (1-PA) )
- TBO_LERP_CONST_ALPHA // Interpolate based on Const Alpha (CA): ( Source1 * CA + Source2 * (1-CA) )
- } eTextureBlendOp;
-
- typedef enum
- {
- TBS_PREV_COLOR = 0, // Color from the previous texture stage
- TBS_PREV_ALPHA,
- TBS_ONE_MINUS_PREV_COLOR,
- TBS_ONE_MINUS_PREV_ALPHA,
- TBS_TEX_COLOR, // Color from the texture bound to this stage
- TBS_TEX_ALPHA,
- TBS_ONE_MINUS_TEX_COLOR,
- TBS_ONE_MINUS_TEX_ALPHA,
- TBS_VERT_COLOR, // The vertex color currently set
- TBS_VERT_ALPHA,
- TBS_ONE_MINUS_VERT_COLOR,
- TBS_ONE_MINUS_VERT_ALPHA,
- TBS_CONST_COLOR, // The constant color value currently set
- TBS_CONST_ALPHA,
- TBS_ONE_MINUS_CONST_COLOR,
- TBS_ONE_MINUS_CONST_ALPHA
- } eTextureBlendSrc;
+ TT_NONE, // No texture type is currently enabled
+ } eTextureType;
+
+ typedef enum
+ {
+ TAM_WRAP = 0, // Standard 2D Texture
+ TAM_MIRROR, // Non power of 2 texture
+ TAM_CLAMP // No texture type is currently enabled
+ } eTextureAddressMode;
+
+ typedef enum
+ { // Note: If mipmapping or anisotropic are not enabled or supported it should fall back gracefully
+ TFO_POINT = 0, // Equal to: min=point, mag=point, mip=none.
+ TFO_BILINEAR, // Equal to: min=linear, mag=linear, mip=point.
+ TFO_TRILINEAR, // Equal to: min=linear, mag=linear, mip=linear.
+ TFO_ANISOTROPIC // Equal to: min=anisotropic, max=anisotropic, mip=linear.
+ } eTextureFilterOptions;
+
+ typedef enum
+ {
+ TMG_NONE = 0, // Mipmaps are not automatically generated for this texture.
+ TMG_AUTO, // Mipmaps are automatically generated for this texture.
+ TMG_MANUAL // Mipmaps are manually generated for this texture.
+ } eTextureMipGeneration;
+
+ typedef enum
+ {
+ TB_REPLACE = 0,
+ TB_ADD,
+ TB_MULT,
+ TB_MULT_X2,
+ TB_ALPHA_BLEND,
+ TB_COMBINE // Doesn't need to be set directly, setTexture___Blend() set TB_COMBINE automatically
+ } eTextureBlendType;
+
+ typedef enum
+ {
+ TBO_REPLACE = 0, // Use Source 1
+ TBO_MULT, // Multiply: ( Source1 * Source2 )
+ TBO_MULT_X2, // Multiply then scale by 2: ( 2.0 * ( Source1 * Source2 ) )
+ TBO_MULT_X4, // Multiply then scale by 4: ( 4.0 * ( Source1 * Source2 ) )
+ TBO_ADD, // Add: ( Source1 + Source2 )
+ TBO_ADD_SIGNED, // Add then subtract 0.5: ( ( Source1 + Source2 ) - 0.5 )
+ TBO_SUBTRACT, // Subtract Source2 from Source1: ( Source1 - Source2 )
+ TBO_LERP_VERT_ALPHA, // Interpolate based on Vertex Alpha (VA): ( Source1 * VA + Source2 * (1-VA) )
+ TBO_LERP_TEX_ALPHA, // Interpolate based on Texture Alpha (TA): ( Source1 * TA + Source2 * (1-TA) )
+ TBO_LERP_PREV_ALPHA, // Interpolate based on Previous Alpha (PA): ( Source1 * PA + Source2 * (1-PA) )
+ TBO_LERP_CONST_ALPHA // Interpolate based on Const Alpha (CA): ( Source1 * CA + Source2 * (1-CA) )
+ } eTextureBlendOp;
+
+ typedef enum
+ {
+ TBS_PREV_COLOR = 0, // Color from the previous texture stage
+ TBS_PREV_ALPHA,
+ TBS_ONE_MINUS_PREV_COLOR,
+ TBS_ONE_MINUS_PREV_ALPHA,
+ TBS_TEX_COLOR, // Color from the texture bound to this stage
+ TBS_TEX_ALPHA,
+ TBS_ONE_MINUS_TEX_COLOR,
+ TBS_ONE_MINUS_TEX_ALPHA,
+ TBS_VERT_COLOR, // The vertex color currently set
+ TBS_VERT_ALPHA,
+ TBS_ONE_MINUS_VERT_COLOR,
+ TBS_ONE_MINUS_VERT_ALPHA,
+ TBS_CONST_COLOR, // The constant color value currently set
+ TBS_CONST_ALPHA,
+ TBS_ONE_MINUS_CONST_COLOR,
+ TBS_ONE_MINUS_CONST_ALPHA
+ } eTextureBlendSrc;
typedef enum
{
@@ -147,77 +147,77 @@ public:
TCS_SRGB
} eTextureColorSpace;
- LLTexUnit(S32 index = -1);
+ LLTexUnit(S32 index = -1);
+
+ // Refreshes renderer state of the texture unit to the cached values
+ // Needed when the render context has changed and invalidated the current state
+ void refreshState(void);
- // Refreshes renderer state of the texture unit to the cached values
- // Needed when the render context has changed and invalidated the current state
- void refreshState(void);
+ // returns the index of this texture unit
+ S32 getIndex(void) const { return mIndex; }
- // returns the index of this texture unit
- S32 getIndex(void) const { return mIndex; }
+ // Sets this tex unit to be the currently active one
+ void activate(void);
- // Sets this tex unit to be the currently active one
- void activate(void);
+ // Enables this texture unit for the given texture type
+ // (automatically disables any previously enabled texture type)
+ void enable(eTextureType type);
- // Enables this texture unit for the given texture type
- // (automatically disables any previously enabled texture type)
- void enable(eTextureType type);
+ // Disables the current texture unit
+ void disable(void);
- // Disables the current texture unit
- void disable(void);
-
- // Binds the LLImageGL to this texture unit
- // (automatically enables the unit for the LLImageGL's texture type)
- bool bind(LLImageGL* texture, bool for_rendering = false, bool forceBind = false, S32 usename = 0);
+ // Binds the LLImageGL to this texture unit
+ // (automatically enables the unit for the LLImageGL's texture type)
+ bool bind(LLImageGL* texture, bool for_rendering = false, bool forceBind = false, S32 usename = 0);
bool bind(LLTexture* texture, bool for_rendering = false, bool forceBind = false);
// bind implementation for inner loops
// makes the following assumptions:
- // - No need for gGL.flush()
+ // - No need for gGL.flush()
// - texture is not null
// - gl_tex->getTexName() is not zero
// - This texture is not being bound redundantly
// - USE_SRGB_DECODE is disabled
// - mTexOptionsDirty is false
- // -
+ // -
void bindFast(LLTexture* texture);
- // Binds a cubemap to this texture unit
- // (automatically enables the texture unit for cubemaps)
- bool bind(LLCubeMap* cubeMap);
+ // Binds a cubemap to this texture unit
+ // (automatically enables the texture unit for cubemaps)
+ bool bind(LLCubeMap* cubeMap);
- // Binds a render target to this texture unit
- // (automatically enables the texture unit for the RT's texture type)
- bool bind(LLRenderTarget * renderTarget, bool bindDepth = false);
+ // Binds a render target to this texture unit
+ // (automatically enables the texture unit for the RT's texture type)
+ bool bind(LLRenderTarget * renderTarget, bool bindDepth = false);
- // Manually binds a texture to the texture unit
- // (automatically enables the tex unit for the given texture type)
- bool bindManual(eTextureType type, U32 texture, bool hasMips = false);
-
- // Unbinds the currently bound texture of the given type
- // (only if there's a texture of the given type currently bound)
- void unbind(eTextureType type);
+ // Manually binds a texture to the texture unit
+ // (automatically enables the tex unit for the given texture type)
+ bool bindManual(eTextureType type, U32 texture, bool hasMips = false);
+
+ // Unbinds the currently bound texture of the given type
+ // (only if there's a texture of the given type currently bound)
+ void unbind(eTextureType type);
// Fast but unsafe version of unbind
void unbindFast(eTextureType type);
- // Sets the addressing mode used to sample the texture
- // Warning: this stays set for the bound texture forever,
- // make sure you want to permanently change the address mode for the bound texture.
- void setTextureAddressMode(eTextureAddressMode mode);
+ // Sets the addressing mode used to sample the texture
+ // Warning: this stays set for the bound texture forever,
+ // make sure you want to permanently change the address mode for the bound texture.
+ void setTextureAddressMode(eTextureAddressMode mode);
- // Sets the filtering options used to sample the texture
- // Warning: this stays set for the bound texture forever,
- // make sure you want to permanently change the filtering for the bound texture.
- void setTextureFilteringOption(LLTexUnit::eTextureFilterOptions option);
+ // Sets the filtering options used to sample the texture
+ // Warning: this stays set for the bound texture forever,
+ // make sure you want to permanently change the filtering for the bound texture.
+ void setTextureFilteringOption(LLTexUnit::eTextureFilterOptions option);
- static U32 getInternalType(eTextureType type);
+ static U32 getInternalType(eTextureType type);
- U32 getCurrTexture(void) { return mCurrTexture; }
+ U32 getCurrTexture(void) { return mCurrTexture; }
- eTextureType getCurrType(void) { return mCurrTexType; }
+ eTextureType getCurrType(void) { return mCurrTexType; }
- void setHasMipMaps(bool hasMips) { mHasMipMaps = hasMips; }
+ void setHasMipMaps(bool hasMips) { mHasMipMaps = hasMips; }
void setTextureColorSpace(eTextureColorSpace space);
@@ -226,293 +226,293 @@ public:
protected:
friend class LLRender;
- S32 mIndex;
- U32 mCurrTexture;
- eTextureType mCurrTexType;
+ S32 mIndex;
+ U32 mCurrTexture;
+ eTextureType mCurrTexType;
eTextureColorSpace mTexColorSpace;
- S32 mCurrColorScale;
- S32 mCurrAlphaScale;
- bool mHasMipMaps;
-
- void debugTextureUnit(void);
- void setColorScale(S32 scale);
- void setAlphaScale(S32 scale);
- GLint getTextureSource(eTextureBlendSrc src);
- GLint getTextureSourceType(eTextureBlendSrc src, bool isAlpha = false);
+ S32 mCurrColorScale;
+ S32 mCurrAlphaScale;
+ bool mHasMipMaps;
+
+ void debugTextureUnit(void);
+ void setColorScale(S32 scale);
+ void setAlphaScale(S32 scale);
+ GLint getTextureSource(eTextureBlendSrc src);
+ GLint getTextureSourceType(eTextureBlendSrc src, bool isAlpha = false);
};
class LLLightState
{
public:
- LLLightState(S32 index = -1);
+ LLLightState(S32 index = -1);
- void enable();
- void disable();
- void setDiffuse(const LLColor4& diffuse);
+ void enable();
+ void disable();
+ void setDiffuse(const LLColor4& diffuse);
void setDiffuseB(const LLColor4& diffuse);
- void setAmbient(const LLColor4& ambient);
- void setSpecular(const LLColor4& specular);
- void setPosition(const LLVector4& position);
- void setConstantAttenuation(const F32& atten);
- void setLinearAttenuation(const F32& atten);
- void setQuadraticAttenuation(const F32& atten);
- void setSpotExponent(const F32& exponent);
- void setSpotCutoff(const F32& cutoff);
- void setSpotDirection(const LLVector3& direction);
+ void setAmbient(const LLColor4& ambient);
+ void setSpecular(const LLColor4& specular);
+ void setPosition(const LLVector4& position);
+ void setConstantAttenuation(const F32& atten);
+ void setLinearAttenuation(const F32& atten);
+ void setQuadraticAttenuation(const F32& atten);
+ void setSpotExponent(const F32& exponent);
+ void setSpotCutoff(const F32& cutoff);
+ void setSpotDirection(const LLVector3& direction);
void setSunPrimary(bool v);
void setSize(F32 size);
void setFalloff(F32 falloff);
protected:
- friend class LLRender;
+ friend class LLRender;
- S32 mIndex;
- bool mEnabled;
- LLColor4 mDiffuse;
+ S32 mIndex;
+ bool mEnabled;
+ LLColor4 mDiffuse;
LLColor4 mDiffuseB;
bool mSunIsPrimary;
- LLColor4 mAmbient;
- LLColor4 mSpecular;
- LLVector4 mPosition;
- LLVector3 mSpotDirection;
+ LLColor4 mAmbient;
+ LLColor4 mSpecular;
+ LLVector4 mPosition;
+ LLVector3 mSpotDirection;
- F32 mConstantAtten;
- F32 mLinearAtten;
- F32 mQuadraticAtten;
+ F32 mConstantAtten;
+ F32 mLinearAtten;
+ F32 mQuadraticAtten;
- F32 mSpotExponent;
- F32 mSpotCutoff;
+ F32 mSpotExponent;
+ F32 mSpotCutoff;
F32 mSize = 0.f;
F32 mFalloff = 0.f;
};
class LLRender
{
- friend class LLTexUnit;
+ friend class LLTexUnit;
public:
- enum eTexIndex : U8
- {
- DIFFUSE_MAP = 0,
+ enum eTexIndex : U8
+ {
+ DIFFUSE_MAP = 0,
ALTERNATE_DIFFUSE_MAP = 1,
- NORMAL_MAP = 1,
- SPECULAR_MAP = 2,
- NUM_TEXTURE_CHANNELS = 3,
- };
-
- enum eVolumeTexIndex : U8
- {
- LIGHT_TEX = 0,
- SCULPT_TEX,
- NUM_VOLUME_TEXTURE_CHANNELS,
- };
-
- enum eGeomModes : U8
+ NORMAL_MAP = 1,
+ SPECULAR_MAP = 2,
+ NUM_TEXTURE_CHANNELS = 3,
+ };
+
+ enum eVolumeTexIndex : U8
+ {
+ LIGHT_TEX = 0,
+ SCULPT_TEX,
+ NUM_VOLUME_TEXTURE_CHANNELS,
+ };
+
+ enum eGeomModes : U8
+ {
+ TRIANGLES = 0,
+ TRIANGLE_STRIP,
+ TRIANGLE_FAN,
+ POINTS,
+ LINES,
+ LINE_STRIP,
+ QUADS,
+ LINE_LOOP,
+ NUM_MODES
+ };
+
+ enum eCompareFunc : U8
{
- TRIANGLES = 0,
- TRIANGLE_STRIP,
- TRIANGLE_FAN,
- POINTS,
- LINES,
- LINE_STRIP,
- QUADS,
- LINE_LOOP,
- NUM_MODES
- };
-
- enum eCompareFunc : U8
- {
- CF_NEVER = 0,
- CF_ALWAYS,
- CF_LESS,
- CF_LESS_EQUAL,
- CF_EQUAL,
- CF_NOT_EQUAL,
- CF_GREATER_EQUAL,
- CF_GREATER,
- CF_DEFAULT
- };
-
- enum eBlendType : U8
- {
- BT_ALPHA = 0,
- BT_ADD,
- BT_ADD_WITH_ALPHA, // Additive blend modulated by the fragment's alpha.
- BT_MULT,
- BT_MULT_ALPHA,
- BT_MULT_X2,
- BT_REPLACE
- };
-
- // WARNING: this MUST match the LL_PART_BF enum in LLPartData, so set values explicitly in case someone
+ CF_NEVER = 0,
+ CF_ALWAYS,
+ CF_LESS,
+ CF_LESS_EQUAL,
+ CF_EQUAL,
+ CF_NOT_EQUAL,
+ CF_GREATER_EQUAL,
+ CF_GREATER,
+ CF_DEFAULT
+ };
+
+ enum eBlendType : U8
+ {
+ BT_ALPHA = 0,
+ BT_ADD,
+ BT_ADD_WITH_ALPHA, // Additive blend modulated by the fragment's alpha.
+ BT_MULT,
+ BT_MULT_ALPHA,
+ BT_MULT_X2,
+ BT_REPLACE
+ };
+
+ // WARNING: this MUST match the LL_PART_BF enum in LLPartData, so set values explicitly in case someone
// decides to add more or reorder them
- enum eBlendFactor : U8
- {
- BF_ONE = 0,
- BF_ZERO = 1,
- BF_DEST_COLOR = 2,
- BF_SOURCE_COLOR = 3,
- BF_ONE_MINUS_DEST_COLOR = 4,
- BF_ONE_MINUS_SOURCE_COLOR = 5,
- BF_DEST_ALPHA = 6,
- BF_SOURCE_ALPHA = 7,
- BF_ONE_MINUS_DEST_ALPHA = 8,
- BF_ONE_MINUS_SOURCE_ALPHA = 9,
- BF_UNDEF
- };
-
- enum eMatrixMode : U8
- {
- MM_MODELVIEW = 0,
- MM_PROJECTION,
- MM_TEXTURE0,
- MM_TEXTURE1,
- MM_TEXTURE2,
- MM_TEXTURE3,
- NUM_MATRIX_MODES,
- MM_TEXTURE
- };
-
- LLRender();
- ~LLRender();
+ enum eBlendFactor : U8
+ {
+ BF_ONE = 0,
+ BF_ZERO = 1,
+ BF_DEST_COLOR = 2,
+ BF_SOURCE_COLOR = 3,
+ BF_ONE_MINUS_DEST_COLOR = 4,
+ BF_ONE_MINUS_SOURCE_COLOR = 5,
+ BF_DEST_ALPHA = 6,
+ BF_SOURCE_ALPHA = 7,
+ BF_ONE_MINUS_DEST_ALPHA = 8,
+ BF_ONE_MINUS_SOURCE_ALPHA = 9,
+ BF_UNDEF
+ };
+
+ enum eMatrixMode : U8
+ {
+ MM_MODELVIEW = 0,
+ MM_PROJECTION,
+ MM_TEXTURE0,
+ MM_TEXTURE1,
+ MM_TEXTURE2,
+ MM_TEXTURE3,
+ NUM_MATRIX_MODES,
+ MM_TEXTURE
+ };
+
+ LLRender();
+ ~LLRender();
bool init(bool needs_vertex_buffer);
void initVertexBuffer();
void resetVertexBuffer();
- void shutdown();
-
- // Refreshes renderer state to the cached values
- // Needed when the render context has changed and invalidated the current state
- void refreshState(void);
-
- void translatef(const GLfloat& x, const GLfloat& y, const GLfloat& z);
- void scalef(const GLfloat& x, const GLfloat& y, const GLfloat& z);
- void rotatef(const GLfloat& a, const GLfloat& x, const GLfloat& y, const GLfloat& z);
- void ortho(F32 left, F32 right, F32 bottom, F32 top, F32 zNear, F32 zFar);
-
- void pushMatrix();
- void popMatrix();
- void loadMatrix(const GLfloat* m);
- void loadIdentity();
- void multMatrix(const GLfloat* m);
- void matrixMode(eMatrixMode mode);
- eMatrixMode getMatrixMode();
-
- const glh::matrix4f& getModelviewMatrix();
- const glh::matrix4f& getProjectionMatrix();
-
- void syncMatrices();
- void syncLightState();
-
- 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);
- void end();
- void vertex2i(const GLint& x, const GLint& y);
- void vertex2f(const GLfloat& x, const GLfloat& y);
- void vertex3f(const GLfloat& x, const GLfloat& y, const GLfloat& z);
- void vertex2fv(const GLfloat* v);
- void vertex3fv(const GLfloat* v);
-
- void texCoord2i(const GLint& x, const GLint& y);
- void texCoord2f(const GLfloat& x, const GLfloat& y);
- void texCoord2fv(const GLfloat* tc);
-
- void color4ub(const GLubyte& r, const GLubyte& g, const GLubyte& b, const GLubyte& a);
- void color4f(const GLfloat& r, const GLfloat& g, const GLfloat& b, const GLfloat& a);
- void color4fv(const GLfloat* c);
- void color3f(const GLfloat& r, const GLfloat& g, const GLfloat& b);
- void color3fv(const GLfloat* c);
- void color4ubv(const GLubyte* c);
-
- void diffuseColor3f(F32 r, F32 g, F32 b);
- void diffuseColor3fv(const F32* c);
- void diffuseColor4f(F32 r, F32 g, F32 b, F32 a);
- void diffuseColor4fv(const F32* c);
- void diffuseColor4ubv(const U8* c);
- void diffuseColor4ub(U8 r, U8 g, U8 b, U8 a);
-
- 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);
-
- // applies blend func to both color and alpha
- void blendFunc(eBlendFactor sfactor, eBlendFactor dfactor);
- // applies separate blend functions to color and alpha
- void blendFunc(eBlendFactor color_sfactor, eBlendFactor color_dfactor,
- eBlendFactor alpha_sfactor, eBlendFactor alpha_dfactor);
-
- LLLightState* getLight(U32 index);
- void setAmbientLightColor(const LLColor4& color);
-
- LLTexUnit* getTexUnit(U32 index);
-
- U32 getCurrentTexUnitIndex(void) const { return mCurrTextureUnitIndex; }
-
- bool verifyTexUnitActive(U32 unitToVerify);
-
- void debugTexUnits(void);
-
- void clearErrors();
-
- struct Vertex
- {
- GLfloat v[3];
- GLubyte c[4];
- GLfloat uv[2];
- };
+ void shutdown();
+
+ // Refreshes renderer state to the cached values
+ // Needed when the render context has changed and invalidated the current state
+ void refreshState(void);
+
+ void translatef(const GLfloat& x, const GLfloat& y, const GLfloat& z);
+ void scalef(const GLfloat& x, const GLfloat& y, const GLfloat& z);
+ void rotatef(const GLfloat& a, const GLfloat& x, const GLfloat& y, const GLfloat& z);
+ void ortho(F32 left, F32 right, F32 bottom, F32 top, F32 zNear, F32 zFar);
+
+ void pushMatrix();
+ void popMatrix();
+ void loadMatrix(const GLfloat* m);
+ void loadIdentity();
+ void multMatrix(const GLfloat* m);
+ void matrixMode(eMatrixMode mode);
+ eMatrixMode getMatrixMode();
+
+ const glh::matrix4f& getModelviewMatrix();
+ const glh::matrix4f& getProjectionMatrix();
+
+ void syncMatrices();
+ void syncLightState();
+
+ 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);
+ void end();
+ void vertex2i(const GLint& x, const GLint& y);
+ void vertex2f(const GLfloat& x, const GLfloat& y);
+ void vertex3f(const GLfloat& x, const GLfloat& y, const GLfloat& z);
+ void vertex2fv(const GLfloat* v);
+ void vertex3fv(const GLfloat* v);
+
+ void texCoord2i(const GLint& x, const GLint& y);
+ void texCoord2f(const GLfloat& x, const GLfloat& y);
+ void texCoord2fv(const GLfloat* tc);
+
+ void color4ub(const GLubyte& r, const GLubyte& g, const GLubyte& b, const GLubyte& a);
+ void color4f(const GLfloat& r, const GLfloat& g, const GLfloat& b, const GLfloat& a);
+ void color4fv(const GLfloat* c);
+ void color3f(const GLfloat& r, const GLfloat& g, const GLfloat& b);
+ void color3fv(const GLfloat* c);
+ void color4ubv(const GLubyte* c);
+
+ void diffuseColor3f(F32 r, F32 g, F32 b);
+ void diffuseColor3fv(const F32* c);
+ void diffuseColor4f(F32 r, F32 g, F32 b, F32 a);
+ void diffuseColor4fv(const F32* c);
+ void diffuseColor4ubv(const U8* c);
+ void diffuseColor4ub(U8 r, U8 g, U8 b, U8 a);
+
+ 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);
+
+ // applies blend func to both color and alpha
+ void blendFunc(eBlendFactor sfactor, eBlendFactor dfactor);
+ // applies separate blend functions to color and alpha
+ void blendFunc(eBlendFactor color_sfactor, eBlendFactor color_dfactor,
+ eBlendFactor alpha_sfactor, eBlendFactor alpha_dfactor);
+
+ LLLightState* getLight(U32 index);
+ void setAmbientLightColor(const LLColor4& color);
+
+ LLTexUnit* getTexUnit(U32 index);
+
+ U32 getCurrentTexUnitIndex(void) const { return mCurrTextureUnitIndex; }
+
+ bool verifyTexUnitActive(U32 unitToVerify);
+
+ void debugTexUnits(void);
+
+ void clearErrors();
+
+ struct Vertex
+ {
+ GLfloat v[3];
+ GLubyte c[4];
+ GLfloat uv[2];
+ };
public:
- static U32 sUICalls;
- static U32 sUIVerts;
- static bool sGLCoreProfile;
- static bool sNsightDebugSupport;
- static LLVector2 sUIGLScaleFactor;
+ static U32 sUICalls;
+ static U32 sUIVerts;
+ static bool sGLCoreProfile;
+ static bool sNsightDebugSupport;
+ static LLVector2 sUIGLScaleFactor;
private:
- friend class LLLightState;
-
- eMatrixMode mMatrixMode;
- U32 mMatIdx[NUM_MATRIX_MODES];
- U32 mMatHash[NUM_MATRIX_MODES];
- glh::matrix4f mMatrix[NUM_MATRIX_MODES][LL_MATRIX_STACK_DEPTH];
- U32 mCurMatHash[NUM_MATRIX_MODES];
- U32 mLightHash;
- LLColor4 mAmbientLightColor;
-
- bool mDirty;
- U32 mQuadCycle;
- U32 mCount;
- U32 mMode;
- U32 mCurrTextureUnitIndex;
- bool mCurrColorMask[4];
-
- LLPointer<LLVertexBuffer> mBuffer;
- LLStrider<LLVector3> mVerticesp;
- LLStrider<LLVector2> mTexcoordsp;
- LLStrider<LLColor4U> mColorsp;
- std::array<LLTexUnit, LL_NUM_TEXTURE_LAYERS> mTexUnits;
- LLTexUnit mDummyTexUnit;
- std::array<LLLightState, LL_NUM_LIGHT_UNITS> mLightState;
-
- eBlendFactor mCurrBlendColorSFactor;
- eBlendFactor mCurrBlendColorDFactor;
- eBlendFactor mCurrBlendAlphaSFactor;
- eBlendFactor mCurrBlendAlphaDFactor;
-
- std::vector<LLVector3> mUIOffset;
- std::vector<LLVector3> mUIScale;
+ friend class LLLightState;
+
+ eMatrixMode mMatrixMode;
+ U32 mMatIdx[NUM_MATRIX_MODES];
+ U32 mMatHash[NUM_MATRIX_MODES];
+ glh::matrix4f mMatrix[NUM_MATRIX_MODES][LL_MATRIX_STACK_DEPTH];
+ U32 mCurMatHash[NUM_MATRIX_MODES];
+ U32 mLightHash;
+ LLColor4 mAmbientLightColor;
+
+ bool mDirty;
+ U32 mQuadCycle;
+ U32 mCount;
+ U32 mMode;
+ U32 mCurrTextureUnitIndex;
+ bool mCurrColorMask[4];
+
+ LLPointer<LLVertexBuffer> mBuffer;
+ LLStrider<LLVector3> mVerticesp;
+ LLStrider<LLVector2> mTexcoordsp;
+ LLStrider<LLColor4U> mColorsp;
+ std::array<LLTexUnit, LL_NUM_TEXTURE_LAYERS> mTexUnits;
+ LLTexUnit mDummyTexUnit;
+ std::array<LLLightState, LL_NUM_LIGHT_UNITS> mLightState;
+
+ eBlendFactor mCurrBlendColorSFactor;
+ eBlendFactor mCurrBlendColorDFactor;
+ eBlendFactor mCurrBlendAlphaSFactor;
+ eBlendFactor mCurrBlendAlphaDFactor;
+
+ std::vector<LLVector3> mUIOffset;
+ std::vector<LLVector3> mUIScale;
};
@@ -526,12 +526,12 @@ extern F32 gGLInverseDeltaModelView[16];
extern thread_local LLRender gGL;
-// This rotation matrix moves the default OpenGL reference frame
+// This rotation matrix moves the default OpenGL reference frame
// (-Z at, Y up) to Cory's favorite reference frame (X at, Z up)
-const F32 OGL_TO_CFR_ROTATION[16] = { 0.f, 0.f, -1.f, 0.f, // -Z becomes X
- -1.f, 0.f, 0.f, 0.f, // -X becomes Y
- 0.f, 1.f, 0.f, 0.f, // Y becomes Z
- 0.f, 0.f, 0.f, 1.f };
+const F32 OGL_TO_CFR_ROTATION[16] = { 0.f, 0.f, -1.f, 0.f, // -Z becomes X
+ -1.f, 0.f, 0.f, 0.f, // -X becomes Y
+ 0.f, 1.f, 0.f, 0.f, // Y becomes Z
+ 0.f, 0.f, 0.f, 1.f };
glh::matrix4f copy_matrix(F32* src);
glh::matrix4f get_current_modelview();
diff --git a/indra/llrender/llrender2dutils.cpp b/indra/llrender/llrender2dutils.cpp
index 52869406d2..e1742f84a1 100644
--- a/indra/llrender/llrender2dutils.cpp
+++ b/indra/llrender/llrender2dutils.cpp
@@ -1,25 +1,25 @@
-/**
+/**
* @file llrender2dutils.cpp
* @brief GL function implementations for immediate-mode gl drawing.
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -53,9 +53,9 @@ const LLColor4 UI_VERTEX_COLOR(1.f, 1.f, 1.f, 1.f);
BOOL ui_point_in_rect(S32 x, S32 y, S32 left, S32 top, S32 right, S32 bottom)
{
- if (x < left || right < x) return FALSE;
- if (y < bottom || top < y) return FALSE;
- return TRUE;
+ if (x < left || right < x) return FALSE;
+ if (y < bottom || top < y) return FALSE;
+ return TRUE;
}
@@ -63,97 +63,97 @@ BOOL ui_point_in_rect(S32 x, S32 y, S32 left, S32 top, S32 right, S32 bottom)
// orthographic projection, etc.
void gl_state_for_2d(S32 width, S32 height)
{
- stop_glerror();
- F32 window_width = (F32) width;//gViewerWindow->getWindowWidth();
- F32 window_height = (F32) height;//gViewerWindow->getWindowHeight();
-
- gGL.matrixMode(LLRender::MM_PROJECTION);
- gGL.loadIdentity();
- gGL.ortho(0.0f, llmax(window_width, 1.f), 0.0f, llmax(window_height,1.f), -1.0f, 1.0f);
- gGL.matrixMode(LLRender::MM_MODELVIEW);
- gGL.loadIdentity();
- stop_glerror();
+ stop_glerror();
+ F32 window_width = (F32) width;//gViewerWindow->getWindowWidth();
+ F32 window_height = (F32) height;//gViewerWindow->getWindowHeight();
+
+ gGL.matrixMode(LLRender::MM_PROJECTION);
+ gGL.loadIdentity();
+ gGL.ortho(0.0f, llmax(window_width, 1.f), 0.0f, llmax(window_height,1.f), -1.0f, 1.0f);
+ gGL.matrixMode(LLRender::MM_MODELVIEW);
+ gGL.loadIdentity();
+ stop_glerror();
}
void gl_draw_x(const LLRect& rect, const LLColor4& color)
{
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
- gGL.color4fv( color.mV );
+ gGL.color4fv( color.mV );
- gGL.begin( LLRender::LINES );
- gGL.vertex2i( rect.mLeft, rect.mTop );
- gGL.vertex2i( rect.mRight, rect.mBottom );
- gGL.vertex2i( rect.mLeft, rect.mBottom );
- gGL.vertex2i( rect.mRight, rect.mTop );
- gGL.end();
+ gGL.begin( LLRender::LINES );
+ gGL.vertex2i( rect.mLeft, rect.mTop );
+ gGL.vertex2i( rect.mRight, rect.mBottom );
+ gGL.vertex2i( rect.mLeft, rect.mBottom );
+ gGL.vertex2i( rect.mRight, rect.mTop );
+ gGL.end();
}
void gl_rect_2d_offset_local( S32 left, S32 top, S32 right, S32 bottom, const LLColor4 &color, S32 pixel_offset, BOOL filled)
{
- gGL.color4fv(color.mV);
- gl_rect_2d_offset_local(left, top, right, bottom, pixel_offset, filled);
+ gGL.color4fv(color.mV);
+ gl_rect_2d_offset_local(left, top, right, bottom, pixel_offset, filled);
}
void gl_rect_2d_offset_local( S32 left, S32 top, S32 right, S32 bottom, S32 pixel_offset, BOOL filled)
{
- gGL.pushUIMatrix();
- left += LLFontGL::sCurOrigin.mX;
- right += LLFontGL::sCurOrigin.mX;
- bottom += LLFontGL::sCurOrigin.mY;
- top += LLFontGL::sCurOrigin.mY;
-
- gGL.loadUIIdentity();
- gl_rect_2d(llfloor((F32)left * LLRender::sUIGLScaleFactor.mV[VX]) - pixel_offset,
- llfloor((F32)top * LLRender::sUIGLScaleFactor.mV[VY]) + pixel_offset,
- llfloor((F32)right * LLRender::sUIGLScaleFactor.mV[VX]) + pixel_offset,
- llfloor((F32)bottom * LLRender::sUIGLScaleFactor.mV[VY]) - pixel_offset,
- filled);
- gGL.popUIMatrix();
+ gGL.pushUIMatrix();
+ left += LLFontGL::sCurOrigin.mX;
+ right += LLFontGL::sCurOrigin.mX;
+ bottom += LLFontGL::sCurOrigin.mY;
+ top += LLFontGL::sCurOrigin.mY;
+
+ gGL.loadUIIdentity();
+ gl_rect_2d(llfloor((F32)left * LLRender::sUIGLScaleFactor.mV[VX]) - pixel_offset,
+ llfloor((F32)top * LLRender::sUIGLScaleFactor.mV[VY]) + pixel_offset,
+ llfloor((F32)right * LLRender::sUIGLScaleFactor.mV[VX]) + pixel_offset,
+ llfloor((F32)bottom * LLRender::sUIGLScaleFactor.mV[VY]) - pixel_offset,
+ filled);
+ gGL.popUIMatrix();
}
void gl_rect_2d(S32 left, S32 top, S32 right, S32 bottom, BOOL filled )
{
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-
- // Counterclockwise quad will face the viewer
- if( filled )
- {
- gGL.begin( LLRender::QUADS );
- gGL.vertex2i(left, top);
- gGL.vertex2i(left, bottom);
- gGL.vertex2i(right, bottom);
- gGL.vertex2i(right, top);
- gGL.end();
- }
- else
- {
- top--;
- right--;
- gGL.begin( LLRender::LINE_STRIP );
- gGL.vertex2i(left, top);
- gGL.vertex2i(left, bottom);
- gGL.vertex2i(right, bottom);
- gGL.vertex2i(right, top);
- gGL.vertex2i(left, top);
- gGL.end();
- }
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+
+ // Counterclockwise quad will face the viewer
+ if( filled )
+ {
+ gGL.begin( LLRender::QUADS );
+ gGL.vertex2i(left, top);
+ gGL.vertex2i(left, bottom);
+ gGL.vertex2i(right, bottom);
+ gGL.vertex2i(right, top);
+ gGL.end();
+ }
+ else
+ {
+ top--;
+ right--;
+ gGL.begin( LLRender::LINE_STRIP );
+ gGL.vertex2i(left, top);
+ gGL.vertex2i(left, bottom);
+ gGL.vertex2i(right, bottom);
+ gGL.vertex2i(right, top);
+ gGL.vertex2i(left, top);
+ gGL.end();
+ }
}
void gl_rect_2d(S32 left, S32 top, S32 right, S32 bottom, const LLColor4 &color, BOOL filled )
{
- gGL.color4fv( color.mV );
- gl_rect_2d( left, top, right, bottom, filled );
+ gGL.color4fv( color.mV );
+ gl_rect_2d( left, top, right, bottom, filled );
}
void gl_rect_2d( const LLRect& rect, const LLColor4& color, BOOL filled )
{
- gGL.color4fv( color.mV );
- gl_rect_2d( rect.mLeft, rect.mTop, rect.mRight, rect.mBottom, filled );
+ gGL.color4fv( color.mV );
+ gl_rect_2d( rect.mLeft, rect.mTop, rect.mRight, rect.mBottom, filled );
}
// Given a rectangle on the screen, draws a drop shadow _outside_
@@ -161,715 +161,715 @@ void gl_rect_2d( const LLRect& rect, const LLColor4& color, BOOL filled )
// and along the bottom it has height "lines".
void gl_drop_shadow(S32 left, S32 top, S32 right, S32 bottom, const LLColor4 &start_color, S32 lines)
{
- stop_glerror();
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-
- // HACK: Overlap with the rectangle by a single pixel.
- right--;
- bottom++;
- lines++;
-
- LLColor4 end_color = start_color;
- end_color.mV[VALPHA] = 0.f;
-
- gGL.begin(LLRender::QUADS);
-
- // Right edge, CCW faces screen
- gGL.color4fv(start_color.mV);
- gGL.vertex2i(right, top-lines);
- gGL.vertex2i(right, bottom);
- gGL.color4fv(end_color.mV);
- gGL.vertex2i(right+lines, bottom);
- gGL.vertex2i(right+lines, top-lines);
-
- // Bottom edge, CCW faces screen
- gGL.color4fv(start_color.mV);
- gGL.vertex2i(right, bottom);
- gGL.vertex2i(left+lines, bottom);
- gGL.color4fv(end_color.mV);
- gGL.vertex2i(left+lines, bottom-lines);
- gGL.vertex2i(right, bottom-lines);
-
- // bottom left Corner
- gGL.color4fv(start_color.mV);
- gGL.vertex2i(left+lines, bottom);
- gGL.color4fv(end_color.mV);
- gGL.vertex2i(left, bottom);
- // make the bottom left corner not sharp
- gGL.vertex2i(left+1, bottom-lines+1);
- gGL.vertex2i(left+lines, bottom-lines);
-
- // bottom right corner
- gGL.color4fv(start_color.mV);
- gGL.vertex2i(right, bottom);
- gGL.color4fv(end_color.mV);
- gGL.vertex2i(right, bottom-lines);
- // make the rightmost corner not sharp
- gGL.vertex2i(right+lines-1, bottom-lines+1);
- gGL.vertex2i(right+lines, bottom);
-
- // top right corner
- gGL.color4fv(start_color.mV);
- gGL.vertex2i( right, top-lines );
- gGL.color4fv(end_color.mV);
- gGL.vertex2i( right+lines, top-lines );
- // make the corner not sharp
- gGL.vertex2i( right+lines-1, top-1 );
- gGL.vertex2i( right, top );
-
- gGL.end();
- stop_glerror();
+ stop_glerror();
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+
+ // HACK: Overlap with the rectangle by a single pixel.
+ right--;
+ bottom++;
+ lines++;
+
+ LLColor4 end_color = start_color;
+ end_color.mV[VALPHA] = 0.f;
+
+ gGL.begin(LLRender::QUADS);
+
+ // Right edge, CCW faces screen
+ gGL.color4fv(start_color.mV);
+ gGL.vertex2i(right, top-lines);
+ gGL.vertex2i(right, bottom);
+ gGL.color4fv(end_color.mV);
+ gGL.vertex2i(right+lines, bottom);
+ gGL.vertex2i(right+lines, top-lines);
+
+ // Bottom edge, CCW faces screen
+ gGL.color4fv(start_color.mV);
+ gGL.vertex2i(right, bottom);
+ gGL.vertex2i(left+lines, bottom);
+ gGL.color4fv(end_color.mV);
+ gGL.vertex2i(left+lines, bottom-lines);
+ gGL.vertex2i(right, bottom-lines);
+
+ // bottom left Corner
+ gGL.color4fv(start_color.mV);
+ gGL.vertex2i(left+lines, bottom);
+ gGL.color4fv(end_color.mV);
+ gGL.vertex2i(left, bottom);
+ // make the bottom left corner not sharp
+ gGL.vertex2i(left+1, bottom-lines+1);
+ gGL.vertex2i(left+lines, bottom-lines);
+
+ // bottom right corner
+ gGL.color4fv(start_color.mV);
+ gGL.vertex2i(right, bottom);
+ gGL.color4fv(end_color.mV);
+ gGL.vertex2i(right, bottom-lines);
+ // make the rightmost corner not sharp
+ gGL.vertex2i(right+lines-1, bottom-lines+1);
+ gGL.vertex2i(right+lines, bottom);
+
+ // top right corner
+ gGL.color4fv(start_color.mV);
+ gGL.vertex2i( right, top-lines );
+ gGL.color4fv(end_color.mV);
+ gGL.vertex2i( right+lines, top-lines );
+ // make the corner not sharp
+ gGL.vertex2i( right+lines-1, top-1 );
+ gGL.vertex2i( right, top );
+
+ gGL.end();
+ stop_glerror();
}
void gl_line_2d(S32 x1, S32 y1, S32 x2, S32 y2 )
{
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-
- gGL.begin(LLRender::LINES);
- gGL.vertex2i(x1, y1);
- gGL.vertex2i(x2, y2);
- gGL.end();
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+
+ gGL.begin(LLRender::LINES);
+ gGL.vertex2i(x1, y1);
+ gGL.vertex2i(x2, y2);
+ gGL.end();
}
void gl_line_2d(S32 x1, S32 y1, S32 x2, S32 y2, const LLColor4 &color )
{
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
- gGL.color4fv( color.mV );
+ gGL.color4fv( color.mV );
- gGL.begin(LLRender::LINES);
- gGL.vertex2i(x1, y1);
- gGL.vertex2i(x2, y2);
- gGL.end();
+ gGL.begin(LLRender::LINES);
+ gGL.vertex2i(x1, y1);
+ gGL.vertex2i(x2, y2);
+ gGL.end();
}
void gl_triangle_2d(S32 x1, S32 y1, S32 x2, S32 y2, S32 x3, S32 y3, const LLColor4& color, BOOL filled)
{
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-
- gGL.color4fv(color.mV);
-
- if (filled)
- {
- gGL.begin(LLRender::TRIANGLES);
- }
- else
- {
- gGL.begin(LLRender::LINE_LOOP);
- }
- gGL.vertex2i(x1, y1);
- gGL.vertex2i(x2, y2);
- gGL.vertex2i(x3, y3);
- gGL.end();
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+
+ gGL.color4fv(color.mV);
+
+ if (filled)
+ {
+ gGL.begin(LLRender::TRIANGLES);
+ }
+ else
+ {
+ gGL.begin(LLRender::LINE_LOOP);
+ }
+ gGL.vertex2i(x1, y1);
+ gGL.vertex2i(x2, y2);
+ gGL.vertex2i(x3, y3);
+ gGL.end();
}
void gl_corners_2d(S32 left, S32 top, S32 right, S32 bottom, S32 length, F32 max_frac)
{
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-
- length = llmin((S32)(max_frac*(right - left)), length);
- length = llmin((S32)(max_frac*(top - bottom)), length);
- gGL.begin(LLRender::LINES);
- gGL.vertex2i(left, top);
- gGL.vertex2i(left + length, top);
-
- gGL.vertex2i(left, top);
- gGL.vertex2i(left, top - length);
-
- gGL.vertex2i(left, bottom);
- gGL.vertex2i(left + length, bottom);
-
- gGL.vertex2i(left, bottom);
- gGL.vertex2i(left, bottom + length);
-
- gGL.vertex2i(right, top);
- gGL.vertex2i(right - length, top);
-
- gGL.vertex2i(right, top);
- gGL.vertex2i(right, top - length);
-
- gGL.vertex2i(right, bottom);
- gGL.vertex2i(right - length, bottom);
-
- gGL.vertex2i(right, bottom);
- gGL.vertex2i(right, bottom + length);
- gGL.end();
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+
+ length = llmin((S32)(max_frac*(right - left)), length);
+ length = llmin((S32)(max_frac*(top - bottom)), length);
+ gGL.begin(LLRender::LINES);
+ gGL.vertex2i(left, top);
+ gGL.vertex2i(left + length, top);
+
+ gGL.vertex2i(left, top);
+ gGL.vertex2i(left, top - length);
+
+ gGL.vertex2i(left, bottom);
+ gGL.vertex2i(left + length, bottom);
+
+ gGL.vertex2i(left, bottom);
+ gGL.vertex2i(left, bottom + length);
+
+ gGL.vertex2i(right, top);
+ gGL.vertex2i(right - length, top);
+
+ gGL.vertex2i(right, top);
+ gGL.vertex2i(right, top - length);
+
+ gGL.vertex2i(right, bottom);
+ gGL.vertex2i(right - length, bottom);
+
+ gGL.vertex2i(right, bottom);
+ gGL.vertex2i(right, bottom + length);
+ gGL.end();
}
void gl_draw_image( S32 x, S32 y, LLTexture* image, const LLColor4& color, const LLRectf& uv_rect )
{
- if (NULL == image)
- {
- LL_WARNS() << "image == NULL; aborting function" << LL_ENDL;
- return;
- }
- gl_draw_scaled_rotated_image( x, y, image->getWidth(0), image->getHeight(0), 0.f, image, color, uv_rect );
+ if (NULL == image)
+ {
+ LL_WARNS() << "image == NULL; aborting function" << LL_ENDL;
+ return;
+ }
+ gl_draw_scaled_rotated_image( x, y, image->getWidth(0), image->getHeight(0), 0.f, image, color, uv_rect );
}
void gl_draw_scaled_target(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* target, const LLColor4& color, const LLRectf& uv_rect)
{
- gl_draw_scaled_rotated_image(x, y, width, height, 0.f, NULL, color, uv_rect, target);
+ gl_draw_scaled_rotated_image(x, y, width, height, 0.f, NULL, color, uv_rect, target);
}
void gl_draw_scaled_image(S32 x, S32 y, S32 width, S32 height, LLTexture* image, const LLColor4& color, const LLRectf& uv_rect)
{
- if (NULL == image)
- {
- LL_WARNS() << "image == NULL; aborting function" << LL_ENDL;
- return;
- }
- gl_draw_scaled_rotated_image( x, y, width, height, 0.f, image, color, uv_rect );
+ if (NULL == image)
+ {
+ LL_WARNS() << "image == NULL; aborting function" << LL_ENDL;
+ return;
+ }
+ gl_draw_scaled_rotated_image( x, y, width, height, 0.f, image, color, uv_rect );
}
void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 border_width, S32 border_height, S32 width, S32 height, LLTexture* image, const LLColor4& color, BOOL solid_color, const LLRectf& uv_rect, bool scale_inner)
{
- if (NULL == image)
- {
- LL_WARNS() << "image == NULL; aborting function" << LL_ENDL;
- return;
- }
-
- // scale screen size of borders down
- F32 border_width_fraction = (F32)border_width / (F32)image->getWidth(0);
- F32 border_height_fraction = (F32)border_height / (F32)image->getHeight(0);
-
- LLRectf scale_rect(border_width_fraction, 1.f - border_height_fraction, 1.f - border_width_fraction, border_height_fraction);
- gl_draw_scaled_image_with_border(x, y, width, height, image, color, solid_color, uv_rect, scale_rect, scale_inner);
+ if (NULL == image)
+ {
+ LL_WARNS() << "image == NULL; aborting function" << LL_ENDL;
+ return;
+ }
+
+ // scale screen size of borders down
+ F32 border_width_fraction = (F32)border_width / (F32)image->getWidth(0);
+ F32 border_height_fraction = (F32)border_height / (F32)image->getHeight(0);
+
+ LLRectf scale_rect(border_width_fraction, 1.f - border_height_fraction, 1.f - border_width_fraction, border_height_fraction);
+ gl_draw_scaled_image_with_border(x, y, width, height, image, color, solid_color, uv_rect, scale_rect, scale_inner);
}
void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 width, S32 height, LLTexture* image, const LLColor4& color, BOOL solid_color, const LLRectf& uv_outer_rect, const LLRectf& center_rect, bool scale_inner)
{
- stop_glerror();
-
- if (NULL == image)
- {
- LL_WARNS() << "image == NULL; aborting function" << LL_ENDL;
- return;
- }
-
- if (solid_color)
- {
- gSolidColorProgram.bind();
- }
-
- if (center_rect.mLeft == 0.f
- && center_rect.mRight == 1.f
- && center_rect.mBottom == 0.f
- && center_rect.mTop == 1.f)
- {
- gl_draw_scaled_image(x, y, width, height, image, color, uv_outer_rect);
- }
- else
- {
- // add in offset of current image to current UI translation
- const LLVector3 ui_scale = gGL.getUIScale();
- const LLVector3 ui_translation = (gGL.getUITranslation() + LLVector3(x, y, 0.f)).scaledVec(ui_scale);
-
- F32 uv_width = uv_outer_rect.getWidth();
- F32 uv_height = uv_outer_rect.getHeight();
-
- // shrink scaling region to be proportional to clipped image region
- LLRectf uv_center_rect( uv_outer_rect.mLeft + (center_rect.mLeft * uv_width),
- uv_outer_rect.mBottom + (center_rect.mTop * uv_height),
- uv_outer_rect.mLeft + (center_rect.mRight * uv_width),
- uv_outer_rect.mBottom + (center_rect.mBottom * uv_height));
-
- F32 image_width = image->getWidth(0);
- F32 image_height = image->getHeight(0);
-
- S32 image_natural_width = ll_round(image_width * uv_width);
- S32 image_natural_height = ll_round(image_height * uv_height);
-
- LLRectf draw_center_rect( uv_center_rect.mLeft * image_width,
- uv_center_rect.mTop * image_height,
- uv_center_rect.mRight * image_width,
- uv_center_rect.mBottom * image_height);
-
- if (scale_inner)
- {
- // scale center region of image to drawn region
- draw_center_rect.mRight += width - image_natural_width;
- draw_center_rect.mTop += height - image_natural_height;
-
- const F32 border_shrink_width = llmax(0.f, draw_center_rect.mLeft - draw_center_rect.mRight);
- const F32 border_shrink_height = llmax(0.f, draw_center_rect.mBottom - draw_center_rect.mTop);
-
- const F32 shrink_width_ratio = center_rect.getWidth() == 1.f ? 0.f : border_shrink_width / ((F32)image_natural_width * (1.f - center_rect.getWidth()));
- const F32 shrink_height_ratio = center_rect.getHeight() == 1.f ? 0.f : border_shrink_height / ((F32)image_natural_height * (1.f - center_rect.getHeight()));
-
- const F32 border_shrink_scale = 1.f - llmax(shrink_width_ratio, shrink_height_ratio);
- draw_center_rect.mLeft *= border_shrink_scale;
- draw_center_rect.mTop = lerp((F32)height, (F32)draw_center_rect.mTop, border_shrink_scale);
- draw_center_rect.mRight = lerp((F32)width, (F32)draw_center_rect.mRight, border_shrink_scale);
- draw_center_rect.mBottom *= border_shrink_scale;
- }
- else
- {
- // keep center region of image at fixed scale, but in same relative position
- F32 scale_factor = llmin((F32)width / draw_center_rect.getWidth(), (F32)height / draw_center_rect.getHeight(), 1.f);
- F32 scaled_width = draw_center_rect.getWidth() * scale_factor;
- F32 scaled_height = draw_center_rect.getHeight() * scale_factor;
- draw_center_rect.setCenterAndSize(uv_center_rect.getCenterX() * width, uv_center_rect.getCenterY() * height, scaled_width, scaled_height);
- }
-
- draw_center_rect.mLeft = ll_round(ui_translation.mV[VX] + (F32)draw_center_rect.mLeft * ui_scale.mV[VX]);
- draw_center_rect.mTop = ll_round(ui_translation.mV[VY] + (F32)draw_center_rect.mTop * ui_scale.mV[VY]);
- draw_center_rect.mRight = ll_round(ui_translation.mV[VX] + (F32)draw_center_rect.mRight * ui_scale.mV[VX]);
- draw_center_rect.mBottom = ll_round(ui_translation.mV[VY] + (F32)draw_center_rect.mBottom * ui_scale.mV[VY]);
-
- LLRectf draw_outer_rect(ui_translation.mV[VX],
- ui_translation.mV[VY] + height * ui_scale.mV[VY],
- ui_translation.mV[VX] + width * ui_scale.mV[VX],
- ui_translation.mV[VY]);
-
- LLGLSUIDefault gls_ui;
-
- gGL.getTexUnit(0)->bind(image, true);
-
- gGL.color4fv(color.mV);
-
- const S32 NUM_VERTICES = 9 * 4; // 9 quads
- LLVector2 uv[NUM_VERTICES];
- LLVector3 pos[NUM_VERTICES];
-
- S32 index = 0;
-
- gGL.begin(LLRender::QUADS);
- {
- // draw bottom left
- uv[index] = LLVector2(uv_outer_rect.mLeft, uv_outer_rect.mBottom);
- pos[index] = LLVector3(draw_outer_rect.mLeft, draw_outer_rect.mBottom, 0.f);
- index++;
-
- uv[index] = LLVector2(uv_center_rect.mLeft, uv_outer_rect.mBottom);
- pos[index] = LLVector3(draw_center_rect.mLeft, draw_outer_rect.mBottom, 0.f);
- index++;
-
- uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mBottom);
- pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mBottom, 0.f);
- index++;
-
- uv[index] = LLVector2(uv_outer_rect.mLeft, uv_center_rect.mBottom);
- pos[index] = LLVector3(draw_outer_rect.mLeft, draw_center_rect.mBottom, 0.f);
- index++;
-
- // draw bottom middle
- uv[index] = LLVector2(uv_center_rect.mLeft, uv_outer_rect.mBottom);
- pos[index] = LLVector3(draw_center_rect.mLeft, draw_outer_rect.mBottom, 0.f);
- index++;
-
- uv[index] = LLVector2(uv_center_rect.mRight, uv_outer_rect.mBottom);
- pos[index] = LLVector3(draw_center_rect.mRight, draw_outer_rect.mBottom, 0.f);
- index++;
-
- uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mBottom);
- pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mBottom, 0.f);
- index++;
-
- uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mBottom);
- pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mBottom, 0.f);
- index++;
-
- // draw bottom right
- uv[index] = LLVector2(uv_center_rect.mRight, uv_outer_rect.mBottom);
- pos[index] = LLVector3(draw_center_rect.mRight, draw_outer_rect.mBottom, 0.f);
- index++;
-
- uv[index] = LLVector2(uv_outer_rect.mRight, uv_outer_rect.mBottom);
- pos[index] = LLVector3(draw_outer_rect.mRight, draw_outer_rect.mBottom, 0.f);
- index++;
-
- uv[index] = LLVector2(uv_outer_rect.mRight, uv_center_rect.mBottom);
- pos[index] = LLVector3(draw_outer_rect.mRight, draw_center_rect.mBottom, 0.f);
- index++;
-
- uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mBottom);
- pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mBottom, 0.f);
- index++;
-
- // draw left
- uv[index] = LLVector2(uv_outer_rect.mLeft, uv_center_rect.mBottom);
- pos[index] = LLVector3(draw_outer_rect.mLeft, draw_center_rect.mBottom, 0.f);
- index++;
-
- uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mBottom);
- pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mBottom, 0.f);
- index++;
-
- uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mTop);
- pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mTop, 0.f);
- index++;
-
- uv[index] = LLVector2(uv_outer_rect.mLeft, uv_center_rect.mTop);
- pos[index] = LLVector3(draw_outer_rect.mLeft, draw_center_rect.mTop, 0.f);
- index++;
-
- // draw middle
- uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mBottom);
- pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mBottom, 0.f);
- index++;
-
- uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mBottom);
- pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mBottom, 0.f);
- index++;
-
- uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mTop);
- pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mTop, 0.f);
- index++;
-
- uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mTop);
- pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mTop, 0.f);
- index++;
-
- // draw right
- uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mBottom);
- pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mBottom, 0.f);
- index++;
-
- uv[index] = LLVector2(uv_outer_rect.mRight, uv_center_rect.mBottom);
- pos[index] = LLVector3(draw_outer_rect.mRight, draw_center_rect.mBottom, 0.f);
- index++;
-
- uv[index] = LLVector2(uv_outer_rect.mRight, uv_center_rect.mTop);
- pos[index] = LLVector3(draw_outer_rect.mRight, draw_center_rect.mTop, 0.f);
- index++;
-
- uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mTop);
- pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mTop, 0.f);
- index++;
-
- // draw top left
- uv[index] = LLVector2(uv_outer_rect.mLeft, uv_center_rect.mTop);
- pos[index] = LLVector3(draw_outer_rect.mLeft, draw_center_rect.mTop, 0.f);
- index++;
-
- uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mTop);
- pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mTop, 0.f);
- index++;
-
- uv[index] = LLVector2(uv_center_rect.mLeft, uv_outer_rect.mTop);
- pos[index] = LLVector3(draw_center_rect.mLeft, draw_outer_rect.mTop, 0.f);
- index++;
-
- uv[index] = LLVector2(uv_outer_rect.mLeft, uv_outer_rect.mTop);
- pos[index] = LLVector3(draw_outer_rect.mLeft, draw_outer_rect.mTop, 0.f);
- index++;
-
- // draw top middle
- uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mTop);
- pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mTop, 0.f);
- index++;
-
- uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mTop);
- pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mTop, 0.f);
- index++;
-
- uv[index] = LLVector2(uv_center_rect.mRight, uv_outer_rect.mTop);
- pos[index] = LLVector3(draw_center_rect.mRight, draw_outer_rect.mTop, 0.f);
- index++;
-
- uv[index] = LLVector2(uv_center_rect.mLeft, uv_outer_rect.mTop);
- pos[index] = LLVector3(draw_center_rect.mLeft, draw_outer_rect.mTop, 0.f);
- index++;
-
- // draw top right
- uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mTop);
- pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mTop, 0.f);
- index++;
-
- uv[index] = LLVector2(uv_outer_rect.mRight, uv_center_rect.mTop);
- pos[index] = LLVector3(draw_outer_rect.mRight, draw_center_rect.mTop, 0.f);
- index++;
-
- uv[index] = LLVector2(uv_outer_rect.mRight, uv_outer_rect.mTop);
- pos[index] = LLVector3(draw_outer_rect.mRight, draw_outer_rect.mTop, 0.f);
- index++;
-
- uv[index] = LLVector2(uv_center_rect.mRight, uv_outer_rect.mTop);
- pos[index] = LLVector3(draw_center_rect.mRight, draw_outer_rect.mTop, 0.f);
- index++;
-
- gGL.vertexBatchPreTransformed(pos, uv, NUM_VERTICES);
- }
- gGL.end();
- }
-
- if (solid_color)
- {
- gUIProgram.bind();
- }
+ stop_glerror();
+
+ if (NULL == image)
+ {
+ LL_WARNS() << "image == NULL; aborting function" << LL_ENDL;
+ return;
+ }
+
+ if (solid_color)
+ {
+ gSolidColorProgram.bind();
+ }
+
+ if (center_rect.mLeft == 0.f
+ && center_rect.mRight == 1.f
+ && center_rect.mBottom == 0.f
+ && center_rect.mTop == 1.f)
+ {
+ gl_draw_scaled_image(x, y, width, height, image, color, uv_outer_rect);
+ }
+ else
+ {
+ // add in offset of current image to current UI translation
+ const LLVector3 ui_scale = gGL.getUIScale();
+ const LLVector3 ui_translation = (gGL.getUITranslation() + LLVector3(x, y, 0.f)).scaledVec(ui_scale);
+
+ F32 uv_width = uv_outer_rect.getWidth();
+ F32 uv_height = uv_outer_rect.getHeight();
+
+ // shrink scaling region to be proportional to clipped image region
+ LLRectf uv_center_rect( uv_outer_rect.mLeft + (center_rect.mLeft * uv_width),
+ uv_outer_rect.mBottom + (center_rect.mTop * uv_height),
+ uv_outer_rect.mLeft + (center_rect.mRight * uv_width),
+ uv_outer_rect.mBottom + (center_rect.mBottom * uv_height));
+
+ F32 image_width = image->getWidth(0);
+ F32 image_height = image->getHeight(0);
+
+ S32 image_natural_width = ll_round(image_width * uv_width);
+ S32 image_natural_height = ll_round(image_height * uv_height);
+
+ LLRectf draw_center_rect( uv_center_rect.mLeft * image_width,
+ uv_center_rect.mTop * image_height,
+ uv_center_rect.mRight * image_width,
+ uv_center_rect.mBottom * image_height);
+
+ if (scale_inner)
+ {
+ // scale center region of image to drawn region
+ draw_center_rect.mRight += width - image_natural_width;
+ draw_center_rect.mTop += height - image_natural_height;
+
+ const F32 border_shrink_width = llmax(0.f, draw_center_rect.mLeft - draw_center_rect.mRight);
+ const F32 border_shrink_height = llmax(0.f, draw_center_rect.mBottom - draw_center_rect.mTop);
+
+ const F32 shrink_width_ratio = center_rect.getWidth() == 1.f ? 0.f : border_shrink_width / ((F32)image_natural_width * (1.f - center_rect.getWidth()));
+ const F32 shrink_height_ratio = center_rect.getHeight() == 1.f ? 0.f : border_shrink_height / ((F32)image_natural_height * (1.f - center_rect.getHeight()));
+
+ const F32 border_shrink_scale = 1.f - llmax(shrink_width_ratio, shrink_height_ratio);
+ draw_center_rect.mLeft *= border_shrink_scale;
+ draw_center_rect.mTop = lerp((F32)height, (F32)draw_center_rect.mTop, border_shrink_scale);
+ draw_center_rect.mRight = lerp((F32)width, (F32)draw_center_rect.mRight, border_shrink_scale);
+ draw_center_rect.mBottom *= border_shrink_scale;
+ }
+ else
+ {
+ // keep center region of image at fixed scale, but in same relative position
+ F32 scale_factor = llmin((F32)width / draw_center_rect.getWidth(), (F32)height / draw_center_rect.getHeight(), 1.f);
+ F32 scaled_width = draw_center_rect.getWidth() * scale_factor;
+ F32 scaled_height = draw_center_rect.getHeight() * scale_factor;
+ draw_center_rect.setCenterAndSize(uv_center_rect.getCenterX() * width, uv_center_rect.getCenterY() * height, scaled_width, scaled_height);
+ }
+
+ draw_center_rect.mLeft = ll_round(ui_translation.mV[VX] + (F32)draw_center_rect.mLeft * ui_scale.mV[VX]);
+ draw_center_rect.mTop = ll_round(ui_translation.mV[VY] + (F32)draw_center_rect.mTop * ui_scale.mV[VY]);
+ draw_center_rect.mRight = ll_round(ui_translation.mV[VX] + (F32)draw_center_rect.mRight * ui_scale.mV[VX]);
+ draw_center_rect.mBottom = ll_round(ui_translation.mV[VY] + (F32)draw_center_rect.mBottom * ui_scale.mV[VY]);
+
+ LLRectf draw_outer_rect(ui_translation.mV[VX],
+ ui_translation.mV[VY] + height * ui_scale.mV[VY],
+ ui_translation.mV[VX] + width * ui_scale.mV[VX],
+ ui_translation.mV[VY]);
+
+ LLGLSUIDefault gls_ui;
+
+ gGL.getTexUnit(0)->bind(image, true);
+
+ gGL.color4fv(color.mV);
+
+ const S32 NUM_VERTICES = 9 * 4; // 9 quads
+ LLVector2 uv[NUM_VERTICES];
+ LLVector3 pos[NUM_VERTICES];
+
+ S32 index = 0;
+
+ gGL.begin(LLRender::QUADS);
+ {
+ // draw bottom left
+ uv[index] = LLVector2(uv_outer_rect.mLeft, uv_outer_rect.mBottom);
+ pos[index] = LLVector3(draw_outer_rect.mLeft, draw_outer_rect.mBottom, 0.f);
+ index++;
+
+ uv[index] = LLVector2(uv_center_rect.mLeft, uv_outer_rect.mBottom);
+ pos[index] = LLVector3(draw_center_rect.mLeft, draw_outer_rect.mBottom, 0.f);
+ index++;
+
+ uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mBottom);
+ pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mBottom, 0.f);
+ index++;
+
+ uv[index] = LLVector2(uv_outer_rect.mLeft, uv_center_rect.mBottom);
+ pos[index] = LLVector3(draw_outer_rect.mLeft, draw_center_rect.mBottom, 0.f);
+ index++;
+
+ // draw bottom middle
+ uv[index] = LLVector2(uv_center_rect.mLeft, uv_outer_rect.mBottom);
+ pos[index] = LLVector3(draw_center_rect.mLeft, draw_outer_rect.mBottom, 0.f);
+ index++;
+
+ uv[index] = LLVector2(uv_center_rect.mRight, uv_outer_rect.mBottom);
+ pos[index] = LLVector3(draw_center_rect.mRight, draw_outer_rect.mBottom, 0.f);
+ index++;
+
+ uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mBottom);
+ pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mBottom, 0.f);
+ index++;
+
+ uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mBottom);
+ pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mBottom, 0.f);
+ index++;
+
+ // draw bottom right
+ uv[index] = LLVector2(uv_center_rect.mRight, uv_outer_rect.mBottom);
+ pos[index] = LLVector3(draw_center_rect.mRight, draw_outer_rect.mBottom, 0.f);
+ index++;
+
+ uv[index] = LLVector2(uv_outer_rect.mRight, uv_outer_rect.mBottom);
+ pos[index] = LLVector3(draw_outer_rect.mRight, draw_outer_rect.mBottom, 0.f);
+ index++;
+
+ uv[index] = LLVector2(uv_outer_rect.mRight, uv_center_rect.mBottom);
+ pos[index] = LLVector3(draw_outer_rect.mRight, draw_center_rect.mBottom, 0.f);
+ index++;
+
+ uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mBottom);
+ pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mBottom, 0.f);
+ index++;
+
+ // draw left
+ uv[index] = LLVector2(uv_outer_rect.mLeft, uv_center_rect.mBottom);
+ pos[index] = LLVector3(draw_outer_rect.mLeft, draw_center_rect.mBottom, 0.f);
+ index++;
+
+ uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mBottom);
+ pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mBottom, 0.f);
+ index++;
+
+ uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mTop);
+ pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mTop, 0.f);
+ index++;
+
+ uv[index] = LLVector2(uv_outer_rect.mLeft, uv_center_rect.mTop);
+ pos[index] = LLVector3(draw_outer_rect.mLeft, draw_center_rect.mTop, 0.f);
+ index++;
+
+ // draw middle
+ uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mBottom);
+ pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mBottom, 0.f);
+ index++;
+
+ uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mBottom);
+ pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mBottom, 0.f);
+ index++;
+
+ uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mTop);
+ pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mTop, 0.f);
+ index++;
+
+ uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mTop);
+ pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mTop, 0.f);
+ index++;
+
+ // draw right
+ uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mBottom);
+ pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mBottom, 0.f);
+ index++;
+
+ uv[index] = LLVector2(uv_outer_rect.mRight, uv_center_rect.mBottom);
+ pos[index] = LLVector3(draw_outer_rect.mRight, draw_center_rect.mBottom, 0.f);
+ index++;
+
+ uv[index] = LLVector2(uv_outer_rect.mRight, uv_center_rect.mTop);
+ pos[index] = LLVector3(draw_outer_rect.mRight, draw_center_rect.mTop, 0.f);
+ index++;
+
+ uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mTop);
+ pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mTop, 0.f);
+ index++;
+
+ // draw top left
+ uv[index] = LLVector2(uv_outer_rect.mLeft, uv_center_rect.mTop);
+ pos[index] = LLVector3(draw_outer_rect.mLeft, draw_center_rect.mTop, 0.f);
+ index++;
+
+ uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mTop);
+ pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mTop, 0.f);
+ index++;
+
+ uv[index] = LLVector2(uv_center_rect.mLeft, uv_outer_rect.mTop);
+ pos[index] = LLVector3(draw_center_rect.mLeft, draw_outer_rect.mTop, 0.f);
+ index++;
+
+ uv[index] = LLVector2(uv_outer_rect.mLeft, uv_outer_rect.mTop);
+ pos[index] = LLVector3(draw_outer_rect.mLeft, draw_outer_rect.mTop, 0.f);
+ index++;
+
+ // draw top middle
+ uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mTop);
+ pos[index] = LLVector3(draw_center_rect.mLeft, draw_center_rect.mTop, 0.f);
+ index++;
+
+ uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mTop);
+ pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mTop, 0.f);
+ index++;
+
+ uv[index] = LLVector2(uv_center_rect.mRight, uv_outer_rect.mTop);
+ pos[index] = LLVector3(draw_center_rect.mRight, draw_outer_rect.mTop, 0.f);
+ index++;
+
+ uv[index] = LLVector2(uv_center_rect.mLeft, uv_outer_rect.mTop);
+ pos[index] = LLVector3(draw_center_rect.mLeft, draw_outer_rect.mTop, 0.f);
+ index++;
+
+ // draw top right
+ uv[index] = LLVector2(uv_center_rect.mRight, uv_center_rect.mTop);
+ pos[index] = LLVector3(draw_center_rect.mRight, draw_center_rect.mTop, 0.f);
+ index++;
+
+ uv[index] = LLVector2(uv_outer_rect.mRight, uv_center_rect.mTop);
+ pos[index] = LLVector3(draw_outer_rect.mRight, draw_center_rect.mTop, 0.f);
+ index++;
+
+ uv[index] = LLVector2(uv_outer_rect.mRight, uv_outer_rect.mTop);
+ pos[index] = LLVector3(draw_outer_rect.mRight, draw_outer_rect.mTop, 0.f);
+ index++;
+
+ uv[index] = LLVector2(uv_center_rect.mRight, uv_outer_rect.mTop);
+ pos[index] = LLVector3(draw_center_rect.mRight, draw_outer_rect.mTop, 0.f);
+ index++;
+
+ gGL.vertexBatchPreTransformed(pos, uv, NUM_VERTICES);
+ }
+ gGL.end();
+ }
+
+ if (solid_color)
+ {
+ gUIProgram.bind();
+ }
}
void gl_draw_rotated_image(S32 x, S32 y, F32 degrees, LLTexture* image, const LLColor4& color, const LLRectf& uv_rect)
{
- gl_draw_scaled_rotated_image( x, y, image->getWidth(0), image->getHeight(0), degrees, image, color, uv_rect );
+ gl_draw_scaled_rotated_image( x, y, image->getWidth(0), image->getHeight(0), degrees, image, color, uv_rect );
}
void gl_draw_scaled_rotated_image(S32 x, S32 y, S32 width, S32 height, F32 degrees, LLTexture* image, const LLColor4& color, const LLRectf& uv_rect, LLRenderTarget* target)
{
- if (!image && !target)
- {
- LL_WARNS() << "image == NULL; aborting function" << LL_ENDL;
- return;
- }
-
- LLGLSUIDefault gls_ui;
-
- if(image != NULL)
- {
- gGL.getTexUnit(0)->bind(image, true);
- }
- else
- {
- gGL.getTexUnit(0)->bind(target);
- }
-
- gGL.color4fv(color.mV);
-
- if (degrees == 0.f)
- {
- const S32 NUM_VERTICES = 4; // 9 quads
- LLVector2 uv[NUM_VERTICES];
- LLVector3 pos[NUM_VERTICES];
-
- gGL.begin(LLRender::QUADS);
- {
- LLVector3 ui_scale = gGL.getUIScale();
- LLVector3 ui_translation = gGL.getUITranslation();
- ui_translation.mV[VX] += x;
- ui_translation.mV[VY] += y;
- ui_translation.scaleVec(ui_scale);
- S32 index = 0;
- S32 scaled_width = ll_round(width * ui_scale.mV[VX]);
- S32 scaled_height = ll_round(height * ui_scale.mV[VY]);
-
- uv[index] = LLVector2(uv_rect.mRight, uv_rect.mTop);
- pos[index] = LLVector3(ui_translation.mV[VX] + scaled_width, ui_translation.mV[VY] + scaled_height, 0.f);
- index++;
-
- uv[index] = LLVector2(uv_rect.mLeft, uv_rect.mTop);
- pos[index] = LLVector3(ui_translation.mV[VX], ui_translation.mV[VY] + scaled_height, 0.f);
- index++;
-
- uv[index] = LLVector2(uv_rect.mLeft, uv_rect.mBottom);
- pos[index] = LLVector3(ui_translation.mV[VX], ui_translation.mV[VY], 0.f);
- index++;
-
- uv[index] = LLVector2(uv_rect.mRight, uv_rect.mBottom);
- pos[index] = LLVector3(ui_translation.mV[VX] + scaled_width, ui_translation.mV[VY], 0.f);
- index++;
-
- gGL.vertexBatchPreTransformed(pos, uv, NUM_VERTICES);
- }
- gGL.end();
- }
- else
- {
- gGL.pushUIMatrix();
- gGL.translateUI((F32)x, (F32)y, 0.f);
-
- F32 offset_x = F32(width/2);
- F32 offset_y = F32(height/2);
-
- gGL.translateUI(offset_x, offset_y, 0.f);
-
- LLMatrix3 quat(0.f, 0.f, degrees*DEG_TO_RAD);
-
- if(image != NULL)
- {
- gGL.getTexUnit(0)->bind(image, true);
- }
- else
- {
- gGL.getTexUnit(0)->bind(target);
- }
-
- gGL.color4fv(color.mV);
-
- gGL.begin(LLRender::QUADS);
- {
- LLVector3 v;
-
- v = LLVector3(offset_x, offset_y, 0.f) * quat;
- gGL.texCoord2f(uv_rect.mRight, uv_rect.mTop);
- gGL.vertex2f(v.mV[0], v.mV[1] );
-
- v = LLVector3(-offset_x, offset_y, 0.f) * quat;
- gGL.texCoord2f(uv_rect.mLeft, uv_rect.mTop);
- gGL.vertex2f(v.mV[0], v.mV[1] );
-
- v = LLVector3(-offset_x, -offset_y, 0.f) * quat;
- gGL.texCoord2f(uv_rect.mLeft, uv_rect.mBottom);
- gGL.vertex2f(v.mV[0], v.mV[1] );
-
- v = LLVector3(offset_x, -offset_y, 0.f) * quat;
- gGL.texCoord2f(uv_rect.mRight, uv_rect.mBottom);
- gGL.vertex2f(v.mV[0], v.mV[1] );
- }
- gGL.end();
- gGL.popUIMatrix();
- }
+ if (!image && !target)
+ {
+ LL_WARNS() << "image == NULL; aborting function" << LL_ENDL;
+ return;
+ }
+
+ LLGLSUIDefault gls_ui;
+
+ if(image != NULL)
+ {
+ gGL.getTexUnit(0)->bind(image, true);
+ }
+ else
+ {
+ gGL.getTexUnit(0)->bind(target);
+ }
+
+ gGL.color4fv(color.mV);
+
+ if (degrees == 0.f)
+ {
+ const S32 NUM_VERTICES = 4; // 9 quads
+ LLVector2 uv[NUM_VERTICES];
+ LLVector3 pos[NUM_VERTICES];
+
+ gGL.begin(LLRender::QUADS);
+ {
+ LLVector3 ui_scale = gGL.getUIScale();
+ LLVector3 ui_translation = gGL.getUITranslation();
+ ui_translation.mV[VX] += x;
+ ui_translation.mV[VY] += y;
+ ui_translation.scaleVec(ui_scale);
+ S32 index = 0;
+ S32 scaled_width = ll_round(width * ui_scale.mV[VX]);
+ S32 scaled_height = ll_round(height * ui_scale.mV[VY]);
+
+ uv[index] = LLVector2(uv_rect.mRight, uv_rect.mTop);
+ pos[index] = LLVector3(ui_translation.mV[VX] + scaled_width, ui_translation.mV[VY] + scaled_height, 0.f);
+ index++;
+
+ uv[index] = LLVector2(uv_rect.mLeft, uv_rect.mTop);
+ pos[index] = LLVector3(ui_translation.mV[VX], ui_translation.mV[VY] + scaled_height, 0.f);
+ index++;
+
+ uv[index] = LLVector2(uv_rect.mLeft, uv_rect.mBottom);
+ pos[index] = LLVector3(ui_translation.mV[VX], ui_translation.mV[VY], 0.f);
+ index++;
+
+ uv[index] = LLVector2(uv_rect.mRight, uv_rect.mBottom);
+ pos[index] = LLVector3(ui_translation.mV[VX] + scaled_width, ui_translation.mV[VY], 0.f);
+ index++;
+
+ gGL.vertexBatchPreTransformed(pos, uv, NUM_VERTICES);
+ }
+ gGL.end();
+ }
+ else
+ {
+ gGL.pushUIMatrix();
+ gGL.translateUI((F32)x, (F32)y, 0.f);
+
+ F32 offset_x = F32(width/2);
+ F32 offset_y = F32(height/2);
+
+ gGL.translateUI(offset_x, offset_y, 0.f);
+
+ LLMatrix3 quat(0.f, 0.f, degrees*DEG_TO_RAD);
+
+ if(image != NULL)
+ {
+ gGL.getTexUnit(0)->bind(image, true);
+ }
+ else
+ {
+ gGL.getTexUnit(0)->bind(target);
+ }
+
+ gGL.color4fv(color.mV);
+
+ gGL.begin(LLRender::QUADS);
+ {
+ LLVector3 v;
+
+ v = LLVector3(offset_x, offset_y, 0.f) * quat;
+ gGL.texCoord2f(uv_rect.mRight, uv_rect.mTop);
+ gGL.vertex2f(v.mV[0], v.mV[1] );
+
+ v = LLVector3(-offset_x, offset_y, 0.f) * quat;
+ gGL.texCoord2f(uv_rect.mLeft, uv_rect.mTop);
+ gGL.vertex2f(v.mV[0], v.mV[1] );
+
+ v = LLVector3(-offset_x, -offset_y, 0.f) * quat;
+ gGL.texCoord2f(uv_rect.mLeft, uv_rect.mBottom);
+ gGL.vertex2f(v.mV[0], v.mV[1] );
+
+ v = LLVector3(offset_x, -offset_y, 0.f) * quat;
+ gGL.texCoord2f(uv_rect.mRight, uv_rect.mBottom);
+ gGL.vertex2f(v.mV[0], v.mV[1] );
+ }
+ gGL.end();
+ gGL.popUIMatrix();
+ }
}
void gl_line_3d( const LLVector3& start, const LLVector3& end, const LLColor4& color)
{
- gGL.color4f(color.mV[VRED], color.mV[VGREEN], color.mV[VBLUE], color.mV[VALPHA]);
+ gGL.color4f(color.mV[VRED], color.mV[VGREEN], color.mV[VBLUE], color.mV[VALPHA]);
- gGL.flush();
- glLineWidth(2.5f);
+ gGL.flush();
+ glLineWidth(2.5f);
- gGL.begin(LLRender::LINES);
- {
- gGL.vertex3fv( start.mV );
- gGL.vertex3fv( end.mV );
- }
- gGL.end();
+ gGL.begin(LLRender::LINES);
+ {
+ gGL.vertex3fv( start.mV );
+ gGL.vertex3fv( end.mV );
+ }
+ gGL.end();
- LLRender2D::getInstance()->setLineWidth(1.f);
+ LLRender2D::getInstance()->setLineWidth(1.f);
}
void gl_arc_2d(F32 center_x, F32 center_y, F32 radius, S32 steps, BOOL filled, F32 start_angle, F32 end_angle)
{
- if (end_angle < start_angle)
- {
- end_angle += F_TWO_PI;
- }
-
- gGL.pushUIMatrix();
- {
- gGL.translateUI(center_x, center_y, 0.f);
-
- // Inexact, but reasonably fast.
- F32 delta = (end_angle - start_angle) / steps;
- F32 sin_delta = sin( delta );
- F32 cos_delta = cos( delta );
- F32 x = cosf(start_angle) * radius;
- F32 y = sinf(start_angle) * radius;
-
- if (filled)
- {
- gGL.begin(LLRender::TRIANGLE_FAN);
- gGL.vertex2f(0.f, 0.f);
- // make sure circle is complete
- steps += 1;
- }
- else
- {
- gGL.begin(LLRender::LINE_STRIP);
- }
-
- while( steps-- )
- {
- // Successive rotations
- gGL.vertex2f( x, y );
- F32 x_new = x * cos_delta - y * sin_delta;
- y = x * sin_delta + y * cos_delta;
- x = x_new;
- }
- gGL.end();
- }
- gGL.popUIMatrix();
+ if (end_angle < start_angle)
+ {
+ end_angle += F_TWO_PI;
+ }
+
+ gGL.pushUIMatrix();
+ {
+ gGL.translateUI(center_x, center_y, 0.f);
+
+ // Inexact, but reasonably fast.
+ F32 delta = (end_angle - start_angle) / steps;
+ F32 sin_delta = sin( delta );
+ F32 cos_delta = cos( delta );
+ F32 x = cosf(start_angle) * radius;
+ F32 y = sinf(start_angle) * radius;
+
+ if (filled)
+ {
+ gGL.begin(LLRender::TRIANGLE_FAN);
+ gGL.vertex2f(0.f, 0.f);
+ // make sure circle is complete
+ steps += 1;
+ }
+ else
+ {
+ gGL.begin(LLRender::LINE_STRIP);
+ }
+
+ while( steps-- )
+ {
+ // Successive rotations
+ gGL.vertex2f( x, y );
+ F32 x_new = x * cos_delta - y * sin_delta;
+ y = x * sin_delta + y * cos_delta;
+ x = x_new;
+ }
+ gGL.end();
+ }
+ gGL.popUIMatrix();
}
void gl_circle_2d(F32 center_x, F32 center_y, F32 radius, S32 steps, BOOL filled)
{
- gGL.pushUIMatrix();
- {
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
- gGL.translateUI(center_x, center_y, 0.f);
-
- // Inexact, but reasonably fast.
- F32 delta = F_TWO_PI / steps;
- F32 sin_delta = sin( delta );
- F32 cos_delta = cos( delta );
- F32 x = radius;
- F32 y = 0.f;
-
- if (filled)
- {
- gGL.begin(LLRender::TRIANGLE_FAN);
- gGL.vertex2f(0.f, 0.f);
- // make sure circle is complete
- steps += 1;
- }
- else
- {
- gGL.begin(LLRender::LINE_LOOP);
- }
-
- while( steps-- )
- {
- // Successive rotations
- gGL.vertex2f( x, y );
- F32 x_new = x * cos_delta - y * sin_delta;
- y = x * sin_delta + y * cos_delta;
- x = x_new;
- }
- gGL.end();
- }
- gGL.popUIMatrix();
+ gGL.pushUIMatrix();
+ {
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+ gGL.translateUI(center_x, center_y, 0.f);
+
+ // Inexact, but reasonably fast.
+ F32 delta = F_TWO_PI / steps;
+ F32 sin_delta = sin( delta );
+ F32 cos_delta = cos( delta );
+ F32 x = radius;
+ F32 y = 0.f;
+
+ if (filled)
+ {
+ gGL.begin(LLRender::TRIANGLE_FAN);
+ gGL.vertex2f(0.f, 0.f);
+ // make sure circle is complete
+ steps += 1;
+ }
+ else
+ {
+ gGL.begin(LLRender::LINE_LOOP);
+ }
+
+ while( steps-- )
+ {
+ // Successive rotations
+ gGL.vertex2f( x, y );
+ F32 x_new = x * cos_delta - y * sin_delta;
+ y = x * sin_delta + y * cos_delta;
+ x = x_new;
+ }
+ gGL.end();
+ }
+ gGL.popUIMatrix();
}
// Renders a ring with sides (tube shape)
void gl_deep_circle( F32 radius, F32 depth, S32 steps )
{
- F32 x = radius;
- F32 y = 0.f;
- F32 angle_delta = F_TWO_PI / (F32)steps;
- gGL.begin( LLRender::TRIANGLE_STRIP );
- {
- S32 step = steps + 1; // An extra step to close the circle.
- while( step-- )
- {
- gGL.vertex3f( x, y, depth );
- gGL.vertex3f( x, y, 0.f );
-
- F32 x_new = x * cosf(angle_delta) - y * sinf(angle_delta);
- y = x * sinf(angle_delta) + y * cosf(angle_delta);
- x = x_new;
- }
- }
- gGL.end();
+ F32 x = radius;
+ F32 y = 0.f;
+ F32 angle_delta = F_TWO_PI / (F32)steps;
+ gGL.begin( LLRender::TRIANGLE_STRIP );
+ {
+ S32 step = steps + 1; // An extra step to close the circle.
+ while( step-- )
+ {
+ gGL.vertex3f( x, y, depth );
+ gGL.vertex3f( x, y, 0.f );
+
+ F32 x_new = x * cosf(angle_delta) - y * sinf(angle_delta);
+ y = x * sinf(angle_delta) + y * cosf(angle_delta);
+ x = x_new;
+ }
+ }
+ gGL.end();
}
void gl_ring( F32 radius, F32 width, const LLColor4& center_color, const LLColor4& side_color, S32 steps, BOOL render_center )
{
- gGL.pushUIMatrix();
- {
- gGL.translateUI(0.f, 0.f, -width / 2);
- if( render_center )
- {
- gGL.color4fv(center_color.mV);
- gGL.diffuseColor4fv(center_color.mV);
- gl_deep_circle( radius, width, steps );
- }
- else
- {
- gGL.diffuseColor4fv(side_color.mV);
- gl_washer_2d(radius, radius - width, steps, side_color, side_color);
- gGL.translateUI(0.f, 0.f, width);
- gl_washer_2d(radius - width, radius, steps, side_color, side_color);
- }
- }
- gGL.popUIMatrix();
+ gGL.pushUIMatrix();
+ {
+ gGL.translateUI(0.f, 0.f, -width / 2);
+ if( render_center )
+ {
+ gGL.color4fv(center_color.mV);
+ gGL.diffuseColor4fv(center_color.mV);
+ gl_deep_circle( radius, width, steps );
+ }
+ else
+ {
+ gGL.diffuseColor4fv(side_color.mV);
+ gl_washer_2d(radius, radius - width, steps, side_color, side_color);
+ gGL.translateUI(0.f, 0.f, width);
+ gl_washer_2d(radius - width, radius, steps, side_color, side_color);
+ }
+ }
+ gGL.popUIMatrix();
}
// Draw gray and white checkerboard with black border
void gl_rect_2d_checkerboard(const LLRect& rect, GLfloat alpha)
{
- //polygon stipple is deprecated, use "Checker" texture
- LLPointer<LLUIImage> img = LLRender2D::getInstance()->getUIImage("Checker");
- gGL.getTexUnit(0)->bind(img->getImage());
- gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_WRAP);
- gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
-
- LLColor4 color(1.f, 1.f, 1.f, alpha);
- LLRectf uv_rect(0, 0, rect.getWidth()/32.f, rect.getHeight()/32.f);
-
- gl_draw_scaled_image(rect.mLeft, rect.mBottom, rect.getWidth(), rect.getHeight(), img->getImage(), color, uv_rect);
-
- gGL.flush();
+ //polygon stipple is deprecated, use "Checker" texture
+ LLPointer<LLUIImage> img = LLRender2D::getInstance()->getUIImage("Checker");
+ gGL.getTexUnit(0)->bind(img->getImage());
+ gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_WRAP);
+ gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
+
+ LLColor4 color(1.f, 1.f, 1.f, alpha);
+ LLRectf uv_rect(0, 0, rect.getWidth()/32.f, rect.getHeight()/32.f);
+
+ gl_draw_scaled_image(rect.mLeft, rect.mBottom, rect.getWidth(), rect.getHeight(), img->getImage(), color, uv_rect);
+
+ gGL.flush();
}
@@ -877,640 +877,640 @@ void gl_rect_2d_checkerboard(const LLRect& rect, GLfloat alpha)
// a doughnut or washer.
void gl_washer_2d(F32 outer_radius, F32 inner_radius, S32 steps, const LLColor4& inner_color, const LLColor4& outer_color)
{
- const F32 DELTA = F_TWO_PI / steps;
- const F32 SIN_DELTA = sin( DELTA );
- const F32 COS_DELTA = cos( DELTA );
-
- F32 x1 = outer_radius;
- F32 y1 = 0.f;
- F32 x2 = inner_radius;
- F32 y2 = 0.f;
-
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-
- gGL.begin( LLRender::TRIANGLE_STRIP );
- {
- steps += 1; // An extra step to close the circle.
- while( steps-- )
- {
- gGL.color4fv(outer_color.mV);
- gGL.vertex2f( x1, y1 );
- gGL.color4fv(inner_color.mV);
- gGL.vertex2f( x2, y2 );
-
- F32 x1_new = x1 * COS_DELTA - y1 * SIN_DELTA;
- y1 = x1 * SIN_DELTA + y1 * COS_DELTA;
- x1 = x1_new;
-
- F32 x2_new = x2 * COS_DELTA - y2 * SIN_DELTA;
- y2 = x2 * SIN_DELTA + y2 * COS_DELTA;
- x2 = x2_new;
- }
- }
- gGL.end();
+ const F32 DELTA = F_TWO_PI / steps;
+ const F32 SIN_DELTA = sin( DELTA );
+ const F32 COS_DELTA = cos( DELTA );
+
+ F32 x1 = outer_radius;
+ F32 y1 = 0.f;
+ F32 x2 = inner_radius;
+ F32 y2 = 0.f;
+
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+
+ gGL.begin( LLRender::TRIANGLE_STRIP );
+ {
+ steps += 1; // An extra step to close the circle.
+ while( steps-- )
+ {
+ gGL.color4fv(outer_color.mV);
+ gGL.vertex2f( x1, y1 );
+ gGL.color4fv(inner_color.mV);
+ gGL.vertex2f( x2, y2 );
+
+ F32 x1_new = x1 * COS_DELTA - y1 * SIN_DELTA;
+ y1 = x1 * SIN_DELTA + y1 * COS_DELTA;
+ x1 = x1_new;
+
+ F32 x2_new = x2 * COS_DELTA - y2 * SIN_DELTA;
+ y2 = x2 * SIN_DELTA + y2 * COS_DELTA;
+ x2 = x2_new;
+ }
+ }
+ gGL.end();
}
// Draws the area between two concentric circles, like
// a doughnut or washer.
void gl_washer_segment_2d(F32 outer_radius, F32 inner_radius, F32 start_radians, F32 end_radians, S32 steps, const LLColor4& inner_color, const LLColor4& outer_color)
{
- const F32 DELTA = (end_radians - start_radians) / steps;
- const F32 SIN_DELTA = sin( DELTA );
- const F32 COS_DELTA = cos( DELTA );
-
- F32 x1 = outer_radius * cos( start_radians );
- F32 y1 = outer_radius * sin( start_radians );
- F32 x2 = inner_radius * cos( start_radians );
- F32 y2 = inner_radius * sin( start_radians );
-
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
- gGL.begin( LLRender::TRIANGLE_STRIP );
- {
- steps += 1; // An extra step to close the circle.
- while( steps-- )
- {
- gGL.color4fv(outer_color.mV);
- gGL.vertex2f( x1, y1 );
- gGL.color4fv(inner_color.mV);
- gGL.vertex2f( x2, y2 );
-
- F32 x1_new = x1 * COS_DELTA - y1 * SIN_DELTA;
- y1 = x1 * SIN_DELTA + y1 * COS_DELTA;
- x1 = x1_new;
-
- F32 x2_new = x2 * COS_DELTA - y2 * SIN_DELTA;
- y2 = x2 * SIN_DELTA + y2 * COS_DELTA;
- x2 = x2_new;
- }
- }
- gGL.end();
+ const F32 DELTA = (end_radians - start_radians) / steps;
+ const F32 SIN_DELTA = sin( DELTA );
+ const F32 COS_DELTA = cos( DELTA );
+
+ F32 x1 = outer_radius * cos( start_radians );
+ F32 y1 = outer_radius * sin( start_radians );
+ F32 x2 = inner_radius * cos( start_radians );
+ F32 y2 = inner_radius * sin( start_radians );
+
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+ gGL.begin( LLRender::TRIANGLE_STRIP );
+ {
+ steps += 1; // An extra step to close the circle.
+ while( steps-- )
+ {
+ gGL.color4fv(outer_color.mV);
+ gGL.vertex2f( x1, y1 );
+ gGL.color4fv(inner_color.mV);
+ gGL.vertex2f( x2, y2 );
+
+ F32 x1_new = x1 * COS_DELTA - y1 * SIN_DELTA;
+ y1 = x1 * SIN_DELTA + y1 * COS_DELTA;
+ x1 = x1_new;
+
+ F32 x2_new = x2 * COS_DELTA - y2 * SIN_DELTA;
+ y2 = x2 * SIN_DELTA + y2 * COS_DELTA;
+ x2 = x2_new;
+ }
+ }
+ gGL.end();
}
void gl_rect_2d_simple_tex( S32 width, S32 height )
{
- gGL.begin( LLRender::QUADS );
+ gGL.begin( LLRender::QUADS );
- gGL.texCoord2f(1.f, 1.f);
- gGL.vertex2i(width, height);
+ gGL.texCoord2f(1.f, 1.f);
+ gGL.vertex2i(width, height);
- gGL.texCoord2f(0.f, 1.f);
- gGL.vertex2i(0, height);
+ gGL.texCoord2f(0.f, 1.f);
+ gGL.vertex2i(0, height);
- gGL.texCoord2f(0.f, 0.f);
- gGL.vertex2i(0, 0);
+ gGL.texCoord2f(0.f, 0.f);
+ gGL.vertex2i(0, 0);
- gGL.texCoord2f(1.f, 0.f);
- gGL.vertex2i(width, 0);
-
- gGL.end();
+ gGL.texCoord2f(1.f, 0.f);
+ gGL.vertex2i(width, 0);
+
+ gGL.end();
}
void gl_rect_2d_simple( S32 width, S32 height )
{
- gGL.begin( LLRender::QUADS );
- gGL.vertex2i(width, height);
- gGL.vertex2i(0, height);
- gGL.vertex2i(0, 0);
- gGL.vertex2i(width, 0);
- gGL.end();
+ gGL.begin( LLRender::QUADS );
+ gGL.vertex2i(width, height);
+ gGL.vertex2i(0, height);
+ gGL.vertex2i(0, 0);
+ gGL.vertex2i(width, 0);
+ gGL.end();
}
-void gl_segmented_rect_2d_tex(const S32 left,
- const S32 top,
- const S32 right,
- const S32 bottom,
- const S32 texture_width,
- const S32 texture_height,
- const S32 border_size,
- const U32 edges)
+void gl_segmented_rect_2d_tex(const S32 left,
+ const S32 top,
+ const S32 right,
+ const S32 bottom,
+ const S32 texture_width,
+ const S32 texture_height,
+ const S32 border_size,
+ const U32 edges)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_UI;
- S32 width = llabs(right - left);
- S32 height = llabs(top - bottom);
+ S32 width = llabs(right - left);
+ S32 height = llabs(top - bottom);
- gGL.pushUIMatrix();
+ gGL.pushUIMatrix();
- gGL.translateUI((F32)left, (F32)bottom, 0.f);
- LLVector2 border_uv_scale((F32)border_size / (F32)texture_width, (F32)border_size / (F32)texture_height);
+ gGL.translateUI((F32)left, (F32)bottom, 0.f);
+ LLVector2 border_uv_scale((F32)border_size / (F32)texture_width, (F32)border_size / (F32)texture_height);
- if (border_uv_scale.mV[VX] > 0.5f)
- {
- border_uv_scale *= 0.5f / border_uv_scale.mV[VX];
- }
- if (border_uv_scale.mV[VY] > 0.5f)
- {
- border_uv_scale *= 0.5f / border_uv_scale.mV[VY];
- }
+ if (border_uv_scale.mV[VX] > 0.5f)
+ {
+ border_uv_scale *= 0.5f / border_uv_scale.mV[VX];
+ }
+ if (border_uv_scale.mV[VY] > 0.5f)
+ {
+ border_uv_scale *= 0.5f / border_uv_scale.mV[VY];
+ }
- F32 border_scale = llmin((F32)border_size, (F32)width * 0.5f, (F32)height * 0.5f);
- LLVector2 border_width_left = ((edges & (~(U32)ROUNDED_RECT_RIGHT)) != 0) ? LLVector2(border_scale, 0.f) : LLVector2::zero;
- LLVector2 border_width_right = ((edges & (~(U32)ROUNDED_RECT_LEFT)) != 0) ? LLVector2(border_scale, 0.f) : LLVector2::zero;
- LLVector2 border_height_bottom = ((edges & (~(U32)ROUNDED_RECT_TOP)) != 0) ? LLVector2(0.f, border_scale) : LLVector2::zero;
- LLVector2 border_height_top = ((edges & (~(U32)ROUNDED_RECT_BOTTOM)) != 0) ? LLVector2(0.f, border_scale) : LLVector2::zero;
- LLVector2 width_vec((F32)width, 0.f);
- LLVector2 height_vec(0.f, (F32)height);
+ F32 border_scale = llmin((F32)border_size, (F32)width * 0.5f, (F32)height * 0.5f);
+ LLVector2 border_width_left = ((edges & (~(U32)ROUNDED_RECT_RIGHT)) != 0) ? LLVector2(border_scale, 0.f) : LLVector2::zero;
+ LLVector2 border_width_right = ((edges & (~(U32)ROUNDED_RECT_LEFT)) != 0) ? LLVector2(border_scale, 0.f) : LLVector2::zero;
+ LLVector2 border_height_bottom = ((edges & (~(U32)ROUNDED_RECT_TOP)) != 0) ? LLVector2(0.f, border_scale) : LLVector2::zero;
+ LLVector2 border_height_top = ((edges & (~(U32)ROUNDED_RECT_BOTTOM)) != 0) ? LLVector2(0.f, border_scale) : LLVector2::zero;
+ LLVector2 width_vec((F32)width, 0.f);
+ LLVector2 height_vec(0.f, (F32)height);
- gGL.begin(LLRender::QUADS);
- {
- // draw bottom left
- gGL.texCoord2f(0.f, 0.f);
- gGL.vertex2f(0.f, 0.f);
+ gGL.begin(LLRender::QUADS);
+ {
+ // draw bottom left
+ gGL.texCoord2f(0.f, 0.f);
+ gGL.vertex2f(0.f, 0.f);
- gGL.texCoord2f(border_uv_scale.mV[VX], 0.f);
- gGL.vertex2fv(border_width_left.mV);
+ gGL.texCoord2f(border_uv_scale.mV[VX], 0.f);
+ gGL.vertex2fv(border_width_left.mV);
- gGL.texCoord2f(border_uv_scale.mV[VX], border_uv_scale.mV[VY]);
- gGL.vertex2fv((border_width_left + border_height_bottom).mV);
+ gGL.texCoord2f(border_uv_scale.mV[VX], border_uv_scale.mV[VY]);
+ gGL.vertex2fv((border_width_left + border_height_bottom).mV);
- gGL.texCoord2f(0.f, border_uv_scale.mV[VY]);
- gGL.vertex2fv(border_height_bottom.mV);
+ gGL.texCoord2f(0.f, border_uv_scale.mV[VY]);
+ gGL.vertex2fv(border_height_bottom.mV);
- // draw bottom middle
- gGL.texCoord2f(border_uv_scale.mV[VX], 0.f);
- gGL.vertex2fv(border_width_left.mV);
+ // draw bottom middle
+ gGL.texCoord2f(border_uv_scale.mV[VX], 0.f);
+ gGL.vertex2fv(border_width_left.mV);
- gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 0.f);
- gGL.vertex2fv((width_vec - border_width_right).mV);
+ gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 0.f);
+ gGL.vertex2fv((width_vec - border_width_right).mV);
- gGL.texCoord2f(1.f - border_uv_scale.mV[VX], border_uv_scale.mV[VY]);
- gGL.vertex2fv((width_vec - border_width_right + border_height_bottom).mV);
+ gGL.texCoord2f(1.f - border_uv_scale.mV[VX], border_uv_scale.mV[VY]);
+ gGL.vertex2fv((width_vec - border_width_right + border_height_bottom).mV);
- gGL.texCoord2f(border_uv_scale.mV[VX], border_uv_scale.mV[VY]);
- gGL.vertex2fv((border_width_left + border_height_bottom).mV);
+ gGL.texCoord2f(border_uv_scale.mV[VX], border_uv_scale.mV[VY]);
+ gGL.vertex2fv((border_width_left + border_height_bottom).mV);
- // draw bottom right
- gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 0.f);
- gGL.vertex2fv((width_vec - border_width_right).mV);
+ // draw bottom right
+ gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 0.f);
+ gGL.vertex2fv((width_vec - border_width_right).mV);
- gGL.texCoord2f(1.f, 0.f);
- gGL.vertex2fv(width_vec.mV);
+ gGL.texCoord2f(1.f, 0.f);
+ gGL.vertex2fv(width_vec.mV);
- gGL.texCoord2f(1.f, border_uv_scale.mV[VY]);
- gGL.vertex2fv((width_vec + border_height_bottom).mV);
+ gGL.texCoord2f(1.f, border_uv_scale.mV[VY]);
+ gGL.vertex2fv((width_vec + border_height_bottom).mV);
- gGL.texCoord2f(1.f - border_uv_scale.mV[VX], border_uv_scale.mV[VY]);
- gGL.vertex2fv((width_vec - border_width_right + border_height_bottom).mV);
+ gGL.texCoord2f(1.f - border_uv_scale.mV[VX], border_uv_scale.mV[VY]);
+ gGL.vertex2fv((width_vec - border_width_right + border_height_bottom).mV);
- // draw left
- gGL.texCoord2f(0.f, border_uv_scale.mV[VY]);
- gGL.vertex2fv(border_height_bottom.mV);
+ // draw left
+ gGL.texCoord2f(0.f, border_uv_scale.mV[VY]);
+ gGL.vertex2fv(border_height_bottom.mV);
- gGL.texCoord2f(border_uv_scale.mV[VX], border_uv_scale.mV[VY]);
- gGL.vertex2fv((border_width_left + border_height_bottom).mV);
+ gGL.texCoord2f(border_uv_scale.mV[VX], border_uv_scale.mV[VY]);
+ gGL.vertex2fv((border_width_left + border_height_bottom).mV);
- gGL.texCoord2f(border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]);
- gGL.vertex2fv((border_width_left + height_vec - border_height_top).mV);
+ gGL.texCoord2f(border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]);
+ gGL.vertex2fv((border_width_left + height_vec - border_height_top).mV);
- gGL.texCoord2f(0.f, 1.f - border_uv_scale.mV[VY]);
- gGL.vertex2fv((height_vec - border_height_top).mV);
+ gGL.texCoord2f(0.f, 1.f - border_uv_scale.mV[VY]);
+ gGL.vertex2fv((height_vec - border_height_top).mV);
- // draw middle
- gGL.texCoord2f(border_uv_scale.mV[VX], border_uv_scale.mV[VY]);
- gGL.vertex2fv((border_width_left + border_height_bottom).mV);
+ // draw middle
+ gGL.texCoord2f(border_uv_scale.mV[VX], border_uv_scale.mV[VY]);
+ gGL.vertex2fv((border_width_left + border_height_bottom).mV);
- gGL.texCoord2f(1.f - border_uv_scale.mV[VX], border_uv_scale.mV[VY]);
- gGL.vertex2fv((width_vec - border_width_right + border_height_bottom).mV);
+ gGL.texCoord2f(1.f - border_uv_scale.mV[VX], border_uv_scale.mV[VY]);
+ gGL.vertex2fv((width_vec - border_width_right + border_height_bottom).mV);
- gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]);
- gGL.vertex2fv((width_vec - border_width_right + height_vec - border_height_top).mV);
+ gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]);
+ gGL.vertex2fv((width_vec - border_width_right + height_vec - border_height_top).mV);
- gGL.texCoord2f(border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]);
- gGL.vertex2fv((border_width_left + height_vec - border_height_top).mV);
+ gGL.texCoord2f(border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]);
+ gGL.vertex2fv((border_width_left + height_vec - border_height_top).mV);
- // draw right
- gGL.texCoord2f(1.f - border_uv_scale.mV[VX], border_uv_scale.mV[VY]);
- gGL.vertex2fv((width_vec - border_width_right + border_height_bottom).mV);
+ // draw right
+ gGL.texCoord2f(1.f - border_uv_scale.mV[VX], border_uv_scale.mV[VY]);
+ gGL.vertex2fv((width_vec - border_width_right + border_height_bottom).mV);
- gGL.texCoord2f(1.f, border_uv_scale.mV[VY]);
- gGL.vertex2fv((width_vec + border_height_bottom).mV);
+ gGL.texCoord2f(1.f, border_uv_scale.mV[VY]);
+ gGL.vertex2fv((width_vec + border_height_bottom).mV);
- gGL.texCoord2f(1.f, 1.f - border_uv_scale.mV[VY]);
- gGL.vertex2fv((width_vec + height_vec - border_height_top).mV);
+ gGL.texCoord2f(1.f, 1.f - border_uv_scale.mV[VY]);
+ gGL.vertex2fv((width_vec + height_vec - border_height_top).mV);
- gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]);
- gGL.vertex2fv((width_vec - border_width_right + height_vec - border_height_top).mV);
+ gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]);
+ gGL.vertex2fv((width_vec - border_width_right + height_vec - border_height_top).mV);
- // draw top left
- gGL.texCoord2f(0.f, 1.f - border_uv_scale.mV[VY]);
- gGL.vertex2fv((height_vec - border_height_top).mV);
+ // draw top left
+ gGL.texCoord2f(0.f, 1.f - border_uv_scale.mV[VY]);
+ gGL.vertex2fv((height_vec - border_height_top).mV);
- gGL.texCoord2f(border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]);
- gGL.vertex2fv((border_width_left + height_vec - border_height_top).mV);
+ gGL.texCoord2f(border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]);
+ gGL.vertex2fv((border_width_left + height_vec - border_height_top).mV);
- gGL.texCoord2f(border_uv_scale.mV[VX], 1.f);
- gGL.vertex2fv((border_width_left + height_vec).mV);
+ gGL.texCoord2f(border_uv_scale.mV[VX], 1.f);
+ gGL.vertex2fv((border_width_left + height_vec).mV);
- gGL.texCoord2f(0.f, 1.f);
- gGL.vertex2fv((height_vec).mV);
+ gGL.texCoord2f(0.f, 1.f);
+ gGL.vertex2fv((height_vec).mV);
- // draw top middle
- gGL.texCoord2f(border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]);
- gGL.vertex2fv((border_width_left + height_vec - border_height_top).mV);
+ // draw top middle
+ gGL.texCoord2f(border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]);
+ gGL.vertex2fv((border_width_left + height_vec - border_height_top).mV);
- gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]);
- gGL.vertex2fv((width_vec - border_width_right + height_vec - border_height_top).mV);
+ gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]);
+ gGL.vertex2fv((width_vec - border_width_right + height_vec - border_height_top).mV);
- gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f);
- gGL.vertex2fv((width_vec - border_width_right + height_vec).mV);
+ gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f);
+ gGL.vertex2fv((width_vec - border_width_right + height_vec).mV);
- gGL.texCoord2f(border_uv_scale.mV[VX], 1.f);
- gGL.vertex2fv((border_width_left + height_vec).mV);
+ gGL.texCoord2f(border_uv_scale.mV[VX], 1.f);
+ gGL.vertex2fv((border_width_left + height_vec).mV);
- // draw top right
- gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]);
- gGL.vertex2fv((width_vec - border_width_right + height_vec - border_height_top).mV);
+ // draw top right
+ gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]);
+ gGL.vertex2fv((width_vec - border_width_right + height_vec - border_height_top).mV);
- gGL.texCoord2f(1.f, 1.f - border_uv_scale.mV[VY]);
- gGL.vertex2fv((width_vec + height_vec - border_height_top).mV);
+ gGL.texCoord2f(1.f, 1.f - border_uv_scale.mV[VY]);
+ gGL.vertex2fv((width_vec + height_vec - border_height_top).mV);
- gGL.texCoord2f(1.f, 1.f);
- gGL.vertex2fv((width_vec + height_vec).mV);
+ gGL.texCoord2f(1.f, 1.f);
+ gGL.vertex2fv((width_vec + height_vec).mV);
- gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f);
- gGL.vertex2fv((width_vec - border_width_right + height_vec).mV);
- }
- gGL.end();
+ gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f);
+ gGL.vertex2fv((width_vec - border_width_right + height_vec).mV);
+ }
+ gGL.end();
- gGL.popUIMatrix();
+ gGL.popUIMatrix();
}
-void gl_segmented_rect_2d_fragment_tex(const LLRect& rect,
- const S32 texture_width,
- const S32 texture_height,
- const S32 border_size,
- const F32 start_fragment,
- const F32 end_fragment,
- const U32 edges)
+void gl_segmented_rect_2d_fragment_tex(const LLRect& rect,
+ const S32 texture_width,
+ const S32 texture_height,
+ const S32 border_size,
+ const F32 start_fragment,
+ const F32 end_fragment,
+ const U32 edges)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_UI;
- const S32 left = rect.mLeft;
- const S32 right = rect.mRight;
- const S32 top = rect.mTop;
- const S32 bottom = rect.mBottom;
- S32 width = llabs(right - left);
- S32 height = llabs(top - bottom);
-
- gGL.pushUIMatrix();
-
- gGL.translateUI((F32)left, (F32)bottom, 0.f);
- LLVector2 border_uv_scale((F32)border_size / (F32)texture_width, (F32)border_size / (F32)texture_height);
-
- if (border_uv_scale.mV[VX] > 0.5f)
- {
- border_uv_scale *= 0.5f / border_uv_scale.mV[VX];
- }
- if (border_uv_scale.mV[VY] > 0.5f)
- {
- border_uv_scale *= 0.5f / border_uv_scale.mV[VY];
- }
+ const S32 left = rect.mLeft;
+ const S32 right = rect.mRight;
+ const S32 top = rect.mTop;
+ const S32 bottom = rect.mBottom;
+ S32 width = llabs(right - left);
+ S32 height = llabs(top - bottom);
- F32 border_scale = llmin((F32)border_size, (F32)width * 0.5f, (F32)height * 0.5f);
- LLVector2 border_width_left = ((edges & (~(U32)ROUNDED_RECT_RIGHT)) != 0) ? LLVector2(border_scale, 0.f) : LLVector2::zero;
- LLVector2 border_width_right = ((edges & (~(U32)ROUNDED_RECT_LEFT)) != 0) ? LLVector2(border_scale, 0.f) : LLVector2::zero;
- LLVector2 border_height_bottom = ((edges & (~(U32)ROUNDED_RECT_TOP)) != 0) ? LLVector2(0.f, border_scale) : LLVector2::zero;
- LLVector2 border_height_top = ((edges & (~(U32)ROUNDED_RECT_BOTTOM)) != 0) ? LLVector2(0.f, border_scale) : LLVector2::zero;
- LLVector2 width_vec((F32)width, 0.f);
- LLVector2 height_vec(0.f, (F32)height);
+ gGL.pushUIMatrix();
- F32 middle_start = border_scale / (F32)width;
- F32 middle_end = 1.f - middle_start;
+ gGL.translateUI((F32)left, (F32)bottom, 0.f);
+ LLVector2 border_uv_scale((F32)border_size / (F32)texture_width, (F32)border_size / (F32)texture_height);
- F32 u_min;
- F32 u_max;
- LLVector2 x_min;
- LLVector2 x_max;
-
- gGL.begin(LLRender::QUADS);
- {
- if (start_fragment < middle_start)
- {
- u_min = (start_fragment / middle_start) * border_uv_scale.mV[VX];
- u_max = llmin(end_fragment / middle_start, 1.f) * border_uv_scale.mV[VX];
- x_min = (start_fragment / middle_start) * border_width_left;
- x_max = llmin(end_fragment / middle_start, 1.f) * border_width_left;
+ if (border_uv_scale.mV[VX] > 0.5f)
+ {
+ border_uv_scale *= 0.5f / border_uv_scale.mV[VX];
+ }
+ if (border_uv_scale.mV[VY] > 0.5f)
+ {
+ border_uv_scale *= 0.5f / border_uv_scale.mV[VY];
+ }
- // draw bottom left
- gGL.texCoord2f(u_min, 0.f);
- gGL.vertex2fv(x_min.mV);
+ F32 border_scale = llmin((F32)border_size, (F32)width * 0.5f, (F32)height * 0.5f);
+ LLVector2 border_width_left = ((edges & (~(U32)ROUNDED_RECT_RIGHT)) != 0) ? LLVector2(border_scale, 0.f) : LLVector2::zero;
+ LLVector2 border_width_right = ((edges & (~(U32)ROUNDED_RECT_LEFT)) != 0) ? LLVector2(border_scale, 0.f) : LLVector2::zero;
+ LLVector2 border_height_bottom = ((edges & (~(U32)ROUNDED_RECT_TOP)) != 0) ? LLVector2(0.f, border_scale) : LLVector2::zero;
+ LLVector2 border_height_top = ((edges & (~(U32)ROUNDED_RECT_BOTTOM)) != 0) ? LLVector2(0.f, border_scale) : LLVector2::zero;
+ LLVector2 width_vec((F32)width, 0.f);
+ LLVector2 height_vec(0.f, (F32)height);
- gGL.texCoord2f(border_uv_scale.mV[VX], 0.f);
- gGL.vertex2fv(x_max.mV);
+ F32 middle_start = border_scale / (F32)width;
+ F32 middle_end = 1.f - middle_start;
- gGL.texCoord2f(u_max, border_uv_scale.mV[VY]);
- gGL.vertex2fv((x_max + border_height_bottom).mV);
+ F32 u_min;
+ F32 u_max;
+ LLVector2 x_min;
+ LLVector2 x_max;
- gGL.texCoord2f(u_min, border_uv_scale.mV[VY]);
- gGL.vertex2fv((x_min + border_height_bottom).mV);
+ gGL.begin(LLRender::QUADS);
+ {
+ if (start_fragment < middle_start)
+ {
+ u_min = (start_fragment / middle_start) * border_uv_scale.mV[VX];
+ u_max = llmin(end_fragment / middle_start, 1.f) * border_uv_scale.mV[VX];
+ x_min = (start_fragment / middle_start) * border_width_left;
+ x_max = llmin(end_fragment / middle_start, 1.f) * border_width_left;
- // draw left
- gGL.texCoord2f(u_min, border_uv_scale.mV[VY]);
- gGL.vertex2fv((x_min + border_height_bottom).mV);
+ // draw bottom left
+ gGL.texCoord2f(u_min, 0.f);
+ gGL.vertex2fv(x_min.mV);
- gGL.texCoord2f(u_max, border_uv_scale.mV[VY]);
- gGL.vertex2fv((x_max + border_height_bottom).mV);
+ gGL.texCoord2f(border_uv_scale.mV[VX], 0.f);
+ gGL.vertex2fv(x_max.mV);
- gGL.texCoord2f(u_max, 1.f - border_uv_scale.mV[VY]);
- gGL.vertex2fv((x_max + height_vec - border_height_top).mV);
+ gGL.texCoord2f(u_max, border_uv_scale.mV[VY]);
+ gGL.vertex2fv((x_max + border_height_bottom).mV);
- gGL.texCoord2f(u_min, 1.f - border_uv_scale.mV[VY]);
- gGL.vertex2fv((x_min + height_vec - border_height_top).mV);
+ gGL.texCoord2f(u_min, border_uv_scale.mV[VY]);
+ gGL.vertex2fv((x_min + border_height_bottom).mV);
- // draw top left
- gGL.texCoord2f(u_min, 1.f - border_uv_scale.mV[VY]);
- gGL.vertex2fv((x_min + height_vec - border_height_top).mV);
+ // draw left
+ gGL.texCoord2f(u_min, border_uv_scale.mV[VY]);
+ gGL.vertex2fv((x_min + border_height_bottom).mV);
- gGL.texCoord2f(u_max, 1.f - border_uv_scale.mV[VY]);
- gGL.vertex2fv((x_max + height_vec - border_height_top).mV);
+ gGL.texCoord2f(u_max, border_uv_scale.mV[VY]);
+ gGL.vertex2fv((x_max + border_height_bottom).mV);
- gGL.texCoord2f(u_max, 1.f);
- gGL.vertex2fv((x_max + height_vec).mV);
+ gGL.texCoord2f(u_max, 1.f - border_uv_scale.mV[VY]);
+ gGL.vertex2fv((x_max + height_vec - border_height_top).mV);
- gGL.texCoord2f(u_min, 1.f);
- gGL.vertex2fv((x_min + height_vec).mV);
- }
+ gGL.texCoord2f(u_min, 1.f - border_uv_scale.mV[VY]);
+ gGL.vertex2fv((x_min + height_vec - border_height_top).mV);
- if (end_fragment > middle_start || start_fragment < middle_end)
- {
- x_min = border_width_left + ((llclamp(start_fragment, middle_start, middle_end) - middle_start)) * width_vec;
- x_max = border_width_left + ((llclamp(end_fragment, middle_start, middle_end) - middle_start)) * width_vec;
+ // draw top left
+ gGL.texCoord2f(u_min, 1.f - border_uv_scale.mV[VY]);
+ gGL.vertex2fv((x_min + height_vec - border_height_top).mV);
- // draw bottom middle
- gGL.texCoord2f(border_uv_scale.mV[VX], 0.f);
- gGL.vertex2fv(x_min.mV);
+ gGL.texCoord2f(u_max, 1.f - border_uv_scale.mV[VY]);
+ gGL.vertex2fv((x_max + height_vec - border_height_top).mV);
- gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 0.f);
- gGL.vertex2fv((x_max).mV);
+ gGL.texCoord2f(u_max, 1.f);
+ gGL.vertex2fv((x_max + height_vec).mV);
- gGL.texCoord2f(1.f - border_uv_scale.mV[VX], border_uv_scale.mV[VY]);
- gGL.vertex2fv((x_max + border_height_bottom).mV);
+ gGL.texCoord2f(u_min, 1.f);
+ gGL.vertex2fv((x_min + height_vec).mV);
+ }
- gGL.texCoord2f(border_uv_scale.mV[VX], border_uv_scale.mV[VY]);
- gGL.vertex2fv((x_min + border_height_bottom).mV);
+ if (end_fragment > middle_start || start_fragment < middle_end)
+ {
+ x_min = border_width_left + ((llclamp(start_fragment, middle_start, middle_end) - middle_start)) * width_vec;
+ x_max = border_width_left + ((llclamp(end_fragment, middle_start, middle_end) - middle_start)) * width_vec;
- // draw middle
- gGL.texCoord2f(border_uv_scale.mV[VX], border_uv_scale.mV[VY]);
- gGL.vertex2fv((x_min + border_height_bottom).mV);
+ // draw bottom middle
+ gGL.texCoord2f(border_uv_scale.mV[VX], 0.f);
+ gGL.vertex2fv(x_min.mV);
- gGL.texCoord2f(1.f - border_uv_scale.mV[VX], border_uv_scale.mV[VY]);
- gGL.vertex2fv((x_max + border_height_bottom).mV);
+ gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 0.f);
+ gGL.vertex2fv((x_max).mV);
- gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]);
- gGL.vertex2fv((x_max + height_vec - border_height_top).mV);
+ gGL.texCoord2f(1.f - border_uv_scale.mV[VX], border_uv_scale.mV[VY]);
+ gGL.vertex2fv((x_max + border_height_bottom).mV);
- gGL.texCoord2f(border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]);
- gGL.vertex2fv((x_min + height_vec - border_height_top).mV);
+ gGL.texCoord2f(border_uv_scale.mV[VX], border_uv_scale.mV[VY]);
+ gGL.vertex2fv((x_min + border_height_bottom).mV);
- // draw top middle
- gGL.texCoord2f(border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]);
- gGL.vertex2fv((x_min + height_vec - border_height_top).mV);
+ // draw middle
+ gGL.texCoord2f(border_uv_scale.mV[VX], border_uv_scale.mV[VY]);
+ gGL.vertex2fv((x_min + border_height_bottom).mV);
- gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]);
- gGL.vertex2fv((x_max + height_vec - border_height_top).mV);
+ gGL.texCoord2f(1.f - border_uv_scale.mV[VX], border_uv_scale.mV[VY]);
+ gGL.vertex2fv((x_max + border_height_bottom).mV);
- gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f);
- gGL.vertex2fv((x_max + height_vec).mV);
+ gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]);
+ gGL.vertex2fv((x_max + height_vec - border_height_top).mV);
- gGL.texCoord2f(border_uv_scale.mV[VX], 1.f);
- gGL.vertex2fv((x_min + height_vec).mV);
- }
+ gGL.texCoord2f(border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]);
+ gGL.vertex2fv((x_min + height_vec - border_height_top).mV);
- if (end_fragment > middle_end)
- {
- u_min = 1.f - ((1.f - llmax(0.f, (start_fragment - middle_end) / middle_start)) * border_uv_scale.mV[VX]);
- u_max = 1.f - ((1.f - ((end_fragment - middle_end) / middle_start)) * border_uv_scale.mV[VX]);
- x_min = width_vec - ((1.f - llmax(0.f, (start_fragment - middle_end) / middle_start)) * border_width_right);
- x_max = width_vec - ((1.f - ((end_fragment - middle_end) / middle_start)) * border_width_right);
+ // draw top middle
+ gGL.texCoord2f(border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]);
+ gGL.vertex2fv((x_min + height_vec - border_height_top).mV);
- // draw bottom right
- gGL.texCoord2f(u_min, 0.f);
- gGL.vertex2fv((x_min).mV);
+ gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f - border_uv_scale.mV[VY]);
+ gGL.vertex2fv((x_max + height_vec - border_height_top).mV);
- gGL.texCoord2f(u_max, 0.f);
- gGL.vertex2fv(x_max.mV);
+ gGL.texCoord2f(1.f - border_uv_scale.mV[VX], 1.f);
+ gGL.vertex2fv((x_max + height_vec).mV);
- gGL.texCoord2f(u_max, border_uv_scale.mV[VY]);
- gGL.vertex2fv((x_max + border_height_bottom).mV);
+ gGL.texCoord2f(border_uv_scale.mV[VX], 1.f);
+ gGL.vertex2fv((x_min + height_vec).mV);
+ }
- gGL.texCoord2f(u_min, border_uv_scale.mV[VY]);
- gGL.vertex2fv((x_min + border_height_bottom).mV);
+ if (end_fragment > middle_end)
+ {
+ u_min = 1.f - ((1.f - llmax(0.f, (start_fragment - middle_end) / middle_start)) * border_uv_scale.mV[VX]);
+ u_max = 1.f - ((1.f - ((end_fragment - middle_end) / middle_start)) * border_uv_scale.mV[VX]);
+ x_min = width_vec - ((1.f - llmax(0.f, (start_fragment - middle_end) / middle_start)) * border_width_right);
+ x_max = width_vec - ((1.f - ((end_fragment - middle_end) / middle_start)) * border_width_right);
- // draw right
- gGL.texCoord2f(u_min, border_uv_scale.mV[VY]);
- gGL.vertex2fv((x_min + border_height_bottom).mV);
+ // draw bottom right
+ gGL.texCoord2f(u_min, 0.f);
+ gGL.vertex2fv((x_min).mV);
- gGL.texCoord2f(u_max, border_uv_scale.mV[VY]);
- gGL.vertex2fv((x_max + border_height_bottom).mV);
+ gGL.texCoord2f(u_max, 0.f);
+ gGL.vertex2fv(x_max.mV);
- gGL.texCoord2f(u_max, 1.f - border_uv_scale.mV[VY]);
- gGL.vertex2fv((x_max + height_vec - border_height_top).mV);
+ gGL.texCoord2f(u_max, border_uv_scale.mV[VY]);
+ gGL.vertex2fv((x_max + border_height_bottom).mV);
- gGL.texCoord2f(u_min, 1.f - border_uv_scale.mV[VY]);
- gGL.vertex2fv((x_min + height_vec - border_height_top).mV);
+ gGL.texCoord2f(u_min, border_uv_scale.mV[VY]);
+ gGL.vertex2fv((x_min + border_height_bottom).mV);
- // draw top right
- gGL.texCoord2f(u_min, 1.f - border_uv_scale.mV[VY]);
- gGL.vertex2fv((x_min + height_vec - border_height_top).mV);
+ // draw right
+ gGL.texCoord2f(u_min, border_uv_scale.mV[VY]);
+ gGL.vertex2fv((x_min + border_height_bottom).mV);
- gGL.texCoord2f(u_max, 1.f - border_uv_scale.mV[VY]);
- gGL.vertex2fv((x_max + height_vec - border_height_top).mV);
+ gGL.texCoord2f(u_max, border_uv_scale.mV[VY]);
+ gGL.vertex2fv((x_max + border_height_bottom).mV);
- gGL.texCoord2f(u_max, 1.f);
- gGL.vertex2fv((x_max + height_vec).mV);
+ gGL.texCoord2f(u_max, 1.f - border_uv_scale.mV[VY]);
+ gGL.vertex2fv((x_max + height_vec - border_height_top).mV);
- gGL.texCoord2f(u_min, 1.f);
- gGL.vertex2fv((x_min + height_vec).mV);
- }
- }
- gGL.end();
+ gGL.texCoord2f(u_min, 1.f - border_uv_scale.mV[VY]);
+ gGL.vertex2fv((x_min + height_vec - border_height_top).mV);
- gGL.popUIMatrix();
+ // draw top right
+ gGL.texCoord2f(u_min, 1.f - border_uv_scale.mV[VY]);
+ gGL.vertex2fv((x_min + height_vec - border_height_top).mV);
+
+ gGL.texCoord2f(u_max, 1.f - border_uv_scale.mV[VY]);
+ gGL.vertex2fv((x_max + height_vec - border_height_top).mV);
+
+ gGL.texCoord2f(u_max, 1.f);
+ gGL.vertex2fv((x_max + height_vec).mV);
+
+ gGL.texCoord2f(u_min, 1.f);
+ gGL.vertex2fv((x_min + height_vec).mV);
+ }
+ }
+ gGL.end();
+
+ gGL.popUIMatrix();
}
-void gl_segmented_rect_3d_tex(const LLRectf& clip_rect, const LLRectf& center_uv_rect, const LLRectf& center_draw_rect,
- const LLVector3& width_vec, const LLVector3& height_vec)
+void gl_segmented_rect_3d_tex(const LLRectf& clip_rect, const LLRectf& center_uv_rect, const LLRectf& center_draw_rect,
+ const LLVector3& width_vec, const LLVector3& height_vec)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_UI;
- gGL.begin(LLRender::QUADS);
- {
- // draw bottom left
- gGL.texCoord2f(clip_rect.mLeft, clip_rect.mBottom);
- gGL.vertex3f(0.f, 0.f, 0.f);
+ gGL.begin(LLRender::QUADS);
+ {
+ // draw bottom left
+ gGL.texCoord2f(clip_rect.mLeft, clip_rect.mBottom);
+ gGL.vertex3f(0.f, 0.f, 0.f);
- gGL.texCoord2f(center_uv_rect.mLeft, clip_rect.mBottom);
- gGL.vertex3fv((center_draw_rect.mLeft * width_vec).mV);
+ gGL.texCoord2f(center_uv_rect.mLeft, clip_rect.mBottom);
+ gGL.vertex3fv((center_draw_rect.mLeft * width_vec).mV);
- gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mBottom);
- gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mBottom * height_vec).mV);
+ gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mBottom);
+ gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mBottom * height_vec).mV);
- gGL.texCoord2f(clip_rect.mLeft, center_uv_rect.mBottom);
- gGL.vertex3fv((center_draw_rect.mBottom * height_vec).mV);
+ gGL.texCoord2f(clip_rect.mLeft, center_uv_rect.mBottom);
+ gGL.vertex3fv((center_draw_rect.mBottom * height_vec).mV);
- // draw bottom middle
- gGL.texCoord2f(center_uv_rect.mLeft, clip_rect.mBottom);
- gGL.vertex3fv((center_draw_rect.mLeft * width_vec).mV);
+ // draw bottom middle
+ gGL.texCoord2f(center_uv_rect.mLeft, clip_rect.mBottom);
+ gGL.vertex3fv((center_draw_rect.mLeft * width_vec).mV);
- gGL.texCoord2f(center_uv_rect.mRight, clip_rect.mBottom);
- gGL.vertex3fv((center_draw_rect.mRight * width_vec).mV);
+ gGL.texCoord2f(center_uv_rect.mRight, clip_rect.mBottom);
+ gGL.vertex3fv((center_draw_rect.mRight * width_vec).mV);
- gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mBottom);
- gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mBottom * height_vec).mV);
+ gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mBottom);
+ gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mBottom * height_vec).mV);
- gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mBottom);
- gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mBottom * height_vec).mV);
+ gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mBottom);
+ gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mBottom * height_vec).mV);
- // draw bottom right
- gGL.texCoord2f(center_uv_rect.mRight, clip_rect.mBottom);
- gGL.vertex3fv((center_draw_rect.mRight * width_vec).mV);
+ // draw bottom right
+ gGL.texCoord2f(center_uv_rect.mRight, clip_rect.mBottom);
+ gGL.vertex3fv((center_draw_rect.mRight * width_vec).mV);
- gGL.texCoord2f(clip_rect.mRight, clip_rect.mBottom);
- gGL.vertex3fv(width_vec.mV);
+ gGL.texCoord2f(clip_rect.mRight, clip_rect.mBottom);
+ gGL.vertex3fv(width_vec.mV);
- gGL.texCoord2f(clip_rect.mRight, center_uv_rect.mBottom);
- gGL.vertex3fv((width_vec + center_draw_rect.mBottom * height_vec).mV);
+ gGL.texCoord2f(clip_rect.mRight, center_uv_rect.mBottom);
+ gGL.vertex3fv((width_vec + center_draw_rect.mBottom * height_vec).mV);
- gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mBottom);
- gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mBottom * height_vec).mV);
+ gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mBottom);
+ gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mBottom * height_vec).mV);
- // draw left
- gGL.texCoord2f(clip_rect.mLeft, center_uv_rect.mBottom);
- gGL.vertex3fv((center_draw_rect.mBottom * height_vec).mV);
+ // draw left
+ gGL.texCoord2f(clip_rect.mLeft, center_uv_rect.mBottom);
+ gGL.vertex3fv((center_draw_rect.mBottom * height_vec).mV);
- gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mBottom);
- gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mBottom * height_vec).mV);
+ gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mBottom);
+ gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mBottom * height_vec).mV);
- gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mTop);
- gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mTop * height_vec).mV);
+ gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mTop);
+ gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mTop * height_vec).mV);
- gGL.texCoord2f(clip_rect.mLeft, center_uv_rect.mTop);
- gGL.vertex3fv((center_draw_rect.mTop * height_vec).mV);
+ gGL.texCoord2f(clip_rect.mLeft, center_uv_rect.mTop);
+ gGL.vertex3fv((center_draw_rect.mTop * height_vec).mV);
- // draw middle
- gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mBottom);
- gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mBottom * height_vec).mV);
+ // draw middle
+ gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mBottom);
+ gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mBottom * height_vec).mV);
- gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mBottom);
- gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mBottom * height_vec).mV);
+ gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mBottom);
+ gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mBottom * height_vec).mV);
- gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mTop);
- gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mTop * height_vec).mV);
+ gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mTop);
+ gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mTop * height_vec).mV);
- gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mTop);
- gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mTop * height_vec).mV);
+ gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mTop);
+ gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mTop * height_vec).mV);
- // draw right
- gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mBottom);
- gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mBottom * height_vec).mV);
+ // draw right
+ gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mBottom);
+ gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mBottom * height_vec).mV);
- gGL.texCoord2f(clip_rect.mRight, center_uv_rect.mBottom);
- gGL.vertex3fv((width_vec + center_draw_rect.mBottom * height_vec).mV);
+ gGL.texCoord2f(clip_rect.mRight, center_uv_rect.mBottom);
+ gGL.vertex3fv((width_vec + center_draw_rect.mBottom * height_vec).mV);
- gGL.texCoord2f(clip_rect.mRight, center_uv_rect.mTop);
- gGL.vertex3fv((width_vec + center_draw_rect.mTop * height_vec).mV);
+ gGL.texCoord2f(clip_rect.mRight, center_uv_rect.mTop);
+ gGL.vertex3fv((width_vec + center_draw_rect.mTop * height_vec).mV);
- gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mTop);
- gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mTop * height_vec).mV);
+ gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mTop);
+ gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mTop * height_vec).mV);
- // draw top left
- gGL.texCoord2f(clip_rect.mLeft, center_uv_rect.mTop);
- gGL.vertex3fv((center_draw_rect.mTop * height_vec).mV);
+ // draw top left
+ gGL.texCoord2f(clip_rect.mLeft, center_uv_rect.mTop);
+ gGL.vertex3fv((center_draw_rect.mTop * height_vec).mV);
- gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mTop);
- gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mTop * height_vec).mV);
+ gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mTop);
+ gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mTop * height_vec).mV);
- gGL.texCoord2f(center_uv_rect.mLeft, clip_rect.mTop);
- gGL.vertex3fv((center_draw_rect.mLeft * width_vec + height_vec).mV);
+ gGL.texCoord2f(center_uv_rect.mLeft, clip_rect.mTop);
+ gGL.vertex3fv((center_draw_rect.mLeft * width_vec + height_vec).mV);
- gGL.texCoord2f(clip_rect.mLeft, clip_rect.mTop);
- gGL.vertex3fv((height_vec).mV);
+ gGL.texCoord2f(clip_rect.mLeft, clip_rect.mTop);
+ gGL.vertex3fv((height_vec).mV);
- // draw top middle
- gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mTop);
- gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mTop * height_vec).mV);
+ // draw top middle
+ gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mTop);
+ gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mTop * height_vec).mV);
- gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mTop);
- gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mTop * height_vec).mV);
+ gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mTop);
+ gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mTop * height_vec).mV);
- gGL.texCoord2f(center_uv_rect.mRight, clip_rect.mTop);
- gGL.vertex3fv((center_draw_rect.mRight * width_vec + height_vec).mV);
+ gGL.texCoord2f(center_uv_rect.mRight, clip_rect.mTop);
+ gGL.vertex3fv((center_draw_rect.mRight * width_vec + height_vec).mV);
- gGL.texCoord2f(center_uv_rect.mLeft, clip_rect.mTop);
- gGL.vertex3fv((center_draw_rect.mLeft * width_vec + height_vec).mV);
+ gGL.texCoord2f(center_uv_rect.mLeft, clip_rect.mTop);
+ gGL.vertex3fv((center_draw_rect.mLeft * width_vec + height_vec).mV);
- // draw top right
- gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mTop);
- gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mTop * height_vec).mV);
+ // draw top right
+ gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mTop);
+ gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mTop * height_vec).mV);
- gGL.texCoord2f(clip_rect.mRight, center_uv_rect.mTop);
- gGL.vertex3fv((width_vec + center_draw_rect.mTop * height_vec).mV);
+ gGL.texCoord2f(clip_rect.mRight, center_uv_rect.mTop);
+ gGL.vertex3fv((width_vec + center_draw_rect.mTop * height_vec).mV);
- gGL.texCoord2f(clip_rect.mRight, clip_rect.mTop);
- gGL.vertex3fv((width_vec + height_vec).mV);
+ gGL.texCoord2f(clip_rect.mRight, clip_rect.mTop);
+ gGL.vertex3fv((width_vec + height_vec).mV);
- gGL.texCoord2f(center_uv_rect.mRight, clip_rect.mTop);
- gGL.vertex3fv((center_draw_rect.mRight * width_vec + height_vec).mV);
- }
- gGL.end();
+ gGL.texCoord2f(center_uv_rect.mRight, clip_rect.mTop);
+ gGL.vertex3fv((center_draw_rect.mRight * width_vec + height_vec).mV);
+ }
+ gGL.end();
}
LLRender2D::LLRender2D(LLImageProviderInterface* image_provider)
{
- mImageProvider = image_provider;
- if(mImageProvider)
- {
- mImageProvider->addOnRemovalCallback(resetProvider);
- }
+ mImageProvider = image_provider;
+ if(mImageProvider)
+ {
+ mImageProvider->addOnRemovalCallback(resetProvider);
+ }
}
LLRender2D::~LLRender2D()
{
- if(mImageProvider)
- {
- mImageProvider->cleanUp();
- mImageProvider->deleteOnRemovalCallback(resetProvider);
- }
+ if(mImageProvider)
+ {
+ mImageProvider->cleanUp();
+ mImageProvider->deleteOnRemovalCallback(resetProvider);
+ }
}
// static
void LLRender2D::translate(F32 x, F32 y, F32 z)
{
- gGL.translateUI(x,y,z);
- LLFontGL::sCurOrigin.mX += (S32) x;
- LLFontGL::sCurOrigin.mY += (S32) y;
- LLFontGL::sCurDepth += z;
+ gGL.translateUI(x,y,z);
+ LLFontGL::sCurOrigin.mX += (S32) x;
+ LLFontGL::sCurOrigin.mY += (S32) y;
+ LLFontGL::sCurDepth += z;
}
// static
void LLRender2D::pushMatrix()
{
- gGL.pushUIMatrix();
- LLFontGL::sOriginStack.push_back(std::make_pair(LLFontGL::sCurOrigin, LLFontGL::sCurDepth));
+ gGL.pushUIMatrix();
+ LLFontGL::sOriginStack.push_back(std::make_pair(LLFontGL::sCurOrigin, LLFontGL::sCurDepth));
}
// static
void LLRender2D::popMatrix()
{
- gGL.popUIMatrix();
- LLFontGL::sCurOrigin = LLFontGL::sOriginStack.back().first;
- LLFontGL::sCurDepth = LLFontGL::sOriginStack.back().second;
- LLFontGL::sOriginStack.pop_back();
+ gGL.popUIMatrix();
+ LLFontGL::sCurOrigin = LLFontGL::sOriginStack.back().first;
+ LLFontGL::sCurDepth = LLFontGL::sOriginStack.back().second;
+ LLFontGL::sOriginStack.pop_back();
}
// static
void LLRender2D::loadIdentity()
{
- gGL.loadUIIdentity();
- LLFontGL::sCurOrigin.mX = 0;
- LLFontGL::sCurOrigin.mY = 0;
- LLFontGL::sCurDepth = 0.f;
+ gGL.loadUIIdentity();
+ LLFontGL::sCurOrigin.mX = 0;
+ LLFontGL::sCurOrigin.mY = 0;
+ LLFontGL::sCurDepth = 0.f;
}
// static
void LLRender2D::setLineWidth(F32 width)
{
- gGL.flush();
+ gGL.flush();
// If outside the allowed range, glLineWidth fails with "invalid value".
// On Darwin, the range is [1, 1].
static GLfloat range[2]{0.0};
@@ -1524,22 +1524,22 @@ void LLRender2D::setLineWidth(F32 width)
LLPointer<LLUIImage> LLRender2D::getUIImageByID(const LLUUID& image_id, S32 priority)
{
- if (mImageProvider)
- {
- return mImageProvider->getUIImageByID(image_id, priority);
- }
- else
- {
- return NULL;
- }
+ if (mImageProvider)
+ {
+ return mImageProvider->getUIImageByID(image_id, priority);
+ }
+ else
+ {
+ return NULL;
+ }
}
LLPointer<LLUIImage> LLRender2D::getUIImage(const std::string& name, S32 priority)
{
- if (!name.empty() && mImageProvider)
- return mImageProvider->getUIImage(name, priority);
- else
- return NULL;
+ if (!name.empty() && mImageProvider)
+ return mImageProvider->getUIImage(name, priority);
+ else
+ return NULL;
}
// static
diff --git a/indra/llrender/llrender2dutils.h b/indra/llrender/llrender2dutils.h
index 135738c3ba..c3c6d66b8e 100644
--- a/indra/llrender/llrender2dutils.h
+++ b/indra/llrender/llrender2dutils.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file llrender2dutils.h
* @brief GL function declarations for immediate-mode gl drawing.
*
* $LicenseInfo:firstyear=2012&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -30,12 +30,12 @@
#ifndef LL_RENDER2DUTILS_H
#define LL_RENDER2DUTILS_H
-#include "llpointer.h" // LLPointer<>
+#include "llpointer.h" // LLPointer<>
#include "llrect.h"
#include "llsingleton.h"
#include "llglslshader.h"
-class LLColor4;
+class LLColor4;
class LLVector3;
class LLVector2;
class LLUIImage;
@@ -79,30 +79,30 @@ void gl_draw_scaled_rotated_image(S32 x, S32 y, S32 width, S32 height, F32 degre
void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 border_width, S32 border_height, S32 width, S32 height, LLTexture* image, const LLColor4 &color, BOOL solid_color = FALSE, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f), bool scale_inner = true);
void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 width, S32 height, LLTexture* image, const LLColor4 &color, BOOL solid_color = FALSE, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f), const LLRectf& scale_rect = LLRectf(0.f, 1.f, 1.f, 0.f), bool scale_inner = true);
-void gl_line_3d( const LLVector3& start, const LLVector3& end, const LLColor4& color);
+void gl_line_3d( const LLVector3& start, const LLVector3& end, const LLColor4& color);
void gl_rect_2d_simple_tex( S32 width, S32 height );
// segmented rectangles
/*
- TL |______TOP_________| TR
- /| |\
+ TL |______TOP_________| TR
+ /| |\
_/_|__________________|_\_
L| | MIDDLE | |R
_|_|__________________|_|_
- \ | BOTTOM | /
+ \ | BOTTOM | /
BL\|__________________|/ BR
- | |
+ | |
*/
typedef enum e_rounded_edge
{
- ROUNDED_RECT_LEFT = 0x1,
- ROUNDED_RECT_TOP = 0x2,
- ROUNDED_RECT_RIGHT = 0x4,
- ROUNDED_RECT_BOTTOM = 0x8,
- ROUNDED_RECT_ALL = 0xf
+ ROUNDED_RECT_LEFT = 0x1,
+ ROUNDED_RECT_TOP = 0x2,
+ ROUNDED_RECT_RIGHT = 0x4,
+ ROUNDED_RECT_BOTTOM = 0x8,
+ ROUNDED_RECT_ALL = 0xf
}ERoundedEdge;
@@ -112,61 +112,61 @@ void gl_segmented_rect_3d_tex(const LLRectf& clip_rect, const LLRectf& center_uv
inline void gl_rect_2d( const LLRect& rect, BOOL filled )
{
- gl_rect_2d( rect.mLeft, rect.mTop, rect.mRight, rect.mBottom, filled );
+ gl_rect_2d( rect.mLeft, rect.mTop, rect.mRight, rect.mBottom, filled );
}
inline void gl_rect_2d_offset_local( const LLRect& rect, S32 pixel_offset, BOOL filled)
{
- gl_rect_2d_offset_local( rect.mLeft, rect.mTop, rect.mRight, rect.mBottom, pixel_offset, filled );
+ gl_rect_2d_offset_local( rect.mLeft, rect.mTop, rect.mRight, rect.mBottom, pixel_offset, filled );
}
class LLImageProviderInterface;
class LLRender2D : public LLParamSingleton<LLRender2D>
{
- LLSINGLETON(LLRender2D, LLImageProviderInterface* image_provider);
- LOG_CLASS(LLRender2D);
- ~LLRender2D();
+ LLSINGLETON(LLRender2D, LLImageProviderInterface* image_provider);
+ LOG_CLASS(LLRender2D);
+ ~LLRender2D();
public:
- static void pushMatrix();
- static void popMatrix();
- static void loadIdentity();
- static void translate(F32 x, F32 y, F32 z = 0.0f);
+ static void pushMatrix();
+ static void popMatrix();
+ static void loadIdentity();
+ static void translate(F32 x, F32 y, F32 z = 0.0f);
- static void setLineWidth(F32 width);
+ static void setLineWidth(F32 width);
- LLPointer<LLUIImage> getUIImageByID(const LLUUID& image_id, S32 priority = 0);
- LLPointer<LLUIImage> getUIImage(const std::string& name, S32 priority = 0);
+ LLPointer<LLUIImage> getUIImageByID(const LLUUID& image_id, S32 priority = 0);
+ LLPointer<LLUIImage> getUIImage(const std::string& name, S32 priority = 0);
protected:
- // since LLRender2D has no control of image provider's lifecycle
- // we need a way to tell LLRender2D that provider died and
- // LLRender2D needs to be updated.
- static void resetProvider();
+ // since LLRender2D has no control of image provider's lifecycle
+ // we need a way to tell LLRender2D that provider died and
+ // LLRender2D needs to be updated.
+ static void resetProvider();
private:
- LLImageProviderInterface* mImageProvider;
+ LLImageProviderInterface* mImageProvider;
};
class LLImageProviderInterface
{
protected:
- LLImageProviderInterface() {};
- virtual ~LLImageProviderInterface();
+ LLImageProviderInterface() {};
+ virtual ~LLImageProviderInterface();
public:
- virtual LLPointer<LLUIImage> getUIImage(const std::string& name, S32 priority) = 0;
- virtual LLPointer<LLUIImage> getUIImageByID(const LLUUID& id, S32 priority) = 0;
- virtual void cleanUp() = 0;
+ virtual LLPointer<LLUIImage> getUIImage(const std::string& name, S32 priority) = 0;
+ virtual LLPointer<LLUIImage> getUIImageByID(const LLUUID& id, S32 priority) = 0;
+ virtual void cleanUp() = 0;
- // to notify holders when pointer gets deleted
- typedef void(*callback_t)();
- void addOnRemovalCallback(callback_t func);
- void deleteOnRemovalCallback(callback_t func);
+ // to notify holders when pointer gets deleted
+ typedef void(*callback_t)();
+ void addOnRemovalCallback(callback_t func);
+ void deleteOnRemovalCallback(callback_t func);
private:
- typedef std::list< callback_t > callback_list_t;
- callback_list_t mCallbackList;
+ typedef std::list< callback_t > callback_list_t;
+ callback_list_t mCallbackList;
};
diff --git a/indra/llrender/llrendernavprim.cpp b/indra/llrender/llrendernavprim.cpp
index eea3077632..419c8e8755 100644
--- a/indra/llrender/llrendernavprim.cpp
+++ b/indra/llrender/llrendernavprim.cpp
@@ -1,4 +1,4 @@
-/**
+/**
* @file llrendernavprim.cpp
* @brief Implementation of llrendernavprim
* @author Prep@lindenlab.com
@@ -43,17 +43,17 @@ void LLRenderNavPrim::renderLLTri( const LLVector3& a, const LLVector3& b, const
gGL.color4ubv(color.mV);
gGL.begin(LLRender::TRIANGLES);
- {
- gGL.vertex3fv( a.mV );
- gGL.vertex3fv( b.mV );
- gGL.vertex3fv( c.mV );
- }
- gGL.end();
+ {
+ gGL.vertex3fv( a.mV );
+ gGL.vertex3fv( b.mV );
+ gGL.vertex3fv( c.mV );
+ }
+ gGL.end();
}
//=============================================================================
void LLRenderNavPrim::renderNavMeshVB( U32 mode, LLVertexBuffer* pVBO, int vertCnt )
-{
- pVBO->setBuffer();
- pVBO->drawArrays( mode, 0, vertCnt );
+{
+ pVBO->setBuffer();
+ pVBO->drawArrays( mode, 0, vertCnt );
}
//=============================================================================
diff --git a/indra/llrender/llrendernavprim.h b/indra/llrender/llrendernavprim.h
index a3a5dfec3a..a7b003a6cf 100644
--- a/indra/llrender/llrendernavprim.h
+++ b/indra/llrender/llrendernavprim.h
@@ -1,4 +1,4 @@
-/**
+/**
* @file llrendernavprim.h
* @brief Header file for llrendernavprim
* @author Prep@lindenlab.com
@@ -37,10 +37,10 @@ class LLVertexBuffer;
class LLRenderNavPrim
{
public:
- //Draw simple tri
- void renderLLTri( const LLVector3& a, const LLVector3& b, const LLVector3& c, const LLColor4U& color ) const;
- //Draw the contents of vertex buffer
- void renderNavMeshVB( U32 mode, LLVertexBuffer* pVBO, int vertCnt );
+ //Draw simple tri
+ void renderLLTri( const LLVector3& a, const LLVector3& b, const LLVector3& c, const LLColor4U& color ) const;
+ //Draw the contents of vertex buffer
+ void renderNavMeshVB( U32 mode, LLVertexBuffer* pVBO, int vertCnt );
private:
};
diff --git a/indra/llrender/llrendersphere.cpp b/indra/llrender/llrendersphere.cpp
index 26bfe036e8..9570180554 100644
--- a/indra/llrender/llrendersphere.cpp
+++ b/indra/llrender/llrendersphere.cpp
@@ -1,32 +1,32 @@
-/**
+/**
* @file llrendersphere.cpp
* @brief implementation of the LLRenderSphere class.
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
-// Sphere creates a set of display lists that can then be called to create
-// a lit sphere at different LOD levels. You only need one instance of sphere
-// per viewer - then call the appropriate list.
+// Sphere creates a set of display lists that can then be called to create
+// a lit sphere at different LOD levels. You only need one instance of sphere
+// per viewer - then call the appropriate list.
#include "linden_common.h"
@@ -39,53 +39,53 @@ LLRenderSphere gSphere;
void LLRenderSphere::render()
{
- renderGGL();
- gGL.flush();
+ renderGGL();
+ gGL.flush();
}
inline LLVector3 polar_to_cart(F32 latitude, F32 longitude)
{
- return LLVector3(sin(F_TWO_PI * latitude) * cos(F_TWO_PI * longitude),
- sin(F_TWO_PI * latitude) * sin(F_TWO_PI * longitude),
- cos(F_TWO_PI * latitude));
+ return LLVector3(sin(F_TWO_PI * latitude) * cos(F_TWO_PI * longitude),
+ sin(F_TWO_PI * latitude) * sin(F_TWO_PI * longitude),
+ cos(F_TWO_PI * latitude));
}
void LLRenderSphere::renderGGL()
{
- S32 const LATITUDE_SLICES = 20;
- S32 const LONGITUDE_SLICES = 30;
+ S32 const LATITUDE_SLICES = 20;
+ S32 const LONGITUDE_SLICES = 30;
+
+ if (mSpherePoints.empty())
+ {
+ mSpherePoints.resize(LATITUDE_SLICES + 1);
+ for (S32 lat_i = 0; lat_i < LATITUDE_SLICES + 1; lat_i++)
+ {
+ mSpherePoints[lat_i].resize(LONGITUDE_SLICES + 1);
+ for (S32 lon_i = 0; lon_i < LONGITUDE_SLICES + 1; lon_i++)
+ {
+ F32 lat = (F32)lat_i / LATITUDE_SLICES;
+ F32 lon = (F32)lon_i / LONGITUDE_SLICES;
- if (mSpherePoints.empty())
- {
- mSpherePoints.resize(LATITUDE_SLICES + 1);
- for (S32 lat_i = 0; lat_i < LATITUDE_SLICES + 1; lat_i++)
- {
- mSpherePoints[lat_i].resize(LONGITUDE_SLICES + 1);
- for (S32 lon_i = 0; lon_i < LONGITUDE_SLICES + 1; lon_i++)
- {
- F32 lat = (F32)lat_i / LATITUDE_SLICES;
- F32 lon = (F32)lon_i / LONGITUDE_SLICES;
+ mSpherePoints[lat_i][lon_i] = polar_to_cart(lat, lon);
+ }
+ }
+ }
- mSpherePoints[lat_i][lon_i] = polar_to_cart(lat, lon);
- }
- }
- }
-
- gGL.begin(LLRender::TRIANGLES);
+ gGL.begin(LLRender::TRIANGLES);
- for (S32 lat_i = 0; lat_i < LATITUDE_SLICES; lat_i++)
- {
- for (S32 lon_i = 0; lon_i < LONGITUDE_SLICES; lon_i++)
- {
- gGL.vertex3fv(mSpherePoints[lat_i][lon_i].mV);
- gGL.vertex3fv(mSpherePoints[lat_i][lon_i+1].mV);
- gGL.vertex3fv(mSpherePoints[lat_i+1][lon_i].mV);
+ for (S32 lat_i = 0; lat_i < LATITUDE_SLICES; lat_i++)
+ {
+ for (S32 lon_i = 0; lon_i < LONGITUDE_SLICES; lon_i++)
+ {
+ gGL.vertex3fv(mSpherePoints[lat_i][lon_i].mV);
+ gGL.vertex3fv(mSpherePoints[lat_i][lon_i+1].mV);
+ gGL.vertex3fv(mSpherePoints[lat_i+1][lon_i].mV);
- gGL.vertex3fv(mSpherePoints[lat_i+1][lon_i].mV);
- gGL.vertex3fv(mSpherePoints[lat_i][lon_i+1].mV);
- gGL.vertex3fv(mSpherePoints[lat_i+1][lon_i+1].mV);
- }
- }
- gGL.end();
+ gGL.vertex3fv(mSpherePoints[lat_i+1][lon_i].mV);
+ gGL.vertex3fv(mSpherePoints[lat_i][lon_i+1].mV);
+ gGL.vertex3fv(mSpherePoints[lat_i+1][lon_i+1].mV);
+ }
+ }
+ gGL.end();
}
diff --git a/indra/llrender/llrendersphere.h b/indra/llrender/llrendersphere.h
index f8e9e86e7f..e2e886fa06 100644
--- a/indra/llrender/llrendersphere.h
+++ b/indra/llrender/llrendersphere.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file llrendersphere.h
* @brief interface for the LLRenderSphere class.
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -35,16 +35,16 @@
#include "v4color.h"
#include "llgl.h"
-void lat2xyz(LLVector3 * result, F32 lat, F32 lon); // utility routine
+void lat2xyz(LLVector3 * result, F32 lat, F32 lon); // utility routine
-class LLRenderSphere
+class LLRenderSphere
{
public:
- void render(); // render at highest LOD
- void renderGGL(); // render using LLRender
+ void render(); // render at highest LOD
+ void renderGGL(); // render using LLRender
private:
- std::vector< std::vector<LLVector3> > mSpherePoints;
+ std::vector< std::vector<LLVector3> > mSpherePoints;
};
extern LLRenderSphere gSphere;
diff --git a/indra/llrender/llrendertarget.cpp b/indra/llrender/llrendertarget.cpp
index 88c48e5166..7f0643c3e8 100644
--- a/indra/llrender/llrendertarget.cpp
+++ b/indra/llrender/llrendertarget.cpp
@@ -1,25 +1,25 @@
-/**
+/**
* @file llrendertarget.cpp
* @brief LLRenderTarget implementation
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -44,7 +44,7 @@ void check_framebuffer_status()
break;
default:
LL_WARNS() << "check_framebuffer_status failed -- " << std::hex << status << LL_ENDL;
- ll_fail("check_framebuffer_status failed");
+ ll_fail("check_framebuffer_status failed");
break;
}
}
@@ -75,10 +75,10 @@ LLRenderTarget::~LLRenderTarget()
}
void LLRenderTarget::resize(U32 resx, U32 resy)
-{
+{
//for accounting, get the number of pixels added/subtracted
S32 pix_diff = (resx*resy)-(mResX*mResY);
-
+
mResX = resx;
mResY = resy;
@@ -92,7 +92,7 @@ void LLRenderTarget::resize(U32 resx, U32 resy)
}
if (mDepth)
- {
+ {
gGL.getTexUnit(0)->bindManual(mUsage, mDepth);
U32 internal_type = LLTexUnit::getInternalType(mUsage);
LLImageGL::setManualImage(internal_type, 0, GL_DEPTH_COMPONENT24, mResX, mResY, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL, false);
@@ -100,7 +100,7 @@ void LLRenderTarget::resize(U32 resx, U32 resy)
sBytesAllocated += pix_diff*4;
}
}
-
+
bool LLRenderTarget::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, LLTexUnit::eTextureType usage, LLTexUnit::eTextureMipGeneration generateMipMaps)
{
@@ -112,7 +112,7 @@ bool LLRenderTarget::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, LLT
resy = llmin(resy, (U32) gGLManager.mGLMaxTextureSize);
release();
-
+
mResX = resx;
mResY = resy;
@@ -125,7 +125,7 @@ bool LLRenderTarget::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, LLT
// Calculate the number of mip levels based upon resolution that we should have.
mMipLevels = 1 + floor(log10((float)llmax(mResX, mResY))/log10(2.0));
}
-
+
if (depth)
{
if (!allocateDepth())
@@ -140,12 +140,12 @@ bool LLRenderTarget::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, LLT
if (mDepth)
{
glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
-
+
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, LLTexUnit::getInternalType(mUsage), mDepth, 0);
glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO);
}
-
+
return addColorAttachment(color_fmt);
}
@@ -190,7 +190,7 @@ void LLRenderTarget::releaseColorAttachment()
llassert(!isBoundInStack());
llassert(mTex.size() == 1); //cannot use releaseColorAttachment with LLRenderTarget managed color targets
llassert(mFBO != 0); // mFBO must be valid
-
+
glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, LLTexUnit::getInternalType(mUsage), 0, 0);
glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO);
@@ -238,12 +238,12 @@ bool LLRenderTarget::addColorAttachment(U32 color_fmt)
return false;
}
}
-
+
sBytesAllocated += mResX*mResY*4;
stop_glerror();
-
+
if (offset == 0)
{ //use bilinear filtering on single texture render targets that aren't multisampled
gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
@@ -266,15 +266,15 @@ bool LLRenderTarget::addColorAttachment(U32 color_fmt)
gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
stop_glerror();
}
-
+
if (mFBO)
{
glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0+offset,
LLTexUnit::getInternalType(mUsage), tex, 0);
-
+
check_framebuffer_status();
-
+
glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO);
}
@@ -286,8 +286,8 @@ bool LLRenderTarget::addColorAttachment(U32 color_fmt)
bindTarget();
flush();
}
-
-
+
+
return true;
}
@@ -296,7 +296,7 @@ bool LLRenderTarget::allocateDepth()
LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
LLImageGL::generateTextures(1, &mDepth);
gGL.getTexUnit(0)->bindManual(mUsage, mDepth);
-
+
U32 internal_type = LLTexUnit::getInternalType(mUsage);
stop_glerror();
clear_glerror();
@@ -336,7 +336,7 @@ void LLRenderTarget::shareDepthBuffer(LLRenderTarget& target)
if (mDepth)
{
glBindFramebuffer(GL_FRAMEBUFFER, target.mFBO);
-
+
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, LLTexUnit::getInternalType(mUsage), mDepth, 0);
check_framebuffer_status();
@@ -355,7 +355,7 @@ void LLRenderTarget::release()
if (mDepth)
{
LLImageGL::deleteTextures(1, &mDepth);
-
+
mDepth = 0;
sBytesAllocated -= mResX*mResY*4;
@@ -408,7 +408,7 @@ void LLRenderTarget::release()
mTex.clear();
mInternalFormat.clear();
-
+
mResX = mResY = 0;
}
@@ -417,7 +417,7 @@ void LLRenderTarget::bindTarget()
LL_PROFILE_GPU_ZONE("bindTarget");
llassert(mFBO);
llassert(!isBoundInStack());
-
+
glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
sCurFBO = mFBO;
@@ -427,7 +427,7 @@ void LLRenderTarget::bindTarget()
GL_COLOR_ATTACHMENT2,
GL_COLOR_ATTACHMENT3};
glDrawBuffers(mTex.size(), drawbuffers);
-
+
if (mTex.empty())
{ //no color buffer to draw to
glDrawBuffer(GL_NONE);
@@ -452,7 +452,7 @@ void LLRenderTarget::clear(U32 mask_in)
if (mUseDepth)
{
mask |= GL_DEPTH_BUFFER_BIT;
-
+
}
if (mFBO)
{
@@ -560,7 +560,7 @@ bool LLRenderTarget::isBoundInStack() const
{
LLRenderTarget* cur = sBoundTarget;
while (cur && cur != this)
- {
+ {
cur = cur->mPreviousRT;
}
diff --git a/indra/llrender/llrendertarget.h b/indra/llrender/llrendertarget.h
index 9fcea35e3d..b5745b5b49 100644
--- a/indra/llrender/llrendertarget.h
+++ b/indra/llrender/llrendertarget.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file llrendertarget.h
* @brief Off screen render target abstraction. Loose wrapper for GL_EXT_framebuffer_objects.
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -37,56 +37,56 @@
SAMPLE USAGE:
- LLRenderTarget target;
+ LLRenderTarget target;
- ...
+ ...
- //allocate a 256x256 RGBA render target with depth buffer
- target.allocate(256,256,GL_RGBA,TRUE);
+ //allocate a 256x256 RGBA render target with depth buffer
+ target.allocate(256,256,GL_RGBA,TRUE);
- //render to contents of offscreen buffer
- target.bindTarget();
- target.clear();
- ... <issue drawing commands> ...
- target.flush();
+ //render to contents of offscreen buffer
+ target.bindTarget();
+ target.clear();
+ ... <issue drawing commands> ...
+ target.flush();
- ...
+ ...
- //use target as a texture
- gGL.getTexUnit(INDEX)->bind(&target);
- ... <issue drawing commands> ...
+ //use target as a texture
+ gGL.getTexUnit(INDEX)->bind(&target);
+ ... <issue drawing commands> ...
*/
class LLRenderTarget
{
public:
- //whether or not to use FBO implementation
- static bool sUseFBO;
- static U32 sBytesAllocated;
- static U32 sCurFBO;
- static U32 sCurResX;
- static U32 sCurResY;
+ //whether or not to use FBO implementation
+ static bool sUseFBO;
+ static U32 sBytesAllocated;
+ static U32 sCurFBO;
+ static U32 sCurResX;
+ static U32 sCurResY;
- LLRenderTarget();
- ~LLRenderTarget();
+ LLRenderTarget();
+ ~LLRenderTarget();
- //allocate resources for rendering
- //must be called before use
- //multiple calls will release previously allocated resources
+ //allocate resources for rendering
+ //must be called before use
+ //multiple calls will release previously allocated resources
// resX - width
// resY - height
// color_fmt - GL color format (e.g. GL_RGB)
// depth - if true, allocate a depth buffer
// usage - deprecated, should always be TT_TEXTURE
- bool allocate(U32 resx, U32 resy, U32 color_fmt, bool depth = false, LLTexUnit::eTextureType usage = LLTexUnit::TT_TEXTURE, LLTexUnit::eTextureMipGeneration generateMipMaps = LLTexUnit::TMG_NONE);
+ bool allocate(U32 resx, U32 resy, U32 color_fmt, bool depth = false, LLTexUnit::eTextureType usage = LLTexUnit::TT_TEXTURE, LLTexUnit::eTextureMipGeneration generateMipMaps = LLTexUnit::TMG_NONE);
- //resize existing attachments to use new resolution and color format
- // CAUTION: if the GL runs out of memory attempting to resize, this render target will be undefined
- // DO NOT use for screen space buffers or for scratch space for an image that might be uploaded
- // DO use for render targets that resize often and aren't likely to ruin someone's day if they break
- void resize(U32 resx, U32 resy);
+ //resize existing attachments to use new resolution and color format
+ // CAUTION: if the GL runs out of memory attempting to resize, this render target will be undefined
+ // DO NOT use for screen space buffers or for scratch space for an image that might be uploaded
+ // DO use for render targets that resize often and aren't likely to ruin someone's day if they break
+ void resize(U32 resx, U32 resy);
//point this render target at a particular LLImageGL
// Intended usage:
@@ -96,95 +96,95 @@ public:
// < issue GL calls>
// target.flush();
// target.releaseColorAttachment();
- //
+ //
// attachment -- LLImageGL to render into
// use_name -- optional texture name to target instead of attachment->getTexName()
// NOTE: setColorAttachment and releaseColorAttachment cannot be used in conjuction with
- // addColorAttachment, allocateDepth, resize, etc.
+ // addColorAttachment, allocateDepth, resize, etc.
void setColorAttachment(LLImageGL* attachment, LLGLuint use_name = 0);
// detach from current color attachment
void releaseColorAttachment();
- //add color buffer attachment
- //limit of 4 color attachments per render target
- bool addColorAttachment(U32 color_fmt);
+ //add color buffer attachment
+ //limit of 4 color attachments per render target
+ bool addColorAttachment(U32 color_fmt);
- //allocate a depth texture
- bool allocateDepth();
+ //allocate a depth texture
+ bool allocateDepth();
- //share depth buffer with provided render target
- void shareDepthBuffer(LLRenderTarget& target);
+ //share depth buffer with provided render target
+ void shareDepthBuffer(LLRenderTarget& target);
- //free any allocated resources
- //safe to call redundantly
+ //free any allocated resources
+ //safe to call redundantly
// asserts that this target is not currently bound or present in the RT stack
- void release();
+ void release();
- //bind target for rendering
- //applies appropriate viewport
- // If an LLRenderTarget is currently bound, stores a reference to that LLRenderTarget
+ //bind target for rendering
+ //applies appropriate viewport
+ // If an LLRenderTarget is currently bound, stores a reference to that LLRenderTarget
// and restores previous binding on flush() (maintains a stack of Render Targets)
// Asserts that this target is not currently bound in the stack
- void bindTarget();
+ void bindTarget();
- //clear render targer, clears depth buffer if present,
- //uses scissor rect if in copy-to-texture mode
+ //clear render targer, clears depth buffer if present,
+ //uses scissor rect if in copy-to-texture mode
// asserts that this target is currently bound
- void clear(U32 mask = 0xFFFFFFFF);
-
- //get applied viewport
- void getViewport(S32* viewport);
+ void clear(U32 mask = 0xFFFFFFFF);
+
+ //get applied viewport
+ void getViewport(S32* viewport);
- //get X resolution
- U32 getWidth() const { return mResX; }
+ //get X resolution
+ U32 getWidth() const { return mResX; }
- //get Y resolution
- U32 getHeight() const { return mResY; }
+ //get Y resolution
+ U32 getHeight() const { return mResY; }
- LLTexUnit::eTextureType getUsage(void) const { return mUsage; }
+ LLTexUnit::eTextureType getUsage(void) const { return mUsage; }
- U32 getTexture(U32 attachment = 0) const;
- U32 getNumTextures() const;
+ U32 getTexture(U32 attachment = 0) const;
+ U32 getNumTextures() const;
- U32 getDepth(void) const { return mDepth; }
+ U32 getDepth(void) const { return mDepth; }
- void bindTexture(U32 index, S32 channel, LLTexUnit::eTextureFilterOptions filter_options = LLTexUnit::TFO_BILINEAR);
+ void bindTexture(U32 index, S32 channel, LLTexUnit::eTextureFilterOptions filter_options = LLTexUnit::TFO_BILINEAR);
- //flush rendering operations
- //must be called when rendering is complete
- //should be used 1:1 with bindTarget
- // call bindTarget once, do all your rendering, call flush once
+ //flush rendering operations
+ //must be called when rendering is complete
+ //should be used 1:1 with bindTarget
+ // call bindTarget once, do all your rendering, call flush once
// If an LLRenderTarget was bound when bindTarget was called, binds that RenderTarget for rendering (maintains RT stack)
// asserts that this target is currently bound
- void flush();
+ void flush();
- //Returns TRUE if target is ready to be rendered into.
- //That is, if the target has been allocated with at least
- //one renderable attachment (i.e. color buffer, depth buffer).
- bool isComplete() const;
+ //Returns TRUE if target is ready to be rendered into.
+ //That is, if the target has been allocated with at least
+ //one renderable attachment (i.e. color buffer, depth buffer).
+ bool isComplete() const;
// Returns true if this RenderTarget is bound somewhere in the stack
bool isBoundInStack() const;
- static LLRenderTarget* getCurrentBoundTarget() { return sBoundTarget; }
+ static LLRenderTarget* getCurrentBoundTarget() { return sBoundTarget; }
protected:
- U32 mResX;
- U32 mResY;
- std::vector<U32> mTex;
- std::vector<U32> mInternalFormat;
- U32 mFBO;
+ U32 mResX;
+ U32 mResY;
+ std::vector<U32> mTex;
+ std::vector<U32> mInternalFormat;
+ U32 mFBO;
LLRenderTarget* mPreviousRT = nullptr;
U32 mDepth;
bool mUseDepth;
- LLTexUnit::eTextureMipGeneration mGenerateMipMaps;
- U32 mMipLevels;
+ LLTexUnit::eTextureMipGeneration mGenerateMipMaps;
+ U32 mMipLevels;
+
+ LLTexUnit::eTextureType mUsage;
- LLTexUnit::eTextureType mUsage;
-
- static LLRenderTarget* sBoundTarget;
+ static LLRenderTarget* sBoundTarget;
};
#endif
diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp
index f78be910d2..85644a95fb 100644
--- a/indra/llrender/llshadermgr.cpp
+++ b/indra/llrender/llshadermgr.cpp
@@ -1,25 +1,25 @@
-/**
+/**
* @file llshadermgr.cpp
* @brief Shader manager implementation.
*
* $LicenseInfo:firstyear=2005&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -57,90 +57,90 @@ LLShaderMgr::~LLShaderMgr()
// static
LLShaderMgr * LLShaderMgr::instance()
{
- if(NULL == sInstance)
- {
- LL_ERRS("Shaders") << "LLShaderMgr should already have been instantiated by the application!" << LL_ENDL;
- }
+ if(NULL == sInstance)
+ {
+ LL_ERRS("Shaders") << "LLShaderMgr should already have been instantiated by the application!" << LL_ENDL;
+ }
- return sInstance;
+ return sInstance;
}
BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
{
- llassert_always(shader != NULL);
- LLShaderFeatures *features = & shader->mFeatures;
-
- if (features->attachNothing)
- {
- return TRUE;
- }
- //////////////////////////////////////
- // Attach Vertex Shader Features First
- //////////////////////////////////////
-
- // NOTE order of shader object attaching is VERY IMPORTANT!!!
- if (features->calculatesAtmospherics)
- {
- if (!shader->attachVertexObject("windlight/atmosphericsVarsV.glsl"))
- {
- return FALSE;
- }
- }
-
- if (features->calculatesLighting || features->calculatesAtmospherics)
- {
- if (!shader->attachVertexObject("windlight/atmosphericsHelpersV.glsl"))
- {
- return FALSE;
- }
- }
-
- if (features->calculatesLighting)
- {
- if (features->isSpecular)
- {
+ llassert_always(shader != NULL);
+ LLShaderFeatures *features = & shader->mFeatures;
+
+ if (features->attachNothing)
+ {
+ return TRUE;
+ }
+ //////////////////////////////////////
+ // Attach Vertex Shader Features First
+ //////////////////////////////////////
+
+ // NOTE order of shader object attaching is VERY IMPORTANT!!!
+ if (features->calculatesAtmospherics)
+ {
+ if (!shader->attachVertexObject("windlight/atmosphericsVarsV.glsl"))
+ {
+ return FALSE;
+ }
+ }
+
+ if (features->calculatesLighting || features->calculatesAtmospherics)
+ {
+ if (!shader->attachVertexObject("windlight/atmosphericsHelpersV.glsl"))
+ {
+ return FALSE;
+ }
+ }
+
+ if (features->calculatesLighting)
+ {
+ if (features->isSpecular)
+ {
if (!shader->attachVertexObject("lighting/lightFuncSpecularV.glsl"))
- {
- return FALSE;
- }
-
- if (!features->isAlphaLighting)
- {
+ {
+ return FALSE;
+ }
+
+ if (!features->isAlphaLighting)
+ {
if (!shader->attachVertexObject("lighting/sumLightsSpecularV.glsl"))
- {
- return FALSE;
- }
- }
-
+ {
+ return FALSE;
+ }
+ }
+
if (!shader->attachVertexObject("lighting/lightSpecularV.glsl"))
- {
- return FALSE;
- }
- }
- else
- {
+ {
+ return FALSE;
+ }
+ }
+ else
+ {
if (!shader->attachVertexObject("lighting/lightFuncV.glsl"))
- {
- return FALSE;
- }
-
- if (!features->isAlphaLighting)
- {
+ {
+ return FALSE;
+ }
+
+ if (!features->isAlphaLighting)
+ {
if (!shader->attachVertexObject("lighting/sumLightsV.glsl"))
- {
- return FALSE;
- }
- }
-
+ {
+ return FALSE;
+ }
+ }
+
if (!shader->attachVertexObject("lighting/lightV.glsl"))
- {
- return FALSE;
- }
- }
- }
-
- // NOTE order of shader object attaching is VERY IMPORTANT!!!
- if (features->calculatesAtmospherics)
+ {
+ return FALSE;
+ }
+ }
+ }
+
+ // NOTE order of shader object attaching is VERY IMPORTANT!!!
+ if (features->calculatesAtmospherics)
{
if (!shader->attachVertexObject("environment/srgbF.glsl")) // NOTE -- "F" suffix is superfluous here, there is nothing fragment specific in srgbF
{
@@ -152,36 +152,36 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
}
if (!shader->attachVertexObject("windlight/atmosphericsV.glsl"))
- {
- return FALSE;
- }
- }
+ {
+ return FALSE;
+ }
+ }
- if (features->hasSkinning)
- {
+ if (features->hasSkinning)
+ {
if (!shader->attachVertexObject("avatar/avatarSkinV.glsl"))
- {
- return FALSE;
- }
- }
+ {
+ return FALSE;
+ }
+ }
- if (features->hasObjectSkinning)
- {
+ if (features->hasObjectSkinning)
+ {
shader->mRiggedVariant = shader;
if (!shader->attachVertexObject("avatar/objectSkinV.glsl"))
- {
- return FALSE;
- }
- }
+ {
+ return FALSE;
+ }
+ }
if (!shader->attachVertexObject("deferred/textureUtilV.glsl"))
{
return FALSE;
}
-
- ///////////////////////////////////////
- // Attach Fragment Shader Features Next
- ///////////////////////////////////////
+
+ ///////////////////////////////////////
+ // Attach Fragment Shader Features Next
+ ///////////////////////////////////////
// NOTE order of shader object attaching is VERY IMPORTANT!!!
if (features->hasSrgb || features->hasAtmospherics || features->calculatesAtmospherics || features->isDeferred)
@@ -192,46 +192,46 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
}
}
- if(features->calculatesAtmospherics || features->hasGamma || features->isDeferred)
- {
- if (!shader->attachFragmentObject("windlight/atmosphericsVarsF.glsl"))
- {
- return FALSE;
- }
- }
+ if(features->calculatesAtmospherics || features->hasGamma || features->isDeferred)
+ {
+ if (!shader->attachFragmentObject("windlight/atmosphericsVarsF.glsl"))
+ {
+ return FALSE;
+ }
+ }
if (features->calculatesLighting || features->calculatesAtmospherics)
- {
+ {
if (!shader->attachFragmentObject("windlight/atmosphericsHelpersF.glsl"))
- {
- return FALSE;
- }
- }
+ {
+ return FALSE;
+ }
+ }
// we want this BEFORE shadows and AO because those facilities use pos/norm access
if (features->isDeferred || features->hasReflectionProbes)
- {
+ {
if (!shader->attachFragmentObject("deferred/deferredUtil.glsl"))
- {
- return FALSE;
- }
- }
+ {
+ return FALSE;
+ }
+ }
- if (features->hasScreenSpaceReflections || features->hasReflectionProbes)
- {
+ if (features->hasScreenSpaceReflections || features->hasReflectionProbes)
+ {
if (!shader->attachFragmentObject("deferred/screenSpaceReflUtil.glsl"))
{
return FALSE;
}
- }
+ }
if (features->hasShadows)
- {
+ {
if (!shader->attachFragmentObject("deferred/shadowUtil.glsl"))
- {
- return FALSE;
- }
- }
+ {
+ return FALSE;
+ }
+ }
if (features->hasReflectionProbes)
{
@@ -242,105 +242,105 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
}
if (features->hasAmbientOcclusion)
- {
+ {
if (!shader->attachFragmentObject("deferred/aoUtil.glsl"))
- {
- return FALSE;
- }
- }
+ {
+ return FALSE;
+ }
+ }
- if (features->hasGamma || features->isDeferred)
- {
+ if (features->hasGamma || features->isDeferred)
+ {
if (!shader->attachFragmentObject("windlight/gammaF.glsl"))
- {
- return FALSE;
- }
- }
+ {
+ return FALSE;
+ }
+ }
if (features->encodesNormal)
- {
+ {
if (!shader->attachFragmentObject("environment/encodeNormF.glsl"))
- {
- return FALSE;
- }
- }
+ {
+ return FALSE;
+ }
+ }
- if (features->hasAtmospherics || features->isDeferred)
+ if (features->hasAtmospherics || features->isDeferred)
{
if (!shader->attachFragmentObject("windlight/atmosphericsFuncs.glsl")) {
return FALSE;
}
if (!shader->attachFragmentObject("windlight/atmosphericsF.glsl"))
- {
- return FALSE;
- }
- }
-
- // NOTE order of shader object attaching is VERY IMPORTANT!!!
- if (features->hasAtmospherics)
- {
+ {
+ return FALSE;
+ }
+ }
+
+ // NOTE order of shader object attaching is VERY IMPORTANT!!!
+ if (features->hasAtmospherics)
+ {
if (!shader->attachFragmentObject("environment/waterFogF.glsl"))
- {
- return FALSE;
- }
- }
-
- if (features->hasLighting)
- {
- if (features->disableTextureIndex)
- {
- if (features->hasAlphaMask)
- {
+ {
+ return FALSE;
+ }
+ }
+
+ if (features->hasLighting)
+ {
+ if (features->disableTextureIndex)
+ {
+ if (features->hasAlphaMask)
+ {
if (!shader->attachFragmentObject("lighting/lightAlphaMaskNonIndexedF.glsl"))
- {
- return FALSE;
- }
- }
- else
- {
+ {
+ return FALSE;
+ }
+ }
+ else
+ {
if (!shader->attachFragmentObject("lighting/lightNonIndexedF.glsl"))
- {
- return FALSE;
- }
- }
- }
- else
- {
- if (features->hasAlphaMask)
- {
+ {
+ return FALSE;
+ }
+ }
+ }
+ else
+ {
+ if (features->hasAlphaMask)
+ {
if (!shader->attachFragmentObject("lighting/lightAlphaMaskF.glsl"))
- {
- return FALSE;
- }
- }
- else
- {
+ {
+ return FALSE;
+ }
+ }
+ else
+ {
if (!shader->attachFragmentObject("lighting/lightF.glsl"))
- {
- return FALSE;
- }
- }
- shader->mFeatures.mIndexedTextureChannels = llmax(LLGLSLShader::sIndexedTextureChannels-1, 1);
- }
- }
-
- if (features->mIndexedTextureChannels <= 1)
- {
- if (!shader->attachVertexObject("objects/nonindexedTextureV.glsl"))
- {
- return FALSE;
- }
- }
- else
- {
+ {
+ return FALSE;
+ }
+ }
+ shader->mFeatures.mIndexedTextureChannels = llmax(LLGLSLShader::sIndexedTextureChannels-1, 1);
+ }
+ }
+
+ if (features->mIndexedTextureChannels <= 1)
+ {
+ if (!shader->attachVertexObject("objects/nonindexedTextureV.glsl"))
+ {
+ return FALSE;
+ }
+ }
+ else
+ {
if (!shader->attachVertexObject("objects/indexedTextureV.glsl"))
- {
- return FALSE;
- }
- }
+ {
+ return FALSE;
+ }
+ }
- return TRUE;
+ return TRUE;
}
//============================================================================
@@ -348,20 +348,20 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
static std::string get_shader_log(GLuint ret)
{
- std::string res;
-
- //get log length
- GLint length;
+ std::string res;
+
+ //get log length
+ GLint length;
glGetShaderiv(ret, GL_INFO_LOG_LENGTH, &length);
- if (length > 0)
- {
- //the log could be any size, so allocate appropriately
- GLchar* log = new GLchar[length];
+ if (length > 0)
+ {
+ //the log could be any size, so allocate appropriately
+ GLchar* log = new GLchar[length];
glGetShaderInfoLog(ret, length, &length, log);
- res = std::string((char *)log);
- delete[] log;
- }
- return res;
+ res = std::string((char *)log);
+ delete[] log;
+ }
+ return res;
}
static std::string get_program_log(GLuint ret)
@@ -369,7 +369,7 @@ static std::string get_program_log(GLuint ret)
LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
std::string res;
- //get log length
+ //get log length
GLint length;
glGetProgramiv(ret, GL_INFO_LOG_LENGTH, &length);
if (length > 0)
@@ -401,16 +401,16 @@ static std::string get_object_log(GLuint ret)
//dump shader source for debugging
void LLShaderMgr::dumpShaderSource(U32 shader_code_count, GLchar** shader_code_text)
{
- char num_str[16]; // U32 = max 10 digits
+ char num_str[16]; // U32 = max 10 digits
- LL_SHADER_LOADING_WARNS() << "\n";
+ LL_SHADER_LOADING_WARNS() << "\n";
- for (U32 i = 0; i < shader_code_count; i++)
- {
- snprintf(num_str, sizeof(num_str), "%4d: ", i+1);
- std::string line_number(num_str);
- LL_CONT << line_number << shader_code_text[i];
- }
+ for (U32 i = 0; i < shader_code_count; i++)
+ {
+ snprintf(num_str, sizeof(num_str), "%4d: ", i+1);
+ std::string line_number(num_str);
+ LL_CONT << line_number << shader_code_text[i];
+ }
LL_CONT << LL_ENDL;
}
@@ -424,11 +424,11 @@ void LLShaderMgr::dumpObjectLog(GLuint ret, BOOL warns, const std::string& filen
fname = "unknown shader file";
}
- if (log.length() > 0)
- {
+ if (log.length() > 0)
+ {
LL_SHADER_LOADING_WARNS() << "Shader loading from " << fname << LL_ENDL;
LL_SHADER_LOADING_WARNS() << "\n" << log << LL_ENDL;
- }
+ }
}
GLuint LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_level, GLenum type, std::map<std::string, std::string>* defines, S32 texture_index_channels)
@@ -442,25 +442,25 @@ GLuint LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_lev
}
#endif
- GLenum error = GL_NO_ERROR;
+ GLenum error = GL_NO_ERROR;
+
+ error = glGetError();
+ if (error != GL_NO_ERROR)
+ {
+ LL_SHADER_LOADING_WARNS() << "GL ERROR entering loadShaderFile(): " << error << " for file: " << filename << LL_ENDL;
+ }
- error = glGetError();
- if (error != GL_NO_ERROR)
- {
- LL_SHADER_LOADING_WARNS() << "GL ERROR entering loadShaderFile(): " << error << " for file: " << filename << LL_ENDL;
- }
-
- if (filename.empty())
- {
- return 0;
- }
+ if (filename.empty())
+ {
+ return 0;
+ }
- //read in from file
- LLFILE* file = NULL;
+ //read in from file
+ LLFILE* file = NULL;
- S32 try_gpu_class = shader_level;
- S32 gpu_class;
+ S32 try_gpu_class = shader_level;
+ S32 gpu_class;
std::string open_file_name;
@@ -485,7 +485,7 @@ GLuint LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_lev
{
//find the most relevant file
for (gpu_class = try_gpu_class; gpu_class > 0; gpu_class--)
- { //search from the current gpu class down to class 1 to find the most relevant shader
+ { //search from the current gpu class down to class 1 to find the most relevant shader
std::stringstream fname;
fname << getShaderDirPrefix();
fname << gpu_class << "/" << filename;
@@ -506,7 +506,7 @@ GLuint LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_lev
*/
LL_DEBUGS("ShaderLoading") << "Looking in " << open_file_name << LL_ENDL;
- file = LLFile::fopen(open_file_name, "r"); /* Flawfinder: ignore */
+ file = LLFile::fopen(open_file_name, "r"); /* Flawfinder: ignore */
if (file)
{
LL_DEBUGS("ShaderLoading") << "Loading file: " << open_file_name << " (Want class " << gpu_class << ")" << LL_ENDL;
@@ -514,31 +514,31 @@ GLuint LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_lev
}
}
}
-
- if (file == NULL)
- {
- LL_WARNS("ShaderLoading") << "GLSL Shader file not found: " << open_file_name << LL_ENDL;
- return 0;
- }
-
- //we can't have any lines longer than 1024 characters
- //or any shaders longer than 4096 lines... deal - DaveP
+
+ if (file == NULL)
+ {
+ LL_WARNS("ShaderLoading") << "GLSL Shader file not found: " << open_file_name << LL_ENDL;
+ return 0;
+ }
+
+ //we can't have any lines longer than 1024 characters
+ //or any shaders longer than 4096 lines... deal - DaveP
GLchar buff[1024];
GLchar *extra_code_text[1024];
GLchar *shader_code_text[4096 + LL_ARRAY_SIZE(extra_code_text)] = { NULL };
GLuint extra_code_count = 0, shader_code_count = 0;
BOOST_STATIC_ASSERT(LL_ARRAY_SIZE(extra_code_text) < LL_ARRAY_SIZE(shader_code_text));
-
-
- S32 major_version = gGLManager.mGLSLVersionMajor;
- S32 minor_version = gGLManager.mGLSLVersionMinor;
-
- if (major_version == 1 && minor_version < 30)
- {
+
+
+ S32 major_version = gGLManager.mGLSLVersionMajor;
+ S32 minor_version = gGLManager.mGLSLVersionMinor;
+
+ if (major_version == 1 && minor_version < 30)
+ {
llassert(false); // GL 3.1 or later required
- }
- else
- {
+ }
+ else
+ {
if (major_version >= 4)
{
//set version to 400 or 420
@@ -554,33 +554,33 @@ GLuint LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_lev
else if (major_version == 3)
{
if (minor_version < 10)
- {
- shader_code_text[shader_code_count++] = strdup("#version 300\n");
- }
- else if (minor_version <= 19)
- {
- shader_code_text[shader_code_count++] = strdup("#version 310\n");
- }
- else if (minor_version <= 29)
- {
- shader_code_text[shader_code_count++] = strdup("#version 320\n");
- }
+ {
+ shader_code_text[shader_code_count++] = strdup("#version 300\n");
+ }
+ else if (minor_version <= 19)
+ {
+ shader_code_text[shader_code_count++] = strdup("#version 310\n");
+ }
+ else if (minor_version <= 29)
+ {
+ shader_code_text[shader_code_count++] = strdup("#version 320\n");
+ }
else
{
shader_code_text[shader_code_count++] = strdup("#version 330\n");
}
}
- else
- {
- //set version to 1.40
- shader_code_text[shader_code_count++] = strdup("#version 140\n");
- //some implementations of GLSL 1.30 require integer precision be explicitly declared
- extra_code_text[extra_code_count++] = strdup("precision mediump int;\n");
- extra_code_text[extra_code_count++] = strdup("precision highp float;\n");
- }
-
- extra_code_text[extra_code_count++] = strdup("#define FXAA_GLSL_130 1\n");
- }
+ else
+ {
+ //set version to 1.40
+ shader_code_text[shader_code_count++] = strdup("#version 140\n");
+ //some implementations of GLSL 1.30 require integer precision be explicitly declared
+ extra_code_text[extra_code_count++] = strdup("precision mediump int;\n");
+ extra_code_text[extra_code_count++] = strdup("precision highp float;\n");
+ }
+
+ extra_code_text[extra_code_count++] = strdup("#define FXAA_GLSL_130 1\n");
+ }
// Use alpha float to store bit flags
// See: C++: addDeferredAttachment(), shader: frag_data[2]
@@ -589,125 +589,125 @@ GLuint LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_lev
extra_code_text[extra_code_count++] = strdup("#define GBUFFER_FLAG_HAS_PBR 0.67\n"); // bit 1
extra_code_text[extra_code_count++] = strdup("#define GET_GBUFFER_FLAG(flag) (abs(norm.w-flag)< 0.1)\n");
- if (defines)
- {
- for (auto iter = defines->begin(); iter != defines->end(); ++iter)
- {
- std::string define = "#define " + iter->first + " " + iter->second + "\n";
- extra_code_text[extra_code_count++] = (GLchar *) strdup(define.c_str());
- }
- }
-
- if( gGLManager.mIsAMD )
- {
- extra_code_text[extra_code_count++] = strdup( "#define IS_AMD_CARD 1\n" );
- }
-
- if (texture_index_channels > 0 && type == GL_FRAGMENT_SHADER)
- {
- //use specified number of texture channels for indexed texture rendering
-
- /* prepend shader code that looks like this:
-
- uniform sampler2D tex0;
- uniform sampler2D tex1;
- uniform sampler2D tex2;
- .
- .
- .
- uniform sampler2D texN;
-
- flat in int vary_texture_index;
-
- vec4 ret = vec4(1,0,1,1);
-
- vec4 diffuseLookup(vec2 texcoord)
- {
- switch (vary_texture_index)
- {
- case 0: ret = texture(tex0, texcoord); break;
- case 1: ret = texture(tex1, texcoord); break;
- case 2: ret = texture(tex2, texcoord); break;
- .
- .
- .
- case N: return texture(texN, texcoord); break;
- }
-
- return ret;
- }
- */
-
- extra_code_text[extra_code_count++] = strdup("#define HAS_DIFFUSE_LOOKUP\n");
-
- //uniform declartion
- for (S32 i = 0; i < texture_index_channels; ++i)
- {
- std::string decl = llformat("uniform sampler2D tex%d;\n", i);
- extra_code_text[extra_code_count++] = strdup(decl.c_str());
- }
-
- if (texture_index_channels > 1)
- {
- extra_code_text[extra_code_count++] = strdup("flat in int vary_texture_index;\n");
- }
-
- extra_code_text[extra_code_count++] = strdup("vec4 diffuseLookup(vec2 texcoord)\n");
- extra_code_text[extra_code_count++] = strdup("{\n");
-
-
- if (texture_index_channels == 1)
- { //don't use flow control, that's silly
- extra_code_text[extra_code_count++] = strdup("return texture(tex0, texcoord);\n");
- extra_code_text[extra_code_count++] = strdup("}\n");
- }
- else if (major_version > 1 || minor_version >= 30)
- { //switches are supported in GLSL 1.30 and later
- if (gGLManager.mIsNVIDIA)
- { //switches are unreliable on some NVIDIA drivers
- for (U32 i = 0; i < texture_index_channels; ++i)
- {
- std::string if_string = llformat("\t%sif (vary_texture_index == %d) { return texture(tex%d, texcoord); }\n", i > 0 ? "else " : "", i, i);
- extra_code_text[extra_code_count++] = strdup(if_string.c_str());
- }
- extra_code_text[extra_code_count++] = strdup("\treturn vec4(1,0,1,1);\n");
- extra_code_text[extra_code_count++] = strdup("}\n");
- }
- else
- {
- extra_code_text[extra_code_count++] = strdup("\tvec4 ret = vec4(1,0,1,1);\n");
- extra_code_text[extra_code_count++] = strdup("\tswitch (vary_texture_index)\n");
- extra_code_text[extra_code_count++] = strdup("\t{\n");
-
- //switch body
- for (S32 i = 0; i < texture_index_channels; ++i)
- {
- std::string case_str = llformat("\t\tcase %d: return texture(tex%d, texcoord);\n", i, i);
- extra_code_text[extra_code_count++] = strdup(case_str.c_str());
- }
-
- extra_code_text[extra_code_count++] = strdup("\t}\n");
- extra_code_text[extra_code_count++] = strdup("\treturn ret;\n");
- extra_code_text[extra_code_count++] = strdup("}\n");
- }
- }
- else
- { //should never get here. Indexed texture rendering requires GLSL 1.30 or later
- // (for passing integers between vertex and fragment shaders)
- LL_ERRS() << "Indexed texture rendering requires GLSL 1.30 or later." << LL_ENDL;
- }
- }
-
- //copy file into memory
- enum {
- flag_write_to_out_of_extra_block_area = 0x01
- , flag_extra_block_marker_was_found = 0x02
- };
-
- unsigned char flags = flag_write_to_out_of_extra_block_area;
-
- GLuint out_of_extra_block_counter = 0, start_shader_code = shader_code_count, file_lines_count = 0;
-
+ if (defines)
+ {
+ for (auto iter = defines->begin(); iter != defines->end(); ++iter)
+ {
+ std::string define = "#define " + iter->first + " " + iter->second + "\n";
+ extra_code_text[extra_code_count++] = (GLchar *) strdup(define.c_str());
+ }
+ }
+
+ if( gGLManager.mIsAMD )
+ {
+ extra_code_text[extra_code_count++] = strdup( "#define IS_AMD_CARD 1\n" );
+ }
+
+ if (texture_index_channels > 0 && type == GL_FRAGMENT_SHADER)
+ {
+ //use specified number of texture channels for indexed texture rendering
+
+ /* prepend shader code that looks like this:
+
+ uniform sampler2D tex0;
+ uniform sampler2D tex1;
+ uniform sampler2D tex2;
+ .
+ .
+ .
+ uniform sampler2D texN;
+
+ flat in int vary_texture_index;
+
+ vec4 ret = vec4(1,0,1,1);
+
+ vec4 diffuseLookup(vec2 texcoord)
+ {
+ switch (vary_texture_index)
+ {
+ case 0: ret = texture(tex0, texcoord); break;
+ case 1: ret = texture(tex1, texcoord); break;
+ case 2: ret = texture(tex2, texcoord); break;
+ .
+ .
+ .
+ case N: return texture(texN, texcoord); break;
+ }
+
+ return ret;
+ }
+ */
+
+ extra_code_text[extra_code_count++] = strdup("#define HAS_DIFFUSE_LOOKUP\n");
+
+ //uniform declartion
+ for (S32 i = 0; i < texture_index_channels; ++i)
+ {
+ std::string decl = llformat("uniform sampler2D tex%d;\n", i);
+ extra_code_text[extra_code_count++] = strdup(decl.c_str());
+ }
+
+ if (texture_index_channels > 1)
+ {
+ extra_code_text[extra_code_count++] = strdup("flat in int vary_texture_index;\n");
+ }
+
+ extra_code_text[extra_code_count++] = strdup("vec4 diffuseLookup(vec2 texcoord)\n");
+ extra_code_text[extra_code_count++] = strdup("{\n");
+
+
+ if (texture_index_channels == 1)
+ { //don't use flow control, that's silly
+ extra_code_text[extra_code_count++] = strdup("return texture(tex0, texcoord);\n");
+ extra_code_text[extra_code_count++] = strdup("}\n");
+ }
+ else if (major_version > 1 || minor_version >= 30)
+ { //switches are supported in GLSL 1.30 and later
+ if (gGLManager.mIsNVIDIA)
+ { //switches are unreliable on some NVIDIA drivers
+ for (U32 i = 0; i < texture_index_channels; ++i)
+ {
+ std::string if_string = llformat("\t%sif (vary_texture_index == %d) { return texture(tex%d, texcoord); }\n", i > 0 ? "else " : "", i, i);
+ extra_code_text[extra_code_count++] = strdup(if_string.c_str());
+ }
+ extra_code_text[extra_code_count++] = strdup("\treturn vec4(1,0,1,1);\n");
+ extra_code_text[extra_code_count++] = strdup("}\n");
+ }
+ else
+ {
+ extra_code_text[extra_code_count++] = strdup("\tvec4 ret = vec4(1,0,1,1);\n");
+ extra_code_text[extra_code_count++] = strdup("\tswitch (vary_texture_index)\n");
+ extra_code_text[extra_code_count++] = strdup("\t{\n");
+
+ //switch body
+ for (S32 i = 0; i < texture_index_channels; ++i)
+ {
+ std::string case_str = llformat("\t\tcase %d: return texture(tex%d, texcoord);\n", i, i);
+ extra_code_text[extra_code_count++] = strdup(case_str.c_str());
+ }
+
+ extra_code_text[extra_code_count++] = strdup("\t}\n");
+ extra_code_text[extra_code_count++] = strdup("\treturn ret;\n");
+ extra_code_text[extra_code_count++] = strdup("}\n");
+ }
+ }
+ else
+ { //should never get here. Indexed texture rendering requires GLSL 1.30 or later
+ // (for passing integers between vertex and fragment shaders)
+ LL_ERRS() << "Indexed texture rendering requires GLSL 1.30 or later." << LL_ENDL;
+ }
+ }
+
+ //copy file into memory
+ enum {
+ flag_write_to_out_of_extra_block_area = 0x01
+ , flag_extra_block_marker_was_found = 0x02
+ };
+
+ unsigned char flags = flag_write_to_out_of_extra_block_area;
+
+ GLuint out_of_extra_block_counter = 0, start_shader_code = shader_code_count, file_lines_count = 0;
+
#define TOUCH_SHADERS 0
#if TOUCH_SHADERS
@@ -715,13 +715,13 @@ GLuint LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_lev
bool touched = false;
#endif
- while(NULL != fgets((char *)buff, 1024, file)
- && shader_code_count < (LL_ARRAY_SIZE(shader_code_text) - LL_ARRAY_SIZE(extra_code_text)))
- {
- file_lines_count++;
+ while(NULL != fgets((char *)buff, 1024, file)
+ && shader_code_count < (LL_ARRAY_SIZE(shader_code_text) - LL_ARRAY_SIZE(extra_code_text)))
+ {
+ file_lines_count++;
+
+ bool extra_block_area_found = NULL != strstr((const char*)buff, "[EXTRA_CODE_HERE]");
- bool extra_block_area_found = NULL != strstr((const char*)buff, "[EXTRA_CODE_HERE]");
-
#if TOUCH_SHADERS
if (NULL != strstr((const char*)buff, marker))
{
@@ -729,67 +729,67 @@ GLuint LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_lev
}
#endif
- if(extra_block_area_found && !(flag_extra_block_marker_was_found & flags))
- {
- if(!(flag_write_to_out_of_extra_block_area & flags))
- {
- //shift
- for(GLuint to = start_shader_code, from = extra_code_count + start_shader_code;
- from < shader_code_count; ++to, ++from)
- {
- shader_code_text[to] = shader_code_text[from];
- }
-
- shader_code_count -= extra_code_count;
- }
-
- //copy extra code
- for(GLuint n = 0; n < extra_code_count
- && shader_code_count < (LL_ARRAY_SIZE(shader_code_text) - LL_ARRAY_SIZE(extra_code_text)); ++n)
- {
- shader_code_text[shader_code_count++] = extra_code_text[n];
- }
-
- extra_code_count = 0;
-
- flags &= ~flag_write_to_out_of_extra_block_area;
- flags |= flag_extra_block_marker_was_found;
- }
+ if(extra_block_area_found && !(flag_extra_block_marker_was_found & flags))
+ {
+ if(!(flag_write_to_out_of_extra_block_area & flags))
+ {
+ //shift
+ for(GLuint to = start_shader_code, from = extra_code_count + start_shader_code;
+ from < shader_code_count; ++to, ++from)
+ {
+ shader_code_text[to] = shader_code_text[from];
+ }
+
+ shader_code_count -= extra_code_count;
+ }
+
+ //copy extra code
+ for(GLuint n = 0; n < extra_code_count
+ && shader_code_count < (LL_ARRAY_SIZE(shader_code_text) - LL_ARRAY_SIZE(extra_code_text)); ++n)
+ {
+ shader_code_text[shader_code_count++] = extra_code_text[n];
+ }
+
+ extra_code_count = 0;
+
+ flags &= ~flag_write_to_out_of_extra_block_area;
+ flags |= flag_extra_block_marker_was_found;
+ }
else
{
shader_code_text[shader_code_count] = (GLchar *)strdup((char *)buff);
-
+
if(flag_write_to_out_of_extra_block_area & flags)
{
shader_code_text[extra_code_count + start_shader_code + out_of_extra_block_counter]
= shader_code_text[shader_code_count];
out_of_extra_block_counter++;
-
+
if(out_of_extra_block_counter == extra_code_count)
{
shader_code_count += extra_code_count;
flags &= ~flag_write_to_out_of_extra_block_area;
}
}
-
+
++shader_code_count;
- }
- } //while
-
- if(!(flag_extra_block_marker_was_found & flags))
- {
- for(GLuint n = start_shader_code; n < extra_code_count + start_shader_code; ++n)
- {
- shader_code_text[n] = extra_code_text[n - start_shader_code];
- }
-
- if (file_lines_count < extra_code_count)
- {
- shader_code_count += extra_code_count;
- }
-
- extra_code_count = 0;
- }
+ }
+ } //while
+
+ if(!(flag_extra_block_marker_was_found & flags))
+ {
+ for(GLuint n = start_shader_code; n < extra_code_count + start_shader_code; ++n)
+ {
+ shader_code_text[n] = extra_code_text[n - start_shader_code];
+ }
+
+ if (file_lines_count < extra_code_count)
+ {
+ shader_code_count += extra_code_count;
+ }
+
+ extra_code_count = 0;
+ }
#if TOUCH_SHADERS
if (!touched)
@@ -798,106 +798,106 @@ GLuint LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_lev
}
#endif
- fclose(file);
+ fclose(file);
- //create shader object
+ //create shader object
GLuint ret = glCreateShader(type);
- error = glGetError();
- if (error != GL_NO_ERROR)
- {
- LL_WARNS("ShaderLoading") << "GL ERROR in glCreateShader: " << error << " for file: " << open_file_name << LL_ENDL;
- if (ret)
- {
- glDeleteShader(ret); //no longer need handle
- ret = 0;
- }
- }
-
- //load source
- if (ret)
- {
- glShaderSource(ret, shader_code_count, (const GLchar**)shader_code_text, NULL);
-
- error = glGetError();
- if (error != GL_NO_ERROR)
- {
- LL_WARNS("ShaderLoading") << "GL ERROR in glShaderSource: " << error << " for file: " << open_file_name << LL_ENDL;
- glDeleteShader(ret); //no longer need handle
- ret = 0;
- }
- }
-
- //compile source
- if (ret)
- {
- glCompileShader(ret);
-
- error = glGetError();
- if (error != GL_NO_ERROR)
- {
- LL_WARNS("ShaderLoading") << "GL ERROR in glCompileShader: " << error << " for file: " << open_file_name << LL_ENDL;
- glDeleteShader(ret); //no longer need handle
- ret = 0;
- }
- }
-
- if (error == GL_NO_ERROR)
- {
- //check for errors
- GLint success = GL_TRUE;
+ error = glGetError();
+ if (error != GL_NO_ERROR)
+ {
+ LL_WARNS("ShaderLoading") << "GL ERROR in glCreateShader: " << error << " for file: " << open_file_name << LL_ENDL;
+ if (ret)
+ {
+ glDeleteShader(ret); //no longer need handle
+ ret = 0;
+ }
+ }
+
+ //load source
+ if (ret)
+ {
+ glShaderSource(ret, shader_code_count, (const GLchar**)shader_code_text, NULL);
+
+ error = glGetError();
+ if (error != GL_NO_ERROR)
+ {
+ LL_WARNS("ShaderLoading") << "GL ERROR in glShaderSource: " << error << " for file: " << open_file_name << LL_ENDL;
+ glDeleteShader(ret); //no longer need handle
+ ret = 0;
+ }
+ }
+
+ //compile source
+ if (ret)
+ {
+ glCompileShader(ret);
+
+ error = glGetError();
+ if (error != GL_NO_ERROR)
+ {
+ LL_WARNS("ShaderLoading") << "GL ERROR in glCompileShader: " << error << " for file: " << open_file_name << LL_ENDL;
+ glDeleteShader(ret); //no longer need handle
+ ret = 0;
+ }
+ }
+
+ if (error == GL_NO_ERROR)
+ {
+ //check for errors
+ GLint success = GL_TRUE;
glGetShaderiv(ret, GL_COMPILE_STATUS, &success);
- error = glGetError();
- if (error != GL_NO_ERROR || success == GL_FALSE)
- {
- //an error occured, print log
- LL_WARNS("ShaderLoading") << "GLSL Compilation Error:" << LL_ENDL;
- dumpObjectLog(ret, TRUE, open_file_name);
- dumpShaderSource(shader_code_count, shader_code_text);
- glDeleteShader(ret); //no longer need handle
- ret = 0;
- }
- }
- else
- {
- ret = 0;
- }
- stop_glerror();
-
- //free memory
- for (GLuint i = 0; i < shader_code_count; i++)
- {
- free(shader_code_text[i]);
- }
-
- //successfully loaded, save results
- if (ret)
- {
- // Add shader file to map
+ error = glGetError();
+ if (error != GL_NO_ERROR || success == GL_FALSE)
+ {
+ //an error occured, print log
+ LL_WARNS("ShaderLoading") << "GLSL Compilation Error:" << LL_ENDL;
+ dumpObjectLog(ret, TRUE, open_file_name);
+ dumpShaderSource(shader_code_count, shader_code_text);
+ glDeleteShader(ret); //no longer need handle
+ ret = 0;
+ }
+ }
+ else
+ {
+ ret = 0;
+ }
+ stop_glerror();
+
+ //free memory
+ for (GLuint i = 0; i < shader_code_count; i++)
+ {
+ free(shader_code_text[i]);
+ }
+
+ //successfully loaded, save results
+ if (ret)
+ {
+ // Add shader file to map
if (type == GL_VERTEX_SHADER) {
mVertexShaderObjects[filename] = ret;
}
else if (type == GL_FRAGMENT_SHADER) {
mFragmentShaderObjects[filename] = ret;
}
- shader_level = try_gpu_class;
- }
- else
- {
- if (shader_level > 1)
- {
- shader_level--;
- return loadShaderFile(filename, shader_level, type, defines, texture_index_channels);
- }
- LL_WARNS("ShaderLoading") << "Failed to load " << filename << LL_ENDL;
- }
- return ret;
+ shader_level = try_gpu_class;
+ }
+ else
+ {
+ if (shader_level > 1)
+ {
+ shader_level--;
+ return loadShaderFile(filename, shader_level, type, defines, texture_index_channels);
+ }
+ LL_WARNS("ShaderLoading") << "Failed to load " << filename << LL_ENDL;
+ }
+ return ret;
}
BOOL LLShaderMgr::linkProgramObject(GLuint obj, BOOL suppress_errors)
{
- //check for errors
+ //check for errors
{
LL_PROFILE_ZONE_NAMED_CATEGORY_SHADER("glLinkProgram");
glLinkProgram(obj);
@@ -917,238 +917,238 @@ BOOL LLShaderMgr::linkProgramObject(GLuint obj, BOOL suppress_errors)
}
}
- std::string log = get_program_log(obj);
- LLStringUtil::toLower(log);
- if (log.find("software") != std::string::npos)
- {
- LL_SHADER_LOADING_WARNS() << "GLSL Linker: Running in Software:" << LL_ENDL;
- success = GL_FALSE;
- suppress_errors = FALSE;
- }
- return success;
+ std::string log = get_program_log(obj);
+ LLStringUtil::toLower(log);
+ if (log.find("software") != std::string::npos)
+ {
+ LL_SHADER_LOADING_WARNS() << "GLSL Linker: Running in Software:" << LL_ENDL;
+ success = GL_FALSE;
+ suppress_errors = FALSE;
+ }
+ return success;
}
BOOL LLShaderMgr::validateProgramObject(GLuint obj)
{
- //check program validity against current GL
- glValidateProgram(obj);
- GLint success = GL_TRUE;
+ //check program validity against current GL
+ glValidateProgram(obj);
+ GLint success = GL_TRUE;
glGetProgramiv(obj, GL_LINK_STATUS, &success);
- if (success == GL_FALSE)
- {
- LL_SHADER_LOADING_WARNS() << "GLSL program not valid: " << LL_ENDL;
- dumpObjectLog(obj);
- }
- else
- {
- dumpObjectLog(obj, FALSE);
- }
-
- return success;
+ if (success == GL_FALSE)
+ {
+ LL_SHADER_LOADING_WARNS() << "GLSL program not valid: " << LL_ENDL;
+ dumpObjectLog(obj);
+ }
+ else
+ {
+ dumpObjectLog(obj, FALSE);
+ }
+
+ return success;
}
void LLShaderMgr::initShaderCache(bool enabled, const LLUUID& old_cache_version, const LLUUID& current_cache_version)
{
- LL_INFOS() << "Initializing shader cache" << LL_ENDL;
-
- mShaderCacheEnabled = gGLManager.mGLVersion >= 4.09 && enabled;
-
- if(!mShaderCacheEnabled || mShaderCacheInitialized)
- return;
-
- mShaderCacheInitialized = true;
-
- mShaderCacheDir = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "shader_cache");
- LLFile::mkdir(mShaderCacheDir);
-
- {
- std::string meta_out_path = gDirUtilp->add(mShaderCacheDir, "shaderdata.llsd");
- if (gDirUtilp->fileExists(meta_out_path))
- {
- LL_INFOS() << "Loading shader cache metadata" << LL_ENDL;
-
- llifstream instream(meta_out_path);
- LLSD in_data;
- LLSDSerialize::fromNotation(in_data, instream, LLSDSerialize::SIZE_UNLIMITED);
- instream.close();
-
- if (old_cache_version == current_cache_version)
- {
- for (const auto& data_pair : llsd::inMap(in_data))
- {
- ProgramBinaryData binary_info = ProgramBinaryData();
- binary_info.mBinaryFormat = data_pair.second["binary_format"].asInteger();
- binary_info.mBinaryLength = data_pair.second["binary_size"].asInteger();
- binary_info.mLastUsedTime = data_pair.second["last_used"].asReal();
- mShaderBinaryCache.insert_or_assign(LLUUID(data_pair.first), binary_info);
- }
- }
- else
- {
- LL_INFOS() << "Shader cache version mismatch detected. Purging." << LL_ENDL;
- clearShaderCache();
- }
- }
- }
+ LL_INFOS() << "Initializing shader cache" << LL_ENDL;
+
+ mShaderCacheEnabled = gGLManager.mGLVersion >= 4.09 && enabled;
+
+ if(!mShaderCacheEnabled || mShaderCacheInitialized)
+ return;
+
+ mShaderCacheInitialized = true;
+
+ mShaderCacheDir = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "shader_cache");
+ LLFile::mkdir(mShaderCacheDir);
+
+ {
+ std::string meta_out_path = gDirUtilp->add(mShaderCacheDir, "shaderdata.llsd");
+ if (gDirUtilp->fileExists(meta_out_path))
+ {
+ LL_INFOS() << "Loading shader cache metadata" << LL_ENDL;
+
+ llifstream instream(meta_out_path);
+ LLSD in_data;
+ LLSDSerialize::fromNotation(in_data, instream, LLSDSerialize::SIZE_UNLIMITED);
+ instream.close();
+
+ if (old_cache_version == current_cache_version)
+ {
+ for (const auto& data_pair : llsd::inMap(in_data))
+ {
+ ProgramBinaryData binary_info = ProgramBinaryData();
+ binary_info.mBinaryFormat = data_pair.second["binary_format"].asInteger();
+ binary_info.mBinaryLength = data_pair.second["binary_size"].asInteger();
+ binary_info.mLastUsedTime = data_pair.second["last_used"].asReal();
+ mShaderBinaryCache.insert_or_assign(LLUUID(data_pair.first), binary_info);
+ }
+ }
+ else
+ {
+ LL_INFOS() << "Shader cache version mismatch detected. Purging." << LL_ENDL;
+ clearShaderCache();
+ }
+ }
+ }
}
void LLShaderMgr::clearShaderCache()
{
- std::string shader_cache = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "shader_cache");
- LL_INFOS() << "Removing shader cache at " << shader_cache << LL_ENDL;
- const std::string mask = "*";
- gDirUtilp->deleteFilesInDir(shader_cache, mask);
- mShaderBinaryCache.clear();
+ std::string shader_cache = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "shader_cache");
+ LL_INFOS() << "Removing shader cache at " << shader_cache << LL_ENDL;
+ const std::string mask = "*";
+ gDirUtilp->deleteFilesInDir(shader_cache, mask);
+ mShaderBinaryCache.clear();
}
void LLShaderMgr::persistShaderCacheMetadata()
{
- if(!mShaderCacheEnabled) return;
-
- LL_INFOS() << "Persisting shader cache metadata to disk" << LL_ENDL;
-
- LLSD out = LLSD::emptyMap();
-
- static const F32 LRU_TIME = (60.f * 60.f) * 24.f * 7.f; // 14 days
- const F32 current_time = LLTimer::getTotalSeconds();
- for (auto it = mShaderBinaryCache.begin(); it != mShaderBinaryCache.end();)
- {
- const ProgramBinaryData& shader_metadata = it->second;
- if ((shader_metadata.mLastUsedTime + LRU_TIME) < current_time)
- {
- std::string shader_path = gDirUtilp->add(mShaderCacheDir, it->first.asString() + ".shaderbin");
- LLFile::remove(shader_path);
- it = mShaderBinaryCache.erase(it);
- }
- else
- {
- LLSD data = LLSD::emptyMap();
- data["binary_format"] = LLSD::Integer(shader_metadata.mBinaryFormat);
- data["binary_size"] = LLSD::Integer(shader_metadata.mBinaryLength);
- data["last_used"] = LLSD::Real(shader_metadata.mLastUsedTime);
- out[it->first.asString()] = data;
- ++it;
- }
- }
-
- std::string meta_out_path = gDirUtilp->add(mShaderCacheDir, "shaderdata.llsd");
- llofstream outstream(meta_out_path);
- LLSDSerialize::toNotation(out, outstream);
- outstream.close();
+ if(!mShaderCacheEnabled) return;
+
+ LL_INFOS() << "Persisting shader cache metadata to disk" << LL_ENDL;
+
+ LLSD out = LLSD::emptyMap();
+
+ static const F32 LRU_TIME = (60.f * 60.f) * 24.f * 7.f; // 14 days
+ const F32 current_time = LLTimer::getTotalSeconds();
+ for (auto it = mShaderBinaryCache.begin(); it != mShaderBinaryCache.end();)
+ {
+ const ProgramBinaryData& shader_metadata = it->second;
+ if ((shader_metadata.mLastUsedTime + LRU_TIME) < current_time)
+ {
+ std::string shader_path = gDirUtilp->add(mShaderCacheDir, it->first.asString() + ".shaderbin");
+ LLFile::remove(shader_path);
+ it = mShaderBinaryCache.erase(it);
+ }
+ else
+ {
+ LLSD data = LLSD::emptyMap();
+ data["binary_format"] = LLSD::Integer(shader_metadata.mBinaryFormat);
+ data["binary_size"] = LLSD::Integer(shader_metadata.mBinaryLength);
+ data["last_used"] = LLSD::Real(shader_metadata.mLastUsedTime);
+ out[it->first.asString()] = data;
+ ++it;
+ }
+ }
+
+ std::string meta_out_path = gDirUtilp->add(mShaderCacheDir, "shaderdata.llsd");
+ llofstream outstream(meta_out_path);
+ LLSDSerialize::toNotation(out, outstream);
+ outstream.close();
}
bool LLShaderMgr::loadCachedProgramBinary(LLGLSLShader* shader)
{
- if (!mShaderCacheEnabled) return false;
-
- glProgramParameteri(shader->mProgramObject, GL_PROGRAM_BINARY_RETRIEVABLE_HINT, GL_TRUE);
-
- auto binary_iter = mShaderBinaryCache.find(shader->mShaderHash);
- if (binary_iter != mShaderBinaryCache.end())
- {
- std::string in_path = gDirUtilp->add(mShaderCacheDir, shader->mShaderHash.asString() + ".shaderbin");
- auto& shader_info = binary_iter->second;
- if (shader_info.mBinaryLength > 0)
- {
- std::vector<U8> in_data;
- in_data.resize(shader_info.mBinaryLength);
-
- LLUniqueFile filep = LLFile::fopen(in_path, "rb");
- if (filep)
- {
- size_t result = fread(in_data.data(), sizeof(U8), in_data.size(), filep);
- filep.close();
-
- if (result == in_data.size())
- {
- GLenum error = glGetError(); // Clear current error
- glProgramBinary(shader->mProgramObject, shader_info.mBinaryFormat, in_data.data(), shader_info.mBinaryLength);
-
- error = glGetError();
- GLint success = GL_TRUE;
- glGetProgramiv(shader->mProgramObject, GL_LINK_STATUS, &success);
- if (error == GL_NO_ERROR && success == GL_TRUE)
- {
- binary_iter->second.mLastUsedTime = LLTimer::getTotalSeconds();
- LL_INFOS() << "Loaded cached binary for shader: " << shader->mName << LL_ENDL;
- return true;
- }
- }
- }
- }
- //an error occured, normally we would print log but in this case it means the shader needs recompiling.
- LL_INFOS() << "Failed to load cached binary for shader: " << shader->mName << " falling back to compilation" << LL_ENDL;
- LLFile::remove(in_path);
- mShaderBinaryCache.erase(binary_iter);
- }
- return false;
+ if (!mShaderCacheEnabled) return false;
+
+ glProgramParameteri(shader->mProgramObject, GL_PROGRAM_BINARY_RETRIEVABLE_HINT, GL_TRUE);
+
+ auto binary_iter = mShaderBinaryCache.find(shader->mShaderHash);
+ if (binary_iter != mShaderBinaryCache.end())
+ {
+ std::string in_path = gDirUtilp->add(mShaderCacheDir, shader->mShaderHash.asString() + ".shaderbin");
+ auto& shader_info = binary_iter->second;
+ if (shader_info.mBinaryLength > 0)
+ {
+ std::vector<U8> in_data;
+ in_data.resize(shader_info.mBinaryLength);
+
+ LLUniqueFile filep = LLFile::fopen(in_path, "rb");
+ if (filep)
+ {
+ size_t result = fread(in_data.data(), sizeof(U8), in_data.size(), filep);
+ filep.close();
+
+ if (result == in_data.size())
+ {
+ GLenum error = glGetError(); // Clear current error
+ glProgramBinary(shader->mProgramObject, shader_info.mBinaryFormat, in_data.data(), shader_info.mBinaryLength);
+
+ error = glGetError();
+ GLint success = GL_TRUE;
+ glGetProgramiv(shader->mProgramObject, GL_LINK_STATUS, &success);
+ if (error == GL_NO_ERROR && success == GL_TRUE)
+ {
+ binary_iter->second.mLastUsedTime = LLTimer::getTotalSeconds();
+ LL_INFOS() << "Loaded cached binary for shader: " << shader->mName << LL_ENDL;
+ return true;
+ }
+ }
+ }
+ }
+ //an error occured, normally we would print log but in this case it means the shader needs recompiling.
+ LL_INFOS() << "Failed to load cached binary for shader: " << shader->mName << " falling back to compilation" << LL_ENDL;
+ LLFile::remove(in_path);
+ mShaderBinaryCache.erase(binary_iter);
+ }
+ return false;
}
bool LLShaderMgr::saveCachedProgramBinary(LLGLSLShader* shader)
{
- if (!mShaderCacheEnabled) return true;
-
- ProgramBinaryData binary_info = ProgramBinaryData();
- glGetProgramiv(shader->mProgramObject, GL_PROGRAM_BINARY_LENGTH, &binary_info.mBinaryLength);
- if (binary_info.mBinaryLength > 0)
- {
- std::vector<U8> program_binary;
- program_binary.resize(binary_info.mBinaryLength);
-
- GLenum error = glGetError(); // Clear current error
- glGetProgramBinary(shader->mProgramObject, program_binary.size() * sizeof(U8), nullptr, &binary_info.mBinaryFormat, program_binary.data());
- error = glGetError();
- if (error == GL_NO_ERROR)
- {
- std::string out_path = gDirUtilp->add(mShaderCacheDir, shader->mShaderHash.asString() + ".shaderbin");
- LLUniqueFile outfile = LLFile::fopen(out_path, "wb");
- if (outfile)
- {
- fwrite(program_binary.data(), sizeof(U8), program_binary.size(), outfile);
- outfile.close();
-
- binary_info.mLastUsedTime = LLTimer::getTotalSeconds();
-
- mShaderBinaryCache.insert_or_assign(shader->mShaderHash, binary_info);
- return true;
- }
- }
- }
- return false;
+ if (!mShaderCacheEnabled) return true;
+
+ ProgramBinaryData binary_info = ProgramBinaryData();
+ glGetProgramiv(shader->mProgramObject, GL_PROGRAM_BINARY_LENGTH, &binary_info.mBinaryLength);
+ if (binary_info.mBinaryLength > 0)
+ {
+ std::vector<U8> program_binary;
+ program_binary.resize(binary_info.mBinaryLength);
+
+ GLenum error = glGetError(); // Clear current error
+ glGetProgramBinary(shader->mProgramObject, program_binary.size() * sizeof(U8), nullptr, &binary_info.mBinaryFormat, program_binary.data());
+ error = glGetError();
+ if (error == GL_NO_ERROR)
+ {
+ std::string out_path = gDirUtilp->add(mShaderCacheDir, shader->mShaderHash.asString() + ".shaderbin");
+ LLUniqueFile outfile = LLFile::fopen(out_path, "wb");
+ if (outfile)
+ {
+ fwrite(program_binary.data(), sizeof(U8), program_binary.size(), outfile);
+ outfile.close();
+
+ binary_info.mLastUsedTime = LLTimer::getTotalSeconds();
+
+ mShaderBinaryCache.insert_or_assign(shader->mShaderHash, binary_info);
+ return true;
+ }
+ }
+ }
+ return false;
}
//virtual
void LLShaderMgr::initAttribsAndUniforms()
{
- //MUST match order of enum in LLVertexBuffer.h
- mReservedAttribs.push_back("position");
- mReservedAttribs.push_back("normal");
- mReservedAttribs.push_back("texcoord0");
- mReservedAttribs.push_back("texcoord1");
- mReservedAttribs.push_back("texcoord2");
- mReservedAttribs.push_back("texcoord3");
- mReservedAttribs.push_back("diffuse_color");
- mReservedAttribs.push_back("emissive");
- mReservedAttribs.push_back("tangent");
- mReservedAttribs.push_back("weight");
- mReservedAttribs.push_back("weight4");
- mReservedAttribs.push_back("clothing");
- mReservedAttribs.push_back("texture_index");
-
- //matrix state
- mReservedUniforms.push_back("modelview_matrix");
- mReservedUniforms.push_back("projection_matrix");
- mReservedUniforms.push_back("inv_proj");
- mReservedUniforms.push_back("modelview_projection_matrix");
+ //MUST match order of enum in LLVertexBuffer.h
+ mReservedAttribs.push_back("position");
+ mReservedAttribs.push_back("normal");
+ mReservedAttribs.push_back("texcoord0");
+ mReservedAttribs.push_back("texcoord1");
+ mReservedAttribs.push_back("texcoord2");
+ mReservedAttribs.push_back("texcoord3");
+ mReservedAttribs.push_back("diffuse_color");
+ mReservedAttribs.push_back("emissive");
+ mReservedAttribs.push_back("tangent");
+ mReservedAttribs.push_back("weight");
+ mReservedAttribs.push_back("weight4");
+ mReservedAttribs.push_back("clothing");
+ mReservedAttribs.push_back("texture_index");
+
+ //matrix state
+ mReservedUniforms.push_back("modelview_matrix");
+ mReservedUniforms.push_back("projection_matrix");
+ mReservedUniforms.push_back("inv_proj");
+ mReservedUniforms.push_back("modelview_projection_matrix");
mReservedUniforms.push_back("inv_modelview");
mReservedUniforms.push_back("identity_matrix");
- mReservedUniforms.push_back("normal_matrix");
- mReservedUniforms.push_back("texture_matrix0");
- mReservedUniforms.push_back("texture_matrix1");
- mReservedUniforms.push_back("texture_matrix2");
- mReservedUniforms.push_back("texture_matrix3");
- mReservedUniforms.push_back("object_plane_s");
- mReservedUniforms.push_back("object_plane_t");
+ mReservedUniforms.push_back("normal_matrix");
+ mReservedUniforms.push_back("texture_matrix0");
+ mReservedUniforms.push_back("texture_matrix1");
+ mReservedUniforms.push_back("texture_matrix2");
+ mReservedUniforms.push_back("texture_matrix3");
+ mReservedUniforms.push_back("object_plane_s");
+ mReservedUniforms.push_back("object_plane_t");
mReservedUniforms.push_back("texture_base_color_transform"); // (GLTF)
mReservedUniforms.push_back("texture_normal_transform"); // (GLTF)
@@ -1157,130 +1157,130 @@ void LLShaderMgr::initAttribsAndUniforms()
llassert(mReservedUniforms.size() == LLShaderMgr::TEXTURE_EMISSIVE_TRANSFORM+1);
- mReservedUniforms.push_back("viewport");
+ mReservedUniforms.push_back("viewport");
- mReservedUniforms.push_back("light_position");
- mReservedUniforms.push_back("light_direction");
- mReservedUniforms.push_back("light_attenuation");
+ mReservedUniforms.push_back("light_position");
+ mReservedUniforms.push_back("light_direction");
+ mReservedUniforms.push_back("light_attenuation");
mReservedUniforms.push_back("light_deferred_attenuation");
- mReservedUniforms.push_back("light_diffuse");
- mReservedUniforms.push_back("light_ambient");
- mReservedUniforms.push_back("light_count");
- mReservedUniforms.push_back("light");
- mReservedUniforms.push_back("light_col");
- mReservedUniforms.push_back("far_z");
+ mReservedUniforms.push_back("light_diffuse");
+ mReservedUniforms.push_back("light_ambient");
+ mReservedUniforms.push_back("light_count");
+ mReservedUniforms.push_back("light");
+ mReservedUniforms.push_back("light_col");
+ mReservedUniforms.push_back("far_z");
- llassert(mReservedUniforms.size() == LLShaderMgr::MULTI_LIGHT_FAR_Z+1);
+ llassert(mReservedUniforms.size() == LLShaderMgr::MULTI_LIGHT_FAR_Z+1);
//NOTE: MUST match order in eGLSLReservedUniforms
- mReservedUniforms.push_back("proj_mat");
- mReservedUniforms.push_back("proj_near");
- mReservedUniforms.push_back("proj_p");
- mReservedUniforms.push_back("proj_n");
- mReservedUniforms.push_back("proj_origin");
- mReservedUniforms.push_back("proj_range");
- mReservedUniforms.push_back("proj_ambiance");
- mReservedUniforms.push_back("proj_shadow_idx");
- mReservedUniforms.push_back("shadow_fade");
- mReservedUniforms.push_back("proj_focus");
- mReservedUniforms.push_back("proj_lod");
- mReservedUniforms.push_back("proj_ambient_lod");
-
- llassert(mReservedUniforms.size() == LLShaderMgr::PROJECTOR_AMBIENT_LOD+1);
-
- mReservedUniforms.push_back("color");
+ mReservedUniforms.push_back("proj_mat");
+ mReservedUniforms.push_back("proj_near");
+ mReservedUniforms.push_back("proj_p");
+ mReservedUniforms.push_back("proj_n");
+ mReservedUniforms.push_back("proj_origin");
+ mReservedUniforms.push_back("proj_range");
+ mReservedUniforms.push_back("proj_ambiance");
+ mReservedUniforms.push_back("proj_shadow_idx");
+ mReservedUniforms.push_back("shadow_fade");
+ mReservedUniforms.push_back("proj_focus");
+ mReservedUniforms.push_back("proj_lod");
+ mReservedUniforms.push_back("proj_ambient_lod");
+
+ llassert(mReservedUniforms.size() == LLShaderMgr::PROJECTOR_AMBIENT_LOD+1);
+
+ mReservedUniforms.push_back("color");
mReservedUniforms.push_back("emissiveColor");
mReservedUniforms.push_back("metallicFactor");
mReservedUniforms.push_back("roughnessFactor");
- mReservedUniforms.push_back("diffuseMap");
+ mReservedUniforms.push_back("diffuseMap");
mReservedUniforms.push_back("altDiffuseMap");
- mReservedUniforms.push_back("specularMap");
+ mReservedUniforms.push_back("specularMap");
mReservedUniforms.push_back("emissiveMap");
- mReservedUniforms.push_back("bumpMap");
+ mReservedUniforms.push_back("bumpMap");
mReservedUniforms.push_back("bumpMap2");
- mReservedUniforms.push_back("environmentMap");
+ mReservedUniforms.push_back("environmentMap");
mReservedUniforms.push_back("sceneMap");
mReservedUniforms.push_back("sceneDepth");
mReservedUniforms.push_back("reflectionProbes");
mReservedUniforms.push_back("irradianceProbes");
- mReservedUniforms.push_back("cloud_noise_texture");
+ mReservedUniforms.push_back("cloud_noise_texture");
mReservedUniforms.push_back("cloud_noise_texture_next");
- mReservedUniforms.push_back("fullbright");
- mReservedUniforms.push_back("lightnorm");
- mReservedUniforms.push_back("sunlight_color");
- mReservedUniforms.push_back("ambient_color");
+ mReservedUniforms.push_back("fullbright");
+ mReservedUniforms.push_back("lightnorm");
+ mReservedUniforms.push_back("sunlight_color");
+ mReservedUniforms.push_back("ambient_color");
mReservedUniforms.push_back("sky_hdr_scale");
mReservedUniforms.push_back("sky_sunlight_scale");
mReservedUniforms.push_back("sky_ambient_scale");
- mReservedUniforms.push_back("blue_horizon");
+ mReservedUniforms.push_back("blue_horizon");
mReservedUniforms.push_back("blue_density");
mReservedUniforms.push_back("haze_horizon");
- mReservedUniforms.push_back("haze_density");
- mReservedUniforms.push_back("cloud_shadow");
- mReservedUniforms.push_back("density_multiplier");
- mReservedUniforms.push_back("distance_multiplier");
- mReservedUniforms.push_back("max_y");
- mReservedUniforms.push_back("glow");
- mReservedUniforms.push_back("cloud_color");
- mReservedUniforms.push_back("cloud_pos_density1");
- mReservedUniforms.push_back("cloud_pos_density2");
- mReservedUniforms.push_back("cloud_scale");
- mReservedUniforms.push_back("gamma");
- mReservedUniforms.push_back("scene_light_strength");
+ mReservedUniforms.push_back("haze_density");
+ mReservedUniforms.push_back("cloud_shadow");
+ mReservedUniforms.push_back("density_multiplier");
+ mReservedUniforms.push_back("distance_multiplier");
+ mReservedUniforms.push_back("max_y");
+ mReservedUniforms.push_back("glow");
+ mReservedUniforms.push_back("cloud_color");
+ mReservedUniforms.push_back("cloud_pos_density1");
+ mReservedUniforms.push_back("cloud_pos_density2");
+ mReservedUniforms.push_back("cloud_scale");
+ mReservedUniforms.push_back("gamma");
+ mReservedUniforms.push_back("scene_light_strength");
- llassert(mReservedUniforms.size() == LLShaderMgr::SCENE_LIGHT_STRENGTH+1);
+ llassert(mReservedUniforms.size() == LLShaderMgr::SCENE_LIGHT_STRENGTH+1);
- mReservedUniforms.push_back("center");
- mReservedUniforms.push_back("size");
- mReservedUniforms.push_back("falloff");
+ mReservedUniforms.push_back("center");
+ mReservedUniforms.push_back("size");
+ mReservedUniforms.push_back("falloff");
- mReservedUniforms.push_back("box_center");
- mReservedUniforms.push_back("box_size");
+ mReservedUniforms.push_back("box_center");
+ mReservedUniforms.push_back("box_size");
- mReservedUniforms.push_back("minLuminance");
- mReservedUniforms.push_back("maxExtractAlpha");
- mReservedUniforms.push_back("lumWeights");
- mReservedUniforms.push_back("warmthWeights");
- mReservedUniforms.push_back("warmthAmount");
- mReservedUniforms.push_back("glowStrength");
- mReservedUniforms.push_back("glowDelta");
- mReservedUniforms.push_back("glowNoiseMap");
+ mReservedUniforms.push_back("minLuminance");
+ mReservedUniforms.push_back("maxExtractAlpha");
+ mReservedUniforms.push_back("lumWeights");
+ mReservedUniforms.push_back("warmthWeights");
+ mReservedUniforms.push_back("warmthAmount");
+ mReservedUniforms.push_back("glowStrength");
+ mReservedUniforms.push_back("glowDelta");
+ mReservedUniforms.push_back("glowNoiseMap");
- llassert(mReservedUniforms.size() == LLShaderMgr::GLOW_NOISE_MAP+1);
+ llassert(mReservedUniforms.size() == LLShaderMgr::GLOW_NOISE_MAP+1);
- mReservedUniforms.push_back("minimum_alpha");
- mReservedUniforms.push_back("emissive_brightness");
+ mReservedUniforms.push_back("minimum_alpha");
+ mReservedUniforms.push_back("emissive_brightness");
// Deferred
- mReservedUniforms.push_back("shadow_matrix");
- mReservedUniforms.push_back("env_mat");
- mReservedUniforms.push_back("shadow_clip");
- mReservedUniforms.push_back("sun_wash");
- mReservedUniforms.push_back("shadow_noise");
- mReservedUniforms.push_back("blur_size");
- mReservedUniforms.push_back("ssao_radius");
- mReservedUniforms.push_back("ssao_max_radius");
- mReservedUniforms.push_back("ssao_factor");
- mReservedUniforms.push_back("ssao_factor_inv");
- mReservedUniforms.push_back("ssao_effect_mat");
- mReservedUniforms.push_back("screen_res");
- mReservedUniforms.push_back("near_clip");
- mReservedUniforms.push_back("shadow_offset");
- mReservedUniforms.push_back("shadow_bias");
- mReservedUniforms.push_back("spot_shadow_bias");
- mReservedUniforms.push_back("spot_shadow_offset");
- mReservedUniforms.push_back("sun_dir");
+ mReservedUniforms.push_back("shadow_matrix");
+ mReservedUniforms.push_back("env_mat");
+ mReservedUniforms.push_back("shadow_clip");
+ mReservedUniforms.push_back("sun_wash");
+ mReservedUniforms.push_back("shadow_noise");
+ mReservedUniforms.push_back("blur_size");
+ mReservedUniforms.push_back("ssao_radius");
+ mReservedUniforms.push_back("ssao_max_radius");
+ mReservedUniforms.push_back("ssao_factor");
+ mReservedUniforms.push_back("ssao_factor_inv");
+ mReservedUniforms.push_back("ssao_effect_mat");
+ mReservedUniforms.push_back("screen_res");
+ mReservedUniforms.push_back("near_clip");
+ mReservedUniforms.push_back("shadow_offset");
+ mReservedUniforms.push_back("shadow_bias");
+ mReservedUniforms.push_back("spot_shadow_bias");
+ mReservedUniforms.push_back("spot_shadow_offset");
+ mReservedUniforms.push_back("sun_dir");
mReservedUniforms.push_back("moon_dir");
- mReservedUniforms.push_back("shadow_res");
- mReservedUniforms.push_back("proj_shadow_res");
- mReservedUniforms.push_back("depth_cutoff");
- mReservedUniforms.push_back("norm_cutoff");
- mReservedUniforms.push_back("shadow_target_width");
-
- llassert(mReservedUniforms.size() == LLShaderMgr::DEFERRED_SHADOW_TARGET_WIDTH + 1);
+ mReservedUniforms.push_back("shadow_res");
+ mReservedUniforms.push_back("proj_shadow_res");
+ mReservedUniforms.push_back("depth_cutoff");
+ mReservedUniforms.push_back("norm_cutoff");
+ mReservedUniforms.push_back("shadow_target_width");
+
+ llassert(mReservedUniforms.size() == LLShaderMgr::DEFERRED_SHADOW_TARGET_WIDTH + 1);
mReservedUniforms.push_back("iterationCount");
mReservedUniforms.push_back("rayStep");
@@ -1294,90 +1294,90 @@ void LLShaderMgr::initAttribsAndUniforms()
mReservedUniforms.push_back("inv_modelview_delta");
mReservedUniforms.push_back("cube_snapshot");
- mReservedUniforms.push_back("tc_scale");
- mReservedUniforms.push_back("rcp_screen_res");
- mReservedUniforms.push_back("rcp_frame_opt");
- mReservedUniforms.push_back("rcp_frame_opt2");
-
- mReservedUniforms.push_back("focal_distance");
- mReservedUniforms.push_back("blur_constant");
- mReservedUniforms.push_back("tan_pixel_angle");
- mReservedUniforms.push_back("magnification");
- mReservedUniforms.push_back("max_cof");
- mReservedUniforms.push_back("res_scale");
- mReservedUniforms.push_back("dof_width");
- mReservedUniforms.push_back("dof_height");
-
- mReservedUniforms.push_back("depthMap");
- mReservedUniforms.push_back("shadowMap0");
- mReservedUniforms.push_back("shadowMap1");
- mReservedUniforms.push_back("shadowMap2");
- mReservedUniforms.push_back("shadowMap3");
- mReservedUniforms.push_back("shadowMap4");
- mReservedUniforms.push_back("shadowMap5");
-
- llassert(mReservedUniforms.size() == LLShaderMgr::DEFERRED_SHADOW5+1);
-
- mReservedUniforms.push_back("normalMap");
- mReservedUniforms.push_back("positionMap");
- mReservedUniforms.push_back("diffuseRect");
- mReservedUniforms.push_back("specularRect");
+ mReservedUniforms.push_back("tc_scale");
+ mReservedUniforms.push_back("rcp_screen_res");
+ mReservedUniforms.push_back("rcp_frame_opt");
+ mReservedUniforms.push_back("rcp_frame_opt2");
+
+ mReservedUniforms.push_back("focal_distance");
+ mReservedUniforms.push_back("blur_constant");
+ mReservedUniforms.push_back("tan_pixel_angle");
+ mReservedUniforms.push_back("magnification");
+ mReservedUniforms.push_back("max_cof");
+ mReservedUniforms.push_back("res_scale");
+ mReservedUniforms.push_back("dof_width");
+ mReservedUniforms.push_back("dof_height");
+
+ mReservedUniforms.push_back("depthMap");
+ mReservedUniforms.push_back("shadowMap0");
+ mReservedUniforms.push_back("shadowMap1");
+ mReservedUniforms.push_back("shadowMap2");
+ mReservedUniforms.push_back("shadowMap3");
+ mReservedUniforms.push_back("shadowMap4");
+ mReservedUniforms.push_back("shadowMap5");
+
+ llassert(mReservedUniforms.size() == LLShaderMgr::DEFERRED_SHADOW5+1);
+
+ mReservedUniforms.push_back("normalMap");
+ mReservedUniforms.push_back("positionMap");
+ mReservedUniforms.push_back("diffuseRect");
+ mReservedUniforms.push_back("specularRect");
mReservedUniforms.push_back("emissiveRect");
mReservedUniforms.push_back("exposureMap");
mReservedUniforms.push_back("brdfLut");
- mReservedUniforms.push_back("noiseMap");
- mReservedUniforms.push_back("lightFunc");
- mReservedUniforms.push_back("lightMap");
- mReservedUniforms.push_back("bloomMap");
- mReservedUniforms.push_back("projectionMap");
- mReservedUniforms.push_back("norm_mat");
- mReservedUniforms.push_back("texture_gamma");
-
- mReservedUniforms.push_back("specular_color");
- mReservedUniforms.push_back("env_intensity");
-
- mReservedUniforms.push_back("matrixPalette");
- mReservedUniforms.push_back("translationPalette");
-
- mReservedUniforms.push_back("screenTex");
- mReservedUniforms.push_back("screenDepth");
- mReservedUniforms.push_back("refTex");
- mReservedUniforms.push_back("eyeVec");
- mReservedUniforms.push_back("time");
- mReservedUniforms.push_back("waveDir1");
- mReservedUniforms.push_back("waveDir2");
- mReservedUniforms.push_back("lightDir");
- mReservedUniforms.push_back("specular");
- mReservedUniforms.push_back("lightExp");
- mReservedUniforms.push_back("waterFogColor");
+ mReservedUniforms.push_back("noiseMap");
+ mReservedUniforms.push_back("lightFunc");
+ mReservedUniforms.push_back("lightMap");
+ mReservedUniforms.push_back("bloomMap");
+ mReservedUniforms.push_back("projectionMap");
+ mReservedUniforms.push_back("norm_mat");
+ mReservedUniforms.push_back("texture_gamma");
+
+ mReservedUniforms.push_back("specular_color");
+ mReservedUniforms.push_back("env_intensity");
+
+ mReservedUniforms.push_back("matrixPalette");
+ mReservedUniforms.push_back("translationPalette");
+
+ mReservedUniforms.push_back("screenTex");
+ mReservedUniforms.push_back("screenDepth");
+ mReservedUniforms.push_back("refTex");
+ mReservedUniforms.push_back("eyeVec");
+ mReservedUniforms.push_back("time");
+ mReservedUniforms.push_back("waveDir1");
+ mReservedUniforms.push_back("waveDir2");
+ mReservedUniforms.push_back("lightDir");
+ mReservedUniforms.push_back("specular");
+ mReservedUniforms.push_back("lightExp");
+ mReservedUniforms.push_back("waterFogColor");
mReservedUniforms.push_back("waterFogColorLinear");
- mReservedUniforms.push_back("waterFogDensity");
- mReservedUniforms.push_back("waterFogKS");
- mReservedUniforms.push_back("refScale");
- mReservedUniforms.push_back("waterHeight");
- mReservedUniforms.push_back("waterPlane");
- mReservedUniforms.push_back("normScale");
- mReservedUniforms.push_back("fresnelScale");
- mReservedUniforms.push_back("fresnelOffset");
- mReservedUniforms.push_back("blurMultiplier");
- mReservedUniforms.push_back("sunAngle");
- mReservedUniforms.push_back("scaledAngle");
- mReservedUniforms.push_back("sunAngle2");
-
- mReservedUniforms.push_back("camPosLocal");
-
- mReservedUniforms.push_back("gWindDir");
- mReservedUniforms.push_back("gSinWaveParams");
- mReservedUniforms.push_back("gGravity");
-
- mReservedUniforms.push_back("detail_0");
- mReservedUniforms.push_back("detail_1");
- mReservedUniforms.push_back("detail_2");
- mReservedUniforms.push_back("detail_3");
- mReservedUniforms.push_back("alpha_ramp");
-
- mReservedUniforms.push_back("origin");
- mReservedUniforms.push_back("display_gamma");
+ mReservedUniforms.push_back("waterFogDensity");
+ mReservedUniforms.push_back("waterFogKS");
+ mReservedUniforms.push_back("refScale");
+ mReservedUniforms.push_back("waterHeight");
+ mReservedUniforms.push_back("waterPlane");
+ mReservedUniforms.push_back("normScale");
+ mReservedUniforms.push_back("fresnelScale");
+ mReservedUniforms.push_back("fresnelOffset");
+ mReservedUniforms.push_back("blurMultiplier");
+ mReservedUniforms.push_back("sunAngle");
+ mReservedUniforms.push_back("scaledAngle");
+ mReservedUniforms.push_back("sunAngle2");
+
+ mReservedUniforms.push_back("camPosLocal");
+
+ mReservedUniforms.push_back("gWindDir");
+ mReservedUniforms.push_back("gSinWaveParams");
+ mReservedUniforms.push_back("gGravity");
+
+ mReservedUniforms.push_back("detail_0");
+ mReservedUniforms.push_back("detail_1");
+ mReservedUniforms.push_back("detail_2");
+ mReservedUniforms.push_back("detail_3");
+ mReservedUniforms.push_back("alpha_ramp");
+
+ mReservedUniforms.push_back("origin");
+ mReservedUniforms.push_back("display_gamma");
mReservedUniforms.push_back("inscatter");
mReservedUniforms.push_back("sun_size");
@@ -1407,17 +1407,17 @@ void LLShaderMgr::initAttribsAndUniforms()
mReservedUniforms.push_back("sun_up_factor");
mReservedUniforms.push_back("moonlight_color");
- llassert(mReservedUniforms.size() == END_RESERVED_UNIFORMS);
+ llassert(mReservedUniforms.size() == END_RESERVED_UNIFORMS);
- std::set<std::string> dupe_check;
+ std::set<std::string> dupe_check;
- for (U32 i = 0; i < mReservedUniforms.size(); ++i)
- {
- if (dupe_check.find(mReservedUniforms[i]) != dupe_check.end())
- {
- LL_ERRS() << "Duplicate reserved uniform name found: " << mReservedUniforms[i] << LL_ENDL;
- }
- dupe_check.insert(mReservedUniforms[i]);
- }
+ for (U32 i = 0; i < mReservedUniforms.size(); ++i)
+ {
+ if (dupe_check.find(mReservedUniforms[i]) != dupe_check.end())
+ {
+ LL_ERRS() << "Duplicate reserved uniform name found: " << mReservedUniforms[i] << LL_ENDL;
+ }
+ dupe_check.insert(mReservedUniforms[i]);
+ }
}
diff --git a/indra/llrender/llshadermgr.h b/indra/llrender/llshadermgr.h
index 79a24773e1..e655dda98d 100644
--- a/indra/llrender/llshadermgr.h
+++ b/indra/llrender/llshadermgr.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file llshadermgr.h
* @brief Shader Manager
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -33,8 +33,8 @@
class LLShaderMgr
{
public:
- LLShaderMgr();
- virtual ~LLShaderMgr();
+ LLShaderMgr();
+ virtual ~LLShaderMgr();
// clang-format off
typedef enum
@@ -291,23 +291,23 @@ public:
} eGLSLReservedUniforms;
// clang-format on
- // singleton pattern implementation
- static LLShaderMgr * instance();
+ // singleton pattern implementation
+ static LLShaderMgr * instance();
- virtual void initAttribsAndUniforms(void);
+ virtual void initAttribsAndUniforms(void);
- BOOL attachShaderFeatures(LLGLSLShader * shader);
- void dumpObjectLog(GLuint ret, BOOL warns = TRUE, const std::string& filename = "");
+ BOOL attachShaderFeatures(LLGLSLShader * shader);
+ void dumpObjectLog(GLuint ret, BOOL warns = TRUE, const std::string& filename = "");
void dumpShaderSource(U32 shader_code_count, GLchar** shader_code_text);
- BOOL linkProgramObject(GLuint obj, BOOL suppress_errors = FALSE);
- BOOL validateProgramObject(GLuint obj);
- GLuint loadShaderFile(const std::string& filename, S32 & shader_level, GLenum type, std::map<std::string, std::string>* defines = NULL, S32 texture_index_channels = -1);
+ BOOL linkProgramObject(GLuint obj, BOOL suppress_errors = FALSE);
+ BOOL validateProgramObject(GLuint obj);
+ GLuint loadShaderFile(const std::string& filename, S32 & shader_level, GLenum type, std::map<std::string, std::string>* defines = NULL, S32 texture_index_channels = -1);
- // Implemented in the application to actually point to the shader directory.
- virtual std::string getShaderDirPrefix(void) = 0; // Pure Virtual
+ // Implemented in the application to actually point to the shader directory.
+ virtual std::string getShaderDirPrefix(void) = 0; // Pure Virtual
- // Implemented in the application to actually update out of date uniforms for a particular shader
- virtual void updateShaderUniforms(LLGLSLShader * shader) = 0; // Pure Virtual
+ // Implemented in the application to actually update out of date uniforms for a particular shader
+ virtual void updateShaderUniforms(LLGLSLShader * shader) = 0; // Pure Virtual
void initShaderCache(bool enabled, const LLUUID& old_cache_version, const LLUUID& current_cache_version);
void clearShaderCache();
@@ -317,14 +317,14 @@ public:
bool saveCachedProgramBinary(LLGLSLShader* shader);
public:
- // Map of shader names to compiled
+ // Map of shader names to compiled
std::map<std::string, GLuint> mVertexShaderObjects;
std::map<std::string, GLuint> mFragmentShaderObjects;
- //global (reserved slot) shader parameters
- std::vector<std::string> mReservedAttribs;
+ //global (reserved slot) shader parameters
+ std::vector<std::string> mReservedAttribs;
- std::vector<std::string> mReservedUniforms;
+ std::vector<std::string> mReservedUniforms;
struct ProgramBinaryData
{
@@ -339,8 +339,8 @@ public:
protected:
- // our parameter manager singleton instance
- static LLShaderMgr * sInstance;
+ // our parameter manager singleton instance
+ static LLShaderMgr * sInstance;
}; //LLShaderMgr
diff --git a/indra/llrender/lltexture.cpp b/indra/llrender/lltexture.cpp
index 6eef36216c..980c0950f9 100644
--- a/indra/llrender/lltexture.cpp
+++ b/indra/llrender/lltexture.cpp
@@ -1,31 +1,31 @@
-/**
+/**
* @file lltexture.cpp
*
* $LicenseInfo:firstyear=2000&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include "linden_common.h"
#include "lltexture.h"
-//virtual
+//virtual
LLTexture::~LLTexture()
{
}
@@ -36,8 +36,8 @@ bool LLTexture::bindDefaultImage(const S32 stage) { llassert(false); return fals
bool LLTexture::bindDebugImage(const S32 stage) { llassert(false); return false; }
void LLTexture::forceImmediateUpdate() { llassert(false); }
void LLTexture::setActive() { llassert(false); }
-S32 LLTexture::getWidth(S32 discard_level) const { llassert(false); return 0; }
-S32 LLTexture::getHeight(S32 discard_level) const { llassert(false); return 0; }
+S32 LLTexture::getWidth(S32 discard_level) const { llassert(false); return 0; }
+S32 LLTexture::getHeight(S32 discard_level) const { llassert(false); return 0; }
bool LLTexture::isActiveFetching() { llassert(false); return false; }
LLImageGL* LLTexture::getGLTexture() const { llassert(false); return nullptr; }
void LLTexture::updateBindStatsForTester() { }
diff --git a/indra/llrender/lltexture.h b/indra/llrender/lltexture.h
index e890a5a30b..35cded86f2 100644
--- a/indra/llrender/lltexture.h
+++ b/indra/llrender/lltexture.h
@@ -1,30 +1,30 @@
-/**
+/**
* @file lltexture.h
* @brief LLTexture definition
*
- * This class acts as a wrapper for OpenGL calls.
- * The goal of this class is to minimize the number of api calls due to legacy rendering
- * code, to define an interface for a multiple rendering API abstraction of the UI
- * rendering, and to abstract out direct rendering calls in a way that is cleaner and easier to maintain.
+ * This class acts as a wrapper for OpenGL calls.
+ * The goal of this class is to minimize the number of api calls due to legacy rendering
+ * code, to define an interface for a multiple rendering API abstraction of the UI
+ * rendering, and to abstract out direct rendering calls in a way that is cleaner and easier to maintain.
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -44,32 +44,32 @@ class LLFontGL ;
//
class LLTexture : public virtual LLRefCount
{
- friend class LLTexUnit ;
- friend class LLFontGL ;
+ friend class LLTexUnit ;
+ friend class LLFontGL ;
protected:
- virtual ~LLTexture();
+ virtual ~LLTexture();
public:
- LLTexture()
- {}
+ LLTexture()
+ {}
- //
- //interfaces to access LLGLTexture
- //
- virtual S8 getType() const;
- virtual void setKnownDrawSize(S32 width, S32 height);
- virtual bool bindDefaultImage(const S32 stage = 0);
- virtual bool bindDebugImage(const S32 stage = 0);
- virtual void forceImmediateUpdate();
- virtual void setActive();
- virtual S32 getWidth(S32 discard_level = -1) const;
- virtual S32 getHeight(S32 discard_level = -1) const;
- virtual bool isActiveFetching();
+ //
+ //interfaces to access LLGLTexture
+ //
+ virtual S8 getType() const;
+ virtual void setKnownDrawSize(S32 width, S32 height);
+ virtual bool bindDefaultImage(const S32 stage = 0);
+ virtual bool bindDebugImage(const S32 stage = 0);
+ virtual void forceImmediateUpdate();
+ virtual void setActive();
+ virtual S32 getWidth(S32 discard_level = -1) const;
+ virtual S32 getHeight(S32 discard_level = -1) const;
+ virtual bool isActiveFetching();
virtual LLImageGL* getGLTexture() const;
private:
- virtual void updateBindStatsForTester();
+ virtual void updateBindStatsForTester();
};
#endif
diff --git a/indra/llrender/lltexturemanagerbridge.cpp b/indra/llrender/lltexturemanagerbridge.cpp
index 33f2185e4f..c243f0697a 100644
--- a/indra/llrender/lltexturemanagerbridge.cpp
+++ b/indra/llrender/lltexturemanagerbridge.cpp
@@ -1,25 +1,25 @@
- /**
+ /**
* @file lltexturemanagerbridge.cpp
* @brief Defined a null texture manager bridge. Applications must provide their own bridge implementaton.
*
* $LicenseInfo:firstyear=2012&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
diff --git a/indra/llrender/lltexturemanagerbridge.h b/indra/llrender/lltexturemanagerbridge.h
index f61433ea4d..0b76ee4de8 100644
--- a/indra/llrender/lltexturemanagerbridge.h
+++ b/indra/llrender/lltexturemanagerbridge.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file lltexturemanagerbridge.h
* @brief Bridge to an application-specific texture manager.
*
* $LicenseInfo:firstyear=2012&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -36,9 +36,9 @@ class LLTextureManagerBridge
public:
virtual ~LLTextureManagerBridge() {}
- virtual LLPointer<LLGLTexture> getLocalTexture(BOOL usemipmaps = TRUE, BOOL generate_gl_tex = TRUE) = 0;
- virtual LLPointer<LLGLTexture> getLocalTexture(const U32 width, const U32 height, const U8 components, BOOL usemipmaps, BOOL generate_gl_tex = TRUE) = 0;
- virtual LLGLTexture* getFetchedTexture(const LLUUID &image_id) = 0;
+ virtual LLPointer<LLGLTexture> getLocalTexture(BOOL usemipmaps = TRUE, BOOL generate_gl_tex = TRUE) = 0;
+ virtual LLPointer<LLGLTexture> getLocalTexture(const U32 width, const U32 height, const U8 components, BOOL usemipmaps, BOOL generate_gl_tex = TRUE) = 0;
+ virtual LLGLTexture* getFetchedTexture(const LLUUID &image_id) = 0;
};
extern LLTextureManagerBridge* gTextureManagerBridgep;
diff --git a/indra/llrender/lluiimage.cpp b/indra/llrender/lluiimage.cpp
index 424672fe8e..bcf665ca18 100644
--- a/indra/llrender/lluiimage.cpp
+++ b/indra/llrender/lluiimage.cpp
@@ -1,25 +1,25 @@
-/**
+/**
* @file lluiimage.cpp
* @brief UI implementation
*
* $LicenseInfo:firstyear=2007&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -33,12 +33,12 @@
#include "lluiimage.h"
LLUIImage::LLUIImage(const std::string& name, LLPointer<LLTexture> image)
-: mName(name),
- mImage(image),
- mScaleRegion(0.f, 1.f, 1.f, 0.f),
- mClipRegion(0.f, 1.f, 1.f, 0.f),
- mImageLoaded(NULL),
- mScaleStyle(SCALE_INNER),
+: mName(name),
+ mImage(image),
+ mScaleRegion(0.f, 1.f, 1.f, 0.f),
+ mClipRegion(0.f, 1.f, 1.f, 0.f),
+ mImageLoaded(NULL),
+ mScaleStyle(SCALE_INNER),
mCachedW(-1),
mCachedH(-1)
{
@@ -48,125 +48,125 @@ LLUIImage::LLUIImage(const std::string& name, LLPointer<LLTexture> image)
LLUIImage::~LLUIImage()
{
- delete mImageLoaded;
+ delete mImageLoaded;
}
S32 LLUIImage::getWidth() const
-{
- // return clipped dimensions of actual image area
- return ll_round((F32)mImage->getWidth(0) * mClipRegion.getWidth());
+{
+ // return clipped dimensions of actual image area
+ return ll_round((F32)mImage->getWidth(0) * mClipRegion.getWidth());
}
S32 LLUIImage::getHeight() const
-{
- // return clipped dimensions of actual image area
- return ll_round((F32)mImage->getHeight(0) * mClipRegion.getHeight());
+{
+ // return clipped dimensions of actual image area
+ return ll_round((F32)mImage->getHeight(0) * mClipRegion.getHeight());
}
-void LLUIImage::draw3D(const LLVector3& origin_agent, const LLVector3& x_axis, const LLVector3& y_axis,
- const LLRect& rect, const LLColor4& color)
+void LLUIImage::draw3D(const LLVector3& origin_agent, const LLVector3& x_axis, const LLVector3& y_axis,
+ const LLRect& rect, const LLColor4& color)
{
- F32 border_scale = 1.f;
- F32 border_height = (1.f - mScaleRegion.getHeight()) * getHeight();
- F32 border_width = (1.f - mScaleRegion.getWidth()) * getWidth();
- if (rect.getHeight() < border_height || rect.getWidth() < border_width)
- {
- if(border_height - rect.getHeight() > border_width - rect.getWidth())
- {
- border_scale = (F32)rect.getHeight() / border_height;
- }
- else
- {
- border_scale = (F32)rect.getWidth() / border_width;
- }
- }
-
- LLRender2D::getInstance()->pushMatrix();
- {
- LLVector3 rect_origin = origin_agent + (rect.mLeft * x_axis) + (rect.mBottom * y_axis);
- LLRender2D::getInstance()->translate(rect_origin.mV[VX],
- rect_origin.mV[VY],
- rect_origin.mV[VZ]);
- gGL.getTexUnit(0)->bind(getImage());
- gGL.color4fv(color.mV);
-
- LLRectf center_uv_rect(mClipRegion.mLeft + mScaleRegion.mLeft * mClipRegion.getWidth(),
- mClipRegion.mBottom + mScaleRegion.mTop * mClipRegion.getHeight(),
- mClipRegion.mLeft + mScaleRegion.mRight * mClipRegion.getWidth(),
- mClipRegion.mBottom + mScaleRegion.mBottom * mClipRegion.getHeight());
- gl_segmented_rect_3d_tex(mClipRegion,
- center_uv_rect,
- LLRectf(border_width * border_scale * 0.5f / (F32)rect.getWidth(),
- (rect.getHeight() - (border_height * border_scale * 0.5f)) / (F32)rect.getHeight(),
- (rect.getWidth() - (border_width * border_scale * 0.5f)) / (F32)rect.getWidth(),
- (border_height * border_scale * 0.5f) / (F32)rect.getHeight()),
- rect.getWidth() * x_axis,
- rect.getHeight() * y_axis);
-
- } LLRender2D::getInstance()->popMatrix();
+ F32 border_scale = 1.f;
+ F32 border_height = (1.f - mScaleRegion.getHeight()) * getHeight();
+ F32 border_width = (1.f - mScaleRegion.getWidth()) * getWidth();
+ if (rect.getHeight() < border_height || rect.getWidth() < border_width)
+ {
+ if(border_height - rect.getHeight() > border_width - rect.getWidth())
+ {
+ border_scale = (F32)rect.getHeight() / border_height;
+ }
+ else
+ {
+ border_scale = (F32)rect.getWidth() / border_width;
+ }
+ }
+
+ LLRender2D::getInstance()->pushMatrix();
+ {
+ LLVector3 rect_origin = origin_agent + (rect.mLeft * x_axis) + (rect.mBottom * y_axis);
+ LLRender2D::getInstance()->translate(rect_origin.mV[VX],
+ rect_origin.mV[VY],
+ rect_origin.mV[VZ]);
+ gGL.getTexUnit(0)->bind(getImage());
+ gGL.color4fv(color.mV);
+
+ LLRectf center_uv_rect(mClipRegion.mLeft + mScaleRegion.mLeft * mClipRegion.getWidth(),
+ mClipRegion.mBottom + mScaleRegion.mTop * mClipRegion.getHeight(),
+ mClipRegion.mLeft + mScaleRegion.mRight * mClipRegion.getWidth(),
+ mClipRegion.mBottom + mScaleRegion.mBottom * mClipRegion.getHeight());
+ gl_segmented_rect_3d_tex(mClipRegion,
+ center_uv_rect,
+ LLRectf(border_width * border_scale * 0.5f / (F32)rect.getWidth(),
+ (rect.getHeight() - (border_height * border_scale * 0.5f)) / (F32)rect.getHeight(),
+ (rect.getWidth() - (border_width * border_scale * 0.5f)) / (F32)rect.getWidth(),
+ (border_height * border_scale * 0.5f) / (F32)rect.getHeight()),
+ rect.getWidth() * x_axis,
+ rect.getHeight() * y_axis);
+
+ } LLRender2D::getInstance()->popMatrix();
}
//#include "lluiimage.inl"
-boost::signals2::connection LLUIImage::addLoadedCallback( const image_loaded_signal_t::slot_type& cb )
+boost::signals2::connection LLUIImage::addLoadedCallback( const image_loaded_signal_t::slot_type& cb )
{
- if (!mImageLoaded)
- {
- mImageLoaded = new image_loaded_signal_t();
- }
- return mImageLoaded->connect(cb);
+ if (!mImageLoaded)
+ {
+ mImageLoaded = new image_loaded_signal_t();
+ }
+ return mImageLoaded->connect(cb);
}
void LLUIImage::onImageLoaded()
{
- if (mImageLoaded)
- {
- (*mImageLoaded)();
- }
+ if (mImageLoaded)
+ {
+ (*mImageLoaded)();
+ }
}
namespace LLInitParam
{
- void ParamValue<LLUIImage*>::updateValueFromBlock()
- {
- // The keyword "none" is specifically requesting a null image
- // do not default to current value. Used to overwrite template images.
- if (name() == "none")
- {
- updateValue(NULL);
- return;
- }
-
- LLUIImage* imagep = LLRender2D::getInstance()->getUIImage(name());
- if (imagep)
- {
- updateValue(imagep);
- }
- }
-
- void ParamValue<LLUIImage*>::updateBlockFromValue(bool make_block_authoritative)
- {
- if (getValue() == NULL)
- {
- name.set("none", make_block_authoritative);
- }
- else
- {
- name.set(getValue()->getName(), make_block_authoritative);
- }
- }
-
-
- bool ParamCompare<LLUIImage*, false>::equals(
- LLUIImage* const &a,
- LLUIImage* const &b)
- {
- // force all LLUIImages for XML UI export to be "non-default"
- if (!a && !b)
- return false;
- else
- return (a == b);
- }
+ void ParamValue<LLUIImage*>::updateValueFromBlock()
+ {
+ // The keyword "none" is specifically requesting a null image
+ // do not default to current value. Used to overwrite template images.
+ if (name() == "none")
+ {
+ updateValue(NULL);
+ return;
+ }
+
+ LLUIImage* imagep = LLRender2D::getInstance()->getUIImage(name());
+ if (imagep)
+ {
+ updateValue(imagep);
+ }
+ }
+
+ void ParamValue<LLUIImage*>::updateBlockFromValue(bool make_block_authoritative)
+ {
+ if (getValue() == NULL)
+ {
+ name.set("none", make_block_authoritative);
+ }
+ else
+ {
+ name.set(getValue()->getName(), make_block_authoritative);
+ }
+ }
+
+
+ bool ParamCompare<LLUIImage*, false>::equals(
+ LLUIImage* const &a,
+ LLUIImage* const &b)
+ {
+ // force all LLUIImages for XML UI export to be "non-default"
+ if (!a && !b)
+ return false;
+ else
+ return (a == b);
+ }
}
diff --git a/indra/llrender/lluiimage.h b/indra/llrender/lluiimage.h
index e462e19004..7988243a89 100644
--- a/indra/llrender/lluiimage.h
+++ b/indra/llrender/lluiimage.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file lluiimage.h
* @brief wrapper for images used in the UI that handles smart scaling, etc.
*
* $LicenseInfo:firstyear=2007&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -43,70 +43,70 @@ extern const LLColor4 UI_VERTEX_COLOR;
class LLUIImage : public LLRefCount
{
public:
- enum EScaleStyle
- {
- SCALE_INNER,
- SCALE_OUTER
- };
+ enum EScaleStyle
+ {
+ SCALE_INNER,
+ SCALE_OUTER
+ };
- typedef boost::signals2::signal<void (void)> image_loaded_signal_t;
+ typedef boost::signals2::signal<void (void)> image_loaded_signal_t;
- LLUIImage(const std::string& name, LLPointer<LLTexture> image);
- virtual ~LLUIImage();
+ LLUIImage(const std::string& name, LLPointer<LLTexture> image);
+ virtual ~LLUIImage();
- LL_FORCE_INLINE void setClipRegion(const LLRectf& region)
- {
- mClipRegion = region;
+ LL_FORCE_INLINE void setClipRegion(const LLRectf& region)
+ {
+ mClipRegion = region;
}
- LL_FORCE_INLINE void setScaleRegion(const LLRectf& region)
- {
- mScaleRegion = region;
+ LL_FORCE_INLINE void setScaleRegion(const LLRectf& region)
+ {
+ mScaleRegion = region;
}
- LL_FORCE_INLINE void setScaleStyle(EScaleStyle style)
+ LL_FORCE_INLINE void setScaleStyle(EScaleStyle style)
{
- mScaleStyle = style;
+ mScaleStyle = style;
}
- LL_FORCE_INLINE LLPointer<LLTexture> getImage() { return mImage; }
- LL_FORCE_INLINE const LLPointer<LLTexture>& getImage() const { return mImage; }
+ LL_FORCE_INLINE LLPointer<LLTexture> getImage() { return mImage; }
+ LL_FORCE_INLINE const LLPointer<LLTexture>& getImage() const { return mImage; }
+
+ LL_FORCE_INLINE void draw(S32 x, S32 y, S32 width, S32 height, const LLColor4& color = UI_VERTEX_COLOR) const;
+ LL_FORCE_INLINE void draw(S32 x, S32 y, const LLColor4& color = UI_VERTEX_COLOR) const;
+ LL_FORCE_INLINE void draw(const LLRect& rect, const LLColor4& color = UI_VERTEX_COLOR) const { draw(rect.mLeft, rect.mBottom, rect.getWidth(), rect.getHeight(), color); }
- LL_FORCE_INLINE void draw(S32 x, S32 y, S32 width, S32 height, const LLColor4& color = UI_VERTEX_COLOR) const;
- LL_FORCE_INLINE void draw(S32 x, S32 y, const LLColor4& color = UI_VERTEX_COLOR) const;
- LL_FORCE_INLINE void draw(const LLRect& rect, const LLColor4& color = UI_VERTEX_COLOR) const { draw(rect.mLeft, rect.mBottom, rect.getWidth(), rect.getHeight(), color); }
-
- LL_FORCE_INLINE void drawSolid(S32 x, S32 y, S32 width, S32 height, const LLColor4& color) const;
- LL_FORCE_INLINE void drawSolid(const LLRect& rect, const LLColor4& color) const { drawSolid(rect.mLeft, rect.mBottom, rect.getWidth(), rect.getHeight(), color); }
- LL_FORCE_INLINE void drawSolid(S32 x, S32 y, const LLColor4& color) const { drawSolid(x, y, getWidth(), getHeight(), color); }
+ LL_FORCE_INLINE void drawSolid(S32 x, S32 y, S32 width, S32 height, const LLColor4& color) const;
+ LL_FORCE_INLINE void drawSolid(const LLRect& rect, const LLColor4& color) const { drawSolid(rect.mLeft, rect.mBottom, rect.getWidth(), rect.getHeight(), color); }
+ LL_FORCE_INLINE void drawSolid(S32 x, S32 y, const LLColor4& color) const { drawSolid(x, y, getWidth(), getHeight(), color); }
- LL_FORCE_INLINE void drawBorder(S32 x, S32 y, S32 width, S32 height, const LLColor4& color, S32 border_width) const;
- LL_FORCE_INLINE void drawBorder(const LLRect& rect, const LLColor4& color, S32 border_width) const { drawBorder(rect.mLeft, rect.mBottom, rect.getWidth(), rect.getHeight(), color, border_width); }
- LL_FORCE_INLINE void drawBorder(S32 x, S32 y, const LLColor4& color, S32 border_width) const { drawBorder(x, y, getWidth(), getHeight(), color, border_width); }
+ LL_FORCE_INLINE void drawBorder(S32 x, S32 y, S32 width, S32 height, const LLColor4& color, S32 border_width) const;
+ LL_FORCE_INLINE void drawBorder(const LLRect& rect, const LLColor4& color, S32 border_width) const { drawBorder(rect.mLeft, rect.mBottom, rect.getWidth(), rect.getHeight(), color, border_width); }
+ LL_FORCE_INLINE void drawBorder(S32 x, S32 y, const LLColor4& color, S32 border_width) const { drawBorder(x, y, getWidth(), getHeight(), color, border_width); }
- void draw3D(const LLVector3& origin_agent, const LLVector3& x_axis, const LLVector3& y_axis, const LLRect& rect, const LLColor4& color);
+ void draw3D(const LLVector3& origin_agent, const LLVector3& x_axis, const LLVector3& y_axis, const LLRect& rect, const LLColor4& color);
- LL_FORCE_INLINE const std::string& getName() const { return mName; }
+ LL_FORCE_INLINE const std::string& getName() const { return mName; }
- virtual S32 getWidth() const;
- virtual S32 getHeight() const;
+ virtual S32 getWidth() const;
+ virtual S32 getHeight() const;
- // returns dimensions of underlying textures, which might not be equal to ui image portion
- LL_FORCE_INLINE S32 getTextureWidth() const;
- LL_FORCE_INLINE S32 getTextureHeight() const;
+ // returns dimensions of underlying textures, which might not be equal to ui image portion
+ LL_FORCE_INLINE S32 getTextureWidth() const;
+ LL_FORCE_INLINE S32 getTextureHeight() const;
- boost::signals2::connection addLoadedCallback( const image_loaded_signal_t::slot_type& cb );
+ boost::signals2::connection addLoadedCallback( const image_loaded_signal_t::slot_type& cb );
- void onImageLoaded();
+ void onImageLoaded();
protected:
- image_loaded_signal_t* mImageLoaded;
+ image_loaded_signal_t* mImageLoaded;
- std::string mName;
- LLRectf mScaleRegion;
- LLRectf mClipRegion;
- LLPointer<LLTexture> mImage;
- EScaleStyle mScaleStyle;
+ std::string mName;
+ LLRectf mScaleRegion;
+ LLRectf mClipRegion;
+ LLPointer<LLTexture> mImage;
+ EScaleStyle mScaleStyle;
mutable S32 mCachedW;
mutable S32 mCachedH;
};
@@ -115,33 +115,33 @@ protected:
namespace LLInitParam
{
- template<>
- class ParamValue<LLUIImage*>
- : public CustomParamValue<LLUIImage*>
- {
- typedef boost::add_reference<boost::add_const<LLUIImage*>::type>::type T_const_ref;
- typedef CustomParamValue<LLUIImage*> super_t;
- public:
- Optional<std::string> name;
-
- ParamValue(LLUIImage* const& image = NULL)
- : super_t(image)
- {
- updateBlockFromValue(false);
- addSynonym(name, "name");
- }
-
- void updateValueFromBlock();
- void updateBlockFromValue(bool make_block_authoritative);
- };
-
- // Need custom comparison function for our test app, which only loads
- // LLUIImage* as NULL.
- template<>
- struct ParamCompare<LLUIImage*, false>
- {
- static bool equals(LLUIImage* const &a, LLUIImage* const &b);
- };
+ template<>
+ class ParamValue<LLUIImage*>
+ : public CustomParamValue<LLUIImage*>
+ {
+ typedef boost::add_reference<boost::add_const<LLUIImage*>::type>::type T_const_ref;
+ typedef CustomParamValue<LLUIImage*> super_t;
+ public:
+ Optional<std::string> name;
+
+ ParamValue(LLUIImage* const& image = NULL)
+ : super_t(image)
+ {
+ updateBlockFromValue(false);
+ addSynonym(name, "name");
+ }
+
+ void updateValueFromBlock();
+ void updateBlockFromValue(bool make_block_authoritative);
+ };
+
+ // Need custom comparison function for our test app, which only loads
+ // LLUIImage* as NULL.
+ template<>
+ struct ParamCompare<LLUIImage*, false>
+ {
+ static bool equals(LLUIImage* const &a, LLUIImage* const &b);
+ };
}
typedef LLPointer<LLUIImage> LLUIImagePtr;
diff --git a/indra/llrender/lluiimage.inl b/indra/llrender/lluiimage.inl
index f5227556f0..a69616c0c1 100644
--- a/indra/llrender/lluiimage.inl
+++ b/indra/llrender/lluiimage.inl
@@ -1,66 +1,66 @@
-/**
+/**
* @file lluiimage.inl
* @brief UI inline func implementation
*
* $LicenseInfo:firstyear=2007&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
void LLUIImage::draw(S32 x, S32 y, const LLColor4& color) const
{
- draw(x, y, getWidth(), getHeight(), color);
+ draw(x, y, getWidth(), getHeight(), color);
}
void LLUIImage::draw(S32 x, S32 y, S32 width, S32 height, const LLColor4& color) const
{
- gl_draw_scaled_image_with_border(
- x, y,
- width, height,
- mImage,
- color,
- FALSE,
- mClipRegion,
- mScaleRegion,
- mScaleStyle == SCALE_INNER);
+ gl_draw_scaled_image_with_border(
+ x, y,
+ width, height,
+ mImage,
+ color,
+ FALSE,
+ mClipRegion,
+ mScaleRegion,
+ mScaleStyle == SCALE_INNER);
}
void LLUIImage::drawSolid(S32 x, S32 y, S32 width, S32 height, const LLColor4& color) const
{
- gl_draw_scaled_image_with_border(
- x, y,
- width, height,
- mImage,
- color,
- TRUE,
- mClipRegion,
- mScaleRegion,
- mScaleStyle == SCALE_INNER);
+ gl_draw_scaled_image_with_border(
+ x, y,
+ width, height,
+ mImage,
+ color,
+ TRUE,
+ mClipRegion,
+ mScaleRegion,
+ mScaleStyle == SCALE_INNER);
}
void LLUIImage::drawBorder(S32 x, S32 y, S32 width, S32 height, const LLColor4& color, S32 border_width) const
{
- LLRect border_rect;
- border_rect.setOriginAndSize(x, y, width, height);
- border_rect.stretch(border_width, border_width);
- drawSolid(border_rect, color);
+ LLRect border_rect;
+ border_rect.setOriginAndSize(x, y, width, height);
+ border_rect.stretch(border_width, border_width);
+ drawSolid(border_rect, color);
}
// returns dimensions of underlying textures, which might not be equal to ui image portion
diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp
index de27636c33..c98de6bf06 100644
--- a/indra/llrender/llvertexbuffer.cpp
+++ b/indra/llrender/llvertexbuffer.cpp
@@ -1,25 +1,25 @@
-/**
+/**
* @file llvertexbuffer.cpp
* @brief LLVertexBuffer implementation
*
* $LicenseInfo:firstyear=2003&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -41,25 +41,25 @@
//helper function, returns first number > v that is a power of 2, or v if v is already a power of 2
U32 nhpo2(U32 v)
{
- U32 r = 1;
- while (r < v) {
- r *= 2;
- }
- return r;
+ U32 r = 1;
+ while (r < v) {
+ r *= 2;
+ }
+ return r;
}
//which power of 2 is i?
//assumes i is a power of 2 > 0
U32 wpo2(U32 i)
{
- llassert(i > 0);
- llassert(nhpo2(i) == i);
+ llassert(i > 0);
+ llassert(nhpo2(i) == i);
- U32 r = 0;
+ U32 r = 0;
- while (i >>= 1) ++r;
+ while (i >>= 1) ++r;
- return r;
+ return r;
}
struct CompareMappedRegion
@@ -381,7 +381,7 @@ public:
Entry& entry = entries.back();
name = entry.mGLName;
data = entry.mData;
-
+
entries.pop_back();
if (entries.empty())
{
@@ -474,9 +474,9 @@ public:
}
#if 0
- LL_INFOS() << llformat("(%d/%d)/%d MB (distributed/allocated)/total in VBO Pool. Overhead: %d percent. Hit rate: %d percent",
- mDistributed / 1000000,
- mAllocated / 1000000,
+ LL_INFOS() << llformat("(%d/%d)/%d MB (distributed/allocated)/total in VBO Pool. Overhead: %d percent. Hit rate: %d percent",
+ mDistributed / 1000000,
+ mAllocated / 1000000,
(mAllocated + mReserved) / 1000000, // total bytes
((mAllocated+mReserved-mDistributed)*100)/llmax(mDistributed, (U64) 1), // overhead percent
(mHits*100)/llmax(mMisses+mHits, (U32)1)) // hit rate percent
@@ -522,7 +522,7 @@ U64 LLVertexBuffer::getBytesAllocated()
}
//============================================================================
-//
+//
//static
U32 LLVertexBuffer::sGLRenderBuffer = 0;
U32 LLVertexBuffer::sGLRenderIndices = 0;
@@ -533,50 +533,50 @@ U32 LLVertexBuffer::sVertexCount = 0;
//NOTE: each component must be AT LEAST 4 bytes in size to avoid a performance penalty on AMD hardware
const U32 LLVertexBuffer::sTypeSize[LLVertexBuffer::TYPE_MAX] =
{
- sizeof(LLVector4), // TYPE_VERTEX,
- sizeof(LLVector4), // TYPE_NORMAL,
- sizeof(LLVector2), // TYPE_TEXCOORD0,
- sizeof(LLVector2), // TYPE_TEXCOORD1,
- sizeof(LLVector2), // TYPE_TEXCOORD2,
- sizeof(LLVector2), // TYPE_TEXCOORD3,
- sizeof(LLColor4U), // TYPE_COLOR,
- sizeof(LLColor4U), // TYPE_EMISSIVE, only alpha is used currently
- sizeof(LLVector4), // TYPE_TANGENT,
- sizeof(F32), // TYPE_WEIGHT,
- sizeof(LLVector4), // TYPE_WEIGHT4,
- sizeof(LLVector4), // TYPE_CLOTHWEIGHT,
- sizeof(LLVector4), // TYPE_TEXTURE_INDEX (actually exists as position.w), no extra data, but stride is 16 bytes
+ sizeof(LLVector4), // TYPE_VERTEX,
+ sizeof(LLVector4), // TYPE_NORMAL,
+ sizeof(LLVector2), // TYPE_TEXCOORD0,
+ sizeof(LLVector2), // TYPE_TEXCOORD1,
+ sizeof(LLVector2), // TYPE_TEXCOORD2,
+ sizeof(LLVector2), // TYPE_TEXCOORD3,
+ sizeof(LLColor4U), // TYPE_COLOR,
+ sizeof(LLColor4U), // TYPE_EMISSIVE, only alpha is used currently
+ sizeof(LLVector4), // TYPE_TANGENT,
+ sizeof(F32), // TYPE_WEIGHT,
+ sizeof(LLVector4), // TYPE_WEIGHT4,
+ sizeof(LLVector4), // TYPE_CLOTHWEIGHT,
+ sizeof(LLVector4), // TYPE_TEXTURE_INDEX (actually exists as position.w), no extra data, but stride is 16 bytes
};
static const std::string vb_type_name[] =
{
- "TYPE_VERTEX",
- "TYPE_NORMAL",
- "TYPE_TEXCOORD0",
- "TYPE_TEXCOORD1",
- "TYPE_TEXCOORD2",
- "TYPE_TEXCOORD3",
- "TYPE_COLOR",
- "TYPE_EMISSIVE",
- "TYPE_TANGENT",
- "TYPE_WEIGHT",
- "TYPE_WEIGHT4",
- "TYPE_CLOTHWEIGHT",
- "TYPE_TEXTURE_INDEX",
- "TYPE_MAX",
- "TYPE_INDEX",
+ "TYPE_VERTEX",
+ "TYPE_NORMAL",
+ "TYPE_TEXCOORD0",
+ "TYPE_TEXCOORD1",
+ "TYPE_TEXCOORD2",
+ "TYPE_TEXCOORD3",
+ "TYPE_COLOR",
+ "TYPE_EMISSIVE",
+ "TYPE_TANGENT",
+ "TYPE_WEIGHT",
+ "TYPE_WEIGHT4",
+ "TYPE_CLOTHWEIGHT",
+ "TYPE_TEXTURE_INDEX",
+ "TYPE_MAX",
+ "TYPE_INDEX",
};
const U32 LLVertexBuffer::sGLMode[LLRender::NUM_MODES] =
{
- GL_TRIANGLES,
- GL_TRIANGLE_STRIP,
- GL_TRIANGLE_FAN,
- GL_POINTS,
- GL_LINES,
- GL_LINE_STRIP,
- GL_QUADS,
- GL_LINE_LOOP,
+ GL_TRIANGLES,
+ GL_TRIANGLE_STRIP,
+ GL_TRIANGLE_FAN,
+ GL_POINTS,
+ GL_LINES,
+ GL_LINE_STRIP,
+ GL_QUADS,
+ GL_LINE_LOOP,
};
//static
@@ -598,7 +598,7 @@ void LLVertexBuffer::setupClientArrays(U32 data_mask)
}
}
else
- { //was disabled
+ { //was disabled
if (data_mask & mask)
{ //needs to be enabled
glEnableVertexAttribArray(loc);
@@ -627,18 +627,18 @@ void LLVertexBuffer::drawArrays(U32 mode, const std::vector<LLVector3>& pos)
void LLVertexBuffer::drawElements(U32 mode, const LLVector4a* pos, const LLVector2* tc, U32 num_indices, const U16* indicesp)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_VERTEX;
- llassert(LLGLSLShader::sCurBoundShaderPtr != NULL);
+ llassert(LLGLSLShader::sCurBoundShaderPtr != NULL);
+
+ gGL.syncMatrices();
- gGL.syncMatrices();
+ U32 mask = LLVertexBuffer::MAP_VERTEX;
+ if (tc)
+ {
+ mask = mask | LLVertexBuffer::MAP_TEXCOORD0;
+ }
- U32 mask = LLVertexBuffer::MAP_VERTEX;
- if (tc)
- {
- mask = mask | LLVertexBuffer::MAP_TEXCOORD0;
- }
+ unbind();
- unbind();
-
gGL.begin(mode);
if (tc != nullptr)
@@ -672,32 +672,32 @@ bool LLVertexBuffer::validateRange(U32 start, U32 end, U32 count, U32 indices_of
llassert(start < (U32)mNumVerts);
llassert(end < (U32)mNumVerts);
- if (start >= (U32) mNumVerts ||
- end >= (U32) mNumVerts)
- {
- LL_ERRS() << "Bad vertex buffer draw range: [" << start << ", " << end << "] vs " << mNumVerts << LL_ENDL;
- }
+ if (start >= (U32) mNumVerts ||
+ end >= (U32) mNumVerts)
+ {
+ LL_ERRS() << "Bad vertex buffer draw range: [" << start << ", " << end << "] vs " << mNumVerts << LL_ENDL;
+ }
- llassert(mNumIndices >= 0);
+ llassert(mNumIndices >= 0);
- if (indices_offset >= (U32) mNumIndices ||
- indices_offset + count > (U32) mNumIndices)
- {
- LL_ERRS() << "Bad index buffer draw range: [" << indices_offset << ", " << indices_offset+count << "]" << LL_ENDL;
- }
+ if (indices_offset >= (U32) mNumIndices ||
+ indices_offset + count > (U32) mNumIndices)
+ {
+ LL_ERRS() << "Bad index buffer draw range: [" << indices_offset << ", " << indices_offset+count << "]" << LL_ENDL;
+ }
- {
- U16* idx = (U16*) mMappedIndexData+indices_offset;
- for (U32 i = 0; i < count; ++i)
- {
+ {
+ U16* idx = (U16*) mMappedIndexData+indices_offset;
+ for (U32 i = 0; i < count; ++i)
+ {
llassert(idx[i] >= start);
llassert(idx[i] <= end);
- if (idx[i] < start || idx[i] > end)
- {
- LL_ERRS() << "Index out of range: " << idx[i] << " not in [" << start << ", " << end << "]" << LL_ENDL;
- }
- }
+ if (idx[i] < start || idx[i] > end)
+ {
+ LL_ERRS() << "Index out of range: " << idx[i] << " not in [" << start << ", " << end << "]" << LL_ENDL;
+ }
+ }
LLVector4a* v = (LLVector4a*)mMappedData;
@@ -709,29 +709,29 @@ bool LLVertexBuffer::validateRange(U32 start, U32 end, U32 count, U32 indices_of
}
}
- LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr;
+ LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr;
+
+ if (shader && shader->mFeatures.mIndexedTextureChannels > 1)
+ {
+ LLVector4a* v = (LLVector4a*) mMappedData;
- if (shader && shader->mFeatures.mIndexedTextureChannels > 1)
- {
- LLVector4a* v = (LLVector4a*) mMappedData;
-
- for (U32 i = start; i < end; i++)
- {
+ for (U32 i = start; i < end; i++)
+ {
U32 idx = (U32) (v[i][3]+0.25f);
- if (idx >= shader->mFeatures.mIndexedTextureChannels)
- {
- LL_ERRS() << "Bad texture index found in vertex data stream." << LL_ENDL;
- }
- }
- }
- }
+ if (idx >= shader->mFeatures.mIndexedTextureChannels)
+ {
+ LL_ERRS() << "Bad texture index found in vertex data stream." << LL_ENDL;
+ }
+ }
+ }
+ }
return true;
}
#ifdef LL_PROFILER_ENABLE_RENDER_DOC
void LLVertexBuffer::setLabel(const char* label) {
- LL_LABEL_OBJECT_GL(GL_BUFFER, mGLBuffer, strlen(label), label);
+ LL_LABEL_OBJECT_GL(GL_BUFFER, mGLBuffer, strlen(label), label);
}
#endif
@@ -756,7 +756,7 @@ void LLVertexBuffer::drawArrays(U32 mode, U32 first, U32 count) const
llassert(first + count <= mNumVerts);
llassert(mGLBuffer == sGLRenderBuffer);
llassert(mGLIndices == sGLRenderIndices);
-
+
gGL.syncMatrices();
glDrawArrays(sGLMode[mode], first, count);
}
@@ -778,21 +778,21 @@ void LLVertexBuffer::initClass(LLWindow* window)
#endif
}
-//static
+//static
void LLVertexBuffer::unbind()
{
glBindBuffer(GL_ARRAY_BUFFER, 0);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
- sGLRenderBuffer = 0;
- sGLRenderIndices = 0;
+ sGLRenderBuffer = 0;
+ sGLRenderIndices = 0;
}
//static
void LLVertexBuffer::cleanupClass()
{
- unbind();
-
+ unbind();
+
delete sVBOPool;
sVBOPool = nullptr;
@@ -812,71 +812,71 @@ void LLVertexBuffer::cleanupClass()
//----------------------------------------------------------------------------
-LLVertexBuffer::LLVertexBuffer(U32 typemask)
-: LLRefCount(),
- mTypeMask(typemask)
+LLVertexBuffer::LLVertexBuffer(U32 typemask)
+: LLRefCount(),
+ mTypeMask(typemask)
{
- //zero out offsets
- for (U32 i = 0; i < TYPE_MAX; i++)
- {
- mOffsets[i] = 0;
- }
+ //zero out offsets
+ for (U32 i = 0; i < TYPE_MAX; i++)
+ {
+ mOffsets[i] = 0;
+ }
}
//static
U32 LLVertexBuffer::calcOffsets(const U32& typemask, U32* offsets, U32 num_vertices)
{
U32 offset = 0;
- for (U32 i=0; i<TYPE_TEXTURE_INDEX; i++)
- {
- U32 mask = 1<<i;
- if (typemask & mask)
- {
- if (offsets && LLVertexBuffer::sTypeSize[i])
- {
- offsets[i] = offset;
- offset += LLVertexBuffer::sTypeSize[i]*num_vertices;
- offset = (offset + 0xF) & ~0xF;
- }
- }
- }
-
- offsets[TYPE_TEXTURE_INDEX] = offsets[TYPE_VERTEX] + 12;
-
- return offset;
+ for (U32 i=0; i<TYPE_TEXTURE_INDEX; i++)
+ {
+ U32 mask = 1<<i;
+ if (typemask & mask)
+ {
+ if (offsets && LLVertexBuffer::sTypeSize[i])
+ {
+ offsets[i] = offset;
+ offset += LLVertexBuffer::sTypeSize[i]*num_vertices;
+ offset = (offset + 0xF) & ~0xF;
+ }
+ }
+ }
+
+ offsets[TYPE_TEXTURE_INDEX] = offsets[TYPE_VERTEX] + 12;
+
+ return offset;
}
-//static
+//static
U32 LLVertexBuffer::calcVertexSize(const U32& typemask)
{
U32 size = 0;
- for (U32 i = 0; i < TYPE_TEXTURE_INDEX; i++)
- {
- U32 mask = 1<<i;
- if (typemask & mask)
- {
- size += LLVertexBuffer::sTypeSize[i];
- }
- }
-
- return size;
+ for (U32 i = 0; i < TYPE_TEXTURE_INDEX; i++)
+ {
+ U32 mask = 1<<i;
+ if (typemask & mask)
+ {
+ size += LLVertexBuffer::sTypeSize[i];
+ }
+ }
+
+ return size;
}
// protected, use unref()
//virtual
LLVertexBuffer::~LLVertexBuffer()
{
- destroyGLBuffer();
- destroyGLIndices();
-
- if (mMappedData)
- {
- LL_ERRS() << "Failed to clear vertex buffer's vertices" << LL_ENDL;
- }
- if (mMappedIndexData)
- {
- LL_ERRS() << "Failed to clear vertex buffer's indices" << LL_ENDL;
- }
+ destroyGLBuffer();
+ destroyGLIndices();
+
+ if (mMappedData)
+ {
+ LL_ERRS() << "Failed to clear vertex buffer's vertices" << LL_ENDL;
+ }
+ if (mMappedIndexData)
+ {
+ LL_ERRS() << "Failed to clear vertex buffer's indices" << LL_ENDL;
+ }
};
//----------------------------------------------------------------------------
@@ -914,54 +914,54 @@ void LLVertexBuffer::genIndices(U32 size)
bool LLVertexBuffer::createGLBuffer(U32 size)
{
- if (mGLBuffer || mMappedData)
- {
- destroyGLBuffer();
- }
-
- if (size == 0)
- {
- return true;
- }
-
- bool success = true;
-
- genBuffer(size);
-
- if (!mMappedData)
- {
- success = false;
- }
- return success;
+ if (mGLBuffer || mMappedData)
+ {
+ destroyGLBuffer();
+ }
+
+ if (size == 0)
+ {
+ return true;
+ }
+
+ bool success = true;
+
+ genBuffer(size);
+
+ if (!mMappedData)
+ {
+ success = false;
+ }
+ return success;
}
bool LLVertexBuffer::createGLIndices(U32 size)
{
- if (mGLIndices)
- {
- destroyGLIndices();
- }
-
- if (size == 0)
- {
- return true;
- }
-
- bool success = true;
-
- genIndices(size);
-
- if (!mMappedIndexData)
- {
- success = false;
- }
- return success;
+ if (mGLIndices)
+ {
+ destroyGLIndices();
+ }
+
+ if (size == 0)
+ {
+ return true;
+ }
+
+ bool success = true;
+
+ genIndices(size);
+
+ if (!mMappedIndexData)
+ {
+ success = false;
+ }
+ return success;
}
void LLVertexBuffer::destroyGLBuffer()
{
- if (mGLBuffer || mMappedData)
- {
+ if (mGLBuffer || mMappedData)
+ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_VERTEX;
//llassert(sVBOPool);
if (sVBOPool)
@@ -972,13 +972,13 @@ void LLVertexBuffer::destroyGLBuffer()
mSize = 0;
mGLBuffer = 0;
mMappedData = nullptr;
- }
+ }
}
void LLVertexBuffer::destroyGLIndices()
{
- if (mGLIndices || mMappedIndexData)
- {
+ if (mGLIndices || mMappedIndexData)
+ {
LL_PROFILE_ZONE_SCOPED_CATEGORY_VERTEX;
//llassert(sVBOPool);
if (sVBOPool)
@@ -989,22 +989,22 @@ void LLVertexBuffer::destroyGLIndices()
mIndicesSize = 0;
mGLIndices = 0;
mMappedIndexData = nullptr;
- }
+ }
}
bool LLVertexBuffer::updateNumVerts(U32 nverts)
{
- llassert(nverts >= 0);
+ llassert(nverts >= 0);
- bool success = true;
+ bool success = true;
- if (nverts > 65536)
- {
- LL_WARNS() << "Vertex buffer overflow!" << LL_ENDL;
- nverts = 65536;
- }
+ if (nverts > 65536)
+ {
+ LL_WARNS() << "Vertex buffer overflow!" << LL_ENDL;
+ nverts = 65536;
+ }
- U32 needed_size = calcOffsets(mTypeMask, mOffsets, nverts);
+ U32 needed_size = calcOffsets(mTypeMask, mOffsets, nverts);
if (needed_size != mSize)
{
@@ -1012,42 +1012,42 @@ bool LLVertexBuffer::updateNumVerts(U32 nverts)
}
llassert(mSize == needed_size);
- mNumVerts = nverts;
- return success;
+ mNumVerts = nverts;
+ return success;
}
bool LLVertexBuffer::updateNumIndices(U32 nindices)
{
- llassert(nindices >= 0);
+ llassert(nindices >= 0);
- bool success = true;
+ bool success = true;
- U32 needed_size = sizeof(U16) * nindices;
+ U32 needed_size = sizeof(U16) * nindices;
- if (needed_size != mIndicesSize)
- {
- success &= createGLIndices(needed_size);
- }
+ if (needed_size != mIndicesSize)
+ {
+ success &= createGLIndices(needed_size);
+ }
llassert(mIndicesSize == needed_size);
- mNumIndices = nindices;
- return success;
+ mNumIndices = nindices;
+ return success;
}
bool LLVertexBuffer::allocateBuffer(U32 nverts, U32 nindices)
{
- if (nverts < 0 || nindices < 0 ||
- nverts > 65536)
- {
- LL_ERRS() << "Bad vertex buffer allocation: " << nverts << " : " << nindices << LL_ENDL;
- }
+ if (nverts < 0 || nindices < 0 ||
+ nverts > 65536)
+ {
+ LL_ERRS() << "Bad vertex buffer allocation: " << nverts << " : " << nindices << LL_ENDL;
+ }
+
+ bool success = true;
- bool success = true;
+ success &= updateNumVerts(nverts);
+ success &= updateNumIndices(nindices);
- success &= updateNumVerts(nverts);
- success &= updateNumIndices(nindices);
-
- return success;
+ return success;
}
//----------------------------------------------------------------------------
@@ -1056,17 +1056,17 @@ bool LLVertexBuffer::allocateBuffer(U32 nverts, U32 nindices)
// otherwise return false
bool expand_region(LLVertexBuffer::MappedRegion& region, U32 start, U32 end)
{
-
- if (end < region.mStart ||
- start > region.mEnd)
- { //gap exists, do not merge
- return false;
- }
+
+ if (end < region.mStart ||
+ start > region.mEnd)
+ { //gap exists, do not merge
+ return false;
+ }
region.mStart = llmin(region.mStart, start);
region.mEnd = llmax(region.mEnd, end);
- return true;
+ return true;
}
@@ -1074,7 +1074,7 @@ bool expand_region(LLVertexBuffer::MappedRegion& region, U32 start, U32 end)
U8* LLVertexBuffer::mapVertexBuffer(LLVertexBuffer::AttributeType type, U32 index, S32 count)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_VERTEX;
-
+
if (count == -1)
{
count = mNumVerts - index;
@@ -1083,24 +1083,24 @@ U8* LLVertexBuffer::mapVertexBuffer(LLVertexBuffer::AttributeType type, U32 inde
U32 start = mOffsets[type] + sTypeSize[type] * index;
U32 end = start + sTypeSize[type] * count-1;
- bool flagged = false;
- // flag region as mapped
- for (U32 i = 0; i < mMappedVertexRegions.size(); ++i)
- {
- MappedRegion& region = mMappedVertexRegions[i];
+ bool flagged = false;
+ // flag region as mapped
+ for (U32 i = 0; i < mMappedVertexRegions.size(); ++i)
+ {
+ MappedRegion& region = mMappedVertexRegions[i];
if (expand_region(region, start, end))
{
flagged = true;
break;
}
- }
+ }
- if (!flagged)
- {
- //didn't expand an existing region, make a new one
+ if (!flagged)
+ {
+ //didn't expand an existing region, make a new one
mMappedVertexRegions.push_back({ start, end });
- }
-
+ }
+
return mMappedData+mOffsets[type]+sTypeSize[type]*index;
}
@@ -1108,11 +1108,11 @@ U8* LLVertexBuffer::mapVertexBuffer(LLVertexBuffer::AttributeType type, U32 inde
U8* LLVertexBuffer::mapIndexBuffer(U32 index, S32 count)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_VERTEX;
-
- if (count == -1)
- {
- count = mNumIndices-index;
- }
+
+ if (count == -1)
+ {
+ count = mNumIndices-index;
+ }
U32 start = sizeof(U16) * index;
U32 end = start + sizeof(U16) * count-1;
@@ -1175,23 +1175,23 @@ void LLVertexBuffer::unmapBuffer()
}
};
- if (!mMappedVertexRegions.empty())
- {
+ if (!mMappedVertexRegions.empty())
+ {
LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("unmapBuffer - vertex");
if (sGLRenderBuffer != mGLBuffer)
{
glBindBuffer(GL_ARRAY_BUFFER, mGLBuffer);
sGLRenderBuffer = mGLBuffer;
}
-
+
U32 start = 0;
U32 end = 0;
std::sort(mMappedVertexRegions.begin(), mMappedVertexRegions.end(), SortMappedRegion());
- for (U32 i = 0; i < mMappedVertexRegions.size(); ++i)
- {
- const MappedRegion& region = mMappedVertexRegions[i];
+ for (U32 i = 0; i < mMappedVertexRegions.size(); ++i)
+ {
+ const MappedRegion& region = mMappedVertexRegions[i];
if (region.mStart == end + 1)
{
end = region.mEnd;
@@ -1202,15 +1202,15 @@ void LLVertexBuffer::unmapBuffer()
start = region.mStart;
end = region.mEnd;
}
- }
+ }
flush_vbo(GL_ARRAY_BUFFER, start, end, (U8*)mMappedData + start);
- mMappedVertexRegions.clear();
- }
-
- if (!mMappedIndexRegions.empty())
- {
+ mMappedVertexRegions.clear();
+ }
+
+ if (!mMappedIndexRegions.empty())
+ {
LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("unmapBuffer - index");
if (mGLIndices != sGLRenderIndices)
@@ -1240,114 +1240,114 @@ void LLVertexBuffer::unmapBuffer()
flush_vbo(GL_ELEMENT_ARRAY_BUFFER, start, end, (U8*)mMappedIndexData + start);
- mMappedIndexRegions.clear();
- }
+ mMappedIndexRegions.clear();
+ }
}
//----------------------------------------------------------------------------
template <class T,LLVertexBuffer::AttributeType type> struct VertexBufferStrider
{
- typedef LLStrider<T> strider_t;
- static bool get(LLVertexBuffer& vbo,
- strider_t& strider,
- S32 index, S32 count)
- {
- if (type == LLVertexBuffer::TYPE_INDEX)
- {
- U8* ptr = vbo.mapIndexBuffer(index, count);
-
- if (ptr == NULL)
- {
- LL_WARNS() << "mapIndexBuffer failed!" << LL_ENDL;
- return false;
- }
-
- strider = (T*)ptr;
- strider.setStride(0);
- return true;
- }
- else if (vbo.hasDataType(type))
- {
+ typedef LLStrider<T> strider_t;
+ static bool get(LLVertexBuffer& vbo,
+ strider_t& strider,
+ S32 index, S32 count)
+ {
+ if (type == LLVertexBuffer::TYPE_INDEX)
+ {
+ U8* ptr = vbo.mapIndexBuffer(index, count);
+
+ if (ptr == NULL)
+ {
+ LL_WARNS() << "mapIndexBuffer failed!" << LL_ENDL;
+ return false;
+ }
+
+ strider = (T*)ptr;
+ strider.setStride(0);
+ return true;
+ }
+ else if (vbo.hasDataType(type))
+ {
U32 stride = LLVertexBuffer::sTypeSize[type];
- U8* ptr = vbo.mapVertexBuffer(type, index, count);
-
- if (ptr == NULL)
- {
- LL_WARNS() << "mapVertexBuffer failed!" << LL_ENDL;
- return false;
- }
-
- strider = (T*)ptr;
- strider.setStride(stride);
- return true;
- }
- else
- {
- LL_ERRS() << "VertexBufferStrider could not find valid vertex data." << LL_ENDL;
- }
- return false;
- }
+ U8* ptr = vbo.mapVertexBuffer(type, index, count);
+
+ if (ptr == NULL)
+ {
+ LL_WARNS() << "mapVertexBuffer failed!" << LL_ENDL;
+ return false;
+ }
+
+ strider = (T*)ptr;
+ strider.setStride(stride);
+ return true;
+ }
+ else
+ {
+ LL_ERRS() << "VertexBufferStrider could not find valid vertex data." << LL_ENDL;
+ }
+ return false;
+ }
};
bool LLVertexBuffer::getVertexStrider(LLStrider<LLVector3>& strider, U32 index, S32 count)
{
- return VertexBufferStrider<LLVector3,TYPE_VERTEX>::get(*this, strider, index, count);
+ return VertexBufferStrider<LLVector3,TYPE_VERTEX>::get(*this, strider, index, count);
}
bool LLVertexBuffer::getVertexStrider(LLStrider<LLVector4a>& strider, U32 index, S32 count)
{
- return VertexBufferStrider<LLVector4a,TYPE_VERTEX>::get(*this, strider, index, count);
+ return VertexBufferStrider<LLVector4a,TYPE_VERTEX>::get(*this, strider, index, count);
}
bool LLVertexBuffer::getIndexStrider(LLStrider<U16>& strider, U32 index, S32 count)
{
- return VertexBufferStrider<U16,TYPE_INDEX>::get(*this, strider, index, count);
+ return VertexBufferStrider<U16,TYPE_INDEX>::get(*this, strider, index, count);
}
bool LLVertexBuffer::getTexCoord0Strider(LLStrider<LLVector2>& strider, U32 index, S32 count)
{
- return VertexBufferStrider<LLVector2,TYPE_TEXCOORD0>::get(*this, strider, index, count);
+ return VertexBufferStrider<LLVector2,TYPE_TEXCOORD0>::get(*this, strider, index, count);
}
bool LLVertexBuffer::getTexCoord1Strider(LLStrider<LLVector2>& strider, U32 index, S32 count)
{
- return VertexBufferStrider<LLVector2,TYPE_TEXCOORD1>::get(*this, strider, index, count);
+ return VertexBufferStrider<LLVector2,TYPE_TEXCOORD1>::get(*this, strider, index, count);
}
bool LLVertexBuffer::getTexCoord2Strider(LLStrider<LLVector2>& strider, U32 index, S32 count)
{
- return VertexBufferStrider<LLVector2,TYPE_TEXCOORD2>::get(*this, strider, index, count);
+ return VertexBufferStrider<LLVector2,TYPE_TEXCOORD2>::get(*this, strider, index, count);
}
bool LLVertexBuffer::getNormalStrider(LLStrider<LLVector3>& strider, U32 index, S32 count)
{
- return VertexBufferStrider<LLVector3,TYPE_NORMAL>::get(*this, strider, index, count);
+ return VertexBufferStrider<LLVector3,TYPE_NORMAL>::get(*this, strider, index, count);
}
bool LLVertexBuffer::getTangentStrider(LLStrider<LLVector3>& strider, U32 index, S32 count)
{
- return VertexBufferStrider<LLVector3,TYPE_TANGENT>::get(*this, strider, index, count);
+ return VertexBufferStrider<LLVector3,TYPE_TANGENT>::get(*this, strider, index, count);
}
bool LLVertexBuffer::getTangentStrider(LLStrider<LLVector4a>& strider, U32 index, S32 count)
{
- return VertexBufferStrider<LLVector4a,TYPE_TANGENT>::get(*this, strider, index, count);
+ return VertexBufferStrider<LLVector4a,TYPE_TANGENT>::get(*this, strider, index, count);
}
bool LLVertexBuffer::getColorStrider(LLStrider<LLColor4U>& strider, U32 index, S32 count)
{
- return VertexBufferStrider<LLColor4U,TYPE_COLOR>::get(*this, strider, index, count);
+ return VertexBufferStrider<LLColor4U,TYPE_COLOR>::get(*this, strider, index, count);
}
bool LLVertexBuffer::getEmissiveStrider(LLStrider<LLColor4U>& strider, U32 index, S32 count)
{
- return VertexBufferStrider<LLColor4U,TYPE_EMISSIVE>::get(*this, strider, index, count);
+ return VertexBufferStrider<LLColor4U,TYPE_EMISSIVE>::get(*this, strider, index, count);
}
bool LLVertexBuffer::getWeightStrider(LLStrider<F32>& strider, U32 index, S32 count)
{
- return VertexBufferStrider<F32,TYPE_WEIGHT>::get(*this, strider, index, count);
+ return VertexBufferStrider<F32,TYPE_WEIGHT>::get(*this, strider, index, count);
}
bool LLVertexBuffer::getWeight4Strider(LLStrider<LLVector4>& strider, U32 index, S32 count)
{
- return VertexBufferStrider<LLVector4,TYPE_WEIGHT4>::get(*this, strider, index, count);
+ return VertexBufferStrider<LLVector4,TYPE_WEIGHT4>::get(*this, strider, index, count);
}
bool LLVertexBuffer::getClothWeightStrider(LLStrider<LLVector4>& strider, U32 index, S32 count)
{
- return VertexBufferStrider<LLVector4,TYPE_CLOTHWEIGHT>::get(*this, strider, index, count);
+ return VertexBufferStrider<LLVector4,TYPE_CLOTHWEIGHT>::get(*this, strider, index, count);
}
//----------------------------------------------------------------------------
@@ -1367,7 +1367,7 @@ void LLVertexBuffer::setBuffer()
// this Vertex Buffer must provide all necessary attributes for currently bound shader
llassert_msg((data_mask & mTypeMask) == data_mask,
- "Attribute mask mismatch! mTypeMask should be a superset of data_mask. data_mask: 0x"
+ "Attribute mask mismatch! mTypeMask should be a superset of data_mask. data_mask: 0x"
<< std::hex << data_mask << " mTypeMask: 0x" << mTypeMask << " Missing: 0x" << (data_mask & ~mTypeMask) << std::dec);
if (sGLRenderBuffer != mGLBuffer)
@@ -1382,7 +1382,7 @@ void LLVertexBuffer::setBuffer()
setupVertexBuffer();
sLastMask = data_mask;
}
-
+
if (mGLIndices != sGLRenderIndices)
{
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mGLIndices);
diff --git a/indra/llrender/llvertexbuffer.h b/indra/llrender/llvertexbuffer.h
index f2d146d4bb..545917cdec 100644
--- a/indra/llrender/llvertexbuffer.h
+++ b/indra/llrender/llvertexbuffer.h
@@ -1,25 +1,25 @@
-/**
+/**
* @file llvertexbuffer.h
* @brief LLVertexBuffer wrapper for OpengGL vertex buffer objects
*
* $LicenseInfo:firstyear=2003&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
- *
+ *
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
- *
+ *
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
+ *
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
@@ -51,51 +51,51 @@
//============================================================================
-// base class
+// base class
class LLPrivateMemoryPool;
class LLVertexBuffer final : public LLRefCount
{
public:
- struct MappedRegion
- {
+ struct MappedRegion
+ {
U32 mStart;
U32 mEnd;
- };
+ };
- LLVertexBuffer(const LLVertexBuffer& rhs)
- {
- *this = rhs;
- }
+ LLVertexBuffer(const LLVertexBuffer& rhs)
+ {
+ *this = rhs;
+ }
- const LLVertexBuffer& operator=(const LLVertexBuffer& rhs)
- {
- LL_ERRS() << "Illegal operation!" << LL_ENDL;
- return *this;
- }
+ const LLVertexBuffer& operator=(const LLVertexBuffer& rhs)
+ {
+ LL_ERRS() << "Illegal operation!" << LL_ENDL;
+ return *this;
+ }
- static void initClass(LLWindow* window);
- static void cleanupClass();
- static void setupClientArrays(U32 data_mask);
- static void drawArrays(U32 mode, const std::vector<LLVector3>& pos);
- static void drawElements(U32 mode, const LLVector4a* pos, const LLVector2* tc, U32 num_indices, const U16* indicesp);
+ static void initClass(LLWindow* window);
+ static void cleanupClass();
+ static void setupClientArrays(U32 data_mask);
+ static void drawArrays(U32 mode, const std::vector<LLVector3>& pos);
+ static void drawElements(U32 mode, const LLVector4a* pos, const LLVector2* tc, U32 num_indices, const U16* indicesp);
- static void unbind(); //unbind any bound vertex buffer
+ static void unbind(); //unbind any bound vertex buffer
- //get the size of a vertex with the given typemask
- static U32 calcVertexSize(const U32& typemask);
+ //get the size of a vertex with the given typemask
+ static U32 calcVertexSize(const U32& typemask);
- //get the size of a buffer with the given typemask and vertex count
- //fill offsets with the offset of each vertex component array into the buffer
- // indexed by the following enum
- static U32 calcOffsets(const U32& typemask, U32* offsets, U32 num_vertices);
+ //get the size of a buffer with the given typemask and vertex count
+ //fill offsets with the offset of each vertex component array into the buffer
+ // indexed by the following enum
+ static U32 calcOffsets(const U32& typemask, U32* offsets, U32 num_vertices);
- //WARNING -- when updating these enums you MUST
- // 1 - update LLVertexBuffer::sTypeSize
+ //WARNING -- when updating these enums you MUST
+ // 1 - update LLVertexBuffer::sTypeSize
// 2 - update LLVertexBuffer::vb_type_name
- // 3 - add a strider accessor
- // 4 - modify LLVertexBuffer::setupVertexBuffer
- // 6 - modify LLViewerShaderMgr::mReservedAttribs
-
+ // 3 - add a strider accessor
+ // 4 - modify LLVertexBuffer::setupVertexBuffer
+ // 6 - modify LLViewerShaderMgr::mReservedAttribs
+
// clang-format off
enum AttributeType { // Shader attribute name, set in LLShaderMgr::initAttribsAndUniforms()
TYPE_VERTEX = 0, // "position"
@@ -112,158 +112,158 @@ public:
TYPE_CLOTHWEIGHT, // "clothing"
TYPE_TEXTURE_INDEX, // "texture_index"
TYPE_MAX, // TYPE_MAX is the size/boundary marker for attributes that go in the vertex buffer
- TYPE_INDEX, // TYPE_INDEX is beyond _MAX because it lives in a separate (index) buffer
+ TYPE_INDEX, // TYPE_INDEX is beyond _MAX because it lives in a separate (index) buffer
};
// clang-format on
enum {
- MAP_VERTEX = (1<<TYPE_VERTEX),
- MAP_NORMAL = (1<<TYPE_NORMAL),
- MAP_TEXCOORD0 = (1<<TYPE_TEXCOORD0),
- MAP_TEXCOORD1 = (1<<TYPE_TEXCOORD1),
- MAP_TEXCOORD2 = (1<<TYPE_TEXCOORD2),
- MAP_TEXCOORD3 = (1<<TYPE_TEXCOORD3),
- MAP_COLOR = (1<<TYPE_COLOR),
- MAP_EMISSIVE = (1<<TYPE_EMISSIVE),
- MAP_TANGENT = (1<<TYPE_TANGENT),
- MAP_WEIGHT = (1<<TYPE_WEIGHT),
- MAP_WEIGHT4 = (1<<TYPE_WEIGHT4),
- MAP_CLOTHWEIGHT = (1<<TYPE_CLOTHWEIGHT),
- MAP_TEXTURE_INDEX = (1<<TYPE_TEXTURE_INDEX),
- };
-
+ MAP_VERTEX = (1<<TYPE_VERTEX),
+ MAP_NORMAL = (1<<TYPE_NORMAL),
+ MAP_TEXCOORD0 = (1<<TYPE_TEXCOORD0),
+ MAP_TEXCOORD1 = (1<<TYPE_TEXCOORD1),
+ MAP_TEXCOORD2 = (1<<TYPE_TEXCOORD2),
+ MAP_TEXCOORD3 = (1<<TYPE_TEXCOORD3),
+ MAP_COLOR = (1<<TYPE_COLOR),
+ MAP_EMISSIVE = (1<<TYPE_EMISSIVE),
+ MAP_TANGENT = (1<<TYPE_TANGENT),
+ MAP_WEIGHT = (1<<TYPE_WEIGHT),
+ MAP_WEIGHT4 = (1<<TYPE_WEIGHT4),
+ MAP_CLOTHWEIGHT = (1<<TYPE_CLOTHWEIGHT),
+ MAP_TEXTURE_INDEX = (1<<TYPE_TEXTURE_INDEX),
+ };
+
protected:
- friend class LLRender;
+ friend class LLRender;
- ~LLVertexBuffer(); // use unref()
+ ~LLVertexBuffer(); // use unref()
- void setupVertexBuffer();
+ void setupVertexBuffer();
- void genBuffer(U32 size);
- void genIndices(U32 size);
- bool createGLBuffer(U32 size);
- bool createGLIndices(U32 size);
- void destroyGLBuffer();
- void destroyGLIndices();
- bool updateNumVerts(U32 nverts);
- bool updateNumIndices(U32 nindices);
+ void genBuffer(U32 size);
+ void genIndices(U32 size);
+ bool createGLBuffer(U32 size);
+ bool createGLIndices(U32 size);
+ void destroyGLBuffer();
+ void destroyGLIndices();
+ bool updateNumVerts(U32 nverts);
+ bool updateNumIndices(U32 nindices);
public:
- LLVertexBuffer(U32 typemask);
-
+ LLVertexBuffer(U32 typemask);
+
// allocate buffer
- bool allocateBuffer(U32 nverts, U32 nindices);
+ bool allocateBuffer(U32 nverts, U32 nindices);
- // map for data access (see also getFooStrider below)
- U8* mapVertexBuffer(AttributeType type, U32 index, S32 count = -1);
- U8* mapIndexBuffer(U32 index, S32 count = -1);
- void unmapBuffer();
+ // map for data access (see also getFooStrider below)
+ U8* mapVertexBuffer(AttributeType type, U32 index, S32 count = -1);
+ U8* mapIndexBuffer(U32 index, S32 count = -1);
+ void unmapBuffer();
- // set for rendering
+ // set for rendering
// assumes (and will assert on) the following:
// - this buffer has no pending unampBuffer call
// - a shader is currently bound
// - This buffer has sufficient attributes within it to satisfy the needs of the currently bound shader
- void setBuffer();
-
- // Only call each getVertexPointer, etc, once before calling unmapBuffer()
- // call unmapBuffer() after calls to getXXXStrider() before any cals to setBuffer()
- // example:
- // vb->getVertexBuffer(verts);
- // vb->getNormalStrider(norms);
- // setVertsNorms(verts, norms);
- // vb->unmapBuffer();
- bool getVertexStrider(LLStrider<LLVector3>& strider, U32 index=0, S32 count = -1);
- bool getVertexStrider(LLStrider<LLVector4a>& strider, U32 index=0, S32 count = -1);
- bool getIndexStrider(LLStrider<U16>& strider, U32 index=0, S32 count = -1);
- bool getTexCoord0Strider(LLStrider<LLVector2>& strider, U32 index=0, S32 count = -1);
- bool getTexCoord1Strider(LLStrider<LLVector2>& strider, U32 index=0, S32 count = -1);
- bool getTexCoord2Strider(LLStrider<LLVector2>& strider, U32 index=0, S32 count = -1);
- bool getNormalStrider(LLStrider<LLVector3>& strider, U32 index=0, S32 count = -1);
- bool getTangentStrider(LLStrider<LLVector3>& strider, U32 index=0, S32 count = -1);
- bool getTangentStrider(LLStrider<LLVector4a>& strider, U32 index=0, S32 count = -1);
- bool getColorStrider(LLStrider<LLColor4U>& strider, U32 index=0, S32 count = -1);
- bool getEmissiveStrider(LLStrider<LLColor4U>& strider, U32 index=0, S32 count = -1);
- bool getWeightStrider(LLStrider<F32>& strider, U32 index=0, S32 count = -1);
- bool getWeight4Strider(LLStrider<LLVector4>& strider, U32 index=0, S32 count = -1);
- bool getClothWeightStrider(LLStrider<LLVector4>& strider, U32 index=0, S32 count = -1);
+ void setBuffer();
+
+ // Only call each getVertexPointer, etc, once before calling unmapBuffer()
+ // call unmapBuffer() after calls to getXXXStrider() before any cals to setBuffer()
+ // example:
+ // vb->getVertexBuffer(verts);
+ // vb->getNormalStrider(norms);
+ // setVertsNorms(verts, norms);
+ // vb->unmapBuffer();
+ bool getVertexStrider(LLStrider<LLVector3>& strider, U32 index=0, S32 count = -1);
+ bool getVertexStrider(LLStrider<LLVector4a>& strider, U32 index=0, S32 count = -1);
+ bool getIndexStrider(LLStrider<U16>& strider, U32 index=0, S32 count = -1);
+ bool getTexCoord0Strider(LLStrider<LLVector2>& strider, U32 index=0, S32 count = -1);
+ bool getTexCoord1Strider(LLStrider<LLVector2>& strider, U32 index=0, S32 count = -1);
+ bool getTexCoord2Strider(LLStrider<LLVector2>& strider, U32 index=0, S32 count = -1);
+ bool getNormalStrider(LLStrider<LLVector3>& strider, U32 index=0, S32 count = -1);
+ bool getTangentStrider(LLStrider<LLVector3>& strider, U32 index=0, S32 count = -1);
+ bool getTangentStrider(LLStrider<LLVector4a>& strider, U32 index=0, S32 count = -1);
+ bool getColorStrider(LLStrider<LLColor4U>& strider, U32 index=0, S32 count = -1);
+ bool getEmissiveStrider(LLStrider<LLColor4U>& strider, U32 index=0, S32 count = -1);
+ bool getWeightStrider(LLStrider<F32>& strider, U32 index=0, S32 count = -1);
+ bool getWeight4Strider(LLStrider<LLVector4>& strider, U32 index=0, S32 count = -1);
+ bool getClothWeightStrider(LLStrider<LLVector4>& strider, U32 index=0, S32 count = -1);
bool getBasecolorTexcoordStrider(LLStrider<LLVector2>& strider, U32 index=0, S32 count = -1);
bool getNormalTexcoordStrider(LLStrider<LLVector2>& strider, U32 index=0, S32 count = -1);
bool getMetallicRoughnessTexcoordStrider(LLStrider<LLVector2>& strider, U32 index=0, S32 count = -1);
bool getEmissiveTexcoordStrider(LLStrider<LLVector2>& strider, U32 index=0, S32 count = -1);
-
+
void setPositionData(const LLVector4a* data);
void setTexCoordData(const LLVector2* data);
void setColorData(const LLColor4U* data);
- U32 getNumVerts() const { return mNumVerts; }
- U32 getNumIndices() const { return mNumIndices; }
-
- U32 getTypeMask() const { return mTypeMask; }
- bool hasDataType(AttributeType type) const { return ((1 << type) & getTypeMask()); }
+ U32 getNumVerts() const { return mNumVerts; }
+ U32 getNumIndices() const { return mNumIndices; }
+
+ U32 getTypeMask() const { return mTypeMask; }
+ bool hasDataType(AttributeType type) const { return ((1 << type) & getTypeMask()); }
U32 getSize() const { return mSize; }
- U32 getIndicesSize() const { return mIndicesSize; }
- U8* getMappedData() const { return mMappedData; }
- U8* getMappedIndices() const { return mMappedIndexData; }
- U32 getOffset(AttributeType type) const { return mOffsets[type]; }
-
+ U32 getIndicesSize() const { return mIndicesSize; }
+ U8* getMappedData() const { return mMappedData; }
+ U8* getMappedIndices() const { return mMappedIndexData; }
+ U32 getOffset(AttributeType type) const { return mOffsets[type]; }
+
// these functions assume (and assert on) the current VBO being bound
// Detailed error checking can be enabled by setting gDebugGL to true
- void draw(U32 mode, U32 count, U32 indices_offset) const;
- void drawArrays(U32 mode, U32 offset, U32 count) const;
+ void draw(U32 mode, U32 count, U32 indices_offset) const;
+ void drawArrays(U32 mode, U32 offset, U32 count) const;
void drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indices_offset) const;
- //for debugging, validate data in given range is valid
- bool validateRange(U32 start, U32 end, U32 count, U32 offset) const;
+ //for debugging, validate data in given range is valid
+ bool validateRange(U32 start, U32 end, U32 count, U32 offset) const;
+
+ #ifdef LL_PROFILER_ENABLE_RENDER_DOC
+ void setLabel(const char* label);
+ #endif
- #ifdef LL_PROFILER_ENABLE_RENDER_DOC
- void setLabel(const char* label);
- #endif
-
-protected:
- U32 mGLBuffer = 0; // GL VBO handle
- U32 mGLIndices = 0; // GL IBO handle
- U32 mNumVerts = 0; // Number of vertices allocated
- U32 mNumIndices = 0; // Number of indices allocated
- U32 mOffsets[TYPE_MAX]; // byte offsets into mMappedData of each attribute
+protected:
+ U32 mGLBuffer = 0; // GL VBO handle
+ U32 mGLIndices = 0; // GL IBO handle
+ U32 mNumVerts = 0; // Number of vertices allocated
+ U32 mNumIndices = 0; // Number of indices allocated
+ U32 mOffsets[TYPE_MAX]; // byte offsets into mMappedData of each attribute
+
+ U8* mMappedData = nullptr; // pointer to currently mapped data (NULL if unmapped)
+ U8* mMappedIndexData = nullptr; // pointer to currently mapped indices (NULL if unmapped)
- U8* mMappedData = nullptr; // pointer to currently mapped data (NULL if unmapped)
- U8* mMappedIndexData = nullptr; // pointer to currently mapped indices (NULL if unmapped)
+ U32 mTypeMask = 0; // bitmask of present vertex attributes
- U32 mTypeMask = 0; // bitmask of present vertex attributes
-
- U32 mSize = 0; // size in bytes of mMappedData
- U32 mIndicesSize = 0; // size in bytes of mMappedIndexData
+ U32 mSize = 0; // size in bytes of mMappedData
+ U32 mIndicesSize = 0; // size in bytes of mMappedIndexData
- std::vector<MappedRegion> mMappedVertexRegions; // list of mMappedData byte ranges that must be sent to GL
- std::vector<MappedRegion> mMappedIndexRegions; // list of mMappedIndexData byte ranges that must be sent to GL
+ std::vector<MappedRegion> mMappedVertexRegions; // list of mMappedData byte ranges that must be sent to GL
+ std::vector<MappedRegion> mMappedIndexRegions; // list of mMappedIndexData byte ranges that must be sent to GL
private:
// DEPRECATED
- // These function signatures are deprecated, but for some reason
+ // These function signatures are deprecated, but for some reason
// there are classes in an external package that depend on LLVertexBuffer
-
+
// TODO: move these classes into viewer repository
friend class LLNavShapeVBOManager;
friend class LLNavMeshVBOManager;
-
+
LLVertexBuffer(U32 typemask, U32 usage)
: LLVertexBuffer(typemask)
{}
- bool allocateBuffer(S32 nverts, S32 nindices, BOOL create) { return allocateBuffer(nverts, nindices); }
+ bool allocateBuffer(S32 nverts, S32 nindices, BOOL create) { return allocateBuffer(nverts, nindices); }
public:
static U64 getBytesAllocated();
- static const U32 sTypeSize[TYPE_MAX];
- static const U32 sGLMode[LLRender::NUM_MODES];
- static U32 sGLRenderBuffer;
- static U32 sGLRenderIndices;
- static U32 sLastMask;
- static U32 sVertexCount;
+ static const U32 sTypeSize[TYPE_MAX];
+ static const U32 sGLMode[LLRender::NUM_MODES];
+ static U32 sGLRenderBuffer;
+ static U32 sGLRenderIndices;
+ static U32 sLastMask;
+ static U32 sVertexCount;
};
#ifdef LL_PROFILER_ENABLE_RENDER_DOC