From 536e38ad51b89808f26d8e3cd107fe093862d22a Mon Sep 17 00:00:00 2001 From: David Parks Date: Tue, 22 Sep 2009 11:11:45 +0000 Subject: Merging render-pipeline-6-qa-2 into viewer-2 Self reviewed. --- indra/llrender/llgl.cpp | 27 +++-- indra/llrender/llgl.h | 32 ++++++ indra/llrender/llimagegl.cpp | 214 +++++++++++++++++++++++++++++++++++--- indra/llrender/llimagegl.h | 44 +++++++- indra/llrender/llrender.cpp | 10 +- indra/llrender/llrender.h | 1 + indra/llrender/llrendertarget.cpp | 59 +++++++++-- indra/llrender/llrendertarget.h | 4 + 8 files changed, 356 insertions(+), 35 deletions(-) (limited to 'indra/llrender') diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp index 7e1df0e565..e29688bf24 100644 --- a/indra/llrender/llgl.cpp +++ b/indra/llrender/llgl.cpp @@ -64,6 +64,8 @@ BOOL gDebugSession = FALSE; BOOL gDebugGL = FALSE; BOOL gClothRipple = FALSE; BOOL gNoRender = FALSE; +BOOL gGLActive = FALSE; + std::ofstream gFailLog; @@ -107,6 +109,7 @@ LLMatrix4 gGLObliqueProjectionInverse; #define LL_GL_NAME_POOLING 0 LLGLNamePool::pool_list_t LLGLNamePool::sInstances; +std::list LLGLUpdate::sGLQ; #if (LL_WINDOWS || LL_LINUX || LL_SOLARIS) && !LL_MESA_HEADLESS // ATI prototypes @@ -1013,6 +1016,16 @@ void flush_glerror() void assert_glerror() { + if (!gGLActive) + { + //llwarns << "GL used while not active!" << llendl; + + if (gDebugSession) + { + ll_fail("GL used while not active"); + } + } + if (gNoRender || !gDebugGL) { return; @@ -1258,8 +1271,10 @@ void LLGLState::checkTextureChannels(const std::string& msg) }; GLint stackDepth = 0; - LLMatrix4 identity; - LLMatrix4 matrix; + + glh::matrix4f mat; + glh::matrix4f identity; + identity.identity(); for (GLint i = 1; i < maxTextureUnits; i++) { @@ -1280,10 +1295,10 @@ void LLGLState::checkTextureChannels(const std::string& msg) } } - glGetFloatv(GL_TEXTURE_MATRIX, (GLfloat*) matrix.mMatrix); + glGetFloatv(GL_TEXTURE_MATRIX, (GLfloat*) mat.m); stop_glerror(); - if (matrix != identity) + if (mat != identity) { error = TRUE; LL_WARNS("RenderState") << "Texture matrix in channel " << i << " corrupt." << LL_ENDL; @@ -1309,10 +1324,6 @@ void LLGLState::checkTextureChannels(const std::string& msg) stop_glerror(); } - glh::matrix4f mat; - glh::matrix4f identity; - identity.identity(); - glGetFloatv(GL_TEXTURE_MATRIX, mat.m); stop_glerror(); diff --git a/indra/llrender/llgl.h b/indra/llrender/llgl.h index 34dd982259..91421f3c95 100644 --- a/indra/llrender/llgl.h +++ b/indra/llrender/llgl.h @@ -37,6 +37,7 @@ #include #include +#include #include "llerror.h" #include "v4color.h" @@ -367,6 +368,35 @@ protected: virtual void releaseName(GLuint name) = 0; }; +/* + Interface for objects that need periodic GL updates applied to them. + Used to synchronize GL updates with GL thread. +*/ +class LLGLUpdate +{ +public: + + static std::list sGLQ; + + BOOL mInQ; + LLGLUpdate() + : mInQ(FALSE) + { + } + virtual ~LLGLUpdate() + { + if (mInQ) + { + std::list::iterator iter = std::find(sGLQ.begin(), sGLQ.end(), this); + if (iter != sGLQ.end()) + { + sGLQ.erase(iter); + } + } + } + virtual void updateGL() = 0; +}; + extern LLMatrix4 gGLObliqueProjectionInverse; #include "llglstates.h" @@ -385,4 +415,6 @@ void parse_gl_version( S32* major, S32* minor, S32* release, std::string* vendor extern BOOL gClothRipple; extern BOOL gNoRender; +extern BOOL gGLActive; + #endif // LL_LLGL_H diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index 9d2cd4867a..dd64d753c7 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -44,7 +44,6 @@ #include "llgl.h" #include "llrender.h" - //---------------------------------------------------------------------------- const F32 MIN_TEXTURE_LIFETIME = 10.f; @@ -57,12 +56,25 @@ S32 LLImageGL::sGlobalTextureMemoryInBytes = 0; S32 LLImageGL::sBoundTextureMemoryInBytes = 0; S32 LLImageGL::sCurBoundTextureMemory = 0; S32 LLImageGL::sCount = 0; +std::list LLImageGL::sDeadTextureList; BOOL LLImageGL::sGlobalUseAnisotropic = FALSE; F32 LLImageGL::sLastFrameTime = 0.f; LLImageGL* LLImageGL::sDefaultGLTexture = NULL ; std::set LLImageGL::sImageList; +#if !LL_RELEASE_FOR_DOWNLOAD +//----------------------- +//debug use +#define MAX_TEXTURE_LOG_SIZE 22 //2048 * 2048 +std::vector LLImageGL::sTextureLoadedCounter(MAX_TEXTURE_LOG_SIZE + 1) ; +std::vector LLImageGL::sTextureBoundCounter(MAX_TEXTURE_LOG_SIZE + 1) ; +std::vector LLImageGL::sTextureCurBoundCounter(MAX_TEXTURE_LOG_SIZE + 1) ; +S32 LLImageGL::sCurTexSizeBar = -1 ; +S32 LLImageGL::sCurTexPickSize = -1 ; +LLPointer LLImageGL::sDefaultTexturep = NULL; +//------------------------ +#endif //************************************************************************************** //below are functions for debug use //do not delete them even though they are not currently being used. @@ -198,6 +210,14 @@ void LLImageGL::updateStats(F32 current_time) sLastFrameTime = current_time; sBoundTextureMemoryInBytes = sCurBoundTextureMemory; sCurBoundTextureMemory = 0; + +#if !LL_RELEASE_FOR_DOWNLOAD + for(U32 i = 0 ; i < sTextureCurBoundCounter.size() ; i++) + { + sTextureBoundCounter[i] = sTextureCurBoundCounter[i] ; + sTextureCurBoundCounter[i] = 0 ; + } +#endif } //static @@ -363,6 +383,10 @@ void LLImageGL::init(BOOL usemipmaps) mGLTextureCreated = FALSE ; mIsMask = FALSE; mNeedsAlphaAndPickMask = TRUE ; + + mDiscardLevelInAtlas = -1 ; + mTexelsInAtlas = 0 ; + mTexelsInGLTexture = 0 ; } void LLImageGL::cleanup() @@ -523,7 +547,7 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips) is_compressed = true; } - gGL.getTexUnit(0)->bind(this); + llverify(gGL.getTexUnit(0)->bind(this)); if (mUseMipMaps) { @@ -728,6 +752,92 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips) llpushcallstacks ; } +BOOL LLImageGL::preAddToAtlas(S32 discard_level, const LLImageRaw* raw_image) +{ + if (gGLManager.mIsDisabled) + { + llwarns << "Trying to create a texture while GL is disabled!" << llendl; + return FALSE; + } + llassert(gGLManager.mInited); + stop_glerror(); + + if (discard_level < 0) + { + llassert(mCurrentDiscardLevel >= 0); + discard_level = mCurrentDiscardLevel; + } + discard_level = llclamp(discard_level, 0, (S32)mMaxDiscardLevel); + + // Actual image width/height = raw image width/height * 2^discard_level + S32 w = raw_image->getWidth() << discard_level; + S32 h = raw_image->getHeight() << discard_level; + + // setSize may call destroyGLTexture if the size does not match + setSize(w, h, raw_image->getComponents()); + + if( !mHasExplicitFormat ) + { + switch (mComponents) + { + case 1: + // Use luminance alpha (for fonts) + mFormatInternal = GL_LUMINANCE8; + mFormatPrimary = GL_LUMINANCE; + mFormatType = GL_UNSIGNED_BYTE; + break; + case 2: + // Use luminance alpha (for fonts) + mFormatInternal = GL_LUMINANCE8_ALPHA8; + mFormatPrimary = GL_LUMINANCE_ALPHA; + mFormatType = GL_UNSIGNED_BYTE; + break; + case 3: + mFormatInternal = GL_RGB8; + mFormatPrimary = GL_RGB; + mFormatType = GL_UNSIGNED_BYTE; + break; + case 4: + mFormatInternal = GL_RGBA8; + mFormatPrimary = GL_RGBA; + mFormatType = GL_UNSIGNED_BYTE; + break; + default: + llerrs << "Bad number of components for texture: " << (U32)getComponents() << llendl; + } + } + + mCurrentDiscardLevel = discard_level; + mDiscardLevelInAtlas = discard_level; + mTexelsInAtlas = raw_image->getWidth() * raw_image->getHeight() ; + mLastBindTime = sLastFrameTime; + mGLTextureCreated = false ; + + glPixelStorei(GL_UNPACK_ROW_LENGTH, raw_image->getWidth()); + stop_glerror(); + + if(mFormatSwapBytes) + { + glPixelStorei(GL_UNPACK_SWAP_BYTES, 1); + stop_glerror(); + } + + return TRUE ; +} + +void LLImageGL::postAddToAtlas() +{ + if(mFormatSwapBytes) + { + glPixelStorei(GL_UNPACK_SWAP_BYTES, 0); + stop_glerror(); + } + + glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); + gGL.getTexUnit(0)->setTextureFilteringOption(mFilterOption); + stop_glerror(); +} + BOOL LLImageGL::setSubImage(const U8* datap, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height, BOOL force_fast_update) { llpushcallstacks ; @@ -832,7 +942,7 @@ 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 (gGL.getTexUnit(0)->bind(this, true)) + if (gGL.getTexUnit(0)->bind(this)) { glCopyTexSubImage2D(GL_TEXTURE_2D, 0, fb_x, fb_y, x_pos, y_pos, width, height); mGLTextureCreated = true; @@ -854,13 +964,17 @@ void LLImageGL::generateTextures(S32 numTextures, U32 *textures) // static void LLImageGL::deleteTextures(S32 numTextures, U32 *textures) { - glDeleteTextures(numTextures, (GLuint*)textures); + for (S32 i = 0; i < numTextures; i++) + { + sDeadTextureList.push_back(textures[i]); + } } // static void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 width, S32 height, U32 pixformat, U32 pixtype, const void *pixels) { glTexImage2D(target, miplevel, intformat, width, height, 0, pixformat, pixtype, pixels); + stop_glerror(); } //create an empty GL texture: just create a texture name @@ -895,12 +1009,12 @@ BOOL LLImageGL::createGLTexture() BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename/*=0*/) { - llpushcallstacks ; if (gGLManager.mIsDisabled) { llwarns << "Trying to create a texture while GL is disabled!" << llendl; return FALSE; } + mGLTextureCreated = false ; llassert(gGLManager.mInited); stop_glerror(); @@ -1023,12 +1137,21 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_ if (old_name != 0) { sGlobalTextureMemoryInBytes -= mTextureMemory; +#if !LL_RELEASE_FOR_DOWNLOAD + decTextureCounter(mTextureMemory / mComponents) ; +#endif + LLImageGL::deleteTextures(1, &old_name); stop_glerror(); } mTextureMemory = getMipBytes(discard_level); sGlobalTextureMemoryInBytes += mTextureMemory; + mTexelsInGLTexture = getWidth() * getHeight() ; + +#if !LL_RELEASE_FOR_DOWNLOAD + incTextureCounter(mTextureMemory / mComponents) ; +#endif // mark this as bound at this point, so we don't throw it out immediately mLastBindTime = sLastFrameTime; @@ -1208,32 +1331,48 @@ BOOL LLImageGL::readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compre return TRUE ; } -void LLImageGL::destroyGLTexture() +void LLImageGL::deleteDeadTextures() { - if (mTexName != 0) + while (!sDeadTextureList.empty()) { - stop_glerror(); - + GLuint tex = sDeadTextureList.front(); + sDeadTextureList.pop_front(); for (int i = 0; i < gGLManager.mNumTextureUnits; i++) { - if (sCurrentBoundTextures[i] == mTexName) + if (sCurrentBoundTextures[i] == tex) { gGL.getTexUnit(i)->unbind(LLTexUnit::TT_TEXTURE); stop_glerror(); } } - sGlobalTextureMemoryInBytes -= mTextureMemory; - mTextureMemory = 0; + glDeleteTextures(1, &tex); + stop_glerror(); + } +} + +void LLImageGL::destroyGLTexture() +{ + if (mTexName != 0) + { + if(mTextureMemory) + { +#if !LL_RELEASE_FOR_DOWNLOAD + decTextureCounter(mTextureMemory / mComponents) ; +#endif + sGlobalTextureMemoryInBytes -= mTextureMemory; + mTextureMemory = 0; + } LLImageGL::deleteTextures(1, &mTexName); mTexName = 0; mCurrentDiscardLevel = -1 ; //invalidate mCurrentDiscardLevel. mGLTextureCreated = FALSE ; - stop_glerror(); } } + + //---------------------------------------------------------------------------- void LLImageGL::setAddressMode(LLTexUnit::eTextureAddressMode mode) @@ -1259,12 +1398,12 @@ void LLImageGL::setFilteringOption(LLTexUnit::eTextureFilterOptions option) mFilterOption = option; } - if (gGL.getTexUnit(gGL.getCurrentTexUnitIndex())->getCurrTexture() == mTexName) + if (mTexName != 0 && gGL.getTexUnit(gGL.getCurrentTexUnitIndex())->getCurrTexture() == mTexName) { gGL.getTexUnit(gGL.getCurrentTexUnitIndex())->setTextureFilteringOption(option); mTexOptionsDirty = false; + stop_glerror(); } - stop_glerror(); } BOOL LLImageGL::getIsResident(BOOL test_now) @@ -1500,7 +1639,50 @@ BOOL LLImageGL::getMask(const LLVector2 &tc) } //---------------------------------------------------------------------------- - +#if !LL_RELEASE_FOR_DOWNLOAD +//for debug use +//val is a "power of two" number +S32 LLImageGL::getTextureCounterIndex(U32 val) +{ + //index range is [0, MAX_TEXTURE_LOG_SIZE]. + if(val < 2) + { + return 0 ; + } + else if(val >= (1 << MAX_TEXTURE_LOG_SIZE)) + { + return MAX_TEXTURE_LOG_SIZE ; + } + else + { + S32 ret = 0 ; + while(val >>= 1) + { + ++ret; + } + return ret ; + } +} +void LLImageGL::incTextureCounter(U32 val) +{ + sTextureLoadedCounter[getTextureCounterIndex(val)]++ ; +} +void LLImageGL::decTextureCounter(U32 val) +{ + sTextureLoadedCounter[getTextureCounterIndex(val)]-- ; +} +void LLImageGL::setCurTexSizebar(S32 index) +{ + sCurTexSizeBar = index ; + sCurTexPickSize = (1 << index) ; +} +void LLImageGL::resetCurTexSizebar() +{ + sCurTexSizeBar = -1 ; + sCurTexPickSize = -1 ; +} +//---------------------------------------------------------------------------- +#endif // Manual Mip Generation /* diff --git a/indra/llrender/llimagegl.h b/indra/llrender/llimagegl.h index 987a1dc538..a094605607 100644 --- a/indra/llrender/llimagegl.h +++ b/indra/llrender/llimagegl.h @@ -42,7 +42,7 @@ #include "v2math.h" #include "llrender.h" - +class LLTextureAtlas ; #define BYTES_TO_MEGA_BYTES(x) ((x) >> 20) #define MEGA_BYTES_TO_BYTES(x) ((x) << 20) @@ -52,6 +52,10 @@ class LLImageGL : public LLRefCount { friend class LLTexUnit; public: + static std::list sDeadTextureList; + + static void deleteDeadTextures(); + // Size calculation static S32 dataFormatBits(S32 dataformat); static S32 dataFormatBytes(S32 dataformat, S32 width, S32 height); @@ -69,7 +73,6 @@ public: // Sometimes called externally for textures not using LLImageGL (should go away...) static S32 updateBoundTexMem(const S32 delta); - static bool checkSize(S32 width, S32 height); //for server side use only. @@ -115,6 +118,7 @@ public: void destroyGLTexture(); void setExplicitFormat(LLGLint internal_format, LLGLenum primary_format, LLGLenum type_format = 0, BOOL swap_bytes = FALSE); + void setComponents(S8 ncomponents) { mComponents = ncomponents; } S32 getDiscardLevel() const { return mCurrentDiscardLevel; } S32 getMaxDiscardLevel() const { return mMaxDiscardLevel; } @@ -128,6 +132,7 @@ public: S32 getMipBytes(S32 discard_level = -1) const; BOOL getBoundRecently() const; LLGLenum getPrimaryFormat() const { return mFormatPrimary; } + LLGLenum getFormatType() const { return mFormatType; } BOOL getHasGLTexture() const { return mTexName != 0; } LLGLuint getTexName() const { return mTexName; } @@ -164,10 +169,20 @@ public: void setFilteringOption(LLTexUnit::eTextureFilterOptions option); LLTexUnit::eTextureFilterOptions getFilteringOption(void) const { return mFilterOption; } + LLGLenum getTexTarget()const { return mTarget ;} + S8 getDiscardLevelInAtlas()const {return mDiscardLevelInAtlas;} + U32 getTexelsInAtlas()const { return mTexelsInAtlas ;} + U32 getTexelsInGLTexture()const {return mTexelsInGLTexture;} + + 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 void setNeedsAlphaAndPickMask(BOOL need_mask) {mNeedsAlphaAndPickMask = need_mask;} + + BOOL preAddToAtlas(S32 discard_level, const LLImageRaw* raw_image); + void postAddToAtlas() ; + public: // Various GL/Rendering options S32 mTextureMemory; @@ -189,6 +204,10 @@ private: U16 mHeight; S8 mCurrentDiscardLevel; + S8 mDiscardLevelInAtlas; + U32 mTexelsInAtlas ; + U32 mTexelsInGLTexture; + protected: LLGLenum mTarget; // Normally GL_TEXTURE2D, sometimes something else (ex. cube maps) LLTexUnit::eTextureType mBindTarget; // Normally TT_TEXTURE, sometimes something else (ex. cube maps) @@ -224,7 +243,26 @@ public: static U32 sBindCount; // Tracks number of texture binds for current frame static U32 sUniqueCount; // Tracks number of unique texture binds for current frame static BOOL sGlobalUseAnisotropic; - static LLImageGL* sDefaultGLTexture ; + static LLImageGL* sDefaultGLTexture ; + static BOOL sAutomatedTest; + +#if !LL_RELEASE_FOR_DOWNLOAD + //for debug use: show texture size distribution + //---------------------------------------- + static LLPointer sDefaultTexturep; //default texture to replace normal textures + static std::vector sTextureLoadedCounter ; + static std::vector sTextureBoundCounter ; + static std::vector sTextureCurBoundCounter ; + static S32 sCurTexSizeBar ; + static S32 sCurTexPickSize ; + + static S32 getTextureCounterIndex(U32 val) ; + static void incTextureCounter(U32 val) ; + static void decTextureCounter(U32 val) ; + static void setCurTexSizebar(S32 index) ; + static void resetCurTexSizebar(); + //---------------------------------------- +#endif #if DEBUG_MISS BOOL mMissed; // Missed on last bind? diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index d577daf3f4..b74d824c9e 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -45,10 +45,11 @@ LLRender gGL; // Handy copies of last good GL matrices F64 gGLModelView[16]; F64 gGLLastModelView[16]; +F64 gGLLastProjection[16]; F64 gGLProjection[16]; S32 gGLViewport[4]; -static const U32 LL_NUM_TEXTURE_LAYERS = 8; +static const U32 LL_NUM_TEXTURE_LAYERS = 16; static GLenum sGLTextureType[] = { @@ -311,6 +312,11 @@ bool LLTexUnit::bind(LLRenderTarget* renderTarget, bool bindDepth) if (bindDepth) { + if (renderTarget->hasStencil()) + { + llerrs << "Cannot bind a render buffer for sampling. Allocate render target without a stencil buffer if sampling of depth buffer is required." << llendl; + } + bindManual(renderTarget->getUsage(), renderTarget->getDepth()); } else @@ -328,7 +334,7 @@ bool LLTexUnit::bindManual(eTextureType type, U32 texture, bool hasMips) { return false; } - + if(mCurrTexture != texture) { gGL.flush(); diff --git a/indra/llrender/llrender.h b/indra/llrender/llrender.h index 74f87f6d40..cb2a4d4450 100644 --- a/indra/llrender/llrender.h +++ b/indra/llrender/llrender.h @@ -355,6 +355,7 @@ private: extern F64 gGLModelView[16]; extern F64 gGLLastModelView[16]; +extern F64 gGLLastProjection[16]; extern F64 gGLProjection[16]; extern S32 gGLViewport[4]; diff --git a/indra/llrender/llrendertarget.cpp b/indra/llrender/llrendertarget.cpp index dc052851ca..567e3a6c3e 100644 --- a/indra/llrender/llrendertarget.cpp +++ b/indra/llrender/llrendertarget.cpp @@ -204,7 +204,7 @@ void LLRenderTarget::allocateDepth() gGL.getTexUnit(0)->bindManual(mUsage, mDepth); U32 internal_type = LLTexUnit::getInternalType(mUsage); gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT); - LLImageGL::setManualImage(internal_type, 0, GL_DEPTH24_STENCIL8_EXT, mResX, mResY, GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT, NULL); + LLImageGL::setManualImage(internal_type, 0, GL_DEPTH_COMPONENT32_ARB, mResX, mResY, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL); } } @@ -382,7 +382,7 @@ void LLRenderTarget::flush(BOOL fetch_depth) allocateDepth(); } - gGL.getTexUnit(0)->bind(this, true); + gGL.getTexUnit(0)->bind(this); glCopyTexImage2D(LLTexUnit::getInternalType(mUsage), 0, GL_DEPTH24_STENCIL8_EXT, 0, 0, mResX, mResY, 0); } @@ -392,7 +392,11 @@ void LLRenderTarget::flush(BOOL fetch_depth) { #if !LL_DARWIN + stop_glerror(); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + + stop_glerror(); if (mSampleBuffer) { @@ -434,7 +438,6 @@ void LLRenderTarget::flush(BOOL fetch_depth) #endif glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); - glFlush(); } } @@ -442,6 +445,7 @@ void LLRenderTarget::copyContents(LLRenderTarget& source, S32 srcX0, S32 srcY0, S32 dstX0, S32 dstY0, S32 dstX1, S32 dstY1, U32 mask, U32 filter) { #if !LL_DARWIN + gGL.flush(); if (!source.mFBO || !mFBO) { llerrs << "Cannot copy framebuffer contents for non FBO render targets." << llendl; @@ -453,12 +457,55 @@ void LLRenderTarget::copyContents(LLRenderTarget& source, S32 srcX0, S32 srcY0, } else { - glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, source.mFBO); - glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, mFBO); + if (mask == GL_DEPTH_BUFFER_BIT && source.mStencil != mStencil) + { + stop_glerror(); + + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, source.mFBO); + gGL.getTexUnit(0)->bind(this, true); + stop_glerror(); + glCopyTexSubImage2D(LLTexUnit::getInternalType(mUsage), 0, srcX0, srcY0, dstX0, dstY0, dstX1, dstY1); + stop_glerror(); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + stop_glerror(); + } + else + { + glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, source.mFBO); + stop_glerror(); + glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, mFBO); + stop_glerror(); + check_framebuffer_status(); + stop_glerror(); + glBlitFramebufferEXT(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter); + stop_glerror(); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + stop_glerror(); + } + } +#endif +} +//static +void LLRenderTarget::copyContentsToFramebuffer(LLRenderTarget& source, S32 srcX0, S32 srcY0, S32 srcX1, S32 srcY1, + S32 dstX0, S32 dstY0, S32 dstX1, S32 dstY1, U32 mask, U32 filter) +{ +#if !LL_DARWIN + if (!source.mFBO) + { + llerrs << "Cannot copy framebuffer contents for non FBO render targets." << llendl; + } + { + glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, source.mFBO); + stop_glerror(); + glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, 0); + stop_glerror(); + check_framebuffer_status(); + stop_glerror(); glBlitFramebufferEXT(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter); - + stop_glerror(); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + stop_glerror(); } #endif } diff --git a/indra/llrender/llrendertarget.h b/indra/llrender/llrendertarget.h index 98b608f834..b7ebfc8f7f 100644 --- a/indra/llrender/llrendertarget.h +++ b/indra/llrender/llrendertarget.h @@ -121,6 +121,7 @@ public: U32 getTexture(U32 attachment = 0) const; U32 getDepth(void) const { return mDepth; } + BOOL hasStencil() const { return mStencil; } void bindTexture(U32 index, S32 channel); @@ -135,6 +136,9 @@ public: void copyContents(LLRenderTarget& source, S32 srcX0, S32 srcY0, S32 srcX1, S32 srcY1, S32 dstX0, S32 dstY0, S32 dstX1, S32 dstY1, U32 mask, U32 filter); + static void copyContentsToFramebuffer(LLRenderTarget& source, S32 srcX0, S32 srcY0, S32 srcX1, S32 srcY1, + S32 dstX0, S32 dstY0, S32 dstX1, S32 dstY1, U32 mask, U32 filter); + //Returns TRUE if target is ready to be rendered into. //That is, if the target has been allocated with at least //one renderable attachment (i.e. color buffer, depth buffer). -- cgit v1.2.3