summaryrefslogtreecommitdiff
path: root/indra/llrender/llrender.cpp
diff options
context:
space:
mode:
authorMark Palange <palange@lindenlab.com>2008-11-07 17:51:03 +0000
committerMark Palange <palange@lindenlab.com>2008-11-07 17:51:03 +0000
commitf89f19990cbb9f3f2e7473ac6c159098bdfabec7 (patch)
treee7fa406e2db5e9adc2e24e00557d7b3d3f93203a /indra/llrender/llrender.cpp
parentb2bfb128e7d30e1cdb293a2ac192a0cbe63fe528 (diff)
QAR-992 Merging revisions 101012-101170,101686-101687 of svn+ssh://svn.lindenlab.com/svn/linden/qa/viewer_combo_1-22-merge into linden/release
Diffstat (limited to 'indra/llrender/llrender.cpp')
-rw-r--r--indra/llrender/llrender.cpp364
1 files changed, 312 insertions, 52 deletions
diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp
index 9b116d6410..969bfe608e 100644
--- a/indra/llrender/llrender.cpp
+++ b/indra/llrender/llrender.cpp
@@ -32,7 +32,11 @@
#include "linden_common.h"
#include "llrender.h"
+
#include "llvertexbuffer.h"
+#include "llcubemap.h"
+#include "llimagegl.h"
+#include "llrendertarget.h"
LLRender gGL;
@@ -44,6 +48,20 @@ S32 gGLViewport[4];
static const U32 LL_NUM_TEXTURE_LAYERS = 8;
+static GLenum sGLTextureType[] =
+{
+ GL_TEXTURE_2D,
+ GL_TEXTURE_RECTANGLE_ARB,
+ GL_TEXTURE_CUBE_MAP_ARB
+};
+
+static GLint sGLAddressMode[] =
+{
+ GL_REPEAT,
+ GL_MIRRORED_REPEAT,
+ GL_CLAMP_TO_EDGE
+};
+
static GLenum sGLCompareFunc[] =
{
GL_NEVER,
@@ -72,82 +90,217 @@ static GLenum sGLBlendFactor[] =
GL_ONE_MINUS_SRC_ALPHA
};
-LLTexUnit::LLTexUnit(U32 index)
-: mIsEnabled(false), mCurrBlendType(TB_MULT),
+LLTexUnit::LLTexUnit(S32 index)
+: mCurrTexType(TT_NONE), mCurrBlendType(TB_MULT),
mCurrColorOp(TBO_MULT), mCurrAlphaOp(TBO_MULT),
mCurrColorSrc1(TBS_TEX_COLOR), mCurrColorSrc2(TBS_PREV_COLOR),
mCurrAlphaSrc1(TBS_TEX_ALPHA), mCurrAlphaSrc2(TBS_PREV_ALPHA),
-mCurrColorScale(1), mCurrAlphaScale(1)
+mCurrColorScale(1), mCurrAlphaScale(1), mCurrTexture(0)
{
llassert_always(index < LL_NUM_TEXTURE_LAYERS);
mIndex = index;
}
-U32 LLTexUnit::getIndex(void)
+//static
+U32 LLTexUnit::getInternalType(eTextureType type)
{
- return mIndex;
+ return sGLTextureType[type];
}
-void LLTexUnit::enable(void)
+void LLTexUnit::refreshState(void)
{
- if (!mIsEnabled)
+ // We set dirty to true so that the tex unit knows to ignore caching
+ // and we reset the cached tex unit state
+
+ glActiveTextureARB(GL_TEXTURE0_ARB + mIndex);
+ if (mCurrTexType != TT_NONE)
{
- activate();
- glEnable(GL_TEXTURE_2D);
- mIsEnabled = true;
+ glEnable(sGLTextureType[mCurrTexType]);
+ glBindTexture(sGLTextureType[mCurrTexType], mCurrTexture);
}
-}
-
-void LLTexUnit::disable(void)
-{
- if (mIsEnabled)
+ else
{
- activate();
glDisable(GL_TEXTURE_2D);
- mIsEnabled = false;
+ glBindTexture(GL_TEXTURE_2D, 0);
+ }
+
+ if (mCurrBlendType != TB_COMBINE)
+ {
+ setTextureBlendType(mCurrBlendType);
+ }
+ else
+ {
+ setTextureCombiner(mCurrColorOp, mCurrColorSrc1, mCurrColorSrc2, false);
+ setTextureCombiner(mCurrAlphaOp, mCurrAlphaSrc1, mCurrAlphaSrc2, true);
}
}
void LLTexUnit::activate(void)
{
- //if (gGL.mCurrTextureUnitIndex != mIndex)
+ if (mIndex < 0) return;
+
+ if (gGL.mCurrTextureUnitIndex != mIndex || gGL.mDirty)
{
glActiveTextureARB(GL_TEXTURE0_ARB + mIndex);
gGL.mCurrTextureUnitIndex = mIndex;
}
}
-// 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)
+void LLTexUnit::enable(eTextureType type)
{
- GLint activeTexture;
- glGetIntegerv(GL_ACTIVE_TEXTURE_ARB, &activeTexture);
- if ((GL_TEXTURE0_ARB + mIndex) != activeTexture)
+ 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;
+ glEnable(sGLTextureType[type]);
+ }
+}
+
+void LLTexUnit::disable(void)
+{
+ if (mIndex < 0) return;
+
+ if (mCurrTexType != TT_NONE)
{
- llerrs << "Incorrect Texture Unit! Expected: " << (activeTexture - GL_TEXTURE0_ARB) << " Actual: " << mIndex << llendl;
+ activate();
+ unbind(mCurrTexType);
+ glDisable(sGLTextureType[mCurrTexType]);
+ mCurrTexType = TT_NONE;
}
}
-void LLTexUnit::bindTexture(const LLImageGL* texture)
+bool LLTexUnit::bind(const LLImageGL* texture)
{
+ if (mIndex < 0) return false;
+
+ gGL.flush();
+
+ if (texture == NULL)
+ {
+ return texture->bindError(mIndex);
+ }
+
+ if (!texture->isInitialized())
+ {
+ return texture->bindDefaultImage(mIndex);
+ }
+
+ // Disabled caching of binding state.
if (texture != NULL)
{
activate();
- texture->bind(mIndex);
+ enable(texture->getTarget());
+ mCurrTexture = texture->getTexName();
+ glBindTexture(sGLTextureType[texture->getTarget()], mCurrTexture);
+ texture->updateBindStats();
+ return true;
}
+ return false;
}
-void LLTexUnit::unbindTexture(void)
+bool LLTexUnit::bind(LLCubeMap* cubeMap)
{
+ if (mIndex < 0) return false;
+
+ gGL.flush();
+
+ // Disabled caching of binding state.
+ if (cubeMap != NULL)
+ {
+ if (gGLManager.mHasCubeMap && LLCubeMap::sUseCubeMaps)
+ {
+ activate();
+ enable(LLTexUnit::TT_CUBE_MAP);
+ mCurrTexture = cubeMap->mImages[0]->getTexName();
+ glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, mCurrTexture);
+ cubeMap->mImages[0]->updateBindStats();
+ cubeMap->mImages[0]->setMipFilterNearest (FALSE, FALSE);
+ return true;
+ }
+ else
+ {
+ llwarns << "Using cube map without extension!" << llendl
+ }
+ }
+ return false;
+}
+
+bool LLTexUnit::bind(LLRenderTarget* renderTarget, bool bindDepth)
+{
+ if (mIndex < 0) return false;
+
+ gGL.flush();
+
+ if (bindDepth)
+ {
+ bindManual(renderTarget->getUsage(), renderTarget->getDepth());
+ }
+ else
+ {
+ bindManual(renderTarget->getUsage(), renderTarget->getTexture());
+ }
+
+ return true;
+}
+
+bool LLTexUnit::bindManual(eTextureType type, U32 texture)
+{
+ if (mIndex < 0) return false;
+
+ // Disabled caching of binding state.
+ gGL.flush();
+
activate();
- glBindTexture(GL_TEXTURE_2D, 0);
+ enable(type);
+ mCurrTexture = texture;
+ glBindTexture(sGLTextureType[type], texture);
+ return true;
+}
+
+void LLTexUnit::unbind(eTextureType type)
+{
+ if (mIndex < 0) return;
+
+ // Disabled caching of binding state.
+ if (mCurrTexType == type)
+ {
+ gGL.flush();
+
+ activate();
+ mCurrTexture = 0;
+ glBindTexture(sGLTextureType[type], 0);
+ }
+}
+
+void LLTexUnit::setTextureAddressMode(eTextureAddressMode mode)
+{
+ if (mIndex < 0) return;
+
+ if (true)
+ {
+ 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_ARB, GL_TEXTURE_WRAP_R, sGLAddressMode[mode]);
+ }
+ }
}
void LLTexUnit::setTextureBlendType(eTextureBlendType type)
{
+ if (mIndex < 0) return;
+
// Do nothing if it's already correctly set.
- if (mCurrBlendType == type)
+ if (mCurrBlendType == type && !gGL.mDirty)
{
return;
}
@@ -262,16 +415,18 @@ GLint LLTexUnit::getTextureSourceType(eTextureBlendSrc src, bool isAlpha)
void LLTexUnit::setTextureCombiner(eTextureBlendOp op, eTextureBlendSrc src1, eTextureBlendSrc src2, bool isAlpha)
{
+ if (mIndex < 0) return;
+
activate();
- if (mCurrBlendType != TB_COMBINE)
+ if (mCurrBlendType != TB_COMBINE || gGL.mDirty)
{
mCurrBlendType = TB_COMBINE;
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
}
// We want an early out, because this function does a LOT of stuff.
- if ( (isAlpha && (mCurrAlphaOp == op) && (mCurrAlphaSrc1 == src1) && (mCurrAlphaSrc2 == src2) )
- || (!isAlpha && (mCurrColorOp == op) && (mCurrColorSrc1 == src1) && (mCurrColorSrc2 == src2) ))
+ if ( ( (isAlpha && (mCurrAlphaOp == op) && (mCurrAlphaSrc1 == src1) && (mCurrAlphaSrc2 == src2))
+ || (!isAlpha && (mCurrColorOp == op) && (mCurrColorSrc1 == src1) && (mCurrColorSrc2 == src2)) ) && !gGL.mDirty)
{
return;
}
@@ -304,7 +459,7 @@ void LLTexUnit::setTextureCombiner(eTextureBlendOp op, eTextureBlendSrc src1, eT
}
else
{
- // Set enums to ALPHA ones
+ // Set enums to RGB ones
comb_enum = GL_COMBINE_RGB_ARB;
src0_enum = GL_SOURCE0_RGB_ARB;
src1_enum = GL_SOURCE1_RGB_ARB;
@@ -405,7 +560,7 @@ void LLTexUnit::setTextureCombiner(eTextureBlendOp op, eTextureBlendSrc src1, eT
void LLTexUnit::setColorScale(S32 scale)
{
- if (mCurrColorScale != scale)
+ if (mCurrColorScale != scale || gGL.mDirty)
{
mCurrColorScale = scale;
glTexEnvi( GL_TEXTURE_ENV, GL_RGB_SCALE, scale );
@@ -414,27 +569,52 @@ void LLTexUnit::setColorScale(S32 scale)
void LLTexUnit::setAlphaScale(S32 scale)
{
- if (mCurrAlphaScale != scale)
+ if (mCurrAlphaScale != scale || gGL.mDirty)
{
mCurrAlphaScale = scale;
glTexEnvi( GL_TEXTURE_ENV, GL_ALPHA_SCALE, scale );
}
}
+// 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;
+
+ GLint activeTexture;
+ glGetIntegerv(GL_ACTIVE_TEXTURE_ARB, &activeTexture);
+ if ((GL_TEXTURE0_ARB + mIndex) != activeTexture)
+ {
+ U32 set_unit = (activeTexture - GL_TEXTURE0_ARB);
+ llwarns << "Incorrect Texture Unit! Expected: " << set_unit << " Actual: " << mIndex << llendl;
+ }
+}
+
+
LLRender::LLRender()
+: mDirty(false), mCount(0), mMode(LLRender::TRIANGLES)
{
- mCount = 0;
- mMode = LLVertexBuffer::TRIANGLES;
mBuffer = new LLVertexBuffer(immediate_mask, 0);
mBuffer->allocateBuffer(4096, 0, TRUE);
mBuffer->getVertexStrider(mVerticesp);
mBuffer->getTexCoordStrider(mTexcoordsp);
mBuffer->getColorStrider(mColorsp);
-
- for (unsigned int i = 0; i < LL_NUM_TEXTURE_LAYERS; i++)
+
+ mTexUnits.reserve(LL_NUM_TEXTURE_LAYERS);
+ for (U32 i = 0; i < LL_NUM_TEXTURE_LAYERS; i++)
{
mTexUnits.push_back(new LLTexUnit(i));
}
+ mDummyTexUnit = new LLTexUnit(-1);
+
+ for (U32 i = 0; i < 4; i++)
+ {
+ mCurrColorMask[i] = true;
+ }
+
+ mCurrAlphaFunc = CF_DEFAULT;
+ mCurrAlphaFuncVal = 0.01f;
}
LLRender::~LLRender()
@@ -449,6 +629,28 @@ void LLRender::shutdown()
delete mTexUnits[i];
}
mTexUnits.clear();
+ delete mDummyTexUnit;
+ mDummyTexUnit = NULL;
+}
+
+void LLRender::refreshState(void)
+{
+ mDirty = true;
+
+ U32 active_unit = mCurrTextureUnitIndex;
+
+ for (U32 i = 0; i < mTexUnits.size(); i++)
+ {
+ mTexUnits[i]->refreshState();
+ }
+
+ mTexUnits[active_unit]->activate();
+
+ setColorMask(mCurrColorMask[0], mCurrColorMask[1], mCurrColorMask[2], mCurrColorMask[3]);
+
+ setAlphaRejectSettings(mCurrAlphaFunc, mCurrAlphaFuncVal);
+
+ mDirty = false;
}
void LLRender::translatef(const GLfloat& x, const GLfloat& y, const GLfloat& z)
@@ -483,6 +685,12 @@ void LLRender::setColorMask(bool writeColor, bool writeAlpha)
void LLRender::setColorMask(bool writeColorR, bool writeColorG, bool writeColorB, bool writeAlpha)
{
flush();
+
+ mCurrColorMask[0] = writeColorR;
+ mCurrColorMask[1] = writeColorG;
+ mCurrColorMask[2] = writeColorB;
+ mCurrColorMask[3] = writeAlpha;
+
glColorMask(writeColorR, writeColorG, writeColorB, writeAlpha);
}
@@ -518,6 +726,9 @@ void LLRender::setSceneBlendType(eBlendType type)
void LLRender::setAlphaRejectSettings(eCompareFunc func, F32 value)
{
flush();
+
+ mCurrAlphaFunc = func;
+ mCurrAlphaFuncVal = value;
if (func == CF_DEFAULT)
{
glAlphaFunc(GL_GREATER, 0.01f);
@@ -536,22 +747,38 @@ void LLRender::blendFunc(eBlendFactor sfactor, eBlendFactor dfactor)
LLTexUnit* LLRender::getTexUnit(U32 index)
{
- if (index < mTexUnits.size())
+ if ((index >= 0) && (index < mTexUnits.size()))
{
return mTexUnits[index];
}
- llerrs << "Non-existing texture unit layer requested: " << index << llendl;
- return NULL;
+ else
+ {
+ lldebugs << "Non-existing texture unit layer requested: " << index << llendl;
+ return mDummyTexUnit;
+ }
+}
+
+bool LLRender::verifyTexUnitActive(U32 unitToVerify)
+{
+ if (mCurrTextureUnitIndex == unitToVerify)
+ {
+ return true;
+ }
+ else
+ {
+ llwarns << "TexUnit currently active: " << mCurrTextureUnitIndex << " (expecting " << unitToVerify << ")" << llendl;
+ return false;
+ }
}
void LLRender::begin(const GLuint& mode)
{
if (mode != mMode)
{
- if (mMode == LLVertexBuffer::QUADS ||
- mMode == LLVertexBuffer::LINES ||
- mMode == LLVertexBuffer::TRIANGLES ||
- mMode == LLVertexBuffer::POINTS)
+ if (mMode == LLRender::QUADS ||
+ mMode == LLRender::LINES ||
+ mMode == LLRender::TRIANGLES ||
+ mMode == LLRender::POINTS)
{
flush();
}
@@ -572,10 +799,10 @@ void LLRender::end()
//IMM_ERRS << "GL begin and end called with no vertices specified." << llendl;
}
- if ((mMode != LLVertexBuffer::QUADS &&
- mMode != LLVertexBuffer::LINES &&
- mMode != LLVertexBuffer::TRIANGLES &&
- mMode != LLVertexBuffer::POINTS) ||
+ if ((mMode != LLRender::QUADS &&
+ mMode != LLRender::LINES &&
+ mMode != LLRender::TRIANGLES &&
+ mMode != LLRender::POINTS) ||
mCount > 2048)
{
flush();
@@ -638,7 +865,8 @@ void LLRender::flush()
}
void LLRender::vertex3f(const GLfloat& x, const GLfloat& y, const GLfloat& z)
{
- if (mCount >= 4096)
+ //the range of mVerticesp, mColorsp and mTexcoordsp is [0, 4095]
+ if (mCount > 4094)
{
// llwarns << "GL immediate mode overflow. Some geometry not drawn." << llendl;
return;
@@ -720,3 +948,35 @@ void LLRender::color3fv(const GLfloat* c)
color4f(c[0],c[1],c[2],1);
}
+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;
+}
+