From f89f19990cbb9f3f2e7473ac6c159098bdfabec7 Mon Sep 17 00:00:00 2001 From: Mark Palange Date: Fri, 7 Nov 2008 17:51:03 +0000 Subject: 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 --- indra/llrender/llcubemap.cpp | 54 ++---- indra/llrender/llcubemap.h | 2 + indra/llrender/llfontgl.cpp | 20 +-- indra/llrender/llgl.cpp | 29 +-- indra/llrender/llglslshader.cpp | 8 +- indra/llrender/llglslshader.h | 5 +- indra/llrender/llglstates.h | 22 +-- indra/llrender/llimagegl.cpp | 266 ++++++++++++++-------------- indra/llrender/llimagegl.h | 26 ++- indra/llrender/llpostprocess.cpp | 18 +- indra/llrender/llrender.cpp | 364 ++++++++++++++++++++++++++++++++------ indra/llrender/llrender.h | 122 ++++++++++--- indra/llrender/llrendertarget.cpp | 56 +++--- indra/llrender/llrendertarget.h | 15 +- indra/llrender/llshadermgr.cpp | 2 +- indra/llrender/llvertexbuffer.cpp | 8 +- indra/llrender/llvertexbuffer.h | 16 +- 17 files changed, 654 insertions(+), 379 deletions(-) (limited to 'indra/llrender') 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 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 @@ -124,49 +124,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) { @@ -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::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 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 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 mBuffer; - LLStrider mVerticesp; - LLStrider mTexcoordsp; - LLStrider mColorsp; - std::vector mTexUnits; + bool mDirty; + U32 mCount; + U32 mMode; + U32 mCurrTextureUnitIndex; + bool mCurrColorMask[4]; + eCompareFunc mCurrAlphaFunc; + F32 mCurrAlphaFuncVal; + + LLPointer mBuffer; + LLStrider mVerticesp; + LLStrider mTexcoordsp; + LLStrider mColorsp; + std::vector 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); ... ... */ @@ -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 #include #include @@ -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; -- cgit v1.2.3