summaryrefslogtreecommitdiff
path: root/indra/llrender
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
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')
-rw-r--r--indra/llrender/llcubemap.cpp54
-rw-r--r--indra/llrender/llcubemap.h2
-rw-r--r--indra/llrender/llfontgl.cpp20
-rw-r--r--indra/llrender/llgl.cpp29
-rw-r--r--indra/llrender/llglslshader.cpp8
-rw-r--r--indra/llrender/llglslshader.h5
-rw-r--r--indra/llrender/llglstates.h22
-rw-r--r--indra/llrender/llimagegl.cpp266
-rw-r--r--indra/llrender/llimagegl.h26
-rw-r--r--indra/llrender/llpostprocess.cpp18
-rw-r--r--indra/llrender/llrender.cpp364
-rw-r--r--indra/llrender/llrender.h122
-rw-r--r--indra/llrender/llrendertarget.cpp56
-rw-r--r--indra/llrender/llrendertarget.h15
-rw-r--r--indra/llrender/llshadermgr.cpp2
-rw-r--r--indra/llrender/llvertexbuffer.cpp8
-rw-r--r--indra/llrender/llvertexbuffer.h16
17 files changed, 654 insertions, 379 deletions
diff --git a/indra/llrender/llcubemap.cpp b/indra/llrender/llcubemap.cpp
index f19992eeab..ba2846202f 100644
--- a/indra/llrender/llcubemap.cpp
+++ b/indra/llrender/llcubemap.cpp
@@ -92,11 +92,11 @@ void LLCubeMap::initGL()
for (int i = 0; i < 6; i++)
{
mImages[i] = new LLImageGL(64, 64, 4, (use_cube_mipmaps? TRUE : FALSE));
- mImages[i]->setTarget(mTargets[i], GL_TEXTURE_CUBE_MAP_ARB);
+ mImages[i]->setTarget(mTargets[i], LLTexUnit::TT_CUBE_MAP);
mRawImages[i] = new LLImageRaw(64, 64, 4);
mImages[i]->createGLTexture(0, mRawImages[i], texname);
- glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, texname);
+ gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_CUBE_MAP, texname);
mImages[i]->setClampCubemap (TRUE, TRUE, TRUE);
stop_glerror();
}
@@ -180,26 +180,7 @@ GLuint LLCubeMap::getGLName()
void LLCubeMap::bind()
{
- if (gGLManager.mHasCubeMap && LLCubeMap::sUseCubeMaps)
- {
- // We assume that if they have cube mapping, they have multitexturing.
- if (mTextureStage > 0)
- {
- gGL.getTexUnit(mTextureStage)->activate();
- }
- glEnable(GL_TEXTURE_CUBE_MAP_ARB);
- glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, mImages[0]->getTexName());
-
- mImages[0]->setMipFilterNearest (FALSE, FALSE);
- if (mTextureStage > 0)
- {
- gGL.getTexUnit(0)->activate();
- }
- }
- else
- {
- llwarns << "Using cube map without extension!" << llendl
- }
+ gGL.getTexUnit(mTextureStage)->bind(this);
}
void LLCubeMap::enable(S32 stage)
@@ -213,17 +194,7 @@ void LLCubeMap::enableTexture(S32 stage)
mTextureStage = stage;
if (gGLManager.mHasCubeMap && stage >= 0 && LLCubeMap::sUseCubeMaps)
{
- if (stage > 0)
- {
- gGL.getTexUnit(stage)->activate();
- }
-
- glEnable(GL_TEXTURE_CUBE_MAP_ARB);
-
- if (stage > 0)
- {
- gGL.getTexUnit(0)->activate();
- }
+ gGL.getTexUnit(stage)->enable(LLTexUnit::TT_CUBE_MAP);
}
}
@@ -262,15 +233,10 @@ void LLCubeMap::disableTexture(void)
{
if (gGLManager.mHasCubeMap && mTextureStage >= 0 && LLCubeMap::sUseCubeMaps)
{
- if (mTextureStage > 0)
+ gGL.getTexUnit(mTextureStage)->disable();
+ if (mTextureStage == 0)
{
- gGL.getTexUnit(mTextureStage)->activate();
- }
- glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, 0);
- glDisable(GL_TEXTURE_CUBE_MAP_ARB);
- if (mTextureStage > 0)
- {
- gGL.getTexUnit(0)->activate();
+ gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE);
}
}
}
@@ -297,6 +263,8 @@ void LLCubeMap::setMatrix(S32 stage)
{
mMatrixStage = stage;
+ if (mMatrixStage < 0) return;
+
if (stage > 0)
{
gGL.getTexUnit(stage)->activate();
@@ -324,6 +292,8 @@ void LLCubeMap::setMatrix(S32 stage)
void LLCubeMap::restoreMatrix()
{
+ if (mMatrixStage < 0) return;
+
if (mMatrixStage > 0)
{
gGL.getTexUnit(mMatrixStage)->activate();
@@ -340,7 +310,7 @@ void LLCubeMap::restoreMatrix()
void LLCubeMap::setReflection (void)
{
- glBindTexture (GL_TEXTURE_CUBE_MAP_ARB, getGLName());
+ gGL.getTexUnit(mTextureStage)->bindManual(LLTexUnit::TT_CUBE_MAP, getGLName());
mImages[0]->setMipFilterNearest (FALSE, FALSE);
mImages[0]->setClampCubemap (TRUE, TRUE);
}
diff --git a/indra/llrender/llcubemap.h b/indra/llrender/llcubemap.h
index c273ab40ec..2fc0f01b9a 100644
--- a/indra/llrender/llcubemap.h
+++ b/indra/llrender/llcubemap.h
@@ -53,6 +53,7 @@ public:
void enableTexture(S32 stage);
void enableTextureCoords(S32 stage);
+ S32 getStage(void) { return mTextureStage; }
void disable(void);
void disableTexture(void);
@@ -77,6 +78,7 @@ public:
static bool sUseCubeMaps;
protected:
+ friend class LLTexUnit;
~LLCubeMap();
LLGLenum mTargets[6];
LLPointer<LLImageGL> mImages[6];
diff --git a/indra/llrender/llfontgl.cpp b/indra/llrender/llfontgl.cpp
index 02e1663513..bc4fc172aa 100644
--- a/indra/llrender/llfontgl.cpp
+++ b/indra/llrender/llfontgl.cpp
@@ -148,7 +148,7 @@ void LLFontGL::init()
{
mImageGLp = new LLImageGL(FALSE);
//RN: use nearest mipmap filtering to obviate the need to do pixel-accurate positioning
- mImageGLp->bind();
+ gGL.getTexUnit(0)->bind(mImageGLp);
// we allow bilinear filtering to get sub-pixel positioning for drop shadows
//mImageGLp->setMipFilterNearest(TRUE, TRUE);
}
@@ -533,7 +533,7 @@ BOOL LLFontGL::loadFace(const std::string& filename,
return FALSE;
}
mImageGLp->createGLTexture(0, mRawImageGLp);
- mImageGLp->bind();
+ gGL.getTexUnit(0)->bind(mImageGLp);
mImageGLp->setMipFilterNearest(TRUE, TRUE);
return TRUE;
}
@@ -547,7 +547,7 @@ BOOL LLFontGL::addChar(const llwchar wch)
stop_glerror();
mImageGLp->setSubImage(mRawImageGLp, 0, 0, mImageGLp->getWidth(), mImageGLp->getHeight());
- mImageGLp->bind();
+ gGL.getTexUnit(0)->bind(mImageGLp);
mImageGLp->setMipFilterNearest(TRUE, TRUE);
stop_glerror();
return TRUE;
@@ -583,7 +583,7 @@ S32 LLFontGL::render(const LLWString &wstr,
return wstr.length() ;
}
- LLGLEnable tex(GL_TEXTURE_2D);
+ gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE);
if (wstr.empty())
{
@@ -663,7 +663,7 @@ S32 LLFontGL::render(const LLWString &wstr,
// Bind the font texture
- mImageGLp->bind(0);
+ gGL.getTexUnit(0)->bind(mImageGLp);
// Not guaranteed to be set correctly
gGL.setSceneBlendType(LLRender::BT_ALPHA);
@@ -761,7 +761,7 @@ S32 LLFontGL::render(const LLWString &wstr,
break;
}
- ext_image->bind();
+ gGL.getTexUnit(0)->bind(ext_image);
const F32 ext_x = cur_render_x + (EXT_X_BEARING * sScaleX);
const F32 ext_y = cur_render_y + (EXT_Y_BEARING * sScaleY + mAscender - mLineHeight);
@@ -795,7 +795,7 @@ S32 LLFontGL::render(const LLWString &wstr,
cur_render_x = cur_x;
// Bind the font texture
- mImageGLp->bind();
+ gGL.getTexUnit(0)->bind(mImageGLp);
}
else
{
@@ -863,8 +863,8 @@ S32 LLFontGL::render(const LLWString &wstr,
if (style & UNDERLINE)
{
- LLGLSNoTexture no_texture;
- gGL.begin(LLVertexBuffer::LINES);
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+ gGL.begin(LLRender::LINES);
gGL.vertex2f(start_x, cur_y - (mDescender));
gGL.vertex2f(cur_x, cur_y - (mDescender));
gGL.end();
@@ -1359,7 +1359,7 @@ void LLFontGL::drawGlyph(const LLRectf& screen_rect, const LLRectf& uv_rect, con
F32 slant_offset;
slant_offset = ((style & ITALIC) ? ( -mAscender * 0.2f) : 0.f);
- gGL.begin(LLVertexBuffer::QUADS);
+ gGL.begin(LLRender::QUADS);
{
//FIXME: bold and drop shadow are mutually exclusive only for convenience
//Allow both when we need them.
diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp
index 570a0cbed1..fa763bf2f8 100644
--- a/indra/llrender/llgl.cpp
+++ b/indra/llrender/llgl.cpp
@@ -960,7 +960,8 @@ void assert_glerror()
GLubyte const * gl_error_msg = gluErrorString(error);
if (NULL != gl_error_msg)
{
- LL_WARNS("RenderState") << "GL Error:" << gl_error_msg << LL_ENDL;
+ LL_WARNS("RenderState") << "GL Error:" << error<< LL_ENDL;
+ LL_WARNS("RenderState") << "GL Error String:" << gl_error_msg << LL_ENDL;
}
else
{
@@ -1001,7 +1002,7 @@ GLboolean LLGLDepthTest::sWriteEnabled = GL_TRUE; // OpenGL default
void LLGLState::initClass()
{
sStateMap[GL_DITHER] = GL_TRUE;
- sStateMap[GL_TEXTURE_2D] = GL_TRUE;
+ // sStateMap[GL_TEXTURE_2D] = GL_TRUE;
//make sure multisample defaults to disabled
sStateMap[GL_MULTISAMPLE_ARB] = GL_FALSE;
@@ -1030,7 +1031,7 @@ void LLGLState::resetTextureStates()
{
gGL.getTexUnit(j)->activate();
glClientActiveTextureARB(GL_TEXTURE0_ARB+j);
- j == 0 ? glEnable(GL_TEXTURE_2D) : glDisable(GL_TEXTURE_2D);
+ j == 0 ? gGL.getTexUnit(j)->enable(LLTexUnit::TT_TEXTURE) : gGL.getTexUnit(j)->disable();
}
}
@@ -1053,14 +1054,6 @@ void LLGLState::checkStates(const std::string& msg)
stop_glerror();
- GLint activeTexture;
- glGetIntegerv(GL_ACTIVE_TEXTURE_ARB, &activeTexture);
-
- if (activeTexture != GL_TEXTURE0_ARB)
- {
- LL_GL_ERRS << "Texture channel corrupted. " << LL_ENDL;
- }
-
GLint src;
GLint dst;
glGetIntegerv(GL_BLEND_SRC, &src);
@@ -1099,17 +1092,7 @@ void LLGLState::checkTextureChannels(const std::string& msg)
BOOL error = FALSE;
- if (activeTexture != GL_TEXTURE0_ARB)
- {
- error = TRUE;
- LL_WARNS("RenderState") << "Active texture channel corrupted. " << LL_ENDL;
- }
- else if (!glIsEnabled(GL_TEXTURE_2D))
- {
- error = TRUE;
- LL_WARNS("RenderState") << "GL_TEXTURE_2D not enabled on texture channel 0." << LL_ENDL;
- }
- else
+ if (activeTexture == GL_TEXTURE0_ARB)
{
GLint tex_env_mode = 0;
@@ -1152,7 +1135,7 @@ void LLGLState::checkTextureChannels(const std::string& msg)
LLMatrix4 identity;
LLMatrix4 matrix;
- for (GLint i = 0; i < maxTextureUnits; i++)
+ for (GLint i = 1; i < maxTextureUnits; i++)
{
gGL.getTexUnit(i)->activate();
glClientActiveTextureARB(GL_TEXTURE0_ARB+i);
diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp
index 7b03944918..1c0fbf477d 100644
--- a/indra/llrender/llglslshader.cpp
+++ b/indra/llrender/llglslshader.cpp
@@ -365,7 +365,7 @@ void LLGLSLShader::bindNoShader(void)
glUseProgramObjectARB(0);
}
-S32 LLGLSLShader::enableTexture(S32 uniform, S32 mode)
+S32 LLGLSLShader::enableTexture(S32 uniform, LLTexUnit::eTextureType mode)
{
if (uniform < 0 || uniform >= (S32)mTexture.size())
{
@@ -376,12 +376,12 @@ S32 LLGLSLShader::enableTexture(S32 uniform, S32 mode)
if (index != -1)
{
gGL.getTexUnit(index)->activate();
- glEnable(mode);
+ gGL.getTexUnit(index)->enable(mode);
}
return index;
}
-S32 LLGLSLShader::disableTexture(S32 uniform, S32 mode)
+S32 LLGLSLShader::disableTexture(S32 uniform, LLTexUnit::eTextureType mode)
{
if (uniform < 0 || uniform >= (S32)mTexture.size())
{
@@ -392,7 +392,7 @@ S32 LLGLSLShader::disableTexture(S32 uniform, S32 mode)
if (index != -1)
{
gGL.getTexUnit(index)->activate();
- glDisable(mode);
+ gGL.getTexUnit(index)->disable();
}
return index;
}
diff --git a/indra/llrender/llglslshader.h b/indra/llrender/llglslshader.h
index c78188ba87..75448191bf 100644
--- a/indra/llrender/llglslshader.h
+++ b/indra/llrender/llglslshader.h
@@ -33,6 +33,7 @@
#define LL_LLGLSLSHADER_H
#include "llgl.h"
+#include "llrender.h"
class LLShaderFeatures
{
@@ -111,8 +112,8 @@ public:
//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, S32 mode = GL_TEXTURE_2D);
- S32 disableTexture(S32 uniform, S32 mode = GL_TEXTURE_2D);
+ S32 enableTexture(S32 uniform, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE);
+ S32 disableTexture(S32 uniform, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE);
BOOL link(BOOL suppress_errors = FALSE);
void bind();
diff --git a/indra/llrender/llglstates.h b/indra/llrender/llglstates.h
index 907e4ee2e6..88b4e91425 100644
--- a/indra/llrender/llglstates.h
+++ b/indra/llrender/llglstates.h
@@ -87,13 +87,6 @@ public:
{ }
};
-class LLGLSNoTexture
-{
-public:
- LLGLSNoTexture()
- { LLImageGL::unbindTexture(0); }
-};
-
class LLGLSObjectSelect
{
protected:
@@ -104,7 +97,7 @@ public:
: mBlend(GL_BLEND), mFog(GL_FOG),
mAlphaTest(GL_ALPHA_TEST),
mCullFace(GL_CULL_FACE)
- { LLImageGL::unbindTexture(0); }
+ { }
};
class LLGLSObjectSelectAlpha
@@ -143,17 +136,6 @@ public:
{}
};
-class LLGLSNoTextureNoAlphaTest // : public LLGLSUIDefault
-{
-protected:
- LLGLDisable mAlphaTest;
-public:
- LLGLSNoTextureNoAlphaTest()
- : mAlphaTest(GL_ALPHA_TEST)
-
- { LLImageGL::unbindTexture(0); }
-};
-
//----------------------------------------------------------------------------
class LLGLSFog
@@ -251,7 +233,7 @@ public:
mBlend(GL_BLEND),
mAlphaTest(GL_ALPHA_TEST)
- { LLImageGL::unbindTexture(0); }
+ { }
};
//----------------------------------------------------------------------------
diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp
index 1c9b4d9693..2ef2bae1ab 100644
--- a/indra/llrender/llimagegl.cpp
+++ b/indra/llrender/llimagegl.cpp
@@ -125,49 +125,6 @@ S32 LLImageGL::dataFormatComponents(S32 dataformat)
//----------------------------------------------------------------------------
// static
-void LLImageGL::bindExternalTexture(LLGLuint gl_name, S32 stage, LLGLenum bind_target )
-{
- gGL.flush();
- if (stage > 0)
- {
- gGL.getTexUnit(stage)->activate();
- }
- glBindTexture(bind_target, gl_name);
- sCurrentBoundTextures[stage] = gl_name;
- if (stage > 0)
- {
- gGL.getTexUnit(0)->activate();
- }
-}
-
-// static
-void LLImageGL::unbindTexture(S32 stage, LLGLenum bind_target)
-{
- // LLGLSLShader can return -1
- if (stage >= 0)
- {
- gGL.flush();
- if (stage > 0)
- {
- gGL.getTexUnit(stage)->activate();
- glBindTexture(GL_TEXTURE_2D, 0);
- gGL.getTexUnit(0)->activate();
- }
- else
- {
- glBindTexture(GL_TEXTURE_2D, 0);
- }
- sCurrentBoundTextures[stage] = 0;
- }
-}
-
-// static (duplicated for speed and to avoid GL_TEXTURE_2D default argument which requires GL header dependency)
-void LLImageGL::unbindTexture(S32 stage)
-{
- unbindTexture(stage, GL_TEXTURE_2D);
-}
-
-// static
void LLImageGL::updateStats(F32 current_time)
{
sLastFrameTime = current_time;
@@ -189,7 +146,7 @@ void LLImageGL::destroyGL(BOOL save_state)
{
for (S32 stage = 0; stage < gGLManager.mNumTextureUnits; stage++)
{
- LLImageGL::unbindTexture(stage, GL_TEXTURE_2D);
+ gGL.getTexUnit(stage)->unbind(LLTexUnit::TT_TEXTURE);
}
for (std::set<LLImageGL*>::iterator iter = sImageList.begin();
iter != sImageList.end(); iter++)
@@ -284,6 +241,8 @@ LLImageGL::~LLImageGL()
{
LLImageGL::cleanup();
sImageList.erase(this);
+ delete [] mPickMask;
+ mPickMask = NULL;
sCount--;
}
@@ -293,11 +252,12 @@ void LLImageGL::init(BOOL usemipmaps)
mMissed = FALSE;
#endif
+ mPickMask = NULL;
mTextureMemory = 0;
mLastBindTime = 0.f;
mTarget = GL_TEXTURE_2D;
- mBindTarget = GL_TEXTURE_2D;
+ mBindTarget = LLTexUnit::TT_TEXTURE;
mUseMipMaps = usemipmaps;
mHasMipMaps = FALSE;
mAutoGenMips = FALSE;
@@ -321,6 +281,8 @@ void LLImageGL::init(BOOL usemipmaps)
mFormatType = GL_UNSIGNED_BYTE;
mFormatSwapBytes = FALSE;
mHasExplicitFormat = FALSE;
+
+ mInitialized = true;
}
void LLImageGL::cleanup()
@@ -421,41 +383,14 @@ void LLImageGL::dump()
//----------------------------------------------------------------------------
-BOOL LLImageGL::bindTextureInternal(const S32 stage) const
+void LLImageGL::updateBindStats(void) const
{
- if (gGLManager.mIsDisabled)
- {
- llwarns << "Trying to bind a texture while GL is disabled!" << llendl;
- }
-
-
- if (sCurrentBoundTextures[stage] && sCurrentBoundTextures[stage] == mTexName)
- {
- // already set!
- return TRUE;
- }
-
if (mTexName != 0)
{
#ifdef DEBUG_MISS
mMissed = ! getIsResident(TRUE);
#endif
-
- gGL.flush();
- if (stage > 0)
- {
- gGL.getTexUnit(stage)->activate();
- }
-
- glBindTexture(mBindTarget, mTexName);
- sCurrentBoundTextures[stage] = mTexName;
sBindCount++;
-
- if (stage > 0)
- {
- gGL.getTexUnit(0)->activate();
- }
-
if (mLastBindTime != sLastFrameTime)
{
// we haven't accounted for this texture yet this frame
@@ -463,38 +398,22 @@ BOOL LLImageGL::bindTextureInternal(const S32 stage) const
updateBoundTexMem(mTextureMemory);
mLastBindTime = sLastFrameTime;
}
-
- return TRUE;
- }
- else
- {
- gGL.flush();
- if (stage > 0)
- {
- gGL.getTexUnit(stage)->activate();
- }
- glBindTexture(mBindTarget, 0);
- if (stage > 0)
- {
- gGL.getTexUnit(0)->activate();
- }
- sCurrentBoundTextures[stage] = 0;
- return FALSE;
}
}
//virtual
-BOOL LLImageGL::bind(const S32 stage) const
+bool LLImageGL::bindError(const S32 stage) const
{
- if (stage == -1)
- {
- return FALSE;
- }
- BOOL res = bindTextureInternal(stage);
- //llassert(res);
- return res;
+ return false;
+}
+
+//virtual
+bool LLImageGL::bindDefaultImage(const S32 stage) const
+{
+ return false;
}
+
void LLImageGL::setExplicitFormat( LLGLint internal_format, LLGLenum primary_format, LLGLenum type_format, BOOL swap_bytes )
{
// Note: must be called before createTexture()
@@ -532,7 +451,7 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips)
{
// LLFastTimer t2(LLFastTimer::FTM_TEMP2);
- llverify(bindTextureInternal(0));
+ llverify(gGL.getTexUnit(0)->bind(this));
}
if (mUseMipMaps)
@@ -569,7 +488,8 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips)
}
glTexImage2D(mTarget, gl_level, mFormatInternal, w, h, 0, mFormatPrimary, GL_UNSIGNED_BYTE, (GLvoid*)data_in);
-
+ updatePickMask(w, h, data_in);
+
if(mFormatSwapBytes)
{
glPixelStorei(GL_UNPACK_SWAP_BYTES, 0);
@@ -585,7 +505,7 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips)
{
if (mAutoGenMips)
{
- glTexParameteri(mBindTarget, GL_GENERATE_MIPMAP_SGIS, TRUE);
+ glTexParameteri(LLTexUnit::getInternalType(mBindTarget), GL_GENERATE_MIPMAP_SGIS, TRUE);
stop_glerror();
{
// LLFastTimer t2(LLFastTimer::FTM_TEMP4);
@@ -596,12 +516,17 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips)
stop_glerror();
}
+ S32 w = getWidth(mCurrentDiscardLevel);
+ S32 h = getHeight(mCurrentDiscardLevel);
+
glTexImage2D(mTarget, 0, mFormatInternal,
- getWidth(mCurrentDiscardLevel), getHeight(mCurrentDiscardLevel), 0,
+ w, h, 0,
mFormatPrimary, mFormatType,
data_in);
stop_glerror();
+ updatePickMask(w, h, data_in);
+
if(mFormatSwapBytes)
{
glPixelStorei(GL_UNPACK_SWAP_BYTES, 0);
@@ -651,6 +576,10 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips)
glTexImage2D(mTarget, m, mFormatInternal, w, h, 0, mFormatPrimary, mFormatType, cur_mip_data);
stop_glerror();
+ if (m == 0)
+ {
+ updatePickMask(w, h, cur_mip_data);
+ }
if(mFormatSwapBytes)
{
@@ -701,6 +630,8 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips)
glTexImage2D(mTarget, 0, mFormatInternal, w, h, 0,
mFormatPrimary, mFormatType, (GLvoid *)data_in);
+ updatePickMask(w, h, data_in);
+
stop_glerror();
if(mFormatSwapBytes)
@@ -713,6 +644,7 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips)
mHasMipMaps = FALSE;
}
stop_glerror();
+ mInitialized = true;
}
BOOL LLImageGL::setSubImage(const U8* datap, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height)
@@ -786,12 +718,10 @@ BOOL LLImageGL::setSubImage(const U8* datap, S32 data_width, S32 data_height, S3
datap += (y_pos * data_width + x_pos) * getComponents();
// Update the GL texture
- BOOL res = bindTextureInternal(0);
+ BOOL res = gGL.getTexUnit(0)->bindManual(mBindTarget, mTexName);
if (!res) llerrs << "LLImageGL::setSubImage(): bindTexture failed" << llendl;
stop_glerror();
- LLGLEnable tex( GL_TEXTURE_2D );
-
glTexSubImage2D(mTarget, 0, x_pos, y_pos,
width, height, mFormatPrimary, mFormatType, datap);
stop_glerror();
@@ -804,6 +734,7 @@ BOOL LLImageGL::setSubImage(const U8* datap, S32 data_width, S32 data_height, S3
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
stop_glerror();
+ mInitialized = true;
}
return TRUE;
@@ -817,9 +748,10 @@ BOOL LLImageGL::setSubImage(const LLImageRaw* imageraw, S32 x_pos, S32 y_pos, S3
// Copy sub image from frame buffer
BOOL LLImageGL::setSubImageFromFrameBuffer(S32 fb_x, S32 fb_y, S32 x_pos, S32 y_pos, S32 width, S32 height)
{
- if (bindTextureInternal(0))
+ if (gGL.getTexUnit(0)->bind(this))
{
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, fb_x, fb_y, x_pos, y_pos, width, height);
+ mInitialized = true;
stop_glerror();
return TRUE;
}
@@ -919,9 +851,9 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_
stop_glerror();
{
// LLFastTimer t1(LLFastTimer::FTM_TEMP6);
- llverify(bindTextureInternal(0));
- glTexParameteri(mBindTarget, GL_TEXTURE_BASE_LEVEL, 0);
- glTexParameteri(mBindTarget, GL_TEXTURE_MAX_LEVEL, mMaxDiscardLevel-discard_level);
+ llverify(gGL.getTexUnit(0)->bind(this));
+ glTexParameteri(LLTexUnit::getInternalType(mBindTarget), GL_TEXTURE_BASE_LEVEL, 0);
+ glTexParameteri(LLTexUnit::getInternalType(mBindTarget), GL_TEXTURE_MAX_LEVEL, mMaxDiscardLevel-discard_level);
}
}
if (!mTexName)
@@ -949,7 +881,7 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_
setMipFilterNearest(mMagFilterNearest);
// things will break if we don't unbind after creation
- unbindTexture(0, mBindTarget);
+ gGL.getTexUnit(0)->unbind(mBindTarget);
stop_glerror();
if (old_name != 0)
@@ -1050,8 +982,8 @@ BOOL LLImageGL::readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compre
S32 gl_discard = discard_level - mCurrentDiscardLevel;
//explicitly unbind texture
- LLImageGL::unbindTexture(0, mTarget);
- llverify(bindTextureInternal(0));
+ gGL.getTexUnit(0)->unbind(mBindTarget);
+ llverify(gGL.getTexUnit(0)->bind(this));
if (gDebugGL)
{
@@ -1148,15 +1080,15 @@ BOOL LLImageGL::readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compre
void LLImageGL::destroyGLTexture()
{
- stop_glerror();
-
if (mTexName != 0)
{
+ stop_glerror();
+
for (int i = 0; i < gGLManager.mNumTextureUnits; i++)
{
if (sCurrentBoundTextures[i] == mTexName)
{
- unbindTexture(i, GL_TEXTURE_2D);
+ gGL.getTexUnit(i)->unbind(LLTexUnit::TT_TEXTURE);
stop_glerror();
}
}
@@ -1184,8 +1116,8 @@ void LLImageGL::glClamp (BOOL clamps, BOOL clampt)
{
if (mTexName != 0)
{
- glTexParameteri (mBindTarget, GL_TEXTURE_WRAP_S, clamps ? GL_CLAMP_TO_EDGE : GL_REPEAT);
- glTexParameteri (mBindTarget, GL_TEXTURE_WRAP_T, clampt ? GL_CLAMP_TO_EDGE : GL_REPEAT);
+ glTexParameteri (LLTexUnit::getInternalType(mBindTarget), GL_TEXTURE_WRAP_S, clamps ? GL_CLAMP_TO_EDGE : GL_REPEAT);
+ glTexParameteri (LLTexUnit::getInternalType(mBindTarget), GL_TEXTURE_WRAP_T, clampt ? GL_CLAMP_TO_EDGE : GL_REPEAT);
}
}
@@ -1223,23 +1155,23 @@ void LLImageGL::setMipFilterNearest(BOOL mag_nearest, BOOL min_nearest)
{
if (mMinFilterNearest)
{
- glTexParameteri(mBindTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(LLTexUnit::getInternalType(mBindTarget), GL_TEXTURE_MIN_FILTER, GL_NEAREST);
}
else if (mHasMipMaps)
{
- glTexParameteri(mBindTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
+ glTexParameteri(LLTexUnit::getInternalType(mBindTarget), GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
}
else
{
- glTexParameteri(mBindTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(LLTexUnit::getInternalType(mBindTarget), GL_TEXTURE_MIN_FILTER, GL_LINEAR);
}
if (mMagFilterNearest)
{
- glTexParameteri(mBindTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(LLTexUnit::getInternalType(mBindTarget), GL_TEXTURE_MAG_FILTER, GL_NEAREST);
}
else
{
- glTexParameteri(mBindTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(LLTexUnit::getInternalType(mBindTarget), GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
if (gGLManager.mHasAnisotropic)
{
@@ -1247,16 +1179,15 @@ void LLImageGL::setMipFilterNearest(BOOL mag_nearest, BOOL min_nearest)
{
F32 largest_anisotropy;
glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &largest_anisotropy);
- glTexParameterf(mBindTarget, GL_TEXTURE_MAX_ANISOTROPY_EXT, largest_anisotropy);
+ glTexParameterf(LLTexUnit::getInternalType(mBindTarget), GL_TEXTURE_MAX_ANISOTROPY_EXT, largest_anisotropy);
}
else
{
- glTexParameterf(mBindTarget, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.f);
+ glTexParameterf(LLTexUnit::getInternalType(mBindTarget), GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.f);
}
}
- }
-
- stop_glerror();
+ stop_glerror();
+ }
}
BOOL LLImageGL::getIsResident(BOOL test_now)
@@ -1337,14 +1268,93 @@ BOOL LLImageGL::getBoundRecently() const
return (BOOL)(sLastFrameTime - mLastBindTime < MIN_TEXTURE_LIFETIME);
}
-void LLImageGL::setTarget(const LLGLenum target, const LLGLenum bind_target)
+void LLImageGL::setTarget(const LLGLenum target, const LLTexUnit::eTextureType bind_target)
{
mTarget = target;
mBindTarget = bind_target;
}
+void LLImageGL::updatePickMask(S32 width, S32 height, const U8* data_in)
+{
+ if (mFormatType != GL_UNSIGNED_BYTE ||
+ mFormatPrimary != GL_RGBA)
+ {
+ //cannot generate a pick mask for this texture
+ delete [] mPickMask;
+ mPickMask = NULL;
+ return;
+ }
+
+ U32 pick_width = width/2;
+ U32 pick_height = height/2;
+
+ U32 size = llmax(pick_width, (U32) 1) * llmax(pick_height, (U32) 1);
+
+ size = size/8 + 1;
+
+ delete[] mPickMask;
+ mPickMask = new U8[size];
+
+ memset(mPickMask, 0, sizeof(U8) * size);
+
+ U32 pick_bit = 0;
+
+ for (S32 y = 0; y < height; y += 2)
+ {
+ for (S32 x = 0; x < width; x += 2)
+ {
+ U8 alpha = data_in[(y*width+x)*4+3];
+
+ if (alpha > 32)
+ {
+ U32 pick_idx = pick_bit/8;
+ U32 pick_offset = pick_bit%8;
+ if (pick_idx >= size)
+ {
+ llerrs << "WTF?" << llendl;
+ }
+
+ mPickMask[pick_idx] |= 1 << pick_offset;
+ }
+
+ ++pick_bit;
+ }
+ }
+}
+
+BOOL LLImageGL::getMask(const LLVector2 &tc)
+{
+ BOOL res = TRUE;
+
+ if (mPickMask)
+ {
+ S32 width = getWidth()/2;
+ S32 height = getHeight()/2;
+
+ F32 u = tc.mV[0] - floorf(tc.mV[0]);
+ F32 v = tc.mV[1] - floorf(tc.mV[1]);
+
+ if (u < 0.f || u > 1.f ||
+ v < 0.f || v > 1.f)
+ {
+ llerrs << "WTF?" << llendl;
+ }
+
+ S32 x = (S32)(u * width);
+ S32 y = (S32)(v * height);
+
+ S32 idx = y*width+x;
+ S32 offset = idx%8;
+
+ res = mPickMask[idx/8] & (1 << offset) ? TRUE : FALSE;
+ }
+
+ return res;
+}
+
//----------------------------------------------------------------------------
+
// Manual Mip Generation
/*
S32 width = getWidth(discard_level);
diff --git a/indra/llrender/llimagegl.h b/indra/llrender/llimagegl.h
index 8aeecb3627..35a98b88fa 100644
--- a/indra/llrender/llimagegl.h
+++ b/indra/llrender/llimagegl.h
@@ -37,6 +37,9 @@
#include "llgltypes.h"
#include "llmemory.h"
+#include "v2math.h"
+
+#include "llrender.h"
//============================================================================
@@ -48,11 +51,7 @@ public:
static S32 dataFormatBytes(S32 dataformat, S32 width, S32 height);
static S32 dataFormatComponents(S32 dataformat);
- // Wrapper for glBindTexture that keeps LLImageGL in sync.
- // Usually you want stage = 0 and bind_target = GL_TEXTURE_2D
- static void bindExternalTexture( LLGLuint gl_name, S32 stage, LLGLenum bind_target);
- static void unbindTexture(S32 stage, LLGLenum target);
- static void unbindTexture(S32 stage); // Uses GL_TEXTURE_2D (not a default arg to avoid gl.h dependency)
+ void updateBindStats(void) const;
// needs to be called every frame
static void updateStats(F32 current_time);
@@ -79,7 +78,6 @@ public:
protected:
virtual ~LLImageGL();
- BOOL bindTextureInternal(const S32 stage = 0) const;
private:
void glClamp (BOOL clamps, BOOL clampt);
@@ -87,7 +85,8 @@ private:
public:
virtual void dump(); // debugging info to llinfos
- virtual BOOL bind(const S32 stage = 0) const;
+ virtual bool bindError(const S32 stage = 0) const;
+ virtual bool bindDefaultImage(const S32 stage = 0) const;
void setSize(S32 width, S32 height, S32 ncomponents);
@@ -132,7 +131,11 @@ public:
BOOL getIsResident(BOOL test_now = FALSE); // not const
- void setTarget(const LLGLenum target, const LLGLenum bind_target);
+ void setTarget(const LLGLenum target, const LLTexUnit::eTextureType bind_target);
+
+ LLTexUnit::eTextureType getTarget(void) const { return mBindTarget; }
+ bool isInitialized(void) const { return mInitialized; }
+ void setInitialized (bool initialized) { mInitialized = initialized; }
BOOL getUseMipMaps() const { return mUseMipMaps; }
void setUseMipMaps(BOOL usemips) { mUseMipMaps = usemips; }
@@ -141,6 +144,9 @@ public:
BOOL isValidForSculpt(S32 discard_level, S32 image_width, S32 image_height, S32 ncomponents) ;
+ void updatePickMask(S32 width, S32 height, const U8* data_in);
+ BOOL getMask(const LLVector2 &tc);
+
protected:
void init(BOOL usemipmaps);
virtual void cleanup(); // Clean up the LLImageGL so it can be reinitialized. Be careful when using this in derived class destructors
@@ -152,6 +158,7 @@ public:
private:
LLPointer<LLImageRaw> mSaveData; // used for destroyGL/restoreGL
+ U8* mPickMask; //downsampled bitmap approximation of alpha channel. NULL if no alpha channel
S8 mUseMipMaps;
S8 mHasMipMaps;
S8 mHasExplicitFormat; // If false (default), GL format is f(mComponents)
@@ -159,7 +166,8 @@ private:
protected:
LLGLenum mTarget; // Normally GL_TEXTURE2D, sometimes something else (ex. cube maps)
- LLGLenum mBindTarget; // NOrmally GL_TEXTURE2D, sometimes something else (ex. cube maps)
+ LLTexUnit::eTextureType mBindTarget; // Normally TT_TEXTURE, sometimes something else (ex. cube maps)
+ bool mInitialized;
LLGLuint mTexName;
diff --git a/indra/llrender/llpostprocess.cpp b/indra/llrender/llpostprocess.cpp
index 7c14b57fff..3c1d8d3f17 100644
--- a/indra/llrender/llpostprocess.cpp
+++ b/indra/llrender/llpostprocess.cpp
@@ -220,9 +220,9 @@ void LLPostProcess::applyColorFilterShader(void)
gPostColorFilterProgram.bind();
gGL.getTexUnit(0)->activate();
- glEnable(GL_TEXTURE_RECTANGLE_ARB);
+ gGL.getTexUnit(0)->enable(LLTexUnit::TT_RECT_TEXTURE);
- glBindTexture(GL_TEXTURE_RECTANGLE_ARB, sceneRenderTexture);
+ gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_RECT_TEXTURE, sceneRenderTexture);
getShaderUniforms(colorFilterUniforms, gPostColorFilterProgram.mProgramObject);
glUniform1iARB(colorFilterUniforms["RenderTexture"], 0);
@@ -264,16 +264,16 @@ void LLPostProcess::applyNightVisionShader(void)
gPostNightVisionProgram.bind();
gGL.getTexUnit(0)->activate();
- glEnable(GL_TEXTURE_RECTANGLE_ARB);
+ gGL.getTexUnit(0)->enable(LLTexUnit::TT_RECT_TEXTURE);
getShaderUniforms(nightVisionUniforms, gPostNightVisionProgram.mProgramObject);
- glBindTexture(GL_TEXTURE_RECTANGLE_ARB, sceneRenderTexture);
+ gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_RECT_TEXTURE, sceneRenderTexture);
glUniform1iARB(nightVisionUniforms["RenderTexture"], 0);
gGL.getTexUnit(1)->activate();
- glEnable(GL_TEXTURE_2D);
+ gGL.getTexUnit(1)->enable(LLTexUnit::TT_TEXTURE);
- glBindTexture(GL_TEXTURE_2D, noiseTexture);
+ gGL.getTexUnit(1)->bindManual(LLTexUnit::TT_TEXTURE, noiseTexture);
glUniform1iARB(nightVisionUniforms["NoiseTexture"], 1);
@@ -373,7 +373,7 @@ void LLPostProcess::doEffects(void)
void LLPostProcess::copyFrameBuffer(GLuint & texture, unsigned int width, unsigned int height)
{
- glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texture);
+ gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_RECT_TEXTURE, texture);
glCopyTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, 0, 0, width, height, 0);
}
@@ -487,7 +487,7 @@ void LLPostProcess::createTexture(GLuint & texture, unsigned int width, unsigned
std::vector<GLubyte> data(width * height * 4, 0);
glGenTextures(1, &texture);
- glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texture);
+ gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_RECT_TEXTURE, texture);
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 4, width, height, 0,
GL_RGBA, GL_UNSIGNED_BYTE, &data[0]);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
@@ -509,7 +509,7 @@ void LLPostProcess::createNoiseTexture(GLuint & texture)
buffer[(i * NOISE_SIZE) + k] = (GLubyte)((double) rand() / ((double) RAND_MAX + 1.f) * 255.f);
}
}
- glBindTexture(GL_TEXTURE_2D, texture);
+ gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, NOISE_SIZE, NOISE_SIZE, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, &buffer[0]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,GL_LINEAR);
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;
+}
+
diff --git a/indra/llrender/llrender.h b/indra/llrender/llrender.h
index 5133f2804e..e604bbb84c 100644
--- a/indra/llrender/llrender.h
+++ b/indra/llrender/llrender.h
@@ -37,14 +37,39 @@
#ifndef LL_LLGLRENDER_H
#define LL_LLGLRENDER_H
-#include "stdtypes.h"
-#include "llgltypes.h"
+//#include "linden_common.h"
+
+#include "v2math.h"
+#include "v3math.h"
+#include "v4coloru.h"
+#include "llstrider.h"
+#include "llmemory.h"
#include "llglheaders.h"
-#include "llvertexbuffer.h"
+
+class LLVertexBuffer;
+class LLCubeMap;
+class LLImageGL;
+class LLRenderTarget;
class LLTexUnit
{
+ friend class LLRender;
public:
+ typedef enum
+ {
+ TT_TEXTURE = 0, // Standard 2D Texture
+ TT_RECT_TEXTURE, // Non power of 2 texture
+ TT_CUBE_MAP, // 6-sided cube map texture
+ TT_NONE // No texture type is currently enabled
+ } eTextureType;
+
+ typedef enum
+ {
+ TAM_WRAP = 0, // Standard 2D Texture
+ TAM_MIRROR, // Non power of 2 texture
+ TAM_CLAMP // No texture type is currently enabled
+ } eTextureAddressMode;
+
typedef enum
{
TB_REPLACE = 0,
@@ -93,15 +118,36 @@ public:
TBS_ONE_MINUS_CONST_ALPHA
} eTextureBlendSrc;
- LLTexUnit(U32 index);
- U32 getIndex(void);
+ LLTexUnit(S32 index);
+
+ // Refreshes renderer state of the texture unit to the cached values
+ // Needed when the render context has changed and invalidated the current state
+ void refreshState(void);
+
+ // returns the index of this texture unit
+ S32 getIndex(void) const { return mIndex; }
- void enable(void);
- void disable(void);
- void activate(void);
+ // Sets this tex unit to be the currently active one
+ void activate(void);
+
+ // Enables this texture unit for the given texture type (automatically disables any previously enabled texture type)
+ void enable(eTextureType type);
+ // Disables the current texture unit
+ void disable(void);
+
+ // Binds the LLImageGL to this texture unit (automatically enables the unit for the LLImageGL's texture type)
+ bool bind(const LLImageGL* texture);
+ // Binds a cubemap to this texture unit (automatically enables the texture unit for cubemaps)
+ bool bind(LLCubeMap* cubeMap);
+ // Binds a render target to this texture unit (automatically enables the texture unit for the RT's texture type)
+ bool bind(LLRenderTarget * renderTarget, bool bindDepth = false);
+ // Manually binds a texture to the texture unit (automatically enables the tex unit for the given texture type)
+ bool bindManual(eTextureType type, U32 texture);
+
+ // Unbinds the currently bound texture of the given type (only if there's a texture of the given type currently bound)
+ void unbind(eTextureType type);
- void bindTexture(const LLImageGL* texture);
- void unbindTexture(void);
+ void setTextureAddressMode(eTextureAddressMode mode);
void setTextureBlendType(eTextureBlendType type);
@@ -110,11 +156,14 @@ public:
// NOTE: If *_COLOR enums are passed to src1 or src2, the corresponding *_ALPHA enum will be used instead.
inline void setTextureAlphaBlend(eTextureBlendOp op, eTextureBlendSrc src1, eTextureBlendSrc src2 = TBS_PREV_ALPHA)
- { setTextureCombiner(op, src1, src2, true); }
+ { setTextureCombiner(op, src1, src2, true); }
-private:
- U32 mIndex;
- bool mIsEnabled;
+ static U32 getInternalType(eTextureType type);
+
+protected:
+ S32 mIndex;
+ U32 mCurrTexture;
+ eTextureType mCurrTexType;
eTextureBlendType mCurrBlendType;
eTextureBlendOp mCurrColorOp;
eTextureBlendSrc mCurrColorSrc1;
@@ -137,6 +186,19 @@ class LLRender
{
friend class LLTexUnit;
public:
+
+ typedef enum {
+ TRIANGLES = 0,
+ TRIANGLE_STRIP,
+ TRIANGLE_FAN,
+ POINTS,
+ LINES,
+ LINE_STRIP,
+ QUADS,
+ LINE_LOOP,
+ NUM_MODES
+ } eGeomModes;
+
typedef enum
{
CF_NEVER = 0,
@@ -178,6 +240,10 @@ public:
~LLRender();
void shutdown();
+ // Refreshes renderer state to the cached values
+ // Needed when the render context has changed and invalidated the current state
+ void refreshState(void);
+
void translatef(const GLfloat& x, const GLfloat& y, const GLfloat& z);
void scalef(const GLfloat& x, const GLfloat& y, const GLfloat& z);
void pushMatrix();
@@ -214,6 +280,12 @@ public:
LLTexUnit* getTexUnit(U32 index);
+ U32 getCurrentTexUnitIndex(void) const { return mCurrTextureUnitIndex; }
+
+ bool verifyTexUnitActive(U32 unitToVerify);
+
+ void debugTexUnits(void);
+
struct Vertex
{
GLfloat v[3];
@@ -224,14 +296,20 @@ public:
public:
private:
- U32 mCount;
- U32 mMode;
- U32 mCurrTextureUnitIndex;
- LLPointer<LLVertexBuffer> mBuffer;
- LLStrider<LLVector3> mVerticesp;
- LLStrider<LLVector2> mTexcoordsp;
- LLStrider<LLColor4U> mColorsp;
- std::vector<LLTexUnit*> mTexUnits;
+ bool mDirty;
+ U32 mCount;
+ U32 mMode;
+ U32 mCurrTextureUnitIndex;
+ bool mCurrColorMask[4];
+ eCompareFunc mCurrAlphaFunc;
+ F32 mCurrAlphaFuncVal;
+
+ LLPointer<LLVertexBuffer> mBuffer;
+ LLStrider<LLVector3> mVerticesp;
+ LLStrider<LLVector2> mTexcoordsp;
+ LLStrider<LLColor4U> mColorsp;
+ std::vector<LLTexUnit*> mTexUnits;
+ LLTexUnit* mDummyTexUnit;
};
extern F64 gGLModelView[16];
diff --git a/indra/llrender/llrendertarget.cpp b/indra/llrender/llrendertarget.cpp
index cfb7496795..1b57e43f07 100644
--- a/indra/llrender/llrendertarget.cpp
+++ b/indra/llrender/llrendertarget.cpp
@@ -47,7 +47,7 @@ LLRenderTarget::LLRenderTarget() :
mStencil(0),
mUseDepth(FALSE),
mRenderDepth(FALSE),
- mUsage(GL_TEXTURE_2D)
+ mUsage(LLTexUnit::TT_TEXTURE)
{
}
@@ -56,7 +56,7 @@ LLRenderTarget::~LLRenderTarget()
release();
}
-void LLRenderTarget::allocate(U32 resx, U32 resy, U32 color_fmt, BOOL depth, U32 usage, BOOL use_fbo)
+void LLRenderTarget::allocate(U32 resx, U32 resy, U32 color_fmt, BOOL depth, LLTexUnit::eTextureType usage, BOOL use_fbo)
{
stop_glerror();
mResX = resx;
@@ -67,22 +67,22 @@ void LLRenderTarget::allocate(U32 resx, U32 resy, U32 color_fmt, BOOL depth, U32
release();
glGenTextures(1, (GLuint *) &mTex);
- glBindTexture(mUsage, mTex);
- glTexImage2D(mUsage, 0, color_fmt, mResX, mResY, 0, color_fmt, GL_UNSIGNED_BYTE, NULL);
+ gGL.getTexUnit(0)->bindManual(mUsage, mTex);
+ glTexImage2D(LLTexUnit::getInternalType(mUsage), 0, color_fmt, mResX, mResY, 0, color_fmt, GL_UNSIGNED_BYTE, NULL);
- glTexParameteri(mUsage, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameteri(mUsage, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(LLTexUnit::getInternalType(mUsage), GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(LLTexUnit::getInternalType(mUsage), GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- if (mUsage != GL_TEXTURE_RECTANGLE_ARB)
+ if (mUsage != LLTexUnit::TT_RECT_TEXTURE)
{
- glTexParameteri(mUsage, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
- glTexParameteri(mUsage, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);
+ glTexParameteri(LLTexUnit::getInternalType(mUsage), GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
+ glTexParameteri(LLTexUnit::getInternalType(mUsage), GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);
}
else
{
// ATI doesn't support mirrored repeat for rectangular textures.
- glTexParameteri(mUsage, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(mUsage, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glTexParameteri(LLTexUnit::getInternalType(mUsage), GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(LLTexUnit::getInternalType(mUsage), GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
}
stop_glerror();
@@ -107,14 +107,14 @@ void LLRenderTarget::allocate(U32 resx, U32 resy, U32 color_fmt, BOOL depth, U32
if (mDepth)
{
- glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, mUsage, mDepth, 0);
+ glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, LLTexUnit::getInternalType(mUsage), mDepth, 0);
stop_glerror();
- glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, mUsage, mDepth, 0);
+ glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, LLTexUnit::getInternalType(mUsage), mDepth, 0);
stop_glerror();
}
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
- mUsage, mTex, 0);
+ LLTexUnit::getInternalType(mUsage), mTex, 0);
stop_glerror();
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
@@ -125,10 +125,11 @@ void LLRenderTarget::allocate(U32 resx, U32 resy, U32 color_fmt, BOOL depth, U32
void LLRenderTarget::allocateDepth()
{
glGenTextures(1, (GLuint *) &mDepth);
- glBindTexture(mUsage, mDepth);
- glTexParameteri(mUsage, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri(mUsage, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexImage2D(mUsage, 0, GL_DEPTH24_STENCIL8_EXT, mResX, mResY, 0, GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT, NULL);
+ gGL.getTexUnit(0)->bindManual(mUsage, mDepth);
+ U32 internal_type = LLTexUnit::getInternalType(mUsage);
+ glTexParameteri(internal_type, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(internal_type, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexImage2D(internal_type, 0, GL_DEPTH24_STENCIL8_EXT, mResX, mResY, 0, GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT, NULL);
}
void LLRenderTarget::release()
@@ -191,24 +192,13 @@ void LLRenderTarget::clear()
}
}
-void LLRenderTarget::bindTexture()
-{
- glBindTexture(mUsage, mTex);
-}
-
-void LLRenderTarget::bindDepth()
-{
- glBindTexture(mUsage, mDepth);
-}
-
-
void LLRenderTarget::flush(BOOL fetch_depth)
{
gGL.flush();
if (!mFBO)
{
- bindTexture();
- glCopyTexSubImage2D(mUsage, 0, 0, 0, 0, 0, mResX, mResY);
+ gGL.getTexUnit(0)->bind(this);
+ glCopyTexSubImage2D(LLTexUnit::getInternalType(mUsage), 0, 0, 0, 0, 0, mResX, mResY);
if (fetch_depth)
{
@@ -217,8 +207,8 @@ void LLRenderTarget::flush(BOOL fetch_depth)
allocateDepth();
}
- bindDepth();
- glCopyTexImage2D(mUsage, 0, GL_DEPTH24_STENCIL8_EXT, 0, 0, mResX, mResY, 0);
+ gGL.getTexUnit(0)->bind(this, true);
+ glCopyTexImage2D(LLTexUnit::getInternalType(mUsage), 0, GL_DEPTH24_STENCIL8_EXT, 0, 0, mResX, mResY, 0);
}
}
else
diff --git a/indra/llrender/llrendertarget.h b/indra/llrender/llrendertarget.h
index df88640970..bb6131741c 100644
--- a/indra/llrender/llrendertarget.h
+++ b/indra/llrender/llrendertarget.h
@@ -33,6 +33,7 @@
#define LL_LLRENDERTARGET_H
#include "llgl.h"
+#include "llrender.h"
/*
SAMPLE USAGE:
@@ -53,7 +54,7 @@
...
//use target as a texture
- target.bindTexture();
+ gGL.getTexUnit(INDEX)->bind(&target);
... <issue drawing commands> ...
*/
@@ -71,7 +72,7 @@ public:
//allocate resources for rendering
//must be called before use
//multiple calls will release previously allocated resources
- void allocate(U32 resx, U32 resy, U32 color_fmt, BOOL depth, U32 usage = GL_TEXTURE_2D, BOOL use_fbo = FALSE);
+ void allocate(U32 resx, U32 resy, U32 color_fmt, BOOL depth, LLTexUnit::eTextureType usage = LLTexUnit::TT_TEXTURE, BOOL use_fbo = FALSE);
//allocate a depth texture
void allocateDepth();
@@ -100,11 +101,11 @@ public:
//get Y resolution
U32 getHeight() const { return mResY; }
- //bind results of render for sampling
- void bindTexture();
+ LLTexUnit::eTextureType getUsage(void) const { return mUsage; }
- //bind results of render for sampling depth buffer
- void bindDepth();
+ U32 getTexture(void) const { return mTex; }
+
+ U32 getDepth(void) const { return mDepth; }
//flush rendering operations
//must be called when rendering is complete
@@ -128,7 +129,7 @@ private:
U32 mStencil;
BOOL mUseDepth;
BOOL mRenderDepth;
- U32 mUsage;
+ LLTexUnit::eTextureType mUsage;
};
diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp
index 3bdc36c677..7a3bcafaf0 100644
--- a/indra/llrender/llshadermgr.cpp
+++ b/indra/llrender/llshadermgr.cpp
@@ -307,7 +307,7 @@ void LLShaderMgr::dumpObjectLog(GLhandleARB ret, BOOL warns)
{
LL_DEBUGS("ShaderLoading") << log << LL_ENDL;
}
-}
+ }
}
GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_level, GLenum type)
diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp
index 2414d2adff..0bb0ea81a2 100644
--- a/indra/llrender/llvertexbuffer.cpp
+++ b/indra/llrender/llvertexbuffer.cpp
@@ -76,7 +76,7 @@ S32 LLVertexBuffer::sTypeOffsets[LLVertexBuffer::TYPE_MAX] =
sizeof(LLVector4), // TYPE_CLOTHWEIGHT,
};
-U32 LLVertexBuffer::sGLMode[LLVertexBuffer::NUM_MODES] =
+U32 LLVertexBuffer::sGLMode[LLRender::NUM_MODES] =
{
GL_TRIANGLES,
GL_TRIANGLE_STRIP,
@@ -187,7 +187,7 @@ void LLVertexBuffer::drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indi
llerrs << "Wrong vertex buffer bound." << llendl;
}
- if (mode > NUM_MODES)
+ if (mode > LLRender::NUM_MODES)
{
llerrs << "Invalid draw mode: " << mode << llendl;
return;
@@ -216,7 +216,7 @@ void LLVertexBuffer::draw(U32 mode, U32 count, U32 indices_offset) const
llerrs << "Wrong vertex buffer bound." << llendl;
}
- if (mode > NUM_MODES)
+ if (mode > LLRender::NUM_MODES)
{
llerrs << "Invalid draw mode: " << mode << llendl;
return;
@@ -240,7 +240,7 @@ void LLVertexBuffer::drawArrays(U32 mode, U32 first, U32 count) const
llerrs << "Wrong vertex buffer bound." << llendl;
}
- if (mode > NUM_MODES)
+ if (mode > LLRender::NUM_MODES)
{
llerrs << "Invalid draw mode: " << mode << llendl;
return;
diff --git a/indra/llrender/llvertexbuffer.h b/indra/llrender/llvertexbuffer.h
index 45f501fe1e..e11eb43702 100644
--- a/indra/llrender/llvertexbuffer.h
+++ b/indra/llrender/llvertexbuffer.h
@@ -39,6 +39,7 @@
#include "v4coloru.h"
#include "llstrider.h"
#include "llmemory.h"
+#include "llrender.h"
#include <set>
#include <vector>
#include <list>
@@ -123,19 +124,8 @@ public:
MAP_UNMAPPED = 0x8000 // Indicates that buffer has been logically un-mapped
};
- enum {
- TRIANGLES = 0,
- TRIANGLE_STRIP,
- TRIANGLE_FAN,
- POINTS,
- LINES,
- LINE_STRIP,
- QUADS,
- LINE_LOOP,
- NUM_MODES
- };
protected:
- friend class LLGLImmediate;
+ friend class LLRender;
virtual ~LLVertexBuffer(); // use unref()
@@ -255,7 +245,7 @@ public:
static BOOL sEnableVBOs;
static S32 sTypeOffsets[TYPE_MAX];
- static U32 sGLMode[NUM_MODES];
+ static U32 sGLMode[LLRender::NUM_MODES];
static U32 sGLRenderBuffer;
static U32 sGLRenderIndices;
static BOOL sVBOActive;