From b16bb264cca63f6820f4a931a68d48184a66f02b Mon Sep 17 00:00:00 2001 From: Shyotl Date: Sat, 6 Apr 2013 02:04:46 -0500 Subject: [PATCH] Added an experimental new alphamask detection method(set SHUseRMSEAutoMask to TRUE to use. Adjust SHAlphaMaskMaxRMSE to tweak cutoff). Fixed per-frame sky updates hammering analyzeAlpha. --- indra/llrender/llgltexture.cpp | 4 +- indra/llrender/llgltexture.h | 2 +- indra/llrender/llimagegl.cpp | 51 ++++++++++++++++--- indra/llrender/llimagegl.h | 4 +- indra/llrender/llrender2dutils.cpp | 2 +- indra/newview/app_settings/settings_sh.xml | 22 ++++++++ indra/newview/llface.cpp | 4 +- indra/newview/llfloaterreporter.cpp | 5 ++ indra/newview/llpreviewtexture.cpp | 9 ++-- indra/newview/llselectmgr.cpp | 4 ++ indra/newview/llviewercontrol.cpp | 2 + indra/newview/llviewermenu.cpp | 29 +++++++---- indra/newview/llviewertexture.h | 2 + indra/newview/llviewerwindow.cpp | 42 +++++++++++++++ indra/newview/llvosky.cpp | 1 + .../xui/en-us/floater_report_abuse.xml | 6 +-- .../skins/default/xui/en-us/notifications.xml | 9 ++++ 17 files changed, 170 insertions(+), 28 deletions(-) diff --git a/indra/llrender/llgltexture.cpp b/indra/llrender/llgltexture.cpp index c7b223fbf..5154a854f 100644 --- a/indra/llrender/llgltexture.cpp +++ b/indra/llrender/llgltexture.cpp @@ -312,11 +312,11 @@ LLGLenum LLGLTexture::getPrimaryFormat() const return mGLTexturep->getPrimaryFormat() ; } -BOOL LLGLTexture::getIsAlphaMask() const +BOOL LLGLTexture::getIsAlphaMask(const F32 max_rmse) const { llassert(mGLTexturep.notNull()) ; - return mGLTexturep->getIsAlphaMask() ; + return mGLTexturep->getIsAlphaMask(max_rmse) ; } BOOL LLGLTexture::getMask(const LLVector2 &tc) diff --git a/indra/llrender/llgltexture.h b/indra/llrender/llgltexture.h index 8d2fc180f..1b6107858 100644 --- a/indra/llrender/llgltexture.h +++ b/indra/llrender/llgltexture.h @@ -140,7 +140,7 @@ public: BOOL getBoundRecently() const; S32 getTextureMemory() const ; LLGLenum getPrimaryFormat() const; - BOOL getIsAlphaMask() const ; + BOOL getIsAlphaMask(const F32 max_rmse) const ; LLTexUnit::eTextureType getTarget(void) const ; BOOL getMask(const LLVector2 &tc); F32 getTimePassedSinceLastBound(); diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index bdc31c9e4..3bccad5e3 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -482,7 +482,11 @@ void LLImageGL::init(BOOL usemipmaps) mHasExplicitFormat = FALSE; mAutoGenMips = FALSE; + mCanMask = TRUE; mIsMask = FALSE; + mMaskRMSE = 1.f ; + + mNeedsAlphaAndPickMask = TRUE ; mAlphaStride = 0 ; mAlphaOffset = 0 ; @@ -1749,7 +1753,7 @@ void LLImageGL::setNeedsAlphaAndPickMask(BOOL need_mask) else //do not need alpha mask { mAlphaOffset = INVALID_OFFSET ; - mIsMask = FALSE; + mCanMask = FALSE; } } } @@ -1773,7 +1777,7 @@ void LLImageGL::calcAlphaChannelOffsetAndStride() break; case GL_RGB: mNeedsAlphaAndPickMask = FALSE ; - mIsMask = FALSE; + mCanMask = FALSE; return ; //no alpha channel. case GL_RGBA: mAlphaStride = 4; @@ -1820,17 +1824,20 @@ void LLImageGL::calcAlphaChannelOffsetAndStride() llwarns << "Cannot analyze alpha for image with format type " << std::hex << mFormatType << std::dec << llendl; mNeedsAlphaAndPickMask = FALSE ; - mIsMask = FALSE; + mCanMask = FALSE; } } +std::map > > sTextureMaskMap; void LLImageGL::analyzeAlpha(const void* data_in, U32 w, U32 h) { - if(!mNeedsAlphaAndPickMask) + if(!mNeedsAlphaAndPickMask || !mCanMask) { return ; } + F64 sum = 0; + U32 length = w * h; U32 alphatotal = 0; @@ -1871,11 +1878,19 @@ void LLImageGL::analyzeAlpha(const void* data_in, U32 w, U32 h) const U32 asum = (s1+s2+s3+s4); alphatotal += asum; sample[asum/(16*4)] += 4; + + S32 avg = (s1+s2+s3+s4)/4; + if(avg >=128) + { + avg-=255; + } + sum+=F64(avg*avg*4)/F64(length); } rowstart += 2 * w * mAlphaStride; } + length *= 2; // we sampled everything twice, essentially } else @@ -1887,9 +1902,17 @@ void LLImageGL::analyzeAlpha(const void* data_in, U32 w, U32 h) alphatotal += s1; ++sample[s1/16]; current += mAlphaStride; + + if(i%2==0) + { + S32 avg = (s1+current[mAlphaStride])/2; + if(avg >=128) + avg-=255; + sum+=F64(avg*avg*2)/F64(length); + } } } - + // if more than 1/16th of alpha samples are mid-range, this // shouldn't be treated as a 1-bit mask @@ -1898,7 +1921,7 @@ void LLImageGL::analyzeAlpha(const void* data_in, U32 w, U32 h) // this to be an intentional effect and don't treat as a mask. U32 midrangetotal = 0; - for (U32 i = 2; i < 13; i++) + for (U32 i = 3; i < 13; i++) { midrangetotal += sample[i]; } @@ -1923,6 +1946,22 @@ void LLImageGL::analyzeAlpha(const void* data_in, U32 w, U32 h) { mIsMask = TRUE; } + + mMaskRMSE = sqrt(sum)/255.0; + + std::list > &data = sTextureMaskMap[getTexName()]; + data.clear(); + data.push_back(std::make_pair("RMSE", llformat("%f",mMaskRMSE))); + data.push_back(std::make_pair(" sum", llformat("%lf",sum))); + data.push_back(std::make_pair(" n", llformat("%u",h*w))); + data.push_back(std::make_pair("legacymask", mIsMask ? "TRUE" : "FALSE")); + data.push_back(std::make_pair(" index", llformat("%u",getTexName()))); + data.push_back(std::make_pair(" length", llformat("%u",length))); + data.push_back(std::make_pair(" stride", llformat("%i",S32(mAlphaOffset)))); + data.push_back(std::make_pair(" split", llformat("%u|%u|%u",lowerhalftotal,midrangetotal,upperhalftotal))); + data.push_back(std::make_pair(" alphatotal", llformat("%u",alphatotal))); + data.push_back(std::make_pair(" alphatotal/48", llformat("%u",length/48))); + } //---------------------------------------------------------------------------- diff --git a/indra/llrender/llimagegl.h b/indra/llrender/llimagegl.h index 4ec1905cc..4cbbcfc63 100644 --- a/indra/llrender/llimagegl.h +++ b/indra/llrender/llimagegl.h @@ -142,7 +142,7 @@ public: BOOL getHasGLTexture() const { return mTexName != 0; } LLGLuint getTexName() const { return mTexName; } - BOOL getIsAlphaMask() const { return mIsMask; } + BOOL getIsAlphaMask(const F32 max_rmse) const { return mCanMask && (max_rmse < 0.f ? (bool)mIsMask : (mMaskRMSE <= max_rmse)); } BOOL getIsResident(BOOL test_now = FALSE); // not const @@ -192,7 +192,9 @@ private: S8 mHasExplicitFormat; // If false (default), GL format is f(mComponents) S8 mAutoGenMips; + BOOL mCanMask; BOOL mIsMask; + F32 mMaskRMSE; BOOL mNeedsAlphaAndPickMask; S8 mAlphaStride ; S8 mAlphaOffset ; diff --git a/indra/llrender/llrender2dutils.cpp b/indra/llrender/llrender2dutils.cpp index 967bd7560..044931fa1 100644 --- a/indra/llrender/llrender2dutils.cpp +++ b/indra/llrender/llrender2dutils.cpp @@ -490,7 +490,7 @@ void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 width, S32 height, LLTex pos[index].set(draw_center_rect.mRight, draw_center_rect.mBottom, 0.f); index++; - uv[index].set(uv_center_rect.mLeft, uv_center_rect.mBottom); + uv[index] = LLVector2(uv_center_rect.mLeft, uv_center_rect.mBottom); pos[index].set(draw_center_rect.mLeft, draw_center_rect.mBottom, 0.f); index++; diff --git a/indra/newview/app_settings/settings_sh.xml b/indra/newview/app_settings/settings_sh.xml index 7d65a20d8..d70e6183f 100644 --- a/indra/newview/app_settings/settings_sh.xml +++ b/indra/newview/app_settings/settings_sh.xml @@ -206,6 +206,28 @@ F32 Value 0.25 + + SHUseRMSEAutoMask + + Comment + Use alternative method of detecing suitable textures for alphamasking. Less prone to excluding textures than standard method. + Persist + 1 + Type + Boolean + Value + 1 + + SHAlphaMaskMaxRMSE + + Comment + Sets the maximum random mean square error cutoff used when detecting suitable textures for alphamasking. (SHUseRMSEAutoMask must be TRUE for this to have any effect) + Persist + 1 + Type + F32 + Value + 0.09 diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp index bbd4426f0..d2c6834b9 100644 --- a/indra/newview/llface.cpp +++ b/indra/newview/llface.cpp @@ -1067,9 +1067,11 @@ bool LLFace::canRenderAsMask() const LLTextureEntry* te = getTextureEntry(); + static const LLCachedControl use_rmse_auto_mask("SHUseRMSEAutoMask",false); + static const LLCachedControl alpha_mas_max_rmse("SHAlphaMaskMaxRMSE",.09f); if ((te->getColor().mV[3] == 1.0f) && // can't treat as mask if we have face alpha (te->getGlow() == 0.f) && // glowing masks are hard to implement - don't mask - getTexture()->getIsAlphaMask()) // texture actually qualifies for masking (lazily recalculated but expensive) + getTexture()->getIsAlphaMask(use_rmse_auto_mask ? alpha_mas_max_rmse : -1.f)) // texture actually qualifies for masking (lazily recalculated but expensive) { if (LLPipeline::sRenderDeferred) { diff --git a/indra/newview/llfloaterreporter.cpp b/indra/newview/llfloaterreporter.cpp index 9e60be11a..06d1590b1 100644 --- a/indra/newview/llfloaterreporter.cpp +++ b/indra/newview/llfloaterreporter.cpp @@ -630,6 +630,11 @@ bool LLFloaterReporter::validateReport() // Ensure user selected a category from the list LLSD category_sd = childGetValue("category_combo"); U8 category = (U8)category_sd.asInteger(); + if(category >= 100) //This is here for reasons (like shenanigans) + { + LLNotificationsUtil::add("HelpReportNope"); + return false; + } if (category == 0) { if ( mReportType != BUG_REPORT ) diff --git a/indra/newview/llpreviewtexture.cpp b/indra/newview/llpreviewtexture.cpp index 8536f4060..af2ee3723 100644 --- a/indra/newview/llpreviewtexture.cpp +++ b/indra/newview/llpreviewtexture.cpp @@ -282,9 +282,12 @@ void LLPreviewTexture::draw() interior.getHeight(), mImage); - if (mAlphaMaskResult != mImage->getIsAlphaMask()) + static const LLCachedControl use_rmse_auto_mask("SHUseRMSEAutoMask",false); + static const LLCachedControl alpha_mas_max_rmse("SHAlphaMaskMaxRMSE",.09f); + if (mAlphaMaskResult != mImage->getIsAlphaMask(use_rmse_auto_mask ? alpha_mas_max_rmse : -1.f)) { - if (!mImage->getIsAlphaMask()) + mAlphaMaskResult = !mAlphaMaskResult; + if (!mAlphaMaskResult) { childSetColor("alphanote", LLColor4::green); childSetText("alphanote", getString("No Alpha")); @@ -294,7 +297,7 @@ void LLPreviewTexture::draw() childSetColor("alphanote", LLColor4::red); childSetText("alphanote", getString("Has Alpha")); } - mAlphaMaskResult = mImage->getIsAlphaMask(); + } // Pump the texture priority F32 pixel_area = mLoadingFullImage ? (F32)MAX_IMAGE_AREA : (F32)(interior.getWidth() * interior.getHeight() ); diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp index 9e9be1c74..5a725767d 100644 --- a/indra/newview/llselectmgr.cpp +++ b/indra/newview/llselectmgr.cpp @@ -937,6 +937,8 @@ LLObjectSelectionHandle LLSelectMgr::setHoverObject(LLViewerObject *objectp, S32 mHoverObjects->mPrimaryObject = objectp; + LLViewerObject* primary_obj = objectp; + objectp = objectp->getRootEdit(); // is the requested object the same as the existing hover object root? @@ -962,6 +964,8 @@ LLObjectSelectionHandle LLSelectMgr::setHoverObject(LLViewerObject *objectp, S32 requestObjectPropertiesFamily(objectp); } + mHoverObjects->mPrimaryObject = primary_obj; + return mHoverObjects; } diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp index 05d5836d6..90c6a6e1a 100644 --- a/indra/newview/llviewercontrol.cpp +++ b/indra/newview/llviewercontrol.cpp @@ -674,6 +674,8 @@ void settings_setup_listeners() gSavedSettings.getControl("RenderDebugTextureBind")->getSignal()->connect(boost::bind(&handleResetVertexBuffersChanged, _2)); gSavedSettings.getControl("RenderAutoMaskAlphaDeferred")->getSignal()->connect(boost::bind(&handleResetVertexBuffersChanged, _2)); gSavedSettings.getControl("RenderAutoMaskAlphaNonDeferred")->getSignal()->connect(boost::bind(&handleResetVertexBuffersChanged, _2)); + gSavedSettings.getControl("SHUseRMSEAutoMask")->getSignal()->connect(boost::bind(&handleResetVertexBuffersChanged, _2)); + gSavedSettings.getControl("SHAlphaMaskMaxRMSE")->getSignal()->connect(boost::bind(&handleResetVertexBuffersChanged, _2)); gSavedSettings.getControl("RenderObjectBump")->getSignal()->connect(boost::bind(&handleResetVertexBuffersChanged, _2)); gSavedSettings.getControl("RenderMaxVBOSize")->getSignal()->connect(boost::bind(&handleResetVertexBuffersChanged, _2)); //See LL jira VWR-3258 comment section. Implemented by LL in 2.1 -Shyotl diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 90b3e7630..abbcce641 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -1587,6 +1587,9 @@ void init_debug_rendering_menu(LLMenuGL* menu) item = new LLMenuItemCheckGL("Automatic Alpha Masks (deferred)", menu_toggle_control, NULL, menu_check_control, (void*)"RenderAutoMaskAlphaDeferred"); menu->addChild(item); + + item = new LLMenuItemCheckGL("Aggressive Alpha Masking", menu_toggle_control, NULL, menu_check_control, (void*)"SHUseRMSEAutoMask"); + menu->addChild(item); item = new LLMenuItemCheckGL("Animate Textures", menu_toggle_control, NULL, menu_check_control, (void*)"AnimateTextures"); menu->addChild(item); @@ -2296,8 +2299,12 @@ public: for (S32 i = 0; i < img->getNumVolumes(); ++i) { LLVOVolume* volume = (*(img->getVolumeList()))[i]; - if (volume && volume->isSculpted() && !volume->isMesh()) - volume->notifyMeshLoaded(); + if (volume && volume->isSculpted()) + { + LLSculptParams *sculpt_params = (LLSculptParams *)volume->getParameterEntry(LLNetworkData::PARAMS_SCULPT); + if(sculpt_params->getSculptTexture() == id) + volume->notifyMeshLoaded(); + } } } } @@ -2359,6 +2366,16 @@ class LLObjectReloadTextures : public view_listener_t iter != LLSelectMgr::getInstance()->getSelection()->valid_end(); iter++) { LLViewerObject* object = (*iter)->getObject(); + object->markForUpdate(TRUE); + + if(object->isSculpted() && !object->isMesh()) + { + LLSculptParams *sculpt_params = (LLSculptParams *)object->getParameterEntry(LLNetworkData::PARAMS_SCULPT); + if(sculpt_params) + { + texture_list.addTexture(LLViewerTextureManager::getFetchedTexture(sculpt_params->getSculptTexture())); + } + } for (U8 i = 0; i < object->getNumTEs(); i++) { @@ -2366,14 +2383,6 @@ class LLObjectReloadTextures : public view_listener_t { texture_list.addTexture(object->getTEImage(i)); } - if(object->isSculpted() && !object->isMesh()) - { - LLSculptParams *sculpt_params = (LLSculptParams *)object->getParameterEntry(LLNetworkData::PARAMS_SCULPT); - if(sculpt_params) - { - texture_list.addTexture(LLViewerTextureManager::getFetchedTexture(sculpt_params->getSculptTexture())); - } - } } } return true; diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h index 294cfefb7..cf8c6d003 100644 --- a/indra/newview/llviewertexture.h +++ b/indra/newview/llviewertexture.h @@ -122,6 +122,8 @@ public: LLViewerTexture(const LLImageRaw* raw, BOOL usemipmaps) ; LLViewerTexture(const U32 width, const U32 height, const U8 components, BOOL usemipmaps) ; + void setNeedsAlphaAndPickMask(BOOL need_mask) { if(mGLTexturep)mGLTexturep->setNeedsAlphaAndPickMask(need_mask); } + virtual S8 getType() const; virtual BOOL isMissingAsset()const ; virtual void dump(); // debug info to llinfos diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 5750d4839..2088000f8 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -274,6 +274,8 @@ extern void toggle_debug_menus(void*); // LLDebugText // +extern std::map > > sTextureMaskMap; + class LLDebugText { private: @@ -336,6 +338,46 @@ public: addText(xpos, ypos, llformat("Time: %d:%02d:%02d", hours,mins,secs)); ypos += y_inc; } } + static const LLCachedControl analyze_target_texture("AnalyzeTargetTexture", false); + if(analyze_target_texture) + { + static LLViewerObject* lastObject = NULL; + LLSelectNode* nodep = LLSelectMgr::instance().getPrimaryHoverNode(); + LLObjectSelectionHandle handle = LLSelectMgr::instance().getHoverObjects(); + if(nodep || handle.notNull()) + { + + LLViewerObject* obj1 = nodep ? nodep->getObject() : NULL; + LLViewerObject* obj2 = handle ? handle->getPrimaryObject() : NULL; + LLViewerObject* obj = obj1 ? obj1 : obj2; + //llinfos << std::hex << obj1 << " " << obj2 << std::dec << llendl; + if(obj) + { + S32 te = nodep ? nodep->getLastSelectedTE() : -1; + if(te > 0) + { + LLViewerTexture* imagep = obj->getTEImage(te); + if(imagep && imagep != (LLViewerTexture*)LLViewerFetchedTexture::sDefaultImagep.get()) + { + LLGLuint tex = imagep->getTexName(); + std::map > >::iterator it = sTextureMaskMap.find(tex); + if(it != sTextureMaskMap.end()) + { + std::list >::reverse_iterator it2 = it->second.rbegin(); + for(;it2!=it->second.rend();++it2) + { + addText(xpos, ypos, llformat(" %s: %s", it2->first.c_str(), it2->second.c_str())); ypos += y_inc; + } + } + static const LLCachedControl use_rmse_auto_mask("SHUseRMSEAutoMask",false); + static const LLCachedControl alpha_mas_max_rmse("SHAlphaMaskMaxRMSE",.09f); + addText(xpos, ypos, llformat("Mask: %s", imagep->getIsAlphaMask(use_rmse_auto_mask ? alpha_mas_max_rmse : -1.f) ? "TRUE":"FALSE")); ypos += y_inc; + addText(xpos, ypos, llformat("ID: %s", imagep->getID().asString())); ypos += y_inc; + } + } + } + } + } #if LL_WINDOWS static const LLCachedControl debug_show_memory("DebugShowMemory"); diff --git a/indra/newview/llvosky.cpp b/indra/newview/llvosky.cpp index a9280517e..ea222c34d 100644 --- a/indra/newview/llvosky.cpp +++ b/indra/newview/llvosky.cpp @@ -298,6 +298,7 @@ void LLSkyTex::create(const F32 brightness) void LLSkyTex::createGLImage(S32 which) { + mTexture[which]->setNeedsAlphaAndPickMask(false); //Needed, else analyzeAlpha is called every frame for each texture. mTexture[which]->createGLTexture(0, mImageRaw[which], 0, TRUE, LLViewerTexture::LOCAL); mTexture[which]->setAddressMode(LLTexUnit::TAM_CLAMP); } diff --git a/indra/newview/skins/default/xui/en-us/floater_report_abuse.xml b/indra/newview/skins/default/xui/en-us/floater_report_abuse.xml index 7c726111f..7c1976e04 100644 --- a/indra/newview/skins/default/xui/en-us/floater_report_abuse.xml +++ b/indra/newview/skins/default/xui/en-us/floater_report_abuse.xml @@ -125,7 +125,7 @@ Fraud > Pyramid scheme or chain letter Fraud > US$ - + Freud > User has taken an interest in their mother Harassment > Advert farms / visual spam @@ -139,7 +139,7 @@ Harassment > Solicting/inciting others to violate ToS Harassment > Verbal abuse - + Harassment > User keeps licking finger and touching me Indecency > Broadly offensive content or conduct @@ -164,7 +164,7 @@ Land > Encroachment > Particles Land > Encroachment > Trees/plants - + Land > Encroachment > User won't stay on their side of the car Wagering/gambling diff --git a/indra/newview/skins/default/xui/en-us/notifications.xml b/indra/newview/skins/default/xui/en-us/notifications.xml index ff3d21719..a9062a821 100644 --- a/indra/newview/skins/default/xui/en-us/notifications.xml +++ b/indra/newview/skins/default/xui/en-us/notifications.xml @@ -4953,6 +4953,15 @@ Be as specific as you can, including steps to reproduce the bug if possible. Entering an accurate description helps us file and process bug reports. + +Do not meddle in the affairs of wizards, for they are subtle and quick to anger. - J.R.R. Tolkien + +Please choose a legitimate category if you actually have something to report. + +