From 446c55538e1fb12d8a1feb541edf99c16bb29121 Mon Sep 17 00:00:00 2001 From: Mark Palange Date: Tue, 13 Jan 2009 03:46:56 +0000 Subject: svn merge -r106055-107012 svn+ssh://svn.lindenlab.com/svn/linden/branches/viewer/viewer_1-22/ merge RC5 changes into trunk, plus add'l localization xml (all newly added) files that should have been added with RC0-RC4 merge, but weren't. --- doc/contributions.txt | 1 + indra/llmath/llvolume.cpp | 30 +- indra/llmath/llvolume.h | 7 +- indra/llrender/llimagegl.cpp | 146 +++++-- indra/llrender/llimagegl.h | 27 +- indra/llrender/llpostprocess.cpp | 93 +++-- indra/llrender/llpostprocess.h | 13 +- indra/llrender/llrender.cpp | 8 +- indra/llui/llmenugl.cpp | 164 ++++---- indra/llui/llmenugl.h | 16 +- indra/mac_crash_logger/llcrashloggermac.cpp | 2 + indra/newview/CMakeLists.txt | 1 + indra/newview/installers/windows/lang_zh.nsi | Bin 5552 -> 5554 bytes indra/newview/installers/windows/language_menu.nsi | Bin 1292 -> 1302 bytes indra/newview/llappviewermacosx.cpp | 107 +++++- indra/newview/lldrawpoolbump.cpp | 5 - indra/newview/lldynamictexture.cpp | 43 ++- indra/newview/lldynamictexture.h | 3 + indra/newview/llfloaterimagepreview.cpp | 35 +- indra/newview/llfloaterimagepreview.h | 2 +- indra/newview/llhudicon.cpp | 101 +++++ indra/newview/llhudicon.h | 3 + indra/newview/llmaniptranslate.cpp | 42 +- indra/newview/llmaniptranslate.h | 2 + indra/newview/lltexlayer.cpp | 85 +++-- indra/newview/lltexlayer.h | 8 +- indra/newview/lltoolmorph.cpp | 2 +- indra/newview/llviewerjointattachment.cpp | 2 + indra/newview/llviewerwindow.cpp | 88 ++++- indra/newview/llviewerwindow.h | 3 + indra/newview/llvoavatar.cpp | 16 + indra/newview/pipeline.cpp | 59 ++- .../skins/default/xui/da/floater_about_land.xml | 4 +- .../skins/default/xui/da/floater_buy_currency.xml | 6 +- .../skins/default/xui/da/floater_buy_land.xml | 12 +- indra/newview/skins/default/xui/da/floater_pay.xml | 4 +- .../default/xui/da/panel_preferences_general.xml | 2 +- .../skins/default/xui/de/floater_beacons.xml | 15 + .../default/xui/de/panel_group_land_money.xml | 2 +- .../default/xui/de/panel_preferences_general.xml | 2 +- .../default/xui/es/panel_group_land_money.xml | 4 +- .../default/xui/es/panel_preferences_general.xml | 2 +- .../skins/default/xui/fr/floater_about_land.xml | 2 +- .../skins/default/xui/fr/floater_beacons.xml | 15 + indra/newview/skins/default/xui/fr/floater_pay.xml | 2 +- .../newview/skins/default/xui/fr/floater_tools.xml | 6 +- indra/newview/skins/default/xui/fr/menu_viewer.xml | 2 +- .../default/xui/fr/panel_group_land_money.xml | 2 +- .../default/xui/fr/panel_preferences_general.xml | 2 +- .../skins/default/xui/ja/floater_beacons.xml | 15 + .../skins/default/xui/ja/floater_customize.xml | 6 +- .../skins/default/xui/ja/floater_inventory.xml | 6 +- .../xui/ja/floater_inventory_item_properties.xml | 8 +- .../skins/default/xui/ja/menu_inventory.xml | 8 +- .../default/xui/ja/panel_preferences_general.xml | 2 +- .../skins/default/xui/pl/floater_about_land.xml | 22 +- .../skins/default/xui/pl/floater_avatar_picker.xml | 2 +- .../skins/default/xui/pl/floater_beacons.xml | 8 +- .../skins/default/xui/pl/floater_buy_currency.xml | 9 +- .../skins/default/xui/pl/floater_buy_land.xml | 10 +- .../skins/default/xui/pl/floater_color_picker.xml | 2 +- .../skins/default/xui/pl/floater_critical.xml | 2 +- .../skins/default/xui/pl/floater_customize.xml | 65 ++-- .../default/xui/pl/floater_day_cycle_options.xml | 4 +- .../default/xui/pl/floater_hardware_settings.xml | 6 +- .../skins/default/xui/pl/floater_image_preview.xml | 10 +- .../skins/default/xui/pl/floater_inspect.xml | 4 +- .../skins/default/xui/pl/floater_joystick.xml | 2 +- .../skins/default/xui/pl/floater_land_holdings.xml | 2 +- .../default/xui/pl/floater_live_lsleditor.xml | 4 +- .../skins/default/xui/pl/floater_media_browser.xml | 2 +- indra/newview/skins/default/xui/pl/floater_pay.xml | 3 +- .../skins/default/xui/pl/floater_pay_object.xml | 23 +- .../default/xui/pl/floater_preview_animation.xml | 4 +- .../skins/default/xui/pl/floater_report_abuse.xml | 20 +- .../skins/default/xui/pl/floater_snapshot.xml | 4 +- .../newview/skins/default/xui/pl/floater_tools.xml | 44 +-- .../skins/default/xui/pl/floater_url_entry.xml | 2 +- indra/newview/skins/default/xui/pl/menu_viewer.xml | 12 +- .../newview/skins/default/xui/pl/panel_friends.xml | 12 +- .../default/xui/pl/panel_group_land_money.xml | 2 +- indra/newview/skins/default/xui/pl/panel_login.xml | 2 +- .../default/xui/pl/panel_preferences_general.xml | 6 +- .../skins/default/xui/pl/panel_region_debug.xml | 2 +- indra/newview/skins/default/xui/pl/strings.xml | 8 +- .../skins/default/xui/pt/floater_about_land.xml | 17 +- .../skins/default/xui/pt/floater_beacons.xml | 15 + .../skins/default/xui/pt/floater_buy_currency.xml | 8 +- .../skins/default/xui/pt/floater_buy_land.xml | 2 +- .../skins/default/xui/pt/floater_camera.xml | 12 + .../skins/default/xui/pt/floater_color_picker.xml | 5 +- .../skins/default/xui/pt/floater_customize.xml | 68 +++- .../default/xui/pt/floater_day_cycle_options.xml | 67 ++++ .../skins/default/xui/pt/floater_env_settings.xml | 23 ++ .../default/xui/pt/floater_hardware_settings.xml | 38 ++ indra/newview/skins/default/xui/pt/floater_hud.xml | 2 + .../skins/default/xui/pt/floater_image_preview.xml | 4 +- .../skins/default/xui/pt/floater_lagmeter.xml | 152 ++++++++ .../skins/default/xui/pt/floater_media_browser.xml | 20 + .../skins/default/xui/pt/floater_mem_leaking.xml | 12 + .../skins/default/xui/pt/floater_mute_object.xml | 11 + .../skins/default/xui/pt/floater_openobject.xml | 4 +- indra/newview/skins/default/xui/pt/floater_pay.xml | 12 +- .../skins/default/xui/pt/floater_pay_object.xml | 23 +- .../skins/default/xui/pt/floater_postcard.xml | 6 +- .../default/xui/pt/floater_preview_animation.xml | 4 +- .../default/xui/pt/floater_preview_classified.xml | 2 + .../skins/default/xui/pt/floater_preview_event.xml | 2 + .../skins/default/xui/pt/floater_region_info.xml | 2 + .../skins/default/xui/pt/floater_url_entry.xml | 12 + .../newview/skins/default/xui/pt/floater_water.xml | 85 +++++ .../default/xui/pt/floater_windlight_options.xml | 186 +++++++++ indra/newview/skins/default/xui/pt/menu_login.xml | 13 + indra/newview/skins/default/xui/pt/menu_slurl.xml | 6 + indra/newview/skins/default/xui/pt/mime_types.xml | 230 +++++++++++ .../skins/default/xui/pt/panel_audio_device.xml | 15 + .../newview/skins/default/xui/pt/panel_friends.xml | 14 + .../default/xui/pt/panel_group_land_money.xml | 2 +- .../default/xui/pt/panel_preferences_chat.xml | 7 +- .../default/xui/pt/panel_preferences_general.xml | 10 +- .../default/xui/pt/panel_preferences_graphics1.xml | 8 +- indra/newview/skins/default/xui/pt/strings.xml | 421 +++++++++++++++++++++ 122 files changed, 2528 insertions(+), 533 deletions(-) create mode 100644 indra/newview/skins/default/xui/de/floater_beacons.xml create mode 100644 indra/newview/skins/default/xui/fr/floater_beacons.xml create mode 100644 indra/newview/skins/default/xui/ja/floater_beacons.xml create mode 100644 indra/newview/skins/default/xui/pt/floater_beacons.xml create mode 100644 indra/newview/skins/default/xui/pt/floater_camera.xml create mode 100644 indra/newview/skins/default/xui/pt/floater_day_cycle_options.xml create mode 100644 indra/newview/skins/default/xui/pt/floater_env_settings.xml create mode 100644 indra/newview/skins/default/xui/pt/floater_hardware_settings.xml create mode 100644 indra/newview/skins/default/xui/pt/floater_hud.xml create mode 100644 indra/newview/skins/default/xui/pt/floater_lagmeter.xml create mode 100644 indra/newview/skins/default/xui/pt/floater_media_browser.xml create mode 100644 indra/newview/skins/default/xui/pt/floater_mem_leaking.xml create mode 100644 indra/newview/skins/default/xui/pt/floater_mute_object.xml create mode 100644 indra/newview/skins/default/xui/pt/floater_preview_classified.xml create mode 100644 indra/newview/skins/default/xui/pt/floater_preview_event.xml create mode 100644 indra/newview/skins/default/xui/pt/floater_region_info.xml create mode 100644 indra/newview/skins/default/xui/pt/floater_url_entry.xml create mode 100644 indra/newview/skins/default/xui/pt/floater_water.xml create mode 100644 indra/newview/skins/default/xui/pt/floater_windlight_options.xml create mode 100644 indra/newview/skins/default/xui/pt/menu_login.xml create mode 100644 indra/newview/skins/default/xui/pt/menu_slurl.xml create mode 100644 indra/newview/skins/default/xui/pt/mime_types.xml create mode 100644 indra/newview/skins/default/xui/pt/panel_audio_device.xml create mode 100644 indra/newview/skins/default/xui/pt/panel_friends.xml create mode 100644 indra/newview/skins/default/xui/pt/strings.xml diff --git a/doc/contributions.txt b/doc/contributions.txt index 42ee00f952..fb3f7ea466 100644 --- a/doc/contributions.txt +++ b/doc/contributions.txt @@ -149,6 +149,7 @@ Fremont Cunningham VWR-1147 Geneko Nemeth CT-117 + VWR-11069 Gigs Taggart SVC-493 VWR-6 diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index 1a7f7ac1a0..7d01ba059c 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -1651,9 +1651,13 @@ void LLPathParams::copyParams(const LLPathParams ¶ms) setSkew(params.getSkew()); } +S32 profile_delete_lock = 1 ; LLProfile::~LLProfile() { - + if(profile_delete_lock) + { + llerrs << "LLProfile should not be deleted here!" << llendl ; + } } @@ -1710,7 +1714,11 @@ LLVolume::~LLVolume() { sNumMeshPoints -= mMesh.size(); delete mPathp; + + profile_delete_lock = 0 ; delete mProfilep; + profile_delete_lock = 1 ; + mPathp = NULL; mProfilep = NULL; mVolumeFaces.clear(); @@ -1755,6 +1763,20 @@ BOOL LLVolume::generate() mLODScaleBias.setVec(0.6f, 0.6f, 0.6f); } + //******************************************************************** + //debug info, to be removed + if((U32)(mPathp->mPath.size() * mProfilep->mProfile.size()) > (1u << 20)) + { + llinfos << "sizeS: " << mPathp->mPath.size() << " sizeT: " << mProfilep->mProfile.size() << llendl ; + llinfos << "path_detail : " << path_detail << " split: " << split << " profile_detail: " << profile_detail << llendl ; + llinfos << mParams << llendl ; + llinfos << "more info to check if mProfilep is deleted or not." << llendl ; + llinfos << mProfilep->mNormals.size() << " : " << mProfilep->mFaces.size() << " : " << mProfilep->mEdgeNormals.size() << " : " << mProfilep->mEdgeCenters.size() << llendl ; + + llerrs << "LLVolume corrupted!" << llendl ; + } + //******************************************************************** + BOOL regenPath = mPathp->generate(mParams.getPathParams(), path_detail, split); BOOL regenProf = mProfilep->generate(mParams.getProfileParams(), mPathp->isOpen(),profile_detail, split); @@ -1763,16 +1785,20 @@ BOOL LLVolume::generate() S32 sizeS = mPathp->mPath.size(); S32 sizeT = mProfilep->mProfile.size(); - //debug info + //******************************************************************** + //debug info, to be removed if((U32)(sizeS * sizeT) > (1u << 20)) { llinfos << "regenPath: " << (S32)regenPath << " regenProf: " << (S32)regenProf << llendl ; llinfos << "sizeS: " << sizeS << " sizeT: " << sizeT << llendl ; llinfos << "path_detail : " << path_detail << " split: " << split << " profile_detail: " << profile_detail << llendl ; llinfos << mParams << llendl ; + llinfos << "more info to check if mProfilep is deleted or not." << llendl ; + llinfos << mProfilep->mNormals.size() << " : " << mProfilep->mFaces.size() << " : " << mProfilep->mEdgeNormals.size() << " : " << mProfilep->mEdgeCenters.size() << llendl ; llerrs << "LLVolume corrupted!" << llendl ; } + //******************************************************************** sNumMeshPoints -= mMesh.size(); mMesh.resize(sizeT * sizeS); diff --git a/indra/llmath/llvolume.h b/indra/llmath/llvolume.h index 38e8f806e2..ab30d78333 100644 --- a/indra/llmath/llvolume.h +++ b/indra/llmath/llvolume.h @@ -672,9 +672,7 @@ public: mConcave(FALSE), mDirty(TRUE), mTotalOut(0), - mTotal(2), - mMinX(0.f), - mMaxX(0.f) + mTotal(2) { } @@ -722,9 +720,6 @@ protected: S32 mTotalOut; S32 mTotal; - - F32 mMaxX; - F32 mMinX; }; //------------------------------------------------------------------- diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index 74b2d292e9..3e1c160198 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -62,8 +62,56 @@ S32 LLImageGL::sCount = 0; BOOL LLImageGL::sGlobalUseAnisotropic = FALSE; F32 LLImageGL::sLastFrameTime = 0.f; +S32 LLImageGL::sMaxTextureSize = 0 ; + std::set LLImageGL::sImageList; +//************************************************************************************** +//below are functions for debug use +//do not delete them even though they are not currently being used. +void check_all_images() +{ + for (std::set::iterator iter = LLImageGL::sImageList.begin(); + iter != LLImageGL::sImageList.end(); iter++) + { + LLImageGL* glimage = *iter; + if (glimage->getTexName() && glimage->isGLTextureCreated()) + { + gGL.getTexUnit(0)->bind(glimage) ; + glimage->checkTexSize() ; + gGL.getTexUnit(0)->unbind(glimage->getTarget()) ; + } + } +} + +void LLImageGL::checkTexSize() const +{ + if (gDebugGL && mTarget == GL_TEXTURE_2D) + { + GLint texname; + glGetIntegerv(GL_TEXTURE_BINDING_2D, &texname); + if (texname != mTexName) + { + llerrs << "Invalid texture bound!" << llendl; + } + stop_glerror() ; + LLGLint x = 0, y = 0 ; + glGetTexLevelParameteriv(mTarget, 0, GL_TEXTURE_WIDTH, (GLint*)&x); + glGetTexLevelParameteriv(mTarget, 0, GL_TEXTURE_HEIGHT, (GLint*)&y) ; + stop_glerror() ; + if(!x || !y) + { + return ; + } + if(x != (mWidth >> mCurrentDiscardLevel) || y != (mHeight >> mCurrentDiscardLevel)) + { + llerrs << "wrong texture size and discard level!" << llendl ; + } + } +} +//end of debug functions +//************************************************************************************** + //---------------------------------------------------------------------------- //static @@ -149,17 +197,22 @@ void LLImageGL::destroyGL(BOOL save_state) { gGL.getTexUnit(stage)->unbind(LLTexUnit::TT_TEXTURE); } + for (std::set::iterator iter = sImageList.begin(); iter != sImageList.end(); iter++) { LLImageGL* glimage = *iter; - if (glimage->mTexName && glimage->mComponents) + if (glimage->mTexName) { - if (save_state && glimage->isInitialized()) + if (save_state && glimage->isGLTextureCreated() && glimage->mComponents) { glimage->mSaveData = new LLImageRaw; - glimage->readBackRaw(glimage->mCurrentDiscardLevel, glimage->mSaveData, false); + if(!glimage->readBackRaw(glimage->mCurrentDiscardLevel, glimage->mSaveData, false)) + { + glimage->mSaveData = NULL ; + } } + glimage->destroyGLTexture(); stop_glerror(); } @@ -173,9 +226,13 @@ void LLImageGL::restoreGL() iter != sImageList.end(); iter++) { LLImageGL* glimage = *iter; - if (glimage->mSaveData.notNull() && glimage->mSaveData->getComponents()) + if(glimage->getTexName()) + { + llerrs << "tex name is not 0." << llendl ; + } + if (glimage->mSaveData.notNull()) { - if (glimage->getComponents()) + if (glimage->getComponents() && glimage->mSaveData->getComponents()) { glimage->createGLTexture(glimage->mCurrentDiscardLevel, glimage->mSaveData); stop_glerror(); @@ -283,7 +340,7 @@ void LLImageGL::init(BOOL usemipmaps) mFormatSwapBytes = FALSE; mHasExplicitFormat = FALSE; - mInitialized = true; + mGLTextureCreated = FALSE ; } void LLImageGL::cleanup() @@ -322,6 +379,16 @@ void LLImageGL::setSize(S32 width, S32 height, S32 ncomponents) { if (width != mWidth || height != mHeight || ncomponents != mComponents) { + if(width > 1024 || height > 1024) + { + llwarns << "texture size is big: width: " << width << " height: " << height << llendl ; + if(!sMaxTextureSize) + { + glGetIntegerv(GL_MAX_TEXTURE_SIZE, (GLint*)&sMaxTextureSize) ; + } + llwarns << "max texture size is: " << sMaxTextureSize << llendl ; + } + // Check if dimensions are a power of two! if (!checkSize(width,height)) { @@ -645,7 +712,7 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips) mHasMipMaps = FALSE; } stop_glerror(); - mInitialized = true; + mGLTextureCreated = true; } BOOL LLImageGL::setSubImage(const U8* datap, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height) @@ -735,9 +802,8 @@ BOOL LLImageGL::setSubImage(const U8* datap, S32 data_width, S32 data_height, S3 glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); stop_glerror(); - mInitialized = true; + mGLTextureCreated = true; } - return TRUE; } @@ -752,7 +818,7 @@ BOOL LLImageGL::setSubImageFromFrameBuffer(S32 fb_x, S32 fb_y, S32 x_pos, S32 y_ if (gGL.getTexUnit(0)->bind(this, true)) { glCopyTexSubImage2D(GL_TEXTURE_2D, 0, fb_x, fb_y, x_pos, y_pos, width, height); - mInitialized = true; + mGLTextureCreated = true; stop_glerror(); return TRUE; } @@ -762,6 +828,36 @@ BOOL LLImageGL::setSubImageFromFrameBuffer(S32 fb_x, S32 fb_y, S32 x_pos, S32 y_ } } +//create an empty GL texture: just create a texture name +//the texture is assiciate with some image by calling glTexImage outside LLImageGL +BOOL LLImageGL::createGLTexture() +{ + if (gGLManager.mIsDisabled) + { + llwarns << "Trying to create a texture while GL is disabled!" << llendl; + return FALSE; + } + + mGLTextureCreated = false ; //do not save this texture when gl is destroyed. + + llassert(gGLManager.mInited); + stop_glerror(); + + if(mTexName) + { + glDeleteTextures(1, (reinterpret_cast(&mTexName))) ; + } + + glGenTextures(1, (GLuint*)&mTexName); + stop_glerror(); + if (!mTexName) + { + llerrs << "LLImageGL::createGLTexture failed to make an empty texture" << llendl; + } + + return TRUE ; +} + BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename/*=0*/) { if (gGLManager.mIsDisabled) @@ -769,6 +865,7 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S llwarns << "Trying to create a texture while GL is disabled!" << llendl; return FALSE; } + mGLTextureCreated = false ; llassert(gGLManager.mInited); stop_glerror(); @@ -874,7 +971,7 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_ #endif } - mCurrentDiscardLevel = discard_level; + mCurrentDiscardLevel = discard_level; setImage(data_in, data_hasmips); @@ -975,7 +1072,7 @@ BOOL LLImageGL::readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compre discard_level = mCurrentDiscardLevel; } - if (mTexName == 0 || discard_level < mCurrentDiscardLevel) + if (mTexName == 0 || discard_level < mCurrentDiscardLevel || discard_level > mMaxDiscardLevel ) { return FALSE; } @@ -986,18 +1083,8 @@ BOOL LLImageGL::readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compre gGL.getTexUnit(0)->unbind(mBindTarget); llverify(gGL.getTexUnit(0)->bind(this)); - if (gDebugGL) - { - if (mTarget == GL_TEXTURE_2D) - { - GLint texname; - glGetIntegerv(GL_TEXTURE_BINDING_2D, &texname); - if (texname != mTexName) - { - llerrs << "Invalid texture bound!" << llendl; - } - } - } + //debug code, leave it there commented. + //checkTexSize() ; LLGLint glwidth = 0; glGetTexLevelParameteriv(mTarget, gl_discard, GL_TEXTURE_WIDTH, (GLint*)&glwidth); @@ -1006,7 +1093,7 @@ BOOL LLImageGL::readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compre // No mip data smaller than current discard level return FALSE; } - + S32 width = getWidth(discard_level); S32 height = getHeight(discard_level); S32 ncomponents = getComponents(); @@ -1014,6 +1101,13 @@ BOOL LLImageGL::readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compre { return FALSE; } + if(width < glwidth) + { + llwarns << "texture size is smaller than it should be." << llendl ; + llwarns << "width: " << width << " glwidth: " << glwidth << " mWidth: " << mWidth << + " mCurrentDiscardLevel: " << (S32)mCurrentDiscardLevel << " discard_level: " << (S32)discard_level << llendl ; + return FALSE ; + } if (width <= 0 || width > 2048 || height <= 0 || height > 2048 || ncomponents < 1 || ncomponents > 4) { @@ -1099,7 +1193,7 @@ void LLImageGL::destroyGLTexture() glDeleteTextures(1, (GLuint*)&mTexName); mTexName = 0; - + mGLTextureCreated = FALSE ; stop_glerror(); } } diff --git a/indra/llrender/llimagegl.h b/indra/llrender/llimagegl.h index b3aa8f0984..01159ed744 100644 --- a/indra/llrender/llimagegl.h +++ b/indra/llrender/llimagegl.h @@ -91,6 +91,7 @@ public: void setSize(S32 width, S32 height, S32 ncomponents); + BOOL createGLTexture() ; BOOL createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename = 0); BOOL createGLTexture(S32 discard_level, const U8* data, BOOL data_hasmips = FALSE, S32 usename = 0); void setImage(const LLImageRaw* imageraw); @@ -114,6 +115,8 @@ public: S32 getDiscardLevel() const { return mCurrentDiscardLevel; } S32 getMaxDiscardLevel() const { return mMaxDiscardLevel; } + S32 getCurrentWidth() const { return mWidth ;} + S32 getCurrentHeight() const { return mHeight ;} S32 getWidth(S32 discard_level = -1) const; S32 getHeight(S32 discard_level = -1) const; U8 getComponents() const { return mComponents; } @@ -135,8 +138,8 @@ public: void setTarget(const LLGLenum target, const LLTexUnit::eTextureType bind_target); LLTexUnit::eTextureType getTarget(void) const { return mBindTarget; } - bool isInitialized(void) const { return mInitialized; } - void setInitialized (bool initialized) { mInitialized = initialized; } + bool isGLTextureCreated(void) const { return mGLTextureCreated ; } + void setGLTextureCreated (bool initialized) { mGLTextureCreated = initialized; } BOOL getUseMipMaps() const { return mUseMipMaps; } void setUseMipMaps(BOOL usemips) { mUseMipMaps = usemips; } @@ -148,6 +151,8 @@ public: void updatePickMask(S32 width, S32 height, const U8* data_in); BOOL getMask(const LLVector2 &tc); + void checkTexSize() const ; + protected: void init(BOOL usemipmaps); virtual void cleanup(); // Clean up the LLImageGL so it can be reinitialized. Be careful when using this in derived class destructors @@ -165,21 +170,20 @@ private: S8 mHasExplicitFormat; // If false (default), GL format is f(mComponents) S8 mAutoGenMips; + bool mGLTextureCreated ; + LLGLuint mTexName; + U16 mWidth; + U16 mHeight; + S8 mCurrentDiscardLevel; + protected: LLGLenum mTarget; // Normally GL_TEXTURE2D, sometimes something else (ex. cube maps) LLTexUnit::eTextureType mBindTarget; // Normally TT_TEXTURE, sometimes something else (ex. cube maps) - bool mInitialized; - - LLGLuint mTexName; - + LLGLboolean mIsResident; - - U16 mWidth; - U16 mHeight; S8 mComponents; - S8 mMaxDiscardLevel; - S8 mCurrentDiscardLevel; + S8 mMaxDiscardLevel; S8 mDontDiscard; // Keep full res version of this image (for UI, etc) S8 mClampS; // Need to save clamp state @@ -210,6 +214,7 @@ public: static U32 sUniqueCount; // Tracks number of unique texture binds for current frame static BOOL sGlobalUseAnisotropic; + static S32 sMaxTextureSize ; #if DEBUG_MISS BOOL mMissed; // Missed on last bind? BOOL getMissed() const { return mMissed; }; diff --git a/indra/llrender/llpostprocess.cpp b/indra/llrender/llpostprocess.cpp index 6aff279a21..940abb54d4 100644 --- a/indra/llrender/llpostprocess.cpp +++ b/indra/llrender/llpostprocess.cpp @@ -52,12 +52,14 @@ static const float LUMINANCE_B = 0.114f; static const char * const XML_FILENAME = "postprocesseffects.xml"; LLPostProcess::LLPostProcess(void) : - sceneRenderTexture(0), noiseTexture(0), - tempBloomTexture(0), initialized(false), mAllEffects(LLSD::emptyMap()), screenW(1), screenH(1) { + mSceneRenderTexture = NULL ; + mNoiseTexture = NULL ; + mTempBloomTexture = NULL ; + /* Do nothing. Needs to be updated to use our current shader system, and to work with the move into llrender. std::string pathName(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "windlight", XML_FILENAME)); LL_DEBUGS2("AppInit", "Shaders") << "Loading PostProcess Effects settings from " << pathName << LL_ENDL; @@ -111,9 +113,7 @@ LLPostProcess::LLPostProcess(void) : LLPostProcess::~LLPostProcess(void) { - glDeleteTextures(1, &sceneRenderTexture); - glDeleteTextures(1, &noiseTexture); - glDeleteTextures(1, &tempBloomTexture); + invalidate() ; } // static @@ -158,6 +158,13 @@ void LLPostProcess::saveEffect(std::string const & effectName) formatter->format(mAllEffects, effectsXML); */ } +void LLPostProcess::invalidate() +{ + mSceneRenderTexture = NULL ; + mNoiseTexture = NULL ; + mTempBloomTexture = NULL ; + initialized = FALSE ; +} void LLPostProcess::apply(unsigned int width, unsigned int height) { @@ -173,7 +180,7 @@ void LLPostProcess::initialize(unsigned int width, unsigned int height) { screenW = width; screenH = height; - createTexture(sceneRenderTexture, screenW, screenH); + createTexture(mSceneRenderTexture, screenW, screenH); initialized = true; checkError(); @@ -199,16 +206,20 @@ void LLPostProcess::applyShaders(void) } if (tweaks.useNightVisionShader()){ /// If any of the above shaders have been called update the frame buffer; - if (tweaks.useColorFilter()){ - copyFrameBuffer(sceneRenderTexture, screenW, screenH); + if (tweaks.useColorFilter()) + { + GLuint tex = mSceneRenderTexture->getTexName() ; + copyFrameBuffer(tex, screenW, screenH); } applyNightVisionShader(); checkError(); } if (tweaks.useBloomShader()){ /// If any of the above shaders have been called update the frame buffer; - if (tweaks.useColorFilter().asBoolean() || tweaks.useNightVisionShader().asBoolean()){ - copyFrameBuffer(sceneRenderTexture, screenW, screenH); + if (tweaks.useColorFilter().asBoolean() || tweaks.useNightVisionShader().asBoolean()) + { + GLuint tex = mSceneRenderTexture->getTexName() ; + copyFrameBuffer(tex, screenW, screenH); } applyBloomShader(); checkError(); @@ -306,7 +317,7 @@ void LLPostProcess::createNightVisionShader(void) nightVisionUniforms["noiseStrength"] = 0; nightVisionUniforms["lumWeights"] = 0; - createNoiseTexture(noiseTexture); + createNoiseTexture(mNoiseTexture); } void LLPostProcess::applyBloomShader(void) @@ -316,7 +327,7 @@ void LLPostProcess::applyBloomShader(void) void LLPostProcess::createBloomShader(void) { - createTexture(tempBloomTexture, unsigned(screenW * 0.5), unsigned(screenH * 0.5)); + createTexture(mTempBloomTexture, unsigned(screenW * 0.5), unsigned(screenH * 0.5)); /// Create Bloom Extract Shader bloomExtractUniforms["RenderTexture"] = 0; @@ -348,7 +359,10 @@ void LLPostProcess::doEffects(void) glPushClientAttrib(GL_ALL_ATTRIB_BITS); /// Copy the screen buffer to the render texture - copyFrameBuffer(sceneRenderTexture, screenW, screenH); + { + GLuint tex = mSceneRenderTexture->getTexName() ; + copyFrameBuffer(tex, screenW, screenH); + } /// Clear the frame buffer. glClearColor(0.0f, 0.0f, 0.0f, 1.0f); @@ -479,43 +493,42 @@ void LLPostProcess::changeOrthogonal(unsigned int width, unsigned int height) viewOrthogonal(width, height); } -void LLPostProcess::createTexture(GLuint & texture, unsigned int width, unsigned int height) +void LLPostProcess::createTexture(LLPointer& texture, unsigned int width, unsigned int height) { - if (texture != 0){ - glDeleteTextures(1, &texture); - } - - std::vector data(width * height * 4, 0); - - glGenTextures(1, &texture); - gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_RECT_TEXTURE, texture); - glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 4, width, height, 0, - GL_RGBA, GL_UNSIGNED_BYTE, &data[0]); - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB,GL_TEXTURE_MIN_FILTER,GL_LINEAR); - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB,GL_TEXTURE_MAG_FILTER,GL_LINEAR); - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB,GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB,GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); -} + std::vector data(width * height * 4, 0) ; -void LLPostProcess::createNoiseTexture(GLuint & texture) -{ - if (texture != 0){ - glDeleteTextures(1, &texture); + texture = new LLImageGL(FALSE) ; + if(texture->createGLTexture()) + { + gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_RECT_TEXTURE, texture->getTexName()); + glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 4, width, height, 0, + GL_RGBA, GL_UNSIGNED_BYTE, &data[0]); + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB,GL_TEXTURE_MIN_FILTER,GL_LINEAR); + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB,GL_TEXTURE_MAG_FILTER,GL_LINEAR); + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB,GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB,GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); } - glGenTextures(1, &texture); +} +void LLPostProcess::createNoiseTexture(LLPointer& texture) +{ std::vector buffer(NOISE_SIZE * NOISE_SIZE); for (unsigned int i = 0; i < NOISE_SIZE; i++){ for (unsigned int k = 0; k < NOISE_SIZE; k++){ buffer[(i * NOISE_SIZE) + k] = (GLubyte)((double) rand() / ((double) RAND_MAX + 1.f) * 255.f); } } - gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, texture); - glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, NOISE_SIZE, NOISE_SIZE, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, &buffer[0]); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + + texture = new LLImageGL(FALSE) ; + if(texture->createGLTexture()) + { + gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, texture->getTexName()); + glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, NOISE_SIZE, NOISE_SIZE, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, &buffer[0]); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + } } bool LLPostProcess::checkError(void) diff --git a/indra/llrender/llpostprocess.h b/indra/llrender/llpostprocess.h index 8e278f8e10..e5e34d920c 100644 --- a/indra/llrender/llpostprocess.h +++ b/indra/llrender/llpostprocess.h @@ -184,21 +184,24 @@ public: }; - GLuint sceneRenderTexture; - GLuint noiseTexture; - GLuint tempBloomTexture; bool initialized; PostProcessTweaks tweaks; // the map of all availible effects LLSD mAllEffects; +private: + LLPointer mSceneRenderTexture ; + LLPointer mNoiseTexture ; + LLPointer mTempBloomTexture ; + public: LLPostProcess(void); ~LLPostProcess(void); void apply(unsigned int width, unsigned int height); + void invalidate() ; /// Perform global initialization for this class. static void initClass(void); @@ -252,9 +255,9 @@ private: /// OpenGL Helper Functions void getShaderUniforms(glslUniforms & uniforms, GLhandleARB & prog); - void createTexture(GLuint & texture, unsigned int width, unsigned int height); + void createTexture(LLPointer& texture, unsigned int width, unsigned int height); void copyFrameBuffer(GLuint & texture, unsigned int width, unsigned int height); - void createNoiseTexture(GLuint & texture); + void createNoiseTexture(LLPointer& texture); bool checkError(void); void checkShaderError(GLhandleARB shader); void drawOrthoQuad(unsigned int width, unsigned int height, QuadType type); diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index 433be9e2eb..c7068133d2 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -187,17 +187,11 @@ bool LLTexUnit::bind(const LLImageGL* texture, bool forceBind) llwarns << "NULL LLTexUnit::bind texture" << llendl; return false; } - - if (!texture->isInitialized() && !forceBind) - { - return texture->bindDefaultImage(mIndex); - } - + if (!texture->getTexName()) //if texture does not exist { return texture->bindDefaultImage(mIndex); } - // Disabled caching of binding state. activate(); enable(texture->getTarget()); diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp index 28b591b7c2..ad980d67fc 100644 --- a/indra/llui/llmenugl.cpp +++ b/indra/llui/llmenugl.cpp @@ -1034,30 +1034,47 @@ void LLMenuItemToggleGL::doIt( void ) } -LLMenuItemBranchGL::LLMenuItemBranchGL( const std::string& name, const std::string& label, LLMenuGL* branch, +LLMenuItemBranchGL::LLMenuItemBranchGL( const std::string& name, const std::string& label, LLHandle branch, KEY key, MASK mask ) : LLMenuItemGL( name, label, key, mask ), mBranch( branch ) { - mBranch->setVisible( FALSE ); - mBranch->setParentMenuItem(this); + if(!dynamic_cast(branch.get())) + { + llerrs << "Non-menu handle passed as branch reference." << llendl; + } + + if(getBranch()) + { + getBranch()->setVisible( FALSE ); + getBranch()->setParentMenuItem(this); + } +} + +LLMenuItemBranchGL::~LLMenuItemBranchGL() +{ + LLView::deleteViewByHandle(mBranch); } // virtual LLView* LLMenuItemBranchGL::getChildView(const std::string& name, BOOL recurse, BOOL create_if_missing) const { // richard: this is redundant with parent, remove - if (mBranch->getName() == name) - { - return mBranch; - } - // Always recurse on branches - LLView* child = mBranch->getChildView(name, recurse, FALSE); - if (!child) + if (getBranch()) { - child = LLView::getChildView(name, recurse, create_if_missing); + if(getBranch()->getName() == name) + { + return getBranch(); + } + + // Always recurse on branches + LLView* child = getBranch()->getChildView(name, recurse, FALSE); + if(child) + { + return child; + } } - return child; + return LLView::getChildView(name, recurse, create_if_missing);; } // virtual @@ -1073,15 +1090,19 @@ BOOL LLMenuItemBranchGL::handleMouseUp(S32 x, S32 y, MASK mask) BOOL LLMenuItemBranchGL::handleAcceleratorKey(KEY key, MASK mask) { - return mBranch->handleAcceleratorKey(key, mask); + if(getBranch()) + { + return getBranch()->handleAcceleratorKey(key, mask); + } + return FALSE; } // virtual LLXMLNodePtr LLMenuItemBranchGL::getXML(bool save_children) const { - if (mBranch) + if (getBranch()) { - return mBranch->getXML(); + return getBranch()->getXML(); } return LLMenuItemGL::getXML(); @@ -1092,14 +1113,17 @@ LLXMLNodePtr LLMenuItemBranchGL::getXML(bool save_children) const // if not, it will be added to the list BOOL LLMenuItemBranchGL::addToAcceleratorList(std::list *listp) { - U32 item_count = mBranch->getItemCount(); - LLMenuItemGL *item; - - while (item_count--) + if(getBranch()) { - if ((item = mBranch->getItem(item_count))) + U32 item_count = getBranch()->getItemCount(); + LLMenuItemGL *item; + + while (item_count--) { - return item->addToAcceleratorList(listp); + if ((item = getBranch()->getItem(item_count))) + { + return item->addToAcceleratorList(listp); + } } } return FALSE; @@ -1123,18 +1147,18 @@ void LLMenuItemBranchGL::doIt( void ) // keyboard navigation automatically propagates highlight to sub-menu // to facilitate fast menu control via jump keys - if (LLMenuGL::getKeyboardMode() && !mBranch->getHighlightedItem()) + if (getBranch() && LLMenuGL::getKeyboardMode() && !getBranch()->getHighlightedItem()) { - mBranch->highlightNextItem(NULL); + getBranch()->highlightNextItem(NULL); } } BOOL LLMenuItemBranchGL::handleKey(KEY key, MASK mask, BOOL called_from_parent) { BOOL handled = FALSE; - if (called_from_parent) + if (called_from_parent && getBranch()) { - handled = mBranch->handleKey(key, mask, called_from_parent); + handled = getBranch()->handleKey(key, mask, called_from_parent); } if (!handled) @@ -1148,9 +1172,9 @@ BOOL LLMenuItemBranchGL::handleKey(KEY key, MASK mask, BOOL called_from_parent) BOOL LLMenuItemBranchGL::handleUnicodeChar(llwchar uni_char, BOOL called_from_parent) { BOOL handled = FALSE; - if (called_from_parent) + if (called_from_parent && getBranch()) { - handled = mBranch->handleUnicodeChar(uni_char, TRUE); + handled = getBranch()->handleUnicodeChar(uni_char, TRUE); } if (!handled) @@ -1166,14 +1190,19 @@ void LLMenuItemBranchGL::setHighlight( BOOL highlight ) { if (highlight == getHighlight()) return; - BOOL auto_open = getEnabled() && (!mBranch->getVisible() || mBranch->getTornOff()); + if(!getBranch()) + { + return; + } + + BOOL auto_open = getEnabled() && (!getBranch()->getVisible() || getBranch()->getTornOff()); // torn off menus don't open sub menus on hover unless they have focus if (getMenu()->getTornOff() && !((LLFloater*)getMenu()->getParent())->hasFocus()) { auto_open = FALSE; } // don't auto open torn off sub-menus (need to explicitly active menu item to give them focus) - if (mBranch->getTornOff()) + if (getBranch()->getTornOff()) { auto_open = FALSE; } @@ -1187,14 +1216,14 @@ void LLMenuItemBranchGL::setHighlight( BOOL highlight ) } else { - if (mBranch->getTornOff()) + if (getBranch()->getTornOff()) { - ((LLFloater*)mBranch->getParent())->setFocus(FALSE); - mBranch->clearHoverItem(); + ((LLFloater*)getBranch()->getParent())->setFocus(FALSE); + getBranch()->clearHoverItem(); } else { - mBranch->setVisible( FALSE ); + getBranch()->setVisible( FALSE ); } } } @@ -1202,7 +1231,7 @@ void LLMenuItemBranchGL::setHighlight( BOOL highlight ) void LLMenuItemBranchGL::draw() { LLMenuItemGL::draw(); - if (mBranch->getVisible() && !mBranch->getTornOff()) + if (getBranch() && getBranch()->getVisible() && !getBranch()->getTornOff()) { setHighlight(TRUE); } @@ -1210,33 +1239,33 @@ void LLMenuItemBranchGL::draw() void LLMenuItemBranchGL::updateBranchParent(LLView* parentp) { - if (mBranch->getParent() == NULL) + if (getBranch() && getBranch()->getParent() == NULL) { // make the branch menu a sibling of my parent menu - mBranch->updateParent(parentp); + getBranch()->updateParent(parentp); } } void LLMenuItemBranchGL::onVisibilityChange( BOOL new_visibility ) { - if (new_visibility == FALSE && !mBranch->getTornOff()) + if (new_visibility == FALSE && getBranch() && !getBranch()->getTornOff()) { - mBranch->setVisible(FALSE); + getBranch()->setVisible(FALSE); } LLMenuItemGL::onVisibilityChange(new_visibility); } BOOL LLMenuItemBranchGL::handleKeyHere( KEY key, MASK mask ) { - if (getMenu()->getVisible() && mBranch->getVisible() && key == KEY_LEFT) + if (getMenu()->getVisible() && getBranch() && getBranch()->getVisible() && key == KEY_LEFT) { // switch to keyboard navigation mode LLMenuGL::setKeyboardMode(TRUE); - BOOL handled = mBranch->clearHoverItem(); - if (mBranch->getTornOff()) + BOOL handled = getBranch()->clearHoverItem(); + if (getBranch()->getTornOff()) { - ((LLFloater*)mBranch->getParent())->setFocus(FALSE); + ((LLFloater*)getBranch()->getParent())->setFocus(FALSE); } if (handled && getMenu()->getTornOff()) { @@ -1247,12 +1276,12 @@ BOOL LLMenuItemBranchGL::handleKeyHere( KEY key, MASK mask ) if (getHighlight() && getMenu()->isOpen() && - key == KEY_RIGHT && !mBranch->getHighlightedItem()) + key == KEY_RIGHT && getBranch() && !getBranch()->getHighlightedItem()) { // switch to keyboard navigation mode LLMenuGL::setKeyboardMode(TRUE); - LLMenuItemGL* itemp = mBranch->highlightNextItem(NULL); + LLMenuItemGL* itemp = getBranch()->highlightNextItem(NULL); if (itemp) { return TRUE; @@ -1264,37 +1293,39 @@ BOOL LLMenuItemBranchGL::handleKeyHere( KEY key, MASK mask ) void LLMenuItemBranchGL::openMenu() { - if (mBranch->getTornOff()) + if(!getBranch()) return; + + if (getBranch()->getTornOff()) { - gFloaterView->bringToFront((LLFloater*)mBranch->getParent()); + gFloaterView->bringToFront((LLFloater*)getBranch()->getParent()); // this might not be necessary, as torn off branches don't get focus and hence no highligth - mBranch->highlightNextItem(NULL); + getBranch()->highlightNextItem(NULL); } - else if( !mBranch->getVisible() ) + else if( !getBranch()->getVisible() ) { // get valid rectangle for menus const LLRect menu_region_rect = LLMenuGL::sMenuContainer->getMenuRect(); - mBranch->arrange(); + getBranch()->arrange(); - LLRect rect = mBranch->getRect(); + LLRect rect = getBranch()->getRect(); // calculate root-view relative position for branch menu S32 left = getRect().mRight; S32 top = getRect().mTop - getRect().mBottom; - localPointToOtherView(left, top, &left, &top, mBranch->getParent()); + localPointToOtherView(left, top, &left, &top, getBranch()->getParent()); rect.setLeftTopAndSize( left, top, rect.getWidth(), rect.getHeight() ); - if (mBranch->getCanTearOff()) + if (getBranch()->getCanTearOff()) { rect.translate(0, TEAROFF_SEPARATOR_HEIGHT_PIXELS); } - mBranch->setRect( rect ); + getBranch()->setRect( rect ); S32 x = 0; S32 y = 0; - mBranch->localPointToOtherView( 0, 0, &x, &y, mBranch->getParent() ); + getBranch()->localPointToOtherView( 0, 0, &x, &y, getBranch()->getParent() ); S32 delta_x = 0; S32 delta_y = 0; if( y < menu_region_rect.mBottom ) @@ -1308,9 +1339,9 @@ void LLMenuItemBranchGL::openMenu() // move sub-menu over to left side delta_x = llmax(-x, (-1 * (rect.getWidth() + getRect().getWidth()))); } - mBranch->translate( delta_x, delta_y ); - mBranch->setVisible( TRUE ); - mBranch->getParent()->sendChildToFront(mBranch); + getBranch()->translate( delta_x, delta_y ); + getBranch()->setVisible( TRUE ); + getBranch()->getParent()->sendChildToFront(getBranch()); } } @@ -1327,7 +1358,7 @@ class LLMenuItemBranchDownGL : public LLMenuItemBranchGL protected: public: - LLMenuItemBranchDownGL( const std::string& name, const std::string& label, LLMenuGL* branch, + LLMenuItemBranchDownGL( const std::string& name, const std::string& label, LLHandle branch, KEY key = KEY_NONE, MASK mask = MASK_NONE ); virtual std::string getType() const { return "menu"; } @@ -1360,7 +1391,7 @@ public: LLMenuItemBranchDownGL::LLMenuItemBranchDownGL( const std::string& name, const std::string& label, - LLMenuGL* branch, + LLHandle branch, KEY key, MASK mask ) : LLMenuItemBranchGL( name, label, branch, key, mask ) { @@ -2258,7 +2289,7 @@ void LLMenuGL::createSpilloverBranch() mSpilloverMenu->setBackgroundColor( mBackgroundColor ); mSpilloverMenu->setCanTearOff(FALSE); - mSpilloverBranch = new LLMenuItemBranchGL(std::string("More"), std::string("More"), mSpilloverMenu); + mSpilloverBranch = new LLMenuItemBranchGL(std::string("More"), std::string("More"), mSpilloverMenu->getHandle()); mSpilloverBranch->setFontStyle(LLFontGL::ITALIC); } } @@ -2278,9 +2309,6 @@ void LLMenuGL::cleanupSpilloverBranch() mItems.erase(found_iter); } - delete mSpilloverBranch; - mSpilloverBranch = NULL; - // pop off spillover items while (mSpilloverMenu->getItemCount()) { @@ -2291,6 +2319,12 @@ void LLMenuGL::cleanupSpilloverBranch() mItems.push_back(itemp); addChild(itemp); } + + // Delete the branch, and since the branch will delete the menu, + // set the menu* to null. + delete mSpilloverBranch; + mSpilloverBranch = NULL; + mSpilloverMenu = NULL; } } @@ -2463,7 +2497,7 @@ BOOL LLMenuGL::appendMenu( LLMenuGL* menu ) BOOL success = TRUE; LLMenuItemBranchGL* branch = NULL; - branch = new LLMenuItemBranchGL( menu->getName(), menu->getLabel(), menu ); + branch = new LLMenuItemBranchGL( menu->getName(), menu->getLabel(), menu->getHandle() ); branch->setJumpKey(menu->getJumpKey()); success &= append( branch ); @@ -4072,7 +4106,7 @@ BOOL LLMenuBarGL::appendMenu( LLMenuGL* menu ) BOOL success = TRUE; LLMenuItemBranchGL* branch = NULL; - branch = new LLMenuItemBranchDownGL( menu->getName(), menu->getLabel(), menu ); + branch = new LLMenuItemBranchDownGL( menu->getName(), menu->getLabel(), menu->getHandle()); success &= branch->addToAcceleratorList(&mAccelerators); success &= append( branch ); branch->setJumpKey(branch->getJumpKey()); diff --git a/indra/llui/llmenugl.h b/indra/llui/llmenugl.h index 30398fb8f8..a2ef968bcd 100644 --- a/indra/llui/llmenugl.h +++ b/indra/llui/llmenugl.h @@ -90,6 +90,7 @@ public: static const LLColor4& getHighlightFGColor() { return sHighlightForeground; } LLMenuItemGL( const std::string& name, const std::string& label, KEY key = KEY_NONE, MASK = MASK_NONE ); + virtual ~LLMenuItemGL() {}; virtual void setValue(const LLSD& value) { setLabel(value.asString()); } @@ -562,8 +563,11 @@ private: class LLMenuItemBranchGL : public LLMenuItemGL { public: - LLMenuItemBranchGL( const std::string& name, const std::string& label, LLMenuGL* branch, + LLMenuItemBranchGL( const std::string& name, const std::string& label, LLHandle branch, KEY key = KEY_NONE, MASK mask = MASK_NONE ); + + virtual ~LLMenuItemBranchGL(); + virtual LLXMLNodePtr getXML(bool save_children = true) const; virtual std::string getType() const { return "menu"; } @@ -590,11 +594,11 @@ public: virtual BOOL handleKeyHere(KEY key, MASK mask); - virtual BOOL isActive() const { return isOpen() && mBranch->getHighlightedItem(); } + virtual BOOL isActive() const { return isOpen() && getBranch()->getHighlightedItem(); } - virtual BOOL isOpen() const { return mBranch->isOpen(); } + virtual BOOL isOpen() const { return getBranch() && getBranch()->isOpen(); } - LLMenuGL *getBranch() const { return mBranch; } + LLMenuGL *getBranch() const { return (LLMenuGL*)(mBranch.get()); } virtual void updateBranchParent( LLView* parentp ); @@ -603,14 +607,14 @@ public: virtual void draw(); - virtual void setEnabledSubMenus(BOOL enabled) { mBranch->setEnabledSubMenus(enabled); } + virtual void setEnabledSubMenus(BOOL enabled) { if(getBranch()) getBranch()->setEnabledSubMenus(enabled); } virtual void openMenu(); virtual LLView* getChildView(const std::string& name, BOOL recurse = TRUE, BOOL create_if_missing = TRUE) const; private: - LLMenuGL* mBranch; + LLHandle mBranch; }; // end class LLMenuItemBranchGL diff --git a/indra/mac_crash_logger/llcrashloggermac.cpp b/indra/mac_crash_logger/llcrashloggermac.cpp index f3a00e07dc..16efa4fe2c 100644 --- a/indra/mac_crash_logger/llcrashloggermac.cpp +++ b/indra/mac_crash_logger/llcrashloggermac.cpp @@ -134,6 +134,8 @@ OSStatus dialogHandler(EventHandlerCallRef handler, EventRef event, void *userda QuitAppModalLoopForWindow(gWindow); result = noErr; break; + default: + result = eventNotHandledErr; } } } diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 0be8b53d41..750771f6ce 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -1298,6 +1298,7 @@ if (FMOD) PROPERTIES BUILD_WITH_INSTALL_RPATH 1 INSTALL_NAME_DIR "@executable_path/../Resources" + LINK_FLAGS "-unexported_symbols_list ../newview/fmod_hidden_symbols.exp" ) endif (DARWIN) set(FMODWRAPPER_LIBRARY fmodwrapper) diff --git a/indra/newview/installers/windows/lang_zh.nsi b/indra/newview/installers/windows/lang_zh.nsi index f4b7b5d143..d17e860df9 100644 Binary files a/indra/newview/installers/windows/lang_zh.nsi and b/indra/newview/installers/windows/lang_zh.nsi differ diff --git a/indra/newview/installers/windows/language_menu.nsi b/indra/newview/installers/windows/language_menu.nsi index 473f9e0784..988f452dea 100644 Binary files a/indra/newview/installers/windows/language_menu.nsi and b/indra/newview/installers/windows/language_menu.nsi differ diff --git a/indra/newview/llappviewermacosx.cpp b/indra/newview/llappviewermacosx.cpp index 67aeef8b12..3cdcb35197 100644 --- a/indra/newview/llappviewermacosx.cpp +++ b/indra/newview/llappviewermacosx.cpp @@ -58,6 +58,17 @@ namespace // They are not used immediately by the app. int gArgC; char** gArgV; + + bool sCrashReporterIsRunning = false; + + OSErr AEQuitHandler(const AppleEvent *messagein, AppleEvent *reply, long refIn) + { + OSErr result = noErr; + + LLAppViewer::instance()->userQuit(); + + return(result); + } } int main( int argc, char **argv ) @@ -259,8 +270,37 @@ void LLAppViewerMacOSX::handleSyncCrashTrace() // do nothing } +static OSStatus CarbonEventHandler(EventHandlerCallRef inHandlerCallRef, + EventRef inEvent, + void* inUserData) +{ + ProcessSerialNumber psn; + + GetEventParameter(inEvent, + kEventParamProcessID, + typeProcessSerialNumber, + NULL, + sizeof(psn), + NULL, + &psn); + + if( GetEventKind(inEvent) == kEventAppTerminated ) + { + Boolean matching_psn = FALSE; + OSErr os_result = SameProcess(&psn, (ProcessSerialNumber*)inUserData, &matching_psn); + if(os_result >= 0 && matching_psn) + { + sCrashReporterIsRunning = false; + } + } + return noErr; +} + void LLAppViewerMacOSX::handleCrashReporting(bool reportFreeze) { + // This used to use fork&exec, but is switched to LSOpenApplication to + // Make sure the crash reporter launches in front of the SL window. + std::string command_str; //command_str = "open Second Life.app/Contents/Resources/mac-crash-logger.app"; command_str = "mac-crash-logger.app/Contents/MacOS/mac-crash-logger"; @@ -282,15 +322,69 @@ void LLAppViewerMacOSX::handleCrashReporting(bool reportFreeze) { // Make sure freeze reporting launches the crash logger synchronously, lest // Log files get changed by SL while the logger is running. + + // *NOTE:Mani A better way - make a copy of the data that the crash reporter will send + // and let SL go about its business. This way makes the mac work like windows and linux + // and is the smallest patch for the issue. + sCrashReporterIsRunning = true; + ProcessSerialNumber o_psn; + + static EventHandlerRef sCarbonEventsRef = NULL; + static const EventTypeSpec kEvents[] = + { + { kEventClassApplication, kEventAppTerminated } + }; + + // Install the handler to detect crash logger termination + InstallEventHandler(GetApplicationEventTarget(), + (EventHandlerUPP) CarbonEventHandler, + GetEventTypeCount(kEvents), + kEvents, + &o_psn, + &sCarbonEventsRef + ); + + // Remove, temporarily the quit handler - which has *crash* behavior before + // the mainloop gets running! + AERemoveEventHandler(kCoreEventClass, + kAEQuitApplication, + NewAEEventHandlerUPP(AEQuitHandler), + false); + + // Launch the crash reporter. + os_result = LSOpenApplication(&appParams, &o_psn); + + if(os_result >= 0) + { + EventRecord evt; + while(sCrashReporterIsRunning) + { + while(WaitNextEvent(osMask, &evt, 0, NULL)) + { + // null op!?! + } + } + } + + // Re-install the apps quit handler. + AEInstallEventHandler(kCoreEventClass, + kAEQuitApplication, + NewAEEventHandlerUPP(AEQuitHandler), + 0, + false); + + // Remove the crash reporter quit handler. + RemoveEventHandler(sCarbonEventsRef); } else { appParams.flags |= kLSLaunchAsync; clear_signals(); + + ProcessSerialNumber o_psn; + os_result = LSOpenApplication(&appParams, &o_psn); } - ProcessSerialNumber o_psn; - os_result = LSOpenApplication(&appParams, &o_psn); } if(!reportFreeze) @@ -368,15 +462,6 @@ OSErr AEGURLHandler(const AppleEvent *messagein, AppleEvent *reply, long refIn) return(result); } -OSErr AEQuitHandler(const AppleEvent *messagein, AppleEvent *reply, long refIn) -{ - OSErr result = noErr; - - LLAppViewer::instance()->userQuit(); - - return(result); -} - OSStatus simpleDialogHandler(EventHandlerCallRef handler, EventRef event, void *userdata) { OSStatus result = eventNotHandledErr; diff --git a/indra/newview/lldrawpoolbump.cpp b/indra/newview/lldrawpoolbump.cpp index 6d6e4b0617..b23819be27 100644 --- a/indra/newview/lldrawpoolbump.cpp +++ b/indra/newview/lldrawpoolbump.cpp @@ -74,7 +74,6 @@ const U32 VERTEX_MASK_SHINY = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_N const U32 VERTEX_MASK_BUMP = LLVertexBuffer::MAP_VERTEX |LLVertexBuffer::MAP_TEXCOORD | LLVertexBuffer::MAP_TEXCOORD2; U32 LLDrawPoolBump::sVertexMask = VERTEX_MASK_SHINY; -static LLPointer sCubeMap; static LLGLSLShader* shader = NULL; static S32 cube_channel = -1; @@ -389,8 +388,6 @@ void LLDrawPoolBump::renderShiny(bool invisible) return; } - sCubeMap = NULL; - if( gSky.mVOSkyp->getCubeMap() ) { LLGLEnable blend_enable(GL_BLEND); @@ -514,8 +511,6 @@ void LLDrawPoolBump::renderFullbrightShiny() return; } - sCubeMap = NULL; - if( gSky.mVOSkyp->getCubeMap() ) { LLGLEnable blend_enable(GL_BLEND); diff --git a/indra/newview/lldynamictexture.cpp b/indra/newview/lldynamictexture.cpp index b03306fa90..6951f3a96a 100644 --- a/indra/newview/lldynamictexture.cpp +++ b/indra/newview/lldynamictexture.cpp @@ -113,7 +113,7 @@ void LLDynamicTexture::generateGLTexture(LLGLint internal_format, LLGLenum prima // llinfos << "ALLOCATING " << (mWidth*mHeight*mComponents)/1024 << "K" << llendl; mTexture->createGLTexture(0, raw_image); mTexture->setClamp(mClamp, mClamp); - mTexture->setInitialized(false); + mTexture->setGLTextureCreated(false); } //----------------------------------------------------------------------------- @@ -198,6 +198,7 @@ BOOL LLDynamicTexture::updateAllInstances() } BOOL result = FALSE; + BOOL ret = FALSE ; for( S32 order = 0; order < ORDER_COUNT; order++ ) { for (instance_list_t::iterator iter = LLDynamicTexture::sInstances[order].begin(); @@ -212,9 +213,10 @@ BOOL LLDynamicTexture::updateAllInstances() gGL.color4f(1,1,1,1); dynamicTexture->preRender(); // Must be called outside of startRender() - + result = FALSE; if (dynamicTexture->render()) { + ret = TRUE ; result = TRUE; sNumRenders++; } @@ -226,7 +228,19 @@ BOOL LLDynamicTexture::updateAllInstances() } } - return result; + return ret; +} + +//virtual +void LLDynamicTexture::restoreGLTexture() +{ + generateGLTexture() ; +} + +//virtual +void LLDynamicTexture::destroyGLTexture() +{ + releaseGLTexture() ; } //----------------------------------------------------------------------------- @@ -235,6 +249,15 @@ BOOL LLDynamicTexture::updateAllInstances() //----------------------------------------------------------------------------- void LLDynamicTexture::destroyGL() { + for( S32 order = 0; order < ORDER_COUNT; order++ ) + { + for (instance_list_t::iterator iter = LLDynamicTexture::sInstances[order].begin(); + iter != LLDynamicTexture::sInstances[order].end(); ++iter) + { + LLDynamicTexture *dynamicTexture = *iter; + dynamicTexture->destroyGLTexture() ; + } + } } //----------------------------------------------------------------------------- @@ -243,4 +266,18 @@ void LLDynamicTexture::destroyGL() //----------------------------------------------------------------------------- void LLDynamicTexture::restoreGL() { + if (gGLManager.mIsDisabled) + { + return ; + } + + for( S32 order = 0; order < ORDER_COUNT; order++ ) + { + for (instance_list_t::iterator iter = LLDynamicTexture::sInstances[order].begin(); + iter != LLDynamicTexture::sInstances[order].end(); ++iter) + { + LLDynamicTexture *dynamicTexture = *iter; + dynamicTexture->restoreGLTexture() ; + } + } } diff --git a/indra/newview/lldynamictexture.h b/indra/newview/lldynamictexture.h index fbfabf49a4..5a20eaef9b 100644 --- a/indra/newview/lldynamictexture.h +++ b/indra/newview/lldynamictexture.h @@ -61,6 +61,9 @@ public: virtual BOOL render(); virtual void postRender(BOOL success); + virtual void restoreGLTexture() ; + virtual void destroyGLTexture() ; + LLImageGL* getTexture(void) const { return mTexture; } static BOOL updateAllInstances(); diff --git a/indra/newview/llfloaterimagepreview.cpp b/indra/newview/llfloaterimagepreview.cpp index 283877751f..67be553ae7 100644 --- a/indra/newview/llfloaterimagepreview.cpp +++ b/indra/newview/llfloaterimagepreview.cpp @@ -76,7 +76,7 @@ LLFloaterImagePreview::LLFloaterImagePreview(const std::string& filename) : { mLastMouseX = 0; mLastMouseY = 0; - mGLName = 0; + mImagep = NULL ; loadImage(mFilenameAndPath); } @@ -139,10 +139,7 @@ LLFloaterImagePreview::~LLFloaterImagePreview() delete mAvatarPreview; delete mSculptedPreview; - if (mGLName) - { - glDeleteTextures(1, &mGLName ); - } + mImagep = NULL ; } //static @@ -225,28 +222,16 @@ void LLFloaterImagePreview::draw() gl_rect_2d_checkerboard(mPreviewRect); LLGLDisable gls_alpha(GL_ALPHA_TEST); - GLenum format_options[4] = { GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_RGB, GL_RGBA }; - GLenum format = format_options[mRawImagep->getComponents()-1]; - - GLenum internal_format_options[4] = { GL_LUMINANCE8, GL_LUMINANCE8_ALPHA8, GL_RGB8, GL_RGBA8 }; - GLenum internal_format = internal_format_options[mRawImagep->getComponents()-1]; - - if (mGLName) + if(mImagep.notNull()) { - gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mGLName); + gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mImagep->getTexName()); } else { - glGenTextures(1, &mGLName ); - stop_glerror(); - - gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mGLName); - stop_glerror(); - - glTexImage2D( - GL_TEXTURE_2D, 0, internal_format, - mRawImagep->getWidth(), mRawImagep->getHeight(), - 0, format, GL_UNSIGNED_BYTE, mRawImagep->getData()); + mImagep = new LLImageGL(mRawImagep, FALSE) ; + + gGL.getTexUnit(0)->unbind(mImagep->getTarget()) ; + gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mImagep->getTexName()); stop_glerror(); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); @@ -255,8 +240,8 @@ void LLFloaterImagePreview::draw() gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); if (mAvatarPreview) { - mAvatarPreview->setTexture(mGLName); - mSculptedPreview->setTexture(mGLName); + mAvatarPreview->setTexture(mImagep->getTexName()); + mSculptedPreview->setTexture(mImagep->getTexName()); } } diff --git a/indra/newview/llfloaterimagepreview.h b/indra/newview/llfloaterimagepreview.h index c061a85d94..e639544f48 100644 --- a/indra/newview/llfloaterimagepreview.h +++ b/indra/newview/llfloaterimagepreview.h @@ -130,7 +130,7 @@ protected: S32 mLastMouseY; LLRect mPreviewRect; LLRectf mPreviewImageRect; - GLuint mGLName; + LLPointer mImagep ; static S32 sUploadAmount; }; diff --git a/indra/newview/llhudicon.cpp b/indra/newview/llhudicon.cpp index a6d57e98e3..8c6b906ccd 100644 --- a/indra/newview/llhudicon.cpp +++ b/indra/newview/llhudicon.cpp @@ -211,6 +211,80 @@ void LLHUDIcon::renderForSelect() renderIcon(TRUE); } +BOOL LLHUDIcon::lineSegmentIntersect(const LLVector3& start, const LLVector3& end, LLVector3* intersection) +{ + if (mHidden) + return FALSE; + + if (mSourceObject.isNull() || mImagep.isNull()) + { + markDead(); + return FALSE; + } + + LLVector3 obj_position = mSourceObject->getRenderPosition(); + + // put icon above object, and in front + // RN: don't use drawable radius, it's fricking HUGE + LLVector3 icon_relative_pos = (LLViewerCamera::getInstance()->getUpAxis() * ~mSourceObject->getRenderRotation()); + icon_relative_pos.abs(); + + F32 distance_scale = llmin(mSourceObject->getScale().mV[VX] / icon_relative_pos.mV[VX], + mSourceObject->getScale().mV[VY] / icon_relative_pos.mV[VY], + mSourceObject->getScale().mV[VZ] / icon_relative_pos.mV[VZ]); + F32 up_distance = 0.5f * distance_scale; + LLVector3 icon_position = obj_position + (up_distance * LLViewerCamera::getInstance()->getUpAxis()) * 1.2f; + + LLVector3 icon_to_cam = LLViewerCamera::getInstance()->getOrigin() - icon_position; + icon_to_cam.normVec(); + + icon_position += icon_to_cam * mSourceObject->mDrawable->getRadius() * 1.1f; + + mDistance = dist_vec(icon_position, LLViewerCamera::getInstance()->getOrigin()); + + LLVector3 x_pixel_vec; + LLVector3 y_pixel_vec; + + LLViewerCamera::getInstance()->getPixelVectors(icon_position, y_pixel_vec, x_pixel_vec); + + F32 scale_factor = 1.f; + if (mAnimTimer.getElapsedTimeF32() < ANIM_TIME) + { + scale_factor = llmax(0.f, calc_bouncy_animation(mAnimTimer.getElapsedTimeF32() / ANIM_TIME)); + } + + F32 time_elapsed = mLifeTimer.getElapsedTimeF32(); + if (time_elapsed > MAX_VISIBLE_TIME) + { + markDead(); + return FALSE; + } + + F32 image_aspect = (F32)mImagep->mFullWidth / (F32)mImagep->mFullHeight; + LLVector3 x_scale = image_aspect * (F32)gViewerWindow->getWindowHeight() * mScale * scale_factor * x_pixel_vec; + LLVector3 y_scale = (F32)gViewerWindow->getWindowHeight() * mScale * scale_factor * y_pixel_vec; + + LLVector3 lower_left = icon_position - (x_scale * 0.5f); + LLVector3 lower_right = icon_position + (x_scale * 0.5f); + LLVector3 upper_left = icon_position - (x_scale * 0.5f) + y_scale; + LLVector3 upper_right = icon_position + (x_scale * 0.5f) + y_scale; + + + F32 t = 0.f; + LLVector3 dir = end-start; + + if (LLTriangleRayIntersect(upper_right, upper_left, lower_right, start, dir, NULL, NULL, &t, FALSE) || + LLTriangleRayIntersect(lower_left, lower_right, upper_left, start, dir, NULL, NULL, &t, FALSE)) + { + if (intersection) + { + *intersection = start + dir*t; + } + return TRUE; + } + + return FALSE; +} //static S32 LLHUDIcon::generatePickIDs(S32 start_id, S32 step_size) @@ -243,6 +317,33 @@ LLHUDIcon* LLHUDIcon::handlePick(S32 pick_id) return NULL; } +//static +LLHUDIcon* LLHUDIcon::lineSegmentIntersectAll(const LLVector3& start, const LLVector3& end, LLVector3* intersection) +{ + icon_instance_t::iterator icon_it; + + LLVector3 local_end = end; + LLVector3 position; + + LLHUDIcon* ret = NULL; + for(icon_it = sIconInstances.begin(); icon_it != sIconInstances.end(); ++icon_it) + { + LLHUDIcon* icon = *icon_it; + if (icon->lineSegmentIntersect(start, local_end, &position)) + { + ret = icon; + if (intersection) + { + *intersection = position; + } + local_end = position; + } + } + + return ret; +} + + //static void LLHUDIcon::updateAll() { diff --git a/indra/newview/llhudicon.h b/indra/newview/llhudicon.h index ffc2985f88..154e6df518 100644 --- a/indra/newview/llhudicon.h +++ b/indra/newview/llhudicon.h @@ -68,6 +68,7 @@ public: static S32 generatePickIDs(S32 start_id, S32 step_size); static LLHUDIcon* handlePick(S32 pick_id); + static LLHUDIcon* lineSegmentIntersectAll(const LLVector3& start, const LLVector3& end, LLVector3* intersection); static void updateAll(); static void cleanupDeadIcons(); @@ -78,6 +79,8 @@ public: BOOL getHidden() const { return mHidden; } void setHidden( BOOL hide ) { mHidden = hide; } + BOOL lineSegmentIntersect(const LLVector3& start, const LLVector3& end, LLVector3* intersection); + protected: LLHUDIcon(const U8 type); ~LLHUDIcon(); diff --git a/indra/newview/llmaniptranslate.cpp b/indra/newview/llmaniptranslate.cpp index 8c0c5fdab1..b9a700991e 100644 --- a/indra/newview/llmaniptranslate.cpp +++ b/indra/newview/llmaniptranslate.cpp @@ -78,7 +78,7 @@ const F32 PLANE_TICK_SIZE = 0.4f; const F32 MANIPULATOR_SCALE_HALF_LIFE = 0.07f; const F32 SNAP_ARROW_SCALE = 0.7f; -static GLuint sGridTex = 0; +static LLPointer sGridTex = NULL ; const LLManip::EManipPart MANIPULATOR_IDS[9] = { @@ -120,12 +120,32 @@ LLManipTranslate::LLManipTranslate( LLToolComposite* composite ) mPlaneScales(1.f, 1.f, 1.f), mPlaneManipPositions(1.f, 1.f, 1.f, 1.f) { - if (sGridTex == 0) + if (sGridTex.isNull()) { restoreGL(); } } +//static +U32 LLManipTranslate::getGridTexName() +{ + if(sGridTex.isNull()) + { + restoreGL() ; + } + + return sGridTex.isNull() ? 0 : sGridTex->getTexName() ; +} + +//static +void LLManipTranslate::destroyGL() +{ + if (sGridTex) + { + sGridTex = NULL ; + } +} + //static void LLManipTranslate::restoreGL() { @@ -133,9 +153,17 @@ void LLManipTranslate::restoreGL() U32 rez = 512; U32 mip = 0; - GLuint* d = new GLuint[rez*rez]; - glGenTextures(1, &sGridTex); - gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, sGridTex); + destroyGL() ; + sGridTex = new LLImageGL() ; + if(!sGridTex->createGLTexture()) + { + sGridTex = NULL ; + return ; + } + + GLuint* d = new GLuint[rez*rez]; + + gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, sGridTex->getTexName()); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); @@ -1504,7 +1532,7 @@ void LLManipTranslate::renderSnapGuides() LLGLDisable stencil(GL_STENCIL_TEST); { LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE, GL_GREATER); - gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, sGridTex); + gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, getGridTexName()); gGL.flush(); gGL.blendFunc(LLRender::BF_ZERO, LLRender::BF_ONE_MINUS_SOURCE_ALPHA); renderGrid(u,v,tiles,0.9f, 0.9f, 0.9f,a*0.15f); @@ -1519,7 +1547,7 @@ void LLManipTranslate::renderSnapGuides() renderGrid(u,v,tiles,0.0f, 0.0f, 0.0f,a*0.16f); //draw grid top - gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, sGridTex); + gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, getGridTexName()); renderGrid(u,v,tiles,1,1,1,a); gGL.popMatrix(); diff --git a/indra/newview/llmaniptranslate.h b/indra/newview/llmaniptranslate.h index cc9053ec65..25ff35cc72 100644 --- a/indra/newview/llmaniptranslate.h +++ b/indra/newview/llmaniptranslate.h @@ -56,6 +56,8 @@ public: LLManipTranslate( LLToolComposite* composite ); virtual ~LLManipTranslate(); + static U32 getGridTexName() ; + static void destroyGL(); static void restoreGL(); virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask); virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask); diff --git a/indra/newview/lltexlayer.cpp b/indra/newview/lltexlayer.cpp index baff4a2d3f..709fcd166b 100644 --- a/indra/newview/lltexlayer.cpp +++ b/indra/newview/lltexlayer.cpp @@ -94,17 +94,59 @@ LLTexLayerSetBuffer::LLTexLayerSetBuffer( LLTexLayerSet* owner, S32 width, S32 h mNeedsUpdate( TRUE ), mNeedsUpload( FALSE ), mUploadPending( FALSE ), // Not used for any logic here, just to sync sending of updates - mTexLayerSet( owner ), - mBumpTexName(0) + mTexLayerSet( owner ) { LLTexLayerSetBuffer::sGLByteCount += getSize(); + mHasBump = has_bump ; + mBumpTex = NULL ; - if( has_bump ) + createBumpTexture() ; +} + +LLTexLayerSetBuffer::~LLTexLayerSetBuffer() +{ + LLTexLayerSetBuffer::sGLByteCount -= getSize(); + + if( mBumpTex.notNull()) + { + mBumpTex = NULL ; + LLImageGL::sGlobalTextureMemory -= mWidth * mHeight * 4; + LLTexLayerSetBuffer::sGLBumpByteCount -= mWidth * mHeight * 4; + } +} +//virtual +void LLTexLayerSetBuffer::restoreGLTexture() +{ + createBumpTexture() ; + LLDynamicTexture::restoreGLTexture() ; +} + +//virtual +void LLTexLayerSetBuffer::destroyGLTexture() +{ + if( mBumpTex.notNull() ) + { + mBumpTex = NULL ; + LLImageGL::sGlobalTextureMemory -= mWidth * mHeight * 4; + LLTexLayerSetBuffer::sGLBumpByteCount -= mWidth * mHeight * 4; + } + + LLDynamicTexture::destroyGLTexture() ; +} + +void LLTexLayerSetBuffer::createBumpTexture() +{ + if( mHasBump ) { LLGLSUIDefault gls_ui; - glGenTextures(1, (GLuint*) &mBumpTexName); + mBumpTex = new LLImageGL(FALSE) ; + if(!mBumpTex->createGLTexture()) + { + mBumpTex = NULL ; + return ; + } - gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mBumpTexName); + gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mBumpTex->getTexName()); stop_glerror(); gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); @@ -112,7 +154,7 @@ LLTexLayerSetBuffer::LLTexLayerSetBuffer( LLTexLayerSet* owner, S32 width, S32 h glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, mWidth, mHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); stop_glerror(); gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); @@ -122,21 +164,6 @@ LLTexLayerSetBuffer::LLTexLayerSetBuffer( LLTexLayerSet* owner, S32 width, S32 h } } -LLTexLayerSetBuffer::~LLTexLayerSetBuffer() -{ - LLTexLayerSetBuffer::sGLByteCount -= getSize(); - - if( mBumpTexName ) - { - glDeleteTextures(1, (GLuint*) &mBumpTexName); - stop_glerror(); - mBumpTexName = 0; - - LLImageGL::sGlobalTextureMemory -= mWidth * mHeight * 4; - LLTexLayerSetBuffer::sGLBumpByteCount -= mWidth * mHeight * 4; - } -} - // static void LLTexLayerSetBuffer::dumpTotalByteCount() { @@ -245,7 +272,7 @@ BOOL LLTexLayerSetBuffer::render() BOOL success = TRUE; // Composite bump - if( mBumpTexName ) + if( mBumpTex.notNull() ) { // Composite the bump data success &= mTexLayerSet->renderBump( mOrigin.mX, mOrigin.mY, mWidth, mHeight ); @@ -256,7 +283,7 @@ BOOL LLTexLayerSetBuffer::render() LLGLSUIDefault gls_ui; // read back into texture (this is done externally for the color data) - gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mBumpTexName); + gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mBumpTex->getTexName()); stop_glerror(); glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, mOrigin.mX, mOrigin.mY, mWidth, mHeight); @@ -296,7 +323,7 @@ BOOL LLTexLayerSetBuffer::render() gGL.setSceneBlendType(LLRender::BT_ALPHA); // we have valid texture data now - mTexture->setInitialized(true); + mTexture->setGLTextureCreated(true); mNeedsUpdate = FALSE; return success; @@ -304,7 +331,7 @@ BOOL LLTexLayerSetBuffer::render() bool LLTexLayerSetBuffer::isInitialized(void) const { - return mTexture->isInitialized(); + return mTexture.notNull() && mTexture->isGLTextureCreated(); } BOOL LLTexLayerSetBuffer::updateImmediate() @@ -352,11 +379,11 @@ void LLTexLayerSetBuffer::readBackAndUpload(U8* baked_bump_data) // writes into baked_color_data const char* comment_text = NULL; - S32 baked_image_components = mBumpTexName ? 5 : 4; // red green blue [bump] clothing + S32 baked_image_components = mBumpTex.notNull() ? 5 : 4; // red green blue [bump] clothing LLPointer baked_image = new LLImageRaw( mWidth, mHeight, baked_image_components ); U8* baked_image_data = baked_image->getData(); - if( mBumpTexName ) + if( mBumpTex.notNull() ) { comment_text = LINDEN_J2C_COMMENT_PREFIX "RGBHM"; // 5 channels: rgb, heightfield/alpha, mask @@ -555,9 +582,9 @@ void LLTexLayerSetBuffer::onTextureUploadComplete(const LLUUID& uuid, void* user void LLTexLayerSetBuffer::bindBumpTexture( U32 stage ) { - if( mBumpTexName ) + if( mBumpTex.notNull() ) { - gGL.getTexUnit(stage)->bindManual(LLTexUnit::TT_TEXTURE, mBumpTexName); + gGL.getTexUnit(stage)->bindManual(LLTexUnit::TT_TEXTURE, mBumpTex->getTexName()); gGL.getTexUnit(0)->activate(); if( mLastBindTime != LLImageGL::sLastFrameTime ) diff --git a/indra/newview/lltexlayer.h b/indra/newview/lltexlayer.h index b838415d22..97b55a3d06 100644 --- a/indra/newview/lltexlayer.h +++ b/indra/newview/lltexlayer.h @@ -221,22 +221,28 @@ public: BOOL uploadPending() { return mUploadPending; } BOOL render( S32 x, S32 y, S32 width, S32 height ); void readBackAndUpload(U8* baked_bump_data); + void createBumpTexture() ; + static void onTextureUploadComplete( const LLUUID& uuid, void* userdata, S32 result, LLExtStat ext_status); static void dumpTotalByteCount(); + virtual void restoreGLTexture() ; + virtual void destroyGLTexture() ; + private: void pushProjection(); void popProjection(); private: + BOOL mHasBump ; BOOL mNeedsUpdate; BOOL mNeedsUpload; BOOL mUploadPending; LLUUID mUploadID; // Identifys the current upload process (null if none). Used to avoid overlaps (eg, when the user rapidly makes two changes outside of Face Edit) LLTexLayerSet* mTexLayerSet; - LLGLuint mBumpTexName; // zero if none + LLPointer mBumpTex; // zero if none static S32 sGLByteCount; static S32 sGLBumpByteCount; diff --git a/indra/newview/lltoolmorph.cpp b/indra/newview/lltoolmorph.cpp index 4ddb1ebd13..f15f0f44b0 100644 --- a/indra/newview/lltoolmorph.cpp +++ b/indra/newview/lltoolmorph.cpp @@ -241,7 +241,7 @@ BOOL LLVisualParamHint::render() } avatarp->setVisualParamWeight(mVisualParam, mLastParamWeight); gGL.color4f(1,1,1,1); - mTexture->setInitialized(true); + mTexture->setGLTextureCreated(true); return TRUE; } diff --git a/indra/newview/llviewerjointattachment.cpp b/indra/newview/llviewerjointattachment.cpp index a2ae7ea5c0..5bd8c93d6a 100644 --- a/indra/newview/llviewerjointattachment.cpp +++ b/indra/newview/llviewerjointattachment.cpp @@ -139,6 +139,8 @@ void LLViewerJointAttachment::setupDrawable(LLDrawable* drawablep) { childp->mDrawable->setState(LLDrawable::USE_BACKLIGHT); gPipeline.markTextured(childp->mDrawable); // face may need to change draw pool to/from POOL_HUD + gPipeline.markMoved(childp->mDrawable); + if(mIsHUDAttachment) { for (S32 face_num = 0; face_num < childp->mDrawable->getNumFaces(); face_num++) diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index bda07951a3..167b89fd02 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -182,6 +182,7 @@ #include "llspatialpartition.h" #include "llviewerjoystick.h" #include "llviewernetwork.h" +#include "llpostprocess.h" #include "llfloatertest.h" // HACK! #include "llfloaternotificationsconsole.h" @@ -3575,6 +3576,29 @@ LLPickInfo LLViewerWindow::pickImmediate(S32 x, S32 y_from_bot, BOOL pick_trans return mLastPick; } +LLHUDIcon* LLViewerWindow::cursorIntersectIcon(S32 mouse_x, S32 mouse_y, F32 depth, + LLVector3* intersection) +{ + S32 x = mouse_x; + S32 y = mouse_y; + + if ((mouse_x == -1) && (mouse_y == -1)) // use current mouse position + { + x = getCurrentMouseX(); + y = getCurrentMouseY(); + } + + // world coordinates of mouse + LLVector3 mouse_direction_global = mouseDirectionGlobal(x,y); + LLVector3 mouse_point_global = LLViewerCamera::getInstance()->getOrigin(); + LLVector3 mouse_world_start = mouse_point_global; + LLVector3 mouse_world_end = mouse_point_global + mouse_direction_global * depth; + + return LLHUDIcon::lineSegmentIntersectAll(mouse_world_start, mouse_world_end, intersection); + + +} + LLViewerObject* LLViewerWindow::cursorIntersect(S32 mouse_x, S32 mouse_y, F32 depth, LLViewerObject *this_object, S32 this_face, @@ -3684,7 +3708,7 @@ LLVector3 LLViewerWindow::mousePointHUD(const S32 x, const S32 y) const F32 hud_x = -((F32)x - (F32)width/2.f) / height; F32 hud_y = ((F32)y - (F32)height/2.f) / height; - return LLVector3(0.f, hud_x, hud_y); + return LLVector3(0.f, hud_x/gAgent.mHUDCurZoom, hud_y/gAgent.mHUDCurZoom); } // Returns unit vector relative to camera in camera space @@ -4552,6 +4576,10 @@ void LLViewerWindow::dumpState() void LLViewerWindow::stopGL(BOOL save_state) { + //Note: --bao + //if not necessary, do not change the order of the function calls in this function. + //if change something, make sure it will not break anything. + //especially be careful to put anything behind gImageList.destroyGL(save_state); if (!gGLManager.mIsDisabled) { llinfos << "Shutting down GL..." << llendl; @@ -4560,12 +4588,12 @@ void LLViewerWindow::stopGL(BOOL save_state) LLAppViewer::getTextureCache()->pause(); LLAppViewer::getImageDecodeThread()->pause(); LLAppViewer::getTextureFetch()->pause(); - + gSky.destroyGL(); - stop_glerror(); - - gImageList.destroyGL(save_state); - stop_glerror(); + stop_glerror(); + + LLManipTranslate::destroyGL() ; + stop_glerror(); gBumpImageList.destroyGL(); stop_glerror(); @@ -4589,6 +4617,14 @@ void LLViewerWindow::stopGL(BOOL save_state) gSphere.cleanupGL(); gCylinder.cleanupGL(); + if(gPostProcess) + { + gPostProcess->invalidate(); + } + + gImageList.destroyGL(save_state); + stop_glerror(); + gGLManager.mIsDisabled = TRUE; stop_glerror(); @@ -4598,25 +4634,32 @@ void LLViewerWindow::stopGL(BOOL save_state) void LLViewerWindow::restoreGL(const std::string& progress_message) { + //Note: --bao + //if not necessary, do not change the order of the function calls in this function. + //if change something, make sure it will not break anything. + //especially, be careful to put something before gImageList.restoreGL(); if (gGLManager.mIsDisabled) { llinfos << "Restoring GL..." << llendl; gGLManager.mIsDisabled = FALSE; + + initGLDefaults(); + LLGLState::restoreGL(); + gImageList.restoreGL(); // for future support of non-square pixels, and fonts that are properly stretched //LLFontGL::destroyDefaultFonts(); initFonts(); - initGLDefaults(); - LLGLState::restoreGL(); + gSky.restoreGL(); gPipeline.restoreGL(); LLDrawPoolWater::restoreGL(); LLManipTranslate::restoreGL(); - gImageList.restoreGL(); + gBumpImageList.restoreGL(); LLDynamicTexture::restoreGL(); LLVOAvatar::restoreGL(); - + gResizeScreenTexture = TRUE; if (gFloaterCustomize && gFloaterCustomize->getVisible()) @@ -4665,6 +4708,7 @@ void LLViewerWindow::toggleFullscreen(BOOL show_progress) if (mWindow) { mWantFullscreen = mWindow->getFullscreen() ? FALSE : TRUE; + mIsFullscreenChecked = mWindow->getFullscreen() ? FALSE : TRUE; mShowFullscreenProgress = show_progress; } } @@ -5175,6 +5219,13 @@ void LLPickInfo::fetchResults() LLVector3 intersection, normal, binormal; LLVector2 uv; + LLHUDIcon* hit_icon = gViewerWindow->cursorIntersectIcon(mMousePt.mX, mMousePt.mY, 512.f, &intersection); + + F32 icon_dist = 0.f; + if (hit_icon) + { + icon_dist = (LLViewerCamera::getInstance()->getOrigin()-intersection).magVec(); + } LLViewerObject* hit_object = gViewerWindow->cursorIntersect(mMousePt.mX, mMousePt.mY, 512.f, NULL, -1, mPickTransparent, &face_hit, &intersection, &uv, &normal, &binormal); @@ -5284,16 +5335,15 @@ void LLPickInfo::fetchResults() } } } - //else - //{ + if (hit_icon && + (!objectp || + icon_dist < (LLViewerCamera::getInstance()->getOrigin()-intersection).magVec())) + { // was this name referring to a hud icon? - // mHUDIcon = LLHUDIcon::handlePick(pick_id); - // if (mHUDIcon) - // { - // mPickType = PICK_ICON; - // mPosGlobal = mHUDIcon->getPositionGlobal(); - // } - //} + mHUDIcon = hit_icon; + mPickType = PICK_ICON; + mPosGlobal = mHUDIcon->getPositionGlobal(); + } if (mPickCallback) { diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h index d74c300a1e..a55913c566 100644 --- a/indra/newview/llviewerwindow.h +++ b/indra/newview/llviewerwindow.h @@ -312,6 +312,9 @@ public: LLPickInfo pickImmediate(S32 x, S32 y, BOOL pick_transparent); static void hoverPickCallback(const LLPickInfo& pick_info); + LLHUDIcon* cursorIntersectIcon(S32 mouse_x, S32 mouse_y, F32 depth, + LLVector3* intersection); + LLViewerObject* cursorIntersect(S32 mouse_x = -1, S32 mouse_y = -1, F32 depth = 512.f, LLViewerObject *this_object = NULL, S32 this_face = -1, diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index e5e858efba..597513ba0c 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -1070,6 +1070,22 @@ void LLVOAvatar::deleteLayerSetCaches() if( mLowerBodyLayerSet ) mLowerBodyLayerSet->deleteCaches(); if( mEyesLayerSet ) mEyesLayerSet->deleteCaches(); if( mSkirtLayerSet ) mSkirtLayerSet->deleteCaches(); + + if(mUpperMaskTexName) + { + glDeleteTextures(1, (GLuint*)&mUpperMaskTexName); + mUpperMaskTexName = 0 ; + } + if(mHeadMaskTexName) + { + glDeleteTextures(1, (GLuint*)&mHeadMaskTexName); + mHeadMaskTexName = 0 ; + } + if(mLowerMaskTexName) + { + glDeleteTextures(1, (GLuint*)&mLowerMaskTexName); + mLowerMaskTexName = 0 ; + } } // static diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 9d1c9c001b..a63b5c5fd1 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -4036,7 +4036,7 @@ LLViewerObject* LLPipeline::lineSegmentIntersectInWorld(const LLVector3& start, LLVector3 position; - sPickAvatar = LLToolMgr::getInstance()->inBuildMode() ? FALSE : TRUE; + sPickAvatar = FALSE; //LLToolMgr::getInstance()->inBuildMode() ? FALSE : TRUE; for (LLWorld::region_list_t::iterator iter = LLWorld::getInstance()->getRegionList().begin(); iter != LLWorld::getInstance()->getRegionList().end(); ++iter) @@ -4067,6 +4067,32 @@ LLViewerObject* LLPipeline::lineSegmentIntersectInWorld(const LLVector3& start, if (!sPickAvatar) { + //save hit info in case we need to restore + //due to attachment override + LLVector3 local_normal; + LLVector3 local_binormal; + LLVector2 local_texcoord; + S32 local_face_hit = -1; + + if (face_hit) + { + local_face_hit = *face_hit; + } + if (tex_coord) + { + local_texcoord = *tex_coord; + } + if (bi_normal) + { + local_binormal = *bi_normal; + } + if (normal) + { + local_normal = *normal; + } + + const F32 ATTACHMENT_OVERRIDE_DIST = 0.1f; + if (!drawable || !drawable->getVObj()->isAttachment()) { //check against avatars sPickAvatar = TRUE; @@ -4081,8 +4107,35 @@ LLViewerObject* LLPipeline::lineSegmentIntersectInWorld(const LLVector3& start, LLDrawable* hit = part->lineSegmentIntersect(start, local_end, pick_transparent, face_hit, &position, tex_coord, normal, bi_normal); if (hit) { - drawable = hit; - local_end = position; + if (!drawable || + !drawable->getVObj()->isAttachment() || + (position-local_end).magVec() > ATTACHMENT_OVERRIDE_DIST) + { //avatar overrides if previously hit drawable is not an attachment or + //attachment is far enough away from detected intersection + drawable = hit; + local_end = position; + } + else + { //prioritize attachments over avatars + position = local_end; + + if (face_hit) + { + *face_hit = local_face_hit; + } + if (tex_coord) + { + *tex_coord = local_texcoord; + } + if (bi_normal) + { + *bi_normal = local_binormal; + } + if (normal) + { + *normal = local_normal; + } + } } } } diff --git a/indra/newview/skins/default/xui/da/floater_about_land.xml b/indra/newview/skins/default/xui/da/floater_about_land.xml index 7163b149e8..3612797a7f 100644 --- a/indra/newview/skins/default/xui/da/floater_about_land.xml +++ b/indra/newview/skins/default/xui/da/floater_about_land.xml @@ -359,10 +359,10 @@ Indstillinger: - + Medie Størrelse: - + pixels diff --git a/indra/newview/skins/default/xui/da/floater_buy_currency.xml b/indra/newview/skins/default/xui/da/floater_buy_currency.xml index cc408de572..a1150d173b 100644 --- a/indra/newview/skins/default/xui/da/floater_buy_currency.xml +++ b/indra/newview/skins/default/xui/da/floater_buy_currency.xml @@ -53,10 +53,12 @@ L$ [AMT] - Der er sket en fejl, og købet er afbrudt. Forsøg venligst igen. + Der er sket en fejl, og købet er afbrudt. +Forsøg venligst igen. - Du køber ikke nok valuta, tast et større beløb og prøv igen. + Du køber ikke nok valuta, tast et større beløb +og prøv igen.