summaryrefslogtreecommitdiff
path: root/indra/llrender
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llrender')
-rw-r--r--indra/llrender/llglslshader.cpp62
-rw-r--r--indra/llrender/llglslshader.h13
-rw-r--r--indra/llrender/llgltexture.cpp331
-rw-r--r--indra/llrender/llgltexture.h257
-rw-r--r--indra/llrender/llrender.cpp2642
-rw-r--r--indra/llrender/llrendertarget.cpp87
-rw-r--r--indra/llrender/llrendertarget.h175
-rw-r--r--indra/llrender/llshadermgr.cpp1887
-rw-r--r--indra/llrender/llshadermgr.h83
-rw-r--r--indra/llrender/llvertexbuffer.cpp691
-rw-r--r--indra/llrender/llvertexbuffer.h289
11 files changed, 3330 insertions, 3187 deletions
diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp
index 97759939c9..be5ad08fbe 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);
- }
+ 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();
- }
+ //link the program
+ res = link();
+ }
mAttribute.clear();
U32 numAttributes = (attributes == NULL) ? 0 : attributes->size();
@@ -1184,12 +1184,14 @@ S32 LLGLSLShader::getTextureChannel(S32 uniform) const
S32 LLGLSLShader::enableTexture(S32 uniform, LLTexUnit::eTextureType mode, LLTexUnit::eTextureColorSpace space)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
-
+
if (uniform < 0 || uniform >= (S32)mTexture.size())
{
LL_SHADER_UNIFORM_ERRS() << "Uniform out of range: " << uniform << LL_ENDL;
return -1;
}
+
+
S32 index = mTexture[uniform];
if (index != -1)
{
diff --git a/indra/llrender/llglslshader.h b/indra/llrender/llglslshader.h
index df568bfea5..ed0f27d143 100644
--- a/indra/llrender/llglslshader.h
+++ b/indra/llrender/llglslshader.h
@@ -49,13 +49,14 @@ public:
bool hasShadows = false;
bool hasAmbientOcclusion = false;
bool hasSrgb = false;
- bool encodesNormal = false; // include: shaders\class1\environment\encodeNormF.glsl
bool isDeferred = false;
bool hasScreenSpaceReflections = false;
bool disableTextureIndex = false;
bool hasAlphaMask = false;
bool hasReflectionProbes = false;
bool attachNothing = false;
+ bool hasHeroProbes = false;
+ bool isPBRTerrain = false;
};
// ============= Structure for caching shader uniforms ===============
@@ -233,7 +234,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 +256,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 +330,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/llgltexture.cpp b/indra/llrender/llgltexture.cpp
index 944a3d0235..a590a8e745 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,366 @@
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
- && mBoostLevel != LLGLTexture::BOOST_THUMBNAIL)
- {
- setNoDelete() ;
- }
- }
+ if(mBoostLevel != level)
+ {
+ mBoostLevel = level ;
+ if(mBoostLevel != LLGLTexture::BOOST_NONE
+ && mBoostLevel != LLGLTexture::BOOST_ICON
+ && mBoostLevel != LLGLTexture::BOOST_THUMBNAIL
+ && mBoostLevel != LLGLTexture::BOOST_TERRAIN)
+ {
+ 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 88057d7920..fa6faa2583 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,87 @@ 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 = 2048,
+ 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_TERRAIN , // Needed for minimap generation for now. Lower than BOOST_HIGH so the texture stats don't get forced, i.e. texture stats are manually managed by minimap/terrain instead.
+
+ BOOST_HIGH = 10,
+ BOOST_BUMP ,
+ BOOST_UNUSED_1 , // Placeholder to avoid disrupting habits around texture debug
+ 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) ;
-
- virtual void dump(); // debug info to LL_INFOS()
+ LLGLTexture(BOOL usemipmaps = TRUE);
+ LLGLTexture(const LLImageRaw* raw, BOOL usemipmaps) ;
+ LLGLTexture(const U32 width, const U32 height, const U8 components, BOOL usemipmaps) ;
- virtual const LLUUID& getID() const;
+ virtual void dump(); // debug info to LL_INFOS()
- void setBoostLevel(S32 level);
- S32 getBoostLevel() { return mBoostLevel; }
+ virtual const LLUUID& getID() const;
- S32 getFullWidth() const { return mFullWidth; }
- S32 getFullHeight() const { return mFullHeight; }
+ void setBoostLevel(S32 level);
+ S32 getBoostLevel() { return mBoostLevel; }
- void generateGLTexture() ;
- void destroyGLTexture() ;
+ S32 getFullWidth() const { return mFullWidth; }
+ S32 getFullHeight() const { return mFullHeight; }
- //---------------------------------------------------------------------------------------------
- //functions to access LLImageGL
- //---------------------------------------------------------------------------------------------
- /*virtual*/S32 getWidth(S32 discard_level = -1) const;
- /*virtual*/S32 getHeight(S32 discard_level = -1) const;
+ void generateGLTexture() ;
+ void destroyGLTexture() ;
- BOOL hasGLTexture() const ;
- LLGLuint getTexName() const ;
- BOOL createGLTexture() ;
+ //---------------------------------------------------------------------------------------------
+ //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() ;
+
// 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 +131,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/llrender.cpp b/indra/llrender/llrender.cpp
index 1073db3bfd..358b35f36b 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();
+ gGL.flush();
+
+ glActiveTexture(GL_TEXTURE0 + mIndex);
- glActiveTexture(GL_TEXTURE0 + mIndex);
-
- if (mCurrTexType != TT_NONE)
- {
- glBindTexture(sGLTextureType[mCurrTexType], mCurrTexture);
- }
- else
- {
- glBindTexture(GL_TEXTURE_2D, 0);
- }
+ 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;
+ mMatrixMode = LLRender::MM_MODELVIEW;
+
+ for (U32 i = 0; i < NUM_MATRIX_MODES; ++i)
+ {
+ mMatIdx[i] = 0;
+ mMatHash[i] = 0;
+ mCurMatHash[i] = 0xFFFFFFFF;
+ }
- for (U32 i = 0; i < NUM_MATRIX_MODES; ++i)
- {
- mMatIdx[i] = 0;
- mMatHash[i] = 0;
- mCurMatHash[i] = 0xFFFFFFFF;
- }
-
- mLightHash = 0;
+ 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;
-
- U32 active_unit = mCurrTextureUnitIndex;
+ mDirty = true;
- for (U32 i = 0; i < mTexUnits.size(); i++)
- {
- mTexUnits[i].refreshState();
- }
+ U32 active_unit = mCurrTextureUnitIndex;
- mTexUnits[active_unit].activate();
-
- setColorMask(mCurrColorMask[0], mCurrColorMask[1], mCurrColorMask[2], mCurrColorMask[3]);
+ for (U32 i = 0; i < mTexUnits.size(); i++)
+ {
+ mTexUnits[i].refreshState();
+ }
+
+ mTexUnits[active_unit].activate();
+ 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);
+ {
- mMatrix[mMatrixMode][mMatIdx[mMatrixMode]].mult_right(ortho_mat);
- mMatHash[mMatrixMode]++;
- }
+ 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]++;
+ }
}
void LLRender::rotatef(const GLfloat& a, const GLfloat& x, const GLfloat& y, const GLfloat& z)
{
- flush();
-
- {
- F32 r = a * DEG_TO_RAD;
+ flush();
- F32 c = cosf(r);
- F32 s = sinf(r);
+ {
+ F32 r = a * DEG_TO_RAD;
- F32 ic = 1.f-c;
+ F32 c = cosf(r);
+ F32 s = sinf(r);
- 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);
+ F32 ic = 1.f-c;
- mMatrix[mMatrixMode][mMatIdx[mMatrixMode]].mult_right(rot_mat);
- mMatHash[mMatrixMode]++;
- }
+ 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]++;
+ }
}
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();
+ 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;
-
- 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,504 @@ 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);
+ }
}
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);
+ }
}
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);
+ }
}
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);
+ }
}
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);
+ }
}
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);
+ }
}
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/llrendertarget.cpp b/indra/llrender/llrendertarget.cpp
index 7f0643c3e8..9cd7527d3e 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,11 +560,38 @@ bool LLRenderTarget::isBoundInStack() const
{
LLRenderTarget* cur = sBoundTarget;
while (cur && cur != this)
- {
+ {
cur = cur->mPreviousRT;
}
return cur == this;
}
+void LLRenderTarget::swapFBORefs(LLRenderTarget& other)
+{
+ // Must be initialized
+ llassert(mFBO);
+ llassert(other.mFBO);
+ // Must be unbound
+ // *NOTE: mPreviousRT can be non-null even if this target is unbound - presumably for debugging purposes?
+ llassert(sCurFBO != mFBO);
+ llassert(sCurFBO != other.mFBO);
+ llassert(!isBoundInStack());
+ llassert(!other.isBoundInStack());
+
+ // Must be same type
+ llassert(sUseFBO == other.sUseFBO);
+ llassert(mResX == other.mResX);
+ llassert(mResY == other.mResY);
+ llassert(mInternalFormat == other.mInternalFormat);
+ llassert(mTex.size() == other.mTex.size());
+ llassert(mDepth == other.mDepth);
+ llassert(mUseDepth == other.mUseDepth);
+ llassert(mGenerateMipMaps == other.mGenerateMipMaps);
+ llassert(mMipLevels == other.mMipLevels);
+ llassert(mUsage == other.mUsage);
+
+ std::swap(mFBO, other.mFBO);
+ std::swap(mTex, other.mTex);
+}
diff --git a/indra/llrender/llrendertarget.h b/indra/llrender/llrendertarget.h
index b5745b5b49..da401572d1 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,98 @@ 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);
+ void clear(U32 mask = 0xFFFFFFFF);
+
+ //get applied viewport
+ void getViewport(S32* viewport);
- //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; }
+
+ // *HACK
+ void swapFBORefs(LLRenderTarget& other);
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::eTextureType mUsage;
+ LLTexUnit::eTextureMipGeneration mGenerateMipMaps;
+ U32 mMipLevels;
- static LLRenderTarget* sBoundTarget;
+ LLTexUnit::eTextureType mUsage;
+
+ static LLRenderTarget* sBoundTarget;
};
#endif
diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp
index 85644a95fb..636e13719a 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$
*/
@@ -44,6 +44,7 @@ using std::make_pair;
using std::string;
LLShaderMgr * LLShaderMgr::sInstance = NULL;
+bool LLShaderMgr::sMirrorsEnabled = false;
LLShaderMgr::LLShaderMgr()
{
@@ -57,90 +58,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,38 +153,44 @@ 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 (!shader->attachFragmentObject("deferred/globalF.glsl"))
+ {
+ return FALSE;
+ }
-// NOTE order of shader object attaching is VERY IMPORTANT!!!
if (features->hasSrgb || features->hasAtmospherics || features->calculatesAtmospherics || features->isDeferred)
{
if (!shader->attachFragmentObject("environment/srgbF.glsl"))
@@ -192,46 +199,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 +249,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;
- }
- }
-
- 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;
+ }
+ }
+
+ if (features->isPBRTerrain)
{
- if (!shader->attachFragmentObject("environment/waterFogF.glsl"))
+ if (!shader->attachFragmentObject("deferred/pbrterrainUtilF.glsl"))
{
return FALSE;
}
}
-
- if (features->hasLighting)
- {
- if (features->disableTextureIndex)
- {
- if (features->hasAlphaMask)
- {
+
+ // 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)
+ {
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);
+ }
+ }
+
+ 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 +355,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 +376,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 +408,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 +431,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 +449,25 @@ GLuint LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_lev
}
#endif
- 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;
- }
+ GLenum error = GL_NO_ERROR;
- if (filename.empty())
- {
- return 0;
- }
+ 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;
+ }
- //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 +492,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 +513,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 +521,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,32 +561,48 @@ 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");
+ }
+ else
{
- 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");
+ shader_code_text[shader_code_count++] = strdup("#version 330\n");
}
- else if (minor_version <= 29)
+ }
+ else
+ {
+ if (type == GL_GEOMETRY_SHADER)
{
- shader_code_text[shader_code_count++] = strdup("#version 320\n");
+ //set version to 1.50
+ shader_code_text[shader_code_count++] = strdup("#version 150\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");
}
else
{
- shader_code_text[shader_code_count++] = strdup("#version 330\n");
+ //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");
}
- }
- 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");
+ }
- extra_code_text[extra_code_count++] = strdup("#define FXAA_GLSL_130 1\n");
+ if (sMirrorsEnabled)
+ {
+ extra_code_text[extra_code_count++] = strdup("#define HERO_PROBES 1\n");
}
// Use alpha float to store bit flags
@@ -587,127 +610,128 @@ GLuint LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_lev
extra_code_text[extra_code_count++] = strdup("#define GBUFFER_FLAG_SKIP_ATMOS 0.0 \n"); // atmo kill
extra_code_text[extra_code_count++] = strdup("#define GBUFFER_FLAG_HAS_ATMOS 0.34\n"); // bit 0
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 GBUFFER_FLAG_HAS_HDRI 1.0\n"); // bit 2
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 +739,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++;
-
- bool extra_block_area_found = NULL != strstr((const char*)buff, "[EXTRA_CODE_HERE]");
+ 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]");
+
#if TOUCH_SHADERS
if (NULL != strstr((const char*)buff, marker))
{
@@ -729,67 +753,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 +822,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 +941,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 +1181,134 @@ 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("mirror_flag");
+ mReservedUniforms.push_back("clipPlane");
+ mReservedUniforms.push_back("clipSign");
- 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("heroProbes");
+ 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 +1322,114 @@ 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("detail_0_base_color");
+ mReservedUniforms.push_back("detail_1_base_color");
+ mReservedUniforms.push_back("detail_2_base_color");
+ mReservedUniforms.push_back("detail_3_base_color");
+ mReservedUniforms.push_back("detail_0_normal");
+ mReservedUniforms.push_back("detail_1_normal");
+ mReservedUniforms.push_back("detail_2_normal");
+ mReservedUniforms.push_back("detail_3_normal");
+ mReservedUniforms.push_back("detail_0_metallic_roughness");
+ mReservedUniforms.push_back("detail_1_metallic_roughness");
+ mReservedUniforms.push_back("detail_2_metallic_roughness");
+ mReservedUniforms.push_back("detail_3_metallic_roughness");
+ mReservedUniforms.push_back("detail_0_emissive");
+ mReservedUniforms.push_back("detail_1_emissive");
+ mReservedUniforms.push_back("detail_2_emissive");
+ mReservedUniforms.push_back("detail_3_emissive");
+
+ mReservedUniforms.push_back("baseColorFactors");
+ mReservedUniforms.push_back("metallicFactors");
+ mReservedUniforms.push_back("roughnessFactors");
+ mReservedUniforms.push_back("emissiveColors");
+ mReservedUniforms.push_back("minimum_alphas");
+
+ mReservedUniforms.push_back("origin");
+ mReservedUniforms.push_back("display_gamma");
mReservedUniforms.push_back("inscatter");
mReservedUniforms.push_back("sun_size");
@@ -1397,6 +1449,7 @@ void LLShaderMgr::initAttribsAndUniforms()
mReservedUniforms.push_back("cloud_variance");
mReservedUniforms.push_back("reflection_probe_ambiance");
mReservedUniforms.push_back("max_probe_lod");
+ mReservedUniforms.push_back("probe_strength");
mReservedUniforms.push_back("sh_input_r");
mReservedUniforms.push_back("sh_input_g");
@@ -1407,17 +1460,19 @@ void LLShaderMgr::initAttribsAndUniforms()
mReservedUniforms.push_back("sun_up_factor");
mReservedUniforms.push_back("moonlight_color");
- llassert(mReservedUniforms.size() == END_RESERVED_UNIFORMS);
+ mReservedUniforms.push_back("debug_normal_draw_length");
- std::set<std::string> dupe_check;
+ llassert(mReservedUniforms.size() == END_RESERVED_UNIFORMS);
- 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]);
- }
+ 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]);
+ }
}
diff --git a/indra/llrender/llshadermgr.h b/indra/llrender/llshadermgr.h
index e655dda98d..eb13418cd7 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
@@ -85,6 +85,9 @@ public:
EMISSIVE_COLOR, // "emissiveColor"
METALLIC_FACTOR, // "metallicFactor"
ROUGHNESS_FACTOR, // "roughnessFactor"
+ MIRROR_FLAG, // "mirror_flag"
+ CLIP_PLANE, // "clipPlane"
+ CLIP_SIGN, // "clipSign"
DIFFUSE_MAP, // "diffuseMap"
ALTERNATE_DIFFUSE_MAP, // "altDiffuseMap"
SPECULAR_MAP, // "specularMap"
@@ -96,6 +99,7 @@ public:
SCENE_DEPTH, // "sceneDepth"
REFLECTION_PROBES, // "reflectionProbes"
IRRADIANCE_PROBES, // "irradianceProbes"
+ HERO_PROBE, // "heroProbes"
CLOUD_NOISE_MAP, // "cloud_noise_texture"
CLOUD_NOISE_MAP_NEXT, // "cloud_noise_texture_next"
FULLBRIGHT, // "fullbright"
@@ -251,8 +255,32 @@ public:
TERRAIN_DETAIL1, // "detail_1"
TERRAIN_DETAIL2, // "detail_2"
TERRAIN_DETAIL3, // "detail_3"
+
TERRAIN_ALPHARAMP, // "alpha_ramp"
+ TERRAIN_DETAIL0_BASE_COLOR, // "detail_0_base_color" (GLTF)
+ TERRAIN_DETAIL1_BASE_COLOR, // "detail_1_base_color" (GLTF)
+ TERRAIN_DETAIL2_BASE_COLOR, // "detail_2_base_color" (GLTF)
+ TERRAIN_DETAIL3_BASE_COLOR, // "detail_3_base_color" (GLTF)
+ TERRAIN_DETAIL0_NORMAL, // "detail_0_normal" (GLTF)
+ TERRAIN_DETAIL1_NORMAL, // "detail_1_normal" (GLTF)
+ TERRAIN_DETAIL2_NORMAL, // "detail_2_normal" (GLTF)
+ TERRAIN_DETAIL3_NORMAL, // "detail_3_normal" (GLTF)
+ TERRAIN_DETAIL0_METALLIC_ROUGHNESS, // "detail_0_metallic_roughness" (GLTF)
+ TERRAIN_DETAIL1_METALLIC_ROUGHNESS, // "detail_1_metallic_roughness" (GLTF)
+ TERRAIN_DETAIL2_METALLIC_ROUGHNESS, // "detail_2_metallic_roughness" (GLTF)
+ TERRAIN_DETAIL3_METALLIC_ROUGHNESS, // "detail_3_metallic_roughness" (GLTF)
+ TERRAIN_DETAIL0_EMISSIVE, // "detail_0_emissive" (GLTF)
+ TERRAIN_DETAIL1_EMISSIVE, // "detail_1_emissive" (GLTF)
+ TERRAIN_DETAIL2_EMISSIVE, // "detail_2_emissive" (GLTF)
+ TERRAIN_DETAIL3_EMISSIVE, // "detail_3_emissive" (GLTF)
+
+ TERRAIN_BASE_COLOR_FACTORS, // "baseColorFactors" (GLTF)
+ TERRAIN_METALLIC_FACTORS, // "metallicFactors" (GLTF)
+ TERRAIN_ROUGHNESS_FACTORS, // "roughnessFactors" (GLTF)
+ TERRAIN_EMISSIVE_COLORS, // "emissiveColors" (GLTF)
+ TERRAIN_MINIMUM_ALPHAS, // "minimum_alphas" (GLTF)
+
SHINY_ORIGIN, // "origin"
DISPLAY_GAMMA, // "display_gamma"
@@ -279,6 +307,7 @@ public:
REFLECTION_PROBE_AMBIANCE, // "reflection_probe_ambiance"
REFLECTION_PROBE_MAX_LOD, // "max_probe_lod"
+ REFLECTION_PROBE_STRENGTH, // "probe_strength"
SH_INPUT_L1R, // "sh_input_r"
SH_INPUT_L1G, // "sh_input_g"
SH_INPUT_L1B, // "sh_input_b"
@@ -287,27 +316,30 @@ public:
WATER_EDGE_FACTOR, // "water_edge"
SUN_UP_FACTOR, // "sun_up_factor"
MOONLIGHT_COLOR, // "moonlight_color"
+
+ DEBUG_NORMAL_DRAW_LENGTH, // "debug_normal_draw_length"
+
END_RESERVED_UNIFORMS
} 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 +349,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
{
@@ -336,11 +368,12 @@ public:
bool mShaderCacheInitialized = false;
bool mShaderCacheEnabled = false;
std::string mShaderCacheDir;
+ static bool sMirrorsEnabled;
protected:
- // our parameter manager singleton instance
- static LLShaderMgr * sInstance;
+ // our parameter manager singleton instance
+ static LLShaderMgr * sInstance;
}; //LLShaderMgr
diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp
index c98de6bf06..1d81c3778b 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);
-
- gGL.syncMatrices();
+ llassert(LLGLSLShader::sCurBoundShaderPtr != NULL);
- U32 mask = LLVertexBuffer::MAP_VERTEX;
- if (tc)
- {
- mask = mask | LLVertexBuffer::MAP_TEXCOORD0;
- }
+ gGL.syncMatrices();
- unbind();
+ U32 mask = LLVertexBuffer::MAP_VERTEX;
+ if (tc)
+ {
+ mask = mask | LLVertexBuffer::MAP_TEXCOORD0;
+ }
+ unbind();
+
gGL.begin(mode);
if (tc != nullptr)
@@ -657,7 +657,7 @@ void LLVertexBuffer::drawElements(U32 mode, const LLVector4a* pos, const LLVecto
U16 idx = indicesp[i];
gGL.vertex3fv(pos[idx].getF32ptr());
}
-}
+ }
gGL.end();
gGL.flush();
}
@@ -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;
-
- for (U32 i = start; i < end; i++)
- {
+ if (shader && shader->mFeatures.mIndexedTextureChannels > 1)
+ {
+ LLVector4a* v = (LLVector4a*) mMappedData;
+
+ 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
@@ -741,8 +741,8 @@ void LLVertexBuffer::drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indi
llassert(mGLBuffer == sGLRenderBuffer);
llassert(mGLIndices == sGLRenderIndices);
gGL.syncMatrices();
- glDrawRangeElements(sGLMode[mode], start, end, count, GL_UNSIGNED_SHORT,
- (GLvoid*) (indices_offset * sizeof(U16)));
+ glDrawRangeElements(sGLMode[mode], start, end, count, mIndicesType,
+ (GLvoid*) (indices_offset * (size_t) mIndicesStride));
}
void LLVertexBuffer::draw(U32 mode, U32 count, U32 indices_offset) const
@@ -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);
-
- return success;
+ success &= updateNumVerts(nverts);
+ success &= updateNumIndices(nindices);
+
+ 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;
@@ -1139,7 +1139,7 @@ U8* LLVertexBuffer::mapIndexBuffer(U32 index, S32 count)
}
// flush the given byte range
-// target -- "targret" parameter for glBufferSubData
+// target -- "target" parameter for glBufferSubData
// start -- first byte to copy
// end -- last byte to copy (NOT last byte + 1)
// data -- mMappedData or mMappedIndexData
@@ -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,120 @@ 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);
+ llassert(mIndicesStride == 2); // cannot access 32-bit indices with U16 strider
+ llassert(mIndicesType == GL_UNSIGNED_SHORT);
+ 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::getNormalStrider(LLStrider<LLVector4a>& strider, U32 index, S32 count)
+{
+ return VertexBufferStrider<LLVector4a, 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 +1373,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 +1388,7 @@ void LLVertexBuffer::setBuffer()
setupVertexBuffer();
sLastMask = data_mask;
}
-
+
if (mGLIndices != sGLRenderIndices)
{
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mGLIndices);
@@ -1503,4 +1509,39 @@ void LLVertexBuffer::setColorData(const LLColor4U* data)
flush_vbo(GL_ARRAY_BUFFER, mOffsets[TYPE_COLOR], mOffsets[TYPE_COLOR] + sTypeSize[TYPE_COLOR] * getNumVerts() - 1, (U8*) data);
}
+void LLVertexBuffer::setNormalData(const LLVector4a* data)
+{
+ llassert(sGLRenderBuffer == mGLBuffer);
+ flush_vbo(GL_ARRAY_BUFFER, mOffsets[TYPE_NORMAL], mOffsets[TYPE_NORMAL] + sTypeSize[TYPE_NORMAL] * getNumVerts() - 1, (U8*) data);
+}
+
+void LLVertexBuffer::setTangentData(const LLVector4a* data)
+{
+ llassert(sGLRenderBuffer == mGLBuffer);
+ flush_vbo(GL_ARRAY_BUFFER, mOffsets[TYPE_TANGENT], mOffsets[TYPE_TANGENT] + sTypeSize[TYPE_TANGENT] * getNumVerts() - 1, (U8*) data);
+}
+
+void LLVertexBuffer::setWeight4Data(const LLVector4a* data)
+{
+ llassert(sGLRenderBuffer == mGLBuffer);
+ flush_vbo(GL_ARRAY_BUFFER, mOffsets[TYPE_WEIGHT4], mOffsets[TYPE_WEIGHT4] + sTypeSize[TYPE_WEIGHT4] * getNumVerts() - 1, (U8*) data);
+}
+
+void LLVertexBuffer::setIndexData(const U16* data)
+{
+ llassert(sGLRenderIndices == mGLIndices);
+ flush_vbo(GL_ELEMENT_ARRAY_BUFFER, 0, sizeof(U16) * getNumIndices() - 1, (U8*) data);
+}
+
+void LLVertexBuffer::setIndexData(const U32* data)
+{
+ llassert(sGLRenderIndices == mGLIndices);
+ if (mIndicesType != GL_UNSIGNED_INT)
+ { // HACK -- vertex buffers are initialized as 16-bit indices, but can be switched to 32-bit indices
+ mIndicesType = GL_UNSIGNED_INT;
+ mIndicesStride = 4;
+ mNumIndices /= 2;
+ }
+ flush_vbo(GL_ELEMENT_ARRAY_BUFFER, 0, sizeof(U32) * getNumIndices() - 1, (U8*)data);
+}
diff --git a/indra/llrender/llvertexbuffer.h b/indra/llrender/llvertexbuffer.h
index 545917cdec..669d89aabf 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,161 @@ 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);
- 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 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 getNormalStrider(LLStrider<LLVector4a>& 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 setPositionData(const LLVector4a* data);
+ void setNormalData(const LLVector4a* data);
+ void setTangentData(const LLVector4a* data);
+ void setWeight4Data(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()); }
+ void setIndexData(const U16* data);
+ void setIndexData(const U32* 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 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 mIndicesType = GL_UNSIGNED_SHORT; // type of indices in index buffer
+ U32 mIndicesStride = 2; // size of each index in bytes
+ 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 mSize = 0; // size in bytes of mMappedData
+ U32 mIndicesSize = 0; // size in bytes of mMappedIndexData
- U32 mTypeMask = 0; // bitmask of present vertex attributes
-
- 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