summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--indra/llrender/llgl.cpp44
-rw-r--r--indra/llrender/llimagegl.cpp34
-rw-r--r--indra/llrender/llimagegl.h10
-rw-r--r--indra/llrender/llrender.cpp6
-rw-r--r--indra/newview/CMakeLists.txt4
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/avatarAlphaShadowF.glsl4
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/avatarAlphaShadowV.glsl3
-rw-r--r--indra/newview/lldrawable.h5
-rw-r--r--indra/newview/lldrawpooltree.cpp10
-rw-r--r--indra/newview/llface.h1
-rw-r--r--indra/newview/llglsandbox.cpp15
-rw-r--r--indra/newview/llspatialpartition.cpp130
-rw-r--r--indra/newview/llspatialpartition.h40
-rw-r--r--indra/newview/lltextureatlas.cpp416
-rw-r--r--indra/newview/lltextureatlas.h90
-rw-r--r--indra/newview/lltextureatlasmanager.cpp268
-rw-r--r--indra/newview/lltextureatlasmanager.h105
-rw-r--r--indra/newview/llviewertexture.cpp71
-rw-r--r--indra/newview/llvovolume.cpp11
-rw-r--r--indra/newview/pipeline.cpp28
-rw-r--r--indra/newview/pipeline.h3
21 files changed, 166 insertions, 1132 deletions
diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp
index 58183adfce..f24bf6ec78 100644
--- a/indra/llrender/llgl.cpp
+++ b/indra/llrender/llgl.cpp
@@ -88,24 +88,32 @@ void APIENTRY gl_debug_callback(GLenum source,
{
if (gGLDebugLoggingEnabled)
{
- if (severity == GL_DEBUG_SEVERITY_HIGH_ARB)
- {
- LL_WARNS() << "----- GL ERROR --------" << LL_ENDL;
- }
- else
- {
- LL_WARNS() << "----- GL WARNING -------" << LL_ENDL;
- }
- LL_WARNS() << "Type: " << std::hex << type << LL_ENDL;
- LL_WARNS() << "ID: " << std::hex << id << LL_ENDL;
- LL_WARNS() << "Severity: " << std::hex << severity << LL_ENDL;
- LL_WARNS() << "Message: " << message << LL_ENDL;
- LL_WARNS() << "-----------------------" << LL_ENDL;
- if (severity == GL_DEBUG_SEVERITY_HIGH_ARB)
- {
- LL_ERRS() << "Halting on GL Error" << LL_ENDL;
- }
-}
+
+ if (severity != GL_DEBUG_SEVERITY_HIGH_ARB &&
+ severity != GL_DEBUG_SEVERITY_MEDIUM_ARB &&
+ severity != GL_DEBUG_SEVERITY_LOW_ARB)
+ { //suppress out-of-spec messages sent by nvidia driver (mostly vertexbuffer hints)
+ return;
+ }
+
+ if (severity == GL_DEBUG_SEVERITY_HIGH_ARB)
+ {
+ LL_WARNS() << "----- GL ERROR --------" << LL_ENDL;
+ }
+ else
+ {
+ LL_WARNS() << "----- GL WARNING -------" << LL_ENDL;
+ }
+ LL_WARNS() << "Type: " << std::hex << type << LL_ENDL;
+ LL_WARNS() << "ID: " << std::hex << id << LL_ENDL;
+ LL_WARNS() << "Severity: " << std::hex << severity << LL_ENDL;
+ LL_WARNS() << "Message: " << message << LL_ENDL;
+ LL_WARNS() << "-----------------------" << LL_ENDL;
+ if (severity == GL_DEBUG_SEVERITY_HIGH_ARB)
+ {
+ LL_ERRS() << "Halting on GL Error" << LL_ENDL;
+ }
+ }
}
#endif
diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp
index 894eb8c773..d3af27272b 100644
--- a/indra/llrender/llimagegl.cpp
+++ b/indra/llrender/llimagegl.cpp
@@ -41,6 +41,10 @@
#include "llrender.h"
#include "llwindow.h"
+#if !LL_IMAGEGL_THREAD_CHECK
+#define checkActiveThread()
+#endif
+
//----------------------------------------------------------------------------
const F32 MIN_TEXTURE_LIFETIME = 10.f;
@@ -437,6 +441,10 @@ LLImageGL::~LLImageGL()
void LLImageGL::init(BOOL usemipmaps)
{
+#if LL_IMAGEGL_THREAD_CHECK
+ mActiveThread = LLThread::currentID();
+#endif
+
// keep these members in the same order as declared in llimagehl.h
// so that it is obvious by visual inspection if we forgot to
// init a field.
@@ -1317,6 +1325,8 @@ void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 widt
BOOL LLImageGL::createGLTexture()
{
LL_PROFILE_ZONE_SCOPED;
+ checkActiveThread();
+
if (gGLManager.mIsDisabled)
{
LL_WARNS() << "Trying to create a texture while GL is disabled!" << LL_ENDL;
@@ -1349,6 +1359,8 @@ BOOL LLImageGL::createGLTexture()
BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename/*=0*/, BOOL to_create, S32 category)
{
LL_PROFILE_ZONE_SCOPED;
+ checkActiveThread();
+
if (gGLManager.mIsDisabled)
{
LL_WARNS() << "Trying to create a texture while GL is disabled!" << LL_ENDL;
@@ -1462,6 +1474,8 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S
BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_hasmips, S32 usename)
{
LL_PROFILE_ZONE_SCOPED;
+ checkActiveThread();
+
llassert(data_in);
stop_glerror();
@@ -1576,6 +1590,7 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_
// mark this as bound at this point, so we don't throw it out immediately
mLastBindTime = sLastFrameTime;
+ checkActiveThread();
return TRUE;
}
@@ -1690,18 +1705,10 @@ BOOL LLImageGL::readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compre
return TRUE ;
}
-void LLImageGL::deleteDeadTextures()
-{
- bool reset = false;
-
- if (reset)
- {
- gGL.getTexUnit(0)->activate();
- }
-}
-
void LLImageGL::destroyGLTexture()
{
+ checkActiveThread();
+
if (mTexName != 0)
{
if(mTextureMemory != S32Bytes(0))
@@ -1720,6 +1727,7 @@ void LLImageGL::destroyGLTexture()
//force to invalidate the gl texture, most likely a sculpty texture
void LLImageGL::forceToInvalidateGLTexture()
{
+ checkActiveThread();
if (mTexName != 0)
{
destroyGLTexture();
@@ -2196,6 +2204,12 @@ void LLImageGL::resetCurTexSizebar()
sCurTexPickSize = -1 ;
}
//----------------------------------------------------------------------------
+#if LL_IMAGEGL_THREAD_CHECK
+void LLImageGL::checkActiveThread()
+{
+ llassert(mActiveThread == LLThread::currentID());
+}
+#endif
//----------------------------------------------------------------------------
diff --git a/indra/llrender/llimagegl.h b/indra/llrender/llimagegl.h
index ae773bb362..28996a554a 100644
--- a/indra/llrender/llimagegl.h
+++ b/indra/llrender/llimagegl.h
@@ -40,7 +40,8 @@
#include "threadpool.h"
#include "workqueue.h"
-class LLTextureAtlas ;
+#define LL_IMAGEGL_THREAD_CHECK 0 //set to 1 to enable thread debugging for ImageGL
+
class LLWindow;
#define BYTES_TO_MEGA_BYTES(x) ((x) >> 20)
@@ -54,7 +55,6 @@ public:
// These 2 functions replace glGenTextures() and glDeleteTextures()
static void generateTextures(S32 numTextures, U32 *textures);
static void deleteTextures(S32 numTextures, const U32 *textures);
- static void deleteDeadTextures();
// Size calculation
static S32 dataFormatBits(S32 dataformat);
@@ -189,6 +189,12 @@ public:
BOOL preAddToAtlas(S32 discard_level, const LLImageRaw* raw_image);
void postAddToAtlas() ;
+#if LL_IMAGEGL_THREAD_CHECK
+ // thread debugging
+ std::thread::id mActiveThread;
+ void checkActiveThread();
+#endif
+
public:
// Various GL/Rendering options
S32Bytes mTextureMemory;
diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp
index 235f8a8eb0..8b4f250894 100644
--- a/indra/llrender/llrender.cpp
+++ b/indra/llrender/llrender.cpp
@@ -181,7 +181,11 @@ void LLTexUnit::bindFast(LLTexture* texture)
mCurrTexture = gl_tex->getTexName();
if (!mCurrTexture)
{
- mCurrTexture = LLImageGL::sDefaultGLTexture->getTexName();
+ LL_PROFILE_ZONE_NAMED("MISSING TEXTURE");
+ //if deleted, will re-generate it immediately
+ texture->forceImmediateUpdate();
+ gl_tex->forceUpdateBindStats();
+ texture->bindDefaultImage(mIndex);
}
glBindTexture(sGLTextureType[gl_tex->getTarget()], mCurrTexture);
mHasMipMaps = gl_tex->mHasMipMaps;
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 4a7f17f15b..8157d1566a 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -590,8 +590,6 @@ set(viewer_SOURCE_FILES
llsyswellwindow.cpp
llteleporthistory.cpp
llteleporthistorystorage.cpp
- lltextureatlas.cpp
- lltextureatlasmanager.cpp
lltexturecache.cpp
lltexturectrl.cpp
lltexturefetch.cpp
@@ -1219,8 +1217,6 @@ set(viewer_HEADER_FILES
lltable.h
llteleporthistory.h
llteleporthistorystorage.h
- lltextureatlas.h
- lltextureatlasmanager.h
lltexturecache.h
lltexturectrl.h
lltexturefetch.h
diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaShadowF.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaShadowF.glsl
index ef49b6f4e8..1b16e4eb09 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaShadowF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaShadowF.glsl
@@ -40,11 +40,11 @@ VARYING vec4 post_pos;
VARYING float pos_w;
VARYING float target_pos_x;
VARYING vec2 vary_texcoord0;
-VARYING vec4 vertex_color;
+uniform vec4 color;
void main()
{
- float alpha = texture2D(diffuseMap, vary_texcoord0.xy).a * vertex_color.a;
+ float alpha = texture2D(diffuseMap, vary_texcoord0.xy).a * color.a;
if (alpha < 0.05) // treat as totally transparent
{
diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaShadowV.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaShadowV.glsl
index d1d7ece6fe..1c5b142ebd 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaShadowV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaShadowV.glsl
@@ -30,7 +30,6 @@ uniform float shadow_target_width;
mat4 getSkinnedTransform();
void passTextureIndex();
-ATTRIBUTE vec4 diffuse_color;
ATTRIBUTE vec3 position;
ATTRIBUTE vec3 normal;
ATTRIBUTE vec2 texcoord0;
@@ -41,7 +40,6 @@ VARYING vec4 post_pos;
VARYING float pos_w;
VARYING float target_pos_x;
VARYING vec2 vary_texcoord0;
-VARYING vec4 vertex_color;
void main()
{
@@ -68,7 +66,6 @@ void main()
vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy;
- vertex_color = diffuse_color;
#if !DEPTH_CLAMP
post_pos = pos;
diff --git a/indra/newview/lldrawable.h b/indra/newview/lldrawable.h
index 6002e3e0dd..9a9f6cf7c2 100644
--- a/indra/newview/lldrawable.h
+++ b/indra/newview/lldrawable.h
@@ -64,6 +64,8 @@ class LLDrawable
{
LL_ALIGN_NEW;
public:
+ typedef std::vector<LLFace*> face_list_t;
+
LLDrawable(const LLDrawable& rhs)
: LLViewerOctreeEntryData(rhs)
{
@@ -129,6 +131,7 @@ public:
inline LLFace* getFace(const S32 i) const;
inline S32 getNumFaces() const;
+ face_list_t& getFaces() { return mFaces; }
//void removeFace(const S32 i); // SJB: Avoid using this, it's slow
LLFace* addFace(LLFacePool *poolp, LLViewerTexture *texturep);
@@ -297,8 +300,6 @@ public:
static F32 sCurPixelAngle; //current pixels per radian
private:
- typedef std::vector<LLFace*> face_list_t;
-
U32 mState;
S32 mRenderType;
LLPointer<LLViewerObject> mVObjp;
diff --git a/indra/newview/lldrawpooltree.cpp b/indra/newview/lldrawpooltree.cpp
index ac957f1cbd..facfb235c9 100644
--- a/indra/newview/lldrawpooltree.cpp
+++ b/indra/newview/lldrawpooltree.cpp
@@ -92,8 +92,9 @@ void LLDrawPoolTree::render(S32 pass)
LLGLState test(GL_ALPHA_TEST, 0);
- gGL.getTexUnit(sDiffTex)->bind(mTexturep);
-
+ gGL.getTexUnit(sDiffTex)->bindFast(mTexturep);
+ gPipeline.touchTexture(mTexturep, 1024.f * 1024.f); // <=== keep Linden tree textures at full res
+
for (std::vector<LLFace*>::iterator iter = mDrawFace.begin();
iter != mDrawFace.end(); iter++)
{
@@ -116,9 +117,8 @@ void LLDrawPoolTree::render(S32 pass)
gPipeline.mMatrixOpCount++;
}
- buff->setBuffer(LLDrawPoolTree::VERTEX_DATA_MASK);
- buff->drawRange(LLRender::TRIANGLES, 0, buff->getNumVerts()-1, buff->getNumIndices(), 0);
- gPipeline.addTrianglesDrawn(buff->getNumIndices());
+ buff->setBufferFast(LLDrawPoolTree::VERTEX_DATA_MASK);
+ buff->drawRangeFast(LLRender::TRIANGLES, 0, buff->getNumVerts()-1, buff->getNumIndices(), 0);
}
}
}
diff --git a/indra/newview/llface.h b/indra/newview/llface.h
index c533edede4..79f50f2273 100644
--- a/indra/newview/llface.h
+++ b/indra/newview/llface.h
@@ -47,7 +47,6 @@ class LLTextureEntry;
class LLVertexProgram;
class LLViewerTexture;
class LLGeometryManager;
-class LLTextureAtlasSlot;
class LLDrawInfo;
class LLMeshSkinInfo;
diff --git a/indra/newview/llglsandbox.cpp b/indra/newview/llglsandbox.cpp
index a135ef0814..0b5064c77d 100644
--- a/indra/newview/llglsandbox.cpp
+++ b/indra/newview/llglsandbox.cpp
@@ -1115,6 +1115,14 @@ F32 gpu_benchmark()
// ensure matched pair of bind() and unbind() calls
ShaderBinder binder(gBenchmarkProgram);
+ U32 glarray = 0;
+
+ if (LLRender::sGLCoreProfile)
+ {
+ glGenVertexArrays(1, &glarray);
+ glBindVertexArray(glarray);
+ }
+
buff->setBuffer(LLVertexBuffer::MAP_VERTEX);
glFinish();
@@ -1147,6 +1155,13 @@ F32 gpu_benchmark()
}
}
+ if (LLRender::sGLCoreProfile)
+ {
+ glBindVertexArray(0);
+ glDeleteVertexArrays(1, &glarray);
+ }
+
+
std::sort(results.begin(), results.end());
F32 gbps = results[results.size()/2];
diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp
index 25d6106361..48e9f3726f 100644
--- a/indra/newview/llspatialpartition.cpp
+++ b/indra/newview/llspatialpartition.cpp
@@ -51,7 +51,6 @@
#include "llphysicsshapebuilderutil.h"
#include "llvoavatar.h"
#include "llvolumemgr.h"
-#include "lltextureatlas.h"
#include "llviewershadermgr.h"
#include "llcontrolavatar.h"
@@ -128,129 +127,6 @@ LLSpatialGroup::~LLSpatialGroup()
sNodeCount--;
clearDrawMap();
- clearAtlasList() ;
-}
-
-BOOL LLSpatialGroup::hasAtlas(LLTextureAtlas* atlasp)
-{
- S8 type = atlasp->getComponents() - 1 ;
- for(std::list<LLTextureAtlas*>::iterator iter = mAtlasList[type].begin(); iter != mAtlasList[type].end() ; ++iter)
- {
- if(atlasp == *iter)
- {
- return TRUE ;
- }
- }
- return FALSE ;
-}
-
-void LLSpatialGroup::addAtlas(LLTextureAtlas* atlasp, S8 recursive_level)
-{
- if(!hasAtlas(atlasp))
- {
- mAtlasList[atlasp->getComponents() - 1].push_back(atlasp) ;
- atlasp->addSpatialGroup(this) ;
- }
-
- --recursive_level;
- if(recursive_level)//levels propagating up.
- {
- LLSpatialGroup* parent = getParent() ;
- if(parent)
- {
- parent->addAtlas(atlasp, recursive_level) ;
- }
- }
-}
-
-void LLSpatialGroup::removeAtlas(LLTextureAtlas* atlasp, BOOL remove_group, S8 recursive_level)
-{
- mAtlasList[atlasp->getComponents() - 1].remove(atlasp) ;
- if(remove_group)
- {
- atlasp->removeSpatialGroup(this) ;
- }
-
- --recursive_level;
- if(recursive_level)//levels propagating up.
- {
- LLSpatialGroup* parent = getParent() ;
- if(parent)
- {
- parent->removeAtlas(atlasp, recursive_level) ;
- }
- }
-}
-
-void LLSpatialGroup::clearAtlasList()
-{
- std::list<LLTextureAtlas*>::iterator iter ;
- for(S8 i = 0 ; i < 4 ; i++)
- {
- if(mAtlasList[i].size() > 0)
- {
- for(iter = mAtlasList[i].begin(); iter != mAtlasList[i].end() ; ++iter)
- {
- ((LLTextureAtlas*)*iter)->removeSpatialGroup(this) ;
- }
- mAtlasList[i].clear() ;
- }
- }
-}
-
-LLTextureAtlas* LLSpatialGroup::getAtlas(S8 ncomponents, S8 to_be_reserved, S8 recursive_level)
-{
- S8 type = ncomponents - 1 ;
- if(mAtlasList[type].size() > 0)
- {
- for(std::list<LLTextureAtlas*>::iterator iter = mAtlasList[type].begin(); iter != mAtlasList[type].end() ; ++iter)
- {
- if(!((LLTextureAtlas*)*iter)->isFull(to_be_reserved))
- {
- return *iter ;
- }
- }
- }
-
- --recursive_level;
- if(recursive_level)
- {
- LLSpatialGroup* parent = getParent() ;
- if(parent)
- {
- return parent->getAtlas(ncomponents, to_be_reserved, recursive_level) ;
- }
- }
- return NULL ;
-}
-
-void LLSpatialGroup::setCurUpdatingSlot(LLTextureAtlasSlot* slotp)
-{
- mCurUpdatingSlotp = slotp;
-
- //if(!hasAtlas(mCurUpdatingSlotp->getAtlas()))
- //{
- // addAtlas(mCurUpdatingSlotp->getAtlas()) ;
- //}
-}
-
-LLTextureAtlasSlot* LLSpatialGroup::getCurUpdatingSlot(LLViewerTexture* imagep, S8 recursive_level)
-{
- if(gFrameCount && mCurUpdatingTime == gFrameCount && mCurUpdatingTexture == imagep)
- {
- return mCurUpdatingSlotp ;
- }
-
- //--recursive_level ;
- //if(recursive_level)
- //{
- // LLSpatialGroup* parent = getParent() ;
- // if(parent)
- // {
- // return parent->getCurUpdatingSlot(imagep, recursive_level) ;
- // }
- //}
- return NULL ;
}
void LLSpatialGroup::clearDrawMap()
@@ -665,11 +541,7 @@ LLSpatialGroup::LLSpatialGroup(OctreeNode* node, LLSpatialPartition* part) : LLO
mDistance(0.f),
mDepth(0.f),
mLastUpdateDistance(-1.f),
- mLastUpdateTime(gFrameTimeSeconds),
- mAtlasList(4),
- mCurUpdatingTime(0),
- mCurUpdatingSlotp(NULL),
- mCurUpdatingTexture (NULL)
+ mLastUpdateTime(gFrameTimeSeconds)
{
ll_assert_aligned(this,16);
diff --git a/indra/newview/llspatialpartition.h b/indra/newview/llspatialpartition.h
index 5fca516f19..58d821353a 100644
--- a/indra/newview/llspatialpartition.h
+++ b/indra/newview/llspatialpartition.h
@@ -50,8 +50,6 @@ class LLViewerOctreePartition;
class LLSpatialPartition;
class LLSpatialBridge;
class LLSpatialGroup;
-class LLTextureAtlas;
-class LLTextureAtlasSlot;
class LLViewerRegion;
void pushVerts(LLFace* face, U32 mask);
@@ -91,6 +89,10 @@ public:
LLPointer<LLViewerTexture> mTexture;
std::vector<LLPointer<LLViewerTexture> > mTextureList;
+ // virtual size of mTexture and mTextureList textures
+ // used to update the decode priority of textures in this DrawInfo
+ std::vector<F32> mTextureListVSize;
+
S32 mDebugColor;
const LLMatrix4* mTextureMatrix;
const LLMatrix4* mModelMatrix;
@@ -304,49 +306,15 @@ public:
virtual void handleDestruction(const TreeNode* node);
virtual void handleChildAddition(const OctreeNode* parent, OctreeNode* child);
-//-------------------
-//for atlas use
-//-------------------
- //atlas
- void setCurUpdatingTime(U32 t) {mCurUpdatingTime = t ;}
- U32 getCurUpdatingTime() const { return mCurUpdatingTime ;}
-
- void setCurUpdatingSlot(LLTextureAtlasSlot* slotp) ;
- LLTextureAtlasSlot* getCurUpdatingSlot(LLViewerTexture* imagep, S8 recursive_level = 3) ;
-
- void setCurUpdatingTexture(LLViewerTexture* tex){ mCurUpdatingTexture = tex ;}
- LLViewerTexture* getCurUpdatingTexture() const { return mCurUpdatingTexture ;}
-
- BOOL hasAtlas(LLTextureAtlas* atlasp) ;
- LLTextureAtlas* getAtlas(S8 ncomponents, S8 to_be_reserved, S8 recursive_level = 3) ;
- void addAtlas(LLTextureAtlas* atlasp, S8 recursive_level = 3) ;
- void removeAtlas(LLTextureAtlas* atlasp, BOOL remove_group = TRUE, S8 recursive_level = 3) ;
- void clearAtlasList() ;
-
public:
-
LL_ALIGN_16(LLVector4a mViewAngle);
LL_ALIGN_16(LLVector4a mLastUpdateViewAngle);
F32 mObjectBoxSize; //cached mObjectBounds[1].getLength3()
-
-private:
- U32 mCurUpdatingTime ;
- //do not make the below two to use LLPointer
- //because mCurUpdatingTime invalidates them automatically.
- LLTextureAtlasSlot* mCurUpdatingSlotp ;
- LLViewerTexture* mCurUpdatingTexture ;
-
- std::vector< std::list<LLTextureAtlas*> > mAtlasList ;
-//-------------------
-//end for atlas use
-//-------------------
protected:
virtual ~LLSpatialGroup();
- static S32 sLODSeed;
-
public:
bridge_list_t mBridgeList;
buffer_map_t mBufferMap; //used by volume buffers to attempt to reuse vertex buffers
diff --git a/indra/newview/lltextureatlas.cpp b/indra/newview/lltextureatlas.cpp
deleted file mode 100644
index 1c8e4f796e..0000000000
--- a/indra/newview/lltextureatlas.cpp
+++ /dev/null
@@ -1,416 +0,0 @@
-/**
- * @file lltextureatlas.cpp
- * @brief LLTextureAtlas class implementation.
- *
- * $LicenseInfo:firstyear=2002&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-#include "llviewerprecompiledheaders.h"
-#include "linden_common.h"
-#include "llerror.h"
-#include "llimage.h"
-#include "llmath.h"
-#include "llgl.h"
-#include "llrender.h"
-#include "lltextureatlas.h"
-
-//-------------------
-S16 LLTextureAtlas::sMaxSubTextureSize = 64 ;
-S16 LLTextureAtlas::sSlotSize = 32 ;
-
-#ifndef DEBUG_ATLAS
-#define DEBUG_ATLAS 0
-#endif
-
-#ifndef DEBUG_USAGE_BITS
-#define DEBUG_USAGE_BITS 0
-#endif
-//**************************************************************************************************************
-LLTextureAtlas::LLTextureAtlas(U8 ncomponents, S16 atlas_dim) :
- LLViewerTexture(atlas_dim * sSlotSize, atlas_dim * sSlotSize, ncomponents, TRUE),
- mAtlasDim(atlas_dim),
- mNumSlotsReserved(0),
- mMaxSlotsInAtlas(atlas_dim * atlas_dim)
-{
- generateEmptyUsageBits() ;
-
- //generate an empty texture
- generateGLTexture() ;
- LLPointer<LLImageRaw> image_raw = new LLImageRaw(mFullWidth, mFullHeight, mComponents);
- createGLTexture(0, image_raw, 0);
- image_raw = NULL;
-}
-
-LLTextureAtlas::~LLTextureAtlas()
-{
- if(mSpatialGroupList.size() > 0)
- {
- LL_ERRS() << "Not clean up the spatial groups!" << LL_ENDL ;
- }
- releaseUsageBits() ;
-}
-
-//virtual
-S8 LLTextureAtlas::getType() const
-{
- return 0; //LLViewerTexture::ATLAS_TEXTURE ;
-}
-
-void LLTextureAtlas::getTexCoordOffset(S16 col, S16 row, F32& xoffset, F32& yoffset)
-{
- xoffset = (F32)col / mAtlasDim ;
- yoffset = (F32)row / mAtlasDim ;
-}
-
-void LLTextureAtlas::getTexCoordScale(S32 w, S32 h, F32& xscale, F32& yscale)
-{
- xscale = (F32)w / (mAtlasDim * sSlotSize) ;
- yscale = (F32)h / (mAtlasDim * sSlotSize) ;
-}
-
-//insert a texture piece into the atlas
-LLGLuint LLTextureAtlas::insertSubTexture(LLImageGL* source_gl_tex, S32 discard_level, const LLImageRaw* raw_image, S16 slot_col, S16 slot_row)
-{
- if(!getTexName())
- {
- return 0 ;
- }
-
- S32 w = raw_image->getWidth() ;
- S32 h = raw_image->getHeight() ;
- if(w < 8 || w > sMaxSubTextureSize || h < 8 || h > sMaxSubTextureSize)
- {
- //size overflow
- return 0 ;
- }
-
- BOOL res = gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, getTexName());
- if (!res)
- {
- LL_ERRS() << "bindTexture failed" << LL_ENDL;
- }
-
- GLint xoffset = sSlotSize * slot_col ;
- GLint yoffset = sSlotSize * slot_row ;
-
- if(!source_gl_tex->preAddToAtlas(discard_level, raw_image))
- {
- return 0 ;
- }
-
- glTexSubImage2D(GL_TEXTURE_2D, 0, xoffset, yoffset, w, h,
- mGLTexturep->getPrimaryFormat(), mGLTexturep->getFormatType(), raw_image->getData());
-
- source_gl_tex->postAddToAtlas() ;
- return getTexName();
-}
-
-//release a sub-texture slot from the atlas
-void LLTextureAtlas::releaseSlot(S16 slot_col, S16 slot_row, S8 slot_width)
-{
- unmarkUsageBits(slot_width, slot_col, slot_row) ;
- mNumSlotsReserved -= slot_width * slot_width ;
-}
-
-BOOL LLTextureAtlas::isEmpty() const
-{
- return !mNumSlotsReserved ;
-}
-
-BOOL LLTextureAtlas::isFull(S8 to_be_reserved) const
-{
- return mNumSlotsReserved + to_be_reserved > mMaxSlotsInAtlas ;
-}
-F32 LLTextureAtlas::getFullness() const
-{
- return (F32)mNumSlotsReserved / mMaxSlotsInAtlas ;
-}
-
-void LLTextureAtlas::addSpatialGroup(LLSpatialGroup* groupp)
-{
- if(groupp && !hasSpatialGroup(groupp))
- {
- mSpatialGroupList.push_back(groupp);
- }
-}
-
-void LLTextureAtlas::removeSpatialGroup(LLSpatialGroup* groupp)
-{
- if(groupp)
- {
- mSpatialGroupList.remove(groupp);
- }
-}
-
-void LLTextureAtlas::clearSpatialGroup()
-{
- mSpatialGroupList.clear();
-}
-void LLTextureAtlas::removeLastSpatialGroup()
-{
- mSpatialGroupList.pop_back() ;
-}
-
-LLSpatialGroup* LLTextureAtlas::getLastSpatialGroup()
-{
- if(mSpatialGroupList.size() > 0)
- {
- return mSpatialGroupList.back() ;
- }
- return NULL ;
-}
-
-BOOL LLTextureAtlas::hasSpatialGroup(LLSpatialGroup* groupp)
-{
- for(std::list<LLSpatialGroup*>::iterator iter = mSpatialGroupList.begin(); iter != mSpatialGroupList.end() ; ++iter)
- {
- if(*iter == groupp)
- {
- return TRUE ;
- }
- }
- return FALSE ;
-}
-
-//--------------------------------------------------------------------------------------
-//private
-void LLTextureAtlas::generateEmptyUsageBits()
-{
- S32 col_len = (mAtlasDim + 7) >> 3 ;
- mUsageBits = new U8*[mAtlasDim] ;
- *mUsageBits = new U8[mAtlasDim * col_len] ;
-
- mUsageBits[0] = *mUsageBits ;
- for(S32 i = 1 ; i < mAtlasDim ; i++)
- {
- mUsageBits[i] = mUsageBits[i-1] + col_len ;
-
- for(S32 j = 0 ; j < col_len ; j++)
- {
- //init by 0 for all bits.
- mUsageBits[i][j] = 0 ;
- }
- }
-
- //do not forget mUsageBits[0]!
- for(S32 j = 0 ; j < col_len ; j++)
- {
- //init by 0 for all bits.
- mUsageBits[0][j] = 0 ;
- }
-
- mTestBits = NULL ;
-#if DEBUG_USAGE_BITS
- //------------
- //test
- mTestBits = new U8*[mAtlasDim] ;
- *mTestBits = new U8[mAtlasDim * mAtlasDim] ;
- mTestBits[0] = *mTestBits ;
- for(S32 i = 1 ; i < mAtlasDim ; i++)
- {
- mTestBits[i] = mTestBits[i-1] + mAtlasDim ;
-
- for(S32 j = 0 ; j < mAtlasDim ; j++)
- {
- //init by 0 for all bits.
- mTestBits[i][j] = 0 ;
- }
- }
-
- for(S32 j = 0 ; j < mAtlasDim ; j++)
- {
- //init by 0 for all bits.
- mTestBits[0][j] = 0 ;
- }
-#endif
-}
-
-void LLTextureAtlas::releaseUsageBits()
-{
- if(mUsageBits)
- {
- delete[] *mUsageBits ;
- delete[] mUsageBits ;
- }
- mUsageBits = NULL ;
-
- //test
- if( mTestBits)
- {
- delete[] *mTestBits;
- delete[] mTestBits;
- }
- mTestBits = NULL ;
-}
-
-void LLTextureAtlas::markUsageBits(S8 bits_len, U8 mask, S16 col, S16 row)
-{
- S16 x = col >> 3 ;
-
- for(S8 i = 0 ; i < bits_len ; i++)
- {
- mUsageBits[row + i][x] |= mask ;
- }
-
-#if DEBUG_USAGE_BITS
- //test
- for(S8 i = row ; i < row + bits_len ; i++)
- {
- for(S8 j = col ; j < col + bits_len ; j++)
- {
- mTestBits[i][j] = 1 ;
- }
- }
-#endif
-}
-
-void LLTextureAtlas::unmarkUsageBits(S8 bits_len, S16 col, S16 row)
-{
- S16 x = col >> 3 ;
- U8 mask = 1 ;
- for(S8 i = 1 ; i < bits_len ; i++)
- {
- mask |= (1 << i) ;
- }
- mask <<= (col & 7) ;
- mask = ~mask ;
-
- for(S8 i = 0 ; i < bits_len ; i++)
- {
- mUsageBits[row + i][x] &= mask ;
- }
-
-#if DEBUG_USAGE_BITS
- //test
- for(S8 i = row ; i < row + bits_len ; i++)
- {
- for(S8 j = col ; j < col + bits_len ; j++)
- {
- mTestBits[i][j] = 0 ;
- }
- }
-#endif
-}
-
-//return true if any of bits in the range marked.
-BOOL LLTextureAtlas::areUsageBitsMarked(S8 bits_len, U8 mask, S16 col, S16 row)
-{
- BOOL ret = FALSE ;
- S16 x = col >> 3 ;
-
- for(S8 i = 0 ; i < bits_len ; i++)
- {
- if(mUsageBits[row + i][x] & mask)
- {
- ret = TRUE ;
- break ;
- //return TRUE ;
- }
- }
-
-#if DEBUG_USAGE_BITS
- //test
- BOOL ret2 = FALSE ;
- for(S8 i = row ; i < row + bits_len ; i++)
- {
- for(S8 j = col ; j < col + bits_len ; j++)
- {
- if(mTestBits[i][j])
- {
- ret2 = TRUE ;
- }
- }
- }
-
- if(ret != ret2)
- {
- LL_ERRS() << "bits map corrupted." << LL_ENDL ;
- }
-#endif
- return ret ;//FALSE ;
-}
-
-//----------------------------------------------------------------------
-//
-//index order: Z order, i.e.:
-// |-----|-----|-----|-----|
-// | 10 | 11 | 14 | 15 |
-// |-----|-----|-----|-----|
-// | 8 | 9 | 12 | 13 |
-// |-----|-----|-----|-----|
-// | 2 | 3 | 6 | 7 |
-// |-----|-----|-----|-----|
-// | 0 | 1 | 4 | 5 |
-// |-----|-----|-----|-----|
-void LLTextureAtlas::getPositionFromIndex(S16 index, S16& col, S16& row)
-{
- col = 0 ;
- row = 0 ;
-
- S16 index_copy = index ;
- for(S16 i = 0 ; index_copy && i < 16 ; i += 2)
- {
- col |= ((index & (1 << i)) >> i) << (i >> 1) ;
- row |= ((index & (1 << (i + 1))) >> (i + 1)) << (i >> 1) ;
- index_copy >>= 2 ;
- }
-}
-void LLTextureAtlas::getIndexFromPosition(S16 col, S16 row, S16& index)
-{
- index = 0 ;
- S16 col_copy = col ;
- S16 row_copy = row ;
- for(S16 i = 0 ; (col_copy || row_copy) && i < 16 ; i++)
- {
- index |= ((col & 1 << i) << i) | ((row & 1 << i) << ( i + 1)) ;
- col_copy >>= 1 ;
- row_copy >>= 1 ;
- }
-}
-//----------------------------------------------------------------------
-//return TRUE if succeeds.
-BOOL LLTextureAtlas::getNextAvailableSlot(S8 bits_len, S16& col, S16& row)
-{
- S16 index_step = bits_len * bits_len ;
-
- U8 mask = 1 ;
- for(S8 i = 1 ; i < bits_len ; i++)
- {
- mask |= (1 << i) ;
- }
-
- U8 cur_mask ;
- for(S16 index = 0 ; index < mMaxSlotsInAtlas ; index += index_step)
- {
- getPositionFromIndex(index, col, row) ;
-
- cur_mask = mask << (col & 7) ;
- if(!areUsageBitsMarked(bits_len, cur_mask, col, row))
- {
- markUsageBits(bits_len, cur_mask, col, row) ;
- mNumSlotsReserved += bits_len * bits_len ;
-
- return TRUE ;
- }
- }
-
- return FALSE ;
-}
diff --git a/indra/newview/lltextureatlas.h b/indra/newview/lltextureatlas.h
deleted file mode 100644
index 6b36eb7fe4..0000000000
--- a/indra/newview/lltextureatlas.h
+++ /dev/null
@@ -1,90 +0,0 @@
-/**
- * @file lltextureatlas.h
- * @brief LLTextureAtlas base class.
- *
- * $LicenseInfo:firstyear=2002&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-
-#ifndef LL_TEXTUREATLAS_H
-#define LL_TEXTUREATLAS_H
-
-#include "llviewertexture.h"
-class LLSpatialGroup ;
-
-class LLTextureAtlas : public LLViewerTexture
-{
-protected:
- /*virtual*/ ~LLTextureAtlas() ;
-
-public:
- LLTextureAtlas(U8 ncomponents, S16 atlas_dim = 16) ;
-
- /*virtual*/ S8 getType() const;
-
- LLGLuint insertSubTexture(LLImageGL* source_gl_tex, S32 discard_level, const LLImageRaw* raw_image, S16 slot_col, S16 slot_row) ;
- void releaseSlot(S16 slot_col, S16 slot_row, S8 slot_width);
-
- BOOL getNextAvailableSlot(S8 bits_len, S16& col, S16& row) ;
- void getTexCoordOffset(S16 col, S16 row, F32& xoffset, F32& yOffset) ;
- void getTexCoordScale(S32 w, S32 h, F32& xscale, F32& yscale) ;
-
- BOOL isEmpty() const ;
- BOOL isFull(S8 to_be_reserved = 1) const ;
- F32 getFullness() const ;
-
- void addSpatialGroup(LLSpatialGroup* groupp) ;
- void removeSpatialGroup(LLSpatialGroup* groupp) ;
- LLSpatialGroup* getLastSpatialGroup() ;
- void removeLastSpatialGroup() ;
- BOOL hasSpatialGroup(LLSpatialGroup* groupp) ;
- void clearSpatialGroup() ;
- std::list<LLSpatialGroup*>* getSpatialGroupList() {return &mSpatialGroupList;}
-private:
- void generateEmptyUsageBits() ;
- void releaseUsageBits() ;
-
- void markUsageBits(S8 bits_len, U8 mask, S16 col, S16 row) ;
- void unmarkUsageBits(S8 bits_len, S16 col, S16 row) ;
-
- void getPositionFromIndex(S16 index, S16& col, S16& row) ;
- void getIndexFromPosition(S16 col, S16 row, S16& index) ;
- BOOL areUsageBitsMarked(S8 bits_len, U8 mask, S16 col, S16 row) ;
-
-private:
- S16 mAtlasDim ; //number of slots per edge, i.e, there are "mAtlasDim * mAtlasDim" total slots in the atlas.
- S16 mNumSlotsReserved ;
- S16 mMaxSlotsInAtlas ;
- U8 **mUsageBits ;
- std::list<LLSpatialGroup*> mSpatialGroupList ;
-
-public:
- //debug use only
- U8 **mTestBits ;
-
-public:
- static S16 sMaxSubTextureSize ;
- static S16 sSlotSize ;
-};
-
-#endif
-
diff --git a/indra/newview/lltextureatlasmanager.cpp b/indra/newview/lltextureatlasmanager.cpp
deleted file mode 100644
index ca9d6da4db..0000000000
--- a/indra/newview/lltextureatlasmanager.cpp
+++ /dev/null
@@ -1,268 +0,0 @@
-/**
- * @file lltextureatlasmanager.cpp
- * @brief LLTextureAtlasManager class implementation.
- *
- * $LicenseInfo:firstyear=2002&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-#include "llviewerprecompiledheaders.h"
-#include "linden_common.h"
-#include "llerror.h"
-#include "llmath.h"
-#include "lltextureatlas.h"
-#include "lltextureatlasmanager.h"
-#include "llspatialpartition.h"
-
-const S8 MAX_NUM_EMPTY_ATLAS = 2 ;
-const F32 MIN_ATLAS_FULLNESS = 0.6f ;
-
-//*********************************************************************************************
-//implementation of class LLTextureAtlasInfo
-//*********************************************************************************************
-LLTextureAtlasSlot::LLTextureAtlasSlot(LLTextureAtlas* atlasp, LLSpatialGroup* groupp, S16 col, S16 row, F32 xoffset, F32 yoffset, S8 slot_width) :
- mAtlasp(atlasp),
- mGroupp(groupp),
- mCol(col),
- mRow(row),
- mReservedSlotWidth(slot_width),
- mValid(FALSE),
- mUpdatedTime(0),
- mTexCoordOffset(xoffset, yoffset),
- mTexCoordScale(1.f, 1.f)
-{
- llassert_always(mAtlasp || mGroupp || mReservedSlotWidth) ;
-}
-
-LLTextureAtlasSlot::~LLTextureAtlasSlot()
-{
- if(mAtlasp)
- {
- mAtlasp->releaseSlot(mCol, mRow, mReservedSlotWidth) ;
- if(mAtlasp->isEmpty())
- {
- LLTextureAtlasManager::getInstance()->releaseAtlas(mAtlasp) ;
- }
- mAtlasp = NULL ;
- }
-}
-
-//void LLTextureAtlasSlot::setAtlas(LLTextureAtlas* atlasp)
-//{
-// mAtlasp = atlasp ;
-//}
-//void LLTextureAtlasSlot::setSlotPos(S16 col, S16 row)
-//{
-// mCol = col ;
-// mRow = row ;
-//}
-//void LLTextureAtlasSlot::setSlotWidth(S8 width)
-//{
-// //slot is a square with each edge length a power-of-two number
-// mReservedSlotWidth = width ;
-//}
-//void LLTextureAtlasSlot::setTexCoordOffset(F32 xoffset, F32 yoffset)
-//{
-// mTexCoordOffset.mV[0] = xoffset ;
-// mTexCoordOffset.mV[1] = yoffset ;
-//}
-
-void LLTextureAtlasSlot::setSpatialGroup(LLSpatialGroup* groupp)
-{
- mGroupp = groupp ;
-}
-void LLTextureAtlasSlot::setTexCoordScale(F32 xscale, F32 yscale)
-{
- mTexCoordScale.mV[0] = xscale ;
- mTexCoordScale.mV[1] = yscale ;
-}
-//*********************************************************************************************
-//END of implementation of class LLTextureAtlasInfo
-//*********************************************************************************************
-
-//*********************************************************************************************
-//implementation of class LLTextureAtlasManager
-//*********************************************************************************************
-LLTextureAtlasManager::LLTextureAtlasManager() :
- mAtlasMap(4),
- mEmptyAtlasMap(4)
-{
-}
-
-LLTextureAtlasManager::~LLTextureAtlasManager()
-{
- for(S32 i = 0 ; i < 4 ; i++)
- {
- for(ll_texture_atlas_list_t::iterator j = mAtlasMap[i].begin() ; j != mAtlasMap[i].end() ; ++j)
- {
- *j = NULL ;
- }
- for(ll_texture_atlas_list_t::iterator j = mEmptyAtlasMap[i].begin() ; j != mEmptyAtlasMap[i].end() ; ++j)
- {
- *j = NULL ;
- }
-
- mAtlasMap[i].clear() ;
- mEmptyAtlasMap[i].clear() ;
- }
- mAtlasMap.clear() ;
- mEmptyAtlasMap.clear() ;
-}
-
-//return TRUE if qualified
-BOOL LLTextureAtlasManager::canAddToAtlas(S32 w, S32 h, S8 ncomponents, LLGLenum target)
-{
- if(ncomponents < 1 || ncomponents > 4)
- {
- return FALSE ;
- }
- //only support GL_TEXTURE_2D
- if(GL_TEXTURE_2D != target)
- {
- return FALSE ;
- }
- //real image size overflows
- if(w < 8 || w > LLTextureAtlas::sMaxSubTextureSize || h < 8 || h > LLTextureAtlas::sMaxSubTextureSize)
- {
- return FALSE ;
- }
-
- //if non-power-of-two number
- if((w & (w - 1)) || (h & (h - 1)))
- {
- return FALSE ;
- }
-
- return TRUE ;
-}
-
-void LLTextureAtlasManager::releaseAtlas(LLTextureAtlas* atlasp)
-{
- LLSpatialGroup* groupp = atlasp->getLastSpatialGroup() ;
- while(groupp)
- {
- groupp->removeAtlas(atlasp, FALSE) ;
- atlasp->removeLastSpatialGroup() ;
-
- groupp = atlasp->getLastSpatialGroup() ;
- }
-
- S8 type = atlasp->getComponents() - 1 ;
- //insert to the empty list
- if(mEmptyAtlasMap[type].size() < MAX_NUM_EMPTY_ATLAS)
- {
- mEmptyAtlasMap[type].push_back(atlasp) ;
- }
-
- //delete the atlasp
- mAtlasMap[type].remove(atlasp) ;
-}
-
-//
-//this function reserves an appropriate slot from atlas pool for an image.
-//return non-NULL if succeeds.
-//Note:
-//1, this function does not check if the image this slot assigned for qualifies for atlas or not,
-// call LLTextureAtlasManager::canAddToAtlas(...) to do the check before calling this function.
-//2, this function also dose not check if the image is already in atlas. It always assigns a new slot anyway.
-//3, this function tries to group sub-textures from same spatial group into ONE atlas to improve render batching.
-//
-LLPointer<LLTextureAtlasSlot> LLTextureAtlasManager::reserveAtlasSlot(S32 sub_texture_size, S8 ncomponents,
- LLSpatialGroup* groupp, LLViewerTexture* imagep)
-{
- if(!groupp)
- {
- //do not insert to atlas if does not have a group.
- return NULL ;
- }
-
- //bits_len must <= 8 and is a power of two number, i.e.: must be one of these numbers: 1, 2, 4, 8.
- if(sub_texture_size > LLTextureAtlas::sMaxSubTextureSize)
- {
- sub_texture_size = LLTextureAtlas::sMaxSubTextureSize ;
- }
- S8 bits_len = sub_texture_size / LLTextureAtlas::sSlotSize ;
- if(bits_len < 1)
- {
- bits_len = 1 ;
- }
-
- S16 col = -1, row = -1;
- S8 total_bits = bits_len * bits_len ;
-
- //insert to the atlas reserved by the same spatial group
- LLPointer<LLTextureAtlas> atlasp = groupp->getAtlas(ncomponents, total_bits) ;
- if(atlasp.notNull())
- {
- if(!atlasp->getNextAvailableSlot(bits_len, col, row))
- {
- //failed
- atlasp = NULL ;
- }
- }
-
- //search an atlas to fit for 'size'
- if(!atlasp)
- {
- S8 atlas_index = ncomponents - 1 ;
- ll_texture_atlas_list_t::iterator iter = mAtlasMap[atlas_index].begin() ;
- for(; iter != mAtlasMap[atlas_index].end(); ++iter)
- {
- LLTextureAtlas* cur = (LLTextureAtlas*)*iter ;
- if(cur->getFullness() < MIN_ATLAS_FULLNESS)//this atlas is empty enough for this group to insert more sub-textures later if necessary.
- {
- if(cur->getNextAvailableSlot(bits_len, col, row))
- {
- atlasp = cur ;
- groupp->addAtlas(atlasp) ;
- break ;
- }
- }
- }
- }
-
- //create a new atlas if necessary
- if(!atlasp)
- {
- if(mEmptyAtlasMap[ncomponents - 1].size() > 0)
- {
- //there is an empty one
- atlasp = mEmptyAtlasMap[ncomponents - 1].back() ;
- mEmptyAtlasMap[ncomponents - 1].pop_back() ;
- }
- else
- {
- atlasp = new LLTextureAtlas(ncomponents, 16) ;
- }
- mAtlasMap[ncomponents - 1].push_back(atlasp) ;
- atlasp->getNextAvailableSlot(bits_len, col, row) ;
- groupp->addAtlas(atlasp) ;
- }
-
- F32 xoffset, yoffset ;
- atlasp->getTexCoordOffset(col, row, xoffset, yoffset) ;
- LLPointer<LLTextureAtlasSlot> slot_infop = new LLTextureAtlasSlot(atlasp, groupp, col, row, xoffset, yoffset, bits_len) ;
-
- return slot_infop ;
-}
-
-//*********************************************************************************************
-//END of implementation of class LLTextureAtlasManager
-//*********************************************************************************************
diff --git a/indra/newview/lltextureatlasmanager.h b/indra/newview/lltextureatlasmanager.h
deleted file mode 100644
index 1b8df708c6..0000000000
--- a/indra/newview/lltextureatlasmanager.h
+++ /dev/null
@@ -1,105 +0,0 @@
-/**
- * @file lltextureatlasmanager.h
- * @brief LLTextureAtlasManager base class.
- *
- * $LicenseInfo:firstyear=2002&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-
-#ifndef LL_TEXTUREATLASMANAGER_H
-#define LL_TEXTUREATLASMANAGER_H
-
-#include "llmemory.h"
-
-class LLSpatialGroup ;
-class LLViewerTexture ;
-
-//just use it as a structure.
-class LLTextureAtlasSlot : public LLRefCount
-{
-public:
- LLTextureAtlasSlot(LLTextureAtlas* atlasp, LLSpatialGroup* groupp, S16 col, S16 row, F32 xoffset, F32 yoffset, S8 slot_width) ;
-
-protected:
- virtual ~LLTextureAtlasSlot();
-
-public:
-
- //
- //do not allow to change those values
- //
- //void setAtlas(LLTextureAtlas* atlasp) ;
- //void setSlotPos(S16 col, S16 row) ;
- //void setSlotWidth(S8 width) ;
- //void setTexCoordOffset(F32 xoffser, F32 yoffset) ;
- //
-
- void setSpatialGroup(LLSpatialGroup* groupp) ;
- void setTexCoordScale(F32 xscale, F32 yscale) ;
- void setValid() {mValid = TRUE ;}
-
- LLTextureAtlas* getAtlas()const {return mAtlasp;}
- LLSpatialGroup* getSpatialGroup() const {return mGroupp ;}
- S16 getSlotCol()const {return mCol;}
- S16 getSlotRow()const {return mRow;}
- S8 getSlotWidth()const{return mReservedSlotWidth;}
- BOOL isValid()const { return mValid;}
- const LLVector2* getTexCoordOffset()const {return &mTexCoordOffset;}
- const LLVector2* getTexCoordScale() const {return &mTexCoordScale;}
-
- void setUpdatedTime(U32 t) {mUpdatedTime = t;}
- U32 getUpdatedTime()const {return mUpdatedTime;}
-
-private:
- LLTextureAtlas* mAtlasp;
- S16 mCol ;//col of the slot
- S16 mRow ;//row of the slot
- S8 mReservedSlotWidth ; //slot is a square with each edge length a power-of-two number
- LLSpatialGroup* mGroupp ;
- BOOL mValid ;
-
- LLVector2 mTexCoordOffset ;
- LLVector2 mTexCoordScale ;
-
- U32 mUpdatedTime ;
-} ;
-
-class LLTextureAtlasManager : public LLSingleton<LLTextureAtlasManager>
-{
- LLSINGLETON(LLTextureAtlasManager);
- ~LLTextureAtlasManager();
- typedef std::list<LLPointer<LLTextureAtlas> > ll_texture_atlas_list_t ;
-
-public:
-
- LLPointer<LLTextureAtlasSlot> reserveAtlasSlot(S32 sub_texture_size, S8 ncomponents,
- LLSpatialGroup* groupp, LLViewerTexture* imagep) ;
- void releaseAtlas(LLTextureAtlas* atlasp);
-
- BOOL canAddToAtlas(S32 w, S32 h, S8 ncomponents, LLGLenum target) ;
-
-private:
- std::vector<ll_texture_atlas_list_t> mAtlasMap ;
- std::vector<ll_texture_atlas_list_t> mEmptyAtlasMap ; //delay some empty atlases deletion to avoid possible creation of new atlas immediately.
-};
-
-#endif
diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp
index f932acd48c..37ed2e9f20 100644
--- a/indra/newview/llviewertexture.cpp
+++ b/indra/newview/llviewertexture.cpp
@@ -1476,6 +1476,10 @@ void LLViewerFetchedTexture::addToCreateTexture()
BOOL LLViewerFetchedTexture::preCreateTexture(S32 usename/*= 0*/)
{
LL_PROFILE_ZONE_SCOPED;
+#if LL_IMAGEGL_THREAD_CHECK
+ mGLTexturep->checkActiveThread();
+#endif
+
if (!mNeedsCreateTexture)
{
destroyRawImage();
@@ -1603,6 +1607,9 @@ void LLViewerFetchedTexture::postCreateTexture()
{
return;
}
+#if LL_IMAGEGL_THREAD_CHECK
+ mGLTexturep->checkActiveThread();
+#endif
notifyAboutCreatingTexture();
@@ -1619,36 +1626,45 @@ void LLViewerFetchedTexture::postCreateTexture()
void LLViewerFetchedTexture::scheduleCreateTexture()
{
- ref();
- mNeedsCreateTexture = TRUE;
- if (preCreateTexture())
+ if (!mNeedsCreateTexture)
{
+ ref();
mNeedsCreateTexture = TRUE;
-#if LL_WINDOWS //flip to 0 to revert to single-threaded OpenGL texture uploads
- auto mainq = mMainQueue.lock();
- if (mainq)
+ if (preCreateTexture())
{
- mainq->postTo(
- mImageQueue,
- // work to be done on LLImageGL worker thread
- [this]()
- {
- //actually create the texture on a background thread
- createTexture();
- },
- // callback to be run on main thread
- [this]()
- {
- //finalize on main thread
- postCreateTexture();
- unref();
- });
- }
- else
+ mNeedsCreateTexture = TRUE;
+#if LL_WINDOWS //flip to 0 to revert to single-threaded OpenGL texture uploads
+ auto mainq = mMainQueue.lock();
+ if (mainq)
+ {
+ mainq->postTo(
+ mImageQueue,
+ // work to be done on LLImageGL worker thread
+ [this]()
+ {
+#if LL_IMAGEGL_THREAD_CHECK
+ mGLTexturep->mActiveThread = LLThread::currentID();
#endif
- {
- gTextureList.mCreateTextureList.insert(this);
- unref();
+ //actually create the texture on a background thread
+ createTexture();
+ },
+ // callback to be run on main thread
+ [this]()
+ {
+#if LL_IMAGEGL_THREAD_CHECK
+ mGLTexturep->mActiveThread = LLThread::currentID();
+#endif
+ //finalize on main thread
+ postCreateTexture();
+ unref();
+ });
+ }
+ else
+#endif
+ {
+ gTextureList.mCreateTextureList.insert(this);
+ unref();
+ }
}
}
}
@@ -2967,7 +2983,8 @@ void LLViewerFetchedTexture::destroyRawImage()
void LLViewerFetchedTexture::switchToCachedImage()
{
LL_PROFILE_ZONE_SCOPED;
- if(mCachedRawImage.notNull())
+ if(mCachedRawImage.notNull() &&
+ !mNeedsCreateTexture) // <--- texture creation is pending, don't step on it
{
mRawImage = mCachedRawImage;
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index 2f554bc9b8..4e7eb4df5d 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -5189,6 +5189,7 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep,
}
}
+ F32 vsize = facep->getVirtualSize(); //TODO -- adjust by texture scale?
if (index < FACE_DO_NOT_BATCH_TEXTURES && idx >= 0)
{
@@ -5202,10 +5203,12 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep,
{
batchable = true;
draw_vec[idx]->mTextureList[index] = tex;
+ draw_vec[idx]->mTextureListVSize[index] = vsize;
}
else if (draw_vec[idx]->mTextureList[index] == tex)
{ //this face's texture index can be used with this batch
batchable = true;
+ draw_vec[idx]->mTextureListVSize[index] = llmax(vsize, draw_vec[idx]->mTextureListVSize[index]);
}
}
else
@@ -5236,12 +5239,14 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep,
{
draw_vec[idx]->mCount += facep->getIndicesCount();
draw_vec[idx]->mEnd += facep->getGeomCount();
- draw_vec[idx]->mVSize = llmax(draw_vec[idx]->mVSize, facep->getVirtualSize());
+ draw_vec[idx]->mVSize = llmax(draw_vec[idx]->mVSize, vsize);
if (index < FACE_DO_NOT_BATCH_TEXTURES && index >= draw_vec[idx]->mTextureList.size())
{
draw_vec[idx]->mTextureList.resize(index+1);
draw_vec[idx]->mTextureList[index] = tex;
+ draw_vec[idx]->mTextureListVSize.resize(index + 1);
+ draw_vec[idx]->mTextureListVSize[index] = vsize;
}
draw_vec[idx]->validate();
update_min_max(draw_vec[idx]->mExtents[0], draw_vec[idx]->mExtents[1], facep->mExtents[0]);
@@ -5256,7 +5261,7 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep,
LLPointer<LLDrawInfo> draw_info = new LLDrawInfo(start,end,count,offset, tex,
facep->getVertexBuffer(), selected, fullbright, bump);
draw_info->mGroup = group;
- draw_info->mVSize = facep->getVirtualSize();
+ draw_info->mVSize = vsize;
draw_vec.push_back(draw_info);
draw_info->mTextureMatrix = tex_mat;
draw_info->mModelMatrix = model_mat;
@@ -5331,6 +5336,8 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep,
{ //initialize texture list for texture batching
draw_info->mTextureList.resize(index+1);
draw_info->mTextureList[index] = tex;
+ draw_info->mTextureListVSize.resize(index + 1);
+ draw_info->mTextureListVSize[index] = vsize;
}
draw_info->validate();
}
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index c122b4f43e..df676b30fc 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -3711,25 +3711,31 @@ void renderSoundHighlights(LLDrawable* drawablep)
}
}
-void LLPipeline::touchTextures(LLDrawInfo* info)
+void LLPipeline::touchTexture(LLViewerTexture* tex, F32 vsize)
{
- LL_PROFILE_ZONE_SCOPED;
- for (auto& tex : info->mTextureList)
+ if (tex)
{
- if (tex.notNull())
+ LLImageGL* gl_tex = tex->getGLTexture();
+ if (gl_tex && gl_tex->updateBindStats(gl_tex->mTextureMemory))
{
- LLImageGL* gl_tex = tex->getGLTexture();
- if (gl_tex && gl_tex->updateBindStats(gl_tex->mTextureMemory))
- {
- tex->setActive();
- }
+ tex->setActive();
+ tex->addTextureStats(vsize);
}
}
- if (info->mTexture.notNull())
+
+}
+void LLPipeline::touchTextures(LLDrawInfo* info)
+{
+ LL_PROFILE_ZONE_SCOPED;
+ for (int i = 0; i < info->mTextureList.size(); ++i)
{
- info->mTexture->addTextureStats(info->mVSize);
+ touchTexture(info->mTextureList[i], info->mTextureListVSize[i]);
}
+
+ touchTexture(info->mTexture, info->mVSize);
+ touchTexture(info->mSpecularMap, info->mVSize);
+ touchTexture(info->mNormalMap, info->mVSize);
}
void LLPipeline::postSort(LLCamera& camera)
diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h
index 3ac3e3ce01..794d806d0c 100644
--- a/indra/newview/pipeline.h
+++ b/indra/newview/pipeline.h
@@ -260,8 +260,11 @@ public:
void stateSort(LLSpatialBridge* bridge, LLCamera& camera, BOOL fov_changed = FALSE);
void stateSort(LLDrawable* drawablep, LLCamera& camera);
void postSort(LLCamera& camera);
+
//update stats for textures in given DrawInfo
void touchTextures(LLDrawInfo* info);
+ void touchTexture(LLViewerTexture* tex, F32 vsize);
+
void forAllVisibleDrawables(void (*func)(LLDrawable*));
void renderObjects(U32 type, U32 mask, bool texture = true, bool batch_texture = false, bool rigged = false);