diff options
| -rw-r--r-- | indra/newview/lltexturefetch.cpp | 45 | ||||
| -rw-r--r-- | indra/newview/lltexturefetch.h | 18 | ||||
| -rw-r--r-- | indra/newview/llviewertexture.cpp | 294 | ||||
| -rw-r--r-- | indra/newview/llviewertexture.h | 2 | 
4 files changed, 231 insertions, 128 deletions
| diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp index 5172fad29d..703030b978 100644 --- a/indra/newview/lltexturefetch.cpp +++ b/indra/newview/lltexturefetch.cpp @@ -2481,7 +2481,7 @@ S32 LLTextureFetch::createRequest(FTType f_type, const std::string& url, const L      LL_PROFILE_ZONE_SCOPED;      if (mDebugPause)      { -        return -1; +        return CREATE_REQUEST_ERROR_DEFAULT;      }      if (f_type == FTT_SERVER_BAKE) @@ -2497,7 +2497,7 @@ S32 LLTextureFetch::createRequest(FTType f_type, const std::string& url, const L                                << host << " != " << worker->mHost << LL_ENDL;              removeRequest(worker, true);              worker = NULL; -            return -1; +            return CREATE_REQUEST_ERROR_MHOSTS;          }      } @@ -2550,13 +2550,13 @@ S32 LLTextureFetch::createRequest(FTType f_type, const std::string& url, const L      {          if (worker->wasAborted())          { -            return -1; // need to wait for previous aborted request to complete +            return CREATE_REQUEST_ERROR_ABORTED; // need to wait for previous aborted request to complete          }          worker->lockWorkMutex();                                        // +Mw          if (worker->mState == LLTextureFetchWorker::DONE && worker->mDesiredSize == llmax(desired_size, TEXTURE_CACHE_ENTRY_SIZE) && worker->mDesiredDiscard == desired_discard) {              worker->unlockWorkMutex();                                  // -Mw -            return -1; // similar request has failed or is in a transitional state +            return CREATE_REQUEST_ERROR_TRANSITION; // similar request has finished, failed or is in a transitional state          }          worker->mActiveCount++;          worker->mNeedsAux = needs_aux; @@ -3149,6 +3149,43 @@ S32 LLTextureFetch::getFetchState(const LLUUID& id, F32& data_progress_p, F32& r      return state;  } +// Threads:  T* +S32 LLTextureFetch::getLastFetchState(const LLUUID& id, S32& requested_discard, S32& decoded_discard, bool& decoded) +{ +    LL_PROFILE_ZONE_SCOPED; +    S32 state = LLTextureFetchWorker::INVALID; + +    LLTextureFetchWorker* worker = getWorker(id); +    if (worker) // Don't check haveWork, intent is to get whatever is in the worker +    { +        worker->lockWorkMutex();                                        // +Mw +        state = worker->mState; +        requested_discard = worker->mDesiredDiscard; +        decoded_discard = worker->mDecodedDiscard; +        decoded = worker->mDecoded; +        worker->unlockWorkMutex();                                      // -Mw +    } +    return state; +} + +// Threads:  T* +S32 LLTextureFetch::getLastRawImage(const LLUUID& id, +    LLPointer<LLImageRaw>& raw, LLPointer<LLImageRaw>& aux) +{ +    LL_PROFILE_ZONE_SCOPED; +    S32 decoded_discard = -1; +    LLTextureFetchWorker* worker = getWorker(id); +    if (worker && !worker->haveWork() && worker->mDecodedDiscard >= 0) +    { +            worker->lockWorkMutex();                                    // +Mw +            raw = worker->mRawImage; +            aux = worker->mAuxImage; +            decoded_discard = worker->mDecodedDiscard; +            worker->unlockWorkMutex();                                  // -Mw +    } +    return decoded_discard; +} +  void LLTextureFetch::dump()  {      LL_INFOS(LOG_TXT) << "LLTextureFetch ACTIVE_HTTP:" << LL_ENDL; diff --git a/indra/newview/lltexturefetch.h b/indra/newview/lltexturefetch.h index c2c5ec5acc..8ab90896dc 100644 --- a/indra/newview/lltexturefetch.h +++ b/indra/newview/lltexturefetch.h @@ -76,6 +76,14 @@ public:      // Threads:  Tmain      void shutDownImageDecodeThread(); +    enum e_crete_request_errors +    { +        CREATE_REQUEST_ERROR_DEFAULT = -1, +        CREATE_REQUEST_ERROR_MHOSTS = -2, +        CREATE_REQUEST_ERROR_ABORTED = -3, +        CREATE_REQUEST_ERROR_TRANSITION = -4, +    }; +      // Threads:  T* (but Tmain mostly)      S32 createRequest(FTType f_type, const std::string& url, const LLUUID& id, const LLHost& host, F32 priority,                         S32 w, S32 h, S32 c, S32 discard, bool needs_aux, bool can_use_http); @@ -114,12 +122,20 @@ public:      // get the current fetch state, if any, from the given UUID      S32 getFetchState(const LLUUID& id); -    // @return  Fetch state of given image and associates statistics +    // @return  Fetch state of an active given image and associates statistics      //          See also getStateString      // Threads:  T*      S32 getFetchState(const LLUUID& id, F32& decode_progress_p, F32& requested_priority_p,                        U32& fetch_priority_p, F32& fetch_dtime_p, F32& request_dtime_p, bool& can_use_http); +    // @return  Fetch last state of given image +    // Threads:  T* +    S32 getLastFetchState(const LLUUID& id, S32& requested_discard, S32 &decoded_discard, bool &decoded); + +    // @return  Fetch last raw image +    // Threads:  T* +    S32 getLastRawImage(const LLUUID& id, LLPointer<LLImageRaw>& raw, LLPointer<LLImageRaw>& aux); +      // Debug utility - generally not safe      void dump(); diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index 00e1ea4cd3..36cc9bf88f 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -1808,6 +1808,141 @@ void LLViewerFetchedTexture::setBoostLevel(S32 level)      }  } +bool LLViewerFetchedTexture::processFetchResults(S32& desired_discard, S32 current_discard, S32 fetch_discard, F32 decode_priority) +{ +    // We may have data ready regardless of whether or not we are finished (e.g. waiting on write) +    if (mRawImage.notNull()) +    { +        LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("vftuf - has raw image"); +        LLTexturePipelineTester* tester = (LLTexturePipelineTester*)LLMetricPerformanceTesterBasic::getTester(sTesterName); +        if (tester) +        { +            mIsFetched = true; +            tester->updateTextureLoadingStats(this, mRawImage, LLAppViewer::getTextureFetch()->isFromLocalCache(mID)); +        } +        mRawDiscardLevel = fetch_discard; +        if ((mRawImage->getDataSize() > 0 && mRawDiscardLevel >= 0) && +            (current_discard < 0 || mRawDiscardLevel < current_discard)) +        { +            LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("vftuf - data good"); + +            // This is going to conflict with Develop, just pick from develop +            // where it uses setDimensions instead of setTexelsPerImage +            mFullWidth = mRawImage->getWidth() << mRawDiscardLevel; +            mFullHeight = mRawImage->getHeight() << mRawDiscardLevel; +            setTexelsPerImage(); + +            if (mFullWidth > MAX_IMAGE_SIZE || mFullHeight > MAX_IMAGE_SIZE) +            { +                //discard all oversized textures. +                destroyRawImage(); +                LL_WARNS() << "oversize, setting as missing" << LL_ENDL; +                setIsMissingAsset(); +                mRawDiscardLevel = INVALID_DISCARD_LEVEL; +                mIsFetching = false; +                mLastPacketTimer.reset(); +            } +            else +            { +                mIsRawImageValid = true; +                addToCreateTexture(); +            } + +            if (mBoostLevel == LLGLTexture::BOOST_ICON) +            { +                S32 expected_width = mKnownDrawWidth > 0 ? mKnownDrawWidth : DEFAULT_ICON_DIMENSIONS; +                S32 expected_height = mKnownDrawHeight > 0 ? mKnownDrawHeight : DEFAULT_ICON_DIMENSIONS; +                if (mRawImage && (mRawImage->getWidth() > expected_width || mRawImage->getHeight() > expected_height)) +                { +                    // scale oversized icon, no need to give more work to gl +                    // since we got mRawImage from thread worker and image may be in use (ex: writing cache), make a copy +                    // +                    // BOOST_ICON gets scaling because profile icons can have a bunch of different formats, not just j2c +                    // Might need another pass to use discard for j2c and scaling for everything else. +                    mRawImage = mRawImage->scaled(expected_width, expected_height); +                } +            } + +            if (mBoostLevel == LLGLTexture::BOOST_THUMBNAIL) +            { +                S32 expected_width = mKnownDrawWidth > 0 ? mKnownDrawWidth : DEFAULT_THUMBNAIL_DIMENSIONS; +                S32 expected_height = mKnownDrawHeight > 0 ? mKnownDrawHeight : DEFAULT_THUMBNAIL_DIMENSIONS; +                if (mRawImage && (mRawImage->getWidth() > expected_width || mRawImage->getHeight() > expected_height)) +                { +                    // scale oversized icon, no need to give more work to gl +                    // since we got mRawImage from thread worker and image may be in use (ex: writing cache), make a copy +                    // +                    // Todo: probably needs to be remade to use discard, all thumbnails are supposed to be j2c, +                    // so no need to scale, should be posible to use discard to scale image down. +                    mRawImage = mRawImage->scaled(expected_width, expected_height); +                } +            } + +            return true; +        } +        else +        { +            LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("vftuf - data not needed"); +            // Data is ready but we don't need it +            // (received it already while fetcher was writing to disk) +            destroyRawImage(); +            return false; // done +        } +    } + +    if (!mIsFetching) +    { +        if ((decode_priority > 0) +            && (mRawDiscardLevel < 0 || mRawDiscardLevel == INVALID_DISCARD_LEVEL) +            && mFetchState > 1) // 1 - initial, make sure fetcher did at least something +        { +            // We finished but received no data +            if (getDiscardLevel() < 0) +            { +                if (getFTType() != FTT_MAP_TILE) +                { +                    LL_WARNS() << mID +                        << " Fetch failure, setting as missing, decode_priority " << decode_priority +                        << " mRawDiscardLevel " << mRawDiscardLevel +                        << " current_discard " << current_discard +                        << " stats " << mLastHttpGetStatus.toHex() +                        << " worker state " << mFetchState +                        << LL_ENDL; +                } +                setIsMissingAsset(); +                desired_discard = -1; +            } +            else +            { +                //LL_WARNS() << mID << ": Setting min discard to " << current_discard << LL_ENDL; +                if (current_discard >= 0) +                { +                    mMinDiscardLevel = current_discard; +                    //desired_discard = current_discard; +                } +                else +                { +                    S32 dis_level = getDiscardLevel(); +                    mMinDiscardLevel = dis_level; +                    //desired_discard = dis_level; +                } +            } +            destroyRawImage(); +        } +        else if (mRawImage.notNull()) +        { +            // We have data, but our fetch failed to return raw data +            // *TODO: FIgure out why this is happening and fix it +            // Potentially can happen when TEX_LIST_SCALE and TEX_LIST_STANDARD +            // get requested for the same texture id at the same time +            // (two textures, one fetcher) +            destroyRawImage(); +        } +    } + +    return true; +} +  bool LLViewerFetchedTexture::updateFetch()  {      LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; @@ -1892,127 +2027,12 @@ bool LLViewerFetchedTexture::updateFetch()                                                                          mFetchPriority, mFetchDeltaTime, mRequestDeltaTime, mCanUseHTTP);          } -        // We may have data ready regardless of whether or not we are finished (e.g. waiting on write) -        if (mRawImage.notNull()) +        if (!processFetchResults(desired_discard, current_discard, fetch_discard, decode_priority))          { -            LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("vftuf - has raw image"); -            LLTexturePipelineTester* tester = (LLTexturePipelineTester*)LLMetricPerformanceTesterBasic::getTester(sTesterName); -            if (tester) -            { -                mIsFetched = true; -                tester->updateTextureLoadingStats(this, mRawImage, LLAppViewer::getTextureFetch()->isFromLocalCache(mID)); -            } -            mRawDiscardLevel = fetch_discard; -            if ((mRawImage->getDataSize() > 0 && mRawDiscardLevel >= 0) && -                (current_discard < 0 || mRawDiscardLevel < current_discard)) -            { -                LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("vftuf - data good"); -                mFullWidth = mRawImage->getWidth() << mRawDiscardLevel; -                mFullHeight = mRawImage->getHeight() << mRawDiscardLevel; -                setTexelsPerImage(); - -                if(mFullWidth > MAX_IMAGE_SIZE || mFullHeight > MAX_IMAGE_SIZE) -                { -                    //discard all oversized textures. -                    destroyRawImage(); -                    LL_WARNS() << "oversize, setting as missing" << LL_ENDL; -                    setIsMissingAsset(); -                    mRawDiscardLevel = INVALID_DISCARD_LEVEL; -                    mIsFetching = false; -                    mLastPacketTimer.reset(); -                } -                else -                { -                    mIsRawImageValid = true; -                    addToCreateTexture(); -                } - -                if (mBoostLevel == LLGLTexture::BOOST_ICON) -                { -                    S32 expected_width = mKnownDrawWidth > 0 ? mKnownDrawWidth : DEFAULT_ICON_DIMENSIONS; -                    S32 expected_height = mKnownDrawHeight > 0 ? mKnownDrawHeight : DEFAULT_ICON_DIMENSIONS; -                    if (mRawImage && (mRawImage->getWidth() > expected_width || mRawImage->getHeight() > expected_height)) -                    { -                        // scale oversized icon, no need to give more work to gl -                        // since we got mRawImage from thread worker and image may be in use (ex: writing cache), make a copy -                        mRawImage = mRawImage->scaled(expected_width, expected_height); -                    } -                } - -                if (mBoostLevel == LLGLTexture::BOOST_THUMBNAIL) -                { -                    S32 expected_width = mKnownDrawWidth > 0 ? mKnownDrawWidth : DEFAULT_THUMBNAIL_DIMENSIONS; -                    S32 expected_height = mKnownDrawHeight > 0 ? mKnownDrawHeight : DEFAULT_THUMBNAIL_DIMENSIONS; -                    if (mRawImage && (mRawImage->getWidth() > expected_width || mRawImage->getHeight() > expected_height)) -                    { -                        // scale oversized icon, no need to give more work to gl -                        // since we got mRawImage from thread worker and image may be in use (ex: writing cache), make a copy -                        mRawImage = mRawImage->scaled(expected_width, expected_height); -                    } -                } - -                return true; -            } -            else -            { -                LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("vftuf - data not needed"); -                // Data is ready but we don't need it -                // (received it already while fetcher was writing to disk) -                destroyRawImage(); -                return false; // done -            } +            return false;          } -        if (!mIsFetching) -        { -            if ((decode_priority > 0) -                && (mRawDiscardLevel < 0 || mRawDiscardLevel == INVALID_DISCARD_LEVEL) -                && mFetchState > 1) // 1 - initial, make sure fetcher did at least something -            { -                // We finished but received no data -                if (getDiscardLevel() < 0) -                { -                    if (getFTType() != FTT_MAP_TILE) -                    { -                        LL_WARNS() << mID -                                << " Fetch failure, setting as missing, decode_priority " << decode_priority -                                << " mRawDiscardLevel " << mRawDiscardLevel -                                << " current_discard " << current_discard -                                << " stats " << mLastHttpGetStatus.toHex() -                                << " worker state " << mFetchState -                                << LL_ENDL; -                    } -                    setIsMissingAsset(); -                    desired_discard = -1; -                } -                else -                { -                    //LL_WARNS() << mID << ": Setting min discard to " << current_discard << LL_ENDL; -                    if(current_discard >= 0) -                    { -                        mMinDiscardLevel = current_discard; -                        //desired_discard = current_discard; -                    } -                    else -                    { -                        S32 dis_level = getDiscardLevel(); -                        mMinDiscardLevel = dis_level; -                        //desired_discard = dis_level; -                    } -                } -                destroyRawImage(); -            } -            else if (mRawImage.notNull()) -            { -                // We have data, but our fetch failed to return raw data -                // *TODO: FIgure out why this is happening and fix it -                // Potentially can happen when TEX_LIST_SCALE and TEX_LIST_STANDARD -                // get requested for the same texture id at the same time -                // (two textures, one fetcher) -                destroyRawImage(); -            } -        } -        else +        if (mIsFetching)          {              static const F32 MAX_HOLD_TIME = 5.0f; //seconds to wait before canceling fecthing if decode_priority is 0.f.              if(decode_priority > 0.0f || mStopFetchingTimer.getElapsedTimeF32() > MAX_HOLD_TIME) @@ -2087,21 +2107,49 @@ bool LLViewerFetchedTexture::updateFetch()          }          // bypass texturefetch directly by pulling from LLTextureCache -        S32 fetch_request_discard = -1; -        fetch_request_discard = LLAppViewer::getTextureFetch()->createRequest(mFTType, mUrl, getID(), getTargetHost(), decode_priority, +        S32 fetch_request_response = -1; +        S32 worker_discard = -1; +        fetch_request_response = LLAppViewer::getTextureFetch()->createRequest(mFTType, mUrl, getID(), getTargetHost(), decode_priority,                                                                                w, h, c, desired_discard, needsAux(), mCanUseHTTP); -        if (fetch_request_discard >= 0) +        if (fetch_request_response >= 0) // positive values and 0 are discard values          {              LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("vftuf - request created");              mHasFetcher = true;              mIsFetching = true;              // in some cases createRequest can modify discard, as an example              // bake textures are always at discard 0 -            mRequestedDiscardLevel = llmin(desired_discard, fetch_request_discard); +            mRequestedDiscardLevel = llmin(desired_discard, fetch_request_response);              mFetchState = LLAppViewer::getTextureFetch()->getFetchState(mID, mDownloadProgress, mRequestedDownloadPriority,                                                         mFetchPriority, mFetchDeltaTime, mRequestDeltaTime, mCanUseHTTP);          } +        else if (fetch_request_response == LLTextureFetch::CREATE_REQUEST_ERROR_TRANSITION) +        { +            LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("vftuf - processing transition error"); +            // Request wasn't created because similar one finished or is in a transitional state, check worker state +            // As an example can happen if an image (like a server bake always fetches at dis 0), was scaled down to +            // needed discard after fetching then sudenly needed higher dis and worker wasn't yet deleted. Worker +            // discard will be identical to requested one and worker will have nothing new to do despite GL image +            // not being up to data. +            S32 desired_discard; +            S32 decoded_discard; +            bool decoded; +            S32 fetch_state = LLAppViewer::getTextureFetch()->getLastFetchState(mID, desired_discard, decoded_discard, decoded); +            if (fetch_state > 1 && decoded && decoded_discard >=0 && decoded_discard <= desired_discard) +            { +                // worker actually has the image +                if (mRawImage.notNull()) sRawCount--; +                if (mAuxRawImage.notNull()) sAuxCount--; +                decoded_discard = LLAppViewer::getTextureFetch()->getLastRawImage(getID(), mRawImage, mAuxRawImage); +                if (mRawImage.notNull()) sRawCount++; +                if (mAuxRawImage.notNull()) +                { +                    mHasAux = true; +                    sAuxCount++; +                } +                processFetchResults(desired_discard, current_discard, decoded_discard, decode_priority); +            } +        }          // If createRequest() failed, that means one of two things:          // 1. We're finishing up a request for this UUID, so we @@ -2923,7 +2971,7 @@ void LLViewerLODTexture::processTextureStats()          mDesiredDiscardLevel = 0;      }      // Generate the request priority and render priority -    else if (mDontDiscard || !mUseMipMaps || (getFTType() == FTT_MAP_TILE)) +    else if (mDontDiscard || !mUseMipMaps)      {          mDesiredDiscardLevel = 0;          if (mFullWidth > MAX_IMAGE_SIZE_DEFAULT || mFullHeight > MAX_IMAGE_SIZE_DEFAULT) diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h index 1da8548573..4241ef958f 100644 --- a/indra/newview/llviewertexture.h +++ b/indra/newview/llviewertexture.h @@ -423,6 +423,8 @@ private:      void init(bool firstinit) ;      void cleanup() ; +    bool processFetchResults(S32& desired_discard, S32 current_discard, S32 fetch_discard, F32 decode_priority); +      void saveRawImage() ;  private: | 
