diff --git a/indra/cmake/Linking.cmake b/indra/cmake/Linking.cmake index 2bddb9517..eaa8a6dc2 100644 --- a/indra/cmake/Linking.cmake +++ b/indra/cmake/Linking.cmake @@ -42,6 +42,7 @@ if (WINDOWS) wldap32 gdi32 user32 + dbghelp ) else (WINDOWS) set(WINDOWS_LIBRARIES "") diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index dbd1f092d..47cddfdba 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -63,6 +63,7 @@ set(llcommon_SOURCE_FILES llsdutil.cpp llsecondlifeurls.cpp llstat.cpp + llstacktrace.cpp llstreamtools.cpp llstring.cpp llstringtable.cpp @@ -92,12 +93,12 @@ set(llcommon_HEADER_FILES linden_common.h linked_lists.h llagentconstants.h + llavatarname.h llapp.h llapr.h llassettype.h llassoclist.h llavatarconstants.h - llavatarname.h llbase32.h llbase64.h llboost.h @@ -173,6 +174,7 @@ set(llcommon_HEADER_FILES llskiplist.h llskipmap.h llstack.h + llstacktrace.h llstat.h llstatenums.h llstl.h diff --git a/indra/llcommon/llstacktrace.cpp b/indra/llcommon/llstacktrace.cpp new file mode 100644 index 000000000..e0446c5d0 --- /dev/null +++ b/indra/llcommon/llstacktrace.cpp @@ -0,0 +1,143 @@ +/** + * @file llstacktrace.cpp + * @brief stack tracing functionality + * + * $LicenseInfo:firstyear=2001&license=viewergpl$ + * + * Copyright (c) 2001-2010, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlife.com/developers/opensource/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlife.com/developers/opensource/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + * + */ + +#include "linden_common.h" +#include "llstacktrace.h" + +#ifdef LL_WINDOWS + +#include +#include + +#include "windows.h" +#include "Dbghelp.h" + +typedef USHORT NTAPI RtlCaptureStackBackTrace_Function( + IN ULONG frames_to_skip, + IN ULONG frames_to_capture, + OUT PVOID *backtrace, + OUT PULONG backtrace_hash); + +static RtlCaptureStackBackTrace_Function* const RtlCaptureStackBackTrace_fn = + (RtlCaptureStackBackTrace_Function*) + GetProcAddress(GetModuleHandleA("ntdll.dll"), "RtlCaptureStackBackTrace"); + +bool ll_get_stack_trace(std::vector& lines) +{ + const S32 MAX_STACK_DEPTH = 32; + const S32 STRING_NAME_LENGTH = 200; + const S32 FRAME_SKIP = 2; + static BOOL symbolsLoaded = false; + static BOOL firstCall = true; + + HANDLE hProc = GetCurrentProcess(); + + // load the symbols if they're not loaded + if(!symbolsLoaded && firstCall) + { + symbolsLoaded = SymInitialize(hProc, NULL, true); + firstCall = false; + } + + // if loaded, get the call stack + if(symbolsLoaded) + { + // create the frames to hold the addresses + void* frames[MAX_STACK_DEPTH]; + memset(frames, 0, sizeof(void*)*MAX_STACK_DEPTH); + S32 depth = 0; + + // get the addresses + depth = RtlCaptureStackBackTrace_fn(FRAME_SKIP, MAX_STACK_DEPTH, frames, NULL); + + IMAGEHLP_LINE64 line; + memset(&line, 0, sizeof(IMAGEHLP_LINE64)); + line.SizeOfStruct = sizeof(IMAGEHLP_LINE64); + + // create something to hold address info + PIMAGEHLP_SYMBOL64 pSym; + pSym = (PIMAGEHLP_SYMBOL64)malloc(sizeof(IMAGEHLP_SYMBOL64) + STRING_NAME_LENGTH); + memset(pSym, 0, sizeof(IMAGEHLP_SYMBOL64) + STRING_NAME_LENGTH); + pSym->MaxNameLength = STRING_NAME_LENGTH; + pSym->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64); + + // get address info for each address frame + // and store + for(S32 i=0; i < depth; i++) + { + std::stringstream stack_line; + BOOL ret; + + DWORD64 addr = (DWORD64)frames[i]; + ret = SymGetSymFromAddr64(hProc, addr, 0, pSym); + if(ret) + { + stack_line << pSym->Name << " "; + } + + DWORD dummy; + ret = SymGetLineFromAddr64(hProc, addr, &dummy, &line); + if(ret) + { + std::string file_name = line.FileName; + std::string::size_type index = file_name.rfind("\\"); + stack_line << file_name.substr(index + 1, file_name.size()) << ":" << line.LineNumber; + } + + lines.push_back(stack_line.str()); + } + + free(pSym); + + // TODO: figure out a way to cleanup symbol loading + // Not hugely necessary, however. + //SymCleanup(hProc); + return true; + } + else + { + lines.push_back("Stack Trace Failed. PDB symbol info not loaded"); + } + + return false; +} + +#else + +bool ll_get_stack_trace(std::vector& lines) +{ + return false; +} + +#endif + diff --git a/indra/llcommon/llstacktrace.h b/indra/llcommon/llstacktrace.h new file mode 100644 index 000000000..93883b8b3 --- /dev/null +++ b/indra/llcommon/llstacktrace.h @@ -0,0 +1,45 @@ +/** + * @file llstacktrace.h + * @brief stack trace functions + * + * $LicenseInfo:firstyear=2001&license=viewergpl$ + * + * Copyright (c) 2001-2010, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlife.com/developers/opensource/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlife.com/developers/opensource/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + * + */ + + +#ifndef LL_LLSTACKTRACE_H +#define LL_LLSTACKTRACE_H + +#include "stdtypes.h" +#include +#include + +LL_COMMON_API bool ll_get_stack_trace(std::vector& lines); + +#endif + diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp index e34b7f305..673bc4b9e 100644 --- a/indra/llrender/llgl.cpp +++ b/indra/llrender/llgl.cpp @@ -45,10 +45,12 @@ #include "llrender.h" #include "llerror.h" +#include "llerrorcontrol.h" #include "llquaternion.h" #include "llmath.h" #include "m4math.h" #include "llstring.h" +#include "llstacktrace.h" #include "llglheaders.h" @@ -56,10 +58,49 @@ //#define GL_STATE_VERIFY #endif + +BOOL gDebugSession = FALSE; BOOL gDebugGL = FALSE; BOOL gClothRipple = FALSE; BOOL gNoRender = FALSE; BOOL gGLActive = FALSE; + +std::ofstream gFailLog; + +void ll_init_fail_log(std::string filename) +{ + gFailLog.open(filename.c_str()); +} + + +void ll_fail(std::string msg) +{ + + if (gDebugSession) + { + std::vector lines; + + gFailLog << LLError::utcTime() << " " << msg << std::endl; + + gFailLog << "Stack Trace:" << std::endl; + + ll_get_stack_trace(lines); + + for(size_t i = 0; i < lines.size(); ++i) + { + gFailLog << lines[i] << std::endl; + } + + gFailLog << "End of Stack Trace." << std::endl << std::endl; + + gFailLog.flush(); + } +}; + +void ll_close_fail_log() +{ + gFailLog.close(); +} LLMatrix4 gGLObliqueProjectionInverse; #define LL_GL_NAME_POOLING 0 @@ -133,12 +174,9 @@ PFNGLFRAMEBUFFERTEXTURE3DEXTPROC glFramebufferTexture3DEXT = NULL; PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC glFramebufferRenderbufferEXT = NULL; PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC glGetFramebufferAttachmentParameterivEXT = NULL; PFNGLGENERATEMIPMAPEXTPROC glGenerateMipmapEXT = NULL; - -// GL_EXT_framebuffer_multisample -PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC glRenderbufferStorageMultisampleEXT = NULL; - -// GL_EXT_framebuffer_blit PFNGLBLITFRAMEBUFFEREXTPROC glBlitFramebufferEXT = NULL; +PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC glRenderbufferStorageMultisampleEXT = NULL; +PFNGLFRAMEBUFFERTEXTURELAYEREXTPROC glFramebufferTextureLayerEXT = NULL; // GL_EXT_blend_func_separate PFNGLBLENDFUNCSEPARATEEXTPROC glBlendFuncSeparateEXT = NULL; @@ -277,6 +315,8 @@ LLGLManager::LLGLManager() : mIsDisabled(FALSE), mHasMultitexture(FALSE), + mHasATIMemInfo(FALSE), + mHasNVXMemInfo(FALSE), mNumTextureUnits(1), mHasMipMapGeneration(FALSE), mHasCompressedTextures(FALSE), @@ -289,6 +329,7 @@ LLGLManager::LLGLManager() : mHasShaderObjects(FALSE), mHasVertexShader(FALSE), mHasFragmentShader(FALSE), + mNumTextureImageUnits(0), mHasOcclusionQuery(FALSE), mHasOcclusionQuery2(FALSE), mHasPointParameters(FALSE), @@ -460,6 +501,20 @@ bool LLGLManager::initGL() // This is called here because it depends on the setting of mIsGF2or4MX, and sets up mHasMultitexture. initExtensions(); + if (mHasATIMemInfo) + { //ask the gl how much vram is free at startup and attempt to use no more than half of that + S32 meminfo[4]; + glGetIntegerv(GL_TEXTURE_FREE_MEMORY_ATI, meminfo); + + mVRAM = meminfo[0]/1024; + } + else if (mHasNVXMemInfo) + { + S32 dedicated_memory; + glGetIntegerv(GL_GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX, &dedicated_memory); + mVRAM = dedicated_memory/1024; + } + if (mHasMultitexture) { GLint num_tex_units; @@ -479,6 +534,12 @@ bool LLGLManager::initGL() return false; } + if (mHasFragmentShader) + { + GLint num_tex_image_units; + glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &num_tex_image_units); + mNumTextureImageUnits = num_tex_image_units; + } initGLStates(); return true; @@ -504,14 +565,13 @@ void LLGLManager::getGLInfo(LLSD& info) std::string LLGLManager::getGLInfoString() { std::string info_str; - std::string all_exts, line; info_str += std::string("GL_VENDOR ") + ll_safe_string((const char *)glGetString(GL_VENDOR)) + std::string("\n"); info_str += std::string("GL_RENDERER ") + ll_safe_string((const char *)glGetString(GL_RENDERER)) + std::string("\n"); info_str += std::string("GL_VERSION ") + ll_safe_string((const char *)glGetString(GL_VERSION)) + std::string("\n"); #if !LL_MESA_HEADLESS - all_exts = (const char *)gGLHExts.mSysExts; + std::string all_exts= ll_safe_string(((const char *)gGLHExts.mSysExts)); LLStringUtil::replaceChar(all_exts, ' ', '\n'); info_str += std::string("GL_EXTENSIONS:\n") + all_exts + std::string("\n"); #endif @@ -522,14 +582,13 @@ std::string LLGLManager::getGLInfoString() void LLGLManager::printGLInfoString() { std::string info_str; - std::string all_exts, line; LL_INFOS("RenderInit") << "GL_VENDOR: " << ((const char *)glGetString(GL_VENDOR)) << LL_ENDL; LL_INFOS("RenderInit") << "GL_RENDERER: " << ((const char *)glGetString(GL_RENDERER)) << LL_ENDL; LL_INFOS("RenderInit") << "GL_VERSION: " << ((const char *)glGetString(GL_VERSION)) << LL_ENDL; #if !LL_MESA_HEADLESS - all_exts = std::string(gGLHExts.mSysExts); + std::string all_exts= ll_safe_string(((const char *)gGLHExts.mSysExts)); LLStringUtil::replaceChar(all_exts, ' ', '\n'); LL_DEBUGS("RenderInit") << "GL_EXTENSIONS:\n" << all_exts << LL_ENDL; #endif @@ -615,6 +674,8 @@ void LLGLManager::initExtensions() mHasTextureRectangle = FALSE; #else // LL_MESA_HEADLESS mHasMultitexture = glh_init_extensions("GL_ARB_multitexture"); + mHasATIMemInfo = ExtensionExists("GL_ATI_meminfo", gGLHExts.mSysExts); + mHasNVXMemInfo = ExtensionExists("GL_NVX_gpu_memory_info", gGLHExts.mSysExts); mHasMipMapGeneration = glh_init_extensions("GL_SGIS_generate_mipmap"); mHasSeparateSpecularColor = glh_init_extensions("GL_EXT_separate_specular_color"); mHasAnisotropic = glh_init_extensions("GL_EXT_texture_filter_anisotropic"); @@ -626,9 +687,15 @@ void LLGLManager::initExtensions() mHasOcclusionQuery2 = ExtensionExists("GL_ARB_occlusion_query2", gGLHExts.mSysExts); mHasVertexBufferObject = ExtensionExists("GL_ARB_vertex_buffer_object", gGLHExts.mSysExts); mHasDepthClamp = ExtensionExists("GL_ARB_depth_clamp", gGLHExts.mSysExts) || ExtensionExists("GL_NV_depth_clamp", gGLHExts.mSysExts); - // mask out FBO support when packed_depth_stencil isn't there 'cause we need it for LLRenderTarget -Brad - mHasFramebufferObject = ExtensionExists("GL_EXT_framebuffer_object", gGLHExts.mSysExts) - && ExtensionExists("GL_EXT_packed_depth_stencil", gGLHExts.mSysExts); + // mask out FBO support when packed_depth_stencil isn't there 'cause we need it for LLRenderTarget -Brad +#ifdef GL_ARB_framebuffer_object + mHasFramebufferObject = ExtensionExists("GL_ARB_framebuffer_object", gGLHExts.mSysExts); +#else + mHasFramebufferObject = ExtensionExists("GL_EXT_framebuffer_object", gGLHExts.mSysExts) && + ExtensionExists("GL_EXT_framebuffer_blit", gGLHExts.mSysExts) && + ExtensionExists("GL_EXT_framebuffer_multisample", gGLHExts.mSysExts) && + ExtensionExists("GL_EXT_packed_depth_stencil", gGLHExts.mSysExts); +#endif mHasFramebufferMultisample = mHasFramebufferObject && ExtensionExists("GL_EXT_framebuffer_multisample", gGLHExts.mSysExts); mHasDrawBuffers = ExtensionExists("GL_ARB_draw_buffers", gGLHExts.mSysExts); mHasBlendFuncSeparate = ExtensionExists("GL_EXT_blend_func_separate", gGLHExts.mSysExts); @@ -832,11 +899,9 @@ void LLGLManager::initExtensions() glFramebufferRenderbufferEXT = (PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC) GLH_EXT_GET_PROC_ADDRESS("glFramebufferRenderbufferEXT"); glGetFramebufferAttachmentParameterivEXT = (PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC) GLH_EXT_GET_PROC_ADDRESS("glGetFramebufferAttachmentParameterivEXT"); glGenerateMipmapEXT = (PFNGLGENERATEMIPMAPEXTPROC) GLH_EXT_GET_PROC_ADDRESS("glGenerateMipmapEXT"); - } - if (mHasFramebufferMultisample) - { - glRenderbufferStorageMultisampleEXT = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC) GLH_EXT_GET_PROC_ADDRESS("glRenderbufferStorageMultisampleEXT"); glBlitFramebufferEXT = (PFNGLBLITFRAMEBUFFEREXTPROC) GLH_EXT_GET_PROC_ADDRESS("glBlitFramebufferEXT"); + glRenderbufferStorageMultisampleEXT = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC) GLH_EXT_GET_PROC_ADDRESS("glRenderbufferStorageMultisampleEXT"); + glFramebufferTextureLayerEXT = (PFNGLFRAMEBUFFERTEXTURELAYEREXTPROC) GLH_EXT_GET_PROC_ADDRESS("glFramebufferTextureLayerEXT"); } if (mHasDrawBuffers) { @@ -1008,12 +1073,35 @@ void flush_glerror() glGetError(); } -void assert_glerror() +//this function outputs gl error to the log file, does not crash the code. +void log_glerror() { - if (gNoRender || !gDebugGL) + if (LL_UNLIKELY(!gGLManager.mInited)) { - return; + return ; } + // Create or update texture to be used with this data + GLenum error; + error = glGetError(); + while (LL_UNLIKELY(error)) + { + GLubyte const * gl_error_msg = gluErrorString(error); + if (NULL != gl_error_msg) + { + llwarns << "GL Error: " << error << " GL Error String: " << gl_error_msg << llendl ; + } + else + { + // gluErrorString returns NULL for some extensions' error codes. + // you'll probably have to grep for the number in glext.h. + llwarns << "GL Error: UNKNOWN 0x" << std::hex << error << std::dec << llendl; + } + error = glGetError(); + } +} + +void do_assert_glerror() +{ if (LL_UNLIKELY(!gGLManager.mInited)) { LL_ERRS("RenderInit") << "GL not initialized" << LL_ENDL; @@ -1025,29 +1113,65 @@ void assert_glerror() while (LL_UNLIKELY(error)) { quit = TRUE; -#ifndef LL_LINUX // *FIX: ! This should be an error for linux as well. GLubyte const * gl_error_msg = gluErrorString(error); if (NULL != gl_error_msg) { LL_WARNS("RenderState") << "GL Error:" << error<< LL_ENDL; LL_WARNS("RenderState") << "GL Error String:" << gl_error_msg << LL_ENDL; + + if (gDebugSession) + { + gFailLog << "GL Error:" << gl_error_msg << std::endl; + } } else { // gluErrorString returns NULL for some extensions' error codes. // you'll probably have to grep for the number in glext.h. LL_WARNS("RenderState") << "GL Error: UNKNOWN 0x" << std::hex << error << std::dec << LL_ENDL; + + if (gDebugSession) + { + gFailLog << "GL Error: UNKNOWN 0x" << std::hex << error << std::dec << std::endl; + } } error = glGetError(); -#endif } if (quit) { - llerrs << "One or more unhandled GL errors." << llendl; + if (gDebugSession) + { + ll_fail("assert_glerror failed"); + } + else + { + llerrs << "One or more unhandled GL errors." << llendl; + } } } +void assert_glerror() +{ + if (gNoRender) + return; + if (!gGLActive) + { + //llwarns << "GL used while not active!" << llendl; + + if (gDebugSession) + { + //ll_fail("GL used while not active"); + } + } + + if (gDebugGL) + { + do_assert_glerror(); + } +} + + void clear_glerror() { // Create or update texture to be used with this data @@ -1130,9 +1254,19 @@ void LLGLState::checkStates(const std::string& msg) glGetIntegerv(GL_BLEND_SRC, &src); glGetIntegerv(GL_BLEND_DST, &dst); + BOOL error = FALSE; + if (src != GL_SRC_ALPHA || dst != GL_ONE_MINUS_SRC_ALPHA) { - LL_GL_ERRS << "Blend function corrupted: " << std::hex << src << " " << std::hex << dst << " " << msg << std::dec << LL_ENDL; + if (gDebugSession) + { + gFailLog << "Blend function corrupted: " << std::hex << src << " " << std::hex << dst << " " << msg << std::dec << std::endl; + error = TRUE; + } + else + { + LL_GL_ERRS << "Blend function corrupted: " << std::hex << src << " " << std::hex << dst << " " << msg << std::dec << LL_ENDL; + } } for (boost::unordered_map::iterator iter = sStateMap.begin(); @@ -1144,10 +1278,22 @@ void LLGLState::checkStates(const std::string& msg) if(cur_state != gl_state) { dumpStates(); - LL_GL_ERRS << llformat("LLGLState error. State: 0x%04x",state) << LL_ENDL; + if (gDebugSession) + { + gFailLog << llformat("LLGLState error. State: 0x%04x",state) << std::endl; + error = TRUE; + } + else + { + LL_GL_ERRS << llformat("LLGLState error. State: 0x%04x",state) << LL_ENDL; + } } } + if (error) + { + ll_fail("LLGLState::checkStates failed."); + } stop_glerror(); } @@ -1158,9 +1304,12 @@ void LLGLState::checkTextureChannels(const std::string& msg) return; } + stop_glerror(); + GLint activeTexture; glGetIntegerv(GL_ACTIVE_TEXTURE_ARB, &activeTexture); - + stop_glerror(); + BOOL error = FALSE; if (activeTexture == GL_TEXTURE0_ARB) @@ -1168,15 +1317,22 @@ void LLGLState::checkTextureChannels(const std::string& msg) GLint tex_env_mode = 0; glGetTexEnviv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &tex_env_mode); + stop_glerror(); + if (tex_env_mode != GL_MODULATE) { error = TRUE; LL_WARNS("RenderState") << "GL_TEXTURE_ENV_MODE invalid: " << std::hex << tex_env_mode << std::dec << LL_ENDL; + if (gDebugSession) + { + gFailLog << "GL_TEXTURE_ENV_MODE invalid: " << std::hex << tex_env_mode << std::dec << std::endl; + } } } GLint maxTextureUnits = 0; glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &maxTextureUnits); + stop_glerror(); static const char* label[] = { @@ -1205,35 +1361,44 @@ void LLGLState::checkTextureChannels(const std::string& msg) }; GLint stackDepth = 0; + glh::matrix4f mat; glh::matrix4f identity; identity.identity(); -// LLMatrix4 identity; -// LLMatrix4 matrix; for (GLint i = 1; i < maxTextureUnits; i++) { gGL.getTexUnit(i)->activate(); glClientActiveTextureARB(GL_TEXTURE0_ARB+i); - + stop_glerror(); glGetIntegerv(GL_TEXTURE_STACK_DEPTH, &stackDepth); + stop_glerror(); if (stackDepth != 1) { error = TRUE; LL_WARNS("RenderState") << "Texture matrix stack corrupted." << LL_ENDL; + + if (gDebugSession) + { + gFailLog << "Texture matrix stack corrupted." << std::endl; + } } - //glGetFloatv(GL_TEXTURE_MATRIX, (GLfloat*) matrix.mMatrix); glGetFloatv(GL_TEXTURE_MATRIX, (GLfloat*) mat.m); + stop_glerror(); - //if (matrix != identity) if (mat != identity) { error = TRUE; LL_WARNS("RenderState") << "Texture matrix in channel " << i << " corrupt." << LL_ENDL; + if (gDebugSession) + { + gFailLog << "Texture matrix in channel " << i << " corrupt." << std::endl; + } } + for (S32 j = (i == 0 ? 1 : 0); j < (gGLManager.mHasTextureRectangle ? 9 : 8); j++) { @@ -1241,24 +1406,42 @@ void LLGLState::checkTextureChannels(const std::string& msg) { error = TRUE; LL_WARNS("RenderState") << "Texture channel " << i << " still has " << label[j] << " enabled." << LL_ENDL; + if (gDebugSession) + { + gFailLog << "Texture channel " << i << " still has " << label[j] << " enabled." << std::endl; + } } + stop_glerror(); } glGetFloatv(GL_TEXTURE_MATRIX, mat.m); + stop_glerror(); if (mat != identity) { error = TRUE; LL_WARNS("RenderState") << "Texture matrix " << i << " is not identity." << LL_ENDL; + if (gDebugSession) + { + gFailLog << "Texture matrix " << i << " is not identity." << std::endl; + } } } gGL.getTexUnit(0)->activate(); glClientActiveTextureARB(GL_TEXTURE0_ARB); + stop_glerror(); if (error) { - LL_GL_ERRS << "GL texture state corruption detected. " << msg << LL_ENDL; + if (gDebugSession) + { + ll_fail("LLGLState::checkTextureChannels failed."); + } + else + { + LL_GL_ERRS << "GL texture state corruption detected. " << msg << LL_ENDL; + } } } @@ -1278,6 +1461,10 @@ void LLGLState::checkClientArrays(const std::string& msg, U32 data_mask) if (active_texture != GL_TEXTURE0_ARB) { llwarns << "Client active texture corrupted: " << active_texture << llendl; + if (gDebugSession) + { + gFailLog << "Client active texture corrupted: " << active_texture << std::endl; + } error = TRUE; } @@ -1285,6 +1472,10 @@ void LLGLState::checkClientArrays(const std::string& msg, U32 data_mask) if (active_texture != GL_TEXTURE0_ARB) { llwarns << "Active texture corrupted: " << active_texture << llendl; + if (gDebugSession) + { + gFailLog << "Active texture corrupted: " << active_texture << std::endl; + } error = TRUE; } @@ -1321,6 +1512,10 @@ void LLGLState::checkClientArrays(const std::string& msg, U32 data_mask) { error = TRUE; LL_WARNS("RenderState") << "GL still has " << label[j] << " enabled." << LL_ENDL; + if (gDebugSession) + { + gFailLog << "GL still has " << label[j] << " enabled." << std::endl; + } } } else @@ -1329,6 +1524,10 @@ void LLGLState::checkClientArrays(const std::string& msg, U32 data_mask) { error = TRUE; LL_WARNS("RenderState") << "GL does not have " << label[j] << " enabled." << LL_ENDL; + if (gDebugSession) + { + gFailLog << "GL does not have " << label[j] << " enabled." << std::endl; + } } } } @@ -1341,6 +1540,10 @@ void LLGLState::checkClientArrays(const std::string& msg, U32 data_mask) { error = TRUE; LL_WARNS("RenderState") << "GL still has GL_TEXTURE_COORD_ARRAY enabled on channel 1." << LL_ENDL; + if (gDebugSession) + { + gFailLog << "GL still has GL_TEXTURE_COORD_ARRAY enabled on channel 1." << std::endl; + } } } else @@ -1349,6 +1552,10 @@ void LLGLState::checkClientArrays(const std::string& msg, U32 data_mask) { error = TRUE; LL_WARNS("RenderState") << "GL does not have GL_TEXTURE_COORD_ARRAY enabled on channel 1." << LL_ENDL; + if (gDebugSession) + { + gFailLog << "GL does not have GL_TEXTURE_COORD_ARRAY enabled on channel 1." << std::endl; + } } } @@ -1358,6 +1565,10 @@ void LLGLState::checkClientArrays(const std::string& msg, U32 data_mask) { error = TRUE; LL_WARNS("RenderState") << "GL still has GL_TEXTURE_2D enabled on channel 1." << LL_ENDL; + if (gDebugSession) + { + gFailLog << "GL still has GL_TEXTURE_2D enabled on channel 1." << std::endl; + } } } else @@ -1366,6 +1577,10 @@ void LLGLState::checkClientArrays(const std::string& msg, U32 data_mask) { error = TRUE; LL_WARNS("RenderState") << "GL does not have GL_TEXTURE_2D enabled on channel 1." << LL_ENDL; + if (gDebugSession) + { + gFailLog << "GL does not have GL_TEXTURE_2D enabled on channel 1." << std::endl; + } } } @@ -1384,13 +1599,24 @@ void LLGLState::checkClientArrays(const std::string& msg, U32 data_mask) { error = TRUE; LL_WARNS("RenderState") << "GL still has vertex attrib array " << i << " enabled." << LL_ENDL; + if (gDebugSession) + { + gFailLog << "GL still has vertex attrib array " << i << " enabled." << std::endl; + } } } } if (error) { + if (gDebugSession) + { + ll_fail("LLGLState::checkClientArrays failed."); + } + else + { LL_GL_ERRS << "GL client array corruption detected. " << msg << LL_ENDL; + } } } @@ -1441,7 +1667,17 @@ LLGLState::~LLGLState() { if (gDebugGL) { + if (!gDebugSession) + { llassert_always(sStateMap[mState] == glIsEnabled(mState)); + } + else + { + if (sStateMap[mState] != glIsEnabled(mState)) + { + ll_fail("GL enabled state does not match expected"); + } + } } if (mIsEnabled != mWasEnabled) @@ -1839,6 +2075,11 @@ void LLGLDepthTest::checkState() sWriteEnabled != mask || sDepthFunc != func) { + if (gDebugSession) + { + gFailLog << "Unexpected depth testing state." << std::endl; + } + else { LL_GL_ERRS << "Unexpected depth testing state." << LL_ENDL; } diff --git a/indra/llrender/llgl.h b/indra/llrender/llgl.h index 217b6f26e..2e0ca22e5 100644 --- a/indra/llrender/llgl.h +++ b/indra/llrender/llgl.h @@ -37,7 +37,7 @@ #include #include -#include +#include #include "llerror.h" #include "v4color.h" @@ -52,9 +52,17 @@ #include "glh/glh_linear.h" extern BOOL gDebugGL; +extern BOOL gDebugSession; +extern std::ofstream gFailLog; #define LL_GL_ERRS LL_ERRS("RenderState") +void ll_init_fail_log(std::string filename); + +void ll_fail(std::string msg); + +void ll_close_fail_log(); + class LLSD; // Manage GL extensions... @@ -75,6 +83,8 @@ public: // Extensions used by everyone BOOL mHasMultitexture; + BOOL mHasATIMemInfo; + BOOL mHasNVXMemInfo; S32 mNumTextureUnits; BOOL mHasMipMapGeneration; BOOL mHasCompressedTextures; @@ -88,6 +98,7 @@ public: BOOL mHasShaderObjects; BOOL mHasVertexShader; BOOL mHasFragmentShader; + S32 mNumTextureImageUnits; BOOL mHasOcclusionQuery; BOOL mHasOcclusionQuery2; BOOL mHasPointParameters; @@ -154,6 +165,7 @@ void rotate_quat(LLQuaternion& rotation); void flush_glerror(); // Flush GL errors when we know we're handling them correctly. +void log_glerror(); void assert_glerror(); void clear_glerror(); @@ -415,4 +427,66 @@ extern BOOL gClothRipple; extern BOOL gNoRender; extern BOOL gGLActive; +// Deal with changing glext.h definitions for newer SDK versions, specifically +// with MAC OSX 10.5 -> 10.6 + + +#ifndef GL_DEPTH_ATTACHMENT +#define GL_DEPTH_ATTACHMENT GL_DEPTH_ATTACHMENT_EXT +#endif + +#ifndef GL_STENCIL_ATTACHMENT +#define GL_STENCIL_ATTACHMENT GL_STENCIL_ATTACHMENT_EXT +#endif + +#ifndef GL_FRAMEBUFFER +#define GL_FRAMEBUFFER GL_FRAMEBUFFER_EXT +#define GL_DRAW_FRAMEBUFFER GL_DRAW_FRAMEBUFFER_EXT +#define GL_READ_FRAMEBUFFER GL_READ_FRAMEBUFFER_EXT +#define GL_FRAMEBUFFER_COMPLETE GL_FRAMEBUFFER_COMPLETE_EXT +#define GL_FRAMEBUFFER_UNSUPPORTED GL_FRAMEBUFFER_UNSUPPORTED_EXT +#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT +#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT +#define glGenFramebuffers glGenFramebuffersEXT +#define glBindFramebuffer glBindFramebufferEXT +#define glCheckFramebufferStatus glCheckFramebufferStatusEXT +#define glBlitFramebuffer glBlitFramebufferEXT +#define glDeleteFramebuffers glDeleteFramebuffersEXT +#define glFramebufferRenderbuffer glFramebufferRenderbufferEXT +#define glFramebufferTexture2D glFramebufferTexture2DEXT +#endif + +#ifndef GL_RENDERBUFFER +#define GL_RENDERBUFFER GL_RENDERBUFFER_EXT +#define glGenRenderbuffers glGenRenderbuffersEXT +#define glBindRenderbuffer glBindRenderbufferEXT +#define glRenderbufferStorage glRenderbufferStorageEXT +#define glRenderbufferStorageMultisample glRenderbufferStorageMultisampleEXT +#define glDeleteRenderbuffers glDeleteRenderbuffersEXT +#endif + +#ifndef GL_COLOR_ATTACHMENT +#define GL_COLOR_ATTACHMENT GL_COLOR_ATTACHMENT_EXT +#endif + +#ifndef GL_COLOR_ATTACHMENT0 +#define GL_COLOR_ATTACHMENT0 GL_COLOR_ATTACHMENT0_EXT +#endif + +#ifndef GL_COLOR_ATTACHMENT1 +#define GL_COLOR_ATTACHMENT1 GL_COLOR_ATTACHMENT1_EXT +#endif + +#ifndef GL_COLOR_ATTACHMENT2 +#define GL_COLOR_ATTACHMENT2 GL_COLOR_ATTACHMENT2_EXT +#endif + +#ifndef GL_COLOR_ATTACHMENT3 +#define GL_COLOR_ATTACHMENT3 GL_COLOR_ATTACHMENT3_EXT +#endif + + +#ifndef GL_DEPTH24_STENCIL8 +#define GL_DEPTH24_STENCIL8 GL_DEPTH24_STENCIL8_EXT +#endif #endif // LL_LLGL_H diff --git a/indra/llrender/llglheaders.h b/indra/llrender/llglheaders.h index 81ae3d40e..9efe16432 100644 --- a/indra/llrender/llglheaders.h +++ b/indra/llrender/llglheaders.h @@ -473,17 +473,17 @@ extern PFNGLFRAMEBUFFERTEXTURE3DEXTPROC glFramebufferTexture3DEXT; extern PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC glFramebufferRenderbufferEXT; extern PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC glGetFramebufferAttachmentParameterivEXT; extern PFNGLGENERATEMIPMAPEXTPROC glGenerateMipmapEXT; - -// GL_EXT_framebuffer_multisample -extern PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC glRenderbufferStorageMultisampleEXT; - -// GL_EXT_framebuffer_blit extern PFNGLBLITFRAMEBUFFEREXTPROC glBlitFramebufferEXT; +extern PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC glRenderbufferStorageMultisampleEXT; +extern PFNGLFRAMEBUFFERTEXTURELAYEREXTPROC glFramebufferTextureLayerEXT; //GL_ARB_draw_buffers extern PFNGLDRAWBUFFERSARBPROC glDrawBuffersARB; + #elif LL_WINDOWS +//---------------------------------------------------------------------------- +// LL_WINDOWS // windows gl headers depend on things like APIENTRY, so include windows. #define WIN32_LEAN_AND_MEAN @@ -672,12 +672,9 @@ extern PFNGLFRAMEBUFFERTEXTURE3DEXTPROC glFramebufferTexture3DEXT; extern PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC glFramebufferRenderbufferEXT; extern PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC glGetFramebufferAttachmentParameterivEXT; extern PFNGLGENERATEMIPMAPEXTPROC glGenerateMipmapEXT; - -// GL_EXT_framebuffer_multisample -extern PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC glRenderbufferStorageMultisampleEXT; - -// GL_EXT_framebuffer_blit extern PFNGLBLITFRAMEBUFFEREXTPROC glBlitFramebufferEXT; +extern PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC glRenderbufferStorageMultisampleEXT; +extern PFNGLFRAMEBUFFERTEXTURELAYEREXTPROC glFramebufferTextureLayerEXT; //GL_ARB_draw_buffers extern PFNGLDRAWBUFFERSARBPROC glDrawBuffersARB; @@ -720,6 +717,9 @@ extern void glFramebufferRenderbufferEXT(GLenum target, GLenum attachment, GLenu extern void glGetFramebufferAttachmentParameterivEXT(GLenum target, GLenum attachment, GLenum pname, GLint *params) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER; extern void glGenerateMipmapEXT(GLenum target) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER; +#ifndef GL_ARB_framebuffer_object +#define glGenerateMipmap glGenerateMipmapEXT +#endif // GL_ARB_draw_buffers extern void glDrawBuffersARB(GLsizei n, const GLenum* bufs) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER; @@ -842,4 +842,21 @@ extern void glGetBufferPointervARB (GLenum, GLenum, GLvoid* *); #define GL_DEPTH_CLAMP 0x864F #endif +//GL_NVX_gpu_memory_info constants +#ifndef GL_NVX_gpu_memory_info +#define GL_NVX_gpu_memory_info +#define GL_GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX 0x9047 +#define GL_GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX 0x9048 +#define GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX 0x9049 +#define GL_GPU_MEMORY_INFO_EVICTION_COUNT_NVX 0x904A +#define GL_GPU_MEMORY_INFO_EVICTED_MEMORY_NVX 0x904B +#endif + +//GL_ATI_meminfo constants +#ifndef GL_ATI_meminfo +#define GL_ATI_meminfo +#define GL_VBO_FREE_MEMORY_ATI 0x87FB +#define GL_TEXTURE_FREE_MEMORY_ATI 0x87FC +#define GL_RENDERBUFFER_FREE_MEMORY_ATI 0x87FD +#endif #endif // LL_LLGLHEADERS_H diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp index 4f767e50e..5eb5ffd10 100644 --- a/indra/llrender/llglslshader.cpp +++ b/indra/llrender/llglslshader.cpp @@ -420,7 +420,15 @@ S32 LLGLSLShader::disableTexture(S32 uniform, LLTexUnit::eTextureType mode) { if (gDebugGL && gGL.getTexUnit(index)->getCurrType() != mode) { - llerrs << "Texture channel " << index << " texture type corrupted." << llendl; + if (gDebugSession) + { + gFailLog << "Texture channel " << index << " texture type corrupted." << std::endl; + ll_fail("LLGLSLShader::disableTexture failed"); + } + else + { + llerrs << "Texture channel " << index << " texture type corrupted." << llendl; + } } gGL.getTexUnit(index)->disable(); } @@ -708,16 +716,34 @@ void LLGLSLShader::uniformMatrix4fv(U32 index, U32 count, GLboolean transpose, c GLint LLGLSLShader::getUniformLocation(const string& uniform) { + GLint ret = -1; if (mProgramObject > 0) { std::map::iterator iter = mUniformMap.find(uniform); if (iter != mUniformMap.end()) { - llassert(iter->second == glGetUniformLocationARB(mProgramObject, uniform.c_str())); - return iter->second; + if (gDebugGL) + { + stop_glerror(); + if (iter->second != glGetUniformLocationARB(mProgramObject, uniform.c_str())) + { + llerrs << "Uniform does not match." << llendl; + } + stop_glerror(); + } + ret = iter->second; } } - return -1; + + /*if (gDebugGL) + { + if (ret == -1 && ret != glGetUniformLocationARB(mProgramObject, uniform.c_str())) + { + llerrs << "Uniform map invalid." << llendl; + } + }*/ + + return ret; } GLint LLGLSLShader::getAttribLocation(U32 attrib) @@ -903,7 +929,9 @@ void LLGLSLShader::uniformMatrix4fv(const string& uniform, U32 count, GLboolean if (location >= 0) { + stop_glerror(); glUniformMatrix4fvARB(location, count, transpose, v); + stop_glerror(); } } diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index f20e0d6ad..763b9a772 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -110,24 +110,58 @@ void LLImageGL::checkTexSize(bool forced) const { if ((forced || gDebugGL) && mTarget == GL_TEXTURE_2D) { + { + //check viewport + GLint vp[4] ; + glGetIntegerv(GL_VIEWPORT, vp) ; + llcallstacks << "viewport: " << vp[0] << " : " << vp[1] << " : " << vp[2] << " : " << vp[3] << llcallstacksendl ; + } GLint texname; glGetIntegerv(GL_TEXTURE_BINDING_2D, &texname); + BOOL error = FALSE; if (texname != mTexName) { - llerrs << "Invalid texture bound!" << llendl; + llinfos << "Bound: " << texname << " Should bind: " << mTexName << " Default: " << LLImageGL::sDefaultGLTexture->getTexName() << llendl; + + error = TRUE; + if (gDebugSession) + { + gFailLog << "Invalid texture bound!" << std::endl; + } + else + { + 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() ; + llcallstacks << "w: " << x << " h: " << y << llcallstacksendl ; + if(!x || !y) { return ; } if(x != (mWidth >> mCurrentDiscardLevel) || y != (mHeight >> mCurrentDiscardLevel)) { - llerrs << "wrong texture size and discard level!" << llendl ; + error = TRUE; + if (gDebugSession) + { + gFailLog << "wrong texture size and discard level!" << + mWidth << " Height: " << mHeight << " Current Level: " << (S32)mCurrentDiscardLevel << std::endl; + } + else + { + llerrs << "wrong texture size and discard level: width: " << + mWidth << " Height: " << mHeight << " Current Level: " << (S32)mCurrentDiscardLevel << llendl ; + } + } + + if (error) + { + ll_fail("LLImageGL::checkTexSize failed."); } } } @@ -649,7 +683,7 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips) } // LLFastTimer t2(LLFastTimer::FTM_TEMP2); - gGL.getTexUnit(0)->bind(this); + llverify(gGL.getTexUnit(0)->bind(this)); if (mUseMipMaps) { @@ -864,12 +898,14 @@ BOOL LLImageGL::setSubImage(const U8* datap, S32 data_width, S32 data_height, S3 } if (mTexName == 0) { - llwarns << "Setting subimage on image without GL texture" << llendl; + // *TODO: Re-enable warning? Ran into thread locking issues? DK 2011-02-18 + //llwarns << "Setting subimage on image without GL texture" << llendl; return FALSE; } if (datap == NULL) { - llwarns << "Setting subimage on image with NULL datap" << llendl; + // *TODO: Re-enable warning? Ran into thread locking issues? DK 2011-02-18 + //llwarns << "Setting subimage on image with NULL datap" << llendl; return FALSE; } @@ -991,6 +1027,7 @@ void LLImageGL::deleteTextures(S32 numTextures, U32 *textures) void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 width, S32 height, U32 pixformat, U32 pixtype, const void *pixels) { glTexImage2D(target, miplevel, intformat, width, height, 0, pixformat, pixtype, pixels); + stop_glerror(); } //create an empty GL texture: just create a texture name @@ -1143,6 +1180,13 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_ if (mUseMipMaps) { mAutoGenMips = gGLManager.mHasMipMapGeneration; +#if LL_DARWIN + // On the Mac GF2 and GF4MX drivers, auto mipmap generation doesn't work right with alpha-only textures. + if(gGLManager.mIsGF2or4MX && (mFormatInternal == GL_ALPHA8) && (mFormatPrimary == GL_ALPHA)) + { + mAutoGenMips = FALSE; + } +#endif } mCurrentDiscardLevel = discard_level; diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index 3eca7daea..b10c77c1a 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -120,14 +120,29 @@ void LLTexUnit::refreshState(void) // and we reset the cached tex unit state glActiveTextureARB(GL_TEXTURE0_ARB + mIndex); + + // + // Per apple spec, don't call glEnable/glDisable when index exceeds max texture units + // http://www.mailinglistarchive.com/html/mac-opengl@lists.apple.com/2008-07/msg00653.html + // + bool enableDisable = (mIndex < gGLManager.mNumTextureUnits); + if (mCurrTexType != TT_NONE) { - glEnable(sGLTextureType[mCurrTexType]); + if (enableDisable) + { + glEnable(sGLTextureType[mCurrTexType]); + } + glBindTexture(sGLTextureType[mCurrTexType], mCurrTexture); } else { - glDisable(GL_TEXTURE_2D); + if (enableDisable) + { + glDisable(GL_TEXTURE_2D); + } + glBindTexture(GL_TEXTURE_2D, 0); } @@ -165,7 +180,10 @@ void LLTexUnit::enable(eTextureType type) disable(); // Force a disable of a previous texture type if it's enabled. } mCurrTexType = type; - glEnable(sGLTextureType[type]); + if (mIndex < gGLManager.mNumTextureUnits) + { + glEnable(sGLTextureType[type]); + } } } @@ -177,7 +195,11 @@ void LLTexUnit::disable(void) { activate(); unbind(mCurrTexType); - glDisable(sGLTextureType[mCurrTexType]); + if (mIndex < gGLManager.mNumTextureUnits) + { + glDisable(sGLTextureType[mCurrTexType]); + } + mCurrTexType = TT_NONE; } } @@ -1078,6 +1100,7 @@ void LLRender::blendFunc(eBlendFactor color_sfactor, eBlendFactor color_dfactor, sGLBlendFactor[alpha_sfactor], sGLBlendFactor[alpha_dfactor]); } } + LLTexUnit* LLRender::getTexUnit(U32 index) { if ((index >= 0) && (index < mTexUnits.size())) @@ -1205,6 +1228,34 @@ void LLRender::flush() } #endif + + if (gDebugGL) + { + if (mMode == LLRender::QUADS) + { + if (mCount%4 != 0) + { + llerrs << "Incomplete quad rendered." << llendl; + } + } + + if (mMode == LLRender::TRIANGLES) + { + if (mCount%3 != 0) + { + llerrs << "Incomplete triangle rendered." << llendl; + } + } + + if (mMode == LLRender::LINES) + { + if (mCount%2 != 0) + { + llerrs << "Incomplete line rendered." << llendl; + } + } + } + mBuffer->setBuffer(immediate_mask); mBuffer->drawArrays(mMode, 0, mCount); diff --git a/indra/llrender/llrendertarget.cpp b/indra/llrender/llrendertarget.cpp index cced3c408..3eefbe571 100644 --- a/indra/llrender/llrendertarget.cpp +++ b/indra/llrender/llrendertarget.cpp @@ -36,6 +36,9 @@ #include "llrender.h" #include "llgl.h" +LLRenderTarget* LLRenderTarget::sBoundTarget = NULL; + + void check_framebuffer_status() { @@ -212,6 +215,16 @@ void LLRenderTarget::shareDepthBuffer(LLRenderTarget& target) llerrs << "Cannot share depth buffer between non FBO render targets." << llendl; } + if (target.mDepth) + { + llerrs << "Attempting to override existing depth buffer. Detach existing buffer first." << llendl; + } + + if (target.mUseDepth) + { + llerrs << "Attempting to override existing shared depth buffer. Detach existing buffer first." << llendl; + } + if (mDepth) { stop_glerror(); @@ -230,11 +243,6 @@ void LLRenderTarget::shareDepthBuffer(LLRenderTarget& target) { glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, LLTexUnit::getInternalType(mUsage), mDepth, 0); stop_glerror(); - if (mStencil) - { - glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, LLTexUnit::getInternalType(mUsage), mDepth, 0); - stop_glerror(); - } } glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); @@ -285,7 +293,9 @@ void LLRenderTarget::release() LLImageGL::deleteTextures(mTex.size(), &mTex[0]); mTex.clear(); } + mSampleBuffer = NULL; + sBoundTarget = NULL; } void LLRenderTarget::bindTarget() @@ -324,6 +334,7 @@ void LLRenderTarget::bindTarget() } glViewport(0, 0, mResX, mResY); + sBoundTarget = this; } // static @@ -333,6 +344,7 @@ void LLRenderTarget::unbindTarget() { glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); } + sBoundTarget = NULL; } void LLRenderTarget::clear(U32 mask_in) @@ -399,7 +411,11 @@ void LLRenderTarget::flush(bool fetch_depth) } else { + stop_glerror(); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + + stop_glerror(); if (mSampleBuffer) { @@ -607,6 +623,7 @@ void LLMultisampleBuffer::bindTarget(LLRenderTarget* ref) glViewport(0, 0, mResX, mResY); + sBoundTarget = this; } void LLMultisampleBuffer::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil, LLTexUnit::eTextureType usage, bool use_fbo ) diff --git a/indra/llrender/llrendertarget.h b/indra/llrender/llrendertarget.h index f264276ff..fe5cf9072 100644 --- a/indra/llrender/llrendertarget.h +++ b/indra/llrender/llrendertarget.h @@ -144,6 +144,8 @@ public: //one renderable attachment (i.e. color buffer, depth buffer). bool isComplete() const; + static LLRenderTarget* getCurrentBoundTarget() { return sBoundTarget; } + protected: friend class LLMultisampleBuffer; U32 mResX; @@ -157,6 +159,8 @@ protected: LLTexUnit::eTextureType mUsage; U32 mSamples; LLMultisampleBuffer* mSampleBuffer; + + static LLRenderTarget* sBoundTarget; }; diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp index 2cb357920..2dc3dae91 100644 --- a/indra/llrender/llshadermgr.cpp +++ b/indra/llrender/llshadermgr.cpp @@ -313,7 +313,7 @@ void LLShaderMgr::dumpObjectLog(GLhandleARB ret, BOOL warns) } else { - LL_DEBUGS("ShaderLoading") << log << LL_ENDL; + LL_INFOS("ShaderLoading") << log << LL_ENDL; } } } diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index 933f5cd35..49c410d27 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -31,13 +31,13 @@ */ #include "linden_common.h" +#include "llmemory.h" #include - +#include "llsys.h" #include "llvertexbuffer.h" // #include "llrender.h" #include "llglheaders.h" -#include "llmemory.h" #include "llmemtype.h" #include "llrender.h" @@ -141,6 +141,7 @@ void LLVertexBuffer::setupClientArrays(U32 data_mask) GL_COLOR_ARRAY, }; + BOOL error = FALSE; for (U32 i = 0; i < 4; ++i) { if (sLastMask & mask[i]) @@ -153,7 +154,15 @@ void LLVertexBuffer::setupClientArrays(U32 data_mask) { //needs to be enabled, make sure it was (DEBUG TEMPORARY) if (i > 0 && !glIsEnabled(array[i])) { - llerrs << "Bad client state! " << array[i] << " disabled." << llendl; + if (gDebugSession) + { + error = TRUE; + gFailLog << "Bad client state! " << array[i] << " disabled." << std::endl; + } + else + { + llerrs << "Bad client state! " << array[i] << " disabled." << llendl; + } } } } @@ -165,11 +174,24 @@ void LLVertexBuffer::setupClientArrays(U32 data_mask) } else if (gDebugGL && i > 0 && glIsEnabled(array[i])) { //needs to be disabled, make sure it was (DEBUG TEMPORARY) - llerrs << "Bad client state! " << array[i] << " enabled." << llendl; + if (gDebugSession) + { + error = TRUE; + gFailLog << "Bad client state! " << array[i] << " enabled." << std::endl; + } + else + { + llerrs << "Bad client state! " << array[i] << " enabled." << llendl; + } } } } + if (error) + { + ll_fail("LLVertexBuffer::setupClientArrays failed"); + } + U32 map_tc[] = { MAP_TEXCOORD1, @@ -268,6 +290,18 @@ void LLVertexBuffer::validateRange(U32 start, U32 end, U32 count, U32 indices_of { llerrs << "Bad index buffer draw range: [" << indices_offset << ", " << indices_offset+count << "]" << llendl; } + + if (gDebugGL && !useVBOs()) + { + U16* idx = ((U16*) getIndicesPointer())+indices_offset; + for (U32 i = 0; i < count; ++i) + { + if (idx[i] < start || idx[i] > end) + { + llerrs << "Index out of range: " << idx[i] << " not in [" << start << ", " << end << "]" << llendl; + } + } + } } void LLVertexBuffer::drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indices_offset) const @@ -685,6 +719,8 @@ void LLVertexBuffer::updateNumVerts(S32 nverts) { LLMemType mt(LLMemType::MTYPE_VERTEX_DATA); + llassert(nverts >= 0); + if (nverts >= 65535) { llwarns << "Vertex buffer overflow!" << llendl; @@ -713,6 +749,9 @@ void LLVertexBuffer::updateNumVerts(S32 nverts) void LLVertexBuffer::updateNumIndices(S32 nindices) { LLMemType mt(LLMemType::MTYPE_VERTEX_DATA); + + llassert(nindices >= 0); + mRequestedNumIndices = nindices; if (!mDynamicSize) { @@ -945,8 +984,16 @@ volatile U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 access) if (!mMappedData) { + log_glerror(); + + //check the availability of memory + U32 avail_phy_mem, avail_vir_mem; + LLMemoryInfo::getAvailableMemoryKB(avail_phy_mem, avail_vir_mem) ; + llinfos << "Available physical mwmory(KB): " << avail_phy_mem << llendl ; + llinfos << "Available virtual memory(KB): " << avail_vir_mem << llendl; + if(!sDisableVBOMapping) - { + { //-------------------- //print out more debug info before crash llinfos << "vertex buffer size: (num verts : num indices) = " << getNumVerts() << " : " << getNumIndices() << llendl ; @@ -1003,12 +1050,13 @@ volatile U8* LLVertexBuffer::mapIndexBuffer(S32 access) else { mMappedIndexData = (U8*) glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB); + stop_glerror(); } - stop_glerror(); } if (!mMappedIndexData) { + log_glerror(); if(!sDisableVBOMapping) { @@ -1094,7 +1142,6 @@ void LLVertexBuffer::unmapBuffer(S32 type) //throw out client data (we won't be using it again) mEmpty = TRUE; mFinal = TRUE; - if(sDisableVBOMapping) { freeClientBuffer() ; @@ -1267,7 +1314,15 @@ void LLVertexBuffer::setBuffer(U32 data_mask, S32 type) glGetIntegerv(GL_ARRAY_BUFFER_BINDING_ARB, &buff); if ((GLuint)buff != mGLBuffer) { - llerrs << "Invalid GL vertex buffer bound: " << buff << llendl; + if (gDebugSession) + { + error = TRUE; + gFailLog << "Invalid GL vertex buffer bound: " << buff << std::endl; + } + else + { + llerrs << "Invalid GL vertex buffer bound: " << buff << llendl; + } } if (mGLIndices) @@ -1275,7 +1330,15 @@ void LLVertexBuffer::setBuffer(U32 data_mask, S32 type) glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB, &buff); if ((GLuint)buff != mGLIndices) { - llerrs << "Invalid GL index buffer bound: " << buff << llendl; + if (gDebugSession) + { + error = TRUE; + gFailLog << "Invalid GL index buffer bound: " << buff << std::endl; + } + else + { + llerrs << "Invalid GL index buffer bound: " << buff << llendl; + } } } } @@ -1288,7 +1351,15 @@ void LLVertexBuffer::setBuffer(U32 data_mask, S32 type) glGetIntegerv(GL_ARRAY_BUFFER_BINDING_ARB, &buff); if ((GLuint)buff != mGLBuffer) { - llerrs << "Invalid GL vertex buffer bound: " << buff << llendl; + if (gDebugSession) + { + error = TRUE; + gFailLog << "Invalid GL vertex buffer bound: " << std::endl; + } + else + { + llerrs << "Invalid GL vertex buffer bound: " << buff << llendl; + } } if (mGLIndices != 0) @@ -1296,7 +1367,15 @@ void LLVertexBuffer::setBuffer(U32 data_mask, S32 type) glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB, &buff); if ((GLuint)buff != mGLIndices) { - llerrs << "Invalid GL index buffer bound: " << buff << llendl; + if (gDebugSession) + { + error = TRUE; + gFailLog << "Invalid GL index buffer bound: "<< std::endl; + } + else + { + llerrs << "Invalid GL index buffer bound: " << buff << llendl; + } } } } @@ -1319,13 +1398,21 @@ void LLVertexBuffer::setBuffer(U32 data_mask, S32 type) if (data_mask != 0) { - llerrs << "Buffer set for rendering before being filled after resize." << llendl; + if (gDebugSession) + { + error = TRUE; + gFailLog << "Buffer set for rendering before being filled after resize." << std::endl; + } + else + { + llerrs << "Buffer set for rendering before being filled after resize." << llendl; + } } } if (error) { - llerrs << "LLVertexBuffer::mapBuffer failed" << llendl; + ll_fail("LLVertexBuffer::mapBuffer failed"); } unmapBuffer(type); } diff --git a/indra/newview/app_settings/cmd_line.xml b/indra/newview/app_settings/cmd_line.xml index 354d40279..6bed5a829 100644 --- a/indra/newview/app_settings/cmd_line.xml +++ b/indra/newview/app_settings/cmd_line.xml @@ -106,6 +106,14 @@ QuitAfterSeconds + + debugsession + + desc + Run as if RenderDebugGL is TRUE, but log errors until end of session. + map-to + DebugSession + rotate map-to @@ -238,7 +246,7 @@ multiple desc - Allow multple viewers. + Allow multiple viewers. map-to AllowMultipleViewers diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 2f8b41b73..e712c1500 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -589,6 +589,7 @@ bool LLAppViewer::init() LLCurl::initClass(); initThreads(); + LL_INFOS("InitInfo") << "Threads initialized." << LL_ENDL ; ; writeSystemInfo(); @@ -736,12 +737,14 @@ bool LLAppViewer::init() OSMB_OK); return 1; } + LL_INFOS("InitInfo") << "Cache initialization is done." << LL_ENDL ; // // Initialize the window // gGLActive = TRUE; initWindow(); + LL_INFOS("InitInfo") << "Window is initialized." << LL_ENDL ; // initWindow also initializes the Feature List, so now we can initialize this global. LLCubeMap::sUseCubeMaps = LLFeatureManager::getInstance()->isFeatureAvailable("RenderCubeMap"); @@ -784,6 +787,32 @@ bool LLAppViewer::init() return 0; } +#if (_M_IX86_FP > 1 || defined(__SSE2__)) + // Without SSE2 support we will crash almost immediately, warn here. + if (!gSysCPU.hasSSE2()) + { + // can't use an alert here since we're exiting and + // all hell breaks lose. + OSMessageBox( + LLNotifications::instance().getGlobalString("UnsupportedCPUSSE2"), + LLStringUtil::null, + OSMB_OK); + return 0; + } +#else if (_M_IX86_FP == 1 || defined(__SSE__)) + // Without SSE support we will crash almost immediately, warn here. + if (!gSysCPU.hasSSE()) + { + // can't use an alert here since we're exiting and + // all hell breaks lose. + OSMessageBox( + LLNotifications::instance().getGlobalString("UnsupportedCPUSSE"), + LLStringUtil::null, + OSMB_OK); + return 0; + } +#endif + // alert the user if they are using unsupported hardware if(!gSavedSettings.getBOOL("AlertedUnsupportedHardware")) { @@ -874,13 +903,33 @@ bool LLAppViewer::mainLoop() LLMemType mt1(LLMemType::MTYPE_MAIN); LLTimer frameTimer,idleTimer; LLTimer debugTime; + LLFrameTimer memCheckTimer; LLViewerJoystick* joystick(LLViewerJoystick::getInstance()); joystick->setNeedsReset(true); + + const F32 memory_check_interval = 1.0f ; //second + // Handle messages while (!LLApp::isExiting()) { LLFastTimer::reset(); // Should be outside of any timer instances + + //clear call stack records + llclearcallstacks; + + //check memory availability information + { + if(memory_check_interval < memCheckTimer.getElapsedTimeF32()) + { + memCheckTimer.reset() ; + + //update the availability of memory + LLMemoryInfo::getAvailableMemoryKB(mAvailPhysicalMemInKB, mAvailVirtualMemInKB) ; + } + llcallstacks << "Available physical mem(KB): " << mAvailPhysicalMemInKB << llcallstacksendl ; + llcallstacks << "Available virtual mem(KB): " << mAvailVirtualMemInKB << llcallstacksendl ; + } try { LLFastTimer t(LLFastTimer::FTM_FRAME); @@ -914,9 +963,11 @@ bool LLAppViewer::mainLoop() #endif //memory leaking simulation - if(LLFloaterMemLeak::getInstance()) + LLFloaterMemLeak* mem_leak_instance = + LLFloaterMemLeak::getInstance(); + if(mem_leak_instance) { - LLFloaterMemLeak::getInstance()->idle() ; + mem_leak_instance->idle() ; } if (!LLApp::isExiting()) @@ -1079,10 +1130,22 @@ bool LLAppViewer::mainLoop() } catch(std::bad_alloc) { - //stop memory leaking simulation - if(LLFloaterMemLeak::getInstance()) { - LLFloaterMemLeak::getInstance()->stop() ; + llinfos << "Availabe physical memory(KB) at the beginning of the frame: " << mAvailPhysicalMemInKB << llendl ; + llinfos << "Availabe virtual memory(KB) at the beginning of the frame: " << mAvailVirtualMemInKB << llendl ; + + LLMemoryInfo::getAvailableMemoryKB(mAvailPhysicalMemInKB, mAvailVirtualMemInKB) ; + + llinfos << "Current availabe physical memory(KB): " << mAvailPhysicalMemInKB << llendl ; + llinfos << "Current availabe virtual memory(KB): " << mAvailVirtualMemInKB << llendl ; + } + + //stop memory leaking simulation + LLFloaterMemLeak* mem_leak_instance = + LLFloaterMemLeak::getInstance(); + if(mem_leak_instance) + { + mem_leak_instance->stop() ; llwarns << "Bad memory allocation in LLAppViewer::mainLoop()!" << llendl ; } else @@ -1107,9 +1170,11 @@ bool LLAppViewer::mainLoop() llwarns << "Bad memory allocation when saveFinalSnapshot() is called!" << llendl ; //stop memory leaking simulation - if(LLFloaterMemLeak::getInstance()) + LLFloaterMemLeak* mem_leak_instance = + LLFloaterMemLeak::getInstance(); + if(mem_leak_instance) { - LLFloaterMemLeak::getInstance()->stop() ; + mem_leak_instance->stop() ; } } } @@ -1123,6 +1188,21 @@ bool LLAppViewer::mainLoop() return true; } +void LLAppViewer::flushVFSIO() +{ + while (1) + { + S32 pending = LLVFSThread::updateClass(0); + pending += LLLFSThread::updateClass(0); + if (!pending) + { + break; + } + llinfos << "Waiting for pending IO to finish: " << pending << llendflush; + ms_sleep(100); + } +} + extern void cleanup_pose_stand(void); bool LLAppViewer::cleanup() @@ -1235,36 +1315,31 @@ bool LLAppViewer::cleanup() removeCacheFiles("*.dsf"); removeCacheFiles("*.bodypart"); removeCacheFiles("*.clothing"); + // + llinfos << "Cache files removed" << llendflush; */ // - llinfos << "Cache files removed" << llendflush; - cleanup_menus(); // Wait for any pending VFS IO - while (1) - { - S32 pending = LLVFSThread::updateClass(0); - pending += LLLFSThread::updateClass(0); - if (!pending) - { - break; - } - llinfos << "Waiting for pending IO to finish: " << pending << llendflush; - ms_sleep(100); - } - llinfos << "Shutting down." << llendflush; + flushVFSIO(); + llinfos << "Shutting down Views" << llendflush; // Destroy the UI if( gViewerWindow) gViewerWindow->shutdownViews(); + + llinfos << "Cleaning up Selections" << llendflush; + // Clean up selection managers after UI is destroyed, as UI may be observing them. // Clean up before GL is shut down because we might be holding on to objects with texture references LLSelectMgr::cleanupGlobals(); + + llinfos << "Shutting down OpenGL" << llendflush; // Shut down OpenGL if( gViewerWindow) @@ -1279,10 +1354,15 @@ bool LLAppViewer::cleanup() llinfos << "ViewerWindow deleted" << llendflush; } + llinfos << "Cleaning up Keyboard & Joystick" << llendflush; + // viewer UI relies on keyboard so keep it aound until viewer UI isa gone delete gKeyboard; gKeyboard = NULL; + + llinfos << "Cleaning up Objects" << llendflush; + LLViewerObject::cleanupVOClasses(); LLWaterParamManager::cleanupClass(); @@ -1311,6 +1391,8 @@ bool LLAppViewer::cleanup() } LLPrimitive::cleanupVolumeManager(); + llinfos << "Additional Cleanup..." << llendflush; + LLViewerParcelMgr::cleanupGlobals(); // *Note: this is where gViewerStats used to be deleted. @@ -1330,8 +1412,10 @@ bool LLAppViewer::cleanup() // Also after shutting down the messaging system since it has VFS dependencies // + llinfos << "Cleaning up VFS" << llendflush; LLVFile::cleanupClass(); - llinfos << "VFS cleaned up" << llendflush; + + llinfos << "Saving Data" << llendflush; // Quitting with "Remember Password" turned off should always stomp your // saved password, whether or not you successfully logged in. JC @@ -1347,10 +1431,17 @@ bool LLAppViewer::cleanup() // save their rects on delete. gSavedSettings.saveToFile(gSavedSettings.getString("ClientSettingsFile"), TRUE); - // PerAccountSettingsFile should be empty if no use has been logged on. + // PerAccountSettingsFile should be empty if no user has been logged on. // *FIX:Mani This should get really saved in a "logoff" mode. - gSavedPerAccountSettings.saveToFile(gSavedSettings.getString("PerAccountSettingsFile"), TRUE); - llinfos << "Saved settings" << llendflush; + if (gSavedSettings.getString("PerAccountSettingsFile").empty()) + { + llinfos << "Not saving per-account settings; don't know the account name yet." << llendl; + } + else + { + gSavedPerAccountSettings.saveToFile(gSavedSettings.getString("PerAccountSettingsFile"), TRUE); + llinfos << "Saved settings" << llendflush; + } std::string crash_settings_filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, CRASH_SETTINGS_FILE); // save all settings, even if equals defaults @@ -1383,6 +1474,11 @@ bool LLAppViewer::cleanup() removeCacheFiles("*.dsf"); removeCacheFiles("*.bodypart"); removeCacheFiles("*.clothing"); + llinfos << "Cache files removed" << llendflush; + } + else + { + llinfos << "Not removing cache files. Other viewer instance detected." << llendflush; } // @@ -1391,6 +1487,8 @@ bool LLAppViewer::cleanup() // Stop the plugin read thread if it's running. LLPluginProcessParent::setUseReadThread(false); + llinfos << "Shutting down Threads" << llendflush; + // Let threads finish LLTimer idleTimer; idleTimer.reset(); @@ -1428,6 +1526,9 @@ bool LLAppViewer::cleanup() delete sImageDecodeThread; sImageDecodeThread = NULL; + + llinfos << "Cleaning up Media and Textures" << llendflush; + //Note: //LLViewerMedia::cleanupClass() has to be put before gTextureList.shutdown() //because some new image might be generated during cleaning up media. --bao @@ -1490,7 +1591,10 @@ bool LLAppViewer::cleanup() llinfos << "File launched." << llendflush; } - llinfos << "Goodbye" << llendflush; + + ll_close_fail_log(); + + llinfos << "Goodbye!" << llendflush; // return 0; return true; @@ -1958,6 +2062,14 @@ bool LLAppViewer::initConfiguration() { gCrashOnStartup = TRUE; } + + if (clp.hasOption("debugsession")) + { + gDebugSession = TRUE; + gDebugGL = TRUE; + + ll_init_fail_log(gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "test_failures.log")); + } // Handle slurl use. NOTE: Don't let SL-55321 reappear. @@ -2363,7 +2475,12 @@ void LLAppViewer::writeSystemInfo() { gDebugInfo["SLLog"] = LLError::logFileName(); - + gDebugInfo["ClientInfo"]["Name"] = LL_CHANNEL; + + gDebugInfo["ClientInfo"]["MajorVersion"] = LL_VERSION_MAJOR; + gDebugInfo["ClientInfo"]["MinorVersion"] = LL_VERSION_MINOR; + gDebugInfo["ClientInfo"]["PatchVersion"] = LL_VERSION_PATCH; + gDebugInfo["ClientInfo"]["BuildVersion"] = LL_VERSION_BUILD; gDebugInfo["CAFilename"] = gDirUtilp->getCAFile(); @@ -2428,6 +2545,8 @@ void LLAppViewer::handleViewerCrash() { llinfos << "Handle viewer crash entry." << llendl; + llinfos << "Last render pool type: " << LLPipeline::sCurRenderPoolType << llendl ; + //print out recorded call stacks if there are any. LLError::LLCallStacks::print(); @@ -2873,45 +2992,54 @@ void LLAppViewer::migrateCacheDirectory() #endif // LL_WINDOWS || LL_DARWIN } +//static +U32 LLAppViewer::getTextureCacheVersion() +{ + //viewer texture cache version, change if the texture cache format changes. + static const U32 TEXTURE_CACHE_VERSION = 7; + + return TEXTURE_CACHE_VERSION ; +} bool LLAppViewer::initCache() { mPurgeCache = false; BOOL read_only = mSecondInstance ? TRUE : FALSE; LLAppViewer::getTextureCache()->setReadOnly(read_only); - BOOL texture_cache_mismatch = FALSE ; - static const S32 cache_version = 7; - if (gSavedSettings.getS32("LocalCacheVersion") != cache_version) + bool texture_cache_mismatch = false; + if (gSavedSettings.getS32("LocalCacheVersion") != LLAppViewer::getTextureCacheVersion()) { - texture_cache_mismatch = TRUE ; - if (!read_only) + texture_cache_mismatch = true; + if(!read_only) { - gSavedSettings.setS32("LocalCacheVersion", cache_version); + gSavedSettings.setS32("LocalCacheVersion", LLAppViewer::getTextureCacheVersion()); } } if (!read_only) { - // Purge cache if user requested it - if (gSavedSettings.getBOOL("PurgeCacheOnStartup") || - gSavedSettings.getBOOL("PurgeCacheOnNextStartup")) - { - gSavedSettings.setBOOL("PurgeCacheOnNextStartup", false); - mPurgeCache = true; - } + // Purge cache if user requested it + if (gSavedSettings.getBOOL("PurgeCacheOnStartup") || + gSavedSettings.getBOOL("PurgeCacheOnNextStartup")) + { + gSavedSettings.setBOOL("PurgeCacheOnNextStartup", false); + mPurgeCache = true; + // STORM-1141 force purgeAllTextures to get called to prevent a crash here. -brad + texture_cache_mismatch = true; + } - // We have moved the location of the cache directory over time. - migrateCacheDirectory(); + // We have moved the location of the cache directory over time. + migrateCacheDirectory(); - // Setup and verify the cache location - std::string cache_location = gSavedSettings.getString("CacheLocation"); - std::string new_cache_location = gSavedSettings.getString("NewCacheLocation"); - if (new_cache_location != cache_location) - { - gDirUtilp->setCacheDir(gSavedSettings.getString("CacheLocation")); - purgeCache(); // purge old cache - gSavedSettings.setString("CacheLocation", new_cache_location); - } + // Setup and verify the cache location + std::string cache_location = gSavedSettings.getString("CacheLocation"); + std::string new_cache_location = gSavedSettings.getString("NewCacheLocation"); + if (new_cache_location != cache_location) + { + gDirUtilp->setCacheDir(gSavedSettings.getString("CacheLocation")); + purgeCache(); // purge old cache + gSavedSettings.setString("CacheLocation", new_cache_location); + } } if (!gDirUtilp->setCacheDir(gSavedSettings.getString("CacheLocation"))) @@ -3238,6 +3366,7 @@ void LLAppViewer::loadNameCache() // Phoenix: Wolfspirit: Loads the Display Name Cache. And set if we are using Display Names. std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "avatar_name_cache.xml"); + LL_INFOS("AvNameCache") << filename << LL_ENDL; llifstream name_cache_stream(filename); if(name_cache_stream.is_open()) { @@ -3922,7 +4051,6 @@ void LLAppViewer::idleNetwork() llpushcallstacks ; LLTimer check_message_timer; // Read all available packets from network - stop_glerror(); const S64 frame_count = gFrameCount; // U32->S64 F32 total_time = 0.0f; while (gMessageSystem->checkAllMessages(frame_count, gServicePump)) @@ -3934,7 +4062,6 @@ void LLAppViewer::idleNetwork() // server going down, so this is OK. break; } - stop_glerror(); total_decoded++; gPacketsIn++; @@ -3954,6 +4081,7 @@ void LLAppViewer::idleNetwork() break; #endif } + // Handle per-frame message system processing. gMessageSystem->processAcks(); @@ -3974,8 +4102,6 @@ void LLAppViewer::idleNetwork() // we want to clear the control after sending out all necessary agent updates gAgent.resetControlFlags(); - stop_glerror(); - // Decode enqueued messages... S32 remaining_possible_decodes = MESSAGE_MAX_PER_FRAME - total_decoded; @@ -4130,7 +4256,7 @@ void LLAppViewer::forceErrorBadMemoryAccess() return; } -void LLAppViewer::forceErrorInifiniteLoop() +void LLAppViewer::forceErrorInfiniteLoop() { while(true) { diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h index 933d4150a..24bb2cd4a 100644 --- a/indra/newview/llappviewer.h +++ b/indra/newview/llappviewer.h @@ -64,6 +64,7 @@ public: virtual bool mainLoop(); // Override for the application main loop. Needs to at least gracefully notice the QUITTING state and exit. // Application control + void flushVFSIO(); // waits for vfs transfers to complete void forceQuit(); // Puts the viewer into 'shutting down without error' mode. void requestQuit(); // Request a quit. A kinder, gentler quit. void userQuit(); // The users asks to quit. Confirm, then requestQuit() @@ -95,6 +96,7 @@ public: static LLImageDecodeThread* getImageDecodeThread() { return sImageDecodeThread; } static LLTextureFetch* getTextureFetch() { return sTextureFetch; } + static U32 getTextureCacheVersion(); const std::string& getSerialNumber() { return mSerialNumber; } bool getPurgeCache() const { return mPurgeCache; } @@ -125,7 +127,7 @@ public: virtual void forceErrorLLError(); virtual void forceErrorBreakpoint(); virtual void forceErrorBadMemoryAccess(); - virtual void forceErrorInifiniteLoop(); + virtual void forceErrorInfiniteLoop(); virtual void forceErrorSoftwareException(); virtual void forceErrorDriverCrash(); @@ -197,8 +199,9 @@ private: void idle(); void idleShutdown(); + // update avatar SLID and display name caches + void idleNameCache(); void idleNetwork(); - void idleNameCache(); void sendLogoutRequest(); void disconnectViewer(); @@ -243,6 +246,10 @@ private: bool mAgentRegionLastAlive; LLUUID mAgentRegionLastID; + + U32 mAvailPhysicalMemInKB ; + U32 mAvailVirtualMemInKB ; + public: //some information for updater typedef struct diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp index 051a5cdaa..b5a185a0c 100644 --- a/indra/newview/llappviewerwin32.cpp +++ b/indra/newview/llappviewerwin32.cpp @@ -244,6 +244,8 @@ int APIENTRY WINMAIN(HINSTANCE hInstance, } #endif + gGLActive = TRUE; + viewer_app_ptr->cleanup(); #if WINDOWS_CRT_MEM_CHECKS @@ -498,7 +500,11 @@ bool LLAppViewerWin32::initHardwareTest() LL_WARNS("AppInit") << " Someone took over my exception handler (post hardware probe)!" << LL_ENDL; } - gGLManager.mVRAM = gDXHardware.getVRAM(); + if (gGLManager.mVRAM == 0) + { + gGLManager.mVRAM = gDXHardware.getVRAM(); + } + LL_INFOS("AppInit") << "Detected VRAM: " << gGLManager.mVRAM << LL_ENDL; return true; diff --git a/indra/newview/lldrawable.cpp b/indra/newview/lldrawable.cpp index fce802f77..dd79a8918 100644 --- a/indra/newview/lldrawable.cpp +++ b/indra/newview/lldrawable.cpp @@ -118,6 +118,10 @@ void LLDrawable::initClass() void LLDrawable::destroy() { + if (gDebugGL) + { + gPipeline.checkReferences(this); + } if (isDead()) { sNumZombieDrawables--; diff --git a/indra/newview/lldrawpoolsky.cpp b/indra/newview/lldrawpoolsky.cpp index 4d34f7cd2..b5cc0d31d 100644 --- a/indra/newview/lldrawpoolsky.cpp +++ b/indra/newview/lldrawpoolsky.cpp @@ -69,6 +69,7 @@ void LLDrawPoolSky::prerender() void LLDrawPoolSky::render(S32 pass) { + gGL.flush(); if (mDrawFace.empty()) { return; diff --git a/indra/newview/lldrawpoolwater.cpp b/indra/newview/lldrawpoolwater.cpp index 69e811905..2b93af7b1 100644 --- a/indra/newview/lldrawpoolwater.cpp +++ b/indra/newview/lldrawpoolwater.cpp @@ -45,7 +45,6 @@ #include "lldrawable.h" #include "llface.h" #include "llsky.h" -#include "llviewercamera.h" // to get OGL_TO_CFR_ROTATION #include "llviewertexturelist.h" #include "llviewerregion.h" #include "llvosky.h" diff --git a/indra/newview/lldrawpoolwlsky.cpp b/indra/newview/lldrawpoolwlsky.cpp index f72da554c..4a6321a69 100644 --- a/indra/newview/lldrawpoolwlsky.cpp +++ b/indra/newview/lldrawpoolwlsky.cpp @@ -42,7 +42,6 @@ #include "llwlparammanager.h" #include "llsky.h" #include "llvowlsky.h" -#include "llagent.h" #include "llviewerregion.h" #include "llface.h" #include "llrender.h" diff --git a/indra/newview/llemote.cpp b/indra/newview/llemote.cpp index bacf3daf5..c83846215 100644 --- a/indra/newview/llemote.cpp +++ b/indra/newview/llemote.cpp @@ -39,7 +39,6 @@ #include "llcharacter.h" #include "m3math.h" #include "llvoavatar.h" -#include "llagent.h" //----------------------------------------------------------------------------- // Constants diff --git a/indra/newview/lleventnotifier.cpp b/indra/newview/lleventnotifier.cpp index 63cf2b16a..1e915a266 100644 --- a/indra/newview/lleventnotifier.cpp +++ b/indra/newview/lleventnotifier.cpp @@ -117,7 +117,6 @@ void LLEventNotifier::load(const LLUserAuth::options_t& event_options) } } - BOOL LLEventNotifier::hasNotification(const U32 event_id) { if (mEventNotifications.find(event_id) != mEventNotifications.end()) @@ -127,7 +126,6 @@ BOOL LLEventNotifier::hasNotification(const U32 event_id) return FALSE; } - void LLEventNotifier::add(LLEventInfo &event_info) { // We need to tell the simulator that we want to pay attention to diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp index 6d66cd4c3..9c7420898 100644 --- a/indra/newview/llface.cpp +++ b/indra/newview/llface.cpp @@ -184,6 +184,11 @@ void LLFace::init(LLDrawable* drawablep, LLViewerObject* objp) void LLFace::destroy() { + if (gDebugGL) + { + gPipeline.checkReferences(this); + } + if(mTexture.notNull()) { mTexture->removeFace(this) ; @@ -952,7 +957,7 @@ bool LLFace::canRenderAsMask() ) // do we want masks at all? && (te->getColor().mV[3] == 1.0f) && // can't treat as mask if we have face alpha - !(LLPipeline::sRenderDeferred && te->getFullbright()) && // hack: alpha masking renders fullbright faces invisible in deferred rendering mode, need to figure out why - for now, avoid + //!(LLPipeline::sRenderDeferred && te->getFullbright()) && // hack: alpha masking renders fullbright faces invisible in deferred rendering mode, need to figure out why - for now, avoid (te->getGlow() == 0.f) && // glowing masks are hard to implement - don't mask getTexture()->getIsAlphaMask() // texture actually qualifies for masking (lazily recalculated but expensive) diff --git a/indra/newview/llfeaturemanager.cpp b/indra/newview/llfeaturemanager.cpp index 9614f639d..ce1c00d73 100644 --- a/indra/newview/llfeaturemanager.cpp +++ b/indra/newview/llfeaturemanager.cpp @@ -207,7 +207,7 @@ BOOL LLFeatureManager::maskFeatures(const std::string& name) LL_DEBUGS("RenderInit") << "Unknown feature mask " << name << LL_ENDL; return FALSE; } - LL_DEBUGS("RenderInit") << "Applying Feature Mask: " << name << LL_ENDL; + LL_INFOS("RenderInit") << "Applying GPU Feature list: " << name << LL_ENDL; return maskList(*maskp); } @@ -221,22 +221,33 @@ BOOL LLFeatureManager::loadFeatureTables() mSkippedFeatures.insert("RenderVBOEnable"); mSkippedFeatures.insert("RenderFogRatio"); - std::string data_path = gDirUtilp->getAppRODataDir(); + // first table is install with app + std::string app_path = gDirUtilp->getAppRODataDir(); + app_path += gDirUtilp->getDirDelimiter(); - data_path += gDirUtilp->getDirDelimiter(); + std::string filename = FEATURE_TABLE_FILENAME; - data_path += FEATURE_TABLE_FILENAME; - lldebugs << "Looking for feature table in " << data_path << llendl; + + app_path += filename; + + + return parseFeatureTable(app_path); +} + + +BOOL LLFeatureManager::parseFeatureTable(std::string filename) +{ + llinfos << "Looking for feature table in " << filename << llendl; llifstream file; std::string name; U32 version; - file.open(data_path); /*Flawfinder: ignore*/ + file.open(filename); /*Flawfinder: ignore*/ if (!file) { - LL_WARNS("RenderInit") << "Unable to open feature table!" << LL_ENDL; + LL_WARNS("RenderInit") << "Unable to open feature table " << filename << LL_ENDL; return FALSE; } @@ -245,7 +256,7 @@ BOOL LLFeatureManager::loadFeatureTables() file >> version; if (name != "version") { - LL_WARNS("RenderInit") << data_path << " does not appear to be a valid feature table!" << LL_ENDL; + LL_WARNS("RenderInit") << filename << " does not appear to be a valid feature table!" << LL_ENDL; return FALSE; } @@ -284,6 +295,7 @@ BOOL LLFeatureManager::loadFeatureTables() if (!flp) { LL_ERRS("RenderInit") << "Specified parameter before keyword!" << LL_ENDL; + return FALSE; } S32 available; F32 recommended; @@ -298,34 +310,41 @@ BOOL LLFeatureManager::loadFeatureTables() void LLFeatureManager::loadGPUClass() { - std::string data_path = gDirUtilp->getAppRODataDir(); - - data_path += gDirUtilp->getDirDelimiter(); - - data_path += GPU_TABLE_FILENAME; - // defaults mGPUClass = GPU_CLASS_UNKNOWN; mGPUString = gGLManager.getRawGLString(); mGPUSupported = FALSE; + // first table is in the app dir + std::string app_path = gDirUtilp->getAppRODataDir(); + app_path += gDirUtilp->getDirDelimiter(); + app_path += GPU_TABLE_FILENAME; + parseGPUTable(app_path); +} + + +void LLFeatureManager::parseGPUTable(std::string filename) +{ llifstream file; - file.open(data_path); /*Flawfinder: ignore*/ + file.open(filename); if (!file) { - LL_WARNS("RenderInit") << "Unable to open GPU table: " << data_path << "!" << LL_ENDL; + LL_WARNS("RenderInit") << "Unable to open GPU table: " << filename << "!" << LL_ENDL; return; } - std::string renderer = gGLManager.getRawGLString(); + std::string rawRenderer = gGLManager.getRawGLString(); + std::string renderer = rawRenderer; for (std::string::iterator i = renderer.begin(); i != renderer.end(); ++i) { *i = tolower(*i); } - - while (!file.eof()) + + bool gpuFound; + U32 lineNumber; + for (gpuFound = false, lineNumber = 0; !gpuFound && !file.eof(); lineNumber++) { char buffer[MAX_STRING]; /*Flawfinder: ignore*/ buffer[0] = 0; @@ -372,6 +391,7 @@ void LLFeatureManager::loadGPUClass() if (label.empty() || expr.empty() || cls.empty() || supported.empty()) { + LL_WARNS("RenderInit") << "invald gpu_table.txt:" << lineNumber << ": '" << buffer << "'" << LL_ENDL; continue; } @@ -385,18 +405,26 @@ void LLFeatureManager::loadGPUClass() if(boost::regex_search(renderer, re)) { // if we found it, stop! - file.close(); - LL_INFOS("RenderInit") << "GPU is " << label << llendl; + gpuFound = true; mGPUString = label; mGPUClass = (EGPUClass) strtol(cls.c_str(), NULL, 10); mGPUSupported = (BOOL) strtol(supported.c_str(), NULL, 10); - file.close(); - return; } } file.close(); - LL_WARNS("RenderInit") << "Couldn't match GPU to a class: " << gGLManager.getRawGLString() << LL_ENDL; + if ( gpuFound ) + { + LL_INFOS("RenderInit") << "GPU '" << rawRenderer << "' recognized as '" << mGPUString << "'" << LL_ENDL; + if (!mGPUSupported) + { + LL_INFOS("RenderInit") << "GPU '" << mGPUString << "' is not supported." << LL_ENDL; + } + } + else + { + LL_WARNS("RenderInit") << "GPU '" << rawRenderer << "' not recognized" << LL_ENDL; + } } void LLFeatureManager::cleanupFeatureTables() @@ -579,6 +607,10 @@ void LLFeatureManager::applyBaseMasks() { maskFeatures("ATI"); } + if (gGLManager.mHasATIMemInfo && gGLManager.mVRAM < 256) + { + maskFeatures("ATIVramLT256"); + } if (gGLManager.mATIOldDriver) { maskFeatures("ATIOldDriver"); @@ -595,6 +627,14 @@ void LLFeatureManager::applyBaseMasks() { maskFeatures("OpenGLPre15"); } + if (gGLManager.mGLVersion < 3.f) + { + maskFeatures("OpenGLPre30"); + } + if (gGLManager.mNumTextureImageUnits <= 8) + { + maskFeatures("TexUnit8orLess"); + } // now mask by gpu string // Replaces ' ' with '_' in mGPUString to deal with inability for parser to handle spaces diff --git a/indra/newview/llfeaturemanager.h b/indra/newview/llfeaturemanager.h index 537bf0c6a..a9cb33598 100644 --- a/indra/newview/llfeaturemanager.h +++ b/indra/newview/llfeaturemanager.h @@ -98,8 +98,14 @@ protected: class LLFeatureManager : public LLFeatureList, public LLSingleton { public: - LLFeatureManager() : - LLFeatureList("default"), mInited(FALSE), mTableVersion(0), mSafe(FALSE), mGPUClass(GPU_CLASS_UNKNOWN) + LLFeatureManager() + : LLFeatureList("default"), + + mInited(FALSE), + mTableVersion(0), + mSafe(FALSE), + mGPUClass(GPU_CLASS_UNKNOWN), + mGPUSupported(FALSE) { } ~LLFeatureManager() {cleanupFeatureTables();} @@ -139,6 +145,8 @@ public: protected: void loadGPUClass(); + BOOL parseFeatureTable(std::string filename); + void parseGPUTable(std::string filename); void initBaseMask(); diff --git a/indra/newview/llphysicsmotion.cpp b/indra/newview/llphysicsmotion.cpp index 581043951..af775f59f 100644 --- a/indra/newview/llphysicsmotion.cpp +++ b/indra/newview/llphysicsmotion.cpp @@ -131,7 +131,8 @@ protected: { return sDefaultController[controller_key]; } - return mCharacter->getVisualParamWeight((*entry).second.c_str()); + const std::string& param_name = (*entry).second.c_str(); + return mCharacter->getVisualParamWeight(param_name.c_str()); } void setParamValue(LLViewerVisualParam *param, const F32 new_value_local, diff --git a/indra/newview/llsky.cpp b/indra/newview/llsky.cpp index b6f4dedbd..de99cb86f 100644 --- a/indra/newview/llsky.cpp +++ b/indra/newview/llsky.cpp @@ -52,7 +52,6 @@ #include "llviewerobject.h" #include "llviewercamera.h" #include "pipeline.h" -#include "llagent.h" #include "lldrawpool.h" #include "llvosky.h" diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp index 9546e3b04..e5d22fc22 100644 --- a/indra/newview/llspatialpartition.cpp +++ b/indra/newview/llspatialpartition.cpp @@ -286,6 +286,10 @@ LLSpatialGroup::~LLSpatialGroup() llerrs << "Illegal deletion of LLSpatialGroup!" << llendl; }*/ + if (gDebugGL) + { + gPipeline.checkReferences(this); + } if (isState(DEAD)) { sZombieGroups--; @@ -3314,6 +3318,11 @@ LLDrawInfo::~LLDrawInfo() { mFace->setDrawInfo(NULL); } + + if (gDebugGL) + { + gPipeline.checkReferences(this); + } } LLVertexBuffer* LLGeometryManager::createVertexBuffer(U32 type_mask, U32 usage) diff --git a/indra/newview/llurlhistory.cpp b/indra/newview/llurlhistory.cpp index a93cc2ff7..5f17aef78 100644 --- a/indra/newview/llurlhistory.cpp +++ b/indra/newview/llurlhistory.cpp @@ -77,7 +77,7 @@ bool LLURLHistory::saveFile(const std::string& filename) std::string temp_str = gDirUtilp->getLindenUserDir(true); if( temp_str.empty() ) { - llwarns << "Can't save. No user directory set." << llendl; + llinfos << "Can't save URL history - no user directory set yet." << llendl; return false; } diff --git a/indra/newview/llurlwhitelist.cpp b/indra/newview/llurlwhitelist.cpp index da69039cf..46bc9276c 100644 --- a/indra/newview/llurlwhitelist.cpp +++ b/indra/newview/llurlwhitelist.cpp @@ -121,6 +121,12 @@ bool LLUrlWhiteList::save () // build filename for each user std::string resolvedFilename = gDirUtilp->getExpandedFilename ( LL_PATH_PER_SL_ACCOUNT, mFilename ); + if (resolvedFilename.empty()) + { + llinfos << "No per-user dir for saving URL whitelist - presumably not logged in yet. Skipping." << llendl; + return false; + } + // open a file for writing llofstream file ( resolvedFilename ); if ( file.is_open () ) diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp index 9d8d029d6..9c563fac4 100644 --- a/indra/newview/llviewerdisplay.cpp +++ b/indra/newview/llviewerdisplay.cpp @@ -953,9 +953,11 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot, boo render_ui(); } - gPipeline.rebuildGroups(); LLSpatialGroup::sNoDelete = FALSE; + gPipeline.clearReferences(); + + gPipeline.rebuildGroups(); } LLAppViewer::instance()->pingMainloopTimeout("Display:FrameStats"); @@ -1151,10 +1153,14 @@ void render_ui(F32 zoom_factor, int subfield, bool tiling) { LLGLState::checkStates(); - glPushMatrix(); - glLoadMatrixd(gGLLastModelView); glh::matrix4f saved_view = glh_get_current_modelview(); - glh_set_current_modelview(glh_copy_matrix(gGLLastModelView)); + + if (!gSnapshot) + { + glPushMatrix(); + glLoadMatrixd(gGLLastModelView); + glh_set_current_modelview(glh_copy_matrix(gGLLastModelView)); + } { BOOL to_texture = gPipeline.canUseVertexShaders() && @@ -1212,8 +1218,11 @@ void render_ui(F32 zoom_factor, int subfield, bool tiling) LLVertexBuffer::unbind(); } - glh_set_current_modelview(saved_view); - glPopMatrix(); + if (!gSnapshot) + { + glh_set_current_modelview(saved_view); + glPopMatrix(); + } if (gDisplaySwapBuffers) { diff --git a/indra/newview/llviewerjointattachment.h b/indra/newview/llviewerjointattachment.h index 269f7158b..7ca508a3c 100644 --- a/indra/newview/llviewerjointattachment.h +++ b/indra/newview/llviewerjointattachment.h @@ -71,7 +71,7 @@ public: void setPieSlice(S32 pie_slice) { mPieSlice = pie_slice; } void setVisibleInFirstPerson(BOOL visibility) { mVisibleInFirst = visibility; } - BOOL getVisibleInFirstPerson() { return mVisibleInFirst; } + BOOL getVisibleInFirstPerson() const { return mVisibleInFirst; } void setGroup(S32 group) { mGroup = group; } void setOriginalPosition(LLVector3 &position); void setAttachmentVisibility(BOOL visible); diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 871f718bd..61c64db32 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -8966,7 +8966,7 @@ void force_error_bad_memory_access(void *) void force_error_infinite_loop(void *) { - LLAppViewer::instance()->forceErrorInifiniteLoop(); + LLAppViewer::instance()->forceErrorInfiniteLoop(); } void force_error_software_exception(void *) diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index e341631a8..d122e012c 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -4299,7 +4299,6 @@ void process_object_update(LLMessageSystem *mesgsys, void **user_data) // Update the object... gObjectList.processObjectUpdate(mesgsys, user_data, OUT_FULL); - stop_glerror(); } void process_compressed_object_update(LLMessageSystem *mesgsys, void **user_data) @@ -4317,7 +4316,6 @@ void process_compressed_object_update(LLMessageSystem *mesgsys, void **user_data // Update the object... gObjectList.processCompressedObjectUpdate(mesgsys, user_data, OUT_FULL_COMPRESSED); - stop_glerror(); } void process_cached_object_update(LLMessageSystem *mesgsys, void **user_data) @@ -4335,7 +4333,6 @@ void process_cached_object_update(LLMessageSystem *mesgsys, void **user_data) // Update the object... gObjectList.processCachedObjectUpdate(mesgsys, user_data, OUT_FULL_CACHED); - stop_glerror(); } diff --git a/indra/newview/llviewerobjectlist.cpp b/indra/newview/llviewerobjectlist.cpp index 6fe2e4b18..94e519604 100644 --- a/indra/newview/llviewerobjectlist.cpp +++ b/indra/newview/llviewerobjectlist.cpp @@ -957,7 +957,8 @@ void LLViewerObjectList::killAllObjects() objectp = *iter; killObject(objectp); - llassert(objectp->isDead()); + // Object must be dead, or it's the LLVOAvatarSelf which never dies. + llassert((objectp == gAgent.getAvatarObject()) || objectp->isDead()); } cleanDeadObjects(FALSE); diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index e329e4560..92f8df217 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -106,6 +106,26 @@ #include "rlvhandler.h" // [/RLVa:KB] +void check_stack_depth(S32 stack_depth) +{ + if (gDebugGL || gDebugSession) + { + GLint depth; + glGetIntegerv(GL_MODELVIEW_STACK_DEPTH, &depth); + if (depth != stack_depth) + { + if (gDebugSession) + { + ll_fail("GL matrix stack corrupted."); + } + else + { + llerrs << "GL matrix stack corrupted!" << llendl; + } + } + } +} + #ifdef _DEBUG // Debug indices is disabled for now for debug performance - djs 4/24/02 //#define DEBUG_INDICES @@ -537,7 +557,13 @@ void LLPipeline::allocateScreenBuffer(U32 resX, U32 resY) addDeferredAttachments(mDeferredScreen); mScreen.allocate(resX, resY, format, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE); + +#if LL_DARWIN + // As of OS X 10.6.7, Apple doesn't support multiple color formats in a single FBO + mEdgeMap.allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE); +#else mEdgeMap.allocate(resX, resY, GL_ALPHA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE); +#endif if (shadow_detail > 0 || ssao) { //only need mDeferredLight[0] for shadows OR ssao @@ -562,7 +588,12 @@ void LLPipeline::allocateScreenBuffer(U32 resX, U32 resY) mDeferredLight[2].allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE); for (U32 i = 0; i < 2; i++) { +#if LL_DARWIN + // As of OS X 10.6.7, Apple doesn't support multiple color formats in a single FBO + mGIMapPost[i].allocate(resX,resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE); +#else mGIMapPost[i].allocate(resX,resY, GL_RGB, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE); +#endif } } else @@ -577,9 +608,13 @@ void LLPipeline::allocateScreenBuffer(U32 resX, U32 resY) F32 scale = gSavedSettings.getF32("RenderShadowResolutionScale"); +#if LL_DARWIN + U32 shadow_fmt = 0; +#else //HACK: make alpha masking work on ATI depth shadows (work around for ATI driver bug) //TO-DO: Test if this is actually needed. U32 shadow_fmt = gGLManager.mIsATI ? GL_ALPHA : 0; +#endif if (shadow_detail > 0) { //allocate 4 sun shadow maps @@ -1532,6 +1567,184 @@ void LLPipeline::grabReferences(LLCullResult& result) sCull = &result; } +void LLPipeline::clearReferences() +{ + sCull = NULL; +} + +void check_references(LLSpatialGroup* group, LLDrawable* drawable) +{ + for (LLSpatialGroup::element_iter i = group->getData().begin(); i != group->getData().end(); ++i) + { + if (drawable == *i) + { + llerrs << "LLDrawable deleted while actively reference by LLPipeline." << llendl; + } + } +} + +void check_references(LLDrawable* drawable, LLFace* face) +{ + for (S32 i = 0; i < drawable->getNumFaces(); ++i) + { + if (drawable->getFace(i) == face) + { + llerrs << "LLFace deleted while actively referenced by LLPipeline." << llendl; + } + } +} + +void check_references(LLSpatialGroup* group, LLFace* face) +{ + for (LLSpatialGroup::element_iter i = group->getData().begin(); i != group->getData().end(); ++i) + { + LLDrawable* drawable = *i; + check_references(drawable, face); + } +} + +void LLPipeline::checkReferences(LLFace* face) +{ +#if 0 + if (sCull) + { + for (LLCullResult::sg_list_t::iterator iter = sCull->beginVisibleGroups(); iter != sCull->endVisibleGroups(); ++iter) + { + LLSpatialGroup* group = *iter; + check_references(group, face); + } + + for (LLCullResult::sg_list_t::iterator iter = sCull->beginAlphaGroups(); iter != sCull->endAlphaGroups(); ++iter) + { + LLSpatialGroup* group = *iter; + check_references(group, face); + } + + for (LLCullResult::sg_list_t::iterator iter = sCull->beginDrawableGroups(); iter != sCull->endDrawableGroups(); ++iter) + { + LLSpatialGroup* group = *iter; + check_references(group, face); + } + + for (LLCullResult::drawable_list_t::iterator iter = sCull->beginVisibleList(); iter != sCull->endVisibleList(); ++iter) + { + LLDrawable* drawable = *iter; + check_references(drawable, face); + } + } +#endif +} + +void LLPipeline::checkReferences(LLDrawable* drawable) +{ +#if 0 + if (sCull) + { + for (LLCullResult::sg_list_t::iterator iter = sCull->beginVisibleGroups(); iter != sCull->endVisibleGroups(); ++iter) + { + LLSpatialGroup* group = *iter; + check_references(group, drawable); + } + + for (LLCullResult::sg_list_t::iterator iter = sCull->beginAlphaGroups(); iter != sCull->endAlphaGroups(); ++iter) + { + LLSpatialGroup* group = *iter; + check_references(group, drawable); + } + + for (LLCullResult::sg_list_t::iterator iter = sCull->beginDrawableGroups(); iter != sCull->endDrawableGroups(); ++iter) + { + LLSpatialGroup* group = *iter; + check_references(group, drawable); + } + + for (LLCullResult::drawable_list_t::iterator iter = sCull->beginVisibleList(); iter != sCull->endVisibleList(); ++iter) + { + if (drawable == *iter) + { + llerrs << "LLDrawable deleted while actively referenced by LLPipeline." << llendl; + } + } + } +#endif +} + +void check_references(LLSpatialGroup* group, LLDrawInfo* draw_info) +{ + for (LLSpatialGroup::draw_map_t::iterator i = group->mDrawMap.begin(); i != group->mDrawMap.end(); ++i) + { + LLSpatialGroup::drawmap_elem_t& draw_vec = i->second; + for (LLSpatialGroup::drawmap_elem_t::iterator j = draw_vec.begin(); j != draw_vec.end(); ++j) + { + LLDrawInfo* params = *j; + if (params == draw_info) + { + llerrs << "LLDrawInfo deleted while actively referenced by LLPipeline." << llendl; + } + } + } +} + + +void LLPipeline::checkReferences(LLDrawInfo* draw_info) +{ +#if 0 + if (sCull) + { + for (LLCullResult::sg_list_t::iterator iter = sCull->beginVisibleGroups(); iter != sCull->endVisibleGroups(); ++iter) + { + LLSpatialGroup* group = *iter; + check_references(group, draw_info); + } + + for (LLCullResult::sg_list_t::iterator iter = sCull->beginAlphaGroups(); iter != sCull->endAlphaGroups(); ++iter) + { + LLSpatialGroup* group = *iter; + check_references(group, draw_info); + } + + for (LLCullResult::sg_list_t::iterator iter = sCull->beginDrawableGroups(); iter != sCull->endDrawableGroups(); ++iter) + { + LLSpatialGroup* group = *iter; + check_references(group, draw_info); + } + } +#endif +} + +void LLPipeline::checkReferences(LLSpatialGroup* group) +{ +#if 0 + if (sCull) + { + for (LLCullResult::sg_list_t::iterator iter = sCull->beginVisibleGroups(); iter != sCull->endVisibleGroups(); ++iter) + { + if (group == *iter) + { + llerrs << "LLSpatialGroup deleted while actively referenced by LLPipeline." << llendl; + } + } + + for (LLCullResult::sg_list_t::iterator iter = sCull->beginAlphaGroups(); iter != sCull->endAlphaGroups(); ++iter) + { + if (group == *iter) + { + llerrs << "LLSpatialGroup deleted while actively referenced by LLPipeline." << llendl; + } + } + + for (LLCullResult::sg_list_t::iterator iter = sCull->beginDrawableGroups(); iter != sCull->endDrawableGroups(); ++iter) + { + if (group == *iter) + { + llerrs << "LLSpatialGroup deleted while actively referenced by LLPipeline." << llendl; + } + } + } +#endif +} + + BOOL LLPipeline::visibleObjectsInFrustum(LLCamera& camera) { for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); @@ -2994,6 +3207,8 @@ void LLPipeline::renderHighlights() } } +//debug use +U32 LLPipeline::sCurRenderPoolType = 0 ; void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate) { LLMemType mt(LLMemType::MTYPE_PIPELINE); @@ -3014,6 +3229,13 @@ void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate) } } + S32 stack_depth = 0; + + if (gDebugGL) + { + glGetIntegerv(GL_MODELVIEW_STACK_DEPTH, &stack_depth); + } + /////////////////////////////////////////// // // Sync and verify GL state @@ -3120,6 +3342,9 @@ void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate) cur_type = poolp->getType(); + //debug use + sCurRenderPoolType = cur_type ; + if (occlude && cur_type >= LLDrawPool::POOL_GRASS) { occlude = FALSE; @@ -3152,14 +3377,9 @@ void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate) } poolp->endRenderPass(i); LLVertexBuffer::unbind(); - if (gDebugGL || gDebugPipeline) + if (gDebugGL) { - GLint depth; - glGetIntegerv(GL_MODELVIEW_STACK_DEPTH, &depth); - if (depth > 3) - { - llerrs << "GL matrix stack corrupted!" << llendl; - } + check_stack_depth(stack_depth); std::string msg = llformat("%s pass %d", gPoolNames[cur_type].c_str(), i); LLGLState::checkStates(msg); LLGLState::checkTextureChannels(msg); @@ -7458,7 +7678,7 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in) if (LLPipeline::sWaterReflections && assertInitialized() && LLDrawPoolWater::sNeedsReflectionUpdate) { LLVOAvatar* agent = gAgent.getAvatarObject(); - if (gAgent.getCameraAnimating() || gAgent.getCameraMode() != CAMERA_MODE_MOUSELOOK) + if (!isAgentAvatarValid() || gAgent.getCameraAnimating() || gAgent.getCameraMode() != CAMERA_MODE_MOUSELOOK) { agent = NULL; } diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index af720625e..56720d027 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -207,6 +207,13 @@ public: void renderGroups(LLRenderPass* pass, U32 type, U32 mask, BOOL texture); void grabReferences(LLCullResult& result); + void clearReferences(); + + //check references will assert that there are no references in sCullResult to the provided data + void checkReferences(LLFace* face); + void checkReferences(LLDrawable* drawable); + void checkReferences(LLDrawInfo* draw_info); + void checkReferences(LLSpatialGroup* group); void renderGeom(LLCamera& camera, BOOL forceVBOUpdate = FALSE); void renderGeomDeferred(LLCamera& camera); @@ -657,6 +664,9 @@ protected: public: static BOOL sRenderBeacons; static BOOL sRenderHighlight; + + //debug use + static U32 sCurRenderPoolType ; }; void render_bbox(const LLVector3 &min, const LLVector3 &max); diff --git a/indra/newview/skins/default/xui/en-us/notifications.xml b/indra/newview/skins/default/xui/en-us/notifications.xml index 6c2ff33a1..42adbe080 100644 --- a/indra/newview/skins/default/xui/en-us/notifications.xml +++ b/indra/newview/skins/default/xui/en-us/notifications.xml @@ -6821,6 +6821,14 @@ The URL you clicked cannot be opened from this web browser. You do not appear to have the proper hardware requirements for [VIEWER_NAME]. The viewer requires an OpenGL graphics card that has multitexture support. If this is the case, you may want to make sure that you have the latest drivers for your graphics card, and service packs and patches for your operating system. + + You do not appear to have the proper hardware requirements for [VIEWER_NAME]. The viewer requires a CPU that supports SSE2 + + + + You do not appear to have the proper hardware requirements for [VIEWER_NAME]. The viewer requires a CPU that supports SSE + + 796