1836 dont store texture in system memory unless absolutely necessary (#1843)

* #1836 Texture memory usage overhaul.  Much decrufting
- don't keep a copy of textures in system memory
- use GPU to downrez textures instead of reloading from cache
- use GPU to generate brightness/darkness bumpmaps
master
Dave Parks 2024-06-27 13:12:43 -05:00 committed by GitHub
parent e95df8a284
commit ab87978cbc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
36 changed files with 485 additions and 1707 deletions

View File

@ -351,20 +351,6 @@ void LLGLTexture::forceUpdateBindStats(void) const
return mGLTexturep->forceUpdateBindStats() ;
}
U32 LLGLTexture::getTexelsInAtlas() const
{
llassert(mGLTexturep.notNull()) ;
return mGLTexturep->getTexelsInAtlas() ;
}
U32 LLGLTexture::getTexelsInGLTexture() const
{
llassert(mGLTexturep.notNull()) ;
return mGLTexturep->getTexelsInGLTexture() ;
}
bool LLGLTexture::isGLTextureCreated() const
{
llassert(mGLTexturep.notNull()) ;
@ -372,13 +358,6 @@ bool LLGLTexture::isGLTextureCreated() const
return mGLTexturep->isGLTextureCreated() ;
}
S32 LLGLTexture::getDiscardLevelInAtlas() const
{
llassert(mGLTexturep.notNull()) ;
return mGLTexturep->getDiscardLevelInAtlas() ;
}
void LLGLTexture::destroyGLTexture()
{
if(mGLTexturep.notNull() && mGLTexturep->getHasGLTexture())

View File

@ -51,10 +51,10 @@ public:
BOOST_NONE = 0,
BOOST_AVATAR ,
BOOST_AVATAR_BAKED ,
BOOST_SCULPTED ,
BOOST_TERRAIN , // Needed for minimap generation for now. Lower than BOOST_HIGH so the texture stats don't get forced, i.e. texture stats are manually managed by minimap/terrain instead.
BOOST_HIGH = 10,
BOOST_SCULPTED ,
BOOST_BUMP ,
BOOST_UNUSED_1 , // Placeholder to avoid disrupting habits around texture debug
BOOST_SELECTED ,
@ -75,7 +75,6 @@ public:
AVATAR_SCRATCH_TEX,
DYNAMIC_TEX,
MEDIA,
ATLAS,
OTHER,
MAX_GL_IMAGE_CATEGORY
};
@ -156,10 +155,7 @@ public:
bool isJustBound()const ;
void forceUpdateBindStats(void) const;
U32 getTexelsInAtlas() const ;
U32 getTexelsInGLTexture() const ;
bool isGLTextureCreated() const ;
S32 getDiscardLevelInAtlas() const ;
LLGLTextureState getTextureState() const { return mTextureState; }
//---------------------------------------------------------------------------------------------

View File

@ -41,6 +41,7 @@
#include "llrender.h"
#include "llwindow.h"
#include "llframetimer.h"
#include <unordered_set>
extern LL_COMMON_API bool on_main_thread();
@ -130,10 +131,9 @@ S32 LLImageGL::sCount = 0;
bool LLImageGL::sGlobalUseAnisotropic = false;
F32 LLImageGL::sLastFrameTime = 0.f;
bool LLImageGL::sAllowReadBackRaw = false ;
LLImageGL* LLImageGL::sDefaultGLTexture = NULL ;
bool LLImageGL::sCompressTextures = false;
std::set<LLImageGL*> LLImageGL::sImageList;
std::unordered_set<LLImageGL*> LLImageGL::sImageList;
bool LLImageGLThread::sEnabledTextures = false;
@ -150,6 +150,9 @@ S32 LLImageGL::sMaxCategories = 1 ;
//optimization for when we don't need to calculate mIsMask
bool LLImageGL::sSkipAnalyzeAlpha;
U32 LLImageGL::sScratchPBO = 0;
U32 LLImageGL::sScratchPBOSize = 0;
//------------------------
//****************************************************************************************************
@ -159,20 +162,6 @@ bool LLImageGL::sSkipAnalyzeAlpha;
//**************************************************************************************
//below are functions for debug use
//do not delete them even though they are not currently being used.
void check_all_images()
{
for (std::set<LLImageGL*>::iterator iter = LLImageGL::sImageList.begin();
iter != LLImageGL::sImageList.end(); iter++)
{
LLImageGL* glimage = *iter;
if (glimage->getTexName() && glimage->isGLTextureCreated())
{
gGL.getTexUnit(0)->bind(glimage) ;
glimage->checkTexSize() ;
gGL.getTexUnit(0)->unbind(glimage->getTarget()) ;
}
}
}
void LLImageGL::checkTexSize(bool forced) const
{
@ -252,6 +241,11 @@ void LLImageGL::initClass(LLWindow* window, S32 num_catagories, bool skip_analyz
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
sSkipAnalyzeAlpha = skip_analyze_alpha;
if (sScratchPBO == 0)
{
glGenBuffers(1, &sScratchPBO);
}
if (thread_texture_loads || thread_media_updates)
{
LLImageGLThread::createInstance(window);
@ -265,6 +259,12 @@ void LLImageGL::cleanupClass()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
LLImageGLThread::deleteSingleton();
if (sScratchPBO != 0)
{
glDeleteBuffers(1, &sScratchPBO);
sScratchPBO = 0;
sScratchPBOSize = 0;
}
}
@ -360,66 +360,19 @@ void LLImageGL::updateStats(F32 current_time)
//----------------------------------------------------------------------------
//static
void LLImageGL::destroyGL(bool save_state)
void LLImageGL::destroyGL()
{
for (S32 stage = 0; stage < gGLManager.mNumTextureImageUnits; stage++)
{
gGL.getTexUnit(stage)->unbind(LLTexUnit::TT_TEXTURE);
}
sAllowReadBackRaw = true ;
for (std::set<LLImageGL*>::iterator iter = sImageList.begin();
iter != sImageList.end(); iter++)
{
LLImageGL* glimage = *iter;
if (glimage->mTexName)
{
if (save_state && glimage->isGLTextureCreated() && glimage->mComponents)
{
glimage->mSaveData = new LLImageRaw;
if(!glimage->readBackRaw(glimage->mCurrentDiscardLevel, glimage->mSaveData, false)) //necessary, keep it.
{
glimage->mSaveData = NULL ;
}
}
glimage->destroyGLTexture();
stop_glerror();
}
}
sAllowReadBackRaw = false ;
}
//static
void LLImageGL::restoreGL()
{
for (std::set<LLImageGL*>::iterator iter = sImageList.begin();
iter != sImageList.end(); iter++)
{
LLImageGL* glimage = *iter;
if(glimage->getTexName())
{
LL_ERRS() << "tex name is not 0." << LL_ENDL ;
}
if (glimage->mSaveData.notNull())
{
if (glimage->getComponents() && glimage->mSaveData->getComponents())
{
glimage->createGLTexture(glimage->mCurrentDiscardLevel, glimage->mSaveData, 0, true, glimage->getCategory());
stop_glerror();
}
glimage->mSaveData = NULL; // deletes data
}
}
}
//static
void LLImageGL::dirtyTexOptions()
{
for (std::set<LLImageGL*>::iterator iter = sImageList.begin();
iter != sImageList.end(); iter++)
for (auto& glimage : sImageList)
{
LLImageGL* glimage = *iter;
glimage->mTexOptionsDirty = true;
stop_glerror();
}
@ -542,10 +495,6 @@ void LLImageGL::init(bool usemipmaps)
mHeight = 0;
mCurrentDiscardLevel = -1;
mDiscardLevelInAtlas = -1 ;
mTexelsInAtlas = 0 ;
mTexelsInGLTexture = 0 ;
mAllowCompression = true;
mTarget = GL_TEXTURE_2D;
@ -622,9 +571,6 @@ bool LLImageGL::setSize(S32 width, S32 height, S32 ncomponents, S32 discard_leve
return false;
}
// pickmask validity depends on old image size, delete it
freePickMask();
mWidth = width;
mHeight = height;
mComponents = ncomponents;
@ -1025,98 +971,6 @@ bool LLImageGL::setImage(const U8* data_in, bool data_hasmips /* = false */, S32
return true;
}
bool LLImageGL::preAddToAtlas(S32 discard_level, const LLImageRaw* raw_image)
{
//not compatible with core GL profile
llassert(!LLRender::sGLCoreProfile);
if (gGLManager.mIsDisabled)
{
LL_WARNS() << "Trying to create a texture while GL is disabled!" << LL_ENDL;
return false;
}
llassert(gGLManager.mInited);
stop_glerror();
if (discard_level < 0)
{
llassert(mCurrentDiscardLevel >= 0);
discard_level = mCurrentDiscardLevel;
}
// 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
if (!setSize(w, h, raw_image->getComponents(), discard_level))
{
LL_WARNS() << "Trying to create a texture with incorrect dimensions!" << LL_ENDL;
return false;
}
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:
LL_ERRS() << "Bad number of components for texture: " << (U32) getComponents() << LL_ENDL;
}
}
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();
}
U32 type_width_from_pixtype(U32 pixtype)
{
U32 type_width = 0;
@ -1752,7 +1606,6 @@ bool LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, bool data_
mTextureMemory = (S64Bytes)getMipBytes(mCurrentDiscardLevel);
mTexelsInGLTexture = getWidth() * getHeight();
// mark this as bound at this point, so we don't throw it out immediately
mLastBindTime = sLastFrameTime;
@ -1830,8 +1683,7 @@ void LLImageGL::syncTexName(LLGLuint texname)
bool LLImageGL::readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compressed_ok) const
{
llassert_always(sAllowReadBackRaw) ;
//LL_ERRS() << "should not call this function!" << LL_ENDL ;
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
if (discard_level < 0)
{
@ -2297,6 +2149,8 @@ void LLImageGL::analyzeAlpha(const void* data_in, U32 w, U32 h)
//----------------------------------------------------------------------------
U32 LLImageGL::createPickMask(S32 pWidth, S32 pHeight)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
freePickMask();
U32 pick_width = pWidth/2 + 1;
U32 pick_height = pHeight/2 + 1;
@ -2314,7 +2168,6 @@ U32 LLImageGL::createPickMask(S32 pWidth, S32 pHeight)
//----------------------------------------------------------------------------
void LLImageGL::freePickMask()
{
// pickmask validity depends on old image size, delete it
if (mPickMask != NULL)
{
delete [] mPickMask;
@ -2352,16 +2205,16 @@ void LLImageGL::updatePickMask(S32 width, S32 height, const U8* data_in)
return ;
}
freePickMask();
if (mFormatType != GL_UNSIGNED_BYTE ||
((mFormatPrimary != GL_RGBA)
&& (mFormatPrimary != GL_SRGB_ALPHA)))
{
//cannot generate a pick mask for this texture
freePickMask();
return;
}
#ifdef SHOW_ASSERT
const U32 pickSize = createPickMask(width, height);
#else // SHOW_ASSERT
@ -2460,6 +2313,73 @@ void LLImageGL::resetCurTexSizebar()
sCurTexSizeBar = -1 ;
sCurTexPickSize = -1 ;
}
bool LLImageGL::scaleDown(S32 desired_discard)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
if (mTarget != GL_TEXTURE_2D)
{
return false;
}
desired_discard = llmin(desired_discard, mMaxDiscardLevel);
if (desired_discard <= mCurrentDiscardLevel)
{
return false;
}
S32 mip = desired_discard - mCurrentDiscardLevel;
S32 desired_width = getWidth(desired_discard);
S32 desired_height = getHeight(desired_discard);
U64 size = getBytes(desired_discard);
llassert(size <= 2048*2048*4); // we shouldn't be using this method to downscale huge textures, but it'll work
gGL.getTexUnit(0)->bind(this);
if (sScratchPBO == 0)
{
glGenBuffers(1, &sScratchPBO);
sScratchPBOSize = 0;
}
glBindBuffer(GL_PIXEL_PACK_BUFFER, sScratchPBO);
if (size > sScratchPBOSize)
{
glBufferData(GL_PIXEL_PACK_BUFFER, size, NULL, GL_STREAM_COPY);
sScratchPBOSize = size;
}
glGetTexImage(mTarget, mip, mFormatPrimary, mFormatType, nullptr);
free_tex_image(mTexName);
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, sScratchPBO);
glTexImage2D(mTarget, 0, mFormatPrimary, desired_width, desired_height, 0, mFormatPrimary, mFormatType, nullptr);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
alloc_tex_image(desired_width, desired_height, mFormatPrimary);
if (mHasMipMaps)
{
LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("scaleDown - glGenerateMipmap");
glGenerateMipmap(mTarget);
}
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
mCurrentDiscardLevel = desired_discard;
return true;
}
//----------------------------------------------------------------------------
#if LL_IMAGEGL_THREAD_CHECK
void LLImageGL::checkActiveThread()

View File

@ -39,6 +39,7 @@
#include "llrender.h"
#include "threadpool.h"
#include "workqueue.h"
#include <unordered_set>
#define LL_IMAGEGL_THREAD_CHECK 0 //set to 1 to enable thread debugging for ImageGL
@ -83,9 +84,8 @@ public:
// needs to be called every frame
static void updateStats(F32 current_time);
// Save off / restore GL textures
static void destroyGL(bool save_state = true);
static void restoreGL();
// cleanup GL state
static void destroyGL();
static void dirtyTexOptions();
static bool checkSize(S32 width, S32 height);
@ -148,6 +148,10 @@ public:
S32 getDiscardLevel() const { return mCurrentDiscardLevel; }
S32 getMaxDiscardLevel() const { return mMaxDiscardLevel; }
// override the current discard level
// should only be used for local textures where you know exactly what you're doing
void setDiscardLevel(S32 level) { mCurrentDiscardLevel = level; }
S32 getCurrentWidth() const { return mWidth ;}
S32 getCurrentHeight() const { return mHeight ;}
S32 getWidth(S32 discard_level = -1) const;
@ -194,26 +198,26 @@ 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;}
LLGLenum getTexTarget()const { return mTarget; }
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);
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
// scale down to the desired discard level using GPU
// returns true if texture was scaled down
// desired discard will be clamped to max discard
// if desired discard is less than or equal to current discard, no scaling will occur
// only works for GL_TEXTURE_2D target
bool scaleDown(S32 desired_discard);
public:
// Various GL/Rendering options
S64Bytes mTextureMemory;
@ -240,15 +244,10 @@ private:
bool mGLTextureCreated ;
LLGLuint mTexName;
//LLGLuint mNewTexName = 0; // tex name set by background thread to be applied in main thread
U16 mWidth;
U16 mHeight;
S8 mCurrentDiscardLevel;
S8 mDiscardLevelInAtlas;
U32 mTexelsInAtlas ;
U32 mTexelsInGLTexture;
bool mAllowCompression;
protected:
@ -275,7 +274,7 @@ protected:
// STATICS
public:
static std::set<LLImageGL*> sImageList;
static std::unordered_set<LLImageGL*> sImageList;
static S32 sCount;
static F32 sLastFrameTime;
@ -301,6 +300,8 @@ public:
private:
static S32 sMaxCategories;
static bool sSkipAnalyzeAlpha;
static U32 sScratchPBO;
static U32 sScratchPBOSize;
//the flag to allow to call readBackRaw(...).
//can be removed if we do not use that function at all.

View File

@ -25,24 +25,53 @@
/*[EXTRA_CODE_HERE]*/
// generate a normal map using an approximation of the old emboss bump map "brightness/darkness" technique
// srcMap is a source color image, output should be a normal
out vec4 frag_color;
uniform sampler2D alphaMap;
uniform sampler2D srcMap;
in vec2 vary_texcoord0;
uniform float stepX;
uniform float stepY;
uniform float norm_scale;
uniform int bump_code;
#define BE_BRIGHTNESS 1
#define BE_DARKNESS 2
// get luminance or inverse luminance depending on bump_code
float getBumpValue(vec2 texcoord)
{
vec3 c = texture(srcMap, texcoord).rgb;
vec3 WEIGHT = vec3(0.2995, 0.5875, 0.1145);
float l = dot(c, WEIGHT);
if (bump_code == BE_DARKNESS)
{
l = 1.0 - l;
}
return l;
}
void main()
{
float c = texture(alphaMap, vary_texcoord0).r;
float c = getBumpValue(vary_texcoord0).r;
vec3 right = vec3(norm_scale, 0, (texture(alphaMap, vary_texcoord0+vec2(stepX, 0)).r-c)*255);
vec3 left = vec3(-norm_scale, 0, (texture(alphaMap, vary_texcoord0-vec2(stepX, 0)).r-c)*255);
vec3 up = vec3(0, -norm_scale, (texture(alphaMap, vary_texcoord0-vec2(0, stepY)).r-c)*255);
vec3 down = vec3(0, norm_scale, (texture(alphaMap, vary_texcoord0+vec2(0, stepY)).r-c)*255);
float scaler = 512.0;
vec3 right = vec3(norm_scale, 0, (getBumpValue(vary_texcoord0+vec2(stepX, 0)).r-c)*scaler);
vec3 left = vec3(-norm_scale, 0, (getBumpValue(vary_texcoord0-vec2(stepX, 0)).r-c)*scaler);
vec3 up = vec3(0, -norm_scale, (getBumpValue(vary_texcoord0-vec2(0, stepY)).r-c)*scaler);
vec3 down = vec3(0, norm_scale, (getBumpValue(vary_texcoord0+vec2(0, stepY)).r-c)*scaler);
vec3 norm = cross(right, down) + cross(down, left) + cross(left,up) + cross(up, right);

View File

@ -180,6 +180,16 @@ namespace LL
data[3] = src[3];
}
template<>
inline void copyVec4<U8, U64>(U8* src, U64& dst)
{
U8* data = (U8*)&dst;
data[0] = src[0];
data[1] = src[1];
data[2] = src[2];
data[3] = src[3];
}
template<>
inline void copyVec4<U16, LLColor4U>(U16* src, LLColor4U& dst)
{

View File

@ -144,7 +144,7 @@ void GLTFSceneManager::uploadSelection()
}
else
{
raw = image.mTexture->getCachedRawImage();
raw = image.mTexture->getRawImage();
}
if (raw.notNull())
@ -339,6 +339,7 @@ void GLTFSceneManager::renderAlpha()
void GLTFSceneManager::addGLTFObject(LLViewerObject* obj, LLUUID gltf_id)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_GLTF;
llassert(obj->getVolume()->getParams().getSculptID() == gltf_id);
llassert(obj->getVolume()->getParams().getSculptType() == LL_SCULPT_TYPE_GLTF);

View File

@ -105,10 +105,7 @@ void LLDebugView::init()
addChild(gSceneMonitorView);
gSceneMonitorView->setRect(rect);
r.setLeftTopAndSize(25, rect.getHeight() - 50, (S32) (gViewerWindow->getWindowRectScaled().getWidth() * 0.75f),
(S32) (gViewerWindow->getWindowRectScaled().getHeight() * 0.75f));
r.set(150, rect.getHeight() - 50, 820, 100);
r.set(150, rect.getHeight() - 60, 820, 110);
LLTextureView::Params tvp;
tvp.name("gTextureView");
tvp.rect(r);
@ -116,7 +113,6 @@ void LLDebugView::init()
tvp.visible(false);
gTextureView = LLUICtrlFactory::create<LLTextureView>(tvp);
addChild(gTextureView);
//gTextureView->reshape(r.getWidth(), r.getHeight(), true);
}
void LLDebugView::draw()

View File

@ -79,11 +79,6 @@ static S32 diffuse_channel = -1;
static S32 bump_channel = -1;
static bool shiny = false;
// Enabled after changing LLViewerTexture::mNeedsCreateTexture to an
// LLAtomicBool; this should work just fine, now. HB
#define LL_BUMPLIST_MULTITHREADED 1
// static
void LLStandardBumpmap::shutdown()
{
@ -764,24 +759,21 @@ LLViewerTexture* LLBumpImageList::getBrightnessDarknessImage(LLViewerFetchedText
LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL;
llassert( (bump_code == BE_BRIGHTNESS) || (bump_code == BE_DARKNESS) );
LLViewerTexture* bump = NULL;
LLViewerTexture* bump = nullptr;
bump_image_map_t* entries_list = NULL;
void (*callback_func)( bool success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, bool final, void* userdata ) = NULL;
bump_image_map_t* entries_list = nullptr;
switch( bump_code )
{
case BE_BRIGHTNESS:
entries_list = &mBrightnessEntries;
callback_func = LLBumpImageList::onSourceBrightnessLoaded;
break;
case BE_DARKNESS:
entries_list = &mDarknessEntries;
callback_func = LLBumpImageList::onSourceDarknessLoaded;
break;
default:
llassert(0);
return NULL;
return nullptr;
}
bump_image_map_t::iterator iter = entries_list->find(src_image->getID());
@ -789,51 +781,18 @@ LLViewerTexture* LLBumpImageList::getBrightnessDarknessImage(LLViewerFetchedText
{
bump = iter->second;
}
else
if (bump == nullptr ||
src_image->getWidth() != bump->getWidth() ||
src_image->getHeight() != bump->getHeight())
{
(*entries_list)[src_image->getID()] = LLViewerTextureManager::getLocalTexture( true );
bump = (*entries_list)[src_image->getID()]; // In case callback was called immediately and replaced the image
onSourceUpdated(src_image, (EBumpEffect) bump_code);
}
if (!src_image->hasCallbacks())
{ //if image has no callbacks but resolutions don't match, trigger raw image loaded callback again
if (src_image->getWidth() != bump->getWidth() ||
src_image->getHeight() != bump->getHeight())// ||
//(LLPipeline::sRenderDeferred && bump->getComponents() != 4))
{
src_image->setBoostLevel(LLGLTexture::BOOST_BUMP) ;
src_image->setLoadedCallback( callback_func, 0, true, false, new LLUUID(src_image->getID()), NULL );
src_image->forceToSaveRawImage(0) ;
}
}
return bump;
return (*entries_list)[src_image->getID()];
}
// static
void LLBumpImageList::onSourceBrightnessLoaded( bool success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, bool final, void* userdata )
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL;
LLUUID* source_asset_id = (LLUUID*)userdata;
LLBumpImageList::onSourceLoaded( success, src_vi, src, *source_asset_id, BE_BRIGHTNESS );
if( final )
{
delete source_asset_id;
}
}
// static
void LLBumpImageList::onSourceDarknessLoaded( bool success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, bool final, void* userdata )
{
LLUUID* source_asset_id = (LLUUID*)userdata;
LLBumpImageList::onSourceLoaded( success, src_vi, src, *source_asset_id, BE_DARKNESS );
if( final )
{
delete source_asset_id;
}
}
void LLBumpImageList::onSourceStandardLoaded( bool success, LLViewerFetchedTexture* src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, bool final, void* userdata)
{
if (success && LLPipeline::sRenderDeferred)
@ -909,289 +868,108 @@ void LLBumpImageList::generateNormalMapFromAlpha(LLImageRaw* src, LLImageRaw* nr
}
// static
void LLBumpImageList::onSourceLoaded( bool success, LLViewerTexture *src_vi, LLImageRaw* src, LLUUID& source_asset_id, EBumpEffect bump_code )
void LLBumpImageList::onSourceUpdated(LLViewerTexture* src, EBumpEffect bump_code)
{
LL_PROFILE_ZONE_SCOPED;
LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL;
if( success )
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL;
const LLUUID& src_id = src->getID();
LLImageDataSharedLock lock(src);
bump_image_map_t& entries_list(bump_code == BE_BRIGHTNESS ? gBumpImageList.mBrightnessEntries : gBumpImageList.mDarknessEntries);
bump_image_map_t::iterator iter = entries_list.find(src_id);
bump_image_map_t& entries_list(bump_code == BE_BRIGHTNESS ? gBumpImageList.mBrightnessEntries : gBumpImageList.mDarknessEntries );
bump_image_map_t::iterator iter = entries_list.find(source_asset_id);
{
if (iter == entries_list.end() ||
iter->second.isNull() ||
iter->second->getWidth() != src->getWidth() ||
iter->second->getHeight() != src->getHeight()) // bump not cached yet or has changed resolution
{ //make sure an entry exists for this image
entries_list[src_vi->getID()] = LLViewerTextureManager::getLocalTexture(true);
iter = entries_list.find(src_vi->getID());
}
}
if (iter->second->getWidth() != src->getWidth() ||
iter->second->getHeight() != src->getHeight()) // bump not cached yet or has changed resolution
{
LLPointer<LLImageRaw> dst_image = new LLImageRaw(src->getWidth(), src->getHeight(), 1);
U8* dst_data = dst_image->getData();
S32 dst_data_size = dst_image->getDataSize();
const U8* src_data = src->getData();
S32 src_data_size = src->getDataSize();
S32 src_components = src->getComponents();
// Convert to luminance and then scale and bias that to get ready for
// embossed bump mapping. (0-255 maps to 127-255)
// Convert to fixed point so we don't have to worry about precision/clamping.
const S32 FIXED_PT = 8;
const S32 R_WEIGHT = S32(0.2995f * (1<<FIXED_PT));
const S32 G_WEIGHT = S32(0.5875f * (1<<FIXED_PT));
const S32 B_WEIGHT = S32(0.1145f * (1<<FIXED_PT));
S32 minimum = 255;
S32 maximum = 0;
switch( src_components )
{
case 1:
case 2:
{
if( src_data_size == dst_data_size * src_components )
{
for( S32 i = 0, j=0; i < dst_data_size; i++, j+= src_components )
{
dst_data[i] = src_data[j];
if( dst_data[i] < minimum )
{
minimum = dst_data[i];
}
if( dst_data[i] > maximum )
{
maximum = dst_data[i];
}
}
}
else
{
llassert(0);
dst_image->clear();
}
}
break;
case 3:
case 4:
{
if( src_data_size == dst_data_size * src_components )
{
for( S32 i = 0, j=0; i < dst_data_size; i++, j+= src_components )
{
// RGB to luminance
dst_data[i] = (R_WEIGHT * src_data[j] + G_WEIGHT * src_data[j+1] + B_WEIGHT * src_data[j+2]) >> FIXED_PT;
//llassert( dst_data[i] <= 255 );true because it's 8bit
if( dst_data[i] < minimum )
{
minimum = dst_data[i];
}
if( dst_data[i] > maximum )
{
maximum = dst_data[i];
}
}
}
else
{
llassert(0);
dst_image->clear();
}
}
break;
default:
llassert(0);
dst_image->clear();
break;
}
if( maximum > minimum )
{
U8 bias_and_scale_lut[256];
F32 twice_one_over_range = 2.f / (maximum - minimum);
S32 i;
const F32 ARTIFICIAL_SCALE = 2.f; // Advantage: exaggerates the effect in midrange. Disadvantage: clamps at the extremes.
if (BE_DARKNESS == bump_code)
{
for( i = minimum; i <= maximum; i++ )
{
F32 minus_one_to_one = F32(maximum - i) * twice_one_over_range - 1.f;
bias_and_scale_lut[i] = llclampb(ll_round(127 * minus_one_to_one * ARTIFICIAL_SCALE + 128));
}
}
else
{
for( i = minimum; i <= maximum; i++ )
{
F32 minus_one_to_one = F32(i - minimum) * twice_one_over_range - 1.f;
bias_and_scale_lut[i] = llclampb(ll_round(127 * minus_one_to_one * ARTIFICIAL_SCALE + 128));
}
}
for( i = 0; i < dst_data_size; i++ )
{
dst_data[i] = bias_and_scale_lut[dst_data[i]];
}
}
//---------------------------------------------------
// immediately assign bump to a smart pointer in case some local smart pointer
// accidentally releases it.
LLPointer<LLViewerTexture> bump = iter->second;
if (!LLPipeline::sRenderDeferred)
{
bump->setExplicitFormat(GL_ALPHA8, GL_ALPHA);
#if LL_BUMPLIST_MULTITHREADED
auto tex_queue = LLImageGLThread::sEnabledTextures ? sTexUpdateQueue.lock() : nullptr;
if (tex_queue)
{ //dispatch creation to background thread
LLImageRaw* dst_ptr = dst_image;
LLViewerTexture* bump_ptr = bump;
dst_ptr->ref();
bump_ptr->ref();
tex_queue->post(
[=]()
{
LL_PROFILE_ZONE_NAMED("bil - create texture");
bump_ptr->createGLTexture(0, dst_ptr);
bump_ptr->unref();
dst_ptr->unref();
});
}
else
#endif
{
bump->createGLTexture(0, dst_image);
}
}
else
{ //convert to normal map
LL_PROFILE_ZONE_NAMED("bil - create normal map");
LLImageGL* img = bump->getGLTexture();
LLImageRaw* dst_ptr = dst_image.get();
LLGLTexture* bump_ptr = bump.get();
dst_ptr->ref();
img->ref();
bump_ptr->ref();
auto create_func = [=]()
{
img->setUseMipMaps(true);
// upload dst_image to GPU (greyscale in red channel)
img->setExplicitFormat(GL_RED, GL_RED);
bump_ptr->createGLTexture(0, dst_ptr);
dst_ptr->unref();
};
auto generate_func = [=]()
{
// Allocate an empty RGBA texture at "tex_name" the same size as bump
// Note: bump will still point at GPU copy of dst_image
bump_ptr->setExplicitFormat(GL_RGBA, GL_RGBA);
LLGLuint tex_name;
img->createGLTexture(0, nullptr, false, 0, true, &tex_name);
// point render target at empty buffer
sRenderTarget.setColorAttachment(img, tex_name);
// generate normal map in empty texture
{
sRenderTarget.bindTarget();
LLGLDepthTest depth(GL_FALSE);
LLGLDisable cull(GL_CULL_FACE);
LLGLDisable blend(GL_BLEND);
gGL.setColorMask(true, true);
gNormalMapGenProgram.bind();
static LLStaticHashedString sNormScale("norm_scale");
static LLStaticHashedString sStepX("stepX");
static LLStaticHashedString sStepY("stepY");
gNormalMapGenProgram.uniform1f(sNormScale, gSavedSettings.getF32("RenderNormalMapScale"));
gNormalMapGenProgram.uniform1f(sStepX, 1.f / bump_ptr->getWidth());
gNormalMapGenProgram.uniform1f(sStepY, 1.f / bump_ptr->getHeight());
gGL.getTexUnit(0)->bind(bump_ptr);
gGL.begin(LLRender::TRIANGLE_STRIP);
gGL.texCoord2f(0, 0);
gGL.vertex2f(0, 0);
gGL.texCoord2f(0, 1);
gGL.vertex2f(0, 1);
gGL.texCoord2f(1, 0);
gGL.vertex2f(1, 0);
gGL.texCoord2f(1, 1);
gGL.vertex2f(1, 1);
gGL.end();
gGL.flush();
gNormalMapGenProgram.unbind();
sRenderTarget.flush();
sRenderTarget.releaseColorAttachment();
}
// point bump at normal map and free gpu copy of dst_image
img->syncTexName(tex_name);
// generate mipmap
gGL.getTexUnit(0)->bind(img);
glGenerateMipmap(GL_TEXTURE_2D);
gGL.getTexUnit(0)->disable();
bump_ptr->unref();
img->unref();
};
#if LL_BUMPLIST_MULTITHREADED
auto main_queue = LLImageGLThread::sEnabledTextures ? sMainQueue.lock() : nullptr;
if (main_queue)
{ //dispatch texture upload to background thread, issue GPU commands to generate normal map on main thread
main_queue->postTo(
sTexUpdateQueue,
create_func,
generate_func);
}
else
#endif
{ // immediate upload texture and generate normal map
create_func();
generate_func();
}
}
iter->second = bump; // derefs (and deletes) old image
//---------------------------------------------------
}
if (iter == entries_list.end())
{ //make sure an entry exists for this image
entries_list[src_id] = LLViewerTextureManager::getLocalTexture(true);
iter = entries_list.find(src_id);
}
//---------------------------------------------------
// immediately assign bump to a smart pointer in case some local smart pointer
// accidentally releases it.
LLPointer<LLViewerTexture> bump = iter->second;
if (bump->getWidth() != src->getWidth() ||
bump->getHeight() != src->getHeight()) // bump not cached yet or has changed resolution
{
//convert to normal map
LL_PROFILE_ZONE_NAMED("bil - create normal map");
bump->setExplicitFormat(GL_RGBA, GL_RGBA);
LLImageGL* src_img = src->getGLTexture();
LLImageGL* dst_img = bump->getGLTexture();
dst_img->setSize(src->getWidth(), src->getHeight(), 4, 0);
dst_img->setUseMipMaps(true);
dst_img->setDiscardLevel(0);
dst_img->createGLTexture();
gGL.getTexUnit(0)->bind(bump);
LLImageGL::setManualImage(GL_TEXTURE_2D, 0, dst_img->getPrimaryFormat(), dst_img->getWidth(), dst_img->getHeight(), GL_RGBA, GL_UNSIGNED_BYTE, nullptr, false);
LLGLuint tex_name = dst_img->getTexName();
// point render target at empty buffer
sRenderTarget.setColorAttachment(bump->getGLTexture(), tex_name);
// generate normal map in empty texture
{
sRenderTarget.bindTarget();
LLGLDepthTest depth(GL_FALSE);
LLGLDisable cull(GL_CULL_FACE);
LLGLDisable blend(GL_BLEND);
gGL.setColorMask(true, true);
LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr;
gNormalMapGenProgram.bind();
static LLStaticHashedString sNormScale("norm_scale");
static LLStaticHashedString sStepX("stepX");
static LLStaticHashedString sStepY("stepY");
static LLStaticHashedString sBumpCode("bump_code");
gNormalMapGenProgram.uniform1f(sNormScale, gSavedSettings.getF32("RenderNormalMapScale"));
gNormalMapGenProgram.uniform1f(sStepX, 1.f / bump->getWidth());
gNormalMapGenProgram.uniform1f(sStepY, 1.f / bump->getHeight());
gNormalMapGenProgram.uniform1i(sBumpCode, bump_code);
gGL.getTexUnit(0)->bind(src);
gGL.begin(LLRender::TRIANGLE_STRIP);
gGL.texCoord2f(0, 0);
gGL.vertex2f(0, 0);
gGL.texCoord2f(0, 1);
gGL.vertex2f(0, 1);
gGL.texCoord2f(1, 0);
gGL.vertex2f(1, 0);
gGL.texCoord2f(1, 1);
gGL.vertex2f(1, 1);
gGL.end();
gGL.flush();
sRenderTarget.flush();
sRenderTarget.releaseColorAttachment();
if (shader)
{
shader->bind();
}
}
// generate mipmap
gGL.getTexUnit(0)->bind(bump);
glGenerateMipmap(GL_TEXTURE_2D);
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
}
iter->second = bump; // derefs (and deletes) old image
//---------------------------------------------------
}
void LLDrawPoolBump::pushBumpBatches(U32 type)

View File

@ -140,14 +140,13 @@ public:
LLViewerTexture* getBrightnessDarknessImage(LLViewerFetchedTexture* src_image, U8 bump_code);
void addTextureStats(U8 bump, const LLUUID& base_image_id, F32 virtual_size);
static void onSourceBrightnessLoaded( bool success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, bool final, void* userdata );
static void onSourceDarknessLoaded( bool success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, bool final, void* userdata );
static void onSourceStandardLoaded( bool success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, bool final, void* userdata );
static void generateNormalMapFromAlpha(LLImageRaw* src, LLImageRaw* nrm_image);
private:
static void onSourceLoaded( bool success, LLViewerTexture *src_vi, LLImageRaw* src, LLUUID& source_asset_id, EBumpEffect bump );
// should be called whenever resolution of src_vi changes compared to the current entry
static void onSourceUpdated( LLViewerTexture *src_vi, EBumpEffect bump );
private:
typedef std::unordered_map<LLUUID, LLPointer<LLViewerTexture> > bump_image_map_t;

View File

@ -951,8 +951,8 @@ void LLFloaterChangeItemThumbnail::onTexturePickerCommit()
|| texturep->getFullWidth() == 0)
{
if (texturep->isFullyLoaded()
&& (texturep->getCachedRawImageLevel() == 0 || texturep->getRawImageLevel() == 0)
&& (texturep->isCachedRawImageReady() || texturep->isRawImageValid()))
&& (texturep->getRawImageLevel() == 0)
&& (texturep->isRawImageValid()))
{
LLUUID task_id = mTaskId;
uuid_set_t inventory_ids = mItemList;
@ -962,20 +962,10 @@ void LLFloaterChangeItemThumbnail::onTexturePickerCommit()
{
onUploadComplete(asset_id, task_id, inventory_ids, handle);
};
if (texturep->isRawImageValid())
{
LLFloaterSimpleSnapshot::uploadThumbnail(texturep->getRawImage(),
*mItemList.begin(),
mTaskId,
callback);
}
else
{
LLFloaterSimpleSnapshot::uploadThumbnail(texturep->getCachedRawImage(),
*mItemList.begin(),
mTaskId,
callback);
}
LLFloaterSimpleSnapshot::uploadThumbnail(texturep->getRawImage(),
*mItemList.begin(),
mTaskId,
callback);
}
else
{

View File

@ -215,7 +215,6 @@ bool LLLocalBitmap::updateSelf(EUpdateType optional_firstupdate)
("file://"+mFilename, FTT_LOCAL_FILE, mWorldID, LL_LOCAL_USE_MIPMAPS);
texture->createGLTexture(LL_LOCAL_DISCARD_LEVEL, raw_image);
texture->setCachedRawImage(LL_LOCAL_DISCARD_LEVEL, raw_image);
texture->ref();
gTextureList.addImage(texture, TEX_LIST_STANDARD);

View File

@ -296,8 +296,6 @@ void LLNetMap::draw()
gGL.color4f(1.f, 0.5f, 0.5f, 1.f);
}
// Draw using texture.
gGL.getTexUnit(0)->bind(regionp->getLand().getSTexture());
gGL.begin(LLRender::QUADS);
@ -311,24 +309,6 @@ void LLNetMap::draw()
gGL.vertex2f(right, top);
gGL.end();
// Draw water
gGL.flush();
{
if (regionp->getLand().getWaterTexture())
{
gGL.getTexUnit(0)->bind(regionp->getLand().getWaterTexture());
gGL.begin(LLRender::QUADS);
gGL.texCoord2f(0.f, 1.f);
gGL.vertex2f(left, top);
gGL.texCoord2f(0.f, 0.f);
gGL.vertex2f(left, bottom);
gGL.texCoord2f(1.f, 0.f);
gGL.vertex2f(right, bottom);
gGL.texCoord2f(1.f, 1.f);
gGL.vertex2f(right, top);
gGL.end();
}
}
gGL.flush();
}

View File

@ -54,6 +54,7 @@
#include "llglheaders.h"
#include "lldrawpoolterrain.h"
#include "lldrawable.h"
#include "llworldmipmap.h"
extern LLPipeline gPipeline;
extern bool gShiftFrame;
@ -74,7 +75,6 @@ LLSurface::LLSurface(U32 type, LLViewerRegion *regionp) :
mDetailTextureScale(0.f),
mOriginGlobal(0.0, 0.0, 0.0),
mSTexturep(NULL),
mWaterTexturep(NULL),
mGridsPerPatchEdge(0),
mMetersPerGrid(1.0f),
mMetersPerEdge(1.0f),
@ -129,14 +129,7 @@ LLSurface::~LLSurface()
{
gPipeline.removePool(poolp);
// Don't enable this until we blitz the draw pool for it as well. -- djs
if (mSTexturep)
{
mSTexturep = NULL;
}
if (mWaterTexturep)
{
mWaterTexturep = NULL;
}
mSTexturep = NULL;
}
else
{
@ -216,62 +209,17 @@ LLViewerTexture* LLSurface::getSTexture()
return mSTexturep;
}
LLViewerTexture* LLSurface::getWaterTexture()
{
if (mWaterTexturep.notNull() && !mWaterTexturep->hasGLTexture())
{
createWaterTexture();
}
return mWaterTexturep;
}
void LLSurface::createSTexture()
{
if (!mSTexturep)
{
// Fill with dummy gray data.
// GL NOT ACTIVE HERE
LLPointer<LLImageRaw> raw = new LLImageRaw(sTextureSize, sTextureSize, 3);
U8 *default_texture = raw->getData();
for (S32 i = 0; i < sTextureSize; i++)
{
for (S32 j = 0; j < sTextureSize; j++)
{
*(default_texture + (i*sTextureSize + j)*3) = 128;
*(default_texture + (i*sTextureSize + j)*3 + 1) = 128;
*(default_texture + (i*sTextureSize + j)*3 + 2) = 128;
}
}
U64 handle = mRegionp->getHandle();
mSTexturep = LLViewerTextureManager::getLocalTexture(raw.get(), false);
mSTexturep->dontDiscard();
gGL.getTexUnit(0)->bind(mSTexturep);
mSTexturep->setAddressMode(LLTexUnit::TAM_CLAMP);
}
}
U32 grid_x, grid_y;
void LLSurface::createWaterTexture()
{
if (!mWaterTexturep)
{
// Create the water texture
LLPointer<LLImageRaw> raw = new LLImageRaw(sTextureSize/2, sTextureSize/2, 4);
U8 *default_texture = raw->getData();
for (S32 i = 0; i < sTextureSize/2; i++)
{
for (S32 j = 0; j < sTextureSize/2; j++)
{
*(default_texture + (i*sTextureSize/2 + j)*4) = MAX_WATER_COLOR.mV[0];
*(default_texture + (i*sTextureSize/2 + j)*4 + 1) = MAX_WATER_COLOR.mV[1];
*(default_texture + (i*sTextureSize/2 + j)*4 + 2) = MAX_WATER_COLOR.mV[2];
*(default_texture + (i*sTextureSize/2 + j)*4 + 3) = MAX_WATER_COLOR.mV[3];
}
}
grid_from_region_handle(handle, &grid_x, &grid_y);
mWaterTexturep = LLViewerTextureManager::getLocalTexture(raw.get(), false);
mWaterTexturep->dontDiscard();
gGL.getTexUnit(0)->bind(mWaterTexturep);
mWaterTexturep->setAddressMode(LLTexUnit::TAM_CLAMP);
mSTexturep = LLWorldMipmap::loadObjectsTile(grid_x, grid_y, 1);
}
}
@ -285,11 +233,10 @@ void LLSurface::initTextures()
///////////////////////
//
// Water texture
// Water object
//
if (gSavedSettings.getBOOL("RenderWater") )
{
createWaterTexture();
mWaterObjp = (LLVOWater *)gObjectList.createObjectViewer(LLViewerObject::LL_VO_WATER, mRegionp);
gPipeline.createObject(mWaterObjp);
LLVector3d water_pos_global = from_region_handle(mRegionp->getHandle());
@ -683,11 +630,8 @@ bool LLSurface::idleUpdate(F32 max_update_time)
}
}
if (did_update)
{
// some patches changed, update region reflection probes
mRegionp->updateReflectionProbes();
}
// some patches changed, update region reflection probes
mRegionp->updateReflectionProbes(did_update);
return did_update;
}
@ -1221,98 +1165,3 @@ F32 LLSurface::getWaterHeight() const
}
}
bool LLSurface::generateWaterTexture(const F32 x, const F32 y,
const F32 width, const F32 height)
{
LL_PROFILE_ZONE_SCOPED
if (!getWaterTexture())
{
return false;
}
S32 tex_width = mWaterTexturep->getWidth();
S32 tex_height = mWaterTexturep->getHeight();
S32 tex_comps = mWaterTexturep->getComponents();
S32 tex_stride = tex_width * tex_comps;
LLPointer<LLImageRaw> raw = new LLImageRaw(tex_width, tex_height, tex_comps);
U8 *rawp = raw->getData();
F32 scale = 256.f * getMetersPerGrid() / (F32)tex_width;
F32 scale_inv = 1.f / scale;
S32 x_begin, y_begin, x_end, y_end;
x_begin = ll_round(x * scale_inv);
y_begin = ll_round(y * scale_inv);
x_end = ll_round((x + width) * scale_inv);
y_end = ll_round((y + width) * scale_inv);
if (x_end > tex_width)
{
x_end = tex_width;
}
if (y_end > tex_width)
{
y_end = tex_width;
}
// OK, for now, just have the composition value equal the height at the point.
LLVector3 location;
LLColor4U coloru;
const F32 WATER_HEIGHT = getWaterHeight();
S32 i, j, offset;
for (j = y_begin; j < y_end; j++)
{
for (i = x_begin; i < x_end; i++)
{
//F32 nv[2];
//nv[0] = i/256.f;
//nv[1] = j/256.f;
// const S32 modulation = noise2(nv)*40;
offset = j*tex_stride + i*tex_comps;
location.mV[VX] = i*scale;
location.mV[VY] = j*scale;
// Sample multiple points
const F32 height = resolveHeightRegion(location);
if (height > WATER_HEIGHT)
{
// Above water...
coloru = MAX_WATER_COLOR;
coloru.mV[3] = ABOVE_WATERLINE_ALPHA;
*(rawp + offset++) = coloru.mV[0];
*(rawp + offset++) = coloru.mV[1];
*(rawp + offset++) = coloru.mV[2];
*(rawp + offset++) = coloru.mV[3];
}
else
{
// Want non-linear curve for transparency gradient
coloru = MAX_WATER_COLOR;
const F32 frac = 1.f - 2.f/(2.f - (height - WATER_HEIGHT));
S32 alpha = 64 + ll_round((255-64)*frac);
alpha = llmin(ll_round((F32)MAX_WATER_COLOR.mV[3]), alpha);
alpha = llmax(64, alpha);
coloru.mV[3] = alpha;
*(rawp + offset++) = coloru.mV[0];
*(rawp + offset++) = coloru.mV[1];
*(rawp + offset++) = coloru.mV[2];
*(rawp + offset++) = coloru.mV[3];
}
}
}
if (!mWaterTexturep->hasGLTexture())
{
mWaterTexturep->createGLTexture(0, raw);
}
mWaterTexturep->setSubImage(raw, x_begin, y_begin, x_end - x_begin, y_end - y_begin);
return true;
}

View File

@ -128,7 +128,7 @@ public:
F32 getWaterHeight() const;
LLViewerTexture *getSTexture();
LLViewerTexture *getWaterTexture();
bool hasZData() const { return mHasZData; }
void dirtyAllPatches(); // Use this to dirty all patches when changing terrain parameters
@ -171,19 +171,11 @@ public:
protected:
void createSTexture();
void createWaterTexture();
void initTextures();
void initWater();
void createPatchData(); // Allocates memory for patches.
void destroyPatchData(); // Deallocates memory for patches.
bool generateWaterTexture(const F32 x, const F32 y,
const F32 width, const F32 height); // Generate texture from composition values.
//F32 updateTexture(LLSurfacePatch *ppatch);
LLSurfacePatch *getPatch(const S32 x, const S32 y) const;
protected:
@ -201,7 +193,6 @@ protected:
// The textures should never be directly initialized - use the setter methods!
LLPointer<LLViewerTexture> mSTexturep; // Texture for surface
LLPointer<LLViewerTexture> mWaterTexturep; // Water texture
LLPointer<LLVOWater> mWaterObjp;

View File

@ -906,15 +906,8 @@ void LLSurfacePatch::updateGL()
updateCompositionStats();
F32 tex_patch_size = meters_per_grid*grids_per_patch_edge;
if (comp->generateMinimapTileLand((F32)origin_region[VX], (F32)origin_region[VY],
tex_patch_size, tex_patch_size))
{
mSTexUpdate = false;
// Also generate the water texture
mSurfacep->generateWaterTexture((F32)origin_region.mdV[VX], (F32)origin_region.mdV[VY],
tex_patch_size, tex_patch_size);
}
mSTexUpdate = false;
}
void LLSurfacePatch::dirtyZ()

View File

@ -461,7 +461,7 @@ public:
: texture_view("texture_view")
{
S32 line_height = LLFontGL::getFontMonospace()->getLineHeight();
changeDefault(rect, LLRect(0,0,100,line_height * 4));
changeDefault(rect, LLRect(0,0,0,line_height * 7));
}
};
@ -492,19 +492,51 @@ void LLGLTexMemBar::draw()
U32 total_objects = gObjectList.getNumObjects();
F32 x_right = 0.0;
U32 image_count = gTextureList.getNumImages();
U32 raw_image_count = 0;
U64 raw_image_bytes = 0;
U32 saved_raw_image_count = 0;
U64 saved_raw_image_bytes = 0;
U32 aux_raw_image_count = 0;
U64 aux_raw_image_bytes = 0;
for (auto& image : gTextureList)
{
const LLImageRaw* raw_image = image->getRawImage();
if (raw_image)
{
raw_image_count++;
raw_image_bytes += raw_image->getDataSize();
}
raw_image = image->getSavedRawImage();
if (raw_image)
{
saved_raw_image_count++;
saved_raw_image_bytes += raw_image->getDataSize();
}
raw_image = image->getAuxRawImage();
if (raw_image)
{
aux_raw_image_count++;
aux_raw_image_bytes += raw_image->getDataSize();
}
}
F64 raw_image_bytes_MB = raw_image_bytes / (1024.0 * 1024.0);
F64 saved_raw_image_bytes_MB = saved_raw_image_bytes / (1024.0 * 1024.0);
F64 aux_raw_image_bytes_MB = aux_raw_image_bytes / (1024.0 * 1024.0);
//----------------------------------------------------------------------------
LLGLSUIDefault gls_ui;
LLColor4 text_color(1.f, 1.f, 1.f, 0.75f);
LLColor4 color;
// Gray background using completely magic numbers
gGL.color4f(0.f, 0.f, 0.f, 0.25f);
// const LLRect & rect(getRect());
// gl_rect_2d(-4, v_offset, rect.mRight - rect.mLeft + 2, v_offset + line_height*4);
std::string text = "";
LLFontGL::getFontMonospace()->renderUTF8(text, 0, 0, v_offset + line_height*6,
text_color, LLFontGL::LEFT, LLFontGL::TOP);
LLTrace::Recording& recording = LLViewerStats::instance().getRecording();
@ -525,6 +557,10 @@ void LLGLTexMemBar::draw()
U32 texFetchLatMed = U32(recording.getMean(LLTextureFetch::sTexFetchLatency).value() * 1000.0f);
U32 texFetchLatMax = U32(recording.getMax(LLTextureFetch::sTexFetchLatency).value() * 1000.0f);
// draw a background above first line.... no idea where the rest of the background comes from for the below text
gGL.color4f(0.f, 0.f, 0.f, 0.25f);
gl_rect_2d(-10, getRect().getHeight() + line_height + 1, getRect().getWidth()+2, getRect().getHeight()+2);
text = llformat("Est. Free: %d MB Sys Free: %d MB FBO: %d MB Bias: %.2f Cache: %.1f/%.1f MB",
(S32)LLViewerTexture::sFreeVRAMMegabytes,
LLMemory::getAvailableMemKB()/1024,
@ -532,11 +568,15 @@ void LLGLTexMemBar::draw()
discard_bias,
cache_usage,
cache_max_usage);
//, cache_entries, cache_max_entries
LLFontGL::getFontMonospace()->renderUTF8(text, 0, 0, v_offset + line_height*6,
LLFontGL::getFontMonospace()->renderUTF8(text, 0, 0, v_offset + line_height*7,
text_color, LLFontGL::LEFT, LLFontGL::TOP);
text = llformat("Images: %d Raw: %d (%.2f MB) Saved: %d (%.2f MB) Aux: %d (%.2f MB)", image_count, raw_image_count, raw_image_bytes_MB,
saved_raw_image_count, saved_raw_image_bytes_MB,
aux_raw_image_count, aux_raw_image_bytes_MB);
LLFontGL::getFontMonospace()->renderUTF8(text, 0, 0, v_offset + line_height * 6,
text_color, LLFontGL::LEFT, LLFontGL::TOP);
U32 cache_read(0U), cache_write(0U), res_wait(0U);
LLAppViewer::getTextureFetch()->getStateStats(&cache_read, &cache_write, &res_wait);
@ -549,7 +589,6 @@ void LLGLTexMemBar::draw()
cache_read,
cache_write,
res_wait);
LLFontGL::getFontMonospace()->renderUTF8(text, 0, 0, v_offset + line_height*5,
text_color, LLFontGL::LEFT, LLFontGL::TOP);
@ -789,7 +828,7 @@ void LLTextureView::draw()
LL_INFOS() << "ID\tMEM\tBOOST\tPRI\tWIDTH\tHEIGHT\tDISCARD" << LL_ENDL;
}
for (LLViewerTextureList::image_priority_list_t::iterator iter = gTextureList.mImageList.begin();
for (LLViewerTextureList::image_list_t::iterator iter = gTextureList.mImageList.begin();
iter != gTextureList.mImageList.end(); )
{
LLPointer<LLViewerFetchedTexture> imagep = *iter++;

View File

@ -1253,41 +1253,46 @@ void LLViewerMedia::getOpenIDCookieCoro(std::string url)
hostEnd = authority.size();
}
LLViewerMedia* inst = getInstance();
if (url.length())
{
LLMediaCtrl* media_instance = LLFloaterReg::getInstance("destinations")->getChild<LLMediaCtrl>("destination_guide_contents");
if (media_instance)
{
std::string cookie_host = authority.substr(hostStart, hostEnd - hostStart);
std::string cookie_name = "";
std::string cookie_value = "";
std::string cookie_path = "";
bool httponly = true;
bool secure = true;
if (inst->parseRawCookie(inst->mOpenIDCookie, cookie_name, cookie_value, cookie_path, httponly, secure) &&
media_instance->getMediaPlugin())
LLAppViewer::instance()->postToMainCoro([=]()
{
// MAINT-5711 - inexplicably, the CEF setCookie function will no longer set the cookie if the
// url and domain are not the same. This used to be my.sl.com and id.sl.com respectively and worked.
// For now, we use the URL for the OpenID POST request since it will have the same authority
// as the domain field.
// (Feels like there must be a less dirty way to construct a URL from component LLURL parts)
// MAINT-6392 - Rider: Do not change, however, the original URI requested, since it is used further
// down.
std::string cefUrl(std::string(inst->mOpenIDURL.mURI) + "://" + std::string(inst->mOpenIDURL.mAuthority));
LLMediaCtrl* media_instance = LLFloaterReg::getInstance("destinations")->getChild<LLMediaCtrl>("destination_guide_contents");
if (media_instance)
{
LLViewerMedia* inst = getInstance();
std::string cookie_host = authority.substr(hostStart, hostEnd - hostStart);
std::string cookie_name = "";
std::string cookie_value = "";
std::string cookie_path = "";
bool httponly = true;
bool secure = true;
if (inst->parseRawCookie(inst->mOpenIDCookie, cookie_name, cookie_value, cookie_path, httponly, secure) &&
media_instance->getMediaPlugin())
{
// MAINT-5711 - inexplicably, the CEF setCookie function will no longer set the cookie if the
// url and domain are not the same. This used to be my.sl.com and id.sl.com respectively and worked.
// For now, we use the URL for the OpenID POST request since it will have the same authority
// as the domain field.
// (Feels like there must be a less dirty way to construct a URL from component LLURL parts)
// MAINT-6392 - Rider: Do not change, however, the original URI requested, since it is used further
// down.
std::string cefUrl(std::string(inst->mOpenIDURL.mURI) + "://" + std::string(inst->mOpenIDURL.mAuthority));
media_instance->getMediaPlugin()->setCookie(cefUrl, cookie_name, cookie_value, cookie_host,
cookie_path, httponly, secure);
media_instance->getMediaPlugin()->setCookie(cefUrl, cookie_name, cookie_value, cookie_host,
cookie_path, httponly, secure);
// Now that we have parsed the raw cookie, we must store it so that each new media instance
// can also get a copy and faciliate logging into internal SL sites.
media_instance->getMediaPlugin()->storeOpenIDCookie(cefUrl, cookie_name, cookie_value,
cookie_host, cookie_path, httponly, secure);
}
}
// Now that we have parsed the raw cookie, we must store it so that each new media instance
// can also get a copy and faciliate logging into internal SL sites.
media_instance->getMediaPlugin()->storeOpenIDCookie(cefUrl, cookie_name, cookie_value,
cookie_host, cookie_path, httponly, secure);
}
}
});
}
LLViewerMedia* inst = getInstance();
// Note: Rider: MAINT-6392 - Some viewer code requires access to the my.sl.com openid cookie for such
// actions as posting snapshots to the feed. This is handled through HTTPCore rather than CEF and so
// we must learn to SHARE the cookies.

View File

@ -3676,7 +3676,9 @@ bool LLViewerObject::updateLOD()
bool LLViewerObject::updateGeometry(LLDrawable *drawable)
{
return false;
// return true means "update complete", return false means "try again next frame"
// default should be return true
return true;
}
void LLViewerObject::updateGL()

View File

@ -1269,8 +1269,12 @@ U32 LLViewerRegion::getNumOfVisibleGroups() const
return mImpl ? static_cast<U32>(mImpl->mVisibleGroups.size()) : 0;
}
void LLViewerRegion::updateReflectionProbes()
void LLViewerRegion::updateReflectionProbes(bool full_update)
{
if (!full_update && mReflectionMaps.empty())
{
return;
}
LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
const F32 probe_spacing = 32.f;
const F32 probe_radius = sqrtf((probe_spacing * 0.5f) * (probe_spacing * 0.5f) * 3.f);

View File

@ -428,7 +428,7 @@ public:
static bool isNewObjectCreationThrottleDisabled() {return sNewObjectCreationThrottle < 0;}
// rebuild reflection probe list
void updateReflectionProbes();
void updateReflectionProbes(bool full_update);
private:
void addToVOCacheTree(LLVOCacheEntry* entry);

View File

@ -414,8 +414,6 @@ void LLViewerTextureManager::init()
}
}
imagep->createGLTexture(0, image_raw);
//cache the raw image
imagep->setCachedRawImage(0, image_raw);
image_raw = NULL;
#else
LLViewerFetchedTexture::sDefaultImagep = LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT, true, LLGLTexture::BOOST_UI);
@ -728,9 +726,6 @@ bool LLViewerTexture::bindDefaultImage(S32 stage)
}
stop_glerror();
//check if there is cached raw image and switch to it if possible
switchToCachedImage();
LLTexturePipelineTester* tester = (LLTexturePipelineTester*)LLMetricPerformanceTesterBasic::getTester(sTesterName);
if (tester)
{
@ -931,18 +926,6 @@ void LLViewerTexture::reorganizeVolumeList()
}
}
//virtual
void LLViewerTexture::switchToCachedImage()
{
//nothing here.
}
//virtual
void LLViewerTexture::setCachedRawImage(S32 discard_level, LLImageRaw* imageraw)
{
//nothing here.
}
bool LLViewerTexture::isLargeImage()
{
return (S32)mTexelsPerImage > LLViewerTexture::sMinLargeImageSize;
@ -1077,10 +1060,6 @@ void LLViewerFetchedTexture::init(bool firstinit)
mIsFetched = false;
mInFastCacheList = false;
mCachedRawImage = NULL;
mCachedRawDiscardLevel = -1;
mCachedRawImageReady = false;
mSavedRawImage = NULL;
mForceToSaveRawImage = false;
mSaveRawImage = false;
@ -1138,9 +1117,6 @@ void LLViewerFetchedTexture::cleanup()
// Clean up image data
destroyRawImage();
mCachedRawImage = NULL;
mCachedRawDiscardLevel = -1;
mCachedRawImageReady = false;
mSavedRawImage = NULL;
mSavedRawDiscardLevel = -1;
}
@ -1220,13 +1196,17 @@ void LLViewerFetchedTexture::setForSculpt()
{
static const S32 MAX_INTERVAL = 8; //frames
forceToSaveRawImage(0, F32_MAX);
setBoostLevel(llmax((S32)getBoostLevel(),
(S32)LLGLTexture::BOOST_SCULPTED));
mForSculpt = true;
if(isForSculptOnly() && hasGLTexture() && !getBoundRecently())
{
destroyGLTexture(); //sculpt image does not need gl texture.
mTextureState = ACTIVE;
}
checkCachedRawSculptImage();
setMaxVirtualSizeResetInterval(MAX_INTERVAL);
}
@ -1339,10 +1319,6 @@ void LLViewerFetchedTexture::addToCreateTexture()
}
}
//discard the cached raw image and the saved raw image
mCachedRawImageReady = false;
mCachedRawDiscardLevel = -1;
mCachedRawImage = NULL;
mSavedRawDiscardLevel = -1;
mSavedRawImage = NULL;
}
@ -2043,13 +2019,6 @@ bool LLViewerFetchedTexture::updateFetch()
LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("vftuf - current < min");
make_request = false;
}
else if(mCachedRawImage.notNull() // can be empty
&& mCachedRawImageReady
&& (current_discard < 0 || current_discard > mCachedRawDiscardLevel))
{
make_request = false;
switchToCachedImage(); //use the cached raw data first
}
if (make_request)
{
@ -2542,20 +2511,6 @@ bool LLViewerFetchedTexture::doLoadedCallbacks()
}
}
//
// Do a readback if required, OR start off a texture decode
//
if (need_readback && (getMaxDiscardLevel() > gl_discard))
{
// Do a readback to get the GL data into the raw image
// We have GL data.
destroyRawImage();
reloadRawImage(mLoadedCallbackDesiredDiscardLevel);
llassert(mRawImage.notNull());
llassert(!mNeedsAux || mAuxRawImage.notNull());
}
//
// Run raw/auxiliary data callbacks
//
@ -2663,61 +2618,6 @@ void LLViewerFetchedTexture::forceImmediateUpdate()
return;
}
LLImageRaw* LLViewerFetchedTexture::reloadRawImage(S8 discard_level)
{
llassert(mGLTexturep.notNull());
llassert(discard_level >= 0);
llassert(mComponents > 0);
if (mRawImage.notNull())
{
//mRawImage is in use by somebody else, do not delete it.
return NULL;
}
if(mSavedRawDiscardLevel >= 0 && mSavedRawDiscardLevel <= discard_level)
{
if (mSavedRawDiscardLevel != discard_level
&& mBoostLevel != BOOST_ICON
&& mBoostLevel != BOOST_THUMBNAIL)
{
mRawImage = new LLImageRaw(getWidth(discard_level), getHeight(discard_level), getComponents());
mRawImage->copy(getSavedRawImage());
}
else
{
mRawImage = getSavedRawImage();
}
mRawDiscardLevel = discard_level;
}
else
{
//force to fetch raw image again if cached raw image is not good enough.
if(mCachedRawDiscardLevel > discard_level)
{
mRawImage = mCachedRawImage;
mRawDiscardLevel = mCachedRawDiscardLevel;
}
else //cached raw image is good enough, copy it.
{
if(mCachedRawDiscardLevel != discard_level)
{
mRawImage = new LLImageRaw(getWidth(discard_level), getHeight(discard_level), getComponents());
mRawImage->copy(mCachedRawImage);
}
else
{
mRawImage = mCachedRawImage;
}
mRawDiscardLevel = discard_level;
}
}
mIsRawImageValid = true;
sRawCount++;
return mRawImage;
}
bool LLViewerFetchedTexture::needsToSaveRawImage()
{
return mForceToSaveRawImage || mSaveRawImage;
@ -2742,7 +2642,6 @@ void LLViewerFetchedTexture::destroyRawImage()
{
saveRawImage();
}
setCachedRawImage();
}
mRawImage = NULL;
@ -2752,151 +2651,6 @@ void LLViewerFetchedTexture::destroyRawImage()
}
}
//use the mCachedRawImage to (re)generate the gl texture.
//virtual
void LLViewerFetchedTexture::switchToCachedImage()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
if(mCachedRawImage.notNull() &&
!mNeedsCreateTexture) // <--- texture creation is pending, don't step on it
{
mRawImage = mCachedRawImage;
if (getComponents() != mRawImage->getComponents())
{
// We've changed the number of components, so we need to move any
// objects using this pool to a different pool.
mComponents = mRawImage->getComponents();
mGLTexturep->setComponents(mComponents);
gTextureList.dirtyImage(this);
}
mIsRawImageValid = true;
mRawDiscardLevel = mCachedRawDiscardLevel;
scheduleCreateTexture();
}
}
//cache the imageraw forcefully.
//virtual
void LLViewerFetchedTexture::setCachedRawImage(S32 discard_level, LLImageRaw* imageraw)
{
if(imageraw != mRawImage.get())
{
if (mBoostLevel == LLGLTexture::BOOST_ICON)
{
S32 expected_width = mKnownDrawWidth > 0 ? mKnownDrawWidth : DEFAULT_ICON_DIMENSIONS;
S32 expected_height = mKnownDrawHeight > 0 ? mKnownDrawHeight : DEFAULT_ICON_DIMENSIONS;
if (mRawImage->getWidth() > expected_width || mRawImage->getHeight() > expected_height)
{
mCachedRawImage = new LLImageRaw(expected_width, expected_height, imageraw->getComponents());
mCachedRawImage->copyScaled(imageraw);
}
else
{
mCachedRawImage = imageraw;
}
}
else if (mBoostLevel == LLGLTexture::BOOST_THUMBNAIL)
{
S32 expected_width = mKnownDrawWidth > 0 ? mKnownDrawWidth : DEFAULT_THUMBNAIL_DIMENSIONS;
S32 expected_height = mKnownDrawHeight > 0 ? mKnownDrawHeight : DEFAULT_THUMBNAIL_DIMENSIONS;
if (mRawImage->getWidth() > expected_width || mRawImage->getHeight() > expected_height)
{
mCachedRawImage = new LLImageRaw(expected_width, expected_height, imageraw->getComponents());
mCachedRawImage->copyScaled(imageraw);
}
else
{
mCachedRawImage = imageraw;
}
}
else
{
mCachedRawImage = imageraw;
}
mCachedRawDiscardLevel = discard_level;
mCachedRawImageReady = true;
}
}
void LLViewerFetchedTexture::setCachedRawImage()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
if(mRawImage == mCachedRawImage)
{
return;
}
if(!mIsRawImageValid)
{
return;
}
if(mCachedRawImageReady)
{
return;
}
if(mCachedRawDiscardLevel < 0 || mCachedRawDiscardLevel > mRawDiscardLevel)
{
S32 i = 0;
S32 w = mRawImage->getWidth();
S32 h = mRawImage->getHeight();
S32 max_size = MAX_CACHED_RAW_IMAGE_AREA;
if(LLGLTexture::BOOST_TERRAIN == mBoostLevel)
{
max_size = MAX_CACHED_RAW_TERRAIN_IMAGE_AREA;
}
if(mForSculpt)
{
max_size = MAX_CACHED_RAW_SCULPT_IMAGE_AREA;
mCachedRawImageReady = !mRawDiscardLevel;
}
else
{
mCachedRawImageReady = (!mRawDiscardLevel || ((w * h) >= max_size));
}
while(((w >> i) * (h >> i)) > max_size)
{
++i;
}
if(i)
{
if(!(w >> i) || !(h >> i))
{
--i;
}
{
//make a duplicate in case somebody else is using this raw image
mRawImage = mRawImage->scaled(w >> i, h >> i);
}
}
mCachedRawImage = mRawImage;
mRawDiscardLevel += i;
mCachedRawDiscardLevel = mRawDiscardLevel;
}
}
void LLViewerFetchedTexture::checkCachedRawSculptImage()
{
if(mCachedRawImageReady && mCachedRawDiscardLevel > 0)
{
if(getDiscardLevel() != 0)
{
mCachedRawImageReady = false;
}
else if(isForSculptOnly())
{
resetTextureStats(); //do not update this image any more.
}
}
}
void LLViewerFetchedTexture::saveRawImage()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
@ -2936,6 +2690,20 @@ void LLViewerFetchedTexture::saveRawImage()
mSavedRawImage = new LLImageRaw(mRawImage->getData(), mRawImage->getWidth(), mRawImage->getHeight(), mRawImage->getComponents());
}
}
else if (mBoostLevel == LLGLTexture::BOOST_SCULPTED)
{
S32 expected_width = mKnownDrawWidth > 0 ? mKnownDrawWidth : sMaxSculptRez;
S32 expected_height = mKnownDrawHeight > 0 ? mKnownDrawHeight : sMaxSculptRez;
if (mRawImage->getWidth() > expected_width || mRawImage->getHeight() > expected_height)
{
mSavedRawImage = new LLImageRaw(expected_width, expected_height, mRawImage->getComponents());
mSavedRawImage->copyScaled(mRawImage);
}
else
{
mSavedRawImage = new LLImageRaw(mRawImage->getData(), mRawImage->getWidth(), mRawImage->getHeight(), mRawImage->getComponents());
}
}
else
{
mSavedRawImage = new LLImageRaw(mRawImage->getData(), mRawImage->getWidth(), mRawImage->getHeight(), mRawImage->getComponents());
@ -2981,20 +2749,23 @@ void LLViewerFetchedTexture::forceToSaveRawImage(S32 desired_discard, F32 kept_t
{
mForceToSaveRawImage = true;
mDesiredSavedRawDiscardLevel = desired_discard;
}
}
//copy from the cached raw image if exists.
if(mCachedRawImage.notNull() && mRawImage.isNull() )
void LLViewerFetchedTexture::readbackRawImage()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
if (mGLTexturep.notNull() && mGLTexturep->getTexName() != 0 && mRawImage.isNull())
{
mRawImage = new LLImageRaw();
if (!mGLTexturep->readBackRaw(-1, mRawImage, false))
{
mRawImage = mCachedRawImage;
mRawDiscardLevel = mCachedRawDiscardLevel;
saveRawImage();
mRawImage = NULL;
mRawDiscardLevel = INVALID_DISCARD_LEVEL;
mRawImage = nullptr;
}
}
}
void LLViewerFetchedTexture::destroySavedRawImage()
{
if(mLastReferencedSavedRawImageTime < mKeptSavedRawImageTime)
@ -3029,6 +2800,11 @@ LLImageRaw* LLViewerFetchedTexture::getSavedRawImage()
return mSavedRawImage;
}
const LLImageRaw* LLViewerFetchedTexture::getSavedRawImage() const
{
return mSavedRawImage;
}
bool LLViewerFetchedTexture::hasSavedRawImage() const
{
return mSavedRawImage.notNull();
@ -3205,20 +2981,14 @@ void LLViewerLODTexture::processTextureStats()
bool LLViewerLODTexture::scaleDown()
{
if(hasGLTexture() && mCachedRawDiscardLevel > getDiscardLevel())
if (mGLTexturep.isNull())
{
switchToCachedImage();
LLTexturePipelineTester* tester = (LLTexturePipelineTester*)LLMetricPerformanceTesterBasic::getTester(sTesterName);
if (tester)
{
tester->setStablizingTime();
}
return true;
return false;
}
return false;
return mGLTexturep->scaleDown(mDesiredDiscardLevel);
}
//----------------------------------------------------------------------------------------------
//end of LLViewerLODTexture
//----------------------------------------------------------------------------------------------

View File

@ -166,8 +166,6 @@ public:
S32 getNumVolumes(U32 channel) const;
const ll_volume_list_t* getVolumeList(U32 channel) const { return &mVolumeList[channel]; }
virtual void setCachedRawImage(S32 discard_level, LLImageRaw* imageraw) ;
bool isLargeImage() ;
void setParcelMedia(LLViewerMediaTexture* media) {mParcelMedia = media;}
@ -185,8 +183,6 @@ private:
friend class LLBumpImageList;
friend class LLUIImageList;
virtual void switchToCachedImage();
protected:
friend class LLViewerTextureList;
LLUUID mID;
@ -371,7 +367,6 @@ public:
U32 getFetchPriority() const { return mFetchPriority ;}
F32 getDownloadProgress() const {return mDownloadProgress ;}
LLImageRaw* reloadRawImage(S8 discard_level) ;
void destroyRawImage();
bool needsToSaveRawImage();
@ -390,17 +385,20 @@ public:
bool isForSculptOnly() const;
//raw image management
void checkCachedRawSculptImage() ;
LLImageRaw* getRawImage()const { return mRawImage ;}
S32 getRawImageLevel() const {return mRawDiscardLevel;}
LLImageRaw* getCachedRawImage() const { return mCachedRawImage ;}
S32 getCachedRawImageLevel() const {return mCachedRawDiscardLevel;}
bool isCachedRawImageReady() const {return mCachedRawImageReady ;}
bool isRawImageValid()const { return mIsRawImageValid ; }
void forceToSaveRawImage(S32 desired_discard = 0, F32 kept_time = 0.f) ;
/*virtual*/ void setCachedRawImage(S32 discard_level, LLImageRaw* imageraw) override;
// readback the raw image from OpenGL if mRawImage is not valid
void readbackRawImage();
void destroySavedRawImage() ;
LLImageRaw* getSavedRawImage() ;
S32 getSavedRawImageLevel() const {return mSavedRawDiscardLevel; }
const LLImageRaw* getSavedRawImage() const;
const LLImageRaw* getAuxRawImage() const { return mAuxRawImage; }
bool hasSavedRawImage() const ;
F32 getElapsedLastReferencedSavedRawImageTime() const ;
bool isFullyLoaded() const;
@ -417,7 +415,6 @@ public:
/*virtual*/bool isActiveFetching() override; //is actively in fetching by the fetching pipeline.
protected:
/*virtual*/ void switchToCachedImage() override;
S32 getCurrentDiscardLevelForFetching() ;
void forceToRefetchTexture(S32 desired_discard = 0, F32 kept_time = 60.f);
@ -426,7 +423,6 @@ private:
void cleanup() ;
void saveRawImage() ;
void setCachedRawImage() ;
//for atlas
void resetFaceAtlas() ;
@ -498,11 +494,6 @@ protected:
F32 mLastReferencedSavedRawImageTime ;
F32 mKeptSavedRawImageTime ;
//a small version of the copy of the raw image (<= 64 * 64)
LLPointer<LLImageRaw> mCachedRawImage;
S32 mCachedRawDiscardLevel;
bool mCachedRawImageReady; //the rez of the mCachedRawImage reaches the upper limit.
LLHost mTargetHost; // if invalid, just request from agent's simulator
// Timers

View File

@ -296,7 +296,7 @@ void LLViewerTextureList::shutdown()
// Write out list of currently loaded textures for precaching on startup
typedef std::set<std::pair<S32,LLViewerFetchedTexture*> > image_area_list_t;
image_area_list_t image_area_list;
for (image_priority_list_t::iterator iter = mImageList.begin();
for (image_list_t::iterator iter = mImageList.begin();
iter != mImageList.end(); ++iter)
{
LLViewerFetchedTexture* image = *iter;
@ -367,7 +367,7 @@ void LLViewerTextureList::dump()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
LL_INFOS() << "LLViewerTextureList::dump()" << LL_ENDL;
for (image_priority_list_t::iterator it = mImageList.begin(); it != mImageList.end(); ++it)
for (image_list_t::iterator it = mImageList.begin(); it != mImageList.end(); ++it)
{
LLViewerFetchedTexture* image = *it;
@ -381,15 +381,9 @@ void LLViewerTextureList::dump()
}
}
void LLViewerTextureList::destroyGL(bool save_state)
void LLViewerTextureList::destroyGL()
{
LLImageGL::destroyGL(save_state);
}
void LLViewerTextureList::restoreGL()
{
llassert_always(mInitialized) ;
LLImageGL::restoreGL();
LLImageGL::destroyGL();
}
/* Vertical tab container button image IDs
@ -895,7 +889,7 @@ void LLViewerTextureList::clearFetchingRequests()
LLAppViewer::getTextureFetch()->deleteAllRequests();
for (image_priority_list_t::iterator iter = mImageList.begin();
for (image_list_t::iterator iter = mImageList.begin();
iter != mImageList.end(); ++iter)
{
LLViewerFetchedTexture* imagep = *iter;
@ -1208,7 +1202,7 @@ void LLViewerTextureList::updateImagesUpdateStats()
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
if (mForceResetTextureStats)
{
for (image_priority_list_t::iterator iter = mImageList.begin();
for (image_list_t::iterator iter = mImageList.begin();
iter != mImageList.end(); )
{
LLViewerFetchedTexture* imagep = *iter++;
@ -1228,7 +1222,7 @@ void LLViewerTextureList::decodeAllImages(F32 max_time)
// Update texture stats and priorities
std::vector<LLPointer<LLViewerFetchedTexture> > image_list;
for (image_priority_list_t::iterator iter = mImageList.begin();
for (image_list_t::iterator iter = mImageList.begin();
iter != mImageList.end(); )
{
LLViewerFetchedTexture* imagep = *iter++;
@ -1248,7 +1242,7 @@ void LLViewerTextureList::decodeAllImages(F32 max_time)
image_list.clear();
// Update fetch (decode)
for (image_priority_list_t::iterator iter = mImageList.begin();
for (image_list_t::iterator iter = mImageList.begin();
iter != mImageList.end(); )
{
LLViewerFetchedTexture* imagep = *iter++;
@ -1275,7 +1269,7 @@ void LLViewerTextureList::decodeAllImages(F32 max_time)
}
}
// Update fetch again
for (image_priority_list_t::iterator iter = mImageList.begin();
for (image_list_t::iterator iter = mImageList.begin();
iter != mImageList.end(); )
{
LLViewerFetchedTexture* imagep = *iter++;

View File

@ -33,7 +33,7 @@
#include "llviewertexture.h"
#include "llui.h"
#include <list>
#include <set>
#include <unordered_set>
#include "lluiimage.h"
const U32 LL_IMAGE_REZ_LOSSLESS_CUTOFF = 128;
@ -115,8 +115,7 @@ public:
void init();
void shutdown();
void dump();
void destroyGL(bool save_state = true);
void restoreGL();
void destroyGL();
bool isInitialized() const {return mInitialized;}
void findTexturesByID(const LLUUID &image_id, std::vector<LLViewerFetchedTexture*> &output);
@ -188,7 +187,7 @@ private:
LLViewerTexture::EBoostLevel boost_priority = LLGLTexture::BOOST_NONE, // Get the requested level immediately upon creation.
S8 texture_type = LLViewerTexture::FETCHED_TEXTURE,
LLGLint internal_format = 0,
LLGLenum primary_format = 0,
LLGLenum primary_format = 0,
const LLUUID& force_id = LLUUID::null
);
@ -211,7 +210,7 @@ private:
{ return getImage(image_id, f_type, true, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, host); }
public:
typedef std::set<LLPointer<LLViewerFetchedTexture> > image_list_t;
typedef std::unordered_set<LLPointer<LLViewerFetchedTexture> > image_list_t;
image_list_t mLoadingStreamList;
image_list_t mCreateTextureList;
image_list_t mCallbackList;
@ -222,16 +221,19 @@ public:
bool mForceResetTextureStats;
// to make "for (auto& imagep : gTextureList)" work
const image_list_t::iterator begin() const { return mImageList.begin(); }
const image_list_t::iterator end() const { return mImageList.end(); }
private:
typedef std::map< LLTextureKey, LLPointer<LLViewerFetchedTexture> > uuid_map_t;
uuid_map_t mUUIDMap;
LLTextureKey mLastUpdateKey;
typedef std::set < LLPointer<LLViewerFetchedTexture> > image_priority_list_t;
image_priority_list_t mImageList;
image_list_t mImageList;
// simply holds on to LLViewerFetchedTexture references to stop them from being purged too soon
std::set<LLPointer<LLViewerFetchedTexture> > mImagePreloads;
std::unordered_set<LLPointer<LLViewerFetchedTexture> > mImagePreloads;
bool mInitialized ;
LLFrameTimer mForceDecodeTimer;

View File

@ -1827,10 +1827,8 @@ LLViewerWindow::LLViewerWindow(const Params& p)
mToolStored( NULL ),
mHideCursorPermanent( false ),
mCursorHidden(false),
mIgnoreActivate( false ),
mResDirty(false),
mStatesDirty(false),
mCurrResolutionIndex(0),
mProgressView(NULL)
{
// gKeyboard is still NULL, so it doesn't do LLWindowListener any good to
@ -2402,7 +2400,7 @@ void LLViewerWindow::shutdownGL()
LLSelectMgr::getInstance()->cleanup();
LL_INFOS() << "Stopping GL during shutdown" << LL_ENDL;
stopGL(false);
stopGL();
stop_glerror();
gGL.shutdown();
@ -5715,7 +5713,7 @@ void LLViewerWindow::dumpState()
<< LL_ENDL;
}
void LLViewerWindow::stopGL(bool save_state)
void LLViewerWindow::stopGL()
{
//Note: --bao
//if not necessary, do not change the order of the function calls in this function.
@ -5761,7 +5759,7 @@ void LLViewerWindow::stopGL(bool save_state)
gPostProcess->invalidate();
}
gTextureList.destroyGL(save_state);
gTextureList.destroyGL();
stop_glerror();
gGLManager.mIsDisabled = true;
@ -5778,6 +5776,14 @@ void LLViewerWindow::stopGL(bool save_state)
void LLViewerWindow::restoreGL(const std::string& progress_message)
{
llassert(false);
// DEPRECATED -- this is left over from when we would completely destroy and restore a GL context
// when switching from windowed to fullscreen. None of this machinery has been exercised in years
// and is unreliable. If we ever *do* have another use case where completely unloading and reloading
// everthing is necessary, requiring a viewer restart for that operation is a fine thing to do.
// -- davep
//Note: --bao
//if not necessary, do not change the order of the function calls in this function.
//if change something, make sure it will not break anything.
@ -5790,8 +5796,6 @@ void LLViewerWindow::restoreGL(const std::string& progress_message)
initGLDefaults();
LLGLState::restoreGL();
gTextureList.restoreGL();
// for future support of non-square pixels, and fonts that are properly stretched
//LLFontGL::destroyDefaultFonts();
initFonts();
@ -5867,122 +5871,6 @@ void LLViewerWindow::checkSettings()
}
}
void LLViewerWindow::restartDisplay(bool show_progress_bar)
{
LL_INFOS() << "Restaring GL" << LL_ENDL;
stopGL();
if (show_progress_bar)
{
restoreGL(LLTrans::getString("ProgressChangingResolution"));
}
else
{
restoreGL();
}
}
bool LLViewerWindow::changeDisplaySettings(LLCoordScreen size, bool enable_vsync, bool show_progress_bar)
{
//bool was_maximized = gSavedSettings.getBOOL("WindowMaximized");
//gResizeScreenTexture = true;
//U32 fsaa = gSavedSettings.getU32("RenderFSAASamples");
//U32 old_fsaa = mWindow->getFSAASamples();
// if not maximized, use the request size
if (!mWindow->getMaximized())
{
mWindow->setSize(size);
}
//if (fsaa == old_fsaa)
{
return true;
}
/*
// Close floaters that don't handle settings change
LLFloaterReg::hideInstance("snapshot");
bool result_first_try = false;
bool result_second_try = false;
LLFocusableElement* keyboard_focus = gFocusMgr.getKeyboardFocus();
send_agent_pause();
LL_INFOS() << "Stopping GL during changeDisplaySettings" << LL_ENDL;
stopGL();
mIgnoreActivate = true;
LLCoordScreen old_size;
LLCoordScreen old_pos;
mWindow->getSize(&old_size);
//mWindow->setFSAASamples(fsaa);
result_first_try = mWindow->switchContext(false, size, disable_vsync);
if (!result_first_try)
{
// try to switch back
//mWindow->setFSAASamples(old_fsaa);
result_second_try = mWindow->switchContext(false, old_size, disable_vsync);
if (!result_second_try)
{
// we are stuck...try once again with a minimal resolution?
send_agent_resume();
mIgnoreActivate = false;
return false;
}
}
send_agent_resume();
LL_INFOS() << "Restoring GL during resolution change" << LL_ENDL;
if (show_progress_bar)
{
restoreGL(LLTrans::getString("ProgressChangingResolution"));
}
else
{
restoreGL();
}
if (!result_first_try)
{
LLSD args;
args["RESX"] = llformat("%d",size.mX);
args["RESY"] = llformat("%d",size.mY);
LLNotificationsUtil::add("ResolutionSwitchFail", args);
size = old_size; // for reshape below
}
bool success = result_first_try || result_second_try;
if (success)
{
// maximize window if was maximized, else reposition
if (was_maximized)
{
mWindow->maximize();
}
else
{
S32 windowX = gSavedSettings.getS32("WindowX");
S32 windowY = gSavedSettings.getS32("WindowY");
mWindow->setPosition(LLCoordScreen ( windowX, windowY ) );
}
}
mIgnoreActivate = false;
gFocusMgr.setKeyboardFocus(keyboard_focus);
return success;
*/
}
F32 LLViewerWindow::getWorldViewAspectRatio() const
{
F32 world_aspect = (F32)mWorldViewRectRaw.getWidth() / (F32)mWorldViewRectRaw.getHeight();

View File

@ -455,9 +455,7 @@ public:
// handle shutting down GL and bringing it back up
void requestResolutionUpdate();
void checkSettings();
void restartDisplay(bool show_progress_bar);
bool changeDisplaySettings(LLCoordScreen size, bool enable_vsync, bool show_progress_bar);
bool getIgnoreDestroyWindow() { return mIgnoreActivate; }
F32 getWorldViewAspectRatio() const;
const LLVector2& getDisplayScale() const { return mDisplayScale; }
void calcDisplayScale();
@ -471,7 +469,7 @@ private:
void switchToolByMask(MASK mask);
void destroyWindow();
void drawMouselookInstructions();
void stopGL(bool save_state = true);
void stopGL();
void restoreGL(const std::string& progress_message = LLStringUtil::null);
void initFonts(F32 zoom_factor = 1.f);
void schedulePick(LLPickInfo& pick_info);
@ -528,8 +526,6 @@ private:
std::string mOverlayTitle; // Used for special titles such as "Second Life - Special E3 2003 Beta"
bool mIgnoreActivate;
std::string mInitAlert; // Window / GL initialization requires an alert
LLHandle<LLView> mWorldViewPlaceholder; // widget that spans the portion of screen dedicated to rendering the 3d world
@ -542,7 +538,6 @@ private:
bool mResDirty;
bool mStatesDirty;
U32 mCurrResolutionIndex;
std::unique_ptr<LLWindowListener> mWindowListener;
std::unique_ptr<LLViewerWindowListener> mViewerWindowListener;

View File

@ -317,7 +317,7 @@ bool LLTerrainMaterials::makeMaterialsReady(bool boost, bool strict)
// static
bool LLTerrainMaterials::makeTextureReady(LLPointer<LLViewerFetchedTexture>& tex, bool boost)
{
llassert(tex);
//llassert(tex); ??? maybe ok ???
if (!tex) { return false; }
if (tex->getDiscardLevel() < 0)
@ -571,416 +571,6 @@ bool LLVLComposition::generateComposition()
return LLTerrainMaterials::generateMaterials();
}
namespace
{
void prepare_fallback_image(LLImageRaw* raw_image)
{
raw_image->resize(BASE_SIZE, BASE_SIZE, 4);
raw_image->fill(LLColor4U::white);
}
// Check if the raw image is loaded for this texture at a discard
// level the minimap can use, and if not then try to get it loaded.
bool prepare_raw_image(LLPointer<LLImageRaw>& raw_image, bool emissive, LLViewerFetchedTexture* tex, bool& delete_raw_post)
{
if (!tex)
{
if (!emissive)
{
prepare_fallback_image(raw_image);
}
else
{
llassert(!raw_image);
raw_image = nullptr;
}
return true;
}
if (raw_image)
{
// Callback already initiated
if (raw_image->getDataSize() > 0)
{
// Callback finished
delete_raw_post = true;
return true;
}
else
{
return false;
}
}
raw_image = new LLImageRaw();
S32 ddiscard = 0;
{
S32 min_dim = llmin(tex->getFullWidth(), tex->getFullHeight());
while (min_dim > BASE_SIZE && ddiscard < MAX_DISCARD_LEVEL)
{
ddiscard++;
min_dim /= 2;
}
}
struct PendingImage
{
LLImageRaw* mRawImage;
S32 mDesiredDiscard;
LLUUID mTextureId;
PendingImage(LLImageRaw* raw_image, S32 ddiscard, const LLUUID& texture_id)
: mRawImage(raw_image)
, mDesiredDiscard(ddiscard)
, mTextureId(texture_id)
{
mRawImage->ref();
}
~PendingImage()
{
mRawImage->unref();
}
};
PendingImage* pending_image = new PendingImage(raw_image, ddiscard, tex->getID());
loaded_callback_func cb = [](bool success, LLViewerFetchedTexture * src_vi, LLImageRaw * src, LLImageRaw * src_aux, S32 discard_level, bool is_final, void* userdata) {
PendingImage* pending = (PendingImage*)userdata;
// Owning LLVLComposition still exists
// Assume mRawImage only used by single LLVLComposition for now
const bool in_use_by_composition = pending->mRawImage->getNumRefs() > 1;
llassert(pending->mRawImage->getNumRefs());
llassert(pending->mRawImage->getNumRefs() <= 2);
const bool needs_data = !pending->mRawImage->getDataSize();
if (in_use_by_composition && needs_data)
{
if (success && pending->mDesiredDiscard == discard_level)
{
pending->mRawImage->resize(BASE_SIZE, BASE_SIZE, src->getComponents());
pending->mRawImage->copyScaled(src);
}
else if (is_final)
{
prepare_fallback_image(pending->mRawImage);
}
}
if (is_final) { delete pending; }
};
tex->setLoadedCallback(cb, ddiscard, true, false, pending_image, nullptr);
tex->forceToSaveRawImage(ddiscard);
return false;
}
};
bool LLVLComposition::generateMinimapTileLand(const F32 x, const F32 y,
const F32 width, const F32 height)
{
LL_PROFILE_ZONE_SCOPED
llassert(mSurfacep);
llassert(x >= 0.f);
llassert(y >= 0.f);
///////////////////////////
//
// Generate raw data arrays for surface textures
//
//
// These have already been validated by generateComposition.
U8* st_data[ASSET_COUNT];
S32 st_data_size[ASSET_COUNT]; // for debugging
const bool use_textures = getMaterialType() != LLTerrainMaterials::Type::PBR;
if (use_textures)
{
if (!makeTexturesReady(true, true)) { return false; }
}
else
{
if (!makeMaterialsReady(true, true)) { return false; }
}
for (S32 i = 0; i < ASSET_COUNT; i++)
{
if (mRawImages[i].isNull())
{
// Read back a raw image for this discard level, if it exists
LLViewerFetchedTexture* tex;
LLViewerFetchedTexture* tex_emissive; // Can be null
bool has_base_color_factor;
bool has_emissive_factor;
bool has_alpha;
LLColor3 base_color_factor;
LLColor3 emissive_factor;
if (use_textures)
{
tex = mDetailTextures[i];
tex_emissive = nullptr;
has_base_color_factor = false;
has_emissive_factor = false;
has_alpha = false;
llassert(tex);
}
else
{
LLPointer<LLFetchedGLTFMaterial>& mat = mDetailRenderMaterials[i];
tex = mat->mBaseColorTexture;
tex_emissive = mat->mEmissiveTexture;
base_color_factor = LLColor3(mat->mBaseColor);
// *HACK: Treat alpha as black
base_color_factor *= (mat->mBaseColor.mV[VW]);
emissive_factor = mat->mEmissiveColor;
has_base_color_factor = (base_color_factor.mV[VX] != 1.f ||
base_color_factor.mV[VY] != 1.f ||
base_color_factor.mV[VZ] != 1.f);
has_emissive_factor = (emissive_factor.mV[VX] != 1.f ||
emissive_factor.mV[VY] != 1.f ||
emissive_factor.mV[VZ] != 1.f);
has_alpha = mat->mAlphaMode != LLGLTFMaterial::ALPHA_MODE_OPAQUE;
}
if (!tex) { tex = LLViewerFetchedTexture::sWhiteImagep; }
bool delete_raw_post = false;
bool delete_raw_post_emissive = false;
if (!prepare_raw_image(mRawImagesBaseColor[i], false, tex, delete_raw_post)) { return false; }
if (tex_emissive && !prepare_raw_image(mRawImagesEmissive[i], true, tex_emissive, delete_raw_post_emissive)) { return false; }
// tex_emissive can be null, and then will be ignored
// In the simplest case, the minimap image is just the base color.
// This will be replaced if we need to do any tinting/compositing.
mRawImages[i] = mRawImagesBaseColor[i];
// *TODO: This isn't quite right for PBR:
// 1) It does not convert the color images from SRGB to linear
// before mixing (which will always require copying the image).
// 2) It mixes emissive and base color before mixing terrain
// materials, but it should be the other way around
// Long-term, we should consider a method that is more
// maintainable. Shaders, perhaps? Bake shaders to textures?
LLPointer<LLImageRaw> raw_emissive;
if (tex_emissive)
{
raw_emissive = mRawImagesEmissive[i];
if (has_emissive_factor ||
tex_emissive->getWidth(tex_emissive->getRawImageLevel()) != BASE_SIZE ||
tex_emissive->getHeight(tex_emissive->getRawImageLevel()) != BASE_SIZE ||
tex_emissive->getComponents() != 4)
{
LLPointer<LLImageRaw> newraw_emissive = new LLImageRaw(BASE_SIZE, BASE_SIZE, 4);
// Copy RGB, leave alpha alone (set to opaque by default)
newraw_emissive->copy(mRawImagesEmissive[i]);
if (has_emissive_factor)
{
newraw_emissive->tint(emissive_factor);
}
raw_emissive = newraw_emissive;
}
}
if (has_base_color_factor ||
raw_emissive ||
has_alpha ||
tex->getWidth(tex->getRawImageLevel()) != BASE_SIZE ||
tex->getHeight(tex->getRawImageLevel()) != BASE_SIZE ||
tex->getComponents() != 3)
{
LLPointer<LLImageRaw> newraw = new LLImageRaw(BASE_SIZE, BASE_SIZE, 3);
if (has_alpha)
{
// Approximate the water underneath terrain alpha with solid water color
newraw->clear(
MAX_WATER_COLOR.mV[VX],
MAX_WATER_COLOR.mV[VY],
MAX_WATER_COLOR.mV[VZ],
255);
}
newraw->composite(mRawImagesBaseColor[i]);
if (has_base_color_factor)
{
newraw->tint(base_color_factor);
}
// Apply emissive texture
if (raw_emissive)
{
newraw->addEmissive(raw_emissive);
}
mRawImages[i] = newraw; // deletes old
}
if (delete_raw_post)
{
tex->destroyRawImage();
}
if (delete_raw_post_emissive)
{
tex_emissive->destroyRawImage();
}
// Remove intermediary image references
mRawImagesBaseColor[i] = nullptr;
mRawImagesEmissive[i] = nullptr;
}
st_data[i] = mRawImages[i]->getData();
st_data_size[i] = mRawImages[i]->getDataSize();
}
///////////////////////////////////////
//
// Generate and clamp x/y bounding box.
//
//
S32 x_begin, y_begin, x_end, y_end;
x_begin = (S32)(x * mScaleInv);
y_begin = (S32)(y * mScaleInv);
x_end = ll_round( (x + width) * mScaleInv );
y_end = ll_round( (y + width) * mScaleInv );
if (x_end > mWidth)
{
llassert(false);
x_end = mWidth;
}
if (y_end > mWidth)
{
llassert(false);
y_end = mWidth;
}
///////////////////////////////////////////
//
// Generate target texture information, stride ratios.
//
//
LLViewerTexture *texturep;
U32 tex_width, tex_height, tex_comps;
U32 tex_stride;
F32 tex_x_scalef, tex_y_scalef;
S32 tex_x_begin, tex_y_begin, tex_x_end, tex_y_end;
F32 tex_x_ratiof, tex_y_ratiof;
texturep = mSurfacep->getSTexture();
tex_width = texturep->getWidth();
tex_height = texturep->getHeight();
tex_comps = texturep->getComponents();
tex_stride = tex_width * tex_comps;
U32 st_comps = 3;
U32 st_width = BASE_SIZE;
U32 st_height = BASE_SIZE;
if (tex_comps != st_comps)
{
llassert(false);
return false;
}
tex_x_scalef = (F32)tex_width / (F32)mWidth;
tex_y_scalef = (F32)tex_height / (F32)mWidth;
tex_x_begin = (S32)((F32)x_begin * tex_x_scalef);
tex_y_begin = (S32)((F32)y_begin * tex_y_scalef);
tex_x_end = (S32)((F32)x_end * tex_x_scalef);
tex_y_end = (S32)((F32)y_end * tex_y_scalef);
tex_x_ratiof = (F32)mWidth*mScale / (F32)tex_width;
tex_y_ratiof = (F32)mWidth*mScale / (F32)tex_height;
LLPointer<LLImageRaw> raw = new LLImageRaw(tex_width, tex_height, tex_comps);
U8 *rawp = raw->getData();
F32 st_x_stride, st_y_stride;
st_x_stride = ((F32)st_width / (F32)mTexScaleX)*((F32)mWidth / (F32)tex_width);
st_y_stride = ((F32)st_height / (F32)mTexScaleY)*((F32)mWidth / (F32)tex_height);
llassert(st_x_stride > 0.f);
llassert(st_y_stride > 0.f);
////////////////////////////////
//
// Iterate through the target texture, striding through the
// subtextures and interpolating appropriately.
//
//
F32 sti, stj;
S32 st_offset;
sti = (tex_x_begin * st_x_stride) - st_width*(llfloor((tex_x_begin * st_x_stride)/st_width));
stj = (tex_y_begin * st_y_stride) - st_height*(llfloor((tex_y_begin * st_y_stride)/st_height));
st_offset = (llfloor(stj * st_width) + llfloor(sti)) * st_comps;
for (S32 j = tex_y_begin; j < tex_y_end; j++)
{
U32 offset = j * tex_stride + tex_x_begin * tex_comps;
sti = (tex_x_begin * st_x_stride) - st_width*((U32)(tex_x_begin * st_x_stride)/st_width);
for (S32 i = tex_x_begin; i < tex_x_end; i++)
{
S32 tex0, tex1;
F32 composition = getValueScaled(i*tex_x_ratiof, j*tex_y_ratiof);
tex0 = llfloor( composition );
tex0 = llclamp(tex0, 0, 3);
composition -= tex0;
tex1 = tex0 + 1;
tex1 = llclamp(tex1, 0, 3);
st_offset = (lltrunc(sti) + lltrunc(stj)*st_width) * st_comps;
for (U32 k = 0; k < tex_comps; k++)
{
// Linearly interpolate based on composition.
if (st_offset >= st_data_size[tex0] || st_offset >= st_data_size[tex1])
{
// SJB: This shouldn't be happening, but does... Rounding error?
//LL_WARNS() << "offset 0 [" << tex0 << "] =" << st_offset << " >= size=" << st_data_size[tex0] << LL_ENDL;
//LL_WARNS() << "offset 1 [" << tex1 << "] =" << st_offset << " >= size=" << st_data_size[tex1] << LL_ENDL;
}
else
{
F32 a = *(st_data[tex0] + st_offset);
F32 b = *(st_data[tex1] + st_offset);
rawp[ offset ] = (U8)lltrunc( a + composition * (b - a) );
}
offset++;
st_offset++;
}
sti += st_x_stride;
if (sti >= st_width)
{
sti -= st_width;
}
}
stj += st_y_stride;
if (stj >= st_height)
{
stj -= st_height;
}
}
if (!texturep->hasGLTexture())
{
texturep->createGLTexture(0, raw);
}
texturep->setSubImage(raw, tex_x_begin, tex_y_begin, tex_x_end - tex_x_begin, tex_y_end - tex_y_begin);
// Un-boost detail textures (will get re-boosted if rendering in high detail)
for (S32 i = 0; i < ASSET_COUNT; i++)
{
unboost_minimap_texture(mDetailTextures[i]);
}
// Un-boost textures for each detail material (will get re-boosted if rendering in high detail)
for (S32 i = 0; i < ASSET_COUNT; i++)
{
unboost_minimap_material(mDetailMaterials[i]);
}
return true;
}
F32 LLVLComposition::getStartHeight(S32 corner)
{
return mStartHeight[corner];

View File

@ -114,8 +114,6 @@ public:
// Viewer side hack to generate composition values
bool generateHeights(const F32 x, const F32 y, const F32 width, const F32 height);
bool generateComposition();
// Generate texture from composition values.
bool generateMinimapTileLand(const F32 x, const F32 y, const F32 width, const F32 height);
// Use these as indeces ito the get/setters below that use 'corner'
enum ECorner

View File

@ -851,19 +851,9 @@ void LLVOVolume::updateTextureVirtualSize(bool forced)
if (mSculptTexture.notNull())
{
mSculptTexture->setBoostLevel(llmax((S32)mSculptTexture->getBoostLevel(),
(S32)LLGLTexture::BOOST_SCULPTED));
mSculptTexture->setForSculpt() ;
if(!mSculptTexture->isCachedRawImageReady())
{
S32 lod = llmin(mLOD, 3);
F32 lodf = ((F32)(lod + 1.0f)/4.f);
F32 tex_size = lodf * LLViewerTexture::sMaxSculptRez ;
mSculptTexture->addTextureStats(2.f * tex_size * tex_size, false);
}
S32 texture_discard = mSculptTexture->getCachedRawImageLevel(); //try to match the texture
S32 texture_discard = mSculptTexture->getRawImageLevel(); //try to match the texture
S32 current_discard = getVolume() ? getVolume()->getSculptLevel() : -2 ;
if (texture_discard >= 0 && //texture has some data available
@ -1159,7 +1149,9 @@ void LLVOVolume::updateSculptTexture()
LLUUID id = sculpt_params->getSculptTexture();
if (id.notNull())
{
mSculptTexture = LLViewerTextureManager::getFetchedTexture(id, FTT_DEFAULT, true, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE);
mSculptTexture = LLViewerTextureManager::getFetchedTexture(id, FTT_DEFAULT, true, LLGLTexture::BOOST_SCULPTED, LLViewerTexture::LOD_TEXTURE);
mSculptTexture->forceToSaveRawImage(0, F32_MAX);
mSculptTexture->addTextureStats(256.f*256.f);
}
mSkinInfoUnavaliable = false;
@ -1252,8 +1244,22 @@ void LLVOVolume::sculpt()
S8 sculpt_components = 0;
const U8* sculpt_data = NULL;
S32 discard_level = mSculptTexture->getCachedRawImageLevel() ;
LLImageRaw* raw_image = mSculptTexture->getCachedRawImage() ;
S32 discard_level = mSculptTexture->getRawImageLevel() ;
LLImageRaw* raw_image = mSculptTexture->getRawImage() ;
if (!raw_image)
{
raw_image = mSculptTexture->getSavedRawImage();
S32 discard_level = mSculptTexture->getSavedRawImageLevel();
}
if (!raw_image)
{
// last resort, read back from GL
mSculptTexture->readbackRawImage();
raw_image = mSculptTexture->getRawImage();
discard_level = mSculptTexture->getRawImageLevel();
}
S32 max_discard = mSculptTexture->getMaxDiscardLevel();
if (discard_level > max_discard)
@ -1310,8 +1316,6 @@ void LLVOVolume::sculpt()
if(!raw_image)
{
llassert(discard_level < 0) ;
sculpt_width = 0;
sculpt_height = 0;
sculpt_data = NULL ;

View File

@ -59,7 +59,6 @@ LLVOWater::LLVOWater(const LLUUID &id,
mbCanSelect = false;
setScale(LLVector3(256.f, 256.f, 0.f)); // Hack for setting scale for bounding boxes/visibility.
mUseTexture = true;
mIsEdgePatch = false;
}
@ -101,14 +100,7 @@ LLDrawable *LLVOWater::createDrawable(LLPipeline *pipeline)
LLDrawPoolWater *pool = (LLDrawPoolWater*) gPipeline.getPool(LLDrawPool::POOL_WATER);
if (mUseTexture)
{
mDrawable->setNumFaces(1, pool, mRegionp->getLand().getWaterTexture());
}
else
{
mDrawable->setNumFaces(1, pool, LLWorld::getInstance()->getDefaultWaterTexture());
}
mDrawable->setNumFaces(1, pool, LLWorld::getInstance()->getDefaultWaterTexture());
return mDrawable;
}
@ -249,11 +241,6 @@ void setVecZ(LLVector3& v)
v.mV[VZ] = 1;
}
void LLVOWater::setUseTexture(const bool use_texture)
{
mUseTexture = use_texture;
}
void LLVOWater::setIsEdgePatch(const bool edge_patch)
{
mIsEdgePatch = edge_patch;

View File

@ -70,13 +70,10 @@ public:
/*virtual*/ bool isActive() const; // Whether this object needs to do an idleUpdate.
void setUseTexture(const bool use_texture);
void setIsEdgePatch(const bool edge_patch);
bool getUseTexture() const { return mUseTexture; }
bool getIsEdgePatch() const { return mIsEdgePatch; }
protected:
bool mUseTexture;
bool mIsEdgePatch;
S32 mRenderType;
};

View File

@ -961,7 +961,6 @@ void LLWorld::updateWaterObjects()
if (!getRegionFromHandle(region_handle))
{ // No region at that area, so make water
LLVOWater* waterp = (LLVOWater *)gObjectList.createObjectViewer(LLViewerObject::LL_VO_WATER, gAgent.getRegion());
waterp->setUseTexture(false);
waterp->setPositionGlobal(LLVector3d(x + rwidth/2,
y + rwidth/2,
256.f + water_height));
@ -1015,7 +1014,6 @@ void LLWorld::updateWaterObjects()
mEdgeWaterObjects[dir] = (LLVOWater *)gObjectList.createObjectViewer(LLViewerObject::LL_VO_VOID_WATER,
gAgent.getRegion());
waterp = mEdgeWaterObjects[dir];
waterp->setUseTexture(false);
waterp->setIsEdgePatch(true);
gPipeline.createObject(waterp);
}

View File

@ -178,6 +178,7 @@ LLPointer<LLViewerFetchedTexture> LLWorldMipmap::getObjectsTile(U32 grid_x, U32
}
}
//static
LLPointer<LLViewerFetchedTexture> LLWorldMipmap::loadObjectsTile(U32 grid_x, U32 grid_y, S32 level)
{
// Get the grid coordinates

View File

@ -74,11 +74,13 @@ public:
// Convert world coordinates to mipmap grid coordinates at a given level
static void globalToMipmap(F64 global_x, F64 global_y, S32 level, U32* grid_x, U32* grid_y);
// Load the relevant tile from S3
static LLPointer<LLViewerFetchedTexture> loadObjectsTile(U32 grid_x, U32 grid_y, S32 level);
private:
// Get a handle (key) from grid coordinates
U64 convertGridToHandle(U32 grid_x, U32 grid_y) { return to_region_handle(grid_x * REGION_WIDTH_UNITS, grid_y * REGION_WIDTH_UNITS); }
// Load the relevant tile from S3
LLPointer<LLViewerFetchedTexture> loadObjectsTile(U32 grid_x, U32 grid_y, S32 level);
// Clear a level from its "missing" tiles
void cleanMissedTilesFromLevel(S32 level);

View File

@ -1 +1 @@
d7915d67467e59287857630bd89bf9529d065199
d7915d67467e59287857630bd89bf9529d065199