summaryrefslogtreecommitdiff
path: root/indra/llrender
diff options
context:
space:
mode:
authorDavid Parks <davep@lindenlab.com>2009-09-22 11:11:45 +0000
committerDavid Parks <davep@lindenlab.com>2009-09-22 11:11:45 +0000
commit536e38ad51b89808f26d8e3cd107fe093862d22a (patch)
tree230159ae9e319f5c419f1a643177b2bbb17d52c5 /indra/llrender
parent760adead96e62cab8f9cdacc6469773a87dfbc1a (diff)
Merging render-pipeline-6-qa-2 into viewer-2
Self reviewed.
Diffstat (limited to 'indra/llrender')
-rw-r--r--indra/llrender/llgl.cpp27
-rw-r--r--indra/llrender/llgl.h32
-rw-r--r--indra/llrender/llimagegl.cpp214
-rw-r--r--indra/llrender/llimagegl.h44
-rw-r--r--indra/llrender/llrender.cpp10
-rw-r--r--indra/llrender/llrender.h1
-rw-r--r--indra/llrender/llrendertarget.cpp59
-rw-r--r--indra/llrender/llrendertarget.h4
8 files changed, 356 insertions, 35 deletions
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*> 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 <string>
#include <map>
+#include <list>
#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<LLGLUpdate*> sGLQ;
+
+ BOOL mInQ;
+ LLGLUpdate()
+ : mInQ(FALSE)
+ {
+ }
+ virtual ~LLGLUpdate()
+ {
+ if (mInQ)
+ {
+ std::list<LLGLUpdate*>::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<U32> LLImageGL::sDeadTextureList;
BOOL LLImageGL::sGlobalUseAnisotropic = FALSE;
F32 LLImageGL::sLastFrameTime = 0.f;
LLImageGL* LLImageGL::sDefaultGLTexture = NULL ;
std::set<LLImageGL*> LLImageGL::sImageList;
+#if !LL_RELEASE_FOR_DOWNLOAD
+//-----------------------
+//debug use
+#define MAX_TEXTURE_LOG_SIZE 22 //2048 * 2048
+std::vector<S32> LLImageGL::sTextureLoadedCounter(MAX_TEXTURE_LOG_SIZE + 1) ;
+std::vector<S32> LLImageGL::sTextureBoundCounter(MAX_TEXTURE_LOG_SIZE + 1) ;
+std::vector<S32> LLImageGL::sTextureCurBoundCounter(MAX_TEXTURE_LOG_SIZE + 1) ;
+S32 LLImageGL::sCurTexSizeBar = -1 ;
+S32 LLImageGL::sCurTexPickSize = -1 ;
+LLPointer<LLImageGL> 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<U32> 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<LLImageGL> sDefaultTexturep; //default texture to replace normal textures
+ static std::vector<S32> sTextureLoadedCounter ;
+ static std::vector<S32> sTextureBoundCounter ;
+ static std::vector<S32> 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).