From bc34217979c0a692b17de7ffcb524ed2418da967 Mon Sep 17 00:00:00 2001 From: Nicky Date: Wed, 26 Sep 2012 20:02:32 +0200 Subject: Add virtual destructor to LLGLFence. --- indra/llrender/llgl.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'indra/llrender') diff --git a/indra/llrender/llgl.h b/indra/llrender/llgl.h index 964495a3ab..d70e764769 100644 --- a/indra/llrender/llgl.h +++ b/indra/llrender/llgl.h @@ -424,6 +424,10 @@ const U32 FENCE_WAIT_TIME_NANOSECONDS = 1000; //1 ms class LLGLFence { public: + virtual ~LLGLFence() + { + } + virtual void placeFence() = 0; virtual bool isCompleted() = 0; virtual void wait() = 0; -- cgit v1.3 From 86e84ae75ef86417be32cff9a22a48fd7853758c Mon Sep 17 00:00:00 2001 From: Nicky Date: Sat, 1 Sep 2012 15:24:54 +0200 Subject: Crashfix; handle errors in release builds more gracefully. --- indra/llrender/llrendertarget.cpp | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) (limited to 'indra/llrender') diff --git a/indra/llrender/llrendertarget.cpp b/indra/llrender/llrendertarget.cpp index cc5c232380..846311a8d0 100644 --- a/indra/llrender/llrendertarget.cpp +++ b/indra/llrender/llrendertarget.cpp @@ -163,10 +163,19 @@ bool LLRenderTarget::addColorAttachment(U32 color_fmt) } U32 offset = mTex.size(); - if (offset >= 4 || - (offset > 0 && (mFBO == 0 || !gGLManager.mHasDrawBuffers))) + + if( offset >= 4 ) { - llerrs << "Too many color attachments!" << llendl; + llwarns << "Too many color attachments" << llendl; + llassert( offset < 4 ); + return false; + } + if( offset > 0 && (mFBO == 0 || !gGLManager.mHasDrawBuffers) ) + { + llwarns << "FBO not used or no drawbuffers available; mFBO=" << (U32)mFBO << " gGLManager.mHasDrawBuffers=" << (U32)gGLManager.mHasDrawBuffers << llendl; + llassert( mFBO != 0 ); + llassert( gGLManager.mHasDrawBuffers ); + return false; } U32 tex; -- cgit v1.3 From e0b334c6154e87729addfb01a52bd5b4c085bf44 Mon Sep 17 00:00:00 2001 From: Nicky Date: Sat, 21 Jul 2012 14:18:10 +0200 Subject: Crashfix; Change llassert_always to llassert + llwarns. This way users don't get disruptive crashes. --- indra/llrender/llvertexbuffer.cpp | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) (limited to 'indra/llrender') diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index eadef93c89..2fe0aa0b72 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -555,8 +555,21 @@ void LLVertexBuffer::drawArrays(U32 mode, const std::vector& pos, con gGL.syncMatrices(); U32 count = pos.size(); - llassert_always(norm.size() >= pos.size()); - llassert_always(count > 0); + + llassert(norm.size() >= pos.size()); + llassert(count > 0); + + if( count == 0 ) + { + llwarns << "Called drawArrays with 0 vertices" << llendl; + return; + } + + if( norm.size() < pos.size() ) + { + llwarns << "Called drawArrays with #" << norm.size() << " normals and #" << pos.size() << " vertices" << llendl; + return; + } unbind(); -- cgit v1.3 From 2eedd0c3c0fa8b4360c1402c1fb604010a4a2d82 Mon Sep 17 00:00:00 2001 From: callum Date: Fri, 15 Jun 2012 13:00:49 -0700 Subject: Merge with tip --- indra/llrender/llimagegl.cpp | 2 ++ indra/llrender/llrendertarget.cpp | 36 ++++++++++++++++++++++++++ indra/llrender/llrendertarget.h | 8 ++++-- indra/newview/lldrawable.cpp | 48 ++++++++++++++++++++++++++++++----- indra/newview/lldrawable.h | 2 +- indra/newview/lldrawpool.cpp | 42 ------------------------------ indra/newview/lldrawpool.h | 4 --- indra/newview/lldrawpoolterrain.cpp | 28 ++++++++++++++++++++ indra/newview/lldrawpoolterrain.h | 1 + indra/newview/lldrawpooltree.cpp | 15 +++++++++++ indra/newview/llface.cpp | 22 ++++++++++------ indra/newview/llfloaterland.cpp | 17 ++++++++----- indra/newview/llsidepaneliteminfo.cpp | 2 +- indra/newview/llspatialpartition.cpp | 17 ++++++++++--- indra/newview/llsurface.cpp | 6 +++++ indra/newview/llsurfacepatch.cpp | 14 ++++++---- indra/newview/llviewerdisplay.cpp | 32 ++++++++++++++++++----- indra/newview/llviewermessage.cpp | 2 ++ indra/newview/llviewerobjectlist.cpp | 39 +++++++++++++++++++++++----- indra/newview/llviewerregion.cpp | 3 ++- indra/newview/llviewerwindow.cpp | 3 +++ indra/newview/llvoavatar.cpp | 6 ++--- indra/newview/llvotree.cpp | 6 ++--- indra/newview/llvovolume.cpp | 17 ++++++++++--- indra/newview/llworld.cpp | 5 +++- 25 files changed, 273 insertions(+), 104 deletions(-) (limited to 'indra/llrender') diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index 793fd4be31..fb03b3f956 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -285,9 +285,11 @@ S32 LLImageGL::dataFormatComponents(S32 dataformat) //---------------------------------------------------------------------------- +static LLFastTimer::DeclareTimer FTM_IMAGE_UPDATE_STATS("Image Stats"); // static void LLImageGL::updateStats(F32 current_time) { + LLFastTimer t(FTM_IMAGE_UPDATE_STATS); sLastFrameTime = current_time; sBoundTextureMemoryInBytes = sCurBoundTextureMemory; sCurBoundTextureMemory = 0; diff --git a/indra/llrender/llrendertarget.cpp b/indra/llrender/llrendertarget.cpp index 99f0da330c..cc5c232380 100644 --- a/indra/llrender/llrendertarget.cpp +++ b/indra/llrender/llrendertarget.cpp @@ -69,6 +69,42 @@ LLRenderTarget::~LLRenderTarget() release(); } +void LLRenderTarget::resize(U32 resx, U32 resy, U32 color_fmt) +{ + //for accounting, get the number of pixels added/subtracted + S32 pix_diff = (resx*resy)-(mResX*mResY); + + mResX = resx; + mResY = resy; + + for (U32 i = 0; i < mTex.size(); ++i) + { //resize color attachments + gGL.getTexUnit(0)->bindManual(mUsage, mTex[i]); + LLImageGL::setManualImage(LLTexUnit::getInternalType(mUsage), 0, color_fmt, mResX, mResY, GL_RGBA, GL_UNSIGNED_BYTE, NULL, false); + sBytesAllocated += pix_diff*4; + } + + if (mDepth) + { //resize depth attachment + if (mStencil) + { + //use render buffers where stencil buffers are in play + glBindRenderbuffer(GL_RENDERBUFFER, mDepth); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, mResX, mResY); + glBindRenderbuffer(GL_RENDERBUFFER, 0); + } + else + { + gGL.getTexUnit(0)->bindManual(mUsage, mDepth); + U32 internal_type = LLTexUnit::getInternalType(mUsage); + LLImageGL::setManualImage(internal_type, 0, GL_DEPTH_COMPONENT24, mResX, mResY, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL, false); + } + + sBytesAllocated += pix_diff*4; + } +} + + bool LLRenderTarget::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil, LLTexUnit::eTextureType usage, bool use_fbo, S32 samples) { stop_glerror(); diff --git a/indra/llrender/llrendertarget.h b/indra/llrender/llrendertarget.h index 8360458840..e1a51304f1 100644 --- a/indra/llrender/llrendertarget.h +++ b/indra/llrender/llrendertarget.h @@ -57,8 +57,6 @@ */ -class LLMultisampleBuffer; - class LLRenderTarget { public: @@ -74,6 +72,12 @@ public: //multiple calls will release previously allocated resources bool allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil, LLTexUnit::eTextureType usage = LLTexUnit::TT_TEXTURE, bool use_fbo = false, S32 samples = 0); + //resize existing attachments to use new resolution and color format + // CAUTION: if the GL runs out of memory attempting to resize, this render target will be undefined + // DO NOT use for screen space buffers or for scratch space for an image that might be uploaded + // DO use for render targets that resize often and aren't likely to ruin someone's day if they break + void resize(U32 resx, U32 resy, U32 color_fmt); + //add color buffer attachment //limit of 4 color attachments per render target bool addColorAttachment(U32 color_fmt); diff --git a/indra/newview/lldrawable.cpp b/indra/newview/lldrawable.cpp index a42f4fcaa1..563b9b9cab 100644 --- a/indra/newview/lldrawable.cpp +++ b/indra/newview/lldrawable.cpp @@ -57,6 +57,8 @@ const F32 MIN_SHADOW_CASTER_RADIUS = 2.0f; static LLFastTimer::DeclareTimer FTM_CULL_REBOUND("Cull Rebound"); +extern bool gShiftFrame; + //////////////////////// // @@ -716,6 +718,11 @@ void LLDrawable::updateDistance(LLCamera& camera, bool force_update) return; } + if (gShiftFrame) + { + return; + } + //switch LOD with the spatial group to avoid artifacts //LLSpatialGroup* sg = getSpatialGroup(); @@ -825,14 +832,19 @@ void LLDrawable::shiftPos(const LLVector4a &shift_vector) mXform.setPosition(mVObjp->getPositionAgent()); } - mXform.setRotation(mVObjp->getRotation()); - mXform.setScale(1,1,1); mXform.updateMatrix(); if (isStatic()) { LLVOVolume* volume = getVOVolume(); - if (!volume) + + bool rebuild = (!volume && + getRenderType() != LLPipeline::RENDER_TYPE_TREE && + getRenderType() != LLPipeline::RENDER_TYPE_TERRAIN && + getRenderType() != LLPipeline::RENDER_TYPE_SKY && + getRenderType() != LLPipeline::RENDER_TYPE_GROUND); + + if (rebuild) { gPipeline.markRebuild(this, LLDrawable::REBUILD_ALL, TRUE); } @@ -846,7 +858,7 @@ void LLDrawable::shiftPos(const LLVector4a &shift_vector) facep->mExtents[0].add(shift_vector); facep->mExtents[1].add(shift_vector); - if (!volume && facep->hasGeometry()) + if (rebuild && facep->hasGeometry()) { facep->clearVertexBuffer(); } @@ -957,6 +969,12 @@ void LLDrawable::updateUVMinMax() { } +LLSpatialGroup* LLDrawable::getSpatialGroup() const +{ + llassert((mSpatialGroupp == NULL) ? getBinIndex() == -1 : getBinIndex() != -1); + return mSpatialGroupp; +} + void LLDrawable::setSpatialGroup(LLSpatialGroup *groupp) { /*if (mSpatialGroupp && (groupp != mSpatialGroupp)) @@ -979,6 +997,8 @@ void LLDrawable::setSpatialGroup(LLSpatialGroup *groupp) } mSpatialGroupp = groupp; + + llassert((mSpatialGroupp == NULL) ? getBinIndex() == -1 : getBinIndex() != -1); } LLSpatialPartition* LLDrawable::getSpatialPartition() @@ -1406,6 +1426,11 @@ void LLSpatialBridge::updateDistance(LLCamera& camera_in, bool force_update) markDead(); return; } + + if (gShiftFrame) + { + return; + } if (mDrawable->getVObj()) { @@ -1484,7 +1509,13 @@ void LLSpatialBridge::cleanupReferences() LLDrawable::cleanupReferences(); if (mDrawable) { - mDrawable->setSpatialGroup(NULL); + LLSpatialGroup* group = mDrawable->getSpatialGroup(); + if (group) + { + group->mOctreeNode->remove(mDrawable); + mDrawable->setSpatialGroup(NULL); + } + if (mDrawable->getVObj()) { LLViewerObject::const_child_list_t& child_list = mDrawable->getVObj()->getChildren(); @@ -1495,7 +1526,12 @@ void LLSpatialBridge::cleanupReferences() LLDrawable* drawable = child->mDrawable; if (drawable) { - drawable->setSpatialGroup(NULL); + LLSpatialGroup* group = drawable->getSpatialGroup(); + if (group) + { + group->mOctreeNode->remove(drawable); + drawable->setSpatialGroup(NULL); + } } } } diff --git a/indra/newview/lldrawable.h b/indra/newview/lldrawable.h index c01a8c3c29..bc4b301ebb 100644 --- a/indra/newview/lldrawable.h +++ b/indra/newview/lldrawable.h @@ -197,7 +197,7 @@ public: S32 findReferences(LLDrawable *drawablep); // Not const because of @#$! iterators... void setSpatialGroup(LLSpatialGroup *groupp); - LLSpatialGroup *getSpatialGroup() const { return mSpatialGroupp; } + LLSpatialGroup *getSpatialGroup() const; LLSpatialPartition* getSpatialPartition(); // Statics diff --git a/indra/newview/lldrawpool.cpp b/indra/newview/lldrawpool.cpp index 7c01a63b86..6c0be0a5c2 100644 --- a/indra/newview/lldrawpool.cpp +++ b/indra/newview/lldrawpool.cpp @@ -253,48 +253,6 @@ void LLFacePool::dirtyTextures(const std::set& textures { } -// static -S32 LLFacePool::drawLoop(face_array_t& face_list) -{ - S32 res = 0; - if (!face_list.empty()) - { - for (std::vector::iterator iter = face_list.begin(); - iter != face_list.end(); iter++) - { - LLFace *facep = *iter; - res += facep->renderIndexed(); - } - } - return res; -} - -// static -S32 LLFacePool::drawLoopSetTex(face_array_t& face_list, S32 stage) -{ - S32 res = 0; - if (!face_list.empty()) - { - for (std::vector::iterator iter = face_list.begin(); - iter != face_list.end(); iter++) - { - LLFace *facep = *iter; - gGL.getTexUnit(stage)->bind(facep->getTexture(), TRUE) ; - gGL.getTexUnit(0)->activate(); - res += facep->renderIndexed(); - } - } - return res; -} - -void LLFacePool::drawLoop() -{ - if (!mDrawFace.empty()) - { - drawLoop(mDrawFace); - } -} - void LLFacePool::enqueue(LLFace* facep) { mDrawFace.push_back(facep); diff --git a/indra/newview/lldrawpool.h b/indra/newview/lldrawpool.h index 64774d06df..e0f2da41d7 100644 --- a/indra/newview/lldrawpool.h +++ b/indra/newview/lldrawpool.h @@ -186,10 +186,6 @@ public: void buildEdges(); - static S32 drawLoop(face_array_t& face_list); - static S32 drawLoopSetTex(face_array_t& face_list, S32 stage); - void drawLoop(); - void addFaceReference(LLFace *facep); void removeFaceReference(LLFace *facep); diff --git a/indra/newview/lldrawpoolterrain.cpp b/indra/newview/lldrawpoolterrain.cpp index b95d8296fa..7fc78fb382 100644 --- a/indra/newview/lldrawpoolterrain.cpp +++ b/indra/newview/lldrawpoolterrain.cpp @@ -294,6 +294,34 @@ void LLDrawPoolTerrain::renderShadow(S32 pass) //glCullFace(GL_BACK); } + +void LLDrawPoolTerrain::drawLoop() +{ + if (!mDrawFace.empty()) + { + for (std::vector::iterator iter = mDrawFace.begin(); + iter != mDrawFace.end(); iter++) + { + LLFace *facep = *iter; + + LLMatrix4* model_matrix = &(facep->getDrawable()->getRegion()->mRenderMatrix); + + if (model_matrix != gGLLastMatrix) + { + gGLLastMatrix = model_matrix; + gGL.loadMatrix(gGLModelView); + if (model_matrix) + { + gGL.multMatrix((GLfloat*) model_matrix->mMatrix); + } + gPipeline.mMatrixOpCount++; + } + + facep->renderIndexed(); + } + } +} + void LLDrawPoolTerrain::renderFullShader() { // Hack! Get the region that this draw pool is rendering from! diff --git a/indra/newview/lldrawpoolterrain.h b/indra/newview/lldrawpoolterrain.h index 283ed87f1a..2163d087e1 100644 --- a/indra/newview/lldrawpoolterrain.h +++ b/indra/newview/lldrawpoolterrain.h @@ -83,6 +83,7 @@ protected: void renderFull2TU(); void renderFull4TU(); void renderFullShader(); + void drawLoop(); }; #endif // LL_LLDRAWPOOLSIMPLE_H diff --git a/indra/newview/lldrawpooltree.cpp b/indra/newview/lldrawpooltree.cpp index 3165a3516c..83f04e45a8 100644 --- a/indra/newview/lldrawpooltree.cpp +++ b/indra/newview/lldrawpooltree.cpp @@ -37,6 +37,7 @@ #include "llviewershadermgr.h" #include "llrender.h" #include "llviewercontrol.h" +#include "llviewerregion.h" S32 LLDrawPoolTree::sDiffTex = 0; static LLGLSLShader* shader = NULL; @@ -104,8 +105,22 @@ void LLDrawPoolTree::render(S32 pass) { LLFace *face = *iter; LLVertexBuffer* buff = face->getVertexBuffer(); + if(buff) { + LLMatrix4* model_matrix = &(face->getDrawable()->getRegion()->mRenderMatrix); + + if (model_matrix != gGLLastMatrix) + { + gGLLastMatrix = model_matrix; + gGL.loadMatrix(gGLModelView); + if (model_matrix) + { + gGL.multMatrix((GLfloat*) model_matrix->mMatrix); + } + gPipeline.mMatrixOpCount++; + } + buff->setBuffer(LLDrawPoolTree::VERTEX_DATA_MASK); buff->drawRange(LLRender::TRIANGLES, 0, buff->getNumVerts()-1, buff->getNumIndices(), 0); gPipeline.addTrianglesDrawn(buff->getNumIndices()); diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp index c1c68040cd..9acdee702b 100644 --- a/indra/newview/llface.cpp +++ b/indra/newview/llface.cpp @@ -1189,19 +1189,25 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, { if (num_indices + (S32) mIndicesIndex > mVertexBuffer->getNumIndices()) { - llwarns << "Index buffer overflow!" << llendl; - llwarns << "Indices Count: " << mIndicesCount - << " VF Num Indices: " << num_indices - << " Indices Index: " << mIndicesIndex - << " VB Num Indices: " << mVertexBuffer->getNumIndices() << llendl; - llwarns << " Face Index: " << f - << " Pool Type: " << mPoolType << llendl; + if (gDebugGL) + { + llwarns << "Index buffer overflow!" << llendl; + llwarns << "Indices Count: " << mIndicesCount + << " VF Num Indices: " << num_indices + << " Indices Index: " << mIndicesIndex + << " VB Num Indices: " << mVertexBuffer->getNumIndices() << llendl; + llwarns << " Face Index: " << f + << " Pool Type: " << mPoolType << llendl; + } return FALSE; } if (num_vertices + mGeomIndex > mVertexBuffer->getNumVerts()) { - llwarns << "Vertex buffer overflow!" << llendl; + if (gDebugGL) + { + llwarns << "Vertex buffer overflow!" << llendl; + } return FALSE; } } diff --git a/indra/newview/llfloaterland.cpp b/indra/newview/llfloaterland.cpp index 64684cef99..8f2b028a44 100644 --- a/indra/newview/llfloaterland.cpp +++ b/indra/newview/llfloaterland.cpp @@ -2227,8 +2227,8 @@ void LLPanelLandOptions::onCommitAny(LLUICtrl *ctrl, void *userdata) BOOL allow_damage = !self->mCheckSafe->get(); BOOL allow_fly = self->mCheckFly->get(); BOOL allow_landmark = TRUE; // cannot restrict landmark creation - BOOL allow_group_scripts = self->mCheckGroupScripts->get() || self->mCheckOtherScripts->get(); BOOL allow_other_scripts = self->mCheckOtherScripts->get(); + BOOL allow_group_scripts = self->mCheckGroupScripts->get() || allow_other_scripts; BOOL allow_publish = FALSE; BOOL mature_publish = self->mMatureCtrl->get(); BOOL push_restriction = self->mPushRestrictionCtrl->get(); @@ -2241,11 +2241,16 @@ void LLPanelLandOptions::onCommitAny(LLUICtrl *ctrl, void *userdata) LLViewerRegion* region; region = LLViewerParcelMgr::getInstance()->getSelectionRegion(); - if (!allow_other_scripts && region && region->getAllowDamage()) - { - - LLNotificationsUtil::add("UnableToDisableOutsideScripts"); - return; + if (region && region->getAllowDamage()) + { // Damage is allowed on the region - server will always allow scripts + if ( (!allow_other_scripts && parcel->getParcelFlag(PF_ALLOW_OTHER_SCRIPTS)) || + (!allow_group_scripts && parcel->getParcelFlag(PF_ALLOW_GROUP_SCRIPTS)) ) + { // Don't allow turning off "Run Scripts" if damage is allowed in the region + self->mCheckOtherScripts->set(parcel->getParcelFlag(PF_ALLOW_OTHER_SCRIPTS)); // Restore UI to actual settings + self->mCheckGroupScripts->set(parcel->getParcelFlag(PF_ALLOW_GROUP_SCRIPTS)); + LLNotificationsUtil::add("UnableToDisableOutsideScripts"); + return; + } } // Push data into current parcel diff --git a/indra/newview/llsidepaneliteminfo.cpp b/indra/newview/llsidepaneliteminfo.cpp index 1ce05da849..92c2863ffd 100644 --- a/indra/newview/llsidepaneliteminfo.cpp +++ b/indra/newview/llsidepaneliteminfo.cpp @@ -352,7 +352,7 @@ void LLSidepanelItemInfo::refreshFromItem(LLViewerInventoryItem* item) getChildView("BtnCreator")->setEnabled(FALSE); getChildView("LabelCreatorTitle")->setEnabled(FALSE); getChildView("LabelCreatorName")->setEnabled(FALSE); - getChild("LabelCreatorName")->setValue(getString("unknown")); + getChild("LabelCreatorName")->setValue(getString("unknown_multiple")); } //////////////// diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp index d995a1a5eb..d82b62dc19 100644 --- a/indra/newview/llspatialpartition.cpp +++ b/indra/newview/llspatialpartition.cpp @@ -68,6 +68,7 @@ const F32 SG_OCCLUSION_FUDGE = 0.25f; #define assert_states_valid(x) #endif +extern bool gShiftFrame; static U32 sZombieGroups = 0; U32 LLSpatialGroup::sNodeCount = 0; @@ -923,7 +924,10 @@ void LLSpatialGroup::shift(const LLVector4a &offset) mObjectExtents[0].add(offset); mObjectExtents[1].add(offset); - if (!mSpatialPartition->mRenderByGroup) + if (!mSpatialPartition->mRenderByGroup && + mSpatialPartition->mPartitionType != LLViewerRegion::PARTITION_TREE && + mSpatialPartition->mPartitionType != LLViewerRegion::PARTITION_TERRAIN && + mSpatialPartition->mPartitionType != LLViewerRegion::PARTITION_BRIDGE) { setState(GEOM_DIRTY); gPipeline.markRebuild(this, TRUE); @@ -1238,6 +1242,11 @@ void LLSpatialGroup::updateDistance(LLCamera &camera) return; } + if (gShiftFrame) + { + return; + } + #if !LL_RELEASE_FOR_DOWNLOAD if (isState(LLSpatialGroup::OBJECT_DIRTY)) { @@ -1838,12 +1847,14 @@ BOOL LLSpatialPartition::remove(LLDrawable *drawablep, LLSpatialGroup *curp) { LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); - drawablep->setSpatialGroup(NULL); - if (!curp->removeObject(drawablep)) { OCT_ERRS << "Failed to remove drawable from octree!" << llendl; } + else + { + drawablep->setSpatialGroup(NULL); + } assert_octree_valid(mOctree); diff --git a/indra/newview/llsurface.cpp b/indra/newview/llsurface.cpp index 54a259f725..230e871b49 100644 --- a/indra/newview/llsurface.cpp +++ b/indra/newview/llsurface.cpp @@ -56,6 +56,7 @@ #include "lldrawable.h" extern LLPipeline gPipeline; +extern bool gShiftFrame; LLColor4U MAX_WATER_COLOR(0, 48, 96, 240); @@ -608,6 +609,11 @@ void LLSurface::moveZ(const S32 x, const S32 y, const F32 delta) void LLSurface::updatePatchVisibilities(LLAgent &agent) { + if (gShiftFrame) + { + return; + } + LLVector3 pos_region = mRegionp->getPosRegionFromGlobal(gAgentCamera.getCameraPositionGlobal()); LLSurfacePatch *patchp; diff --git a/indra/newview/llsurfacepatch.cpp b/indra/newview/llsurfacepatch.cpp index 5077c2c7e1..a9ba2bce9c 100644 --- a/indra/newview/llsurfacepatch.cpp +++ b/indra/newview/llsurfacepatch.cpp @@ -43,6 +43,7 @@ #include "lldrawpool.h" #include "noise.h" +extern bool gShiftFrame; extern U64 gFrameTime; extern LLPipeline gPipeline; @@ -218,7 +219,7 @@ void LLSurfacePatch::eval(const U32 x, const U32 y, const U32 stride, LLVector3 pos_agent.mV[VX] += x * mSurfacep->getMetersPerGrid(); pos_agent.mV[VY] += y * mSurfacep->getMetersPerGrid(); pos_agent.mV[VZ] = *(mDataZ + point_offset); - *vertex = pos_agent; + *vertex = pos_agent-mVObjp->getRegion()->getOriginAgent(); LLVector3 rel_pos = pos_agent - mSurfacep->getOriginAgent(); LLVector3 tex_pos = rel_pos * (1.f/surface_stride); @@ -366,10 +367,13 @@ void LLSurfacePatch::updateCameraDistanceRegion(const LLVector3 &pos_region) { if (LLPipeline::sDynamicLOD) { - LLVector3 dv = pos_region; - dv -= mCenterRegion; - mVisInfo.mDistance = llmax(0.f, (F32)(dv.magVec() - mRadius))/ - llmax(LLVOSurfacePatch::sLODFactor, 0.1f); + if (!gShiftFrame) + { + LLVector3 dv = pos_region; + dv -= mCenterRegion; + mVisInfo.mDistance = llmax(0.f, (F32)(dv.magVec() - mRadius))/ + llmax(LLVOSurfacePatch::sLODFactor, 0.1f); + } } else { diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp index 000e7404e8..0ad2a6eb9b 100644 --- a/indra/newview/llviewerdisplay.cpp +++ b/indra/newview/llviewerdisplay.cpp @@ -79,6 +79,7 @@ #include "llpostprocess.h" extern LLPointer gStartTexture; +extern bool gShiftFrame; LLPointer gDisconnectedImagep = NULL; @@ -162,8 +163,11 @@ void display_startup() glClear(GL_DEPTH_BUFFER_BIT); } +static LLFastTimer::DeclareTimer FTM_UPDATE_CAMERA("Update Camera"); + void display_update_camera() { + LLFastTimer t(FTM_UPDATE_CAMERA); LLMemType mt_uc(LLMemType::MTYPE_DISPLAY_UPDATE_CAMERA); // TODO: cut draw distance down if customizing avatar? // TODO: cut draw distance on per-parcel basis? @@ -217,6 +221,11 @@ static LLFastTimer::DeclareTimer FTM_IMAGE_UPDATE_CLASS("Class"); static LLFastTimer::DeclareTimer FTM_IMAGE_UPDATE_BUMP("Bump"); static LLFastTimer::DeclareTimer FTM_IMAGE_UPDATE_LIST("List"); static LLFastTimer::DeclareTimer FTM_IMAGE_UPDATE_DELETE("Delete"); +static LLFastTimer::DeclareTimer FTM_RESIZE_WINDOW("Resize Window"); +static LLFastTimer::DeclareTimer FTM_HUD_UPDATE("HUD Update"); +static LLFastTimer::DeclareTimer FTM_DISPLAY_UPDATE_GEOM("Update Geom"); +static LLFastTimer::DeclareTimer FTM_TEXTURE_UNBIND("Texture Unbind"); +static LLFastTimer::DeclareTimer FTM_TELEPORT_DISPLAY("Teleport Display"); // Paint the display! void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) @@ -226,6 +235,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) if (gWindowResized) { //skip render on frames where window has been resized + LLFastTimer t(FTM_RESIZE_WINDOW); gGL.flush(); glClear(GL_COLOR_BUFFER_BIT); gViewerWindow->getWindow()->swapBuffers(); @@ -362,6 +372,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) if (gTeleportDisplay) { + LLFastTimer t(FTM_TELEPORT_DISPLAY); LLAppViewer::instance()->pingMainloopTimeout("Display:Teleport"); const F32 TELEPORT_ARRIVAL_DELAY = 2.f; // Time to preload the world before raising the curtain after we've actually already arrived. @@ -581,6 +592,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) // *TODO: merge these two methods { + LLFastTimer t(FTM_HUD_UPDATE); LLMemType mt_uh(LLMemType::MTYPE_DISPLAY_UPDATE_HUD); LLHUDManager::getInstance()->updateEffects(); LLHUDObject::updateAll(); @@ -588,6 +600,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) } { + LLFastTimer t(FTM_DISPLAY_UPDATE_GEOM); LLMemType mt_ug(LLMemType::MTYPE_DISPLAY_UPDATE_GEOM); const F32 max_geom_update_time = 0.005f*10.f*gFrameIntervalSeconds; // 50 ms/second update time gPipeline.createObjects(max_geom_update_time); @@ -597,6 +610,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) } gPipeline.updateGL(); + stop_glerror(); S32 water_clip = 0; @@ -928,14 +942,18 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) stop_glerror(); } - for (U32 i = 0; i < gGLManager.mNumTextureImageUnits; i++) - { //dummy cleanup of any currently bound textures - if (gGL.getTexUnit(i)->getCurrType() != LLTexUnit::TT_NONE) - { - gGL.getTexUnit(i)->unbind(gGL.getTexUnit(i)->getCurrType()); - gGL.getTexUnit(i)->disable(); + { + LLFastTimer t(FTM_TEXTURE_UNBIND); + for (U32 i = 0; i < gGLManager.mNumTextureImageUnits; i++) + { //dummy cleanup of any currently bound textures + if (gGL.getTexUnit(i)->getCurrType() != LLTexUnit::TT_NONE) + { + gGL.getTexUnit(i)->unbind(gGL.getTexUnit(i)->getCurrType()); + gGL.getTexUnit(i)->disable(); + } } } + LLAppViewer::instance()->pingMainloopTimeout("Display:RenderFlush"); if (to_texture) @@ -1001,6 +1019,8 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) display_stats(); LLAppViewer::instance()->pingMainloopTimeout("Display:Done"); + + gShiftFrame = false; } void render_hud_attachments() diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index d72f6cfb59..bc15d90520 100755 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -132,6 +132,7 @@ static const U32 LLREQUEST_PERMISSION_THROTTLE_LIMIT = 5; // requests static const F32 LLREQUEST_PERMISSION_THROTTLE_INTERVAL = 10.0f; // seconds extern BOOL gDebugClicks; +extern bool gShiftFrame; // function prototypes bool check_offer_throttle(const std::string& from_name, bool check_only); @@ -3736,6 +3737,7 @@ void process_avatar_init_complete(LLMessageSystem* msg, void**) void process_agent_movement_complete(LLMessageSystem* msg, void**) { + gShiftFrame = true; gAgentMovementCompleted = true; LLUUID agent_id; diff --git a/indra/newview/llviewerobjectlist.cpp b/indra/newview/llviewerobjectlist.cpp index 4a06685994..383d4a7955 100644 --- a/indra/newview/llviewerobjectlist.cpp +++ b/indra/newview/llviewerobjectlist.cpp @@ -1438,12 +1438,24 @@ void LLViewerObjectList::updateActive(LLViewerObject *objectp) if (active) { //llinfos << "Adding " << objectp->mID << " " << objectp->getPCodeString() << " to active list." << llendl; - llassert(objectp->getListIndex() == -1); - - mActiveObjects.push_back(objectp); - objectp->setListIndex(mActiveObjects.size()-1); + S32 idx = objectp->getListIndex(); + if (idx <= -1) + { + mActiveObjects.push_back(objectp); + objectp->setListIndex(mActiveObjects.size()-1); + objectp->setOnActiveList(TRUE); + } + else + { + llassert(idx < mActiveObjects.size()); + llassert(mActiveObjects[idx] == objectp); - objectp->setOnActiveList(TRUE); + if (idx >= mActiveObjects.size() || + mActiveObjects[idx] != objectp) + { + llwarns << "Invalid object list index detected!" << llendl; + } + } } else { @@ -1522,6 +1534,10 @@ void LLViewerObjectList::onPhysicsFlagsFetchFailure(const LLUUID& object_id) mPendingPhysicsFlags.erase(object_id); } +static LLFastTimer::DeclareTimer FTM_SHIFT_OBJECTS("Shift Objects"); +static LLFastTimer::DeclareTimer FTM_PIPELINE_SHIFT("Pipeline Shift"); +static LLFastTimer::DeclareTimer FTM_REGION_SHIFT("Region Shift"); + void LLViewerObjectList::shiftObjects(const LLVector3 &offset) { // This is called when we shift our origin when we cross region boundaries... @@ -1533,6 +1549,8 @@ void LLViewerObjectList::shiftObjects(const LLVector3 &offset) return; } + LLFastTimer t(FTM_SHIFT_OBJECTS); + LLViewerObject *objectp; for (vobj_list_t::iterator iter = mObjects.begin(); iter != mObjects.end(); ++iter) { @@ -1549,8 +1567,15 @@ void LLViewerObjectList::shiftObjects(const LLVector3 &offset) } } - gPipeline.shiftObjects(offset); - LLWorld::getInstance()->shiftRegions(offset); + { + LLFastTimer t(FTM_PIPELINE_SHIFT); + gPipeline.shiftObjects(offset); + } + + { + LLFastTimer t(FTM_REGION_SHIFT); + LLWorld::getInstance()->shiftRegions(offset); + } } void LLViewerObjectList::repartitionObjects() diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index e3cb985ddb..e4108e2cd1 100644 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -1461,7 +1461,8 @@ void LLViewerRegion::unpackRegionHandshake() // all of our terrain stuff, by if (compp->getParamsReady()) { - getLand().dirtyAllPatches(); + //this line creates frame stalls on region crossing and removing it appears to have no effect + //getLand().dirtyAllPatches(); } else { diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index ca5523dfbd..c5cbc307ed 100755 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -4757,8 +4757,11 @@ void LLViewerWindow::requestResolutionUpdate() mResDirty = true; } +static LLFastTimer::DeclareTimer FTM_WINDOW_CHECK_SETTINGS("Window Settings"); + void LLViewerWindow::checkSettings() { + LLFastTimer t(FTM_WINDOW_CHECK_SETTINGS); if (mStatesDirty) { gGL.refreshState(); diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 414ddc0c24..73c57adedd 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -1370,8 +1370,6 @@ void LLVOAvatar::onShift(const LLVector4a& shift_vector) const LLVector3& shift = reinterpret_cast(shift_vector); mLastAnimExtents[0] += shift; mLastAnimExtents[1] += shift; - mNeedsImpostorUpdate = TRUE; - mNeedsAnimUpdate = TRUE; } void LLVOAvatar::updateSpatialExtents(LLVector4a& newMin, LLVector4a &newMax) @@ -5066,9 +5064,9 @@ LLJoint *LLVOAvatar::getJoint( const std::string &name ) LLJoint* jointp = NULL; - if (iter == mJointMap.end()) + if (iter == mJointMap.end() || iter->second == NULL) { //search for joint and cache found joint in lookup table - LLJoint* jointp = mRoot.findJoint(name); + jointp = mRoot.findJoint(name); mJointMap[name] = jointp; } else diff --git a/indra/newview/llvotree.cpp b/indra/newview/llvotree.cpp index 3556bde9a8..337ddfb24d 100644 --- a/indra/newview/llvotree.cpp +++ b/indra/newview/llvotree.cpp @@ -374,7 +374,7 @@ BOOL LLVOTree::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) // *TODO: I don't know what's so special about trees // that they don't get REBUILD_POSITION automatically // at a higher level. - const LLVector3 &this_position = getPositionAgent(); + const LLVector3 &this_position = getPositionRegion(); if (this_position != mLastPosition) { gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_POSITION); @@ -843,10 +843,10 @@ void LLVOTree::updateMesh() LLMatrix4 matrix; // Translate to tree base HACK - adjustment in Z plants tree underground - const LLVector3 &pos_agent = getPositionAgent(); + const LLVector3 &pos_region = getPositionRegion(); //gGL.translatef(pos_agent.mV[VX], pos_agent.mV[VY], pos_agent.mV[VZ] - 0.1f); LLMatrix4 trans_mat; - trans_mat.setTranslation(pos_agent.mV[VX], pos_agent.mV[VY], pos_agent.mV[VZ] - 0.1f); + trans_mat.setTranslation(pos_region.mV[VX], pos_region.mV[VY], pos_region.mV[VZ] - 0.1f); trans_mat *= matrix; // Rotate to tree position and bend for current trunk/wind diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index d66c47787e..082818b112 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -4702,8 +4702,14 @@ void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group) if (buff) { llassert(!face->isState(LLFace::RIGGED)); - face->getGeometryVolume(*volume, face->getTEOffset(), - vobj->getRelativeXform(), vobj->getRelativeXformInvTrans(), face->getGeomIndex()); + + if (!face->getGeometryVolume(*volume, face->getTEOffset(), + vobj->getRelativeXform(), vobj->getRelativeXformInvTrans(), face->getGeomIndex())) + { //something's gone wrong with the vertex buffer accounting, rebuild this group + group->dirtyGeom(); + gPipeline.markRebuild(group, TRUE); + } + if (buff->isLocked()) { @@ -5037,8 +5043,11 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std:: llassert(!facep->isState(LLFace::RIGGED)); - facep->getGeometryVolume(*volume, te_idx, - vobj->getRelativeXform(), vobj->getRelativeXformInvTrans(), index_offset,true); + if (!facep->getGeometryVolume(*volume, te_idx, + vobj->getRelativeXform(), vobj->getRelativeXformInvTrans(), index_offset,true)) + { + llwarns << "Failed to get geometry for face!" << llendl; + } if (drawablep->isState(LLDrawable::ANIMATED_CHILD)) { diff --git a/indra/newview/llworld.cpp b/indra/newview/llworld.cpp index 14867db182..03fef07c11 100644 --- a/indra/newview/llworld.cpp +++ b/indra/newview/llworld.cpp @@ -657,7 +657,10 @@ void LLWorld::updateRegions(F32 max_update_time) if (did_one && max_time <= 0.f) break; max_time = llmin(max_time, max_update_time*.1f); - did_one |= regionp->idleUpdate(max_update_time); + if (regionp->idleUpdate(max_update_time)) + { + did_one = TRUE; + } } } -- cgit v1.3 From 28ccf4190e83670af2f03015ac16db6b9c76c805 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Fri, 22 Jun 2012 17:31:46 -0500 Subject: MAINT-653 Fix for shadow acne at high altitudes --- indra/llrender/llshadermgr.cpp | 2 +- indra/newview/app_settings/settings.xml | 2 +- .../shaders/class2/deferred/alphaF.glsl | 37 ++++++++-------- .../shaders/class2/deferred/alphaNonIndexedF.glsl | 36 ++++++++-------- .../class2/deferred/alphaNonIndexedNoColorF.glsl | 39 +++++++++-------- .../shaders/class2/deferred/sunLightF.glsl | 45 ++++++++++---------- .../shaders/class2/deferred/sunLightSSAOF.glsl | 49 +++++++++++----------- indra/newview/pipeline.cpp | 21 +++++----- 8 files changed, 113 insertions(+), 118 deletions(-) (limited to 'indra/llrender') diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp index bf917d4474..e828b7c4e8 100644 --- a/indra/llrender/llshadermgr.cpp +++ b/indra/llrender/llshadermgr.cpp @@ -643,7 +643,7 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade text[count++] = strdup("#define textureCube texture\n"); text[count++] = strdup("#define texture2DLod textureLod\n"); text[count++] = strdup("#define shadow2D(a,b) vec2(texture(a,b))\n"); - + if (major_version > 1 || minor_version >= 40) { //GLSL 1.40 replaces texture2DRect et al with texture text[count++] = strdup("#define texture2DRect texture\n"); diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index b7b040f98b..ea54f4b881 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -8068,7 +8068,7 @@ Type F32 Value - 0 + -0.007 RenderShadowOffsetError diff --git a/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl b/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl index 08f6ec63fe..99bf03ceca 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl @@ -34,10 +34,10 @@ out vec4 frag_color; VARYING vec4 vertex_color; VARYING vec2 vary_texcoord0; -uniform sampler2DRectShadow shadowMap0; -uniform sampler2DRectShadow shadowMap1; -uniform sampler2DRectShadow shadowMap2; -uniform sampler2DRectShadow shadowMap3; +uniform sampler2DShadow shadowMap0; +uniform sampler2DShadow shadowMap1; +uniform sampler2DShadow shadowMap2; +uniform sampler2DShadow shadowMap3; uniform sampler2DRect depthMap; uniform mat4 shadow_matrix[6]; @@ -58,18 +58,21 @@ uniform float shadow_bias; uniform mat4 inv_proj; -float pcfShadow(sampler2DRectShadow shadowMap, vec4 stc, float scl) +float pcfShadow(sampler2DShadow shadowMap, vec4 stc, float scl) { stc.xyz /= stc.w; stc.z += shadow_bias; - - float cs = shadow2DRect(shadowMap, stc.xyz).x; + + float cs = shadow2D(shadowMap, stc.xyz).x; float shadow = cs; - shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(scl, scl, 0.0)).x, cs); - shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(scl, -scl, 0.0)).x, cs); - shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(-scl, scl, 0.0)).x, cs); - shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(-scl, -scl, 0.0)).x, cs); + + vec2 off = scl/shadow_res; + + shadow += max(shadow2D(shadowMap, stc.xyz+vec3(off.x, off.y, 0.0)).x, cs); + shadow += max(shadow2D(shadowMap, stc.xyz+vec3(off.x, -off.y, 0.0)).x, cs); + shadow += max(shadow2D(shadowMap, stc.xyz+vec3(-off.x, off.y, 0.0)).x, cs); + shadow += max(shadow2D(shadowMap, stc.xyz+vec3(-off.x, -off.y, 0.0)).x, cs); return shadow/5.0; } @@ -97,8 +100,7 @@ void main() if (spos.z < near_split.z) { lpos = shadow_matrix[3]*spos; - lpos.xy *= shadow_res; - + float w = 1.0; w -= max(spos.z-far_split.z, 0.0)/transition_domain.z; shadow += pcfShadow(shadowMap3, lpos, 0.25)*w; @@ -109,8 +111,7 @@ void main() if (spos.z < near_split.y && spos.z > far_split.z) { lpos = shadow_matrix[2]*spos; - lpos.xy *= shadow_res; - + float w = 1.0; w -= max(spos.z-far_split.y, 0.0)/transition_domain.y; w -= max(near_split.z-spos.z, 0.0)/transition_domain.z; @@ -121,8 +122,7 @@ void main() if (spos.z < near_split.x && spos.z > far_split.y) { lpos = shadow_matrix[1]*spos; - lpos.xy *= shadow_res; - + float w = 1.0; w -= max(spos.z-far_split.x, 0.0)/transition_domain.x; w -= max(near_split.y-spos.z, 0.0)/transition_domain.y; @@ -133,8 +133,7 @@ void main() if (spos.z > far_split.x) { lpos = shadow_matrix[0]*spos; - lpos.xy *= shadow_res; - + float w = 1.0; w -= max(near_split.x-spos.z, 0.0)/transition_domain.x; diff --git a/indra/newview/app_settings/shaders/class2/deferred/alphaNonIndexedF.glsl b/indra/newview/app_settings/shaders/class2/deferred/alphaNonIndexedF.glsl index aae6a070e2..4f6a88961b 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/alphaNonIndexedF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/alphaNonIndexedF.glsl @@ -31,17 +31,16 @@ out vec4 frag_color; #define frag_color gl_FragColor #endif -uniform sampler2DRectShadow shadowMap0; -uniform sampler2DRectShadow shadowMap1; -uniform sampler2DRectShadow shadowMap2; -uniform sampler2DRectShadow shadowMap3; +uniform sampler2DShadow shadowMap0; +uniform sampler2DShadow shadowMap1; +uniform sampler2DShadow shadowMap2; +uniform sampler2DShadow shadowMap3; uniform sampler2DRect depthMap; uniform sampler2D diffuseMap; uniform mat4 shadow_matrix[6]; uniform vec4 shadow_clip; uniform vec2 screen_res; -uniform vec2 shadow_res; vec3 atmosLighting(vec3 light); vec3 scaleSoftClip(vec3 light); @@ -54,6 +53,7 @@ VARYING vec3 vary_pointlight_col; VARYING vec2 vary_texcoord0; VARYING vec4 vertex_color; +uniform vec2 shadow_res; uniform float shadow_bias; uniform mat4 inv_proj; @@ -71,18 +71,20 @@ vec4 getPosition(vec2 pos_screen) return pos; } -float pcfShadow(sampler2DRectShadow shadowMap, vec4 stc, float scl) +float pcfShadow(sampler2DShadow shadowMap, vec4 stc, float scl) { stc.xyz /= stc.w; stc.z += shadow_bias; - + float cs = shadow2DRect(shadowMap, stc.xyz).x; float shadow = cs; + + vec2 off = scl/shadow_res; - shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(scl, scl, 0.0)).x, cs); - shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(scl, -scl, 0.0)).x, cs); - shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(-scl, scl, 0.0)).x, cs); - shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(-scl, -scl, 0.0)).x, cs); + shadow += max(shadow2D(shadowMap, stc.xyz+vec3(off.x, off.y, 0.0)).x, cs); + shadow += max(shadow2D(shadowMap, stc.xyz+vec3(off.x, -off.y, 0.0)).x, cs); + shadow += max(shadow2D(shadowMap, stc.xyz+vec3(-off.x, off.y, 0.0)).x, cs); + shadow += max(shadow2D(shadowMap, stc.xyz+vec3(-off.x, -off.y, 0.0)).x, cs); return shadow/5.0; } @@ -110,8 +112,7 @@ void main() if (spos.z < near_split.z) { lpos = shadow_matrix[3]*spos; - lpos.xy *= shadow_res; - + float w = 1.0; w -= max(spos.z-far_split.z, 0.0)/transition_domain.z; shadow += pcfShadow(shadowMap3, lpos, 0.25)*w; @@ -122,8 +123,7 @@ void main() if (spos.z < near_split.y && spos.z > far_split.z) { lpos = shadow_matrix[2]*spos; - lpos.xy *= shadow_res; - + float w = 1.0; w -= max(spos.z-far_split.y, 0.0)/transition_domain.y; w -= max(near_split.z-spos.z, 0.0)/transition_domain.z; @@ -134,8 +134,7 @@ void main() if (spos.z < near_split.x && spos.z > far_split.y) { lpos = shadow_matrix[1]*spos; - lpos.xy *= shadow_res; - + float w = 1.0; w -= max(spos.z-far_split.x, 0.0)/transition_domain.x; w -= max(near_split.y-spos.z, 0.0)/transition_domain.y; @@ -146,8 +145,7 @@ void main() if (spos.z > far_split.x) { lpos = shadow_matrix[0]*spos; - lpos.xy *= shadow_res; - + float w = 1.0; w -= max(near_split.x-spos.z, 0.0)/transition_domain.x; diff --git a/indra/newview/app_settings/shaders/class2/deferred/alphaNonIndexedNoColorF.glsl b/indra/newview/app_settings/shaders/class2/deferred/alphaNonIndexedNoColorF.glsl index d6848c8dc1..90cd0f8602 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/alphaNonIndexedNoColorF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/alphaNonIndexedNoColorF.glsl @@ -33,17 +33,16 @@ out vec4 frag_color; uniform float minimum_alpha; -uniform sampler2DRectShadow shadowMap0; -uniform sampler2DRectShadow shadowMap1; -uniform sampler2DRectShadow shadowMap2; -uniform sampler2DRectShadow shadowMap3; +uniform sampler2DShadow shadowMap0; +uniform sampler2DShadow shadowMap1; +uniform sampler2DShadow shadowMap2; +uniform sampler2DShadow shadowMap3; uniform sampler2DRect depthMap; uniform sampler2D diffuseMap; uniform mat4 shadow_matrix[6]; uniform vec4 shadow_clip; uniform vec2 screen_res; -uniform vec2 shadow_res; vec3 atmosLighting(vec3 light); vec3 scaleSoftClip(vec3 light); @@ -55,6 +54,8 @@ VARYING vec3 vary_position; VARYING vec3 vary_pointlight_col; VARYING vec2 vary_texcoord0; +uniform vec2 shadow_res; + uniform float shadow_bias; uniform mat4 inv_proj; @@ -72,18 +73,20 @@ vec4 getPosition(vec2 pos_screen) return pos; } -float pcfShadow(sampler2DRectShadow shadowMap, vec4 stc, float scl) +float pcfShadow(sampler2DShadow shadowMap, vec4 stc, float scl) { stc.xyz /= stc.w; stc.z += shadow_bias; - - float cs = shadow2DRect(shadowMap, stc.xyz).x; + + float cs = shadow2D(shadowMap, stc.xyz).x; float shadow = cs; - shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(scl, scl, 0.0)).x, cs); - shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(scl, -scl, 0.0)).x, cs); - shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(-scl, scl, 0.0)).x, cs); - shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(-scl, -scl, 0.0)).x, cs); + vec2 off = scl/shadow_res; + + shadow += max(shadow2D(shadowMap, stc.xyz+vec3(off.x, off.y, 0.0)).x, cs); + shadow += max(shadow2D(shadowMap, stc.xyz+vec3(off.x, -off.y, 0.0)).x, cs); + shadow += max(shadow2D(shadowMap, stc.xyz+vec3(-off.x, off.y, 0.0)).x, cs); + shadow += max(shadow2D(shadowMap, stc.xyz+vec3(-off.x, -off.y, 0.0)).x, cs); return shadow/5.0; } @@ -118,8 +121,7 @@ void main() if (spos.z < near_split.z) { lpos = shadow_matrix[3]*spos; - lpos.xy *= shadow_res; - + float w = 1.0; w -= max(spos.z-far_split.z, 0.0)/transition_domain.z; shadow += pcfShadow(shadowMap3, lpos, 0.25)*w; @@ -130,8 +132,7 @@ void main() if (spos.z < near_split.y && spos.z > far_split.z) { lpos = shadow_matrix[2]*spos; - lpos.xy *= shadow_res; - + float w = 1.0; w -= max(spos.z-far_split.y, 0.0)/transition_domain.y; w -= max(near_split.z-spos.z, 0.0)/transition_domain.z; @@ -142,8 +143,7 @@ void main() if (spos.z < near_split.x && spos.z > far_split.y) { lpos = shadow_matrix[1]*spos; - lpos.xy *= shadow_res; - + float w = 1.0; w -= max(spos.z-far_split.x, 0.0)/transition_domain.x; w -= max(near_split.y-spos.z, 0.0)/transition_domain.y; @@ -154,8 +154,7 @@ void main() if (spos.z > far_split.x) { lpos = shadow_matrix[0]*spos; - lpos.xy *= shadow_res; - + float w = 1.0; w -= max(near_split.x-spos.z, 0.0)/transition_domain.x; diff --git a/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl index 8c4ccf9cb3..219ae687d5 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl @@ -35,10 +35,10 @@ out vec4 frag_color; uniform sampler2DRect depthMap; uniform sampler2DRect normalMap; -uniform sampler2DRectShadow shadowMap0; -uniform sampler2DRectShadow shadowMap1; -uniform sampler2DRectShadow shadowMap2; -uniform sampler2DRectShadow shadowMap3; +uniform sampler2DShadow shadowMap0; +uniform sampler2DShadow shadowMap1; +uniform sampler2DShadow shadowMap2; +uniform sampler2DShadow shadowMap3; uniform sampler2DShadow shadowMap4; uniform sampler2DShadow shadowMap5; @@ -55,10 +55,10 @@ VARYING vec2 vary_fragcoord; uniform mat4 inv_proj; uniform vec2 screen_res; -uniform vec2 shadow_res; uniform vec2 proj_shadow_res; uniform vec3 sun_dir; +uniform vec2 shadow_res; uniform float shadow_bias; uniform float shadow_offset; @@ -78,29 +78,32 @@ vec4 getPosition(vec2 pos_screen) return pos; } -float pcfShadow(sampler2DRectShadow shadowMap, vec4 stc, float scl) +float pcfShadow(sampler2DShadow shadowMap, vec4 stc, float scl) { stc.xyz /= stc.w; - stc.z += shadow_bias*scl; - - float cs = shadow2DRect(shadowMap, stc.xyz).x; + stc.z += shadow_bias; + + float cs = shadow2D(shadowMap, stc.xyz).x; float shadow = cs; - shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(1.5, 1.5, 0.0)).x, cs); - shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(1.5, -1.5, 0.0)).x, cs); - shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(-1.5, 1.5, 0.0)).x, cs); - shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(-1.5, -1.5, 0.0)).x, cs); + + vec2 off = 1.5/shadow_res; + + shadow += max(shadow2D(shadowMap, stc.xyz+vec3(off.x, off.y, 0.0)).x, cs); + shadow += max(shadow2D(shadowMap, stc.xyz+vec3(off.x, -off.y, 0.0)).x, cs); + shadow += max(shadow2D(shadowMap, stc.xyz+vec3(-off.x, off.y, 0.0)).x, cs); + shadow += max(shadow2D(shadowMap, stc.xyz+vec3(-off.x, -off.y, 0.0)).x, cs); return shadow/5.0; //return shadow; } -float pcfShadow(sampler2DShadow shadowMap, vec4 stc, float scl) +float pcfSpotShadow(sampler2DShadow shadowMap, vec4 stc, float scl) { stc.xyz /= stc.w; stc.z += spot_shadow_bias*scl; - + float cs = shadow2D(shadowMap, stc.xyz).x; float shadow = cs; @@ -162,8 +165,7 @@ void main() if (spos.z < near_split.z) { lpos = shadow_matrix[3]*spos; - lpos.xy *= shadow_res; - + float w = 1.0; w -= max(spos.z-far_split.z, 0.0)/transition_domain.z; shadow += pcfShadow(shadowMap3, lpos, 0.25)*w; @@ -174,8 +176,7 @@ void main() if (spos.z < near_split.y && spos.z > far_split.z) { lpos = shadow_matrix[2]*spos; - lpos.xy *= shadow_res; - + float w = 1.0; w -= max(spos.z-far_split.y, 0.0)/transition_domain.y; w -= max(near_split.z-spos.z, 0.0)/transition_domain.z; @@ -186,7 +187,6 @@ void main() if (spos.z < near_split.x && spos.z > far_split.y) { lpos = shadow_matrix[1]*spos; - lpos.xy *= shadow_res; float w = 1.0; w -= max(spos.z-far_split.x, 0.0)/transition_domain.x; @@ -198,7 +198,6 @@ void main() if (spos.z > far_split.x) { lpos = shadow_matrix[0]*spos; - lpos.xy *= shadow_res; float w = 1.0; w -= max(near_split.x-spos.z, 0.0)/transition_domain.x; @@ -237,11 +236,11 @@ void main() //spotlight shadow 1 vec4 lpos = shadow_matrix[4]*spos; - frag_color[2] = pcfShadow(shadowMap4, lpos, 0.8); + frag_color[2] = pcfSpotShadow(shadowMap4, lpos, 0.8); //spotlight shadow 2 lpos = shadow_matrix[5]*spos; - frag_color[3] = pcfShadow(shadowMap5, lpos, 0.8); + frag_color[3] = pcfSpotShadow(shadowMap5, lpos, 0.8); //frag_color.rgb = pos.xyz; //frag_color.b = shadow; diff --git a/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl b/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl index 02075a7687..f6b009577a 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl @@ -34,10 +34,10 @@ out vec4 frag_color; uniform sampler2DRect depthMap; uniform sampler2DRect normalMap; -uniform sampler2DRectShadow shadowMap0; -uniform sampler2DRectShadow shadowMap1; -uniform sampler2DRectShadow shadowMap2; -uniform sampler2DRectShadow shadowMap3; +uniform sampler2DShadow shadowMap0; +uniform sampler2DShadow shadowMap1; +uniform sampler2DShadow shadowMap2; +uniform sampler2DShadow shadowMap3; uniform sampler2DShadow shadowMap4; uniform sampler2DShadow shadowMap5; uniform sampler2D noiseMap; @@ -55,10 +55,11 @@ VARYING vec2 vary_fragcoord; uniform mat4 inv_proj; uniform vec2 screen_res; -uniform vec2 shadow_res; uniform vec2 proj_shadow_res; uniform vec3 sun_dir; +uniform vec2 shadow_res; + uniform float shadow_bias; uniform float shadow_offset; @@ -139,29 +140,31 @@ float calcAmbientOcclusion(vec4 pos, vec3 norm) return min(ret, 1.0); } -float pcfShadow(sampler2DRectShadow shadowMap, vec4 stc, float scl) +float pcfShadow(sampler2DShadow shadowMap, vec4 stc, float scl) { stc.xyz /= stc.w; - stc.z += shadow_bias*scl; - - float cs = shadow2DRect(shadowMap, stc.xyz).x; + stc.z += shadow_bias; + + float cs = shadow2D(shadowMap, stc.xyz).x; float shadow = cs; - shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(1.5, 1.5, 0.0)).x, cs); - shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(1.5, -1.5, 0.0)).x, cs); - shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(-1.5, 1.5, 0.0)).x, cs); - shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(-1.5, -1.5, 0.0)).x, cs); + vec2 off = 1.5/shadow_res; + + shadow += max(shadow2D(shadowMap, stc.xyz+vec3(off.x, off.y, 0.0)).x, cs); + shadow += max(shadow2D(shadowMap, stc.xyz+vec3(off.x, -off.y, 0.0)).x, cs); + shadow += max(shadow2D(shadowMap, stc.xyz+vec3(-off.x, off.y, 0.0)).x, cs); + shadow += max(shadow2D(shadowMap, stc.xyz+vec3(-off.x, -off.y, 0.0)).x, cs); return shadow/5.0; //return shadow; } -float pcfShadow(sampler2DShadow shadowMap, vec4 stc, float scl) +float pcfSpotShadow(sampler2DShadow shadowMap, vec4 stc, float scl) { stc.xyz /= stc.w; stc.z += spot_shadow_bias*scl; - + float cs = shadow2D(shadowMap, stc.xyz).x; float shadow = cs; @@ -223,8 +226,7 @@ void main() if (spos.z < near_split.z) { lpos = shadow_matrix[3]*spos; - lpos.xy *= shadow_res; - + float w = 1.0; w -= max(spos.z-far_split.z, 0.0)/transition_domain.z; shadow += pcfShadow(shadowMap3, lpos, 0.25)*w; @@ -235,8 +237,7 @@ void main() if (spos.z < near_split.y && spos.z > far_split.z) { lpos = shadow_matrix[2]*spos; - lpos.xy *= shadow_res; - + float w = 1.0; w -= max(spos.z-far_split.y, 0.0)/transition_domain.y; w -= max(near_split.z-spos.z, 0.0)/transition_domain.z; @@ -247,8 +248,7 @@ void main() if (spos.z < near_split.x && spos.z > far_split.y) { lpos = shadow_matrix[1]*spos; - lpos.xy *= shadow_res; - + float w = 1.0; w -= max(spos.z-far_split.x, 0.0)/transition_domain.x; w -= max(near_split.y-spos.z, 0.0)/transition_domain.y; @@ -259,8 +259,7 @@ void main() if (spos.z > far_split.x) { lpos = shadow_matrix[0]*spos; - lpos.xy *= shadow_res; - + float w = 1.0; w -= max(near_split.x-spos.z, 0.0)/transition_domain.x; @@ -298,11 +297,11 @@ void main() //spotlight shadow 1 vec4 lpos = shadow_matrix[4]*spos; - frag_color[2] = pcfShadow(shadowMap4, lpos, 0.8); + frag_color[2] = pcfSpotShadow(shadowMap4, lpos, 0.8); //spotlight shadow 2 lpos = shadow_matrix[5]*spos; - frag_color[3] = pcfShadow(shadowMap5, lpos, 0.8); + frag_color[3] = pcfSpotShadow(shadowMap5, lpos, 0.8); //frag_color.rgb = pos.xyz; //frag_color.b = shadow; diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index a8dd6cf908..4ad0497954 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -885,7 +885,7 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples) { //allocate 4 sun shadow maps for (U32 i = 0; i < 4; i++) { - if (!mShadow[i].allocate(U32(resX*scale),U32(resY*scale), 0, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE)) return false; + if (!mShadow[i].allocate(U32(resX*scale),U32(resY*scale), 0, TRUE, FALSE, LLTexUnit::TT_TEXTURE)) return false; } } else @@ -7278,7 +7278,7 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, U32 light_index, U32 n for (U32 i = 0; i < 4; i++) { - channel = shader.enableTexture(LLShaderMgr::DEFERRED_SHADOW0+i, LLTexUnit::TT_RECT_TEXTURE); + channel = shader.enableTexture(LLShaderMgr::DEFERRED_SHADOW0+i, LLTexUnit::TT_TEXTURE); stop_glerror(); if (channel > -1) { @@ -7288,8 +7288,8 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, U32 light_index, U32 n gGL.getTexUnit(channel)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); stop_glerror(); - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB); - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL); stop_glerror(); } } @@ -7369,13 +7369,13 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, U32 light_index, U32 n matrix_nondiag, matrix_nondiag, matrix_diag}; shader.uniformMatrix3fv(LLShaderMgr::DEFERRED_SSAO_EFFECT_MAT, 1, GL_FALSE, ssao_effect_mat); - F32 shadow_offset_error = 1.f + RenderShadowOffsetError * fabsf(LLViewerCamera::getInstance()->getOrigin().mV[2]); - F32 shadow_bias_error = 1.f + RenderShadowBiasError * fabsf(LLViewerCamera::getInstance()->getOrigin().mV[2]); + //F32 shadow_offset_error = 1.f + RenderShadowOffsetError * fabsf(LLViewerCamera::getInstance()->getOrigin().mV[2]); + F32 shadow_bias_error = RenderShadowBiasError * fabsf(LLViewerCamera::getInstance()->getOrigin().mV[2])/3000.f; shader.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, mDeferredScreen.getWidth(), mDeferredScreen.getHeight()); shader.uniform1f(LLShaderMgr::DEFERRED_NEAR_CLIP, LLViewerCamera::getInstance()->getNear()*2.f); - shader.uniform1f (LLShaderMgr::DEFERRED_SHADOW_OFFSET, RenderShadowOffset*shadow_offset_error); - shader.uniform1f(LLShaderMgr::DEFERRED_SHADOW_BIAS, RenderShadowBias*shadow_bias_error); + shader.uniform1f (LLShaderMgr::DEFERRED_SHADOW_OFFSET, RenderShadowOffset); //*shadow_offset_error); + shader.uniform1f(LLShaderMgr::DEFERRED_SHADOW_BIAS, RenderShadowBias+shadow_bias_error); shader.uniform1f(LLShaderMgr::DEFERRED_SPOT_SHADOW_OFFSET, RenderSpotShadowOffset); shader.uniform1f(LLShaderMgr::DEFERRED_SPOT_SHADOW_BIAS, RenderSpotShadowBias); @@ -8099,9 +8099,9 @@ void LLPipeline::unbindDeferredShader(LLGLSLShader &shader) for (U32 i = 0; i < 4; i++) { - if (shader.disableTexture(LLShaderMgr::DEFERRED_SHADOW0+i, LLTexUnit::TT_RECT_TEXTURE) > -1) + if (shader.disableTexture(LLShaderMgr::DEFERRED_SHADOW0+i) > -1) { - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE); } } @@ -8517,6 +8517,7 @@ void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera gGL.setColorMask(false, false); LLFastTimer ftm(FTM_SHADOW_SIMPLE); + gGL.getTexUnit(0)->disable(); for (U32 i = 0; i < sizeof(types)/sizeof(U32); ++i) { -- cgit v1.3 From d1c056beba8c3558756eac816e26a388a512e0ee Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Tue, 3 Jul 2012 14:35:08 -0500 Subject: MAINT-685 Fix for disabling basic shaders making high detail terrain render incorrectly. --- indra/llrender/llglstates.h | 5 ----- indra/llrender/llrender.cpp | 13 ++++++++++++- indra/llrender/llrender.h | 1 + indra/newview/lldrawpool.cpp | 1 + indra/newview/lldrawpoolterrain.cpp | 6 +++++- indra/newview/lldrawpooltree.cpp | 1 + indra/newview/llvosurfacepatch.cpp | 4 ++-- 7 files changed, 22 insertions(+), 9 deletions(-) (limited to 'indra/llrender') diff --git a/indra/llrender/llglstates.h b/indra/llrender/llglstates.h index e26aead676..0e2c3bcb44 100644 --- a/indra/llrender/llglstates.h +++ b/indra/llrender/llglstates.h @@ -59,7 +59,6 @@ protected: LLGLEnable mColorMaterial; LLGLDisable mAlphaTest, mBlend, mCullFace, mDither, mFog, mLineSmooth, mLineStipple, mNormalize, mPolygonSmooth, - mTextureGenQ, mTextureGenR, mTextureGenS, mTextureGenT, mGLMultisample; public: LLGLSDefault() @@ -76,10 +75,6 @@ public: mLineStipple(GL_LINE_STIPPLE), mNormalize(GL_NORMALIZE), mPolygonSmooth(GL_POLYGON_SMOOTH), - mTextureGenQ(GL_TEXTURE_GEN_Q), - mTextureGenR(GL_TEXTURE_GEN_R), - mTextureGenS(GL_TEXTURE_GEN_S), - mTextureGenT(GL_TEXTURE_GEN_T), mGLMultisample(GL_MULTISAMPLE_ARB) { } }; diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index 348c1eb1b7..4597d06260 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -648,7 +648,7 @@ void LLTexUnit::setTextureCombiner(eTextureBlendOp op, eTextureBlendSrc src1, eT gGL.flush(); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB); } - + // We want an early out, because this function does a LOT of stuff. if ( ( (isAlpha && (mCurrAlphaOp == op) && (mCurrAlphaSrc1 == src1) && (mCurrAlphaSrc2 == src2)) || (!isAlpha && (mCurrColorOp == op) && (mCurrColorSrc1 == src1) && (mCurrColorSrc2 == src2)) ) && !gGL.mDirty) @@ -1437,6 +1437,17 @@ void LLRender::matrixMode(U32 mode) mMatrixMode = mode; } +U32 LLRender::getMatrixMode() +{ + if (mMatrixMode >= MM_TEXTURE0 && mMatrixMode <= MM_TEXTURE3) + { //always return MM_TEXTURE if current matrix mode points at any texture matrix + return MM_TEXTURE; + } + + return mMatrixMode; +} + + void LLRender::loadIdentity() { flush(); diff --git a/indra/llrender/llrender.h b/indra/llrender/llrender.h index fa5f7f311d..78a310e525 100644 --- a/indra/llrender/llrender.h +++ b/indra/llrender/llrender.h @@ -346,6 +346,7 @@ public: void loadIdentity(); void multMatrix(const GLfloat* m); void matrixMode(U32 mode); + U32 getMatrixMode(); const glh::matrix4f& getModelviewMatrix(); const glh::matrix4f& getProjectionMatrix(); diff --git a/indra/newview/lldrawpool.cpp b/indra/newview/lldrawpool.cpp index 6c0be0a5c2..b8c143e9c1 100644 --- a/indra/newview/lldrawpool.cpp +++ b/indra/newview/lldrawpool.cpp @@ -418,6 +418,7 @@ void LLRenderPass::applyModelMatrix(LLDrawInfo& params) gGL.loadMatrix(gGLModelView); if (params.mModelMatrix) { + llassert(gGL.getMatrixMode() == LLRender::MM_MODELVIEW); gGL.multMatrix((GLfloat*) params.mModelMatrix->mMatrix); } gPipeline.mMatrixOpCount++; diff --git a/indra/newview/lldrawpoolterrain.cpp b/indra/newview/lldrawpoolterrain.cpp index 7fc78fb382..9bc32fddbd 100644 --- a/indra/newview/lldrawpoolterrain.cpp +++ b/indra/newview/lldrawpoolterrain.cpp @@ -308,6 +308,7 @@ void LLDrawPoolTerrain::drawLoop() if (model_matrix != gGLLastMatrix) { + llassert(gGL.getMatrixMode() == LLRender::MM_MODELVIEW); gGLLastMatrix = model_matrix; gGL.loadMatrix(gGLModelView); if (model_matrix) @@ -594,7 +595,8 @@ void LLDrawPoolTerrain::renderFull4TU() gGL.matrixMode(LLRender::MM_TEXTURE); gGL.loadIdentity(); gGL.translatef(-1.f, 0.f, 0.f); - + gGL.matrixMode(LLRender::MM_MODELVIEW); + // Set alpha texture and do lighting modulation gGL.getTexUnit(3)->setTextureColorBlend(LLTexUnit::TBO_MULT, LLTexUnit::TBS_PREV_COLOR, LLTexUnit::TBS_VERT_COLOR); gGL.getTexUnit(3)->setTextureAlphaBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_TEX_ALPHA); @@ -742,6 +744,7 @@ void LLDrawPoolTerrain::renderFull2TU() gGL.matrixMode(LLRender::MM_TEXTURE); gGL.loadIdentity(); gGL.translatef(-1.f, 0.f, 0.f); + gGL.matrixMode(LLRender::MM_MODELVIEW); // Care about alpha only gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_PREV_COLOR); @@ -781,6 +784,7 @@ void LLDrawPoolTerrain::renderFull2TU() gGL.matrixMode(LLRender::MM_TEXTURE); gGL.loadIdentity(); gGL.translatef(-2.f, 0.f, 0.f); + gGL.matrixMode(LLRender::MM_MODELVIEW); // Care about alpha only gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_PREV_COLOR); diff --git a/indra/newview/lldrawpooltree.cpp b/indra/newview/lldrawpooltree.cpp index 83f04e45a8..fedbd782dc 100644 --- a/indra/newview/lldrawpooltree.cpp +++ b/indra/newview/lldrawpooltree.cpp @@ -116,6 +116,7 @@ void LLDrawPoolTree::render(S32 pass) gGL.loadMatrix(gGLModelView); if (model_matrix) { + llassert(gGL.getMatrixMode() == LLRender::MM_MODELVIEW); gGL.multMatrix((GLfloat*) model_matrix->mMatrix); } gPipeline.mMatrixOpCount++; diff --git a/indra/newview/llvosurfacepatch.cpp b/indra/newview/llvosurfacepatch.cpp index 94a3111f4c..cb905d02da 100644 --- a/indra/newview/llvosurfacepatch.cpp +++ b/indra/newview/llvosurfacepatch.cpp @@ -80,9 +80,9 @@ public: glNormalPointer(GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_NORMAL], (void*)(base + mOffsets[TYPE_NORMAL])); } if (data_mask & MAP_TEXCOORD3) - { //substitute tex coord 0 for tex coord 3 + { //substitute tex coord 1 for tex coord 3 glClientActiveTextureARB(GL_TEXTURE3_ARB); - glTexCoordPointer(2,GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD0], (void*)(base + mOffsets[TYPE_TEXCOORD0])); + glTexCoordPointer(2,GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD1], (void*)(base + mOffsets[TYPE_TEXCOORD1])); glClientActiveTextureARB(GL_TEXTURE0_ARB); } if (data_mask & MAP_TEXCOORD2) -- cgit v1.3 From e86b1c18db0629d64f8bf26fcf69e64072d084e6 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Wed, 11 Jul 2012 15:17:13 -0500 Subject: MAINT-794 Fix for assert on loading some types of objects before their parents. --- indra/llrender/llshadermgr.cpp | 39 ++++++++++++++-------- indra/llrender/llvertexbuffer.cpp | 6 ++-- .../shaders/class1/objects/indexedTextureV.glsl | 4 +-- indra/newview/llface.cpp | 11 +++--- 4 files changed, 35 insertions(+), 25 deletions(-) (limited to 'indra/llrender') diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp index 3fbf34296f..b6a9a6b653 100644 --- a/indra/llrender/llshadermgr.cpp +++ b/indra/llrender/llshadermgr.cpp @@ -702,7 +702,7 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade if (texture_index_channels > 1) { - text[count++] = strdup("VARYING_FLAT ivec4 vary_texture_index;\n"); + text[count++] = strdup("VARYING_FLAT int vary_texture_index;\n"); } text[count++] = strdup("vec4 diffuseLookup(vec2 texcoord)\n"); @@ -716,20 +716,33 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade } else if (major_version > 1 || minor_version >= 30) { //switches are supported in GLSL 1.30 and later - text[count++] = strdup("\tvec4 ret = vec4(1,0,1,1);\n"); - text[count++] = strdup("\tswitch (vary_texture_index.r)\n"); - text[count++] = strdup("\t{\n"); - - //switch body - for (S32 i = 0; i < texture_index_channels; ++i) - { - std::string case_str = llformat("\t\tcase %d: ret = texture2D(tex%d, texcoord); break;\n", i, i); - text[count++] = strdup(case_str.c_str()); + if (gGLManager.mIsNVIDIA) + { //switches are unreliable on some NVIDIA drivers + for (U32 i = 0; i < texture_index_channels; ++i) + { + std::string if_string = llformat("\t%sif (vary_texture_index == %d) { return texture2D(tex%d, texcoord); }\n", i > 0 ? "else " : "", i, i); + text[count++] = strdup(if_string.c_str()); + } + text[count++] = strdup("\treturn vec4(1,0,1,1);\n"); + text[count++] = strdup("}\n"); } + else + { + text[count++] = strdup("\tvec4 ret = vec4(1,0,1,1);\n"); + text[count++] = strdup("\tswitch (vary_texture_index)\n"); + text[count++] = strdup("\t{\n"); + + //switch body + for (S32 i = 0; i < texture_index_channels; ++i) + { + std::string case_str = llformat("\t\tcase %d: return texture2D(tex%d, texcoord);\n", i, i); + text[count++] = strdup(case_str.c_str()); + } - text[count++] = strdup("\t}\n"); - text[count++] = strdup("\treturn ret;\n"); - text[count++] = strdup("}\n"); + text[count++] = strdup("\t}\n"); + text[count++] = strdup("\treturn ret;\n"); + text[count++] = strdup("}\n"); + } } else { //should never get here. Indexed texture rendering requires GLSL 1.30 or later diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index 0092df6587..fd106ab79b 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -1326,7 +1326,7 @@ void LLVertexBuffer::setupVertexArray() 1, //TYPE_WEIGHT, 4, //TYPE_WEIGHT4, 4, //TYPE_CLOTHWEIGHT, - 4, //TYPE_TEXTURE_INDEX + 1, //TYPE_TEXTURE_INDEX }; U32 attrib_type[] = @@ -1343,7 +1343,7 @@ void LLVertexBuffer::setupVertexArray() GL_FLOAT, //TYPE_WEIGHT, GL_FLOAT, //TYPE_WEIGHT4, GL_FLOAT, //TYPE_CLOTHWEIGHT, - GL_UNSIGNED_BYTE, //TYPE_TEXTURE_INDEX + GL_UNSIGNED_INT, //TYPE_TEXTURE_INDEX }; bool attrib_integer[] = @@ -2400,7 +2400,7 @@ void LLVertexBuffer::setupVertexBuffer(U32 data_mask) #if !LL_DARWIN S32 loc = TYPE_TEXTURE_INDEX; void *ptr = (void*) (base + mOffsets[TYPE_VERTEX] + 12); - glVertexAttribIPointer(loc, 4, GL_UNSIGNED_BYTE, LLVertexBuffer::sTypeSize[TYPE_VERTEX], ptr); + glVertexAttribIPointer(loc, 1, GL_UNSIGNED_INT, LLVertexBuffer::sTypeSize[TYPE_VERTEX], ptr); #endif } if (data_mask & MAP_VERTEX) diff --git a/indra/newview/app_settings/shaders/class1/objects/indexedTextureV.glsl b/indra/newview/app_settings/shaders/class1/objects/indexedTextureV.glsl index 7c0699d72f..ca29bf3143 100644 --- a/indra/newview/app_settings/shaders/class1/objects/indexedTextureV.glsl +++ b/indra/newview/app_settings/shaders/class1/objects/indexedTextureV.glsl @@ -23,9 +23,9 @@ * $/LicenseInfo$ */ -ATTRIBUTE ivec4 texture_index; +ATTRIBUTE int texture_index; -VARYING_FLAT ivec4 vary_texture_index; +VARYING_FLAT int vary_texture_index; void passTextureIndex() { diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp index f5b217d539..4b107ae151 100644 --- a/indra/newview/llface.cpp +++ b/indra/newview/llface.cpp @@ -1943,15 +1943,12 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, LLVector4a texIdx; - U8 index = mTextureIndex < 255 ? mTextureIndex : 0; + S32 index = mTextureIndex < 255 ? mTextureIndex : 0; F32 val = 0.f; - U8* vp = (U8*) &val; - vp[0] = index; - vp[1] = 0; - vp[2] = 0; - vp[3] = 0; - + S32* vp = (S32*) &val; + *vp = index; + llassert(index <= LLGLSLShader::sIndexedTextureChannels-1); LLVector4Logical mask; -- cgit v1.3 From 35eda06ae47255f4d4ba15ab7e3df443c1c39a6e Mon Sep 17 00:00:00 2001 From: Aura Linden Date: Wed, 18 Jul 2012 17:35:10 -0700 Subject: llglheader include change for building on Lion --- indra/llrender/llglheaders.h | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'indra/llrender') diff --git a/indra/llrender/llglheaders.h b/indra/llrender/llglheaders.h index a0727b8686..d93f464502 100644 --- a/indra/llrender/llglheaders.h +++ b/indra/llrender/llglheaders.h @@ -993,7 +993,12 @@ extern void glGetBufferPointervARB (GLenum, GLenum, GLvoid* *); } #endif +#ifdef MAC_OS_VERSION_10_7 +#include +#else #include +#endif + #endif // LL_MESA / LL_WINDOWS / LL_DARWIN -- cgit v1.3 From afcc61a07a0449f390643aafea479e5ab068bda6 Mon Sep 17 00:00:00 2001 From: Xiaohong Bao Date: Thu, 19 Jul 2012 15:31:33 -0600 Subject: fix for SH-3238: Textures are loaded at lower detail on subsequent log-ins --- indra/llrender/llimagegl.cpp | 17 ++++++++++------- indra/llrender/llimagegl.h | 2 +- 2 files changed, 11 insertions(+), 8 deletions(-) (limited to 'indra/llrender') diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index c04a3f6b41..c962193565 100755 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -470,7 +470,7 @@ bool LLImageGL::checkSize(S32 width, S32 height) return check_power_of_two(width) && check_power_of_two(height); } -void LLImageGL::setSize(S32 width, S32 height, S32 ncomponents) +void LLImageGL::setSize(S32 width, S32 height, S32 ncomponents, S32 discard_level) { if (width != mWidth || height != mHeight || ncomponents != mComponents) { @@ -503,6 +503,11 @@ void LLImageGL::setSize(S32 width, S32 height, S32 ncomponents) width >>= 1; height >>= 1; } + + if(discard_level > 0) + { + mMaxDiscardLevel = llmax(mMaxDiscardLevel, (S8)discard_level); + } } else { @@ -836,14 +841,13 @@ BOOL LLImageGL::preAddToAtlas(S32 discard_level, const LLImageRaw* raw_image) llassert(mCurrentDiscardLevel >= 0); discard_level = mCurrentDiscardLevel; } - discard_level = llclamp(discard_level, 0, (S32)mMaxDiscardLevel); - + // Actual image width/height = raw image width/height * 2^discard_level S32 w = raw_image->getWidth() << discard_level; S32 h = raw_image->getHeight() << discard_level; // setSize may call destroyGLTexture if the size does not match - setSize(w, h, raw_image->getComponents()); + setSize(w, h, raw_image->getComponents(), discard_level); if( !mHasExplicitFormat ) { @@ -1197,8 +1201,7 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S llassert(mCurrentDiscardLevel >= 0); discard_level = mCurrentDiscardLevel; } - discard_level = llclamp(discard_level, 0, (S32)mMaxDiscardLevel); - + // Actual image width/height = raw image width/height * 2^discard_level S32 raw_w = imageraw->getWidth() ; S32 raw_h = imageraw->getHeight() ; @@ -1206,7 +1209,7 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S S32 h = raw_h << discard_level; // setSize may call destroyGLTexture if the size does not match - setSize(w, h, imageraw->getComponents()); + setSize(w, h, imageraw->getComponents(), discard_level); if( !mHasExplicitFormat ) { diff --git a/indra/llrender/llimagegl.h b/indra/llrender/llimagegl.h index f34b9fa91a..ee240f2797 100755 --- a/indra/llrender/llimagegl.h +++ b/indra/llrender/llimagegl.h @@ -92,7 +92,7 @@ protected: public: virtual void dump(); // debugging info to llinfos - void setSize(S32 width, S32 height, S32 ncomponents); + void setSize(S32 width, S32 height, S32 ncomponents, S32 discard_level = -1); void setComponents(S32 ncomponents) { mComponents = (S8)ncomponents ;} void setAllowCompression(bool allow) { mAllowCompression = allow; } -- cgit v1.3 From a1d026889343b4745eeebffc85695bbcb2b93d64 Mon Sep 17 00:00:00 2001 From: Aura Linden Date: Tue, 24 Jul 2012 16:52:33 -0700 Subject: Minor improvement to identifying gl lib to use. Should use xcode version. --- indra/llrender/llglheaders.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/llrender') diff --git a/indra/llrender/llglheaders.h b/indra/llrender/llglheaders.h index d93f464502..509de51f4d 100644 --- a/indra/llrender/llglheaders.h +++ b/indra/llrender/llglheaders.h @@ -993,7 +993,7 @@ extern void glGetBufferPointervARB (GLenum, GLenum, GLvoid* *); } #endif -#ifdef MAC_OS_VERSION_10_7 +#if __MAC_OS_X_VERSION_MAX_ALLOWED <= 1070 #include #else #include -- cgit v1.3 From 3653727e7f84f10caefb6ea7dc33859455ebfa0b Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Wed, 10 Oct 2012 14:57:43 -0400 Subject: Introduce new LLDir::findSkinnedFilenames() method. Use as needed. In a number of different places, for different reasons, the viewer wants to load a UI-related file that might be overridden by a non-default skin; and within that skin, might further be overridden by a non-default language. Apparently, for each of those use cases, every individual developer approached it as an entirely new problem, solving it idiosyncratically for that one case. Not only is this a maintenance problem, but it rubs one's nose in the fact that most such solutions consider only a subset of the relevant skin directories. Richard and I evolved an API intended to address all such cases: a central LLDir method returning a list of relevant pathnames, from most general to most localized, filtered to present only existing files; plus a couple of convenience methods to specifically obtain the most general and most localized available file. There were several load-skinned-file methods (LLFloater::buildFromFile(), LLPanel::buildFromFile() and LLUICtrlFactory::createFromFile() -- apparently cloned-and-modified from each other) that contained funky bolted-on logic to output the loaded data to an optional passed LLXMLNodePtr param. The trouble is that passing that param forced each of these methods to subvert its normal search: specifically for that case, it needed to find the baseline XML file instead of the localized one. Richard agreed that for the intended usage (reformatting XML files) we should use XML schema instead, and that the hacky functionality should be removed. Remove it. Also remove LLUICtrlFactory::getLocalizedXMLNode(), only used for those three special cases. Some callers explicitly passed the optional LLXMLNodePtr param as NULL. Remove that. Remove LLFloaterUIPreview::displayFloater(save) param, which relied on the optional output LLXMLNodePtr param. Make onClickSaveFloater() and onClickSaveAll() emit popupAndPrintWarning() about discontinued functionality. Recast LLFloater::buildFromFile(), LLPanel::buildFromFile(), LLUICtrlFactory::createFromFile(), LLNotifications::loadTemplates(), LLUI::locateSkin(), LLFontRegistry::parseFontInfo(), LLUIColorTable::loadFromSettings(), LLUICtrlFactory::loadWidgetTemplate(), LLUICtrlFactory::getLayeredXMLNode(), LLUIImageList::initFromFile(), LLAppViewer::launchUpdater() and LLMediaCtrl::navigateToLocalPage() to use findSkinnedFilenames(). (Is LLAppViewer::launchUpdater() ever called any more? Apparently so -- though the linux-updater.bin logic to process the relevant command-line switch has been disabled. Shrug.) (Is LLMediaCtrl::navigateToLocalPage() ever used?? If so, why?) Remove LLUI::setupPaths(), getXUIPaths(), getSkinPath() and getLocalizedSkinPath(). Remove the skins/paths.xml file read by setupPaths(). The only configuration it contained was the pair of partial paths "xui/en" and "xui/[LANGUAGE]" -- hardly likely to change. getSkinPath() specifically returned the first of these, while getLocalizedSkinPath() specifically returned the second. This knowledge is now embedded in findSkinnedFilenames(). Also remove paths.xml from viewer_manifest.py. Remove injected xui_paths from LLFontGL::initClass() and LLFontRegistry::LLFontRegistry(). These are no longer needed since LLFontRegistry can now directly consult LLDir for its path search. Stop passing LLUI::getXUIPaths() to LLFontGL::initClass() in LLViewerWindow's constructor and initFonts() method. Add LLDir::append() and add() methods for the simple task of combining two path components separated by getDirDelimiter() -- but only if they're both non-empty. Amazing how often that logic is replicated. Replace some existing concatenations with add() or append(). New LLDir::findSkinnedFilenames() method must know current language. Allow injecting current language by adding an LLDir::setSkinFolder(language) param, and pass it where LLAppViewer::init() and initConfiguration() currently call setSkinFolder(). Also add LLDir::getSkinFolder() and getLanguage() methods. Change LLFLoaterUIPreview's LLLocalizationResetForcer helper to "forcibly reset language" using LLDir::setSkinFolder() instead of LLUI::setupPaths(). Update LLDir stubs in lldir_stub.cpp and llupdaterservice_test.cpp. Add LLDir::getUserDefaultSkinDir() to obtain often-overlooked possible skin directory -- like getUserSkinDir() but with "default" in place of the current skin name as the last path component. (However, we hope findSkinnedFilenames() obviates most explicit use of such individual skin directory pathnames.) Add LLDir unit tests for new findSkinnedFilenames() and add() methods -- the latter exercises append() as well. Tweak indra/integration_tests/llui_libtest/llui_libtest.cpp for all the above. Notably, comment out its export_test_floaters() function, since the essential LLFloater::buildFromFile(optional LLXMLNodePtr) functionality has been removed. This may mean that llui_libtest.cpp has little remaining value, not sure. --- .../llimage_libtest/llimage_libtest.cpp | 2 +- .../llui_libtest/llui_libtest.cpp | 29 +- indra/linux_updater/linux_updater.cpp | 2 +- indra/llrender/llfontgl.cpp | 4 +- indra/llrender/llfontgl.h | 2 +- indra/llrender/llfontregistry.cpp | 30 +- indra/llrender/llfontregistry.h | 4 +- indra/llui/llfloater.cpp | 18 +- indra/llui/llfloater.h | 2 +- indra/llui/llfloaterreg.cpp | 2 +- indra/llui/llnotifications.cpp | 25 +- indra/llui/llpanel.cpp | 18 +- indra/llui/llpanel.h | 2 +- indra/llui/llui.cpp | 87 +--- indra/llui/llui.h | 5 - indra/llui/lluicolortable.cpp | 17 +- indra/llui/lluictrlfactory.cpp | 46 +-- indra/llui/lluictrlfactory.h | 17 +- indra/llvfs/lldir.cpp | 458 ++++++++++++++++----- indra/llvfs/lldir.h | 91 +++- indra/llvfs/tests/lldir_test.cpp | 339 ++++++++++++++- indra/newview/llappviewer.cpp | 65 +-- indra/newview/lldaycyclemanager.cpp | 2 +- indra/newview/llfloateruipreview.cpp | 122 ++---- indra/newview/llhints.cpp | 4 +- indra/newview/llmediactrl.cpp | 30 +- indra/newview/llpreviewscript.cpp | 2 +- indra/newview/llsyswellwindow.cpp | 4 +- indra/newview/lltoast.cpp | 2 +- indra/newview/llviewermedia.cpp | 15 +- indra/newview/llviewertexturelist.cpp | 55 ++- indra/newview/llviewerwindow.cpp | 6 +- indra/newview/llwaterparammanager.cpp | 2 +- indra/newview/llwlparammanager.cpp | 2 +- indra/newview/skins/paths.xml | 10 - indra/newview/tests/lldir_stub.cpp | 2 +- indra/newview/viewer_manifest.py | 1 - .../updater/tests/llupdaterservice_test.cpp | 4 +- 38 files changed, 978 insertions(+), 550 deletions(-) delete mode 100644 indra/newview/skins/paths.xml (limited to 'indra/llrender') diff --git a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp index 36c5b67826..034c816742 100644 --- a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp +++ b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp @@ -240,7 +240,7 @@ void store_input_file(std::list &input_filenames, const std::string LLDirIterator iter(dir, name); while (iter.next(next_name)) { - std::string file_name = dir + gDirUtilp->getDirDelimiter() + next_name; + std::string file_name = gDirUtilp->add(dir, next_name); input_filenames.push_back(file_name); } } diff --git a/indra/integration_tests/llui_libtest/llui_libtest.cpp b/indra/integration_tests/llui_libtest/llui_libtest.cpp index 217e26c3ca..38aa1bbeb2 100644 --- a/indra/integration_tests/llui_libtest/llui_libtest.cpp +++ b/indra/integration_tests/llui_libtest/llui_libtest.cpp @@ -107,12 +107,6 @@ public: }; TestImageProvider gTestImageProvider; -static std::string get_xui_dir() -{ - std::string delim = gDirUtilp->getDirDelimiter(); - return gDirUtilp->getSkinBaseDir() + delim + "default" + delim + "xui" + delim; -} - void init_llui() { // Font lookup needs directory support @@ -122,13 +116,12 @@ void init_llui() const char* newview_path = "../../../newview"; #endif gDirUtilp->initAppDirs("SecondLife", newview_path); - gDirUtilp->setSkinFolder("default"); + gDirUtilp->setSkinFolder("default", "en"); // colors are no longer stored in a LLControlGroup file LLUIColorTable::instance().loadFromSettings(); - std::string config_filename = gDirUtilp->getExpandedFilename( - LL_PATH_APP_SETTINGS, "settings.xml"); + std::string config_filename = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "settings.xml"); gSavedSettings.loadFromFile(config_filename); // See LLAppViewer::init() @@ -143,9 +136,7 @@ void init_llui() const bool no_register_widgets = false; LLWidgetReg::initClass( no_register_widgets ); - - // Unclear if this is needed - LLUI::setupPaths(); + // Otherwise we get translation warnings when setting up floaters // (tooltips for buttons) std::set default_args; @@ -157,7 +148,6 @@ void init_llui() // otherwise it crashes. LLFontGL::initClass(96.f, 1.f, 1.f, gDirUtilp->getAppRODataDir(), - LLUI::getXUIPaths(), false ); // don't create gl textures LLFloaterView::Params fvparams; @@ -169,6 +159,14 @@ void init_llui() gFloaterView = LLUICtrlFactory::create (fvparams); } +/*==========================================================================*| +static std::string get_xui_dir() +{ + std::string delim = gDirUtilp->getDirDelimiter(); + return gDirUtilp->getSkinBaseDir() + delim + "default" + delim + "xui" + delim; +} + +// buildFromFile() no longer supports generate-output-LLXMLNode void export_test_floaters() { // Convert all test floaters to new XML format @@ -191,7 +189,7 @@ void export_test_floaters() floater->buildFromFile( filename, // FALSE, // don't open floater output_node); - std::string out_filename = xui_dir + filename; + std::string out_filename = gDirUtilp->add(xui_dir, filename); std::string::size_type extension_pos = out_filename.rfind(".xml"); out_filename.resize(extension_pos); out_filename += "_new.xml"; @@ -203,6 +201,7 @@ void export_test_floaters() fclose(floater_file); } } +|*==========================================================================*/ int main(int argc, char** argv) { @@ -211,7 +210,7 @@ int main(int argc, char** argv) init_llui(); - export_test_floaters(); +// export_test_floaters(); return 0; } diff --git a/indra/linux_updater/linux_updater.cpp b/indra/linux_updater/linux_updater.cpp index 277f0a5367..991dfd9dce 100644 --- a/indra/linux_updater/linux_updater.cpp +++ b/indra/linux_updater/linux_updater.cpp @@ -251,7 +251,7 @@ std::string next_image_filename(std::string& image_path, LLDirIterator& iter) { std::string image_filename; iter.next(image_filename); - return image_path + "/" + image_filename; + return gDirUtilp->add(image_path, image_filename); } void on_window_closed(GtkWidget *sender, GdkEvent* event, gpointer data) diff --git a/indra/llrender/llfontgl.cpp b/indra/llrender/llfontgl.cpp index 4dc2fcd714..647512eb2e 100644 --- a/indra/llrender/llfontgl.cpp +++ b/indra/llrender/llfontgl.cpp @@ -789,7 +789,7 @@ const LLFontDescriptor& LLFontGL::getFontDesc() const } // static -void LLFontGL::initClass(F32 screen_dpi, F32 x_scale, F32 y_scale, const std::string& app_dir, const std::vector& xui_paths, bool create_gl_textures) +void LLFontGL::initClass(F32 screen_dpi, F32 x_scale, F32 y_scale, const std::string& app_dir, bool create_gl_textures) { sVertDPI = (F32)llfloor(screen_dpi * y_scale); sHorizDPI = (F32)llfloor(screen_dpi * x_scale); @@ -800,7 +800,7 @@ void LLFontGL::initClass(F32 screen_dpi, F32 x_scale, F32 y_scale, const std::st // Font registry init if (!sFontRegistry) { - sFontRegistry = new LLFontRegistry(xui_paths, create_gl_textures); + sFontRegistry = new LLFontRegistry(create_gl_textures); sFontRegistry->parseFontInfo("fonts.xml"); } else diff --git a/indra/llrender/llfontgl.h b/indra/llrender/llfontgl.h index 5ed5d2c4eb..0988e99deb 100644 --- a/indra/llrender/llfontgl.h +++ b/indra/llrender/llfontgl.h @@ -150,7 +150,7 @@ public: const LLFontDescriptor& getFontDesc() const; - static void initClass(F32 screen_dpi, F32 x_scale, F32 y_scale, const std::string& app_dir, const std::vector& xui_paths, bool create_gl_textures = true); + static void initClass(F32 screen_dpi, F32 x_scale, F32 y_scale, const std::string& app_dir, bool create_gl_textures = true); // Load sans-serif, sans-serif-small, etc. // Slow, requires multiple seconds to load fonts. diff --git a/indra/llrender/llfontregistry.cpp b/indra/llrender/llfontregistry.cpp index 4d22eba3d9..b5bdba996f 100644 --- a/indra/llrender/llfontregistry.cpp +++ b/indra/llrender/llfontregistry.cpp @@ -163,14 +163,9 @@ LLFontDescriptor LLFontDescriptor::normalize() const return LLFontDescriptor(new_name,new_size,new_style,getFileNames()); } -LLFontRegistry::LLFontRegistry(const string_vec_t& xui_paths, - bool create_gl_textures) +LLFontRegistry::LLFontRegistry(bool create_gl_textures) : mCreateGLTextures(create_gl_textures) { - // Propagate this down from LLUICtrlFactory so LLRender doesn't - // need an upstream dependency on LLUI. - mXUIPaths = xui_paths; - // This is potentially a slow directory traversal, so we want to // cache the result. mUltimateFallbackList = LLWindow::getDynamicFallbackFontList(); @@ -183,27 +178,30 @@ LLFontRegistry::~LLFontRegistry() bool LLFontRegistry::parseFontInfo(const std::string& xml_filename) { - bool success = false; // Succeed if we find at least one XUI file - const string_vec_t& xml_paths = mXUIPaths; + bool success = false; // Succeed if we find and read at least one XUI file + const string_vec_t xml_paths = gDirUtilp->findSkinnedFilenames(LLDir::XUI, xml_filename); + if (xml_paths.empty()) + { + // We didn't even find one single XUI file + return false; + } + for (string_vec_t::const_iterator path_it = xml_paths.begin(); path_it != xml_paths.end(); ++path_it) { - LLXMLNodePtr root; - std::string full_filename = gDirUtilp->findSkinnedFilename(*path_it, xml_filename); - bool parsed_file = LLXMLNode::parseFile(full_filename, root, NULL); + bool parsed_file = LLXMLNode::parseFile(*path_it, root, NULL); if (!parsed_file) continue; - + if ( root.isNull() || ! root->hasName( "fonts" ) ) { - llwarns << "Bad font info file: " - << full_filename << llendl; + llwarns << "Bad font info file: " << *path_it << llendl; continue; } - + std::string root_name; root->getAttributeString("name",root_name); if (root->hasName("fonts")) @@ -215,7 +213,7 @@ bool LLFontRegistry::parseFontInfo(const std::string& xml_filename) } //if (success) // dump(); - + return success; } diff --git a/indra/llrender/llfontregistry.h b/indra/llrender/llfontregistry.h index 8b06191c56..059248fbbd 100644 --- a/indra/llrender/llfontregistry.h +++ b/indra/llrender/llfontregistry.h @@ -67,8 +67,7 @@ class LLFontRegistry public: // create_gl_textures - set to false for test apps with no OpenGL window, // such as llui_libtest - LLFontRegistry(const string_vec_t& xui_paths, - bool create_gl_textures); + LLFontRegistry(bool create_gl_textures); ~LLFontRegistry(); // Load standard font info from XML file(s). @@ -105,7 +104,6 @@ private: font_size_map_t mFontSizes; string_vec_t mUltimateFallbackList; - string_vec_t mXUIPaths; bool mCreateGLTextures; }; diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index 8ca1e685a9..33295f882d 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -3229,24 +3229,14 @@ bool LLFloater::isVisible(const LLFloater* floater) static LLFastTimer::DeclareTimer FTM_BUILD_FLOATERS("Build Floaters"); -bool LLFloater::buildFromFile(const std::string& filename, LLXMLNodePtr output_node) +bool LLFloater::buildFromFile(const std::string& filename) { LLFastTimer timer(FTM_BUILD_FLOATERS); LLXMLNodePtr root; - //if exporting, only load the language being exported, - //instead of layering localized version on top of english - if (output_node) - { - if (!LLUICtrlFactory::getLocalizedXMLNode(filename, root)) - { - llwarns << "Couldn't parse floater from: " << LLUI::getLocalizedSkinPath() + gDirUtilp->getDirDelimiter() + filename << llendl; - return false; - } - } - else if (!LLUICtrlFactory::getLayeredXMLNode(filename, root)) + if (!LLUICtrlFactory::getLayeredXMLNode(filename, root)) { - llwarns << "Couldn't parse floater from: " << LLUI::getSkinPath() + gDirUtilp->getDirDelimiter() + filename << llendl; + llwarns << "Couldn't find (or parse) floater from: " << filename << llendl; return false; } @@ -3271,7 +3261,7 @@ bool LLFloater::buildFromFile(const std::string& filename, LLXMLNodePtr output_n getCommitCallbackRegistrar().pushScope(); getEnableCallbackRegistrar().pushScope(); - res = initFloaterXML(root, getParent(), filename, output_node); + res = initFloaterXML(root, getParent(), filename, NULL); setXMLFilename(filename); diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h index 64d6dcea04..e64b6d04d3 100644 --- a/indra/llui/llfloater.h +++ b/indra/llui/llfloater.h @@ -202,7 +202,7 @@ public: // Don't export top/left for rect, only height/width static void setupParamsForExport(Params& p, LLView* parent); - bool buildFromFile(const std::string &filename, LLXMLNodePtr output_node = NULL); + bool buildFromFile(const std::string &filename); boost::signals2::connection setMinimizeCallback( const commit_signal_t::slot_type& cb ); boost::signals2::connection setOpenCallback( const commit_signal_t::slot_type& cb ); diff --git a/indra/llui/llfloaterreg.cpp b/indra/llui/llfloaterreg.cpp index 9115eb7174..306caf2b91 100644 --- a/indra/llui/llfloaterreg.cpp +++ b/indra/llui/llfloaterreg.cpp @@ -154,7 +154,7 @@ LLFloater* LLFloaterReg::getInstance(const std::string& name, const LLSD& key) llwarns << "Failed to build floater type: '" << name << "'." << llendl; return NULL; } - bool success = res->buildFromFile(xui_file, NULL); + bool success = res->buildFromFile(xui_file); if (!success) { llwarns << "Failed to build floater type: '" << name << "'." << llendl; diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp index 629eef2c3b..4fbee8cd80 100644 --- a/indra/llui/llnotifications.cpp +++ b/indra/llui/llnotifications.cpp @@ -1424,25 +1424,18 @@ void addPathIfExists(const std::string& new_path, std::vector& path bool LLNotifications::loadTemplates() { llinfos << "Reading notifications template" << llendl; - std::vector search_paths; - - std::string skin_relative_path = gDirUtilp->getDirDelimiter() + LLUI::getSkinPath() + gDirUtilp->getDirDelimiter() + "notifications.xml"; - std::string localized_skin_relative_path = gDirUtilp->getDirDelimiter() + LLUI::getLocalizedSkinPath() + gDirUtilp->getDirDelimiter() + "notifications.xml"; - - addPathIfExists(gDirUtilp->getDefaultSkinDir() + skin_relative_path, search_paths); - addPathIfExists(gDirUtilp->getDefaultSkinDir() + localized_skin_relative_path, search_paths); - addPathIfExists(gDirUtilp->getSkinDir() + skin_relative_path, search_paths); - addPathIfExists(gDirUtilp->getSkinDir() + localized_skin_relative_path, search_paths); - addPathIfExists(gDirUtilp->getUserSkinDir() + skin_relative_path, search_paths); - addPathIfExists(gDirUtilp->getUserSkinDir() + localized_skin_relative_path, search_paths); + // Passing findSkinnedFilenames(merge=true) makes it output all relevant + // pathnames instead of just the ones from the most specific skin. + std::vector search_paths = + gDirUtilp->findSkinnedFilenames(LLDir::XUI, "notifications.xml", true); std::string base_filename = search_paths.front(); LLXMLNodePtr root; BOOL success = LLXMLNode::getLayeredXMLNode(root, search_paths); - + if (!success || root.isNull() || !root->hasName( "notifications" )) { - llerrs << "Problem reading UI Notifications file: " << base_filename << llendl; + llerrs << "Problem reading XML from UI Notifications file: " << base_filename << llendl; return false; } @@ -1452,7 +1445,7 @@ bool LLNotifications::loadTemplates() if(!params.validateBlock()) { - llerrs << "Problem reading UI Notifications file: " << base_filename << llendl; + llerrs << "Problem reading XUI from UI Notifications file: " << base_filename << llendl; return false; } @@ -1508,7 +1501,9 @@ bool LLNotifications::loadTemplates() bool LLNotifications::loadVisibilityRules() { const std::string xml_filename = "notification_visibility.xml"; - std::string full_filename = gDirUtilp->findSkinnedFilename(LLUI::getXUIPaths().front(), xml_filename); + // Note that here we're looking for the "en" version, the default + // language, rather than the most localized version of this file. + std::string full_filename = gDirUtilp->findSkinnedFilenameBaseLang(LLDir::XUI, xml_filename); LLNotificationVisibilityRule::Rules params; LLSimpleXUIParser parser; diff --git a/indra/llui/llpanel.cpp b/indra/llui/llpanel.cpp index 00318cec6b..67472ad166 100644 --- a/indra/llui/llpanel.cpp +++ b/indra/llui/llpanel.cpp @@ -968,25 +968,15 @@ static LLFastTimer::DeclareTimer FTM_BUILD_PANELS("Build Panels"); //----------------------------------------------------------------------------- // buildPanel() //----------------------------------------------------------------------------- -BOOL LLPanel::buildFromFile(const std::string& filename, LLXMLNodePtr output_node, const LLPanel::Params& default_params) +BOOL LLPanel::buildFromFile(const std::string& filename, const LLPanel::Params& default_params) { LLFastTimer timer(FTM_BUILD_PANELS); BOOL didPost = FALSE; LLXMLNodePtr root; - //if exporting, only load the language being exported, - //instead of layering localized version on top of english - if (output_node) - { - if (!LLUICtrlFactory::getLocalizedXMLNode(filename, root)) - { - llwarns << "Couldn't parse panel from: " << LLUI::getLocalizedSkinPath() + gDirUtilp->getDirDelimiter() + filename << llendl; - return didPost; - } - } - else if (!LLUICtrlFactory::getLayeredXMLNode(filename, root)) + if (!LLUICtrlFactory::getLayeredXMLNode(filename, root)) { - llwarns << "Couldn't parse panel from: " << LLUI::getSkinPath() + gDirUtilp->getDirDelimiter() + filename << llendl; + llwarns << "Couldn't parse panel from: " << filename << llendl; return didPost; } @@ -1010,7 +1000,7 @@ BOOL LLPanel::buildFromFile(const std::string& filename, LLXMLNodePtr output_nod getCommitCallbackRegistrar().pushScope(); getEnableCallbackRegistrar().pushScope(); - didPost = initPanelXML(root, NULL, output_node, default_params); + didPost = initPanelXML(root, NULL, NULL, default_params); getCommitCallbackRegistrar().popScope(); getEnableCallbackRegistrar().popScope(); diff --git a/indra/llui/llpanel.h b/indra/llui/llpanel.h index f620201020..e63b41f97c 100644 --- a/indra/llui/llpanel.h +++ b/indra/llui/llpanel.h @@ -105,7 +105,7 @@ protected: LLPanel(const LLPanel::Params& params = getDefaultParams()); public: - BOOL buildFromFile(const std::string &filename, LLXMLNodePtr output_node = NULL, const LLPanel::Params&default_params = getDefaultParams()); + BOOL buildFromFile(const std::string &filename, const LLPanel::Params& default_params = getDefaultParams()); static LLPanel* createFactoryPanel(const std::string& name); diff --git a/indra/llui/llui.cpp b/indra/llui/llui.cpp index 87bf518aa1..507ced9172 100644 --- a/indra/llui/llui.cpp +++ b/indra/llui/llui.cpp @@ -1836,88 +1836,39 @@ struct Paths : public LLInitParam::Block {} }; -//static -void LLUI::setupPaths() -{ - std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_SKINS, "paths.xml"); - - LLXMLNodePtr root; - BOOL success = LLXMLNode::parseFile(filename, root, NULL); - Paths paths; - - if(success) - { - LLXUIParser parser; - parser.readXUI(root, paths, filename); - } - sXUIPaths.clear(); - - if (success && paths.validateBlock()) - { - LLStringUtil::format_map_t path_args; - path_args["[LANGUAGE]"] = LLUI::getLanguage(); - - for (LLInitParam::ParamIterator::const_iterator it = paths.directories.begin(), - end_it = paths.directories.end(); - it != end_it; - ++it) - { - std::string path_val_ui; - for (LLInitParam::ParamIterator::const_iterator subdir_it = it->subdirs.begin(), - subdir_end_it = it->subdirs.end(); - subdir_it != subdir_end_it;) - { - path_val_ui += subdir_it->value(); - if (++subdir_it != subdir_end_it) - path_val_ui += gDirUtilp->getDirDelimiter(); - } - LLStringUtil::format(path_val_ui, path_args); - if (std::find(sXUIPaths.begin(), sXUIPaths.end(), path_val_ui) == sXUIPaths.end()) - { - sXUIPaths.push_back(path_val_ui); - } - - } - } - else // parsing failed - { - std::string slash = gDirUtilp->getDirDelimiter(); - std::string dir = "xui" + slash + "en"; - llwarns << "XUI::config file unable to open: " << filename << llendl; - sXUIPaths.push_back(dir); - } -} - //static std::string LLUI::locateSkin(const std::string& filename) { - std::string slash = gDirUtilp->getDirDelimiter(); std::string found_file = filename; - if (!gDirUtilp->fileExists(found_file)) + if (gDirUtilp->fileExists(found_file)) { - found_file = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, filename); // Should be CUSTOM_SKINS? + return found_file; } - if (sSettingGroups["config"] && sSettingGroups["config"]->controlExists("Language")) + + found_file = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, filename); // Should be CUSTOM_SKINS? + if (gDirUtilp->fileExists(found_file)) { - if (!gDirUtilp->fileExists(found_file)) - { - std::string localization = getLanguage(); - std::string local_skin = "xui" + slash + localization + slash + filename; - found_file = gDirUtilp->findSkinnedFilename(local_skin); - } + return found_file; } - if (!gDirUtilp->fileExists(found_file)) + + found_file = gDirUtilp->findSkinnedFilename(LLDir::XUI, filename); + if (! found_file.empty()) { - std::string local_skin = "xui" + slash + "en" + slash + filename; - found_file = gDirUtilp->findSkinnedFilename(local_skin); + return found_file; } - if (!gDirUtilp->fileExists(found_file)) + + found_file = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, filename); +/*==========================================================================*| + // Hmm, if we got this far, previous implementation of this method would + // return this last found_file value whether or not it actually exists. + if (gDirUtilp->fileExists(found_file)) { - found_file = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, filename); + return found_file; } +|*==========================================================================*/ return found_file; -} +} //static LLVector2 LLUI::getWindowSize() diff --git a/indra/llui/llui.h b/indra/llui/llui.h index 28e84fa444..c5a12d2b31 100644 --- a/indra/llui/llui.h +++ b/indra/llui/llui.h @@ -292,11 +292,6 @@ public: // Return the ISO639 language name ("en", "ko", etc.) for the viewer UI. // http://www.loc.gov/standards/iso639-2/php/code_list.php static std::string getLanguage(); - - static void setupPaths(); - static const std::vector& getXUIPaths() { return sXUIPaths; } - static std::string getSkinPath() { return sXUIPaths.front(); } - static std::string getLocalizedSkinPath() { return sXUIPaths.back(); } //all files may not exist at the localized path //helper functions (should probably move free standing rendering helper functions here) static LLView* getRootView() { return sRootView; } diff --git a/indra/llui/lluicolortable.cpp b/indra/llui/lluicolortable.cpp index 9455d09cc0..2717445396 100644 --- a/indra/llui/lluicolortable.cpp +++ b/indra/llui/lluicolortable.cpp @@ -32,6 +32,7 @@ #include "llui.h" #include "lluicolortable.h" #include "lluictrlfactory.h" +#include LLUIColorTable::ColorParams::ColorParams() : value("value"), @@ -206,19 +207,11 @@ bool LLUIColorTable::loadFromSettings() { bool result = false; - std::string default_filename = gDirUtilp->getExpandedFilename(LL_PATH_DEFAULT_SKIN, "colors.xml"); - result |= loadFromFilename(default_filename, mLoadedColors); - - std::string current_filename = gDirUtilp->getExpandedFilename(LL_PATH_TOP_SKIN, "colors.xml"); - if(current_filename != default_filename) - { - result |= loadFromFilename(current_filename, mLoadedColors); - } - - current_filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SKIN, "colors.xml"); - if(current_filename != default_filename) + // pass merge=true because we want colors.xml from every skin dir + BOOST_FOREACH(std::string colors_path, + gDirUtilp->findSkinnedFilenames(LLDir::SKINBASE, "colors.xml", true)) { - result |= loadFromFilename(current_filename, mLoadedColors); + result |= loadFromFilename(colors_path, mLoadedColors); } std::string user_filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "colors.xml"); diff --git a/indra/llui/lluictrlfactory.cpp b/indra/llui/lluictrlfactory.cpp index 25e7a31e90..2b317b46e3 100644 --- a/indra/llui/lluictrlfactory.cpp +++ b/indra/llui/lluictrlfactory.cpp @@ -90,10 +90,12 @@ LLUICtrlFactory::~LLUICtrlFactory() void LLUICtrlFactory::loadWidgetTemplate(const std::string& widget_tag, LLInitParam::BaseBlock& block) { - std::string filename = std::string("widgets") + gDirUtilp->getDirDelimiter() + widget_tag + ".xml"; + std::string filename = gDirUtilp->add("widgets", widget_tag + ".xml"); LLXMLNodePtr root_node; - std::string full_filename = gDirUtilp->findSkinnedFilename(LLUI::getXUIPaths().front(), filename); + // Here we're looking for the "en" version, the default-language version + // of the file, rather than the localized version. + std::string full_filename = gDirUtilp->findSkinnedFilenameBaseLang(LLDir::XUI, filename); if (!full_filename.empty()) { LLUICtrlFactory::instance().pushFileName(full_filename); @@ -152,19 +154,8 @@ static LLFastTimer::DeclareTimer FTM_XML_PARSE("XML Reading/Parsing"); bool LLUICtrlFactory::getLayeredXMLNode(const std::string &xui_filename, LLXMLNodePtr& root) { LLFastTimer timer(FTM_XML_PARSE); - - std::vector paths; - std::string path = gDirUtilp->findSkinnedFilename(LLUI::getSkinPath(), xui_filename); - if (!path.empty()) - { - paths.push_back(path); - } - - std::string localize_path = gDirUtilp->findSkinnedFilename(LLUI::getLocalizedSkinPath(), xui_filename); - if (!localize_path.empty() && localize_path != path) - { - paths.push_back(localize_path); - } + std::vector paths = + gDirUtilp->findSkinnedFilenames(LLDir::XUI, xui_filename); if (paths.empty()) { @@ -176,23 +167,6 @@ bool LLUICtrlFactory::getLayeredXMLNode(const std::string &xui_filename, LLXMLNo } -//----------------------------------------------------------------------------- -// getLocalizedXMLNode() -//----------------------------------------------------------------------------- -bool LLUICtrlFactory::getLocalizedXMLNode(const std::string &xui_filename, LLXMLNodePtr& root) -{ - LLFastTimer timer(FTM_XML_PARSE); - std::string full_filename = gDirUtilp->findSkinnedFilename(LLUI::getLocalizedSkinPath(), xui_filename); - if (!LLXMLNode::parseFile(full_filename, root, NULL)) - { - return false; - } - else - { - return true; - } -} - //----------------------------------------------------------------------------- // saveToXML() //----------------------------------------------------------------------------- @@ -239,8 +213,10 @@ std::string LLUICtrlFactory::getCurFileName() void LLUICtrlFactory::pushFileName(const std::string& name) -{ - mFileNames.push_back(gDirUtilp->findSkinnedFilename(LLUI::getSkinPath(), name)); +{ + // Here we seem to be looking for the default language file ("en") rather + // than the localized one, if any. + mFileNames.push_back(gDirUtilp->findSkinnedFilenameBaseLang(LLDir::XUI, name)); } void LLUICtrlFactory::popFileName() @@ -260,7 +236,7 @@ void LLUICtrlFactory::setCtrlParent(LLView* view, LLView* parent, S32 tab_group) //static std::string LLUICtrlFactory::findSkinnedFilename(const std::string& filename) { - return gDirUtilp->findSkinnedFilename(LLUI::getSkinPath(), filename); + return gDirUtilp->findSkinnedFilenameBaseLang(LLDir::XUI, filename); } //static diff --git a/indra/llui/lluictrlfactory.h b/indra/llui/lluictrlfactory.h index d612ad5005..56e5f3eb7b 100644 --- a/indra/llui/lluictrlfactory.h +++ b/indra/llui/lluictrlfactory.h @@ -169,7 +169,7 @@ public: LLView* createFromXML(LLXMLNodePtr node, LLView* parent, const std::string& filename, const widget_registry_t&, LLXMLNodePtr output_node ); template - static T* createFromFile(const std::string &filename, LLView *parent, const widget_registry_t& registry, LLXMLNodePtr output_node = NULL) + static T* createFromFile(const std::string &filename, LLView *parent, const widget_registry_t& registry) { T* widget = NULL; @@ -178,23 +178,13 @@ public: { LLXMLNodePtr root_node; - //if exporting, only load the language being exported, - //instead of layering localized version on top of english - if (output_node) - { - if (!LLUICtrlFactory::getLocalizedXMLNode(filename, root_node)) - { - llwarns << "Couldn't parse XUI file: " << filename << llendl; - goto fail; - } - } - else if (!LLUICtrlFactory::getLayeredXMLNode(filename, root_node)) + if (!LLUICtrlFactory::getLayeredXMLNode(filename, root_node)) { llwarns << "Couldn't parse XUI file: " << skinned_filename << llendl; goto fail; } - LLView* view = getInstance()->createFromXML(root_node, parent, filename, registry, output_node); + LLView* view = getInstance()->createFromXML(root_node, parent, filename, registry, NULL); if (view) { widget = dynamic_cast(view); @@ -223,7 +213,6 @@ fail: static void createChildren(LLView* viewp, LLXMLNodePtr node, const widget_registry_t&, LLXMLNodePtr output_node = NULL); static bool getLayeredXMLNode(const std::string &filename, LLXMLNodePtr& root); - static bool getLocalizedXMLNode(const std::string &xui_filename, LLXMLNodePtr& root); private: //NOTE: both friend declarations are necessary to keep both gcc and msvc happy diff --git a/indra/llvfs/lldir.cpp b/indra/llvfs/lldir.cpp index 32d081d552..a7d12476a4 100644 --- a/indra/llvfs/lldir.cpp +++ b/indra/llvfs/lldir.cpp @@ -41,6 +41,12 @@ #include "lluuid.h" #include "lldiriterator.h" +#include "stringize.h" +#include +#include +#include +#include +#include #if LL_WINDOWS #include "lldir_win32.h" @@ -58,6 +64,14 @@ LLDir_Linux gDirUtil; LLDir *gDirUtilp = (LLDir *)&gDirUtil; +/// Values for findSkinnedFilenames(subdir) parameter +const char + *LLDir::XUI = "xui", + *LLDir::TEXTURES = "textures", + *LLDir::SKINBASE = ""; + +static const char* const empty = ""; + LLDir::LLDir() : mAppName(""), mExecutablePathAndName(""), @@ -70,7 +84,8 @@ LLDir::LLDir() mOSCacheDir(""), mCAFile(""), mTempDir(""), - mDirDelimiter("/") // fallback to forward slash if not overridden + mDirDelimiter("/"), // fallback to forward slash if not overridden + mLanguage("en") { } @@ -96,9 +111,7 @@ S32 LLDir::deleteFilesInDir(const std::string &dirname, const std::string &mask) LLDirIterator iter(dirname, mask); while (iter.next(filename)) { - fullpath = dirname; - fullpath += getDirDelimiter(); - fullpath += filename; + fullpath = add(dirname, filename); if(LLFile::isdir(fullpath)) { @@ -270,12 +283,12 @@ std::string LLDir::buildSLOSCacheDir() const } else { - res = getOSUserAppDir() + mDirDelimiter + "cache"; + res = add(getOSUserAppDir(), "cache"); } } else { - res = getOSCacheDir() + mDirDelimiter + "SecondLife"; + res = add(getOSCacheDir(), "SecondLife"); } return res; } @@ -298,19 +311,24 @@ const std::string &LLDir::getDirDelimiter() const return mDirDelimiter; } +const std::string& LLDir::getDefaultSkinDir() const +{ + return mDefaultSkinDir; +} + const std::string &LLDir::getSkinDir() const { return mSkinDir; } -const std::string &LLDir::getUserSkinDir() const +const std::string &LLDir::getUserDefaultSkinDir() const { - return mUserSkinDir; + return mUserDefaultSkinDir; } -const std::string& LLDir::getDefaultSkinDir() const +const std::string &LLDir::getUserSkinDir() const { - return mDefaultSkinDir; + return mUserSkinDir; } const std::string LLDir::getSkinBaseDir() const @@ -323,6 +341,41 @@ const std::string &LLDir::getLLPluginDir() const return mLLPluginDir; } +static std::string ELLPathToString(ELLPath location) +{ + typedef std::map ELLPathMap; +#define ENT(symbol) ELLPathMap::value_type(symbol, #symbol) + static ELLPathMap::value_type init[] = + { + ENT(LL_PATH_NONE), + ENT(LL_PATH_USER_SETTINGS), + ENT(LL_PATH_APP_SETTINGS), + ENT(LL_PATH_PER_SL_ACCOUNT), // returns/expands to blank string if we don't know the account name yet + ENT(LL_PATH_CACHE), + ENT(LL_PATH_CHARACTER), + ENT(LL_PATH_HELP), + ENT(LL_PATH_LOGS), + ENT(LL_PATH_TEMP), + ENT(LL_PATH_SKINS), + ENT(LL_PATH_TOP_SKIN), + ENT(LL_PATH_CHAT_LOGS), + ENT(LL_PATH_PER_ACCOUNT_CHAT_LOGS), + ENT(LL_PATH_USER_SKIN), + ENT(LL_PATH_LOCAL_ASSETS), + ENT(LL_PATH_EXECUTABLE), + ENT(LL_PATH_DEFAULT_SKIN), + ENT(LL_PATH_FONTS), + ENT(LL_PATH_LAST) + }; +#undef ENT + static const ELLPathMap sMap(boost::begin(init), boost::end(init)); + + ELLPathMap::const_iterator found = sMap.find(location); + if (found != sMap.end()) + return found->second; + return STRINGIZE("Invalid ELLPath value " << location); +} + std::string LLDir::getExpandedFilename(ELLPath location, const std::string& filename) const { return getExpandedFilename(location, "", filename); @@ -343,15 +396,11 @@ std::string LLDir::getExpandedFilename(ELLPath location, const std::string& subd break; case LL_PATH_APP_SETTINGS: - prefix = getAppRODataDir(); - prefix += mDirDelimiter; - prefix += "app_settings"; + prefix = add(getAppRODataDir(), "app_settings"); break; case LL_PATH_CHARACTER: - prefix = getAppRODataDir(); - prefix += mDirDelimiter; - prefix += "character"; + prefix = add(getAppRODataDir(), "character"); break; case LL_PATH_HELP: @@ -363,16 +412,22 @@ std::string LLDir::getExpandedFilename(ELLPath location, const std::string& subd break; case LL_PATH_USER_SETTINGS: - prefix = getOSUserAppDir(); - prefix += mDirDelimiter; - prefix += "user_settings"; + prefix = add(getOSUserAppDir(), "user_settings"); break; case LL_PATH_PER_SL_ACCOUNT: prefix = getLindenUserDir(); if (prefix.empty()) { - // if we're asking for the per-SL-account directory but we haven't logged in yet (or otherwise don't know the account name from which to build this string), then intentionally return a blank string to the caller and skip the below warning about a blank prefix. + // if we're asking for the per-SL-account directory but we haven't + // logged in yet (or otherwise don't know the account name from + // which to build this string), then intentionally return a blank + // string to the caller and skip the below warning about a blank + // prefix. + LL_DEBUGS("LLDir") << "getLindenUserDir() not yet set: " + << ELLPathToString(location) + << ", '" << subdir1 << "', '" << subdir2 << "', '" << in_filename + << "' => ''" << LL_ENDL; return std::string(); } break; @@ -386,9 +441,7 @@ std::string LLDir::getExpandedFilename(ELLPath location, const std::string& subd break; case LL_PATH_LOGS: - prefix = getOSUserAppDir(); - prefix += mDirDelimiter; - prefix += "logs"; + prefix = add(getOSUserAppDir(), "logs"); break; case LL_PATH_TEMP: @@ -412,9 +465,7 @@ std::string LLDir::getExpandedFilename(ELLPath location, const std::string& subd break; case LL_PATH_LOCAL_ASSETS: - prefix = getAppRODataDir(); - prefix += mDirDelimiter; - prefix += "local_assets"; + prefix = add(getAppRODataDir(), "local_assets"); break; case LL_PATH_EXECUTABLE: @@ -422,56 +473,36 @@ std::string LLDir::getExpandedFilename(ELLPath location, const std::string& subd break; case LL_PATH_FONTS: - prefix = getAppRODataDir(); - prefix += mDirDelimiter; - prefix += "fonts"; + prefix = add(getAppRODataDir(), "fonts"); break; default: llassert(0); } - std::string filename = in_filename; - if (!subdir2.empty()) - { - filename = subdir2 + mDirDelimiter + filename; - } - - if (!subdir1.empty()) - { - filename = subdir1 + mDirDelimiter + filename; - } - if (prefix.empty()) { - llwarns << "prefix is empty, possible bad filename" << llendl; - } - - std::string expanded_filename; - if (!filename.empty()) - { - if (!prefix.empty()) - { - expanded_filename += prefix; - expanded_filename += mDirDelimiter; - expanded_filename += filename; - } - else - { - expanded_filename = filename; - } - } - else if (!prefix.empty()) - { - // Directory only, no file name. - expanded_filename = prefix; + llwarns << ELLPathToString(location) + << ", '" << subdir1 << "', '" << subdir2 << "', '" << in_filename + << "': prefix is empty, possible bad filename" << llendl; } - else + + std::string expanded_filename = add(add(prefix, subdir1), subdir2); + if (expanded_filename.empty() && in_filename.empty()) { - expanded_filename.assign(""); + return ""; } - - //llinfos << "*** EXPANDED FILENAME: <" << expanded_filename << ">" << llendl; + // Use explicit concatenation here instead of another add() call. Callers + // passing in_filename as "" expect to obtain a pathname ending with + // mDirSeparator so they can later directly concatenate with a specific + // filename. A caller using add() doesn't care, but there's still code + // loose in the system that uses std::string::operator+(). + expanded_filename += mDirDelimiter; + expanded_filename += in_filename; + + LL_DEBUGS("LLDir") << ELLPathToString(location) + << ", '" << subdir1 << "', '" << subdir2 << "', '" << in_filename + << "' => '" << expanded_filename << "'" << LL_ENDL; return expanded_filename; } @@ -511,31 +542,168 @@ std::string LLDir::getExtension(const std::string& filepath) const return exten; } -std::string LLDir::findSkinnedFilename(const std::string &filename) const +std::string LLDir::findSkinnedFilenameBaseLang(const std::string &subdir, + const std::string &filename, + bool merge) const { - return findSkinnedFilename("", "", filename); + // This implementation is basically just as described in the declaration comments. + std::vector found(findSkinnedFilenames(subdir, filename, merge)); + if (found.empty()) + { + return ""; + } + return found.front(); } -std::string LLDir::findSkinnedFilename(const std::string &subdir, const std::string &filename) const +std::string LLDir::findSkinnedFilename(const std::string &subdir, + const std::string &filename, + bool merge) const { - return findSkinnedFilename("", subdir, filename); + // This implementation is basically just as described in the declaration comments. + std::vector found(findSkinnedFilenames(subdir, filename, merge)); + if (found.empty()) + { + return ""; + } + return found.back(); } -std::string LLDir::findSkinnedFilename(const std::string &subdir1, const std::string &subdir2, const std::string &filename) const +std::vector LLDir::findSkinnedFilenames(const std::string& subdir, + const std::string& filename, + bool merge) const { - // generate subdirectory path fragment, e.g. "/foo/bar", "/foo", "" - std::string subdirs = ((subdir1.empty() ? "" : mDirDelimiter) + subdir1) - + ((subdir2.empty() ? "" : mDirDelimiter) + subdir2); + // Recognize subdirs that have no localization. + static const char* sUnlocalizedData[] = + { + "", // top-level directory not localized + "textures" // textures not localized + }; + static const std::set sUnlocalized(boost::begin(sUnlocalizedData), + boost::end(sUnlocalizedData)); + + LL_DEBUGS("LLDir") << "subdir '" << subdir << "', filename '" << filename + << "', merge " << std::boolalpha << merge << LL_ENDL; + + // Cache the default language directory for each subdir we've encountered. + // A cache entry whose value is the empty string means "not localized, + // don't bother checking again." + typedef std::map LocalizedMap; + static LocalizedMap sLocalized; + + // Check whether we've already discovered if this subdir is localized. + LocalizedMap::const_iterator found = sLocalized.find(subdir); + if (found == sLocalized.end()) + { + // We have not yet determined that. Is it one of the subdirs "known" + // to be unlocalized? + if (sUnlocalized.find(subdir) != sUnlocalized.end()) + { + // This subdir is known to be unlocalized. Remember that. + found = sLocalized.insert(LocalizedMap::value_type(subdir, "")).first; + } + else + { + // We do not recognize this subdir. Investigate. + std::string subdir_path(add(getDefaultSkinDir(), subdir)); + if (fileExists(add(subdir_path, "en"))) + { + // defaultSkinDir/subdir contains subdir "en". That's our + // default language; this subdir is localized. + found = sLocalized.insert(LocalizedMap::value_type(subdir, "en")).first; + } + else if (fileExists(add(subdir_path, "en-us"))) + { + // defaultSkinDir/subdir contains subdir "en-us" but not "en". + // Set as default language; this subdir is localized. + found = sLocalized.insert(LocalizedMap::value_type(subdir, "en-us")).first; + } + else + { + // defaultSkinDir/subdir contains neither "en" nor "en-us". + // Assume it's not localized. Remember that assumption. + found = sLocalized.insert(LocalizedMap::value_type(subdir, "")).first; + } + } + } + // Every code path above should have resulted in 'found' becoming a valid + // iterator to an entry in sLocalized. + llassert(found != sLocalized.end()); + + // Now -- is this subdir localized, or not? The answer determines what + // subdirectories we check (under subdir) for the requested filename. + std::vector subsubdirs; + if (found->second.empty()) + { + // subdir is not localized. filename should be located directly within it. + subsubdirs.push_back(""); + } + else + { + // subdir is localized, and found->second is the default language + // directory within it. Check both the default language and the + // current language -- if it differs from the default, of course. + subsubdirs.push_back(found->second); + if (mLanguage != found->second) + { + subsubdirs.push_back(mLanguage); + } + } + // Code below relies on subsubdirs not being empty: more specifically, on + // front() being valid. There may or may not be additional entries, but we + // have at least one. For an unlocalized subdir, it's the only one; for a + // localized subdir, it's the default one. + llassert(! subsubdirs.empty()); + + // Build results vector. + std::vector results; + BOOST_FOREACH(std::string skindir, mSearchSkinDirs) + { + std::string subdir_path(add(skindir, subdir)); + // Does subdir_path/subsubdirs[0]/filename exist? If there's more than + // one entry in subsubdirs, the first is the default language ("en"), + // the second is the current language. A skin that contains + // subdir/language/filename without also containing subdir/en/filename + // is ill-formed: skip any such skin. So to decide whether to keep + // this skin dir or skip it, we need only check for the existence of + // the first subsubdir entry ("en" or only). + std::string subsubdir_path(add(add(subdir_path, subsubdirs.front()), filename)); + if (! fileExists(subsubdir_path)) + continue; - std::vector search_paths; - - search_paths.push_back(getUserSkinDir() + subdirs); // first look in user skin override - search_paths.push_back(getSkinDir() + subdirs); // then in current skin - search_paths.push_back(getDefaultSkinDir() + subdirs); // then default skin - search_paths.push_back(getCacheDir() + subdirs); // and last in preload directory + // Here the desired filename exists in the first subsubdir. That means + // this is a skindir we want to record in results. But if the caller + // passed merge=false, we must discard all previous skindirs. + if (! merge) + { + results.clear(); + } + + // Now add every subsubdir in which filename exists. We already know + // it exists in the first one. + results.push_back(subsubdir_path); + + // Append all remaining subsubdirs in which filename exists. + for (std::vector::const_iterator ssdi(subsubdirs.begin() + 1), ssdend(subsubdirs.end()); + ssdi != ssdend; ++ssdi) + { + subsubdir_path = add(add(subdir_path, *ssdi), filename); + if (fileExists(subsubdir_path)) + { + results.push_back(subsubdir_path); + } + } + } - std::string found_file = findFile(filename, search_paths); - return found_file; + LL_DEBUGS("LLDir") << empty; + const char* comma = ""; + BOOST_FOREACH(std::string path, results) + { + LL_CONT << comma << "'" << path << "'"; + comma = ", "; + } + LL_CONT << LL_ENDL; + + return results; } std::string LLDir::getTempFilename() const @@ -546,12 +714,7 @@ std::string LLDir::getTempFilename() const random_uuid.generate(); random_uuid.toString(uuid_str); - std::string temp_filename = getTempDir(); - temp_filename += mDirDelimiter; - temp_filename += uuid_str; - temp_filename += ".tmp"; - - return temp_filename; + return add(getTempDir(), uuid_str + ".tmp"); } // static @@ -587,9 +750,7 @@ void LLDir::setLindenUserDir(const std::string &username) std::string userlower(username); LLStringUtil::toLower(userlower); LLStringUtil::replaceChar(userlower, ' ', '_'); - mLindenUserDir = getOSUserAppDir(); - mLindenUserDir += mDirDelimiter; - mLindenUserDir += userlower; + mLindenUserDir = add(getOSUserAppDir(), userlower); } else { @@ -621,9 +782,7 @@ void LLDir::setPerAccountChatLogsDir(const std::string &username) std::string userlower(username); LLStringUtil::toLower(userlower); LLStringUtil::replaceChar(userlower, ' ', '_'); - mPerAccountChatLogsDir = getChatLogsDir(); - mPerAccountChatLogsDir += mDirDelimiter; - mPerAccountChatLogsDir += userlower; + mPerAccountChatLogsDir = add(getChatLogsDir(), userlower); } else { @@ -632,25 +791,59 @@ void LLDir::setPerAccountChatLogsDir(const std::string &username) } -void LLDir::setSkinFolder(const std::string &skin_folder) +void LLDir::setSkinFolder(const std::string &skin_folder, const std::string& language) { - mSkinDir = getSkinBaseDir(); - mSkinDir += mDirDelimiter; - mSkinDir += skin_folder; + LL_DEBUGS("LLDir") << "Setting skin '" << skin_folder << "', language '" << language << "'" + << LL_ENDL; + mSkinName = skin_folder; + mLanguage = language; - // user modifications to current skin - // e.g. c:\documents and settings\users\username\application data\second life\skins\dazzle - mUserSkinDir = getOSUserAppDir(); - mUserSkinDir += mDirDelimiter; - mUserSkinDir += "skins"; - mUserSkinDir += mDirDelimiter; - mUserSkinDir += skin_folder; + // This method is called multiple times during viewer initialization. Each + // time it's called, reset mSearchSkinDirs. + mSearchSkinDirs.clear(); // base skin which is used as fallback for all skinned files // e.g. c:\program files\secondlife\skins\default mDefaultSkinDir = getSkinBaseDir(); - mDefaultSkinDir += mDirDelimiter; - mDefaultSkinDir += "default"; + append(mDefaultSkinDir, "default"); + // This is always the most general of the search skin directories. + addSearchSkinDir(mDefaultSkinDir); + + mSkinDir = getSkinBaseDir(); + append(mSkinDir, skin_folder); + // Next level of generality is a skin installed with the viewer. + addSearchSkinDir(mSkinDir); + + // user modifications to skins, current and default + // e.g. c:\documents and settings\users\username\application data\second life\skins\dazzle + mUserSkinDir = getOSUserAppDir(); + append(mUserSkinDir, "skins"); + mUserDefaultSkinDir = mUserSkinDir; + append(mUserDefaultSkinDir, "default"); + append(mUserSkinDir, skin_folder); + // Next level of generality is user modifications to default skin... + addSearchSkinDir(mUserDefaultSkinDir); + // then user-defined skins. + addSearchSkinDir(mUserSkinDir); +} + +void LLDir::addSearchSkinDir(const std::string& skindir) +{ + if (std::find(mSearchSkinDirs.begin(), mSearchSkinDirs.end(), skindir) == mSearchSkinDirs.end()) + { + LL_DEBUGS("LLDir") << "search skin: '" << skindir << "'" << LL_ENDL; + mSearchSkinDirs.push_back(skindir); + } +} + +std::string LLDir::getSkinFolder() const +{ + return mSkinName; +} + +std::string LLDir::getLanguage() const +{ + return mLanguage; } bool LLDir::setCacheDir(const std::string &path) @@ -664,7 +857,7 @@ bool LLDir::setCacheDir(const std::string &path) else { LLFile::mkdir(path); - std::string tempname = path + mDirDelimiter + "temp"; + std::string tempname = add(path, "temp"); LLFILE* file = LLFile::fopen(tempname,"wt"); if (file) { @@ -697,6 +890,57 @@ void LLDir::dumpCurrentDirectories() LL_DEBUGS2("AppInit","Directories") << " SkinDir: " << getSkinDir() << LL_ENDL; } +std::string LLDir::add(const std::string& path, const std::string& name) const +{ + std::string destpath(path); + append(destpath, name); + return destpath; +} + +void LLDir::append(std::string& destpath, const std::string& name) const +{ + // Delegate question of whether we need a separator to helper method. + SepOff sepoff(needSep(destpath, name)); + if (sepoff.first) // do we need a separator? + { + destpath += mDirDelimiter; + } + // If destpath ends with a separator, AND name starts with one, skip + // name's leading separator. + destpath += name.substr(sepoff.second); +} + +LLDir::SepOff LLDir::needSep(const std::string& path, const std::string& name) const +{ + if (path.empty() || name.empty()) + { + // If either path or name are empty, we do not need a separator + // between them. + return SepOff(false, 0); + } + // Here we know path and name are both non-empty. But if path already ends + // with a separator, or if name already starts with a separator, we need + // not add one. + std::string::size_type seplen(mDirDelimiter.length()); + bool path_ends_sep(path.substr(path.length() - seplen) == mDirDelimiter); + bool name_starts_sep(name.substr(0, seplen) == mDirDelimiter); + if ((! path_ends_sep) && (! name_starts_sep)) + { + // If neither path nor name brings a separator to the junction, then + // we need one. + return SepOff(true, 0); + } + if (path_ends_sep && name_starts_sep) + { + // But if BOTH path and name bring a separator, we need not add one. + // Moreover, we should actually skip the leading separator of 'name'. + return SepOff(false, seplen); + } + // Here we know that either path_ends_sep or name_starts_sep is true -- + // but not both. So don't add a separator, and don't skip any characters: + // simple concatenation will do the trick. + return SepOff(false, 0); +} void dir_exists_or_crash(const std::string &dir_name) { diff --git a/indra/llvfs/lldir.h b/indra/llvfs/lldir.h index 5ee8bdb542..a242802979 100644 --- a/indra/llvfs/lldir.h +++ b/indra/llvfs/lldir.h @@ -56,7 +56,7 @@ typedef enum ELLPath LL_PATH_LAST } ELLPath; - +/// Directory operations class LLDir { public: @@ -100,9 +100,10 @@ class LLDir const std::string &getOSCacheDir() const; // location of OS-specific cache folder (may be empty string) const std::string &getCAFile() const; // File containing TLS certificate authorities const std::string &getDirDelimiter() const; // directory separator for platform (ie. '\' or '/' or ':') + const std::string &getDefaultSkinDir() const; // folder for default skin. e.g. c:\program files\second life\skins\default const std::string &getSkinDir() const; // User-specified skin folder. + const std::string &getUserDefaultSkinDir() const; // dir with user modifications to default skin const std::string &getUserSkinDir() const; // User-specified skin folder with user modifications. e.g. c:\documents and settings\username\application data\second life\skins\curskin - const std::string &getDefaultSkinDir() const; // folder for default skin. e.g. c:\program files\second life\skins\default const std::string getSkinBaseDir() const; // folder that contains all installed skins (not user modifications). e.g. c:\program files\second life\skins const std::string &getLLPluginDir() const; // Directory containing plugins and plugin shell @@ -117,10 +118,59 @@ class LLDir std::string getExtension(const std::string& filepath) const; // Excludes '.', e.g getExtension("foo.wav") == "wav" // these methods search the various skin paths for the specified file in the following order: - // getUserSkinDir(), getSkinDir(), getDefaultSkinDir() - std::string findSkinnedFilename(const std::string &filename) const; - std::string findSkinnedFilename(const std::string &subdir, const std::string &filename) const; - std::string findSkinnedFilename(const std::string &subdir1, const std::string &subdir2, const std::string &filename) const; + // getUserSkinDir(), getUserDefaultSkinDir(), getSkinDir(), getDefaultSkinDir() + /** + * Given a filename within skin, return an ordered sequence of paths to + * search. Nonexistent files will be filtered out -- which means that the + * vector might be empty. + * + * @param subdir Identify top-level skin subdirectory by passing one of + * LLDir::XUI (file lives under "xui" subtree), LLDir::TEXTURES (file + * lives under "textures" subtree), LLDir::SKINBASE (file lives at top + * level of skin subdirectory). + * @param filename Desired filename within subdir within skin, e.g. + * "panel_login.xml". DO NOT prepend (e.g.) "xui" or the desired language. + * @param merge Callers perform two different kinds of processing. When + * fetching a XUI file, for instance, the existence of @a filename in the + * specified skin completely supercedes any @a filename in the default + * skin. For that case, leave the default @a merge=false. The returned + * vector will contain only + * ".../current_skin/xui/en/filename", + * ".../current_skin/xui/current_language/filename". + * But for (e.g.) "strings.xml", we want a given skin to be able to + * override only specific entries from the default skin. Any string not + * defined in the specified skin will be sought in the default skin. For + * that case, pass @a merge=true. The returned vector will contain at + * least ".../default/xui/en/strings.xml", + * ".../default/xui/current_language/strings.xml", + * ".../current_skin/xui/en/strings.xml", + * ".../current_skin/xui/current_language/strings.xml". + */ + std::vector findSkinnedFilenames(const std::string& subdir, + const std::string& filename, + bool merge=false) const; + /// Values for findSkinnedFilenames(subdir) parameter + static const char *XUI, *TEXTURES, *SKINBASE; + /** + * Return the base-language pathname from findSkinnedFilenames(), or + * the empty string if no such file exists. Parameters are identical to + * findSkinnedFilenames(). This is shorthand for capturing the vector + * returned by findSkinnedFilenames(), checking for empty() and then + * returning front(). + */ + std::string findSkinnedFilenameBaseLang(const std::string &subdir, + const std::string &filename, + bool merge=false) const; + /** + * Return the "most localized" pathname from findSkinnedFilenames(), or + * the empty string if no such file exists. Parameters are identical to + * findSkinnedFilenames(). This is shorthand for capturing the vector + * returned by findSkinnedFilenames(), checking for empty() and then + * returning back(). + */ + std::string findSkinnedFilename(const std::string &subdir, + const std::string &filename, + bool merge=false) const; // random filename in common temporary directory std::string getTempFilename() const; @@ -132,15 +182,30 @@ class LLDir virtual void setChatLogsDir(const std::string &path); // Set the chat logs dir to this user's dir virtual void setPerAccountChatLogsDir(const std::string &username); // Set the per user chat log directory. virtual void setLindenUserDir(const std::string &username); // Set the linden user dir to this user's dir - virtual void setSkinFolder(const std::string &skin_folder); + virtual void setSkinFolder(const std::string &skin_folder, const std::string& language); + virtual std::string getSkinFolder() const; + virtual std::string getLanguage() const; virtual bool setCacheDir(const std::string &path); virtual void dumpCurrentDirectories(); - + // Utility routine std::string buildSLOSCacheDir() const; + /// Append specified @a name to @a destpath, separated by getDirDelimiter() + /// if both are non-empty. + void append(std::string& destpath, const std::string& name) const; + /// Append specified @a name to @a path, separated by getDirDelimiter() + /// if both are non-empty. Return result, leaving @a path unmodified. + std::string add(const std::string& path, const std::string& name) const; + protected: + // Does an add() or append() call need a directory delimiter? + typedef std::pair SepOff; + SepOff needSep(const std::string& path, const std::string& name) const; + // build mSearchSkinDirs without adding duplicates + void addSearchSkinDir(const std::string& skindir); + std::string mAppName; // install directory under progams/ ie "SecondLife" std::string mExecutablePathAndName; // full path + Filename of .exe std::string mExecutableFilename; // Filename of .exe @@ -158,10 +223,18 @@ protected: std::string mDefaultCacheDir; // default cache diretory std::string mOSCacheDir; // operating system cache dir std::string mDirDelimiter; + std::string mSkinName; // caller-specified skin name std::string mSkinBaseDir; // Base for skins paths. - std::string mSkinDir; // Location for current skin info. std::string mDefaultSkinDir; // Location for default skin info. + std::string mSkinDir; // Location for current skin info. + std::string mUserDefaultSkinDir; // Location for default skin info. std::string mUserSkinDir; // Location for user-modified skin info. + // Skin directories to search, most general to most specific. This order + // works well for composing fine-grained files, in which an individual item + // in a specific file overrides the corresponding item in more general + // files. Of course, for a file-level search, iterate backwards. + std::vector mSearchSkinDirs; + std::string mLanguage; // Current viewer language std::string mLLPluginDir; // Location for plugins and plugin shell }; diff --git a/indra/llvfs/tests/lldir_test.cpp b/indra/llvfs/tests/lldir_test.cpp index ea321c5ae9..a00fc8684c 100644 --- a/indra/llvfs/tests/lldir_test.cpp +++ b/indra/llvfs/tests/lldir_test.cpp @@ -27,11 +27,161 @@ #include "linden_common.h" +#include "llstring.h" +#include "tests/StringVec.h" #include "../lldir.h" #include "../lldiriterator.h" #include "../test/lltut.h" +#include "stringize.h" +#include +#include + +using boost::assign::list_of; + +// We use ensure_equals(..., vec(list_of(...))) not because it's functionally +// required, but because ensure_equals() knows how to format a StringVec. +// Turns out that when ensure_equals() displays a test failure with just +// list_of("string")("another"), you see 'stringanother' vs. '("string", +// "another")'. +StringVec vec(const StringVec& v) +{ + return v; +} +// For some tests, use a dummy LLDir that uses memory data instead of touching +// the filesystem +struct LLDir_Dummy: public LLDir +{ + /*----------------------------- LLDir API ------------------------------*/ + LLDir_Dummy() + { + // Initialize important LLDir data members based on the filesystem + // data below. + mDirDelimiter = "/"; + mExecutableDir = "install"; + mExecutableFilename = "test"; + mExecutablePathAndName = add(mExecutableDir, mExecutableFilename); + mWorkingDir = mExecutableDir; + mAppRODataDir = "install"; + mSkinBaseDir = add(mAppRODataDir, "skins"); + mOSUserDir = "user"; + mOSUserAppDir = mOSUserDir; + mLindenUserDir = ""; + + // Make the dummy filesystem look more or less like what we expect in + // the real one. + static const char* preload[] = + { + "install/skins/default/colors.xml", + "install/skins/default/xui/en/strings.xml", + "install/skins/default/xui/fr/strings.xml", + "install/skins/default/xui/en/floater.xml", + "install/skins/default/xui/fr/floater.xml", + "install/skins/default/xui/en/newfile.xml", + "install/skins/default/xui/fr/newfile.xml", + "install/skins/default/html/en-us/welcome.html", + "install/skins/default/html/fr/welcome.html", + "install/skins/default/textures/only_default.jpeg", + "install/skins/default/future/somefile.txt", + "install/skins/steam/colors.xml", + "install/skins/steam/xui/en/strings.xml", + "install/skins/steam/xui/fr/strings.xml", + "install/skins/steam/textures/only_steam.jpeg", + "user/skins/default/colors.xml", + "user/skins/default/xui/en/strings.xml", + "user/skins/default/xui/fr/strings.xml", + // This is an attempted override that doesn't work: for a + // localized subdir, a skin must have subdir/en/filename as well + // as subdir/language/filename. + "user/skins/default/xui/fr/floater.xml", + // This is an override that only specifies the "en" version + "user/skins/default/xui/en/newfile.xml", + "user/skins/default/textures/only_user_default.jpeg", + "user/skins/steam/colors.xml", + "user/skins/steam/xui/en/strings.xml", + "user/skins/steam/xui/fr/strings.xml", + "user/skins/steam/textures/only_user_steam.jpeg" + }; + BOOST_FOREACH(const char* path, preload) + { + buildFilesystem(path); + } + } + + virtual ~LLDir_Dummy() {} + + virtual void initAppDirs(const std::string& app_name, const std::string& app_read_only_data_dir) + { + // Implement this when we write a test that needs it + } + + virtual std::string getCurPath() + { + // Implement this when we write a test that needs it + return ""; + } + + virtual U32 countFilesInDir(const std::string& dirname, const std::string& mask) + { + // Implement this when we write a test that needs it + return 0; + } + + virtual BOOL fileExists(const std::string& pathname) const + { + // Record fileExists() calls so we can check whether caching is + // working right. Certain LLDir calls should be able to make decisions + // without calling fileExists() again, having already checked existence. + mChecked.insert(pathname); + // For our simple flat set of strings, see whether the identical + // pathname exists in our set. + return (mFilesystem.find(pathname) != mFilesystem.end()); + } + + virtual std::string getLLPluginLauncher() + { + // Implement this when we write a test that needs it + return ""; + } + + virtual std::string getLLPluginFilename(std::string base_name) + { + // Implement this when we write a test that needs it + return ""; + } + + /*----------------------------- Dummy data -----------------------------*/ + void clearFilesystem() { mFilesystem.clear(); } + void buildFilesystem(const std::string& path) + { + // Split the pathname on slashes, ignoring leading, trailing, doubles + StringVec components; + LLStringUtil::getTokens(path, components, "/"); + // Ensure we have an entry representing every level of this path + std::string partial; + BOOST_FOREACH(std::string component, components) + { + append(partial, component); + mFilesystem.insert(partial); + } + } + + void clear_checked() { mChecked.clear(); } + void ensure_checked(const std::string& pathname) const + { + tut::ensure(STRINGIZE(pathname << " was not checked but should have been"), + mChecked.find(pathname) != mChecked.end()); + } + void ensure_not_checked(const std::string& pathname) const + { + tut::ensure(STRINGIZE(pathname << " was checked but should not have been"), + mChecked.find(pathname) == mChecked.end()); + } + + std::set mFilesystem; + mutable std::set mChecked; +}; namespace tut { @@ -419,5 +569,192 @@ namespace tut LLFile::rmdir(dir1); LLFile::rmdir(dir2); } -} + template<> template<> + void LLDirTest_object_t::test<6>() + { + set_test_name("findSkinnedFilenames()"); + LLDir_Dummy lldir; + /*------------------------ "default", "en" -------------------------*/ + // Setting "default" means we shouldn't consider any "*/skins/steam" + // directories; setting "en" means we shouldn't consider any "xui/fr" + // directories. + lldir.setSkinFolder("default", "en"); + ensure_equals(lldir.getSkinFolder(), "default"); + ensure_equals(lldir.getLanguage(), "en"); + + // top-level directory of a skin isn't localized + ensure_equals(lldir.findSkinnedFilenames(LLDir::SKINBASE, "colors.xml", true), + vec(list_of("install/skins/default/colors.xml") + ("user/skins/default/colors.xml"))); + // We should not have needed to check for skins/default/en. We should + // just "know" that SKINBASE is not localized. + lldir.ensure_not_checked("install/skins/default/en"); + + ensure_equals(lldir.findSkinnedFilenames(LLDir::TEXTURES, "only_default.jpeg"), + vec(list_of("install/skins/default/textures/only_default.jpeg"))); + // Nor should we have needed to check skins/default/textures/en + // because textures is known to be unlocalized. + lldir.ensure_not_checked("install/skins/default/textures/en"); + + StringVec expected(vec(list_of("install/skins/default/xui/en/strings.xml") + ("user/skins/default/xui/en/strings.xml"))); + ensure_equals(lldir.findSkinnedFilenames(LLDir::XUI, "strings.xml", true), + expected); + // The first time, we had to probe to find out whether xui was localized. + lldir.ensure_checked("install/skins/default/xui/en"); + lldir.clear_checked(); + // Now make the same call again -- should return same result -- + ensure_equals(lldir.findSkinnedFilenames(LLDir::XUI, "strings.xml", true), + expected); + // but this time it should remember that xui is localized. + lldir.ensure_not_checked("install/skins/default/xui/en"); + + // localized subdir with "en-us" instead of "en" + ensure_equals(lldir.findSkinnedFilenames("html", "welcome.html"), + vec(list_of("install/skins/default/html/en-us/welcome.html"))); + lldir.ensure_checked("install/skins/default/html/en"); + lldir.ensure_checked("install/skins/default/html/en-us"); + lldir.clear_checked(); + ensure_equals(lldir.findSkinnedFilenames("html", "welcome.html"), + vec(list_of("install/skins/default/html/en-us/welcome.html"))); + lldir.ensure_not_checked("install/skins/default/html/en"); + lldir.ensure_not_checked("install/skins/default/html/en-us"); + + ensure_equals(lldir.findSkinnedFilenames("future", "somefile.txt"), + vec(list_of("install/skins/default/future/somefile.txt"))); + // Test probing for an unrecognized unlocalized future subdir. + lldir.ensure_checked("install/skins/default/future/en"); + lldir.clear_checked(); + ensure_equals(lldir.findSkinnedFilenames("future", "somefile.txt"), + vec(list_of("install/skins/default/future/somefile.txt"))); + // Second time it should remember that future is unlocalized. + lldir.ensure_not_checked("install/skins/default/future/en"); + + // When language is set to "en", requesting an html file pulls up the + // "en-us" version -- not because it magically matches those strings, + // but because there's no "en" localization and it falls back on the + // default "en-us"! Note that it would probably still be better to + // make the default localization be "en" and allow "en-gb" (or + // whatever) localizations, which would work much more the way you'd + // expect. + ensure_equals(lldir.findSkinnedFilenames("html", "welcome.html"), + vec(list_of("install/skins/default/html/en-us/welcome.html"))); + + /*------------------------ "default", "fr" -------------------------*/ + // We start being able to distinguish localized subdirs from + // unlocalized when we ask for a non-English language. + lldir.setSkinFolder("default", "fr"); + ensure_equals(lldir.getLanguage(), "fr"); + + // pass merge=true to request this filename in all relevant skins + ensure_equals(lldir.findSkinnedFilenames(LLDir::XUI, "strings.xml", true), + vec(list_of + ("install/skins/default/xui/en/strings.xml") + ("install/skins/default/xui/fr/strings.xml") + ("user/skins/default/xui/en/strings.xml") + ("user/skins/default/xui/fr/strings.xml"))); + + // pass (or default) merge=false to request only most specific skin + ensure_equals(lldir.findSkinnedFilenames(LLDir::XUI, "strings.xml"), + vec(list_of + ("user/skins/default/xui/en/strings.xml") + ("user/skins/default/xui/fr/strings.xml"))); + + // The most specific skin for our dummy floater.xml is the installed + // default. Although we have a user xui/fr/floater.xml, we would also + // need a xui/en/floater.xml file to consider the user skin for this. + ensure_equals(lldir.findSkinnedFilenames(LLDir::XUI, "floater.xml"), + vec(list_of + ("install/skins/default/xui/en/floater.xml") + ("install/skins/default/xui/fr/floater.xml"))); + + // The user override for the default skin does define newfile.xml, but + // only an "en" version, not a "fr" version as well. Nonetheless + // that's the most specific skin we have, regardless of the existence + // of a "fr" version in the installed default skin. + ensure_equals(lldir.findSkinnedFilenames(LLDir::XUI, "newfile.xml"), + vec(list_of("user/skins/default/xui/en/newfile.xml"))); + + ensure_equals(lldir.findSkinnedFilenames("html", "welcome.html"), + vec(list_of + ("install/skins/default/html/en-us/welcome.html") + ("install/skins/default/html/fr/welcome.html"))); + + /*------------------------ "default", "zh" -------------------------*/ + lldir.setSkinFolder("default", "zh"); + // Because the user default skins strings.xml has only a "fr" override + // but not a "zh" override, the most localized version we can find is "en". + ensure_equals(lldir.findSkinnedFilenames(LLDir::XUI, "strings.xml"), + vec(list_of("user/skins/default/xui/en/strings.xml"))); + + /*------------------------- "steam", "en" --------------------------*/ + lldir.setSkinFolder("steam", "en"); + + ensure_equals(lldir.findSkinnedFilenames(LLDir::SKINBASE, "colors.xml", true), + vec(list_of + ("install/skins/default/colors.xml") + ("install/skins/steam/colors.xml") + ("user/skins/default/colors.xml") + ("user/skins/steam/colors.xml"))); + + ensure_equals(lldir.findSkinnedFilenames(LLDir::TEXTURES, "only_default.jpeg"), + vec(list_of("install/skins/default/textures/only_default.jpeg"))); + + ensure_equals(lldir.findSkinnedFilenames(LLDir::TEXTURES, "only_steam.jpeg"), + vec(list_of("install/skins/steam/textures/only_steam.jpeg"))); + + ensure_equals(lldir.findSkinnedFilenames(LLDir::TEXTURES, "only_user_default.jpeg"), + vec(list_of("user/skins/default/textures/only_user_default.jpeg"))); + + ensure_equals(lldir.findSkinnedFilenames(LLDir::TEXTURES, "only_user_steam.jpeg"), + vec(list_of("user/skins/steam/textures/only_user_steam.jpeg"))); + + // merge=false + ensure_equals(lldir.findSkinnedFilenames(LLDir::XUI, "strings.xml"), + vec(list_of("user/skins/steam/xui/en/strings.xml"))); + + // pass merge=true to request this filename in all relevant skins + ensure_equals(lldir.findSkinnedFilenames(LLDir::XUI, "strings.xml", true), + vec(list_of + ("install/skins/default/xui/en/strings.xml") + ("install/skins/steam/xui/en/strings.xml") + ("user/skins/default/xui/en/strings.xml") + ("user/skins/steam/xui/en/strings.xml"))); + + /*------------------------- "steam", "fr" --------------------------*/ + lldir.setSkinFolder("steam", "fr"); + + // pass merge=true to request this filename in all relevant skins + ensure_equals(lldir.findSkinnedFilenames(LLDir::XUI, "strings.xml"), + vec(list_of + ("user/skins/steam/xui/en/strings.xml") + ("user/skins/steam/xui/fr/strings.xml"))); + + // pass merge=true to request this filename in all relevant skins + ensure_equals(lldir.findSkinnedFilenames(LLDir::XUI, "strings.xml", true), + vec(list_of + ("install/skins/default/xui/en/strings.xml") + ("install/skins/default/xui/fr/strings.xml") + ("install/skins/steam/xui/en/strings.xml") + ("install/skins/steam/xui/fr/strings.xml") + ("user/skins/default/xui/en/strings.xml") + ("user/skins/default/xui/fr/strings.xml") + ("user/skins/steam/xui/en/strings.xml") + ("user/skins/steam/xui/fr/strings.xml"))); + } + + template<> template<> + void LLDirTest_object_t::test<7>() + { + set_test_name("add()"); + LLDir_Dummy lldir; + ensure_equals("both empty", lldir.add("", ""), ""); + ensure_equals("path empty", lldir.add("", "b"), "b"); + ensure_equals("name empty", lldir.add("a", ""), "a"); + ensure_equals("both simple", lldir.add("a", "b"), "a/b"); + ensure_equals("name leading slash", lldir.add("a", "/b"), "a/b"); + ensure_equals("path trailing slash", lldir.add("a/", "b"), "a/b"); + ensure_equals("both bring slashes", lldir.add("a/", "/b"), "a/b"); + } +} diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index e8934d9a9e..e7a8a52a75 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -122,7 +122,6 @@ #include - #if LL_WINDOWS # include // For _SH_DENYWR in initMarkerFile #else @@ -684,7 +683,7 @@ bool LLAppViewer::init() gDirUtilp->initAppDirs("SecondLife"); // set skin search path to default, will be overridden later // this allows simple skinned file lookups to work - gDirUtilp->setSkinFolder("default"); + gDirUtilp->setSkinFolder("default", "en"); initLogging(); @@ -768,12 +767,16 @@ bool LLAppViewer::init() &LLUI::sGLScaleFactor); LL_INFOS("InitInfo") << "UI initialized." << LL_ENDL ; - // Setup paths and LLTrans after LLUI::initClass has been called. - LLUI::setupPaths(); + // NOW LLUI::getLanguage() should work. gDirUtilp must know the language + // for this session ASAP so all the file-loading commands that follow, + // that use findSkinnedFilenames(), will include the localized files. + gDirUtilp->setSkinFolder(gDirUtilp->getSkinFolder(), LLUI::getLanguage()); + + // Setup LLTrans after LLUI::initClass has been called. LLTransUtil::parseStrings("strings.xml", default_trans_args); LLTransUtil::parseLanguageStrings("language_settings.xml"); - // Setup notifications after LLUI::setupPaths() has been called. + // Setup notifications after LLUI::initClass() has been called. LLNotifications::instance(); LL_INFOS("InitInfo") << "Notifications initialized." << LL_ENDL ; @@ -2242,8 +2245,7 @@ bool LLAppViewer::initConfiguration() OSMessageBox(msg.str(),LLStringUtil::null,OSMB_OK); return false; } - - LLUI::setupPaths(); // setup paths for LLTrans based on settings files only + LLTransUtil::parseStrings("strings.xml", default_trans_args); LLTransUtil::parseLanguageStrings("language_settings.xml"); // - set procedural settings @@ -2559,13 +2561,15 @@ bool LLAppViewer::initConfiguration() LLStartUp::setStartSLURL(start_slurl); } - const LLControlVariable* skinfolder = gSavedSettings.getControl("SkinCurrent"); - if(skinfolder && LLStringUtil::null != skinfolder->getValue().asString()) - { - // hack to force the skin to default. - gDirUtilp->setSkinFolder(skinfolder->getValue().asString()); - //gDirUtilp->setSkinFolder("default"); - } + const LLControlVariable* skinfolder = gSavedSettings.getControl("SkinCurrent"); + if(skinfolder && LLStringUtil::null != skinfolder->getValue().asString()) + { + // Examining "Language" may not suffice -- see LLUI::getLanguage() + // logic. Unfortunately LLUI::getLanguage() doesn't yet do us much + // good because we haven't yet called LLUI::initClass(). + gDirUtilp->setSkinFolder(skinfolder->getValue().asString(), + gSavedSettings.getString("Language")); + } if (gSavedSettings.getBOOL("SpellCheck")) { @@ -3589,8 +3593,7 @@ void LLAppViewer::migrateCacheDirectory() { gSavedSettings.setBOOL("MigrateCacheDirectory", FALSE); - std::string delimiter = gDirUtilp->getDirDelimiter(); - std::string old_cache_dir = gDirUtilp->getOSUserAppDir() + delimiter + "cache"; + std::string old_cache_dir = gDirUtilp->add(gDirUtilp->getOSUserAppDir(), "cache"); std::string new_cache_dir = gDirUtilp->getCacheDir(true); if (gDirUtilp->fileExists(old_cache_dir)) @@ -3606,8 +3609,8 @@ void LLAppViewer::migrateCacheDirectory() while (iter.next(file_name)) { if (file_name == "." || file_name == "..") continue; - std::string source_path = old_cache_dir + delimiter + file_name; - std::string dest_path = new_cache_dir + delimiter + file_name; + std::string source_path = gDirUtilp->add(old_cache_dir, file_name); + std::string dest_path = gDirUtilp->add(new_cache_dir, file_name); if (!LLFile::rename(source_path, dest_path)) { file_count++; @@ -3838,7 +3841,7 @@ bool LLAppViewer::initCache() LLDirIterator iter(dir, mask); if (iter.next(found_file)) { - old_vfs_data_file = dir + gDirUtilp->getDirDelimiter() + found_file; + old_vfs_data_file = gDirUtilp->add(dir, found_file); S32 start_pos = found_file.find_last_of('.'); if (start_pos > 0) @@ -5149,20 +5152,20 @@ void LLAppViewer::launchUpdater() // we tell the updater where to find the xml containing string // translations which it can use for its own UI std::string xml_strings_file = "strings.xml"; - std::vector xui_path_vec = LLUI::getXUIPaths(); + std::vector xui_path_vec = + gDirUtilp->findSkinnedFilenames(LLDir::XUI, xml_strings_file); std::string xml_search_paths; - std::vector::const_iterator iter; + const char* delim = ""; // build comma-delimited list of xml paths to pass to updater - for (iter = xui_path_vec.begin(); iter != xui_path_vec.end(); ) - { - std::string this_skin_dir = gDirUtilp->getDefaultSkinDir() - + gDirUtilp->getDirDelimiter() - + (*iter); - llinfos << "Got a XUI path: " << this_skin_dir << llendl; - xml_search_paths.append(this_skin_dir); - ++iter; - if (iter != xui_path_vec.end()) - xml_search_paths.append(","); // comma-delimit + BOOST_FOREACH(std::string this_skin_path, xui_path_vec) + { + // Although we already have the full set of paths with the filename + // appended, the linux-updater.bin command-line switches require us to + // snip the filename OFF and pass it as a separate switch argument. :-P + llinfos << "Got a XUI path: " << this_skin_path << llendl; + xml_search_paths.append(delim); + xml_search_paths.append(gDirUtilp->getDirName(this_skin_path)); + delim = ","; } // build the overall command-line to run the updater correctly LLAppViewer::sUpdaterInfo->mUpdateExePath = diff --git a/indra/newview/lldaycyclemanager.cpp b/indra/newview/lldaycyclemanager.cpp index 347a467a8b..8af2f4ea33 100644 --- a/indra/newview/lldaycyclemanager.cpp +++ b/indra/newview/lldaycyclemanager.cpp @@ -184,7 +184,7 @@ void LLDayCycleManager::loadPresets(const std::string& dir) { std::string file; if (!dir_iter.next(file)) break; // no more files - loadPreset(dir + file); + loadPreset(gDirUtilp->add(dir, file)); } } diff --git a/indra/newview/llfloateruipreview.cpp b/indra/newview/llfloateruipreview.cpp index d741b5b133..15e0b89f6c 100644 --- a/indra/newview/llfloateruipreview.cpp +++ b/indra/newview/llfloateruipreview.cpp @@ -137,7 +137,7 @@ public: virtual ~LLFloaterUIPreview(); std::string getLocStr(S32 ID); // fetches the localization string based on what is selected in the drop-down menu - void displayFloater(BOOL click, S32 ID, bool save = false); // needs to be public so live file can call it when it finds an update + void displayFloater(BOOL click, S32 ID); // needs to be public so live file can call it when it finds an update /*virtual*/ BOOL postBuild(); /*virtual*/ void onClose(bool app_quitting); @@ -291,7 +291,8 @@ LLLocalizationResetForcer::LLLocalizationResetForcer(LLFloaterUIPreview* floater { mSavedLocalization = LLUI::sSettingGroups["config"]->getString("Language"); // save current localization setting LLUI::sSettingGroups["config"]->setString("Language", floater->getLocStr(ID));// hack language to be the one we want to preview floaters in - LLUI::setupPaths(); // forcibly reset XUI paths with this new language + // forcibly reset XUI paths with this new language + gDirUtilp->setSkinFolder(gDirUtilp->getSkinFolder(), floater->getLocStr(ID)); } // Actually reset in destructor @@ -299,7 +300,8 @@ LLLocalizationResetForcer::LLLocalizationResetForcer(LLFloaterUIPreview* floater LLLocalizationResetForcer::~LLLocalizationResetForcer() { LLUI::sSettingGroups["config"]->setString("Language", mSavedLocalization); // reset language to what it was before we changed it - LLUI::setupPaths(); // forcibly reset XUI paths with this new language + // forcibly reset XUI paths with this new language + gDirUtilp->setSkinFolder(gDirUtilp->getSkinFolder(), mSavedLocalization); } // Live file constructor @@ -488,7 +490,7 @@ BOOL LLFloaterUIPreview::postBuild() { if((found = iter.next(language_directory))) // get next directory { - std::string full_path = xui_dir + language_directory; + std::string full_path = gDirUtilp->add(xui_dir, language_directory); if(LLFile::isfile(full_path.c_str())) // if it's not a directory, skip it { continue; @@ -773,7 +775,8 @@ void LLFloaterUIPreview::onClickDisplayFloater(S32 caller_id) // Saves the current floater/panel void LLFloaterUIPreview::onClickSaveFloater(S32 caller_id) { - displayFloater(TRUE, caller_id, true); + displayFloater(TRUE, caller_id); + popupAndPrintWarning("Save-floater functionality removed, use XML schema to clean up XUI files"); } // Saves all floater/panels @@ -784,25 +787,15 @@ void LLFloaterUIPreview::onClickSaveAll(S32 caller_id) for (int index = 0; index < listSize; index++) { mFileList->selectNthItem(index); - displayFloater(TRUE, caller_id, true); + displayFloater(TRUE, caller_id); } -} - -// Given path to floater or panel XML file "filename.xml", -// returns "filename_new.xml" -static std::string append_new_to_xml_filename(const std::string& path) -{ - std::string full_filename = gDirUtilp->findSkinnedFilename(LLUI::getLocalizedSkinPath(), path); - std::string::size_type extension_pos = full_filename.rfind(".xml"); - full_filename.resize(extension_pos); - full_filename += "_new.xml"; - return full_filename; + popupAndPrintWarning("Save-floater functionality removed, use XML schema to clean up XUI files"); } // Actually display the floater // Only set up a new live file if this came from a click (at which point there should be no existing live file), rather than from the live file's update itself; // otherwise, we get an infinite loop as the live file keeps recreating itself. That means this function is generally called twice. -void LLFloaterUIPreview::displayFloater(BOOL click, S32 ID, bool save) +void LLFloaterUIPreview::displayFloater(BOOL click, S32 ID) { // Convince UI that we're in a different language (the one selected on the drop-down menu) LLLocalizationResetForcer reset_forcer(this, ID); // save old language in reset forcer object (to be reset upon destruction when it falls out of scope) @@ -843,48 +836,13 @@ void LLFloaterUIPreview::displayFloater(BOOL click, S32 ID, bool save) if(!strncmp(path.c_str(),"floater_",8) || !strncmp(path.c_str(), "inspect_", 8)) // if it's a floater { - if (save) - { - LLXMLNodePtr floater_write = new LLXMLNode(); - (*floaterp)->buildFromFile(path, floater_write); // just build it - - if (!floater_write->isNull()) - { - std::string full_filename = append_new_to_xml_filename(path); - LLFILE* floater_temp = LLFile::fopen(full_filename.c_str(), "w"); - LLXMLNode::writeHeaderToFile(floater_temp); - const bool use_type_decorations = false; - floater_write->writeToFile(floater_temp, std::string(), use_type_decorations); - fclose(floater_temp); - } - } - else - { - (*floaterp)->buildFromFile(path); // just build it - (*floaterp)->openFloater((*floaterp)->getKey()); - (*floaterp)->setCanResize((*floaterp)->isResizable()); - } - + (*floaterp)->buildFromFile(path); // just build it + (*floaterp)->openFloater((*floaterp)->getKey()); + (*floaterp)->setCanResize((*floaterp)->isResizable()); } else if (!strncmp(path.c_str(),"menu_",5)) // if it's a menu { - if (save) - { - LLXMLNodePtr menu_write = new LLXMLNode(); - LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile(path, gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance(), menu_write); - - if (!menu_write->isNull()) - { - std::string full_filename = append_new_to_xml_filename(path); - LLFILE* menu_temp = LLFile::fopen(full_filename.c_str(), "w"); - LLXMLNode::writeHeaderToFile(menu_temp); - const bool use_type_decorations = false; - menu_write->writeToFile(menu_temp, std::string(), use_type_decorations); - fclose(menu_temp); - } - - delete menu; - } + // former 'save' processing excised } else // if it is a panel... { @@ -896,39 +854,21 @@ void LLFloaterUIPreview::displayFloater(BOOL click, S32 ID, bool save) LLPanel::Params panel_params; LLPanel* panel = LLUICtrlFactory::create(panel_params); // create a new panel - if (save) - { - LLXMLNodePtr panel_write = new LLXMLNode(); - panel->buildFromFile(path, panel_write); // build it - - if (!panel_write->isNull()) - { - std::string full_filename = append_new_to_xml_filename(path); - LLFILE* panel_temp = LLFile::fopen(full_filename.c_str(), "w"); - LLXMLNode::writeHeaderToFile(panel_temp); - const bool use_type_decorations = false; - panel_write->writeToFile(panel_temp, std::string(), use_type_decorations); - fclose(panel_temp); - } - } - else - { - panel->buildFromFile(path); // build it - LLRect new_size = panel->getRect(); // get its rectangle - panel->setOrigin(2,2); // reset its origin point so it's not offset by -left or other XUI attributes - (*floaterp)->setTitle(path); // use the file name as its title, since panels have no guaranteed meaningful name attribute - panel->setUseBoundingRect(TRUE); // enable the use of its outer bounding rect (normally disabled because it's O(n) on the number of sub-elements) - panel->updateBoundingRect(); // update bounding rect - LLRect bounding_rect = panel->getBoundingRect(); // get the bounding rect - LLRect new_rect = panel->getRect(); // get the panel's rect - new_rect.unionWith(bounding_rect); // union them to make sure we get the biggest one possible - LLRect floater_rect = new_rect; - floater_rect.stretch(4, 4); - (*floaterp)->reshape(floater_rect.getWidth(), floater_rect.getHeight() + floater_header_size); // reshape floater to match the union rect's dimensions - panel->reshape(new_rect.getWidth(), new_rect.getHeight()); // reshape panel to match the union rect's dimensions as well (both are needed) - (*floaterp)->addChild(panel); // add panel as child - (*floaterp)->openFloater(); // open floater (needed?) - } + panel->buildFromFile(path); // build it + LLRect new_size = panel->getRect(); // get its rectangle + panel->setOrigin(2,2); // reset its origin point so it's not offset by -left or other XUI attributes + (*floaterp)->setTitle(path); // use the file name as its title, since panels have no guaranteed meaningful name attribute + panel->setUseBoundingRect(TRUE); // enable the use of its outer bounding rect (normally disabled because it's O(n) on the number of sub-elements) + panel->updateBoundingRect(); // update bounding rect + LLRect bounding_rect = panel->getBoundingRect(); // get the bounding rect + LLRect new_rect = panel->getRect(); // get the panel's rect + new_rect.unionWith(bounding_rect); // union them to make sure we get the biggest one possible + LLRect floater_rect = new_rect; + floater_rect.stretch(4, 4); + (*floaterp)->reshape(floater_rect.getWidth(), floater_rect.getHeight() + floater_header_size); // reshape floater to match the union rect's dimensions + panel->reshape(new_rect.getWidth(), new_rect.getHeight()); // reshape panel to match the union rect's dimensions as well (both are needed) + (*floaterp)->addChild(panel); // add panel as child + (*floaterp)->openFloater(); // open floater (needed?) } if(ID == 1) @@ -964,7 +904,7 @@ void LLFloaterUIPreview::displayFloater(BOOL click, S32 ID, bool save) (*floaterp)->center(); addDependentFloater(*floaterp); - if(click && ID == 1 && !save) + if(click && ID == 1) { // set up live file to track it if(mLiveFile) diff --git a/indra/newview/llhints.cpp b/indra/newview/llhints.cpp index e15862e2a4..197408b40e 100644 --- a/indra/newview/llhints.cpp +++ b/indra/newview/llhints.cpp @@ -171,12 +171,12 @@ LLHintPopup::LLHintPopup(const LLHintPopup::Params& p) } if (p.hint_image.isProvided()) { - buildFromFile("panel_hint_image.xml", NULL, p); + buildFromFile("panel_hint_image.xml", p); getChild("hint_image")->setImage(p.hint_image()); } else { - buildFromFile( "panel_hint.xml", NULL, p); + buildFromFile( "panel_hint.xml", p); } } diff --git a/indra/newview/llmediactrl.cpp b/indra/newview/llmediactrl.cpp index 7650fe9229..99b4707158 100644 --- a/indra/newview/llmediactrl.cpp +++ b/indra/newview/llmediactrl.cpp @@ -564,32 +564,13 @@ void LLMediaCtrl::navigateTo( std::string url_in, std::string mime_type) // void LLMediaCtrl::navigateToLocalPage( const std::string& subdir, const std::string& filename_in ) { - std::string language = LLUI::getLanguage(); - std::string delim = gDirUtilp->getDirDelimiter(); - std::string filename; + std::string filename(gDirUtilp->add(subdir, filename_in)); + std::string expanded_filename = gDirUtilp->findSkinnedFilename("html", filename); - filename += subdir; - filename += delim; - filename += filename_in; - - std::string expanded_filename = gDirUtilp->findSkinnedFilename("html", language, filename); - - if (! gDirUtilp->fileExists(expanded_filename)) + if (expanded_filename.empty()) { - if (language != "en") - { - expanded_filename = gDirUtilp->findSkinnedFilename("html", "en", filename); - if (! gDirUtilp->fileExists(expanded_filename)) - { - llwarns << "File " << subdir << delim << filename_in << "not found" << llendl; - return; - } - } - else - { - llwarns << "File " << subdir << delim << filename_in << "not found" << llendl; - return; - } + llwarns << "File " << filename << "not found" << llendl; + return; } if (ensureMediaSourceExists()) { @@ -597,7 +578,6 @@ void LLMediaCtrl::navigateToLocalPage( const std::string& subdir, const std::str mMediaSource->setSize(mTextureWidth, mTextureHeight); mMediaSource->navigateTo(expanded_filename, "text/html", false); } - } //////////////////////////////////////////////////////////////////////////////// diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp index 88727bf59b..9c25e69db0 100644 --- a/indra/newview/llpreviewscript.cpp +++ b/indra/newview/llpreviewscript.cpp @@ -815,7 +815,7 @@ void LLScriptEdCore::onBtnDynamicHelp() if (!live_help_floater) { live_help_floater = new LLFloater(LLSD()); - live_help_floater->buildFromFile("floater_lsl_guide.xml", NULL); + live_help_floater->buildFromFile("floater_lsl_guide.xml"); LLFloater* parent = dynamic_cast(getParent()); llassert(parent); if (parent) diff --git a/indra/newview/llsyswellwindow.cpp b/indra/newview/llsyswellwindow.cpp index 0cb6c85012..2002647fef 100644 --- a/indra/newview/llsyswellwindow.cpp +++ b/indra/newview/llsyswellwindow.cpp @@ -242,7 +242,7 @@ LLIMWellWindow::RowPanel::RowPanel(const LLSysWellWindow* parent, const LLUUID& S32 chicletCounter, const std::string& name, const LLUUID& otherParticipantId) : LLPanel(LLPanel::Params()), mChiclet(NULL), mParent(parent) { - buildFromFile( "panel_activeim_row.xml", NULL); + buildFromFile( "panel_activeim_row.xml"); // Choose which of the pre-created chiclets (IM/group) to use. // The other one gets hidden. @@ -356,7 +356,7 @@ LLIMWellWindow::ObjectRowPanel::ObjectRowPanel(const LLUUID& notification_id, bo : LLPanel() , mChiclet(NULL) { - buildFromFile( "panel_active_object_row.xml", NULL); + buildFromFile( "panel_active_object_row.xml"); initChiclet(notification_id); diff --git a/indra/newview/lltoast.cpp b/indra/newview/lltoast.cpp index 0eec7f0afd..9dfb29b905 100644 --- a/indra/newview/lltoast.cpp +++ b/indra/newview/lltoast.cpp @@ -118,7 +118,7 @@ LLToast::LLToast(const LLToast::Params& p) { mTimer.reset(new LLToastLifeTimer(this, p.lifetime_secs)); - buildFromFile("panel_toast.xml", NULL); + buildFromFile("panel_toast.xml"); setCanDrag(FALSE); diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index 1eb4bedfaf..47059b0b8c 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -1184,12 +1184,9 @@ void LLViewerMedia::clearAllCookies() LLDirIterator dir_iter(base_dir, "*_*"); while (dir_iter.next(filename)) { - target = base_dir; - target += filename; - target += gDirUtilp->getDirDelimiter(); - target += "browser_profile"; - target += gDirUtilp->getDirDelimiter(); - target += "cookies"; + target = gDirUtilp->add(base_dir, filename); + gDirUtilp->append(target, "browser_profile"); + gDirUtilp->append(target, "cookies"); lldebugs << "target = " << target << llendl; if(LLFile::isfile(target)) { @@ -1197,10 +1194,8 @@ void LLViewerMedia::clearAllCookies() } // Other accounts may have new-style cookie files too -- delete them as well - target = base_dir; - target += filename; - target += gDirUtilp->getDirDelimiter(); - target += PLUGIN_COOKIE_FILE_NAME; + target = gDirUtilp->add(base_dir, filename); + gDirUtilp->append(target, PLUGIN_COOKIE_FILE_NAME); lldebugs << "target = " << target << llendl; if(LLFile::isfile(target)) { diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp index 9a6c0569a9..7eb1a202a0 100644 --- a/indra/newview/llviewertexturelist.cpp +++ b/indra/newview/llviewertexturelist.cpp @@ -1583,49 +1583,42 @@ struct UIImageDeclarations : public LLInitParam::Block bool LLUIImageList::initFromFile() { - // construct path to canonical textures.xml in default skin dir - std::string base_file_path = gDirUtilp->getExpandedFilename(LL_PATH_SKINS, "default", "textures", "textures.xml"); + // Look for textures.xml in all the right places. Pass merge=true because + // we want to overlay textures.xml from all the skins directories. + std::vector textures_paths = + gDirUtilp->findSkinnedFilenames(LLDir::TEXTURES, "textures.xml", true); + std::vector::const_iterator pi(textures_paths.begin()), pend(textures_paths.end()); + if (pi == pend) + { + llwarns << "No textures.xml found in skins directories" << llendl; + return false; + } + // The first (most generic) file gets special validations LLXMLNodePtr root; - - if (!LLXMLNode::parseFile(base_file_path, root, NULL)) + if (!LLXMLNode::parseFile(*pi, root, NULL)) { - llwarns << "Unable to parse UI image list file " << base_file_path << llendl; + llwarns << "Unable to parse UI image list file " << *pi << llendl; return false; } if (!root->hasAttribute("version")) { - llwarns << "No valid version number in UI image list file " << base_file_path << llendl; + llwarns << "No valid version number in UI image list file " << *pi << llendl; return false; } UIImageDeclarations images; LLXUIParser parser; - parser.readXUI(root, images, base_file_path); - - // add components defined in current skin - std::string skin_update_path = gDirUtilp->getSkinDir() - + gDirUtilp->getDirDelimiter() - + "textures" - + gDirUtilp->getDirDelimiter() - + "textures.xml"; - LLXMLNodePtr update_root; - if (skin_update_path != base_file_path - && LLXMLNode::parseFile(skin_update_path, update_root, NULL)) - { - parser.readXUI(update_root, images, skin_update_path); - } - - // add components defined in user override of current skin - skin_update_path = gDirUtilp->getUserSkinDir() - + gDirUtilp->getDirDelimiter() - + "textures" - + gDirUtilp->getDirDelimiter() - + "textures.xml"; - if (skin_update_path != base_file_path - && LLXMLNode::parseFile(skin_update_path, update_root, NULL)) - { - parser.readXUI(update_root, images, skin_update_path); + parser.readXUI(root, images, *pi); + + // add components defined in the rest of the skin paths + while (++pi != pend) + { + LLXMLNodePtr update_root; + if (LLXMLNode::parseFile(*pi, update_root, NULL)) + { + parser.readXUI(update_root, images, *pi); + } } if (!images.validateBlock()) return false; diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 30bb787fa7..e569c9504f 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -1685,8 +1685,7 @@ LLViewerWindow::LLViewerWindow(const Params& p) LLFontGL::initClass( gSavedSettings.getF32("FontScreenDPI"), mDisplayScale.mV[VX], mDisplayScale.mV[VY], - gDirUtilp->getAppRODataDir(), - LLUI::getXUIPaths()); + gDirUtilp->getAppRODataDir()); // Create container for all sub-views LLView::Params rvp; @@ -4757,8 +4756,7 @@ void LLViewerWindow::initFonts(F32 zoom_factor) LLFontGL::initClass( gSavedSettings.getF32("FontScreenDPI"), mDisplayScale.mV[VX] * zoom_factor, mDisplayScale.mV[VY] * zoom_factor, - gDirUtilp->getAppRODataDir(), - LLUI::getXUIPaths()); + gDirUtilp->getAppRODataDir()); // Force font reloads, which can be very slow LLFontGL::loadDefaultFonts(); } diff --git a/indra/newview/llwaterparammanager.cpp b/indra/newview/llwaterparammanager.cpp index e386112334..4f52ff9778 100644 --- a/indra/newview/llwaterparammanager.cpp +++ b/indra/newview/llwaterparammanager.cpp @@ -100,7 +100,7 @@ void LLWaterParamManager::loadPresetsFromDir(const std::string& dir) break; // no more files } - std::string path = dir + file; + std::string path = gDirUtilp->add(dir, file); if (!loadPreset(path)) { llwarns << "Error loading water preset from " << path << llendl; diff --git a/indra/newview/llwlparammanager.cpp b/indra/newview/llwlparammanager.cpp index 49d9d44d74..6077208799 100644 --- a/indra/newview/llwlparammanager.cpp +++ b/indra/newview/llwlparammanager.cpp @@ -283,7 +283,7 @@ void LLWLParamManager::loadPresetsFromDir(const std::string& dir) break; // no more files } - std::string path = dir + file; + std::string path = gDirUtilp->add(dir, file); if (!loadPreset(path)) { llwarns << "Error loading sky preset from " << path << llendl; diff --git a/indra/newview/skins/paths.xml b/indra/newview/skins/paths.xml deleted file mode 100644 index 3c0da041c7..0000000000 --- a/indra/newview/skins/paths.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - xui - en - - - xui - [LANGUAGE] - - \ No newline at end of file diff --git a/indra/newview/tests/lldir_stub.cpp b/indra/newview/tests/lldir_stub.cpp index 18cf4e7419..3c0a4377d8 100644 --- a/indra/newview/tests/lldir_stub.cpp +++ b/indra/newview/tests/lldir_stub.cpp @@ -32,7 +32,7 @@ BOOL LLDir::deleteFilesInDir(const std::string &dirname, const std::string &mask void LLDir::setChatLogsDir(const std::string &path) {} void LLDir::setPerAccountChatLogsDir(const std::string &first, const std::string &last) {} void LLDir::setLindenUserDir(const std::string &first, const std::string &last) {} -void LLDir::setSkinFolder(const std::string &skin_folder) {} +void LLDir::setSkinFolder(const std::string &skin_folder, const std::string& language) {} bool LLDir::setCacheDir(const std::string &path) { return true; } void LLDir::dumpCurrentDirectories() {} diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index 7c6b5403e1..e754c26733 100644 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -114,7 +114,6 @@ class ViewerManifest(LLManifest): # skins if self.prefix(src="skins"): - self.path("paths.xml") # include the entire textures directory recursively if self.prefix(src="*/textures"): self.path("*/*.tga") diff --git a/indra/viewer_components/updater/tests/llupdaterservice_test.cpp b/indra/viewer_components/updater/tests/llupdaterservice_test.cpp index 7c016fecf9..db52e6c55f 100644 --- a/indra/viewer_components/updater/tests/llupdaterservice_test.cpp +++ b/indra/viewer_components/updater/tests/llupdaterservice_test.cpp @@ -78,7 +78,9 @@ S32 LLDir::deleteFilesInDir(const std::string &dirname, void LLDir::setChatLogsDir(const std::string &path){} void LLDir::setPerAccountChatLogsDir(const std::string &username){} void LLDir::setLindenUserDir(const std::string &username){} -void LLDir::setSkinFolder(const std::string &skin_folder){} +void LLDir::setSkinFolder(const std::string &skin_folder, const std::string& language){} +std::string LLDir::getSkinFolder() const { return "default"; } +std::string LLDir::getLanguage() const { return "en"; } bool LLDir::setCacheDir(const std::string &path){ return true; } void LLDir::dumpCurrentDirectories() {} -- cgit v1.3 From cb96ab1a6fed15da0407d2aba5e9de566417088f Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Wed, 18 Jul 2012 15:49:47 -0500 Subject: MAINT-628 Fix for seams in high res snapshots when lighting and shadows is enabled. --- indra/llrender/llrendertarget.cpp | 34 ++++++------- indra/llrender/llrendertarget.h | 5 +- .../shaders/class1/deferred/fxaaF.glsl | 1 - indra/newview/llviewerwindow.cpp | 55 +++++++++++++++++++--- indra/newview/pipeline.cpp | 29 ++++++------ indra/newview/pipeline.h | 8 +++- 6 files changed, 90 insertions(+), 42 deletions(-) (limited to 'indra/llrender') diff --git a/indra/llrender/llrendertarget.cpp b/indra/llrender/llrendertarget.cpp index 846311a8d0..c1b96a43da 100644 --- a/indra/llrender/llrendertarget.cpp +++ b/indra/llrender/llrendertarget.cpp @@ -51,11 +51,13 @@ void check_framebuffer_status() } bool LLRenderTarget::sUseFBO = false; +U32 LLRenderTarget::sCurFBO = 0; LLRenderTarget::LLRenderTarget() : mResX(0), mResY(0), mFBO(0), + mPreviousFBO(0), mDepth(0), mStencil(0), mUseDepth(false), @@ -107,6 +109,9 @@ void LLRenderTarget::resize(U32 resx, U32 resy, U32 color_fmt) bool LLRenderTarget::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil, LLTexUnit::eTextureType usage, bool use_fbo, S32 samples) { + resx = llmin(resx, (U32) 4096); + resy = llmin(resy, (U32) 4096); + stop_glerror(); release(); stop_glerror(); @@ -146,7 +151,7 @@ bool LLRenderTarget::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, boo glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, LLTexUnit::getInternalType(mUsage), mDepth, 0); stop_glerror(); } - glBindFramebuffer(GL_FRAMEBUFFER, 0); + glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO); } stop_glerror(); @@ -233,7 +238,7 @@ bool LLRenderTarget::addColorAttachment(U32 color_fmt) check_framebuffer_status(); - glBindFramebuffer(GL_FRAMEBUFFER, 0); + glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO); } mTex.push_back(tex); @@ -322,7 +327,7 @@ void LLRenderTarget::shareDepthBuffer(LLRenderTarget& target) check_framebuffer_status(); - glBindFramebuffer(GL_FRAMEBUFFER, 0); + glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO); target.mUseDepth = true; } @@ -385,9 +390,13 @@ void LLRenderTarget::bindTarget() { if (mFBO) { + mPreviousFBO = sCurFBO; + stop_glerror(); glBindFramebuffer(GL_FRAMEBUFFER, mFBO); + sCurFBO = mFBO; + stop_glerror(); if (gGLManager.mHasDrawBuffers) { //setup multiple render targets @@ -413,16 +422,6 @@ void LLRenderTarget::bindTarget() sBoundTarget = this; } -// static -void LLRenderTarget::unbindTarget() -{ - if (gGLManager.mHasFramebufferObject) - { - glBindFramebuffer(GL_FRAMEBUFFER, 0); - } - sBoundTarget = NULL; -} - void LLRenderTarget::clear(U32 mask_in) { U32 mask = GL_COLOR_BUFFER_BIT; @@ -488,7 +487,8 @@ void LLRenderTarget::flush(bool fetch_depth) else { stop_glerror(); - glBindFramebuffer(GL_FRAMEBUFFER, 0); + glBindFramebuffer(GL_FRAMEBUFFER, mPreviousFBO); + sCurFBO = mPreviousFBO; stop_glerror(); } } @@ -518,7 +518,7 @@ void LLRenderTarget::copyContents(LLRenderTarget& source, S32 srcX0, S32 srcY0, stop_glerror(); glCopyTexSubImage2D(LLTexUnit::getInternalType(mUsage), 0, srcX0, srcY0, dstX0, dstY0, dstX1, dstY1); stop_glerror(); - glBindFramebuffer(GL_FRAMEBUFFER, 0); + glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO); stop_glerror(); } else @@ -535,7 +535,7 @@ void LLRenderTarget::copyContents(LLRenderTarget& source, S32 srcX0, S32 srcY0, stop_glerror(); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); stop_glerror(); - glBindFramebuffer(GL_FRAMEBUFFER, 0); + glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO); stop_glerror(); } } @@ -561,7 +561,7 @@ void LLRenderTarget::copyContentsToFramebuffer(LLRenderTarget& source, S32 srcX0 stop_glerror(); glBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter); stop_glerror(); - glBindFramebuffer(GL_FRAMEBUFFER, 0); + glBindFramebuffer(GL_FRAMEBUFFER, sCurFBO); stop_glerror(); } } diff --git a/indra/llrender/llrendertarget.h b/indra/llrender/llrendertarget.h index e1a51304f1..cf15f66d31 100644 --- a/indra/llrender/llrendertarget.h +++ b/indra/llrender/llrendertarget.h @@ -63,6 +63,7 @@ public: //whether or not to use FBO implementation static bool sUseFBO; static U32 sBytesAllocated; + static U32 sCurFBO; LLRenderTarget(); ~LLRenderTarget(); @@ -96,9 +97,6 @@ public: //applies appropriate viewport void bindTarget(); - //unbind target for rendering - static void unbindTarget(); - //clear render targer, clears depth buffer if present, //uses scissor rect if in copy-to-texture mode void clear(U32 mask = 0xFFFFFFFF); @@ -148,6 +146,7 @@ protected: std::vector mTex; std::vector mInternalFormat; U32 mFBO; + U32 mPreviousFBO; U32 mDepth; bool mStencil; bool mUseDepth; diff --git a/indra/newview/app_settings/shaders/class1/deferred/fxaaF.glsl b/indra/newview/app_settings/shaders/class1/deferred/fxaaF.glsl index e02a7b405b..2cef8f2a5d 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/fxaaF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/fxaaF.glsl @@ -2093,7 +2093,6 @@ uniform sampler2D diffuseMap; uniform vec2 rcp_screen_res; uniform vec4 rcp_frame_opt; uniform vec4 rcp_frame_opt2; -uniform vec2 screen_res; VARYING vec2 vary_fragcoord; VARYING vec2 vary_tc; diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 44e6d70546..ffaf881521 100755 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -4236,14 +4236,48 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei image_height = llmin(image_height, window_height); } + S32 original_width = 0; + S32 original_height = 0; + bool reset_deferred = false; + + LLRenderTarget scratch_space; + F32 scale_factor = 1.0f ; if (!keep_window_aspect || (image_width > window_width) || (image_height > window_height)) { - // if image cropping or need to enlarge the scene, compute a scale_factor - F32 ratio = llmin( (F32)window_width / image_width , (F32)window_height / image_height) ; - snapshot_width = (S32)(ratio * image_width) ; - snapshot_height = (S32)(ratio * image_height) ; - scale_factor = llmax(1.0f, 1.0f / ratio) ; + if ((image_width > window_width || image_height > window_height) && LLPipeline::sRenderDeferred && !show_ui) + { + if (scratch_space.allocate(image_width, image_height, GL_RGBA, true, true)) + { + original_width = gPipeline.mDeferredScreen.getWidth(); + original_height = gPipeline.mDeferredScreen.getHeight(); + + if (gPipeline.allocateScreenBuffer(image_width, image_height)) + { + window_width = image_width; + window_height = image_height; + snapshot_width = image_width; + snapshot_height = image_height; + reset_deferred = true; + mWorldViewRectRaw.set(0, image_height, image_width, 0); + scratch_space.bindTarget(); + } + else + { + scratch_space.release(); + gPipeline.allocateScreenBuffer(original_width, original_height); + } + } + } + + if (!reset_deferred) + { + // if image cropping or need to enlarge the scene, compute a scale_factor + F32 ratio = llmin( (F32)window_width / image_width , (F32)window_height / image_height) ; + snapshot_width = (S32)(ratio * image_width) ; + snapshot_height = (S32)(ratio * image_height) ; + scale_factor = llmax(1.0f, 1.0f / ratio) ; + } } if (show_ui && scale_factor > 1.f) @@ -4432,11 +4466,20 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei gPipeline.resetDrawOrders(); } + if (reset_deferred) + { + mWorldViewRectRaw = window_rect; + scratch_space.flush(); + scratch_space.release(); + gPipeline.allocateScreenBuffer(original_width, original_height); + + } + if (high_res) { send_agent_resume(); } - + return ret; } diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index ea2dc60b07..6f8ead0943 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -779,7 +779,7 @@ void LLPipeline::allocatePhysicsBuffer() } } -void LLPipeline::allocateScreenBuffer(U32 resX, U32 resY) +bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY) { refreshCachedSettings(); U32 samples = RenderFSAASamples; @@ -789,8 +789,13 @@ void LLPipeline::allocateScreenBuffer(U32 resX, U32 resY) // - if not multisampled, shrink resolution and try again (favor X resolution over Y) // Make sure to call "releaseScreenBuffers" after each failure to cleanup the partially loaded state + bool ret = true; + if (!allocateScreenBuffer(resX, resY, samples)) { + //failed to allocate at requested specification, return false + ret = false; + releaseScreenBuffers(); //reduce number of samples while (samples > 0) @@ -798,7 +803,7 @@ void LLPipeline::allocateScreenBuffer(U32 resX, U32 resY) samples /= 2; if (allocateScreenBuffer(resX, resY, samples)) { //success - return; + return ret; } releaseScreenBuffers(); } @@ -811,20 +816,22 @@ void LLPipeline::allocateScreenBuffer(U32 resX, U32 resY) resY /= 2; if (allocateScreenBuffer(resX, resY, samples)) { - return; + return ret; } releaseScreenBuffers(); resX /= 2; if (allocateScreenBuffer(resX, resY, samples)) { - return; + return ret; } releaseScreenBuffers(); } llwarns << "Unable to allocate screen buffer at any resolution!" << llendl; } + + return ret; } @@ -869,7 +876,7 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples) if (!mScreen.allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE, samples)) return false; if (samples > 0) { - if (!mFXAABuffer.allocate(nhpo2(resX), nhpo2(resY), GL_RGBA, FALSE, FALSE, LLTexUnit::TT_TEXTURE, FALSE, samples)) return false; + if (!mFXAABuffer.allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_TEXTURE, FALSE, samples)) return false; } else { @@ -903,7 +910,7 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples) } } - U32 width = nhpo2(U32(resX*scale))/2; + U32 width = resX*scale; U32 height = width; if (shadow_detail > 1) @@ -7117,11 +7124,11 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield) gGlowProgram.unbind(); - if (LLRenderTarget::sUseFBO) + /*if (LLRenderTarget::sUseFBO) { LLFastTimer ftm(FTM_RENDER_BLOOM_FBO); glBindFramebuffer(GL_FRAMEBUFFER, 0); - } + }*/ gGLViewport[0] = gViewerWindow->getWorldViewRectRaw().mLeft; gGLViewport[1] = gViewerWindow->getWorldViewRectRaw().mBottom; @@ -7997,10 +8004,6 @@ void LLPipeline::renderDeferredLighting() gGL.popMatrix(); stop_glerror(); - //copy depth and stencil from deferred screen - //mScreen.copyContents(mDeferredScreen, 0, 0, mDeferredScreen.getWidth(), mDeferredScreen.getHeight(), - // 0, 0, mScreen.getWidth(), mScreen.getHeight(), GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST); - mScreen.bindTarget(); // clear color buffer here - zeroing alpha (glow) is important or it will accumulate against sky glClearColor(0,0,0,0); @@ -8772,8 +8775,6 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in) } last_update = LLDrawPoolWater::sNeedsReflectionUpdate && LLDrawPoolWater::sNeedsDistortionUpdate; - LLRenderTarget::unbindTarget(); - LLPipeline::sReflectionRender = FALSE; if (!LLRenderTarget::sUseFBO) diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index 7a0ca86231..c38e7fbdc1 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -119,8 +119,14 @@ public: void createGLBuffers(); void createLUTBuffers(); - void allocateScreenBuffer(U32 resX, U32 resY); + //allocate the largest screen buffer possible up to resX, resY + //returns true if full size buffer allocated, false if some other size is allocated + bool allocateScreenBuffer(U32 resX, U32 resY); + + //attempt to allocate screen buffers at resX, resY + //returns true if allocation successful, false otherwise bool allocateScreenBuffer(U32 resX, U32 resY, U32 samples); + void allocatePhysicsBuffer(); void resetVertexBuffers(LLDrawable* drawable); -- cgit v1.3