summaryrefslogtreecommitdiff
path: root/indra
diff options
context:
space:
mode:
authorOz Linden <oz@lindenlab.com>2011-06-30 21:27:04 -0400
committerOz Linden <oz@lindenlab.com>2011-06-30 21:27:04 -0400
commit08ef4819d64bca0ac55cd9d4b77602e3e219d3a2 (patch)
treea7995d822c7fb2b1fb7403deb8a81e6e731420bc /indra
parent06b314aaf2d1d1176c846a3bdb17738de98252b7 (diff)
parent662a92784328f31b680f4f049350dd0f6cacf4c7 (diff)
merge latest changes from viewer-development
Diffstat (limited to 'indra')
-rw-r--r--indra/llcharacter/llcharacter.cpp25
-rw-r--r--indra/llcharacter/llcharacter.h1
-rw-r--r--indra/llcharacter/llkeyframemotion.cpp73
-rw-r--r--indra/llcharacter/llkeyframemotion.h2
-rw-r--r--indra/llrender/llgl.cpp7
-rw-r--r--indra/llrender/llglslshader.cpp10
-rw-r--r--indra/llrender/llshadermgr.cpp42
-rw-r--r--indra/newview/featuretable.txt3
-rw-r--r--indra/newview/featuretable_xp.txt3
-rw-r--r--indra/newview/llviewershadermgr.cpp9
-rw-r--r--indra/newview/llviewertexturelist.cpp19
-rw-r--r--indra/newview/llviewertexturelist.h7
-rw-r--r--indra/newview/llvoavatar.cpp4
-rw-r--r--indra/newview/llvovolume.cpp5
14 files changed, 162 insertions, 48 deletions
diff --git a/indra/llcharacter/llcharacter.cpp b/indra/llcharacter/llcharacter.cpp
index 5f84be2c5d..c9fb8534f1 100644
--- a/indra/llcharacter/llcharacter.cpp
+++ b/indra/llcharacter/llcharacter.cpp
@@ -38,7 +38,7 @@
LLStringTable LLCharacter::sVisualParamNames(1024);
std::vector< LLCharacter* > LLCharacter::sInstances;
-
+BOOL LLCharacter::sAllowInstancesChange = TRUE ;
//-----------------------------------------------------------------------------
// LLCharacter()
@@ -51,8 +51,10 @@ LLCharacter::LLCharacter()
mAppearanceSerialNum( 0 ),
mSkeletonSerialNum( 0 )
{
- mMotionController.setCharacter( this );
+ llassert_always(sAllowInstancesChange) ;
sInstances.push_back(this);
+
+ mMotionController.setCharacter( this );
mPauseRequest = new LLPauseRequestHandle();
}
@@ -62,18 +64,29 @@ LLCharacter::LLCharacter()
// Class Destructor
//-----------------------------------------------------------------------------
LLCharacter::~LLCharacter()
-{
+{
for (LLVisualParam *param = getFirstVisualParam();
param;
param = getNextVisualParam())
{
delete param;
}
- std::vector<LLCharacter*>::iterator iter = std::find(sInstances.begin(), sInstances.end(), this);
- if (iter != sInstances.end())
+
+ U32 i ;
+ U32 size = sInstances.size() ;
+ for(i = 0 ; i < size ; i++)
{
- sInstances.erase(iter);
+ if(sInstances[i] == this)
+ {
+ break ;
+ }
}
+
+ llassert_always(i < size) ;
+
+ llassert_always(sAllowInstancesChange) ;
+ sInstances[i] = sInstances[size - 1] ;
+ sInstances.pop_back() ;
}
diff --git a/indra/llcharacter/llcharacter.h b/indra/llcharacter/llcharacter.h
index a6347fcc3c..e81a27c2bc 100644
--- a/indra/llcharacter/llcharacter.h
+++ b/indra/llcharacter/llcharacter.h
@@ -266,6 +266,7 @@ public:
void setSkeletonSerialNum( U32 num ) { mSkeletonSerialNum = num; }
static std::vector< LLCharacter* > sInstances;
+ static BOOL sAllowInstancesChange ; //debug use
protected:
LLMotionController mMotionController;
diff --git a/indra/llcharacter/llkeyframemotion.cpp b/indra/llcharacter/llkeyframemotion.cpp
index 9df033a4ca..c6f45bffa2 100644
--- a/indra/llcharacter/llkeyframemotion.cpp
+++ b/indra/llcharacter/llkeyframemotion.cpp
@@ -467,13 +467,15 @@ LLPointer<LLJointState>& LLKeyframeMotion::getJointState(U32 index)
}
//-----------------------------------------------------------------------------
-// getJoin()
+// getJoint()
//-----------------------------------------------------------------------------
LLJoint* LLKeyframeMotion::getJoint(U32 index)
{
llassert_always (index < mJointStates.size());
LLJoint* joint = mJointStates[index]->getJoint();
- llassert_always (joint);
+
+ //Commented out 06-28-11 by Aura.
+ //llassert_always (joint);
return joint;
}
@@ -821,7 +823,11 @@ void LLKeyframeMotion::initializeConstraint(JointConstraint* constraint)
S32 joint_num;
LLVector3 source_pos = mCharacter->getVolumePos(shared_data->mSourceConstraintVolume, shared_data->mSourceConstraintOffset);
LLJoint* cur_joint = getJoint(shared_data->mJointStateIndices[0]);
-
+ if ( !cur_joint )
+ {
+ return;
+ }
+
F32 source_pos_offset = dist_vec(source_pos, cur_joint->getWorldPosition());
constraint->mTotalLength = constraint->mJointLengths[0] = dist_vec(cur_joint->getParent()->getWorldPosition(), source_pos);
@@ -872,6 +878,10 @@ void LLKeyframeMotion::activateConstraint(JointConstraint* constraint)
for (joint_num = 1; joint_num < shared_data->mChainLength; joint_num++)
{
LLJoint* cur_joint = getJoint(shared_data->mJointStateIndices[joint_num]);
+ if ( !cur_joint )
+ {
+ return;
+ }
constraint->mPositions[joint_num] = (cur_joint->getWorldPosition() - mPelvisp->getWorldPosition()) * ~mPelvisp->getWorldRotation();
}
@@ -932,6 +942,11 @@ void LLKeyframeMotion::applyConstraint(JointConstraint* constraint, F32 time, U8
}
LLJoint* root_joint = getJoint(shared_data->mJointStateIndices[shared_data->mChainLength]);
+ if (! root_joint)
+ {
+ return;
+ }
+
LLVector3 root_pos = root_joint->getWorldPosition();
// LLQuaternion root_rot =
root_joint->getParent()->getWorldRotation();
@@ -943,6 +958,11 @@ void LLKeyframeMotion::applyConstraint(JointConstraint* constraint, F32 time, U8
for (joint_num = 0; joint_num <= shared_data->mChainLength; joint_num++)
{
LLJoint* cur_joint = getJoint(shared_data->mJointStateIndices[joint_num]);
+ if (!cur_joint)
+ {
+ return;
+ }
+
if (joint_mask[cur_joint->getJointNum()] >= (0xff >> (7 - getPriority())))
{
// skip constraint
@@ -1033,7 +1053,14 @@ void LLKeyframeMotion::applyConstraint(JointConstraint* constraint, F32 time, U8
if (shared_data->mChainLength)
{
- LLQuaternion end_rot = getJoint(shared_data->mJointStateIndices[0])->getWorldRotation();
+ LLJoint* end_joint = getJoint(shared_data->mJointStateIndices[0]);
+
+ if (!end_joint)
+ {
+ return;
+ }
+
+ LLQuaternion end_rot = end_joint->getWorldRotation();
// slam start and end of chain to the proper positions (rest of chain stays put)
positions[0] = lerp(keyframe_source_pos, target_pos, weight);
@@ -1042,7 +1069,14 @@ void LLKeyframeMotion::applyConstraint(JointConstraint* constraint, F32 time, U8
// grab keyframe-specified positions of joints
for (joint_num = 1; joint_num < shared_data->mChainLength; joint_num++)
{
- LLVector3 kinematic_position = getJoint(shared_data->mJointStateIndices[joint_num])->getWorldPosition() +
+ LLJoint* cur_joint = getJoint(shared_data->mJointStateIndices[joint_num]);
+
+ if (!cur_joint)
+ {
+ return;
+ }
+
+ LLVector3 kinematic_position = cur_joint->getWorldPosition() +
(source_to_target * constraint->mJointLengthFractions[joint_num]);
// convert intermediate joint positions to world coordinates
@@ -1088,7 +1122,17 @@ void LLKeyframeMotion::applyConstraint(JointConstraint* constraint, F32 time, U8
for (joint_num = shared_data->mChainLength; joint_num > 0; joint_num--)
{
LLJoint* cur_joint = getJoint(shared_data->mJointStateIndices[joint_num]);
+
+ if (!cur_joint)
+ {
+ return;
+ }
LLJoint* child_joint = getJoint(shared_data->mJointStateIndices[joint_num - 1]);
+ if (!child_joint)
+ {
+ return;
+ }
+
LLQuaternion parent_rot = cur_joint->getParent()->getWorldRotation();
LLQuaternion cur_rot = cur_joint->getWorldRotation();
@@ -1122,7 +1166,6 @@ void LLKeyframeMotion::applyConstraint(JointConstraint* constraint, F32 time, U8
cur_joint->setRotation(target_rot);
}
- LLJoint* end_joint = getJoint(shared_data->mJointStateIndices[0]);
LLQuaternion end_local_rot = end_rot * ~end_joint->getParent()->getWorldRotation();
if (weight == 1.f)
@@ -1150,7 +1193,13 @@ void LLKeyframeMotion::applyConstraint(JointConstraint* constraint, F32 time, U8
//reset old joint rots
for (joint_num = 0; joint_num <= shared_data->mChainLength; joint_num++)
{
- getJoint(shared_data->mJointStateIndices[joint_num])->setRotation(old_rots[joint_num]);
+ LLJoint* cur_joint = getJoint(shared_data->mJointStateIndices[joint_num]);
+ if (!cur_joint)
+ {
+ return;
+ }
+
+ cur_joint->setRotation(old_rots[joint_num]);
}
}
// simple positional constraint (pelvis only)
@@ -1775,7 +1824,15 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp)
constraintp->mJointStateIndices[i] = -1;
for (U32 j = 0; j < mJointMotionList->getNumJointMotions(); j++)
{
- if(getJoint(j) == joint)
+ LLJoint* constraint_joint = getJoint(j);
+
+ if ( !constraint_joint )
+ {
+ llwarns << "Invalid joint " << j << llendl;
+ return FALSE;
+ }
+
+ if(constraint_joint == joint)
{
constraintp->mJointStateIndices[i] = (S32)j;
break;
diff --git a/indra/llcharacter/llkeyframemotion.h b/indra/llcharacter/llkeyframemotion.h
index 1fe9af40b3..b1422b2b90 100644
--- a/indra/llcharacter/llkeyframemotion.h
+++ b/indra/llcharacter/llkeyframemotion.h
@@ -70,7 +70,7 @@ public:
private:
// private helper functions to wrap some asserts
LLPointer<LLJointState>& getJointState(U32 index);
- LLJoint* getJoint(U32 index);
+ LLJoint* getJoint(U32 index );
public:
//-------------------------------------------------------------------------
diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp
index a3aed4dd8a..c224ab0e9b 100644
--- a/indra/llrender/llgl.cpp
+++ b/indra/llrender/llgl.cpp
@@ -568,6 +568,13 @@ bool LLGLManager::initGL()
glGetIntegerv(GL_MAX_SAMPLE_MASK_WORDS, &mMaxSampleMaskWords);
}
+#if LL_WINDOWS
+ if (mIsATI)
+ { //using multisample textures on ATI results in black screen for some reason
+ mHasTextureMultisample = FALSE;
+ }
+#endif
+
if (mHasFramebufferObject)
{
glGetIntegerv(GL_MAX_SAMPLES, &mMaxSamples);
diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp
index 8e99f62de6..ad2c662dfc 100644
--- a/indra/llrender/llglslshader.cpp
+++ b/indra/llrender/llglslshader.cpp
@@ -109,6 +109,11 @@ BOOL LLGLSLShader::createShader(vector<string> * attributes,
// Create program
mProgramObject = glCreateProgramObjectARB();
+ if (gGLManager.mGLVersion < 3.1f)
+ { //force indexed texture channels to 1 if GL version is old (performance improvement for drivers with poor branching shader model support)
+ mFeatures.mIndexedTextureChannels = llmin(mFeatures.mIndexedTextureChannels, 1);
+ }
+
//compile new source
vector< pair<string,GLenum> >::iterator fileIter = mShaderFiles.begin();
for ( ; fileIter != mShaderFiles.end(); fileIter++ )
@@ -131,6 +136,11 @@ BOOL LLGLSLShader::createShader(vector<string> * attributes,
return FALSE;
}
+ if (gGLManager.mGLVersion < 3.1f)
+ { //attachShaderFeatures may have set the number of indexed texture channels, so set to 1 again
+ mFeatures.mIndexedTextureChannels = llmin(mFeatures.mIndexedTextureChannels, 1);
+ }
+
// Map attributes and uniforms
if (success)
{
diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp
index bdc103b917..751b250d96 100644
--- a/indra/llrender/llshadermgr.cpp
+++ b/indra/llrender/llshadermgr.cpp
@@ -462,7 +462,11 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade
GLcharARB* text[1024];
GLuint count = 0;
- if (gGLManager.mGLVersion < 3.f)
+ if (gGLManager.mGLVersion < 2.1f)
+ {
+ text[count++] = strdup("#version 110\n");
+ }
+ else if (gGLManager.mGLVersion < 3.f)
{
//set version to 1.20
text[count++] = strdup("#version 120\n");
@@ -524,7 +528,12 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade
text[count++] = strdup("{\n");
- if (gGLManager.mGLVersion >= 3.f)
+ if (texture_index_channels == 1)
+ { //don't use flow control, that's silly
+ text[count++] = strdup("return texture2D(tex0, texcoord);\n");
+ text[count++] = strdup("}\n");
+ }
+ else if (gGLManager.mGLVersion >= 3.f)
{
text[count++] = strdup("\tswitch (int(vary_texture_index+0.25))\n");
text[count++] = strdup("\t{\n");
@@ -537,6 +546,8 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade
}
text[count++] = strdup("\t}\n");
+ text[count++] = strdup("\treturn vec4(0,0,0,0);\n");
+ text[count++] = strdup("}\n");
}
else
{
@@ -557,10 +568,10 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade
std::string if_str = llformat("if (ti == %d) return texture2D(tex%d, texcoord);\n", i, i);
text[count++] = strdup(if_str.c_str());
}
- }
- text[count++] = strdup("\treturn vec4(0,0,0,0);\n");
- text[count++] = strdup("}\n");
+ text[count++] = strdup("\treturn vec4(0,0,0,0);\n");
+ text[count++] = strdup("}\n");
+ }
}
//copy file into memory
@@ -605,11 +616,6 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade
}
}
- //free memory
- for (GLuint i = 0; i < count; i++)
- {
- free(text[i]);
- }
if (error == GL_NO_ERROR)
{
//check for errors
@@ -623,6 +629,16 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade
//an error occured, print log
LL_WARNS("ShaderLoading") << "GLSL Compilation Error: (" << error << ") in " << filename << LL_ENDL;
dumpObjectLog(ret);
+
+ std::stringstream ostr;
+ //dump shader source for debugging
+ for (GLuint i = 0; i < count; i++)
+ {
+ ostr << i << ": " << text[i];
+ }
+
+ LL_WARNS("ShaderLoading") << "\n" << ostr.str() << llendl;
+
ret = 0;
}
}
@@ -633,6 +649,12 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade
}
stop_glerror();
+ //free memory
+ for (GLuint i = 0; i < count; i++)
+ {
+ free(text[i]);
+ }
+
//successfully loaded, save results
if (ret)
{
diff --git a/indra/newview/featuretable.txt b/indra/newview/featuretable.txt
index 639a47d7fa..22c79a4cbd 100644
--- a/indra/newview/featuretable.txt
+++ b/indra/newview/featuretable.txt
@@ -1,4 +1,4 @@
-version 29
+version 30
// NOTE: This is mostly identical to featuretable_mac.txt with a few differences
// Should be combined into one table
@@ -295,6 +295,7 @@ RenderDeferred 0 0
list Intel
RenderAnisotropic 1 0
+RenderVBOEnable 1 0
list GeForce2
RenderAnisotropic 1 0
diff --git a/indra/newview/featuretable_xp.txt b/indra/newview/featuretable_xp.txt
index a69fd4fdaf..ba74f9a6c2 100644
--- a/indra/newview/featuretable_xp.txt
+++ b/indra/newview/featuretable_xp.txt
@@ -1,4 +1,4 @@
-version 29
+version 30
// NOTE: This is mostly identical to featuretable_mac.txt with a few differences
// Should be combined into one table
@@ -293,6 +293,7 @@ RenderDeferred 0 0
list Intel
RenderAnisotropic 1 0
+RenderVBOEnable 1 0
list GeForce2
RenderAnisotropic 1 0
diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp
index 31f9413f20..e473901609 100644
--- a/indra/newview/llviewershadermgr.cpp
+++ b/indra/newview/llviewershadermgr.cpp
@@ -722,6 +722,11 @@ BOOL LLViewerShaderMgr::loadBasicShaders()
shaders.reserve(13);
S32 ch = gGLManager.mNumTextureImageUnits-1;
+ if (gGLManager.mGLVersion < 3.1f)
+ { //force to 1 texture index channel for old drivers
+ ch = 1;
+ }
+
std::vector<S32> index_channels;
index_channels.push_back(-1); shaders.push_back( make_pair( "windlight/atmosphericsVarsF.glsl", mVertexShaderLevel[SHADER_WINDLIGHT] ) );
index_channels.push_back(-1); shaders.push_back( make_pair( "windlight/gammaF.glsl", mVertexShaderLevel[SHADER_WINDLIGHT]) );
@@ -1209,7 +1214,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
{
if (multisample)
{
- fragment = "deferred/sunlightSSAOMSF.glsl";
+ fragment = "deferred/sunLightSSAOMSF.glsl";
}
else
{
@@ -1220,7 +1225,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
{
if (multisample)
{
- fragment = "deferred/sunlightMSF.glsl";
+ fragment = "deferred/sunLightMSF.glsl";
}
else
{
diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp
index a1d9434d44..d24174adea 100644
--- a/indra/newview/llviewertexturelist.cpp
+++ b/indra/newview/llviewertexturelist.cpp
@@ -76,7 +76,6 @@ LLStat LLViewerTextureList::sFormattedMemStat(32, TRUE);
LLViewerTextureList gTextureList;
static LLFastTimer::DeclareTimer FTM_PROCESS_IMAGES("Process Images");
-U32 LLViewerTextureList::sRenderThreadID = 0 ;
///////////////////////////////////////////////////////////////////////////////
LLViewerTextureList::LLViewerTextureList()
@@ -90,7 +89,6 @@ LLViewerTextureList::LLViewerTextureList()
void LLViewerTextureList::init()
{
- sRenderThreadID = LLThread::currentID() ;
mInitialized = TRUE ;
sNumImages = 0;
mUpdateStats = TRUE;
@@ -502,10 +500,9 @@ LLViewerFetchedTexture *LLViewerTextureList::findImage(const LLUUID &image_id)
return iter->second;
}
-void LLViewerTextureList::addImageToList(LLViewerFetchedTexture *image, U32 thread_id)
+void LLViewerTextureList::addImageToList(LLViewerFetchedTexture *image)
{
llassert_always(mInitialized) ;
- llassert_always(sRenderThreadID == thread_id);
llassert(image);
if (image->isInImageList())
{
@@ -519,10 +516,9 @@ void LLViewerTextureList::addImageToList(LLViewerFetchedTexture *image, U32 thre
image->setInImageList(TRUE) ;
}
-void LLViewerTextureList::removeImageFromList(LLViewerFetchedTexture *image, U32 thread_id)
+void LLViewerTextureList::removeImageFromList(LLViewerFetchedTexture *image)
{
llassert_always(mInitialized) ;
- llassert_always(sRenderThreadID == thread_id);
llassert(image);
if (!image->isInImageList())
{
@@ -659,10 +655,7 @@ void LLViewerTextureList::updateImagesDecodePriorities()
const F32 LAZY_FLUSH_TIMEOUT = 30.f; // stop decoding
const F32 MAX_INACTIVE_TIME = 50.f; // actually delete
S32 min_refs = 3; // 1 for mImageList, 1 for mUUIDMap, 1 for local reference
- if (imagep->hasCallbacks())
- {
- min_refs++; // Add an extra reference if we're on the loaded callback list
- }
+
S32 num_refs = imagep->getNumRefs();
if (num_refs == min_refs)
{
@@ -719,9 +712,9 @@ void LLViewerTextureList::updateImagesDecodePriorities()
if ((decode_priority_test < old_priority_test * .8f) ||
(decode_priority_test > old_priority_test * 1.25f))
{
- removeImageFromList(imagep, sRenderThreadID);
+ removeImageFromList(imagep);
imagep->setDecodePriority(decode_priority);
- addImageToList(imagep, sRenderThreadID);
+ addImageToList(imagep);
}
update_counter--;
}
@@ -893,8 +886,6 @@ void LLViewerTextureList::decodeAllImages(F32 max_time)
{
LLTimer timer;
- llassert_always(sRenderThreadID == LLThread::currentID());
-
// Update texture stats and priorities
std::vector<LLPointer<LLViewerFetchedTexture> > image_list;
for (image_priority_list_t::iterator iter = mImageList.begin();
diff --git a/indra/newview/llviewertexturelist.h b/indra/newview/llviewertexturelist.h
index d02b6be6b5..7f4dd0ae88 100644
--- a/indra/newview/llviewertexturelist.h
+++ b/indra/newview/llviewertexturelist.h
@@ -121,8 +121,8 @@ private:
void addImage(LLViewerFetchedTexture *image);
void deleteImage(LLViewerFetchedTexture *image);
- void addImageToList(LLViewerFetchedTexture *image, U32 thread_id = LLThread::currentID());
- void removeImageFromList(LLViewerFetchedTexture *image, U32 thread_id = LLThread::currentID());
+ void addImageToList(LLViewerFetchedTexture *image);
+ void removeImageFromList(LLViewerFetchedTexture *image);
LLViewerFetchedTexture * getImage(const LLUUID &image_id,
BOOL usemipmap = TRUE,
@@ -208,9 +208,6 @@ public:
private:
static S32 sNumImages;
static void (*sUUIDCallback)(void**, const LLUUID &);
-
- //debug use
- static U32 sRenderThreadID;
};
class LLUIImageList : public LLImageProviderInterface, public LLSingleton<LLUIImageList>
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 1b53348b43..8eda6346b0 100644
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -8242,6 +8242,8 @@ U32 LLVOAvatar::getPartitionType() const
//static
void LLVOAvatar::updateImpostors()
{
+ LLCharacter::sAllowInstancesChange = FALSE ;
+
for (std::vector<LLCharacter*>::iterator iter = LLCharacter::sInstances.begin();
iter != LLCharacter::sInstances.end(); ++iter)
{
@@ -8251,6 +8253,8 @@ void LLVOAvatar::updateImpostors()
gPipeline.generateImpostor(avatar);
}
}
+
+ LLCharacter::sAllowInstancesChange = TRUE ;
}
BOOL LLVOAvatar::isImpostor() const
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index c5e2c56e4b..e6da8eb89d 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -4495,6 +4495,11 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::
S32 texture_index_channels = gGLManager.mNumTextureImageUnits-1; //always reserve one for shiny for now just for simplicity
+ if (gGLManager.mGLVersion < 3.1f)
+ {
+ texture_index_channels = 1;
+ }
+
if (LLPipeline::sRenderDeferred && distance_sort)
{
texture_index_channels = gDeferredAlphaProgram.mFeatures.mIndexedTextureChannels;