diff options
Diffstat (limited to 'indra/llrender')
-rw-r--r-- | indra/llrender/llcubemap.cpp | 12 | ||||
-rw-r--r-- | indra/llrender/llfontgl.cpp | 6 | ||||
-rw-r--r-- | indra/llrender/llgl.cpp | 422 | ||||
-rw-r--r-- | indra/llrender/llgl.h | 93 | ||||
-rw-r--r-- | indra/llrender/llglheaders.h | 228 | ||||
-rw-r--r-- | indra/llrender/llglslshader.cpp | 114 | ||||
-rw-r--r-- | indra/llrender/llglslshader.h | 19 | ||||
-rw-r--r-- | indra/llrender/llglstates.h | 32 | ||||
-rw-r--r-- | indra/llrender/llimagegl.cpp | 30 | ||||
-rw-r--r-- | indra/llrender/llimagegl.h | 2 | ||||
-rw-r--r-- | indra/llrender/llrender.cpp | 305 | ||||
-rw-r--r-- | indra/llrender/llrender.h | 43 | ||||
-rw-r--r-- | indra/llrender/llrendertarget.cpp | 617 | ||||
-rw-r--r-- | indra/llrender/llrendertarget.h | 50 | ||||
-rw-r--r-- | indra/llrender/llshadermgr.cpp | 409 | ||||
-rw-r--r-- | indra/llrender/llshadermgr.h | 5 | ||||
-rw-r--r-- | indra/llrender/llvertexbuffer.cpp | 855 | ||||
-rw-r--r-- | indra/llrender/llvertexbuffer.h | 133 |
18 files changed, 2380 insertions, 995 deletions
diff --git a/indra/llrender/llcubemap.cpp b/indra/llrender/llcubemap.cpp index fb22d7f1f5..1b10354c22 100644 --- a/indra/llrender/llcubemap.cpp +++ b/indra/llrender/llcubemap.cpp @@ -259,7 +259,7 @@ void LLCubeMap::setMatrix(S32 stage) if (mMatrixStage < 0) return; - if (stage > 0) + //if (stage > 0) { gGL.getTexUnit(stage)->activate(); } @@ -278,17 +278,17 @@ void LLCubeMap::setMatrix(S32 stage) glLoadMatrixf((F32 *)trans.mMatrix); glMatrixMode(GL_MODELVIEW); - if (stage > 0) + /*if (stage > 0) { gGL.getTexUnit(0)->activate(); - } + }*/ } void LLCubeMap::restoreMatrix() { if (mMatrixStage < 0) return; - if (mMatrixStage > 0) + //if (mMatrixStage > 0) { gGL.getTexUnit(mMatrixStage)->activate(); } @@ -296,10 +296,10 @@ void LLCubeMap::restoreMatrix() glPopMatrix(); glMatrixMode(GL_MODELVIEW); - if (mMatrixStage > 0) + /*if (mMatrixStage > 0) { gGL.getTexUnit(0)->activate(); - } + }*/ } void LLCubeMap::setReflection (void) diff --git a/indra/llrender/llfontgl.cpp b/indra/llrender/llfontgl.cpp index 13008292f6..607473d416 100644 --- a/indra/llrender/llfontgl.cpp +++ b/indra/llrender/llfontgl.cpp @@ -189,6 +189,9 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons origin.mV[VX] -= llround((F32)sCurOrigin.mX) - (sCurOrigin.mX); origin.mV[VY] -= llround((F32)sCurOrigin.mY) - (sCurOrigin.mY); + // Depth translation, so that floating text appears 'inworld' + // and is correclty occluded. + gGL.translatef(0.f,0.f,sCurOrigin.mZ); S32 chars_drawn = 0; S32 i; @@ -271,7 +274,6 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons } } - const LLFontGlyphInfo* next_glyph = NULL; const S32 GLYPH_BATCH_SIZE = 30; @@ -555,7 +557,7 @@ S32 LLFontGL::maxDrawableChars(const llwchar* wchars, F32 max_pixels, S32 max_ch BOOL in_word = FALSE; // avoid S32 overflow when max_pixels == S32_MAX by staying in floating point - F32 scaled_max_pixels = ceil(max_pixels * sScaleX); + F32 scaled_max_pixels = max_pixels * sScaleX; F32 width_padding = 0.f; LLFontGlyphInfo* next_glyph = NULL; diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp index c86c89fa9b..4e3cfb9c8a 100644 --- a/indra/llrender/llgl.cpp +++ b/indra/llrender/llgl.cpp @@ -48,6 +48,7 @@ #include "llstacktrace.h" #include "llglheaders.h" +#include "llglslshader.h" #ifdef _DEBUG //#define GL_STATE_VERIFY @@ -105,7 +106,6 @@ LLMatrix4 gGLObliqueProjectionInverse; #define LL_GL_NAME_POOLING 0 -LLGLNamePool::pool_list_t LLGLNamePool::sInstances; std::list<LLGLUpdate*> LLGLUpdate::sGLQ; #if (LL_WINDOWS || LL_LINUX || LL_SOLARIS) && !LL_MESA_HEADLESS @@ -128,6 +128,23 @@ PFNGLUNMAPBUFFERARBPROC glUnmapBufferARB = NULL; PFNGLGETBUFFERPARAMETERIVARBPROC glGetBufferParameterivARB = NULL; PFNGLGETBUFFERPOINTERVARBPROC glGetBufferPointervARB = NULL; +// GL_ARB_map_buffer_range +PFNGLMAPBUFFERRANGEPROC glMapBufferRange = NULL; +PFNGLFLUSHMAPPEDBUFFERRANGEPROC glFlushMappedBufferRange = NULL; + +// GL_ARB_sync +PFNGLFENCESYNCPROC glFenceSync = NULL; +PFNGLISSYNCPROC glIsSync = NULL; +PFNGLDELETESYNCPROC glDeleteSync = NULL; +PFNGLCLIENTWAITSYNCPROC glClientWaitSync = NULL; +PFNGLWAITSYNCPROC glWaitSync = NULL; +PFNGLGETINTEGER64VPROC glGetInteger64v = NULL; +PFNGLGETSYNCIVPROC glGetSynciv = NULL; + +// GL_APPLE_flush_buffer_range +PFNGLBUFFERPARAMETERIAPPLEPROC glBufferParameteriAPPLE = NULL; +PFNGLFLUSHMAPPEDBUFFERRANGEAPPLEPROC glFlushMappedBufferRangeAPPLE = NULL; + // vertex object prototypes PFNGLNEWOBJECTBUFFERATIPROC glNewObjectBufferATI = NULL; PFNGLISOBJECTBUFFERATIPROC glIsObjectBufferATI = NULL; @@ -157,30 +174,33 @@ PFNGLGETQUERYOBJECTUIVARBPROC glGetQueryObjectuivARB = NULL; PFNGLPOINTPARAMETERFARBPROC glPointParameterfARB = NULL; PFNGLPOINTPARAMETERFVARBPROC glPointParameterfvARB = NULL; -// GL_EXT_framebuffer_object -PFNGLISRENDERBUFFEREXTPROC glIsRenderbufferEXT = NULL; -PFNGLBINDRENDERBUFFEREXTPROC glBindRenderbufferEXT = NULL; -PFNGLDELETERENDERBUFFERSEXTPROC glDeleteRenderbuffersEXT = NULL; -PFNGLGENRENDERBUFFERSEXTPROC glGenRenderbuffersEXT = NULL; -PFNGLRENDERBUFFERSTORAGEEXTPROC glRenderbufferStorageEXT = NULL; -PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC glGetRenderbufferParameterivEXT = NULL; -PFNGLISFRAMEBUFFEREXTPROC glIsFramebufferEXT = NULL; -PFNGLBINDFRAMEBUFFEREXTPROC glBindFramebufferEXT = NULL; -PFNGLDELETEFRAMEBUFFERSEXTPROC glDeleteFramebuffersEXT = NULL; -PFNGLGENFRAMEBUFFERSEXTPROC glGenFramebuffersEXT = NULL; -PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC glCheckFramebufferStatusEXT = NULL; -PFNGLFRAMEBUFFERTEXTURE1DEXTPROC glFramebufferTexture1DEXT = NULL; -PFNGLFRAMEBUFFERTEXTURE2DEXTPROC glFramebufferTexture2DEXT = NULL; -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; +// GL_ARB_framebuffer_object +PFNGLISRENDERBUFFERPROC glIsRenderbuffer = NULL; +PFNGLBINDRENDERBUFFERPROC glBindRenderbuffer = NULL; +PFNGLDELETERENDERBUFFERSPROC glDeleteRenderbuffers = NULL; +PFNGLGENRENDERBUFFERSPROC glGenRenderbuffers = NULL; +PFNGLRENDERBUFFERSTORAGEPROC glRenderbufferStorage = NULL; +PFNGLGETRENDERBUFFERPARAMETERIVPROC glGetRenderbufferParameteriv = NULL; +PFNGLISFRAMEBUFFERPROC glIsFramebuffer = NULL; +PFNGLBINDFRAMEBUFFERPROC glBindFramebuffer = NULL; +PFNGLDELETEFRAMEBUFFERSPROC glDeleteFramebuffers = NULL; +PFNGLGENFRAMEBUFFERSPROC glGenFramebuffers = NULL; +PFNGLCHECKFRAMEBUFFERSTATUSPROC glCheckFramebufferStatus = NULL; +PFNGLFRAMEBUFFERTEXTURE1DPROC glFramebufferTexture1D = NULL; +PFNGLFRAMEBUFFERTEXTURE2DPROC glFramebufferTexture2D = NULL; +PFNGLFRAMEBUFFERTEXTURE3DPROC glFramebufferTexture3D = NULL; +PFNGLFRAMEBUFFERRENDERBUFFERPROC glFramebufferRenderbuffer = NULL; +PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC glGetFramebufferAttachmentParameteriv = NULL; +PFNGLGENERATEMIPMAPPROC glGenerateMipmap = NULL; +PFNGLBLITFRAMEBUFFERPROC glBlitFramebuffer = NULL; +PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC glRenderbufferStorageMultisample = NULL; +PFNGLFRAMEBUFFERTEXTURELAYERPROC glFramebufferTextureLayer = NULL; + +//GL_ARB_texture_multisample +PFNGLTEXIMAGE2DMULTISAMPLEPROC glTexImage2DMultisample; +PFNGLTEXIMAGE3DMULTISAMPLEPROC glTexImage3DMultisample; +PFNGLGETMULTISAMPLEFVPROC glGetMultisamplefv; +PFNGLSAMPLEMASKIPROC glSampleMaski; // GL_EXT_blend_func_separate PFNGLBLENDFUNCSEPARATEEXTPROC glBlendFuncSeparateEXT = NULL; @@ -319,22 +339,33 @@ LLGLManager::LLGLManager() : mIsDisabled(FALSE), mHasMultitexture(FALSE), + mHasATIMemInfo(FALSE), + mHasNVXMemInfo(FALSE), mNumTextureUnits(1), mHasMipMapGeneration(FALSE), mHasCompressedTextures(FALSE), mHasFramebufferObject(FALSE), - mHasFramebufferMultisample(FALSE), + mMaxSamples(0), mHasBlendFuncSeparate(FALSE), - + mHasSync(FALSE), mHasVertexBufferObject(FALSE), + mHasMapBufferRange(FALSE), + mHasFlushBufferRange(FALSE), mHasPBuffer(FALSE), mHasShaderObjects(FALSE), mHasVertexShader(FALSE), mHasFragmentShader(FALSE), + mNumTextureImageUnits(0), mHasOcclusionQuery(FALSE), + mHasOcclusionQuery2(FALSE), mHasPointParameters(FALSE), mHasDrawBuffers(FALSE), mHasTextureRectangle(FALSE), + mHasTextureMultisample(FALSE), + mMaxSampleMaskWords(0), + mMaxColorTextureSamples(0), + mMaxDepthTextureSamples(0), + mMaxIntegerSamples(0), mHasAnisotropic(FALSE), mHasARBEnvCombine(FALSE), @@ -503,6 +534,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; @@ -522,6 +567,33 @@ bool LLGLManager::initGL() return false; } + if (mHasFragmentShader) + { + GLint num_tex_image_units; + glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &num_tex_image_units); + mNumTextureImageUnits = llmin(num_tex_image_units, 32); + } + + if (mHasTextureMultisample) + { + glGetIntegerv(GL_MAX_COLOR_TEXTURE_SAMPLES, &mMaxColorTextureSamples); + glGetIntegerv(GL_MAX_DEPTH_TEXTURE_SAMPLES, &mMaxDepthTextureSamples); + glGetIntegerv(GL_MAX_INTEGER_SAMPLES, &mMaxIntegerSamples); + glGetIntegerv(GL_MAX_SAMPLE_MASK_WORDS, &mMaxSampleMaskWords); + } + +#if LL_WINDOWS + if (mIsATI) + { //using multisample textures on ATI results in black screen for some reason + mHasTextureMultisample = FALSE; + } +#endif + + if (mHasFramebufferObject) + { + glGetIntegerv(GL_MAX_SAMPLES, &mMaxSamples); + } + setToDebugGPU(); initGLStates(); @@ -628,6 +700,14 @@ std::string LLGLManager::getRawGLString() return gl_string; } +U32 LLGLManager::getNumFBOFSAASamples(U32 samples) +{ + samples = llmin(samples, (U32) mMaxColorTextureSamples); + samples = llmin(samples, (U32) mMaxDepthTextureSamples); + samples = llmin(samples, (U32) 4); + return samples; +} + void LLGLManager::shutdownGL() { if (mInited) @@ -669,11 +749,6 @@ void LLGLManager::initExtensions() # else mHasFramebufferObject = FALSE; # endif // GL_EXT_framebuffer_object -# ifdef GL_EXT_framebuffer_multisample - mHasFramebufferMultisample = TRUE; -# else - mHasFramebufferMultisample = FALSE; -# endif // GL_EXT_framebuffer_multisample # ifdef GL_ARB_draw_buffers mHasDrawBuffers = TRUE; #else @@ -701,6 +776,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"); @@ -709,15 +786,26 @@ void LLGLManager::initExtensions() mHasARBEnvCombine = ExtensionExists("GL_ARB_texture_env_combine", gGLHExts.mSysExts); mHasCompressedTextures = glh_init_extensions("GL_ARB_texture_compression"); mHasOcclusionQuery = ExtensionExists("GL_ARB_occlusion_query", gGLHExts.mSysExts); + mHasOcclusionQuery2 = ExtensionExists("GL_ARB_occlusion_query2", gGLHExts.mSysExts); mHasVertexBufferObject = ExtensionExists("GL_ARB_vertex_buffer_object", gGLHExts.mSysExts); + mHasSync = ExtensionExists("GL_ARB_sync", gGLHExts.mSysExts); + mHasMapBufferRange = ExtensionExists("GL_ARB_map_buffer_range", gGLHExts.mSysExts); + mHasFlushBufferRange = ExtensionExists("GL_APPLE_flush_buffer_range", 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); - mHasFramebufferMultisample = mHasFramebufferObject && ExtensionExists("GL_EXT_framebuffer_multisample", gGLHExts.mSysExts); +#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 + mHasDrawBuffers = ExtensionExists("GL_ARB_draw_buffers", gGLHExts.mSysExts); mHasBlendFuncSeparate = ExtensionExists("GL_EXT_blend_func_separate", gGLHExts.mSysExts); mHasTextureRectangle = ExtensionExists("GL_ARB_texture_rectangle", gGLHExts.mSysExts); + mHasTextureMultisample = ExtensionExists("GL_ARB_texture_multisample", gGLHExts.mSysExts); #if !LL_DARWIN mHasPointParameters = !mIsATI && ExtensionExists("GL_ARB_point_parameters", gGLHExts.mSysExts); #endif @@ -739,7 +827,6 @@ void LLGLManager::initExtensions() mHasCompressedTextures = FALSE; mHasVertexBufferObject = FALSE; mHasFramebufferObject = FALSE; - mHasFramebufferMultisample = FALSE; mHasDrawBuffers = FALSE; mHasBlendFuncSeparate = FALSE; mHasMipMapGeneration = FALSE; @@ -793,10 +880,9 @@ void LLGLManager::initExtensions() if (strchr(blacklist,'p')) mHasPointParameters = FALSE;//S if (strchr(blacklist,'q')) mHasFramebufferObject = FALSE;//S if (strchr(blacklist,'r')) mHasDrawBuffers = FALSE;//S - if (strchr(blacklist,'s')) mHasFramebufferMultisample = FALSE; - if (strchr(blacklist,'t')) mHasTextureRectangle = FALSE; - if (strchr(blacklist,'u')) mHasBlendFuncSeparate = FALSE;//S - if (strchr(blacklist,'v')) mHasDepthClamp = FALSE; + if (strchr(blacklist,'s')) mHasTextureRectangle = FALSE; + if (strchr(blacklist,'t')) mHasBlendFuncSeparate = FALSE;//S + if (strchr(blacklist,'u')) mHasDepthClamp = FALSE; } #endif // LL_LINUX || LL_SOLARIS @@ -829,6 +915,10 @@ void LLGLManager::initExtensions() { LL_INFOS("RenderInit") << "Couldn't initialize GL_ARB_occlusion_query" << LL_ENDL; } + if (!mHasOcclusionQuery2) + { + LL_INFOS("RenderInit") << "Couldn't initialize GL_ARB_occlusion_query2" << LL_ENDL; + } if (!mHasPointParameters) { LL_INFOS("RenderInit") << "Couldn't initialize GL_ARB_point_parameters" << LL_ENDL; @@ -860,11 +950,13 @@ void LLGLManager::initExtensions() LL_INFOS("RenderInit") << "Disabling mip-map generation for Intel GPUs" << LL_ENDL; mHasMipMapGeneration = FALSE; } +#if !LL_DARWIN if (mIsATI && mHasMipMapGeneration) { LL_INFOS("RenderInit") << "Disabling mip-map generation for ATI GPUs (performance opt)" << LL_ENDL; mHasMipMapGeneration = FALSE; } +#endif // Misc glGetIntegerv(GL_MAX_ELEMENTS_VERTICES, (GLint*) &mGLMaxVertexRange); @@ -893,31 +985,44 @@ void LLGLManager::initExtensions() mHasVertexBufferObject = FALSE; } } + if (mHasSync) + { + glFenceSync = (PFNGLFENCESYNCPROC) GLH_EXT_GET_PROC_ADDRESS("glFenceSync"); + glIsSync = (PFNGLISSYNCPROC) GLH_EXT_GET_PROC_ADDRESS("glIsSync"); + glDeleteSync = (PFNGLDELETESYNCPROC) GLH_EXT_GET_PROC_ADDRESS("glDeleteSync"); + glClientWaitSync = (PFNGLCLIENTWAITSYNCPROC) GLH_EXT_GET_PROC_ADDRESS("glClientWaitSync"); + glWaitSync = (PFNGLWAITSYNCPROC) GLH_EXT_GET_PROC_ADDRESS("glWaitSync"); + glGetInteger64v = (PFNGLGETINTEGER64VPROC) GLH_EXT_GET_PROC_ADDRESS("glGetInteger64v"); + glGetSynciv = (PFNGLGETSYNCIVPROC) GLH_EXT_GET_PROC_ADDRESS("glGetSynciv"); + } + if (mHasMapBufferRange) + { + glMapBufferRange = (PFNGLMAPBUFFERRANGEPROC) GLH_EXT_GET_PROC_ADDRESS("glMapBufferRange"); + glFlushMappedBufferRange = (PFNGLFLUSHMAPPEDBUFFERRANGEPROC) GLH_EXT_GET_PROC_ADDRESS("glFlushMappedBufferRange"); + } if (mHasFramebufferObject) { llinfos << "initExtensions() FramebufferObject-related procs..." << llendl; - glIsRenderbufferEXT = (PFNGLISRENDERBUFFEREXTPROC) GLH_EXT_GET_PROC_ADDRESS("glIsRenderbufferEXT"); - glBindRenderbufferEXT = (PFNGLBINDRENDERBUFFEREXTPROC) GLH_EXT_GET_PROC_ADDRESS("glBindRenderbufferEXT"); - glDeleteRenderbuffersEXT = (PFNGLDELETERENDERBUFFERSEXTPROC) GLH_EXT_GET_PROC_ADDRESS("glDeleteRenderbuffersEXT"); - glGenRenderbuffersEXT = (PFNGLGENRENDERBUFFERSEXTPROC) GLH_EXT_GET_PROC_ADDRESS("glGenRenderbuffersEXT"); - glRenderbufferStorageEXT = (PFNGLRENDERBUFFERSTORAGEEXTPROC) GLH_EXT_GET_PROC_ADDRESS("glRenderbufferStorageEXT"); - glGetRenderbufferParameterivEXT = (PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC) GLH_EXT_GET_PROC_ADDRESS("glGetRenderbufferParameterivEXT"); - glIsFramebufferEXT = (PFNGLISFRAMEBUFFEREXTPROC) GLH_EXT_GET_PROC_ADDRESS("glIsFramebufferEXT"); - glBindFramebufferEXT = (PFNGLBINDFRAMEBUFFEREXTPROC) GLH_EXT_GET_PROC_ADDRESS("glBindFramebufferEXT"); - glDeleteFramebuffersEXT = (PFNGLDELETEFRAMEBUFFERSEXTPROC) GLH_EXT_GET_PROC_ADDRESS("glDeleteFramebuffersEXT"); - glGenFramebuffersEXT = (PFNGLGENFRAMEBUFFERSEXTPROC) GLH_EXT_GET_PROC_ADDRESS("glGenFramebuffersEXT"); - glCheckFramebufferStatusEXT = (PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC) GLH_EXT_GET_PROC_ADDRESS("glCheckFramebufferStatusEXT"); - glFramebufferTexture1DEXT = (PFNGLFRAMEBUFFERTEXTURE1DEXTPROC) GLH_EXT_GET_PROC_ADDRESS("glFramebufferTexture1DEXT"); - glFramebufferTexture2DEXT = (PFNGLFRAMEBUFFERTEXTURE2DEXTPROC) GLH_EXT_GET_PROC_ADDRESS("glFramebufferTexture2DEXT"); - glFramebufferTexture3DEXT = (PFNGLFRAMEBUFFERTEXTURE3DEXTPROC) GLH_EXT_GET_PROC_ADDRESS("glFramebufferTexture3DEXT"); - 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"); + glIsRenderbuffer = (PFNGLISRENDERBUFFERPROC) GLH_EXT_GET_PROC_ADDRESS("glIsRenderbuffer"); + glBindRenderbuffer = (PFNGLBINDRENDERBUFFERPROC) GLH_EXT_GET_PROC_ADDRESS("glBindRenderbuffer"); + glDeleteRenderbuffers = (PFNGLDELETERENDERBUFFERSPROC) GLH_EXT_GET_PROC_ADDRESS("glDeleteRenderbuffers"); + glGenRenderbuffers = (PFNGLGENRENDERBUFFERSPROC) GLH_EXT_GET_PROC_ADDRESS("glGenRenderbuffers"); + glRenderbufferStorage = (PFNGLRENDERBUFFERSTORAGEPROC) GLH_EXT_GET_PROC_ADDRESS("glRenderbufferStorage"); + glGetRenderbufferParameteriv = (PFNGLGETRENDERBUFFERPARAMETERIVPROC) GLH_EXT_GET_PROC_ADDRESS("glGetRenderbufferParameteriv"); + glIsFramebuffer = (PFNGLISFRAMEBUFFERPROC) GLH_EXT_GET_PROC_ADDRESS("glIsFramebuffer"); + glBindFramebuffer = (PFNGLBINDFRAMEBUFFERPROC) GLH_EXT_GET_PROC_ADDRESS("glBindFramebuffer"); + glDeleteFramebuffers = (PFNGLDELETEFRAMEBUFFERSPROC) GLH_EXT_GET_PROC_ADDRESS("glDeleteFramebuffers"); + glGenFramebuffers = (PFNGLGENFRAMEBUFFERSPROC) GLH_EXT_GET_PROC_ADDRESS("glGenFramebuffers"); + glCheckFramebufferStatus = (PFNGLCHECKFRAMEBUFFERSTATUSPROC) GLH_EXT_GET_PROC_ADDRESS("glCheckFramebufferStatus"); + glFramebufferTexture1D = (PFNGLFRAMEBUFFERTEXTURE1DPROC) GLH_EXT_GET_PROC_ADDRESS("glFramebufferTexture1D"); + glFramebufferTexture2D = (PFNGLFRAMEBUFFERTEXTURE2DPROC) GLH_EXT_GET_PROC_ADDRESS("glFramebufferTexture2D"); + glFramebufferTexture3D = (PFNGLFRAMEBUFFERTEXTURE3DPROC) GLH_EXT_GET_PROC_ADDRESS("glFramebufferTexture3D"); + glFramebufferRenderbuffer = (PFNGLFRAMEBUFFERRENDERBUFFERPROC) GLH_EXT_GET_PROC_ADDRESS("glFramebufferRenderbuffer"); + glGetFramebufferAttachmentParameteriv = (PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC) GLH_EXT_GET_PROC_ADDRESS("glGetFramebufferAttachmentParameteriv"); + glGenerateMipmap = (PFNGLGENERATEMIPMAPPROC) GLH_EXT_GET_PROC_ADDRESS("glGenerateMipmap"); + glBlitFramebuffer = (PFNGLBLITFRAMEBUFFERPROC) GLH_EXT_GET_PROC_ADDRESS("glBlitFramebuffer"); + glRenderbufferStorageMultisample = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC) GLH_EXT_GET_PROC_ADDRESS("glRenderbufferStorageMultisample"); + glFramebufferTextureLayer = (PFNGLFRAMEBUFFERTEXTURELAYERPROC) GLH_EXT_GET_PROC_ADDRESS("glFramebufferTextureLayer"); } if (mHasDrawBuffers) { @@ -927,6 +1032,13 @@ void LLGLManager::initExtensions() { glBlendFuncSeparateEXT = (PFNGLBLENDFUNCSEPARATEEXTPROC) GLH_EXT_GET_PROC_ADDRESS("glBlendFuncSeparateEXT"); } + if (mHasTextureMultisample) + { + glTexImage2DMultisample = (PFNGLTEXIMAGE2DMULTISAMPLEPROC) GLH_EXT_GET_PROC_ADDRESS("glTexImage2DMultisample"); + glTexImage3DMultisample = (PFNGLTEXIMAGE3DMULTISAMPLEPROC) GLH_EXT_GET_PROC_ADDRESS("glTexImage3DMultisample"); + glGetMultisamplefv = (PFNGLGETMULTISAMPLEFVPROC) GLH_EXT_GET_PROC_ADDRESS("glGetMultisamplefv"); + glSampleMaski = (PFNGLSAMPLEMASKIPROC) GLH_EXT_GET_PROC_ADDRESS("glSampleMaski"); + } #if (!LL_LINUX && !LL_SOLARIS) || LL_LINUX_NV_GL_HEADERS // This is expected to be a static symbol on Linux GL implementations, except if we use the nvidia headers - bah glDrawRangeElements = (PFNGLDRAWRANGEELEMENTSPROC)GLH_EXT_GET_PROC_ADDRESS("glDrawRangeElements"); @@ -1268,6 +1380,8 @@ void LLGLState::checkStates(const std::string& msg) glGetIntegerv(GL_BLEND_SRC, &src); glGetIntegerv(GL_BLEND_DST, &dst); + stop_glerror(); + BOOL error = FALSE; if (src != GL_SRC_ALPHA || dst != GL_ONE_MINUS_SRC_ALPHA) @@ -1288,7 +1402,9 @@ void LLGLState::checkStates(const std::string& msg) { LLGLenum state = iter->first; LLGLboolean cur_state = iter->second; + stop_glerror(); LLGLboolean gl_state = glIsEnabled(state); + stop_glerror(); if(cur_state != gl_state) { dumpStates(); @@ -1313,11 +1429,11 @@ void LLGLState::checkStates(const std::string& msg) void LLGLState::checkTextureChannels(const std::string& msg) { +#if 0 if (!gDebugGL) { return; } - stop_glerror(); GLint activeTexture; @@ -1344,10 +1460,6 @@ void LLGLState::checkTextureChannels(const std::string& msg) } } - GLint maxTextureUnits = 0; - glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &maxTextureUnits); - stop_glerror(); - static const char* label[] = { "GL_TEXTURE_2D", @@ -1358,7 +1470,8 @@ void LLGLState::checkTextureChannels(const std::string& msg) "GL_TEXTURE_GEN_T", "GL_TEXTURE_GEN_Q", "GL_TEXTURE_GEN_R", - "GL_TEXTURE_RECTANGLE_ARB" + "GL_TEXTURE_RECTANGLE_ARB", + "GL_TEXTURE_2D_MULTISAMPLE" }; static GLint value[] = @@ -1371,7 +1484,8 @@ void LLGLState::checkTextureChannels(const std::string& msg) GL_TEXTURE_GEN_T, GL_TEXTURE_GEN_Q, GL_TEXTURE_GEN_R, - GL_TEXTURE_RECTANGLE_ARB + GL_TEXTURE_RECTANGLE_ARB, + GL_TEXTURE_2D_MULTISAMPLE }; GLint stackDepth = 0; @@ -1380,68 +1494,96 @@ void LLGLState::checkTextureChannels(const std::string& msg) glh::matrix4f identity; identity.identity(); - for (GLint i = 1; i < maxTextureUnits; i++) + for (GLint i = 1; i < gGLManager.mNumTextureUnits; i++) { gGL.getTexUnit(i)->activate(); - glClientActiveTextureARB(GL_TEXTURE0_ARB+i); - stop_glerror(); - glGetIntegerv(GL_TEXTURE_STACK_DEPTH, &stackDepth); - stop_glerror(); - if (stackDepth != 1) + if (i < gGLManager.mNumTextureUnits) { - error = TRUE; - LL_WARNS("RenderState") << "Texture matrix stack corrupted." << LL_ENDL; + glClientActiveTextureARB(GL_TEXTURE0_ARB+i); + stop_glerror(); + glGetIntegerv(GL_TEXTURE_STACK_DEPTH, &stackDepth); + stop_glerror(); - if (gDebugSession) + if (stackDepth != 1) { - gFailLog << "Texture matrix stack corrupted." << std::endl; + 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*) mat.m); - stop_glerror(); + glGetFloatv(GL_TEXTURE_MATRIX, (GLfloat*) mat.m); + stop_glerror(); - if (mat != identity) - { - error = TRUE; - LL_WARNS("RenderState") << "Texture matrix in channel " << i << " corrupt." << LL_ENDL; - if (gDebugSession) + if (mat != identity) { - gFailLog << "Texture matrix in channel " << i << " corrupt." << std::endl; + 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 < 9; j++) + { + if (j == 8 && !gGLManager.mHasTextureRectangle || + j == 9 && !gGLManager.mHasTextureMultisample) + { + continue; + } + + if (glIsEnabled(value[j])) + { + 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(); } - } - - for (S32 j = (i == 0 ? 1 : 0); - j < (gGLManager.mHasTextureRectangle ? 9 : 8); j++) - { - if (glIsEnabled(value[j])) + glGetFloatv(GL_TEXTURE_MATRIX, mat.m); + stop_glerror(); + + if (mat != identity) { error = TRUE; - LL_WARNS("RenderState") << "Texture channel " << i << " still has " << label[j] << " enabled." << LL_ENDL; + LL_WARNS("RenderState") << "Texture matrix " << i << " is not identity." << LL_ENDL; if (gDebugSession) { - gFailLog << "Texture channel " << i << " still has " << label[j] << " enabled." << std::endl; + gFailLog << "Texture matrix " << i << " is not identity." << 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) + GLint tex = 0; + stop_glerror(); + glGetIntegerv(GL_TEXTURE_BINDING_2D, &tex); + stop_glerror(); + + if (tex != 0) { - gFailLog << "Texture matrix " << i << " is not identity." << std::endl; + error = TRUE; + LL_WARNS("RenderState") << "Texture channel " << i << " still has texture " << tex << " bound." << llendl; + + if (gDebugSession) + { + gFailLog << "Texture channel " << i << " still has texture " << tex << " bound." << std::endl; + } } } } + stop_glerror(); gGL.getTexUnit(0)->activate(); glClientActiveTextureARB(GL_TEXTURE0_ARB); stop_glerror(); @@ -1457,6 +1599,7 @@ void LLGLState::checkTextureChannels(const std::string& msg) LL_GL_ERRS << "GL texture state corruption detected. " << msg << LL_ENDL; } } +#endif } void LLGLState::checkClientArrays(const std::string& msg, U32 data_mask) @@ -1573,7 +1716,7 @@ void LLGLState::checkClientArrays(const std::string& msg, U32 data_mask) } } - if (glIsEnabled(GL_TEXTURE_2D)) + /*if (glIsEnabled(GL_TEXTURE_2D)) { if (!(data_mask & 0x0008)) { @@ -1596,7 +1739,7 @@ void LLGLState::checkClientArrays(const std::string& msg, U32 data_mask) gFailLog << "GL does not have GL_TEXTURE_2D enabled on channel 1." << std::endl; } } - } + }*/ glClientActiveTextureARB(GL_TEXTURE0_ARB); gGL.getTexUnit(0)->activate(); @@ -1639,6 +1782,16 @@ void LLGLState::checkClientArrays(const std::string& msg, U32 data_mask) LLGLState::LLGLState(LLGLenum state, S32 enabled) : mState(state), mWasEnabled(FALSE), mIsEnabled(FALSE) { + if (LLGLSLShader::sNoFixedFunction) + { //always disable state that's deprecated post GL 3.0 + switch (state) + { + case GL_ALPHA_TEST: + enabled = 0; + break; + } + } + stop_glerror(); if (state) { @@ -1875,12 +2028,17 @@ void parse_gl_version( S32* major, S32* minor, S32* release, std::string* vendor } } -LLGLUserClipPlane::LLGLUserClipPlane(const LLPlane& p, const glh::matrix4f& modelview, const glh::matrix4f& projection) +LLGLUserClipPlane::LLGLUserClipPlane(const LLPlane& p, const glh::matrix4f& modelview, const glh::matrix4f& projection, bool apply) { - mModelview = modelview; - mProjection = projection; + mApply = apply; - setPlane(p.mV[0], p.mV[1], p.mV[2], p.mV[3]); + if (mApply) + { + mModelview = modelview; + mProjection = projection; + + setPlane(p[0], p[1], p[2], p[3]); + } } void LLGLUserClipPlane::setPlane(F32 a, F32 b, F32 c, F32 d) @@ -1911,31 +2069,20 @@ void LLGLUserClipPlane::setPlane(F32 a, F32 b, F32 c, F32 d) LLGLUserClipPlane::~LLGLUserClipPlane() { - glMatrixMode(GL_PROJECTION); - glPopMatrix(); - glMatrixMode(GL_MODELVIEW); + if (mApply) + { + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + } } LLGLNamePool::LLGLNamePool() { } -void LLGLNamePool::registerPool(LLGLNamePool* pool) -{ - pool_list_t::iterator iter = std::find(sInstances.begin(), sInstances.end(), pool); - if (iter == sInstances.end()) - { - sInstances.push_back(pool); - } -} - LLGLNamePool::~LLGLNamePool() { - pool_list_t::iterator iter = std::find(sInstances.begin(), sInstances.end(), this); - if (iter != sInstances.end()) - { - sInstances.erase(iter); - } } void LLGLNamePool::upkeep() @@ -2004,20 +2151,20 @@ void LLGLNamePool::release(GLuint name) void LLGLNamePool::upkeepPools() { LLMemType mt(LLMemType::MTYPE_UPKEEP_POOLS); - for (pool_list_t::iterator iter = sInstances.begin(); iter != sInstances.end(); ++iter) + for (tracker_t::instance_iter iter = beginInstances(); iter != endInstances(); ++iter) { - LLGLNamePool* pool = *iter; - pool->upkeep(); + LLGLNamePool & pool = *iter; + pool.upkeep(); } } //static void LLGLNamePool::cleanupPools() { - for (pool_list_t::iterator iter = sInstances.begin(); iter != sInstances.end(); ++iter) + for (tracker_t::instance_iter iter = beginInstances(); iter != endInstances(); ++iter) { - LLGLNamePool* pool = *iter; - pool->cleanup(); + LLGLNamePool & pool = *iter; + pool.cleanup(); } } @@ -2106,11 +2253,14 @@ void LLGLDepthTest::checkState() } } -LLGLSquashToFarClip::LLGLSquashToFarClip(glh::matrix4f P) +LLGLSquashToFarClip::LLGLSquashToFarClip(glh::matrix4f P, U32 layer) { + + F32 depth = 0.99999f - 0.0001f * layer; + for (U32 i = 0; i < 4; i++) { - P.element(2, i) = P.element(3, i) * 0.99999f; + P.element(2, i) = P.element(3, i) * depth; } glMatrixMode(GL_PROJECTION); diff --git a/indra/llrender/llgl.h b/indra/llrender/llgl.h index 684fd50883..d736133f3f 100644 --- a/indra/llrender/llgl.h +++ b/indra/llrender/llgl.h @@ -40,6 +40,7 @@ #include "v4math.h" #include "llplane.h" #include "llgltypes.h" +#include "llinstancetracker.h" #include "llglheaders.h" #include "glh/glh_linear.h" @@ -76,24 +77,36 @@ public: // Extensions used by everyone BOOL mHasMultitexture; + BOOL mHasATIMemInfo; + BOOL mHasNVXMemInfo; S32 mNumTextureUnits; BOOL mHasMipMapGeneration; BOOL mHasCompressedTextures; BOOL mHasFramebufferObject; - BOOL mHasFramebufferMultisample; + S32 mMaxSamples; BOOL mHasBlendFuncSeparate; - + // ARB Extensions BOOL mHasVertexBufferObject; + BOOL mHasSync; + BOOL mHasMapBufferRange; + BOOL mHasFlushBufferRange; BOOL mHasPBuffer; BOOL mHasShaderObjects; BOOL mHasVertexShader; BOOL mHasFragmentShader; + S32 mNumTextureImageUnits; BOOL mHasOcclusionQuery; + BOOL mHasOcclusionQuery2; BOOL mHasPointParameters; BOOL mHasDrawBuffers; BOOL mHasDepthClamp; BOOL mHasTextureRectangle; + BOOL mHasTextureMultisample; + S32 mMaxSampleMaskWords; + S32 mMaxColorTextureSamples; + S32 mMaxDepthTextureSamples; + S32 mMaxIntegerSamples; // Other extensions. BOOL mHasAnisotropic; @@ -135,6 +148,7 @@ public: void printGLInfoString(); void getGLInfo(LLSD& info); + U32 getNumFBOFSAASamples(U32 desired_samples = 32); // In ALL CAPS std::string mGLVendor; std::string mGLVendorShort; @@ -299,12 +313,14 @@ class LLGLUserClipPlane { public: - LLGLUserClipPlane(const LLPlane& plane, const glh::matrix4f& modelview, const glh::matrix4f& projection); + LLGLUserClipPlane(const LLPlane& plane, const glh::matrix4f& modelview, const glh::matrix4f& projection, bool apply = true); ~LLGLUserClipPlane(); void setPlane(F32 a, F32 b, F32 c, F32 d); private: + bool mApply; + glh::matrix4f mProjection; glh::matrix4f mModelview; }; @@ -320,7 +336,7 @@ private: class LLGLSquashToFarClip { public: - LLGLSquashToFarClip(glh::matrix4f projection); + LLGLSquashToFarClip(glh::matrix4f projection, U32 layer = 0); ~LLGLSquashToFarClip(); }; @@ -328,9 +344,11 @@ public: Generic pooling scheme for things which use GL names (used for occlusion queries and vertex buffer objects). Prevents thrashing of GL name caches by avoiding calls to glGenFoo and glDeleteFoo. */ -class LLGLNamePool +class LLGLNamePool : public LLInstanceTracker<LLGLNamePool> { public: + typedef LLInstanceTracker<LLGLNamePool> tracker_t; + struct NameEntry { GLuint name; @@ -357,13 +375,11 @@ public: GLuint allocate(); void release(GLuint name); - static void registerPool(LLGLNamePool* pool); static void upkeepPools(); static void cleanupPools(); protected: typedef std::vector<LLGLNamePool*> pool_list_t; - static pool_list_t sInstances; virtual GLuint allocateName() = 0; virtual void releaseName(GLuint name) = 0; @@ -418,4 +434,67 @@ extern BOOL gClothRipple; extern BOOL gHeadlessClient; 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 576969b81a..851a75629e 100644 --- a/indra/llrender/llglheaders.h +++ b/indra/llrender/llglheaders.h @@ -1,25 +1,25 @@ -/** +/** * @file llglheaders.h * @brief LLGL definitions * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * + * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -68,6 +68,23 @@ extern PFNGLUNMAPBUFFERARBPROC glUnmapBufferARB; extern PFNGLGETBUFFERPARAMETERIVARBPROC glGetBufferParameterivARB; extern PFNGLGETBUFFERPOINTERVARBPROC glGetBufferPointervARB; +// GL_ARB_sync +extern PFNGLFENCESYNCPROC glFenceSync; +extern PFNGLISSYNCPROC glIsSync; +extern PFNGLDELETESYNCPROC glDeleteSync; +extern PFNGLCLIENTWAITSYNCPROC glClientWaitSync; +extern PFNGLWAITSYNCPROC glWaitSync; +extern PFNGLGETINTEGER64VPROC glGetInteger64v; +extern PFNGLGETSYNCIVPROC glGetSynciv; + +// GL_APPLE_flush_buffer_range +extern PFNGLBUFFERPARAMETERIAPPLEPROC glBufferParameteriAPPLE; +extern PFNGLFLUSHMAPPEDBUFFERRANGEAPPLEPROC glFlushMappedBufferRangeAPPLE; + +// GL_ARB_map_buffer_range +extern PFNGLMAPBUFFERRANGEPROC glMapBufferRange; +extern PFNGLFLUSHMAPPEDBUFFERRANGEPROC glFlushMappedBufferRange; + // GL_ATI_vertex_array_object extern PFNGLNEWOBJECTBUFFERATIPROC glNewObjectBufferATI; extern PFNGLISOBJECTBUFFERATIPROC glIsObjectBufferATI; @@ -306,6 +323,23 @@ extern PFNGLUNMAPBUFFERARBPROC glUnmapBufferARB; extern PFNGLGETBUFFERPARAMETERIVARBPROC glGetBufferParameterivARB; extern PFNGLGETBUFFERPOINTERVARBPROC glGetBufferPointervARB; +// GL_ARB_sync +extern PFNGLFENCESYNCPROC glFenceSync; +extern PFNGLISSYNCPROC glIsSync; +extern PFNGLDELETESYNCPROC glDeleteSync; +extern PFNGLCLIENTWAITSYNCPROC glClientWaitSync; +extern PFNGLWAITSYNCPROC glWaitSync; +extern PFNGLGETINTEGER64VPROC glGetInteger64v; +extern PFNGLGETSYNCIVPROC glGetSynciv; + +// GL_APPLE_flush_buffer_range +extern PFNGLBUFFERPARAMETERIAPPLEPROC glBufferParameteriAPPLE; +extern PFNGLFLUSHMAPPEDBUFFERRANGEAPPLEPROC glFlushMappedBufferRangeAPPLE; + +// GL_ARB_map_buffer_range +extern PFNGLMAPBUFFERRANGEPROC glMapBufferRange; +extern PFNGLFLUSHMAPPEDBUFFERRANGEPROC glFlushMappedBufferRange; + // GL_ATI_vertex_array_object extern PFNGLNEWOBJECTBUFFERATIPROC glNewObjectBufferATI; extern PFNGLISOBJECTBUFFERATIPROC glIsObjectBufferATI; @@ -449,34 +483,36 @@ extern PFNGLGETCOMPRESSEDTEXIMAGEARBPROC glGetCompressedTexImageARB; //GL_EXT_blend_func_separate extern PFNGLBLENDFUNCSEPARATEEXTPROC glBlendFuncSeparateEXT; -//GL_EXT_framebuffer_object -extern PFNGLISRENDERBUFFEREXTPROC glIsRenderbufferEXT; -extern PFNGLBINDRENDERBUFFEREXTPROC glBindRenderbufferEXT; -extern PFNGLDELETERENDERBUFFERSEXTPROC glDeleteRenderbuffersEXT; -extern PFNGLGENRENDERBUFFERSEXTPROC glGenRenderbuffersEXT; -extern PFNGLRENDERBUFFERSTORAGEEXTPROC glRenderbufferStorageEXT; -extern PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC glGetRenderbufferParameterivEXT; -extern PFNGLISFRAMEBUFFEREXTPROC glIsFramebufferEXT; -extern PFNGLBINDFRAMEBUFFEREXTPROC glBindFramebufferEXT; -extern PFNGLDELETEFRAMEBUFFERSEXTPROC glDeleteFramebuffersEXT; -extern PFNGLGENFRAMEBUFFERSEXTPROC glGenFramebuffersEXT; -extern PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC glCheckFramebufferStatusEXT; -extern PFNGLFRAMEBUFFERTEXTURE1DEXTPROC glFramebufferTexture1DEXT; -extern PFNGLFRAMEBUFFERTEXTURE2DEXTPROC glFramebufferTexture2DEXT; -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; +//GL_ARB_framebuffer_object +extern PFNGLISRENDERBUFFERPROC glIsRenderbuffer; +extern PFNGLBINDRENDERBUFFERPROC glBindRenderbuffer; +extern PFNGLDELETERENDERBUFFERSPROC glDeleteRenderbuffers; +extern PFNGLGENRENDERBUFFERSPROC glGenRenderbuffers; +extern PFNGLRENDERBUFFERSTORAGEPROC glRenderbufferStorage; +extern PFNGLGETRENDERBUFFERPARAMETERIVPROC glGetRenderbufferParameteriv; +extern PFNGLISFRAMEBUFFERPROC glIsFramebuffer; +extern PFNGLBINDFRAMEBUFFERPROC glBindFramebuffer; +extern PFNGLDELETEFRAMEBUFFERSPROC glDeleteFramebuffers; +extern PFNGLGENFRAMEBUFFERSPROC glGenFramebuffers; +extern PFNGLCHECKFRAMEBUFFERSTATUSPROC glCheckFramebufferStatus; +extern PFNGLFRAMEBUFFERTEXTURE1DPROC glFramebufferTexture1D; +extern PFNGLFRAMEBUFFERTEXTURE2DPROC glFramebufferTexture2D; +extern PFNGLFRAMEBUFFERTEXTURE3DPROC glFramebufferTexture3D; +extern PFNGLFRAMEBUFFERRENDERBUFFERPROC glFramebufferRenderbuffer; +extern PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC glGetFramebufferAttachmentParameteriv; +extern PFNGLGENERATEMIPMAPPROC glGenerateMipmap; +extern PFNGLBLITFRAMEBUFFERPROC glBlitFramebuffer; +extern PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC glRenderbufferStorageMultisample; +extern PFNGLFRAMEBUFFERTEXTURELAYERPROC glFramebufferTextureLayer; //GL_ARB_draw_buffers extern PFNGLDRAWBUFFERSARBPROC glDrawBuffersARB; +//GL_ARB_texture_multisample +extern PFNGLTEXIMAGE2DMULTISAMPLEPROC glTexImage2DMultisample; +extern PFNGLTEXIMAGE3DMULTISAMPLEPROC glTexImage3DMultisample; +extern PFNGLGETMULTISAMPLEFVPROC glGetMultisamplefv; +extern PFNGLSAMPLEMASKIPROC glSampleMaski; #elif LL_WINDOWS //---------------------------------------------------------------------------- @@ -509,6 +545,23 @@ extern PFNGLUNMAPBUFFERARBPROC glUnmapBufferARB; extern PFNGLGETBUFFERPARAMETERIVARBPROC glGetBufferParameterivARB; extern PFNGLGETBUFFERPOINTERVARBPROC glGetBufferPointervARB; +// GL_ARB_sync +extern PFNGLFENCESYNCPROC glFenceSync; +extern PFNGLISSYNCPROC glIsSync; +extern PFNGLDELETESYNCPROC glDeleteSync; +extern PFNGLCLIENTWAITSYNCPROC glClientWaitSync; +extern PFNGLWAITSYNCPROC glWaitSync; +extern PFNGLGETINTEGER64VPROC glGetInteger64v; +extern PFNGLGETSYNCIVPROC glGetSynciv; + +// GL_APPLE_flush_buffer_range +extern PFNGLBUFFERPARAMETERIAPPLEPROC glBufferParameteriAPPLE; +extern PFNGLFLUSHMAPPEDBUFFERRANGEAPPLEPROC glFlushMappedBufferRangeAPPLE; + +// GL_ARB_map_buffer_range +extern PFNGLMAPBUFFERRANGEPROC glMapBufferRange; +extern PFNGLFLUSHMAPPEDBUFFERRANGEPROC glFlushMappedBufferRange; + // GL_ATI_vertex_array_object extern PFNGLNEWOBJECTBUFFERATIPROC glNewObjectBufferATI; extern PFNGLISOBJECTBUFFERATIPROC glIsObjectBufferATI; @@ -651,34 +704,36 @@ extern PFNGLGETATTRIBLOCATIONARBPROC glGetAttribLocationARB; //GL_EXT_blend_func_separate extern PFNGLBLENDFUNCSEPARATEEXTPROC glBlendFuncSeparateEXT; -//GL_EXT_framebuffer_object -extern PFNGLISRENDERBUFFEREXTPROC glIsRenderbufferEXT; -extern PFNGLBINDRENDERBUFFEREXTPROC glBindRenderbufferEXT; -extern PFNGLDELETERENDERBUFFERSEXTPROC glDeleteRenderbuffersEXT; -extern PFNGLGENRENDERBUFFERSEXTPROC glGenRenderbuffersEXT; -extern PFNGLRENDERBUFFERSTORAGEEXTPROC glRenderbufferStorageEXT; -extern PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC glGetRenderbufferParameterivEXT; -extern PFNGLISFRAMEBUFFEREXTPROC glIsFramebufferEXT; -extern PFNGLBINDFRAMEBUFFEREXTPROC glBindFramebufferEXT; -extern PFNGLDELETEFRAMEBUFFERSEXTPROC glDeleteFramebuffersEXT; -extern PFNGLGENFRAMEBUFFERSEXTPROC glGenFramebuffersEXT; -extern PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC glCheckFramebufferStatusEXT; -extern PFNGLFRAMEBUFFERTEXTURE1DEXTPROC glFramebufferTexture1DEXT; -extern PFNGLFRAMEBUFFERTEXTURE2DEXTPROC glFramebufferTexture2DEXT; -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; +//GL_ARB_framebuffer_object +extern PFNGLISRENDERBUFFERPROC glIsRenderbuffer; +extern PFNGLBINDRENDERBUFFERPROC glBindRenderbuffer; +extern PFNGLDELETERENDERBUFFERSPROC glDeleteRenderbuffers; +extern PFNGLGENRENDERBUFFERSPROC glGenRenderbuffers; +extern PFNGLRENDERBUFFERSTORAGEPROC glRenderbufferStorage; +extern PFNGLGETRENDERBUFFERPARAMETERIVPROC glGetRenderbufferParameteriv; +extern PFNGLISFRAMEBUFFERPROC glIsFramebuffer; +extern PFNGLBINDFRAMEBUFFERPROC glBindFramebuffer; +extern PFNGLDELETEFRAMEBUFFERSPROC glDeleteFramebuffers; +extern PFNGLGENFRAMEBUFFERSPROC glGenFramebuffers; +extern PFNGLCHECKFRAMEBUFFERSTATUSPROC glCheckFramebufferStatus; +extern PFNGLFRAMEBUFFERTEXTURE1DPROC glFramebufferTexture1D; +extern PFNGLFRAMEBUFFERTEXTURE2DPROC glFramebufferTexture2D; +extern PFNGLFRAMEBUFFERTEXTURE3DPROC glFramebufferTexture3D; +extern PFNGLFRAMEBUFFERRENDERBUFFERPROC glFramebufferRenderbuffer; +extern PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC glGetFramebufferAttachmentParameteriv; +extern PFNGLGENERATEMIPMAPPROC glGenerateMipmap; +extern PFNGLBLITFRAMEBUFFERPROC glBlitFramebuffer; +extern PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC glRenderbufferStorageMultisample; +extern PFNGLFRAMEBUFFERTEXTURELAYERPROC glFramebufferTextureLayer; //GL_ARB_draw_buffers extern PFNGLDRAWBUFFERSARBPROC glDrawBuffersARB; +//GL_ARB_texture_multisample +extern PFNGLTEXIMAGE2DMULTISAMPLEPROC glTexImage2DMultisample; +extern PFNGLTEXIMAGE3DMULTISAMPLEPROC glTexImage3DMultisample; +extern PFNGLGETMULTISAMPLEFVPROC glGetMultisamplefv; +extern PFNGLSAMPLEMASKIPROC glSampleMaski; #elif LL_DARWIN //---------------------------------------------------------------------------- @@ -697,7 +752,7 @@ extern PFNGLDRAWBUFFERSARBPROC glDrawBuffersARB; #include <AvailabilityMacros.h> //GL_EXT_blend_func_separate -extern void glBlendFuncSeparateEXT(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER; +extern void glBlendFuncSeparateEXT(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha) ; // GL_EXT_framebuffer_object extern GLboolean glIsRenderbufferEXT(GLuint renderbuffer) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER; @@ -718,12 +773,57 @@ 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 +#define GL_MAX_SAMPLES 0x8D57 +#endif + // GL_ARB_draw_buffers extern void glDrawBuffersARB(GLsizei n, const GLenum* bufs) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER; #ifdef __cplusplus extern "C" { #endif + +// +// Define map buffer range headers on Mac +// +#ifndef GL_ARB_map_buffer_range +#define GL_MAP_READ_BIT 0x0001 +#define GL_MAP_WRITE_BIT 0x0002 +#define GL_MAP_INVALIDATE_RANGE_BIT 0x0004 +#define GL_MAP_INVALIDATE_BUFFER_BIT 0x0008 +#define GL_MAP_FLUSH_EXPLICIT_BIT 0x0010 +#define GL_MAP_UNSYNCHRONIZED_BIT 0x0020 +#endif + +// +// Define multisample headers on Mac +// +#ifndef GL_ARB_texture_multisample +#define GL_SAMPLE_POSITION 0x8E50 +#define GL_SAMPLE_MASK 0x8E51 +#define GL_SAMPLE_MASK_VALUE 0x8E52 +#define GL_MAX_SAMPLE_MASK_WORDS 0x8E59 +#define GL_TEXTURE_2D_MULTISAMPLE 0x9100 +#define GL_PROXY_TEXTURE_2D_MULTISAMPLE 0x9101 +#define GL_TEXTURE_2D_MULTISAMPLE_ARRAY 0x9102 +#define GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY 0x9103 +#define GL_TEXTURE_BINDING_2D_MULTISAMPLE 0x9104 +#define GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY 0x9105 +#define GL_TEXTURE_SAMPLES 0x9106 +#define GL_TEXTURE_FIXED_SAMPLE_LOCATIONS 0x9107 +#define GL_SAMPLER_2D_MULTISAMPLE 0x9108 +#define GL_INT_SAMPLER_2D_MULTISAMPLE 0x9109 +#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE 0x910A +#define GL_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910B +#define GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910C +#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910D +#define GL_MAX_COLOR_TEXTURE_SAMPLES 0x910E +#define GL_MAX_DEPTH_TEXTURE_SAMPLES 0x910F +#define GL_MAX_INTEGER_SAMPLES 0x9110 +#endif + // // Define vertex buffer object headers on Mac // @@ -760,7 +860,7 @@ extern "C" { #define GL_DYNAMIC_READ_ARB 0x88E9 #define GL_DYNAMIC_COPY_ARB 0x88EA #endif - + #ifndef GL_ARB_vertex_buffer_object @@ -840,4 +940,22 @@ 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 16534fa9a5..f51d83abe4 100644 --- a/indra/llrender/llglslshader.cpp +++ b/indra/llrender/llglslshader.cpp @@ -48,6 +48,14 @@ using std::pair; using std::make_pair; using std::string; +GLhandleARB LLGLSLShader::sCurBoundShader = 0; +LLGLSLShader* LLGLSLShader::sCurBoundShaderPtr = NULL; +bool LLGLSLShader::sNoFixedFunction = false; + +//UI shader -- declared here so llui_libtest will link properly +LLGLSLShader gUIProgram; +LLGLSLShader gSolidColorProgram; + BOOL shouldChange(const LLVector4& v1, const LLVector4& v2) { return v1 != v2; @@ -55,8 +63,9 @@ BOOL shouldChange(const LLVector4& v1, const LLVector4& v2) LLShaderFeatures::LLShaderFeatures() : calculatesLighting(false), isShiny(false), isFullbright(false), hasWaterFog(false), -hasTransport(false), hasSkinning(false), hasAtmospherics(false), isSpecular(false), -hasGamma(false), hasLighting(false), calculatesAtmospherics(false) +hasTransport(false), hasSkinning(false), hasObjectSkinning(false), hasAtmospherics(false), isSpecular(false), +hasGamma(false), hasLighting(false), calculatesAtmospherics(false), mIndexedTextureChannels(0), disableTextureIndex(false), +hasAlphaMask(false) { } @@ -107,18 +116,18 @@ BOOL LLGLSLShader::createShader(vector<string> * attributes, // Create program mProgramObject = glCreateProgramObjectARB(); - // Attach existing objects - if (!LLShaderMgr::instance()->attachShaderFeatures(this)) - { - return FALSE; + if (gGLManager.mGLVersion < 3.1f) + { //force indexed texture channels to 1 if GL version is old (performance improvement for drivers with poor branching shader model support) + mFeatures.mIndexedTextureChannels = llmin(mFeatures.mIndexedTextureChannels, 1); } + //compile new source vector< pair<string,GLenum> >::iterator fileIter = mShaderFiles.begin(); for ( ; fileIter != mShaderFiles.end(); fileIter++ ) { - GLhandleARB shaderhandle = LLShaderMgr::instance()->loadShaderFile((*fileIter).first, mShaderLevel, (*fileIter).second); + GLhandleARB shaderhandle = LLShaderMgr::instance()->loadShaderFile((*fileIter).first, mShaderLevel, (*fileIter).second, mFeatures.mIndexedTextureChannels); LL_DEBUGS("ShaderLoading") << "SHADER FILE: " << (*fileIter).first << " mShaderLevel=" << mShaderLevel << LL_ENDL; - if (mShaderLevel > 0) + if (shaderhandle > 0) { attachObject(shaderhandle); } @@ -128,6 +137,17 @@ BOOL LLGLSLShader::createShader(vector<string> * attributes, } } + // Attach existing objects + if (!LLShaderMgr::instance()->attachShaderFeatures(this)) + { + return FALSE; + } + + if (gGLManager.mGLVersion < 3.1f) + { //attachShaderFeatures may have set the number of indexed texture channels, so set to 1 again + mFeatures.mIndexedTextureChannels = llmin(mFeatures.mIndexedTextureChannels, 1); + } + // Map attributes and uniforms if (success) { @@ -149,6 +169,29 @@ BOOL LLGLSLShader::createShader(vector<string> * attributes, return createShader(attributes,uniforms); } } + else if (mFeatures.mIndexedTextureChannels > 0) + { //override texture channels for indexed texture rendering + bind(); + S32 channel_count = mFeatures.mIndexedTextureChannels; + + for (S32 i = 0; i < channel_count; i++) + { + uniform1i(llformat("tex%d", i), i); + } + + S32 cur_tex = channel_count; //adjust any texture channels that might have been overwritten + for (U32 i = 0; i < mTexture.size(); i++) + { + if (mTexture[i] > -1 && mTexture[i] < channel_count) + { + llassert(cur_tex < gGLManager.mNumTextureImageUnits); + uniform1i(i, cur_tex); + mTexture[i] = cur_tex++; + } + } + unbind(); + } + return success; } @@ -293,7 +336,8 @@ void LLGLSLShader::mapUniform(GLint index, const vector<string> * uniforms) GLint LLGLSLShader::mapUniformTextureChannel(GLint location, GLenum type) { - if (type >= GL_SAMPLER_1D_ARB && type <= GL_SAMPLER_2D_RECT_SHADOW_ARB) + if (type >= GL_SAMPLER_1D_ARB && type <= GL_SAMPLER_2D_RECT_SHADOW_ARB || + type == GL_SAMPLER_2D_MULTISAMPLE) { //this here is a texture glUniform1iARB(location, mActiveTextureChannels); LL_DEBUGS("ShaderLoading") << "Assigned to texture channel " << mActiveTextureChannels << LL_ENDL; @@ -339,10 +383,12 @@ BOOL LLGLSLShader::link(BOOL suppress_errors) void LLGLSLShader::bind() { + gGL.flush(); if (gGLManager.mHasShaderObjects) { glUseProgramObjectARB(mProgramObject); - + sCurBoundShader = mProgramObject; + sCurBoundShaderPtr = this; if (mUniformsDirty) { LLShaderMgr::instance()->updateShaderUniforms(this); @@ -353,6 +399,7 @@ void LLGLSLShader::bind() void LLGLSLShader::unbind() { + gGL.flush(); if (gGLManager.mHasShaderObjects) { stop_glerror(); @@ -365,6 +412,8 @@ void LLGLSLShader::unbind() } } glUseProgramObjectARB(0); + sCurBoundShader = 0; + sCurBoundShaderPtr = NULL; stop_glerror(); } } @@ -372,6 +421,8 @@ void LLGLSLShader::unbind() void LLGLSLShader::bindNoShader(void) { glUseProgramObjectARB(0); + sCurBoundShader = 0; + sCurBoundShaderPtr = NULL; } S32 LLGLSLShader::enableTexture(S32 uniform, LLTexUnit::eTextureType mode) @@ -698,17 +749,46 @@ void LLGLSLShader::uniformMatrix4fv(U32 index, U32 count, GLboolean transpose, c GLint LLGLSLShader::getUniformLocation(const string& uniform) { + GLint ret = -1; if (mProgramObject > 0) { std::map<string, GLint>::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) +{ + if (attrib < mAttribute.size()) + { + return mAttribute[attrib]; + } + else + { + return -1; + } } void LLGLSLShader::uniform1i(const string& uniform, GLint v) @@ -882,7 +962,9 @@ void LLGLSLShader::uniformMatrix4fv(const string& uniform, U32 count, GLboolean if (location >= 0) { + stop_glerror(); glUniformMatrix4fvARB(location, count, transpose, v); + stop_glerror(); } } @@ -902,3 +984,9 @@ void LLGLSLShader::vertexAttrib4fv(U32 index, GLfloat* v) glVertexAttrib4fvARB(mAttribute[index], v); } } + +void LLGLSLShader::setAlphaRange(F32 minimum, F32 maximum) +{ + uniform1f("minimum_alpha", minimum); + uniform1f("maximum_alpha", maximum); +} diff --git a/indra/llrender/llglslshader.h b/indra/llrender/llglslshader.h index c11bd50716..558ea66b50 100644 --- a/indra/llrender/llglslshader.h +++ b/indra/llrender/llglslshader.h @@ -42,8 +42,12 @@ public: bool hasWaterFog; // implies no gamma bool hasTransport; // implies no lighting (it's possible to have neither though) bool hasSkinning; + bool hasObjectSkinning; bool hasAtmospherics; bool hasGamma; + S32 mIndexedTextureChannels; + bool disableTextureIndex; + bool hasAlphaMask; // char numLights; @@ -63,6 +67,11 @@ public: LLGLSLShader(); + static GLhandleARB sCurBoundShader; + static LLGLSLShader* sCurBoundShaderPtr; + + static bool sNoFixedFunction; + void unload(); BOOL createShader(std::vector<std::string> * attributes, std::vector<std::string> * uniforms); @@ -99,11 +108,13 @@ public: void uniformMatrix3fv(const std::string& uniform, U32 count, GLboolean transpose, const GLfloat *v); void uniformMatrix4fv(const std::string& uniform, U32 count, GLboolean transpose, const GLfloat *v); + void setAlphaRange(F32 minimum, F32 maximum); + void vertexAttrib4f(U32 index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); void vertexAttrib4fv(U32 index, GLfloat* v); GLint getUniformLocation(const std::string& uniform); - + GLint getAttribLocation(U32 attrib); GLint mapUniformTextureChannel(GLint location, GLenum type); @@ -136,4 +147,10 @@ public: std::string mName; }; +//UI shader (declared here so llui_libtest will link properly) +extern LLGLSLShader gUIProgram; +//output vec4(color.rgb,color.a*tex0[tc0].a) +extern LLGLSLShader gSolidColorProgram; + + #endif diff --git a/indra/llrender/llglstates.h b/indra/llrender/llglstates.h index d5a29dcd0c..e26aead676 100644 --- a/indra/llrender/llglstates.h +++ b/indra/llrender/llglstates.h @@ -238,9 +238,11 @@ public: class LLGLSSpecular { public: + F32 mShininess; LLGLSSpecular(const LLColor4& color, F32 shininess) { - if (shininess > 0.0f) + mShininess = shininess; + if (mShininess > 0.0f) { glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, color.mV); S32 shiny = (S32)(shininess*128.f); @@ -250,32 +252,14 @@ public: } ~LLGLSSpecular() { - glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, LLColor4(0.f,0.f,0.f,0.f).mV); - glMateriali(GL_FRONT_AND_BACK, GL_SHININESS, 0); + if (mShininess > 0.f) + { + glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, LLColor4(0.f,0.f,0.f,0.f).mV); + glMateriali(GL_FRONT_AND_BACK, GL_SHININESS, 0); + } } }; //---------------------------------------------------------------------------- - -class LLGLSBlendFunc : public LLGLSPipeline { -protected: - GLint mSavedSrc, mSavedDst; - LLGLEnable mBlend; - -public: - LLGLSBlendFunc(GLenum srcFunc, GLenum dstFunc) : - mBlend(GL_BLEND) - { - glGetIntegerv(GL_BLEND_SRC, &mSavedSrc); - glGetIntegerv(GL_BLEND_DST, &mSavedDst); - glBlendFunc(srcFunc, dstFunc); - } - - ~LLGLSBlendFunc(void) { - glBlendFunc(mSavedSrc, mSavedDst); - } -}; - - #endif diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index d4ffd6f88e..7188b0fa44 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -1083,12 +1083,17 @@ void LLImageGL::generateTextures(S32 numTextures, U32 *textures) } // static -void LLImageGL::deleteTextures(S32 numTextures, U32 *textures) +void LLImageGL::deleteTextures(S32 numTextures, U32 *textures, bool immediate) { for (S32 i = 0; i < numTextures; i++) { sDeadTextureList.push_back(textures[i]); } + + if (immediate) + { + LLImageGL::deleteDeadTextures(); + } } // static @@ -1409,22 +1414,36 @@ BOOL LLImageGL::readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compre void LLImageGL::deleteDeadTextures() { + bool reset = false; + while (!sDeadTextureList.empty()) { GLuint tex = sDeadTextureList.front(); sDeadTextureList.pop_front(); - for (int i = 0; i < gGLManager.mNumTextureUnits; i++) + for (int i = 0; i < gGLManager.mNumTextureImageUnits; i++) { - if (sCurrentBoundTextures[i] == tex) + LLTexUnit* tex_unit = gGL.getTexUnit(i); + + if (tex_unit && tex_unit->getCurrTexture() == tex) { - gGL.getTexUnit(i)->unbind(LLTexUnit::TT_TEXTURE); + tex_unit->unbind(tex_unit->getCurrType()); stop_glerror(); + + if (i > 0) + { + reset = true; + } } } glDeleteTextures(1, &tex); stop_glerror(); } + + if (reset) + { + gGL.getTexUnit(0)->activate(); + } } void LLImageGL::destroyGLTexture() @@ -1710,6 +1729,7 @@ void LLImageGL::analyzeAlpha(const void* data_in, U32 w, U32 h) sample[asum/(16*4)] += 4; } + rowstart += 2 * w * mAlphaStride; } length *= 2; // we sampled everything twice, essentially @@ -1867,6 +1887,7 @@ BOOL LLImageGL::getMask(const LLVector2 &tc) void LLImageGL::setCategory(S32 category) { +#if 0 //turn this off temporarily because it is not in use now. if(!gAuditTexture) { return ; @@ -1887,6 +1908,7 @@ void LLImageGL::setCategory(S32 category) mCategory = -1 ; } } +#endif } //for debug use diff --git a/indra/llrender/llimagegl.h b/indra/llrender/llimagegl.h index 6c980984c0..2cfb15b0d9 100644 --- a/indra/llrender/llimagegl.h +++ b/indra/llrender/llimagegl.h @@ -98,7 +98,7 @@ public: // These 3 functions currently wrap glGenTextures(), glDeleteTextures(), and glTexImage2D() // for tracking purposes and will be deprecated in the future static void generateTextures(S32 numTextures, U32 *textures); - static void deleteTextures(S32 numTextures, U32 *textures); + static void deleteTextures(S32 numTextures, U32 *textures, bool immediate = false); static void setManualImage(U32 target, S32 miplevel, S32 intformat, S32 width, S32 height, U32 pixformat, U32 pixtype, const void *pixels); BOOL createGLTexture() ; diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index 8eb160f4e7..edcc47aa14 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -30,6 +30,7 @@ #include "llvertexbuffer.h" #include "llcubemap.h" +#include "llglslshader.h" #include "llimagegl.h" #include "llrendertarget.h" #include "lltexture.h" @@ -45,14 +46,17 @@ S32 gGLViewport[4]; U32 LLRender::sUICalls = 0; U32 LLRender::sUIVerts = 0; +U32 LLTexUnit::sWhiteTexture = 0; -static const U32 LL_NUM_TEXTURE_LAYERS = 16; +static const U32 LL_NUM_TEXTURE_LAYERS = 32; +static const U32 LL_NUM_LIGHT_UNITS = 8; static GLenum sGLTextureType[] = { GL_TEXTURE_2D, GL_TEXTURE_RECTANGLE_ARB, - GL_TEXTURE_CUBE_MAP_ARB + GL_TEXTURE_CUBE_MAP_ARB, + GL_TEXTURE_2D_MULTISAMPLE }; static GLint sGLAddressMode[] = @@ -118,14 +122,30 @@ void LLTexUnit::refreshState(void) gGL.flush(); 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 = !LLGLSLShader::sNoFixedFunction && + (mIndex < gGLManager.mNumTextureUnits) && mCurrTexType != LLTexUnit::TT_MULTISAMPLE_TEXTURE; + 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); } @@ -166,7 +186,12 @@ void LLTexUnit::enable(eTextureType type) mCurrTexType = type; gGL.flush(); - glEnable(sGLTextureType[type]); + if (!LLGLSLShader::sNoFixedFunction && + type != LLTexUnit::TT_MULTISAMPLE_TEXTURE && + mIndex < gGLManager.mNumTextureUnits) + { + glEnable(sGLTextureType[type]); + } } } @@ -179,7 +204,13 @@ void LLTexUnit::disable(void) activate(); unbind(mCurrTexType); gGL.flush(); - glDisable(sGLTextureType[mCurrTexType]); + if (!LLGLSLShader::sNoFixedFunction && + mCurrTexType != LLTexUnit::TT_MULTISAMPLE_TEXTURE && + mIndex < gGLManager.mNumTextureUnits) + { + glDisable(sGLTextureType[mCurrTexType]); + } + mCurrTexType = TT_NONE; } } @@ -376,7 +407,15 @@ void LLTexUnit::unbind(eTextureType type) activate(); mCurrTexture = 0; - glBindTexture(sGLTextureType[type], 0); + if (LLGLSLShader::sNoFixedFunction && type == LLTexUnit::TT_TEXTURE) + { + glBindTexture(sGLTextureType[type], sWhiteTexture); + } + else + { + glBindTexture(sGLTextureType[type], 0); + } + stop_glerror(); } } @@ -398,7 +437,7 @@ void LLTexUnit::setTextureAddressMode(eTextureAddressMode mode) void LLTexUnit::setTextureFilteringOption(LLTexUnit::eTextureFilterOptions option) { - if (mIndex < 0 || mCurrTexture == 0) return; + if (mIndex < 0 || mCurrTexture == 0 || mCurrTexType == LLTexUnit::TT_MULTISAMPLE_TEXTURE) return; gGL.flush(); @@ -446,6 +485,11 @@ void LLTexUnit::setTextureFilteringOption(LLTexUnit::eTextureFilterOptions optio void LLTexUnit::setTextureBlendType(eTextureBlendType type) { + if (LLGLSLShader::sNoFixedFunction) + { //texture blend type means nothing when using shaders + return; + } + if (mIndex < 0) return; // Do nothing if it's already correctly set. @@ -566,6 +610,11 @@ GLint LLTexUnit::getTextureSourceType(eTextureBlendSrc src, bool isAlpha) void LLTexUnit::setTextureCombiner(eTextureBlendOp op, eTextureBlendSrc src1, eTextureBlendSrc src2, bool isAlpha) { + if (LLGLSLShader::sNoFixedFunction) + { //register combiners do nothing when not using fixed function + return; + } + if (mIndex < 0) return; activate(); @@ -747,6 +796,130 @@ void LLTexUnit::debugTextureUnit(void) } } +LLLightState::LLLightState(S32 index) +: mIndex(index), + mEnabled(false), + mConstantAtten(1.f), + mLinearAtten(0.f), + mQuadraticAtten(0.f), + mSpotExponent(0.f), + mSpotCutoff(180.f) +{ + if (mIndex == 0) + { + mDiffuse.set(1,1,1,1); + mSpecular.set(1,1,1,1); + } + + mAmbient.set(0,0,0,1); + mPosition.set(0,0,1,0); + mSpotDirection.set(0,0,-1); + +} + +void LLLightState::enable() +{ + if (!mEnabled) + { + glEnable(GL_LIGHT0+mIndex); + mEnabled = true; + } +} + +void LLLightState::disable() +{ + if (mEnabled) + { + glDisable(GL_LIGHT0+mIndex); + mEnabled = false; + } +} + +void LLLightState::setDiffuse(const LLColor4& diffuse) +{ + if (mDiffuse != diffuse) + { + mDiffuse = diffuse; + glLightfv(GL_LIGHT0+mIndex, GL_DIFFUSE, mDiffuse.mV); + } +} + +void LLLightState::setAmbient(const LLColor4& ambient) +{ + if (mAmbient != ambient) + { + mAmbient = ambient; + glLightfv(GL_LIGHT0+mIndex, GL_AMBIENT, mAmbient.mV); + } +} + +void LLLightState::setSpecular(const LLColor4& specular) +{ + if (mSpecular != specular) + { + mSpecular = specular; + glLightfv(GL_LIGHT0+mIndex, GL_SPECULAR, mSpecular.mV); + } +} + +void LLLightState::setPosition(const LLVector4& position) +{ + //always set position because modelview matrix may have changed + mPosition = position; + glLightfv(GL_LIGHT0+mIndex, GL_POSITION, mPosition.mV); +} + +void LLLightState::setConstantAttenuation(const F32& atten) +{ + if (mConstantAtten != atten) + { + mConstantAtten = atten; + glLightf(GL_LIGHT0+mIndex, GL_CONSTANT_ATTENUATION, atten); + } +} + +void LLLightState::setLinearAttenuation(const F32& atten) +{ + if (mLinearAtten != atten) + { + mLinearAtten = atten; + glLightf(GL_LIGHT0+mIndex, GL_LINEAR_ATTENUATION, atten); + } +} + +void LLLightState::setQuadraticAttenuation(const F32& atten) +{ + if (mQuadraticAtten != atten) + { + mQuadraticAtten = atten; + glLightf(GL_LIGHT0+mIndex, GL_QUADRATIC_ATTENUATION, atten); + } +} + +void LLLightState::setSpotExponent(const F32& exponent) +{ + if (mSpotExponent != exponent) + { + mSpotExponent = exponent; + glLightf(GL_LIGHT0+mIndex, GL_SPOT_EXPONENT, exponent); + } +} + +void LLLightState::setSpotCutoff(const F32& cutoff) +{ + if (mSpotCutoff != cutoff) + { + mSpotCutoff = cutoff; + glLightf(GL_LIGHT0+mIndex, GL_SPOT_CUTOFF, cutoff); + } +} + +void LLLightState::setSpotDirection(const LLVector3& direction) +{ + //always set direction because modelview matrix may have changed + mSpotDirection = direction; + glLightfv(GL_LIGHT0+mIndex, GL_SPOT_DIRECTION, direction.mV); +} LLRender::LLRender() : mDirty(false), @@ -754,13 +927,7 @@ LLRender::LLRender() mMode(LLRender::TRIANGLES), mCurrTextureUnitIndex(0), mMaxAnisotropy(0.f) -{ - mBuffer = new LLVertexBuffer(immediate_mask, 0); - mBuffer->allocateBuffer(4096, 0, TRUE); - mBuffer->getVertexStrider(mVerticesp); - mBuffer->getTexCoord0Strider(mTexcoordsp); - mBuffer->getColorStrider(mColorsp); - +{ mTexUnits.reserve(LL_NUM_TEXTURE_LAYERS); for (U32 i = 0; i < LL_NUM_TEXTURE_LAYERS; i++) { @@ -768,6 +935,11 @@ LLRender::LLRender() } mDummyTexUnit = new LLTexUnit(-1); + for (U32 i = 0; i < LL_NUM_LIGHT_UNITS; ++i) + { + mLightState.push_back(new LLLightState(i)); + } + for (U32 i = 0; i < 4; i++) { mCurrColorMask[i] = true; @@ -786,6 +958,17 @@ LLRender::~LLRender() shutdown(); } +void LLRender::init() +{ + llassert_always(mBuffer.isNull()) ; + + mBuffer = new LLVertexBuffer(immediate_mask, 0); + mBuffer->allocateBuffer(4096, 0, TRUE); + mBuffer->getVertexStrider(mVerticesp); + mBuffer->getTexCoord0Strider(mTexcoordsp); + mBuffer->getColorStrider(mColorsp); +} + void LLRender::shutdown() { for (U32 i = 0; i < mTexUnits.size(); i++) @@ -795,6 +978,13 @@ void LLRender::shutdown() mTexUnits.clear(); delete mDummyTexUnit; mDummyTexUnit = NULL; + + for (U32 i = 0; i < mLightState.size(); ++i) + { + delete mLightState[i]; + } + mLightState.clear(); + mBuffer = NULL ; } void LLRender::refreshState(void) @@ -898,7 +1088,7 @@ LLVector3 LLRender::getUITranslation() { if (mUIOffset.empty()) { - return LLVector3::zero; + return LLVector3(0,0,0); } return mUIOffset.back(); } @@ -907,7 +1097,7 @@ LLVector3 LLRender::getUIScale() { if (mUIScale.empty()) { - return LLVector3(1.f, 1.f, 1.f); + return LLVector3(1,1,1); } return mUIScale.back(); } @@ -932,15 +1122,21 @@ void LLRender::setColorMask(bool writeColorR, bool writeColorG, bool writeColorB { flush(); - mCurrColorMask[0] = writeColorR; - mCurrColorMask[1] = writeColorG; - mCurrColorMask[2] = writeColorB; - mCurrColorMask[3] = writeAlpha; + if (mCurrColorMask[0] != writeColorR || + mCurrColorMask[1] != writeColorG || + mCurrColorMask[2] != writeColorB || + mCurrColorMask[3] != writeAlpha) + { + mCurrColorMask[0] = writeColorR; + mCurrColorMask[1] = writeColorG; + mCurrColorMask[2] = writeColorB; + mCurrColorMask[3] = writeAlpha; - glColorMask(writeColorR ? GL_TRUE : GL_FALSE, - writeColorG ? GL_TRUE : GL_FALSE, - writeColorB ? GL_TRUE : GL_FALSE, - writeAlpha ? GL_TRUE : GL_FALSE); + glColorMask(writeColorR ? GL_TRUE : GL_FALSE, + writeColorG ? GL_TRUE : GL_FALSE, + writeColorB ? GL_TRUE : GL_FALSE, + writeAlpha ? GL_TRUE : GL_FALSE); + } } void LLRender::setSceneBlendType(eBlendType type) @@ -978,15 +1174,48 @@ void LLRender::setAlphaRejectSettings(eCompareFunc func, F32 value) { flush(); - mCurrAlphaFunc = func; - mCurrAlphaFuncVal = value; - if (func == CF_DEFAULT) - { - glAlphaFunc(GL_GREATER, 0.01f); - } - else + if (LLGLSLShader::sNoFixedFunction) + { //glAlphaFunc is deprecated in OpenGL 3.3 + return; + } + + if (mCurrAlphaFunc != func || + mCurrAlphaFuncVal != value) { - glAlphaFunc(sGLCompareFunc[func], value); + mCurrAlphaFunc = func; + mCurrAlphaFuncVal = value; + if (func == CF_DEFAULT) + { + glAlphaFunc(GL_GREATER, 0.01f); + } + else + { + glAlphaFunc(sGLCompareFunc[func], value); + } + } + + if (gDebugGL) + { //make sure cached state is correct + GLint cur_func = 0; + glGetIntegerv(GL_ALPHA_TEST_FUNC, &cur_func); + + if (func == CF_DEFAULT) + { + func = CF_GREATER; + } + + if (cur_func != sGLCompareFunc[func]) + { + llerrs << "Alpha test function corrupted!" << llendl; + } + + F32 ref = 0.f; + glGetFloatv(GL_ALPHA_TEST_REF, &ref); + + if (ref != value) + { + llerrs << "Alpha test value corrupted!" << llendl; + } } } @@ -1045,6 +1274,16 @@ LLTexUnit* LLRender::getTexUnit(U32 index) } } +LLLightState* LLRender::getLight(U32 index) +{ + if (index < mLightState.size()) + { + return mLightState[index]; + } + + return NULL; +} + bool LLRender::verifyTexUnitActive(U32 unitToVerify) { if (mCurrTextureUnitIndex == unitToVerify) diff --git a/indra/llrender/llrender.h b/indra/llrender/llrender.h index 2767aa64a8..8f7ee30d87 100644 --- a/indra/llrender/llrender.h +++ b/indra/llrender/llrender.h @@ -37,6 +37,7 @@ #include "v2math.h" #include "v3math.h" #include "v4coloru.h" +#include "v4math.h" #include "llstrider.h" #include "llpointer.h" #include "llglheaders.h" @@ -51,11 +52,14 @@ class LLTexUnit { friend class LLRender; public: + static U32 sWhiteTexture; + typedef enum { TT_TEXTURE = 0, // Standard 2D Texture TT_RECT_TEXTURE, // Non power of 2 texture TT_CUBE_MAP, // 6-sided cube map texture + TT_MULTISAMPLE_TEXTURE, // see GL_ARB_texture_multisample TT_NONE // No texture type is currently enabled } eTextureType; @@ -212,6 +216,41 @@ protected: void setTextureCombiner(eTextureBlendOp op, eTextureBlendSrc src1, eTextureBlendSrc src2, bool isAlpha = false); }; +class LLLightState +{ +public: + LLLightState(S32 index); + + void enable(); + void disable(); + void setDiffuse(const LLColor4& diffuse); + void setAmbient(const LLColor4& ambient); + void setSpecular(const LLColor4& specular); + void setPosition(const LLVector4& position); + void setConstantAttenuation(const F32& atten); + void setLinearAttenuation(const F32& atten); + void setQuadraticAttenuation(const F32& atten); + void setSpotExponent(const F32& exponent); + void setSpotCutoff(const F32& cutoff); + void setSpotDirection(const LLVector3& direction); + +protected: + S32 mIndex; + bool mEnabled; + LLColor4 mDiffuse; + LLColor4 mAmbient; + LLColor4 mSpecular; + LLVector4 mPosition; + LLVector3 mSpotDirection; + + F32 mConstantAtten; + F32 mLinearAtten; + F32 mQuadraticAtten; + + F32 mSpotExponent; + F32 mSpotCutoff; +}; + class LLRender { friend class LLTexUnit; @@ -271,6 +310,7 @@ public: LLRender(); ~LLRender(); + void init() ; void shutdown(); // Refreshes renderer state to the cached values @@ -327,6 +367,8 @@ public: void blendFunc(eBlendFactor color_sfactor, eBlendFactor color_dfactor, eBlendFactor alpha_sfactor, eBlendFactor alpha_dfactor); + LLLightState* getLight(U32 index); + LLTexUnit* getTexUnit(U32 index); U32 getCurrentTexUnitIndex(void) const { return mCurrTextureUnitIndex; } @@ -363,6 +405,7 @@ private: LLStrider<LLColor4U> mColorsp; std::vector<LLTexUnit*> mTexUnits; LLTexUnit* mDummyTexUnit; + std::vector<LLLightState*> mLightState; eBlendFactor mCurrBlendColorSFactor; eBlendFactor mCurrBlendColorDFactor; diff --git a/indra/llrender/llrendertarget.cpp b/indra/llrender/llrendertarget.cpp index 7205210fcc..8c0d3592df 100644 --- a/indra/llrender/llrendertarget.cpp +++ b/indra/llrender/llrendertarget.cpp @@ -38,19 +38,20 @@ void check_framebuffer_status() { if (gDebugGL) { - GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); + GLenum status = glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER); switch (status) { - case GL_FRAMEBUFFER_COMPLETE_EXT: + case GL_FRAMEBUFFER_COMPLETE: break; default: + llwarns << "check_framebuffer_status failed -- " << std::hex << status << llendl; ll_fail("check_framebuffer_status failed"); break; } } } -BOOL LLRenderTarget::sUseFBO = FALSE; +bool LLRenderTarget::sUseFBO = false; LLRenderTarget::LLRenderTarget() : mResX(0), @@ -59,11 +60,10 @@ LLRenderTarget::LLRenderTarget() : mFBO(0), mDepth(0), mStencil(0), - mUseDepth(FALSE), - mRenderDepth(FALSE), + mUseDepth(false), + mRenderDepth(false), mUsage(LLTexUnit::TT_TEXTURE), - mSamples(0), - mSampleBuffer(NULL) + mSamples(0) { } @@ -72,64 +72,75 @@ LLRenderTarget::~LLRenderTarget() release(); } - -void LLRenderTarget::setSampleBuffer(LLMultisampleBuffer* buffer) -{ - mSampleBuffer = buffer; -} - -void LLRenderTarget::allocate(U32 resx, U32 resy, U32 color_fmt, BOOL depth, BOOL stencil, LLTexUnit::eTextureType usage, BOOL use_fbo) +bool LLRenderTarget::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil, LLTexUnit::eTextureType usage, bool use_fbo, S32 samples) { stop_glerror(); + release(); + stop_glerror(); + mResX = resx; mResY = resy; mStencil = stencil; mUsage = usage; mUseDepth = depth; + mSamples = samples; - release(); + mSamples = gGLManager.getNumFBOFSAASamples(mSamples); + + if (mSamples > 1 && gGLManager.mHasTextureMultisample) + { + mUsage = LLTexUnit::TT_MULTISAMPLE_TEXTURE; + //no support for multisampled stencil targets yet + mStencil = false; + } + else + { + mSamples = 0; + } if ((sUseFBO || use_fbo) && gGLManager.mHasFramebufferObject) { if (depth) { - stop_glerror(); - allocateDepth(); - stop_glerror(); + if (!allocateDepth()) + { + llwarns << "Failed to allocate depth buffer for render target." << llendl; + return false; + } } - glGenFramebuffersEXT(1, (GLuint *) &mFBO); + glGenFramebuffers(1, (GLuint *) &mFBO); if (mDepth) { - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFBO); + glBindFramebuffer(GL_FRAMEBUFFER, mFBO); if (mStencil) { - glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, mDepth); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, mDepth); stop_glerror(); - glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, mDepth); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, mDepth); stop_glerror(); } else { - glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, LLTexUnit::getInternalType(mUsage), mDepth, 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, LLTexUnit::getInternalType(mUsage), mDepth, 0); stop_glerror(); } - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + glBindFramebuffer(GL_FRAMEBUFFER, 0); } stop_glerror(); } - addColorAttachment(color_fmt); + return addColorAttachment(color_fmt); } -void LLRenderTarget::addColorAttachment(U32 color_fmt) +bool LLRenderTarget::addColorAttachment(U32 color_fmt) { if (color_fmt == 0) { - return; + return true; } U32 offset = mTex.size(); @@ -145,61 +156,127 @@ void LLRenderTarget::addColorAttachment(U32 color_fmt) stop_glerror(); - LLImageGL::setManualImage(LLTexUnit::getInternalType(mUsage), 0, color_fmt, mResX, mResY, GL_RGBA, GL_UNSIGNED_BYTE, NULL); - stop_glerror(); - - if (offset == 0) +#ifdef GL_ARB_texture_multisample + if (mSamples > 1) { - gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR); + clear_glerror(); + glTexImage2DMultisample(LLTexUnit::getInternalType(mUsage), mSamples, color_fmt, mResX, mResY, GL_TRUE); + if (glGetError() != GL_NO_ERROR) + { + llwarns << "Could not allocate multisample color buffer for render target." << llendl; + return false; + } } else - { //don't filter data attachments - gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT); - } - if (mUsage != LLTexUnit::TT_RECT_TEXTURE) +#else + llassert_always(mSamples <= 1); +#endif { - gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_MIRROR); + clear_glerror(); + LLImageGL::setManualImage(LLTexUnit::getInternalType(mUsage), 0, color_fmt, mResX, mResY, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + if (glGetError() != GL_NO_ERROR) + { + llwarns << "Could not allocate color buffer for render target." << llendl; + return false; + } } - else - { - // ATI doesn't support mirrored repeat for rectangular textures. - gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); + + stop_glerror(); + + if (mSamples == 0) + { + if (offset == 0) + { //use bilinear filtering on single texture render targets that aren't multisampled + gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR); + stop_glerror(); + } + else + { //don't filter data attachments + gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT); + stop_glerror(); + } + + if (mUsage != LLTexUnit::TT_RECT_TEXTURE) + { + gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_MIRROR); + stop_glerror(); + } + else + { + // ATI doesn't support mirrored repeat for rectangular textures. + gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); + stop_glerror(); + } } + if (mFBO) { - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFBO); - glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT+offset, + stop_glerror(); + glBindFramebuffer(GL_FRAMEBUFFER, mFBO); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0+offset, LLTexUnit::getInternalType(mUsage), tex, 0); stop_glerror(); check_framebuffer_status(); - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + glBindFramebuffer(GL_FRAMEBUFFER, 0); } mTex.push_back(tex); + if (gDebugGL) + { //bind and unbind to validate target + bindTarget(); + flush(); + } + + return true; } -void LLRenderTarget::allocateDepth() +bool LLRenderTarget::allocateDepth() { if (mStencil) { //use render buffers where stencil buffers are in play - glGenRenderbuffersEXT(1, (GLuint *) &mDepth); - glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, mDepth); - glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8_EXT, mResX, mResY); - glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0); + glGenRenderbuffers(1, (GLuint *) &mDepth); + glBindRenderbuffer(GL_RENDERBUFFER, mDepth); + stop_glerror(); + clear_glerror(); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, mResX, mResY); + glBindRenderbuffer(GL_RENDERBUFFER, 0); } else { LLImageGL::generateTextures(1, &mDepth); gGL.getTexUnit(0)->bindManual(mUsage, mDepth); - U32 internal_type = LLTexUnit::getInternalType(mUsage); - gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT); - LLImageGL::setManualImage(internal_type, 0, GL_DEPTH_COMPONENT32_ARB, mResX, mResY, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL); + if (mSamples == 0) + { + U32 internal_type = LLTexUnit::getInternalType(mUsage); + gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT); + stop_glerror(); + clear_glerror(); + LLImageGL::setManualImage(internal_type, 0, GL_DEPTH_COMPONENT32, mResX, mResY, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL); + } +#ifdef GL_ARB_texture_multisample + else + { + stop_glerror(); + clear_glerror(); + glTexImage2DMultisample(LLTexUnit::getInternalType(mUsage), mSamples, GL_DEPTH_COMPONENT32, mResX, mResY, GL_TRUE); + } +#else + llassert_always(mSamples <= 1); +#endif + } + + if (glGetError() != GL_NO_ERROR) + { + llwarns << "Unable to allocate depth buffer for render target." << llendl; + return false; } + + return true; } void LLRenderTarget::shareDepthBuffer(LLRenderTarget& target) @@ -209,65 +286,90 @@ 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(); - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, target.mFBO); + glBindFramebuffer(GL_FRAMEBUFFER, target.mFBO); stop_glerror(); if (mStencil) { - glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, mDepth); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, mDepth); stop_glerror(); - glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, mDepth); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, mDepth); stop_glerror(); + target.mStencil = true; } else { - glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, LLTexUnit::getInternalType(mUsage), mDepth, 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, 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); - target.mUseDepth = TRUE; + check_framebuffer_status(); + + glBindFramebuffer(GL_FRAMEBUFFER, 0); + + target.mUseDepth = true; } } void LLRenderTarget::release() { - if (mFBO) - { - glDeleteFramebuffersEXT(1, (GLuint *) &mFBO); - mFBO = 0; - } - - if (mTex.size() > 0) - { - LLImageGL::deleteTextures(mTex.size(), &mTex[0]); - mTex.clear(); - } - if (mDepth) { if (mStencil) { - glDeleteRenderbuffersEXT(1, (GLuint*) &mDepth); + glDeleteRenderbuffers(1, (GLuint*) &mDepth); stop_glerror(); } else { - LLImageGL::deleteTextures(1, &mDepth); + LLImageGL::deleteTextures(1, &mDepth, true); stop_glerror(); } mDepth = 0; } + else if (mUseDepth && mFBO) + { //detach shared depth buffer + glBindFramebuffer(GL_FRAMEBUFFER, mFBO); + if (mStencil) + { //attached as a renderbuffer + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, 0); + mStencil = false; + } + else + { //attached as a texture + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, LLTexUnit::getInternalType(mUsage), 0, 0); + } + mUseDepth = false; + } + + if (mFBO) + { + glDeleteFramebuffers(1, (GLuint *) &mFBO); + mFBO = 0; + } + + if (mTex.size() > 0) + { + LLImageGL::deleteTextures(mTex.size(), &mTex[0], true); + mTex.clear(); + } + + mResX = mResY = 0; - mSampleBuffer = NULL; sBoundTarget = NULL; } @@ -276,34 +378,27 @@ void LLRenderTarget::bindTarget() if (mFBO) { stop_glerror(); - if (mSampleBuffer) - { - mSampleBuffer->bindTarget(this); - stop_glerror(); + + glBindFramebuffer(GL_FRAMEBUFFER, mFBO); + stop_glerror(); + if (gGLManager.mHasDrawBuffers) + { //setup multiple render targets + GLenum drawbuffers[] = {GL_COLOR_ATTACHMENT0, + GL_COLOR_ATTACHMENT1, + GL_COLOR_ATTACHMENT2, + GL_COLOR_ATTACHMENT3}; + glDrawBuffersARB(mTex.size(), drawbuffers); } - else - { - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFBO); - stop_glerror(); - if (gGLManager.mHasDrawBuffers) - { //setup multiple render targets - GLenum drawbuffers[] = {GL_COLOR_ATTACHMENT0_EXT, - GL_COLOR_ATTACHMENT1_EXT, - GL_COLOR_ATTACHMENT2_EXT, - GL_COLOR_ATTACHMENT3_EXT}; - glDrawBuffersARB(mTex.size(), drawbuffers); - } - if (mTex.empty()) - { //no color buffer to draw to - glDrawBuffer(GL_NONE); - glReadBuffer(GL_NONE); - } + if (mTex.empty()) + { //no color buffer to draw to + glDrawBuffer(GL_NONE); + glReadBuffer(GL_NONE); + } - check_framebuffer_status(); + check_framebuffer_status(); - stop_glerror(); - } + stop_glerror(); } glViewport(0, 0, mResX, mResY); @@ -315,7 +410,7 @@ void LLRenderTarget::unbindTarget() { if (gGLManager.mHasFramebufferObject) { - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + glBindFramebuffer(GL_FRAMEBUFFER, 0); } sBoundTarget = NULL; } @@ -349,19 +444,19 @@ U32 LLRenderTarget::getTexture(U32 attachment) const { llerrs << "Invalid attachment index." << llendl; } + if (mTex.empty()) + { + return 0; + } return mTex[attachment]; } void LLRenderTarget::bindTexture(U32 index, S32 channel) { - if (index > mTex.size()-1) - { - llerrs << "Invalid attachment index." << llendl; - } - gGL.getTexUnit(channel)->bindManual(mUsage, mTex[index]); + gGL.getTexUnit(channel)->bindManual(mUsage, getTexture(index)); } -void LLRenderTarget::flush(BOOL fetch_depth) +void LLRenderTarget::flush(bool fetch_depth) { gGL.flush(); if (!mFBO) @@ -377,7 +472,7 @@ void LLRenderTarget::flush(BOOL fetch_depth) } gGL.getTexUnit(0)->bind(this); - glCopyTexImage2D(LLTexUnit::getInternalType(mUsage), 0, GL_DEPTH24_STENCIL8_EXT, 0, 0, mResX, mResY, 0); + glCopyTexImage2D(LLTexUnit::getInternalType(mUsage), 0, GL_DEPTH24_STENCIL8, 0, 0, mResX, mResY, 0); } gGL.getTexUnit(0)->disable(); @@ -385,93 +480,54 @@ void LLRenderTarget::flush(BOOL fetch_depth) else { stop_glerror(); - - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); - + glBindFramebuffer(GL_FRAMEBUFFER, 0); stop_glerror(); - - if (mSampleBuffer) - { - LLGLEnable multisample(GL_MULTISAMPLE_ARB); - stop_glerror(); - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFBO); - stop_glerror(); - check_framebuffer_status(); - glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, mSampleBuffer->mFBO); - check_framebuffer_status(); - - stop_glerror(); - glBlitFramebufferEXT(0, 0, mResX, mResY, 0, 0, mResX, mResY, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST); - stop_glerror(); - - if (mTex.size() > 1) - { - for (U32 i = 1; i < mTex.size(); ++i) - { - glFramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, - LLTexUnit::getInternalType(mUsage), mTex[i], 0); - stop_glerror(); - glFramebufferRenderbufferEXT(GL_READ_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, mSampleBuffer->mTex[i]); - stop_glerror(); - glBlitFramebufferEXT(0, 0, mResX, mResY, 0, 0, mResX, mResY, GL_COLOR_BUFFER_BIT, GL_NEAREST); - stop_glerror(); - } - - for (U32 i = 0; i < mTex.size(); ++i) - { - glFramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT+i, - LLTexUnit::getInternalType(mUsage), mTex[i], 0); - stop_glerror(); - glFramebufferRenderbufferEXT(GL_READ_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT+i, GL_RENDERBUFFER_EXT, mSampleBuffer->mTex[i]); - stop_glerror(); - } - } - } - - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); } } void LLRenderTarget::copyContents(LLRenderTarget& source, S32 srcX0, S32 srcY0, S32 srcX1, S32 srcY1, S32 dstX0, S32 dstY0, S32 dstX1, S32 dstY1, U32 mask, U32 filter) { + GLboolean write_depth = mask & GL_DEPTH_BUFFER_BIT ? TRUE : FALSE; + + LLGLDepthTest depth(write_depth, write_depth); + gGL.flush(); if (!source.mFBO || !mFBO) { llerrs << "Cannot copy framebuffer contents for non FBO render targets." << llendl; } - if (mSampleBuffer) + + if (mask == GL_DEPTH_BUFFER_BIT && source.mStencil != mStencil) { - mSampleBuffer->copyContents(source, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter); + stop_glerror(); + + glBindFramebuffer(GL_FRAMEBUFFER, source.mFBO); + check_framebuffer_status(); + gGL.getTexUnit(0)->bind(this, true); + stop_glerror(); + glCopyTexSubImage2D(LLTexUnit::getInternalType(mUsage), 0, srcX0, srcY0, dstX0, dstY0, dstX1, dstY1); + stop_glerror(); + glBindFramebuffer(GL_FRAMEBUFFER, 0); + stop_glerror(); } else { - if (mask == GL_DEPTH_BUFFER_BIT && source.mStencil != mStencil) - { - stop_glerror(); - - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, source.mFBO); - gGL.getTexUnit(0)->bind(this, true); - stop_glerror(); - glCopyTexSubImage2D(LLTexUnit::getInternalType(mUsage), 0, srcX0, srcY0, dstX0, dstY0, dstX1, dstY1); - stop_glerror(); - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); - stop_glerror(); - } - else - { - glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, source.mFBO); - stop_glerror(); - glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, mFBO); - stop_glerror(); - check_framebuffer_status(); - stop_glerror(); - glBlitFramebufferEXT(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter); - stop_glerror(); - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); - stop_glerror(); - } + glBindFramebuffer(GL_READ_FRAMEBUFFER, source.mFBO); + stop_glerror(); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mFBO); + stop_glerror(); + check_framebuffer_status(); + stop_glerror(); + glBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter); + stop_glerror(); + glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); + stop_glerror(); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + stop_glerror(); + glBindFramebuffer(GL_FRAMEBUFFER, 0); + stop_glerror(); } } @@ -484,22 +540,26 @@ void LLRenderTarget::copyContentsToFramebuffer(LLRenderTarget& source, S32 srcX0 llerrs << "Cannot copy framebuffer contents for non FBO render targets." << llendl; } { - glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, source.mFBO); + GLboolean write_depth = mask & GL_DEPTH_BUFFER_BIT ? TRUE : FALSE; + + LLGLDepthTest depth(write_depth, write_depth); + + glBindFramebuffer(GL_READ_FRAMEBUFFER, source.mFBO); stop_glerror(); - glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, 0); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); stop_glerror(); check_framebuffer_status(); stop_glerror(); - glBlitFramebufferEXT(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter); + glBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter); stop_glerror(); - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + glBindFramebuffer(GL_FRAMEBUFFER, 0); stop_glerror(); } } -BOOL LLRenderTarget::isComplete() const +bool LLRenderTarget::isComplete() const { - return (!mTex.empty() || mDepth) ? TRUE : FALSE; + return (!mTex.empty() || mDepth) ? true : false; } void LLRenderTarget::getViewport(S32* viewport) @@ -510,188 +570,3 @@ void LLRenderTarget::getViewport(S32* viewport) viewport[3] = mResY; } -//================================================== -// LLMultisampleBuffer implementation -//================================================== -LLMultisampleBuffer::LLMultisampleBuffer() -{ - -} - -LLMultisampleBuffer::~LLMultisampleBuffer() -{ - releaseSampleBuffer(); -} - -void LLMultisampleBuffer::releaseSampleBuffer() -{ - if (mFBO) - { - glDeleteFramebuffersEXT(1, (GLuint *) &mFBO); - mFBO = 0; - } - - if (mTex.size() > 0) - { - glDeleteRenderbuffersEXT(mTex.size(), (GLuint *) &mTex[0]); - mTex.clear(); - } - - if (mDepth) - { - glDeleteRenderbuffersEXT(1, (GLuint *) &mDepth); - mDepth = 0; - } -} - -void LLMultisampleBuffer::bindTarget() -{ - bindTarget(this); -} - -void LLMultisampleBuffer::bindTarget(LLRenderTarget* ref) -{ - if (!ref) - { - ref = this; - } - - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFBO); - if (gGLManager.mHasDrawBuffers) - { //setup multiple render targets - GLenum drawbuffers[] = {GL_COLOR_ATTACHMENT0_EXT, - GL_COLOR_ATTACHMENT1_EXT, - GL_COLOR_ATTACHMENT2_EXT, - GL_COLOR_ATTACHMENT3_EXT}; - glDrawBuffersARB(ref->mTex.size(), drawbuffers); - } - - check_framebuffer_status(); - - 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 ) -{ - allocate(resx,resy,color_fmt,depth,stencil,usage,use_fbo,2); -} - -void LLMultisampleBuffer::allocate(U32 resx, U32 resy, U32 color_fmt, BOOL depth, BOOL stencil, LLTexUnit::eTextureType usage, BOOL use_fbo, U32 samples ) -{ - stop_glerror(); - mResX = resx; - mResY = resy; - - mUsage = usage; - mUseDepth = depth; - mStencil = stencil; - - releaseSampleBuffer(); - - if (!gGLManager.mHasFramebufferMultisample) - { - llerrs << "Attempting to allocate unsupported render target type!" << llendl; - } - - mSamples = samples; - - if (mSamples <= 1) - { - llerrs << "Cannot create a multisample buffer with less than 2 samples." << llendl; - } - - stop_glerror(); - - if ((sUseFBO || use_fbo) && gGLManager.mHasFramebufferObject) - { - - if (depth) - { - stop_glerror(); - allocateDepth(); - stop_glerror(); - } - - glGenFramebuffersEXT(1, (GLuint *) &mFBO); - - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFBO); - - if (mDepth) - { - glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, mDepth); - if (mStencil) - { - glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, mDepth); - } - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); - } - - stop_glerror(); - - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); - stop_glerror(); - } - - addColorAttachment(color_fmt); -} - -void LLMultisampleBuffer::addColorAttachment(U32 color_fmt) -{ - if (color_fmt == 0) - { - return; - } - - U32 offset = mTex.size(); - if (offset >= 4 || - (offset > 0 && (mFBO == 0 || !gGLManager.mHasDrawBuffers))) - { - llerrs << "Too many color attachments!" << llendl; - } - - U32 tex; - glGenRenderbuffersEXT(1, &tex); - - glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, tex); - glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, mSamples, color_fmt, mResX, mResY); - stop_glerror(); - - if (mFBO) - { - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFBO); - glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT+offset, GL_RENDERBUFFER_EXT, tex); - stop_glerror(); - GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); - switch (status) - { - case GL_FRAMEBUFFER_COMPLETE_EXT: - break; - case GL_FRAMEBUFFER_UNSUPPORTED_EXT: - llerrs << "WTF?" << llendl; - break; - default: - llerrs << "WTF?" << llendl; - } - - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); - } - - mTex.push_back(tex); -} - -void LLMultisampleBuffer::allocateDepth() -{ - glGenRenderbuffersEXT(1, (GLuint* ) &mDepth); - glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, mDepth); - if (mStencil) - { - glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, mSamples, GL_DEPTH24_STENCIL8_EXT, mResX, mResY); - } - else - { - glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, mSamples, GL_DEPTH_COMPONENT16_ARB, mResX, mResY); - } -} - diff --git a/indra/llrender/llrendertarget.h b/indra/llrender/llrendertarget.h index ae8613d9be..dea1de12d8 100644 --- a/indra/llrender/llrendertarget.h +++ b/indra/llrender/llrendertarget.h @@ -63,28 +63,25 @@ class LLRenderTarget { public: //whether or not to use FBO implementation - static BOOL sUseFBO; + static bool sUseFBO; LLRenderTarget(); - virtual ~LLRenderTarget(); + ~LLRenderTarget(); //allocate resources for rendering //must be called before use //multiple calls will release previously allocated resources - void allocate(U32 resx, U32 resy, U32 color_fmt, BOOL depth, BOOL stencil, LLTexUnit::eTextureType usage = LLTexUnit::TT_TEXTURE, BOOL use_fbo = FALSE); - - //provide this render target with a multisample resource. - void setSampleBuffer(LLMultisampleBuffer* buffer); + bool allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil, LLTexUnit::eTextureType usage = LLTexUnit::TT_TEXTURE, bool use_fbo = false, S32 samples = 0); //add color buffer attachment //limit of 4 color attachments per render target - virtual void addColorAttachment(U32 color_fmt); + bool addColorAttachment(U32 color_fmt); //allocate a depth texture - virtual void allocateDepth(); + bool allocateDepth(); //share depth buffer with provided render target - virtual void shareDepthBuffer(LLRenderTarget& target); + void shareDepthBuffer(LLRenderTarget& target); //free any allocated resources //safe to call redundantly @@ -92,7 +89,7 @@ public: //bind target for rendering //applies appropriate viewport - virtual void bindTarget(); + void bindTarget(); //unbind target for rendering static void unbindTarget(); @@ -115,7 +112,7 @@ public: U32 getTexture(U32 attachment = 0) const; U32 getDepth(void) const { return mDepth; } - BOOL hasStencil() const { return mStencil; } + bool hasStencil() const { return mStencil; } void bindTexture(U32 index, S32 channel); @@ -125,7 +122,7 @@ public: // call bindTarget once, do all your rendering, call flush once // if fetch_depth is TRUE, every effort will be made to copy the depth buffer into // the current depth texture. A depth texture will be allocated if needed. - void flush(BOOL fetch_depth = FALSE); + void flush(bool fetch_depth = FALSE); void copyContents(LLRenderTarget& source, S32 srcX0, S32 srcY0, S32 srcX1, S32 srcY1, S32 dstX0, S32 dstY0, S32 dstX1, S32 dstY1, U32 mask, U32 filter); @@ -136,42 +133,23 @@ public: //Returns TRUE if target is ready to be rendered into. //That is, if the target has been allocated with at least //one renderable attachment (i.e. color buffer, depth buffer). - BOOL isComplete() const; + bool isComplete() const; static LLRenderTarget* getCurrentBoundTarget() { return sBoundTarget; } protected: - friend class LLMultisampleBuffer; U32 mResX; U32 mResY; std::vector<U32> mTex; U32 mFBO; U32 mDepth; - BOOL mStencil; - BOOL mUseDepth; - BOOL mRenderDepth; + bool mStencil; + bool mUseDepth; + bool mRenderDepth; LLTexUnit::eTextureType mUsage; U32 mSamples; - LLMultisampleBuffer* mSampleBuffer; - - static LLRenderTarget* sBoundTarget; -}; - -class LLMultisampleBuffer : public LLRenderTarget -{ -public: - LLMultisampleBuffer(); - virtual ~LLMultisampleBuffer(); - - void releaseSampleBuffer(); - - virtual void bindTarget(); - void bindTarget(LLRenderTarget* ref); - virtual void allocate(U32 resx, U32 resy, U32 color_fmt, BOOL depth, BOOL stencil, LLTexUnit::eTextureType usage, BOOL use_fbo); - void allocate(U32 resx, U32 resy, U32 color_fmt, BOOL depth, BOOL stencil, LLTexUnit::eTextureType usage, BOOL use_fbo, U32 samples); - virtual void addColorAttachment(U32 color_fmt); - virtual void allocateDepth(); + static LLRenderTarget* sBoundTarget; }; #endif //!LL_MESA_HEADLESS diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp index c859d41e17..986c1f2774 100644 --- a/indra/llrender/llshadermgr.cpp +++ b/indra/llrender/llshadermgr.cpp @@ -146,6 +146,14 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader) return FALSE; } } + + if (features->hasObjectSkinning) + { + if (!shader->attachObject("avatar/objectSkinV.glsl")) + { + return FALSE; + } + } /////////////////////////////////////// // Attach Fragment Shader Features Next @@ -198,20 +206,81 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader) if (features->hasLighting) { - if (features->hasWaterFog) { - if (!shader->attachObject("lighting/lightWaterF.glsl")) + if (features->disableTextureIndex) { - return FALSE; + if (features->hasAlphaMask) + { + if (!shader->attachObject("lighting/lightWaterAlphaMaskNonIndexedF.glsl")) + { + return FALSE; + } + } + else + { + if (!shader->attachObject("lighting/lightWaterNonIndexedF.glsl")) + { + return FALSE; + } + } + } + else + { + if (features->hasAlphaMask) + { + if (!shader->attachObject("lighting/lightWaterAlphaMaskF.glsl")) + { + return FALSE; + } + } + else + { + if (!shader->attachObject("lighting/lightWaterF.glsl")) + { + return FALSE; + } + } + shader->mFeatures.mIndexedTextureChannels = gGLManager.mNumTextureImageUnits-1; } } else { - if (!shader->attachObject("lighting/lightF.glsl")) + if (features->disableTextureIndex) { - return FALSE; + if (features->hasAlphaMask) + { + if (!shader->attachObject("lighting/lightAlphaMaskNonIndexedF.glsl")) + { + return FALSE; + } + } + else + { + if (!shader->attachObject("lighting/lightNonIndexedF.glsl")) + { + return FALSE; + } + } + } + else + { + if (features->hasAlphaMask) + { + if (!shader->attachObject("lighting/lightAlphaMaskF.glsl")) + { + return FALSE; + } + } + else + { + if (!shader->attachObject("lighting/lightF.glsl")) + { + return FALSE; + } + } + shader->mFeatures.mIndexedTextureChannels = gGLManager.mNumTextureImageUnits-1; } } } @@ -220,27 +289,113 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader) else if (features->isFullbright) { - if (features->hasWaterFog) + if (features->isShiny && features->hasWaterFog) { - if (!shader->attachObject("lighting/lightFullbrightWaterF.glsl")) + if (features->disableTextureIndex) { - return FALSE; + if (!shader->attachObject("lighting/lightFullbrightShinyWaterNonIndexedF.glsl")) + { + return FALSE; + } + } + else + { + if (!shader->attachObject("lighting/lightFullbrightShinyWaterF.glsl")) + { + return FALSE; + } + shader->mFeatures.mIndexedTextureChannels = gGLManager.mNumTextureImageUnits-1; + } + } + else if (features->hasWaterFog) + { + if (features->disableTextureIndex) + { + if (features->hasAlphaMask) + { + if (!shader->attachObject("lighting/lightFullbrightWaterNonIndexedAlphaMaskF.glsl")) + { + return FALSE; + } + } + else if (!shader->attachObject("lighting/lightFullbrightWaterNonIndexedF.glsl")) + { + return FALSE; + } + } + else + { + if (features->hasAlphaMask) + { + if (!shader->attachObject("lighting/lightFullbrightWaterAlphaMaskF.glsl")) + { + return FALSE; + } + } + else if (!shader->attachObject("lighting/lightFullbrightWaterF.glsl")) + { + return FALSE; + } + shader->mFeatures.mIndexedTextureChannels = gGLManager.mNumTextureImageUnits-1; } } else if (features->isShiny) { - if (!shader->attachObject("lighting/lightFullbrightShinyF.glsl")) + if (features->disableTextureIndex) { - return FALSE; + if (!shader->attachObject("lighting/lightFullbrightShinyNonIndexedF.glsl")) + { + return FALSE; + } + } + else + { + if (!shader->attachObject("lighting/lightFullbrightShinyF.glsl")) + { + return FALSE; + } + shader->mFeatures.mIndexedTextureChannels = gGLManager.mNumTextureImageUnits-1; } } else { - if (!shader->attachObject("lighting/lightFullbrightF.glsl")) + if (features->disableTextureIndex) { - return FALSE; + + if (features->hasAlphaMask) + { + if (!shader->attachObject("lighting/lightFullbrightNonIndexedAlphaMaskF.glsl")) + { + return FALSE; + } + } + else + { + if (!shader->attachObject("lighting/lightFullbrightNonIndexedF.glsl")) + { + return FALSE; + } + } + } + else + { + if (features->hasAlphaMask) + { + if (!shader->attachObject("lighting/lightFullbrightAlphaMaskF.glsl")) + { + return FALSE; + } + } + else + { + if (!shader->attachObject("lighting/lightFullbrightF.glsl")) + { + return FALSE; + } + } + shader->mFeatures.mIndexedTextureChannels = gGLManager.mNumTextureImageUnits-1; } } } @@ -251,17 +406,39 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader) if (features->hasWaterFog) { - if (!shader->attachObject("lighting/lightShinyWaterF.glsl")) + if (features->disableTextureIndex) { - return FALSE; + if (!shader->attachObject("lighting/lightShinyWaterNonIndexedF.glsl")) + { + return FALSE; + } + } + else + { + if (!shader->attachObject("lighting/lightShinyWaterF.glsl")) + { + return FALSE; + } + shader->mFeatures.mIndexedTextureChannels = gGLManager.mNumTextureImageUnits-1; } } else { - if (!shader->attachObject("lighting/lightShinyF.glsl")) + if (features->disableTextureIndex) { - return FALSE; + if (!shader->attachObject("lighting/lightShinyNonIndexedF.glsl")) + { + return FALSE; + } + } + else + { + if (!shader->attachObject("lighting/lightShinyF.glsl")) + { + return FALSE; + } + shader->mFeatures.mIndexedTextureChannels = gGLManager.mNumTextureImageUnits-1; } } } @@ -303,15 +480,18 @@ void LLShaderMgr::dumpObjectLog(GLhandleARB ret, BOOL warns) LL_DEBUGS("ShaderLoading") << log << LL_ENDL; } } -} + } -GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_level, GLenum type) +GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_level, GLenum type, S32 texture_index_channels) { - GLenum error; - error = glGetError(); - if (error != GL_NO_ERROR) + GLenum error = GL_NO_ERROR; + if (gDebugGL) { - LL_WARNS("ShaderLoading") << "GL ERROR entering loadShaderFile(): " << error << LL_ENDL; + error = glGetError(); + if (error != GL_NO_ERROR) + { + LL_WARNS("ShaderLoading") << "GL ERROR entering loadShaderFile(): " << error << LL_ENDL; + } } LL_DEBUGS("ShaderLoading") << "Loading shader file: " << filename << " class " << shader_level << LL_ENDL; @@ -356,6 +536,117 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade GLcharARB* text[1024]; GLuint count = 0; + if (gGLManager.mGLVersion < 2.1f) + { + text[count++] = strdup("#version 110\n"); + } + else if (gGLManager.mGLVersion < 3.f) + { + //set version to 1.20 + text[count++] = strdup("#version 120\n"); + } + else + { //set version to 1.30 + text[count++] = strdup("#version 130\n"); + } + + //copy preprocessor definitions into buffer + for (std::map<std::string,std::string>::iterator iter = mDefinitions.begin(); iter != mDefinitions.end(); ++iter) + { + std::string define = "#define " + iter->first + " " + iter->second + "\n"; + text[count++] = (GLcharARB *) strdup(define.c_str()); + } + + if (texture_index_channels > 0 && type == GL_FRAGMENT_SHADER_ARB) + { + //use specified number of texture channels for indexed texture rendering + + /* prepend shader code that looks like this: + + uniform sampler2D tex0; + uniform sampler2D tex1; + uniform sampler2D tex2; + . + . + . + uniform sampler2D texN; + + varying float vary_texture_index; + + vec4 diffuseLookup(vec2 texcoord) + { + switch (int(vary_texture_index+0.25)) + { + case 0: return texture2D(tex0, texcoord); + case 1: return texture2D(tex1, texcoord); + case 2: return texture2D(tex2, texcoord); + . + . + . + case N: return texture2D(texN, texcoord); + } + + return vec4(0,0,0,0); + } + */ + + //uniform declartion + for (S32 i = 0; i < texture_index_channels; ++i) + { + std::string decl = llformat("uniform sampler2D tex%d;\n", i); + text[count++] = strdup(decl.c_str()); + } + + text[count++] = strdup("varying float vary_texture_index;\n"); + text[count++] = strdup("vec4 diffuseLookup(vec2 texcoord)\n"); + text[count++] = strdup("{\n"); + + + if (texture_index_channels == 1) + { //don't use flow control, that's silly + text[count++] = strdup("return texture2D(tex0, texcoord);\n"); + text[count++] = strdup("}\n"); + } + else if (gGLManager.mGLVersion >= 3.f) + { + text[count++] = strdup("\tswitch (int(vary_texture_index+0.25))\n"); + text[count++] = strdup("\t{\n"); + + //switch body + for (S32 i = 0; i < texture_index_channels; ++i) + { + std::string case_str = llformat("\t\tcase %d: return texture2D(tex%d, texcoord);\n", i, i); + text[count++] = strdup(case_str.c_str()); + } + + text[count++] = strdup("\t}\n"); + text[count++] = strdup("\treturn vec4(0,0,0,0);\n"); + text[count++] = strdup("}\n"); + } + else + { + //switches aren't supported, make block that looks like: + /* + int ti = int(vary_texture_index+0.25); + if (ti == 0) return texture2D(tex0, texcoord); + if (ti == 1) return texture2D(tex1, texcoord); + . + . + . + if (ti == N) return texture2D(texN, texcoord); + */ + + text[count++] = strdup("int ti = int(vary_texture_index+0.25);\n"); + for (S32 i = 0; i < texture_index_channels; ++i) + { + std::string if_str = llformat("if (ti == %d) return texture2D(tex%d, texcoord);\n", i, i); + text[count++] = strdup(if_str.c_str()); + } + + text[count++] = strdup("\treturn vec4(0,0,0,0);\n"); + text[count++] = strdup("}\n"); + } + } //copy file into memory while( fgets((char *)buff, 1024, file) != NULL && count < LL_ARRAY_SIZE(buff) ) @@ -366,48 +657,64 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade //create shader object GLhandleARB ret = glCreateShaderObjectARB(type); - error = glGetError(); - if (error != GL_NO_ERROR) + if (gDebugGL) { - LL_WARNS("ShaderLoading") << "GL ERROR in glCreateShaderObjectARB: " << error << LL_ENDL; + error = glGetError(); + if (error != GL_NO_ERROR) + { + LL_WARNS("ShaderLoading") << "GL ERROR in glCreateShaderObjectARB: " << error << LL_ENDL; + } } - else + + //load source + glShaderSourceARB(ret, count, (const GLcharARB**) text, NULL); + + if (gDebugGL) { - //load source - glShaderSourceARB(ret, count, (const GLcharARB**) text, NULL); error = glGetError(); if (error != GL_NO_ERROR) { LL_WARNS("ShaderLoading") << "GL ERROR in glShaderSourceARB: " << error << LL_ENDL; } - else - { - //compile source - glCompileShaderARB(ret); - error = glGetError(); - if (error != GL_NO_ERROR) - { - LL_WARNS("ShaderLoading") << "GL ERROR in glCompileShaderARB: " << error << LL_ENDL; - } - } } - //free memory - for (GLuint i = 0; i < count; i++) + + //compile source + glCompileShaderARB(ret); + + if (gDebugGL) { - free(text[i]); + error = glGetError(); + if (error != GL_NO_ERROR) + { + LL_WARNS("ShaderLoading") << "GL ERROR in glCompileShaderARB: " << error << LL_ENDL; + } } + if (error == GL_NO_ERROR) { //check for errors GLint success = GL_TRUE; glGetObjectParameterivARB(ret, GL_OBJECT_COMPILE_STATUS_ARB, &success); - error = glGetError(); - if (error != GL_NO_ERROR || success == GL_FALSE) + if (gDebugGL || success == GL_FALSE) { - //an error occured, print log - LL_WARNS("ShaderLoading") << "GLSL Compilation Error: (" << error << ") in " << filename << LL_ENDL; - dumpObjectLog(ret); - ret = 0; + error = glGetError(); + if (error != GL_NO_ERROR || success == GL_FALSE) + { + //an error occured, print log + LL_WARNS("ShaderLoading") << "GLSL Compilation Error: (" << error << ") in " << filename << LL_ENDL; + dumpObjectLog(ret); + + std::stringstream ostr; + //dump shader source for debugging + for (GLuint i = 0; i < count; i++) + { + ostr << i << ": " << text[i]; + } + + LL_WARNS("ShaderLoading") << "\n" << ostr.str() << llendl; + + ret = 0; + } } } else @@ -416,6 +723,12 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade } stop_glerror(); + //free memory + for (GLuint i = 0; i < count; i++) + { + free(text[i]); + } + //successfully loaded, save results if (ret) { @@ -428,7 +741,7 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade if (shader_level > 1) { shader_level--; - return loadShaderFile(filename,shader_level,type); + return loadShaderFile(filename,shader_level,type,texture_index_channels); } LL_WARNS("ShaderLoading") << "Failed to load " << filename << LL_ENDL; } diff --git a/indra/llrender/llshadermgr.h b/indra/llrender/llshadermgr.h index c54c4608d7..2f30103811 100644 --- a/indra/llrender/llshadermgr.h +++ b/indra/llrender/llshadermgr.h @@ -43,7 +43,7 @@ public: void dumpObjectLog(GLhandleARB ret, BOOL warns = TRUE); BOOL linkProgramObject(GLhandleARB obj, BOOL suppress_errors = FALSE); BOOL validateProgramObject(GLhandleARB obj); - GLhandleARB loadShaderFile(const std::string& filename, S32 & shader_level, GLenum type); + GLhandleARB loadShaderFile(const std::string& filename, S32 & shader_level, GLenum type, S32 texture_index_channels = -1); // Implemented in the application to actually point to the shader directory. virtual std::string getShaderDirPrefix(void) = 0; // Pure Virtual @@ -60,6 +60,9 @@ public: std::vector<std::string> mReservedUniforms; + //preprocessor definitions (name/value) + std::map<std::string, std::string> mDefinitions; + protected: // our parameter manager singleton instance diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index 1beb74eca6..8fd1193780 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -33,6 +33,10 @@ #include "llglheaders.h" #include "llmemtype.h" #include "llrender.h" +#include "llvector4a.h" +#include "llglslshader.h" +#include "llmemory.h" + //============================================================================ @@ -42,6 +46,7 @@ LLVBOPool LLVertexBuffer::sDynamicVBOPool; LLVBOPool LLVertexBuffer::sStreamIBOPool; LLVBOPool LLVertexBuffer::sDynamicIBOPool; +LLPrivateMemoryPool* LLVertexBuffer::sPrivatePoolp = NULL ; U32 LLVertexBuffer::sBindCount = 0; U32 LLVertexBuffer::sSetCount = 0; S32 LLVertexBuffer::sCount = 0; @@ -57,20 +62,78 @@ BOOL LLVertexBuffer::sIBOActive = FALSE; U32 LLVertexBuffer::sAllocatedBytes = 0; BOOL LLVertexBuffer::sMapped = FALSE; BOOL LLVertexBuffer::sUseStreamDraw = TRUE; +BOOL LLVertexBuffer::sPreferStreamDraw = FALSE; +S32 LLVertexBuffer::sWeight4Loc = -1; std::vector<U32> LLVertexBuffer::sDeleteList; -S32 LLVertexBuffer::sTypeOffsets[LLVertexBuffer::TYPE_MAX] = + +const U32 FENCE_WAIT_TIME_NANOSECONDS = 10000; //1 ms + +class LLGLSyncFence : public LLGLFence +{ +public: +#ifdef GL_ARB_sync + GLsync mSync; +#endif + + LLGLSyncFence() + { +#ifdef GL_ARB_sync + mSync = 0; +#endif + } + + ~LLGLSyncFence() + { +#ifdef GL_ARB_sync + if (mSync) + { + glDeleteSync(mSync); + } +#endif + } + + void placeFence() + { +#ifdef GL_ARB_sync + if (mSync) + { + glDeleteSync(mSync); + } + mSync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); +#endif + } + + void wait() + { +#ifdef GL_ARB_sync + if (mSync) + { + while (glClientWaitSync(mSync, 0, FENCE_WAIT_TIME_NANOSECONDS) == GL_TIMEOUT_EXPIRED) + { //track the number of times we've waited here + static S32 waits = 0; + waits++; + } + } +#endif + } + + +}; + +S32 LLVertexBuffer::sTypeSize[LLVertexBuffer::TYPE_MAX] = { - sizeof(LLVector3), // TYPE_VERTEX, - sizeof(LLVector3), // TYPE_NORMAL, + sizeof(LLVector4), // TYPE_VERTEX, + sizeof(LLVector4), // TYPE_NORMAL, sizeof(LLVector2), // TYPE_TEXCOORD0, sizeof(LLVector2), // TYPE_TEXCOORD1, sizeof(LLVector2), // TYPE_TEXCOORD2, sizeof(LLVector2), // TYPE_TEXCOORD3, sizeof(LLColor4U), // TYPE_COLOR, - sizeof(LLVector3), // TYPE_BINORMAL, + sizeof(LLVector4), // TYPE_BINORMAL, sizeof(F32), // TYPE_WEIGHT, + sizeof(LLVector4), // TYPE_WEIGHT4, sizeof(LLVector4), // TYPE_CLOTHWEIGHT, }; @@ -139,11 +202,11 @@ void LLVertexBuffer::setupClientArrays(U32 data_mask) } else { //was disabled - if (data_mask & mask[i]) + if (data_mask & mask[i] && i > 0) { //needs to be enabled glEnableClientState(array[i]); } - else if (gDebugGL && glIsEnabled(array[i])) + else if (gDebugGL && i > 0 && glIsEnabled(array[i])) { //needs to be disabled, make sure it was (DEBUG TEMPORARY) if (gDebugSession) { @@ -205,18 +268,54 @@ void LLVertexBuffer::setupClientArrays(U32 data_mask) glClientActiveTextureARB(GL_TEXTURE0_ARB); } + if (sLastMask & MAP_WEIGHT4) + { + if (sWeight4Loc < 0) + { + llerrs << "Weighting disabled but vertex buffer still bound!" << llendl; + } + + if (!(data_mask & MAP_WEIGHT4)) + { //disable 4-component skin weight + glDisableVertexAttribArrayARB(sWeight4Loc); + } + } + else if (data_mask & MAP_WEIGHT4) + { + if (sWeight4Loc >= 0) + { //enable 4-component skin weight + glEnableVertexAttribArrayARB(sWeight4Loc); + } + } + + sLastMask = data_mask; } } -void LLVertexBuffer::drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indices_offset) const +//static +void LLVertexBuffer::drawArrays(U32 mode, const std::vector<LLVector3>& pos, const std::vector<LLVector3>& norm) { - llassert(mRequestedNumVerts >= 0); + U32 count = pos.size(); + llassert_always(norm.size() >= pos.size()); + llassert_always(count > 0) ; + + unbind(); + + setupClientArrays(MAP_VERTEX | MAP_NORMAL); + + glVertexPointer(3, GL_FLOAT, 0, pos[0].mV); + glNormalPointer(GL_FLOAT, 0, norm[0].mV); + glDrawArrays(sGLMode[mode], 0, count); +} + +void LLVertexBuffer::validateRange(U32 start, U32 end, U32 count, U32 indices_offset) const +{ if (start >= (U32) mRequestedNumVerts || end >= (U32) mRequestedNumVerts) { - llerrs << "Bad vertex buffer draw range: [" << start << ", " << end << "]" << llendl; + llerrs << "Bad vertex buffer draw range: [" << start << ", " << end << "] vs " << mRequestedNumVerts << llendl; } llassert(mRequestedNumIndices >= 0); @@ -227,6 +326,25 @@ void LLVertexBuffer::drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indi 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 +{ + validateRange(start, end, count, indices_offset); + + llassert(mRequestedNumVerts >= 0); + if (mGLIndices != sGLRenderIndices) { llerrs << "Wrong index buffer bound." << llendl; @@ -243,16 +361,18 @@ void LLVertexBuffer::drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indi return; } + U16* idx = ((U16*) getIndicesPointer())+indices_offset; + stop_glerror(); glDrawRangeElements(sGLMode[mode], start, end, count, GL_UNSIGNED_SHORT, - ((U16*) getIndicesPointer()) + indices_offset); + idx); stop_glerror(); + placeFence(); } void LLVertexBuffer::draw(U32 mode, U32 count, U32 indices_offset) const { llassert(mRequestedNumIndices >= 0); - if (indices_offset >= (U32) mRequestedNumIndices || indices_offset + count > (U32) mRequestedNumIndices) { @@ -279,12 +399,12 @@ void LLVertexBuffer::draw(U32 mode, U32 count, U32 indices_offset) const glDrawElements(sGLMode[mode], count, GL_UNSIGNED_SHORT, ((U16*) getIndicesPointer()) + indices_offset); stop_glerror(); + placeFence(); } void LLVertexBuffer::drawArrays(U32 mode, U32 first, U32 count) const { llassert(mRequestedNumVerts >= 0); - if (first >= (U32) mRequestedNumVerts || first + count > (U32) mRequestedNumVerts) { @@ -305,6 +425,7 @@ void LLVertexBuffer::drawArrays(U32 mode, U32 first, U32 count) const stop_glerror(); glDrawArrays(sGLMode[mode], first, count); stop_glerror(); + placeFence(); } //static @@ -323,10 +444,11 @@ void LLVertexBuffer::initClass(bool use_vbo, bool no_vbo_mapping) } sDisableVBOMapping = sEnableVBOs && no_vbo_mapping ; - LLGLNamePool::registerPool(&sDynamicVBOPool); - LLGLNamePool::registerPool(&sDynamicIBOPool); - LLGLNamePool::registerPool(&sStreamVBOPool); - LLGLNamePool::registerPool(&sStreamIBOPool); + + if(!sPrivatePoolp) + { + sPrivatePoolp = LLPrivateMemoryPoolManager::getInstance()->newPool(LLPrivateMemoryPool::STATIC) ; + } } //static @@ -355,6 +477,12 @@ void LLVertexBuffer::cleanupClass() LLMemType mt2(LLMemType::MTYPE_VERTEX_CLEANUP_CLASS); unbind(); clientCopy(); // deletes GL buffers + + if(sPrivatePoolp) + { + LLPrivateMemoryPoolManager::getInstance()->deletePool(sPrivatePoolp) ; + sPrivatePoolp = NULL ; + } } void LLVertexBuffer::clientCopy(F64 max_time) @@ -386,9 +514,11 @@ LLVertexBuffer::LLVertexBuffer(U32 typemask, S32 usage) : mFilthy(FALSE), mEmpty(TRUE), mResized(FALSE), - mDynamicSize(FALSE) + mDynamicSize(FALSE), + mFence(NULL) { LLMemType mt2(LLMemType::MTYPE_VERTEX_CONSTRUCTOR); + mFence = NULL; if (!sEnableVBOs) { mUsage = 0 ; @@ -399,22 +529,29 @@ LLVertexBuffer::LLVertexBuffer(U32 typemask, S32 usage) : mUsage = 0; } - if (mUsage == GL_STREAM_DRAW_ARB && !sUseStreamDraw) + if (mUsage == GL_DYNAMIC_DRAW_ARB && sPreferStreamDraw) { - mUsage = 0; + mUsage = GL_STREAM_DRAW_ARB; } - S32 stride = calcStride(typemask, mOffsets); + //zero out offsets + for (U32 i = 0; i < TYPE_MAX; i++) + { + mOffsets[i] = 0; + } mTypeMask = typemask; - mStride = stride; + mSize = 0; + mAlignedOffset = 0; + mAlignedIndexOffset = 0; + sCount++; } //static -S32 LLVertexBuffer::calcStride(const U32& typemask, S32* offsets) +S32 LLVertexBuffer::calcOffsets(const U32& typemask, S32* offsets, S32 num_vertices) { - S32 stride = 0; + S32 offset = 0; for (S32 i=0; i<TYPE_MAX; i++) { U32 mask = 1<<i; @@ -422,13 +559,35 @@ S32 LLVertexBuffer::calcStride(const U32& typemask, S32* offsets) { if (offsets) { - offsets[i] = stride; + offsets[i] = offset; + offset += LLVertexBuffer::sTypeSize[i]*num_vertices; + offset = (offset + 0xF) & ~0xF; } - stride += sTypeOffsets[i]; } } - return stride; + return offset+16; +} + +//static +S32 LLVertexBuffer::calcVertexSize(const U32& typemask) +{ + S32 size = 0; + for (S32 i = 0; i < TYPE_MAX; i++) + { + U32 mask = 1<<i; + if (typemask & mask) + { + size += LLVertexBuffer::sTypeSize[i]; + } + } + + return size; +} + +S32 LLVertexBuffer::getSize() const +{ + return mSize; } // protected, use unref() @@ -440,9 +599,40 @@ LLVertexBuffer::~LLVertexBuffer() destroyGLIndices(); sCount--; + if (mFence) + { + delete mFence; + } + + mFence = NULL; + llassert_always(!mMappedData && !mMappedIndexData) ; }; +void LLVertexBuffer::placeFence() const +{ + /*if (!mFence && useVBOs()) + { + if (gGLManager.mHasSync) + { + mFence = new LLGLSyncFence(); + } + } + + if (mFence) + { + mFence->placeFence(); + }*/ +} + +void LLVertexBuffer::waitFence() const +{ + /*if (mFence) + { + mFence->wait(); + }*/ +} + //---------------------------------------------------------------------------- void LLVertexBuffer::genBuffer() @@ -542,8 +732,7 @@ void LLVertexBuffer::createGLBuffer() { static int gl_buffer_idx = 0; mGLBuffer = ++gl_buffer_idx; - mMappedData = new U8[size]; - memset(mMappedData, 0, size); + mMappedData = (U8*)ALLOCATE_MEM(sPrivatePoolp, size); } } @@ -564,16 +753,20 @@ void LLVertexBuffer::createGLIndices() mEmpty = TRUE; + //pad by 16 bytes for aligned copies + size += 16; + if (useVBOs()) { + //pad by another 16 bytes for VBO pointer adjustment + size += 16; mMappedIndexData = NULL; genIndices(); mResized = TRUE; } else { - mMappedIndexData = new U8[size]; - memset(mMappedIndexData, 0, size); + mMappedIndexData = (U8*)ALLOCATE_MEM(sPrivatePoolp, size); static int gl_buffer_idx = 0; mGLIndices = ++gl_buffer_idx; } @@ -596,7 +789,7 @@ void LLVertexBuffer::destroyGLBuffer() } else { - delete [] mMappedData; + FREE_MEM(sPrivatePoolp, mMappedData) ; mMappedData = NULL; mEmpty = TRUE; } @@ -605,7 +798,7 @@ void LLVertexBuffer::destroyGLBuffer() } mGLBuffer = 0; - unbind(); + //unbind(); } void LLVertexBuffer::destroyGLIndices() @@ -621,11 +814,11 @@ void LLVertexBuffer::destroyGLIndices() { llerrs << "Vertex buffer destroyed while mapped." << llendl; } - releaseIndices(); + releaseIndices(); } else { - delete [] mMappedIndexData; + FREE_MEM(sPrivatePoolp, mMappedIndexData) ; mMappedIndexData = NULL; mEmpty = TRUE; } @@ -634,7 +827,7 @@ void LLVertexBuffer::destroyGLIndices() } mGLIndices = 0; - unbind(); + //unbind(); } void LLVertexBuffer::updateNumVerts(S32 nverts) @@ -650,7 +843,7 @@ void LLVertexBuffer::updateNumVerts(S32 nverts) } mRequestedNumVerts = nverts; - + if (!mDynamicSize) { mNumVerts = nverts; @@ -665,7 +858,7 @@ void LLVertexBuffer::updateNumVerts(S32 nverts) } mNumVerts = nverts; } - + mSize = calcOffsets(mTypeMask, mOffsets, mNumVerts); } void LLVertexBuffer::updateNumIndices(S32 nindices) @@ -696,6 +889,12 @@ void LLVertexBuffer::allocateBuffer(S32 nverts, S32 nindices, bool create) { LLMemType mt2(LLMemType::MTYPE_VERTEX_ALLOCATE_BUFFER); + if (nverts < 0 || nindices < 0 || + nverts > 65536) + { + llerrs << "Bad vertex buffer allocation: " << nverts << " : " << nindices << llendl; + } + updateNumVerts(nverts); updateNumIndices(nindices); @@ -734,9 +933,6 @@ void LLVertexBuffer::resizeBuffer(S32 newnverts, S32 newnindices) { sAllocatedBytes -= getSize() + getIndicesSize(); - S32 oldsize = getSize(); - S32 old_index_size = getIndicesSize(); - updateNumVerts(newnverts); updateNumIndices(newnindices); @@ -753,26 +949,10 @@ void LLVertexBuffer::resizeBuffer(S32 newnverts, S32 newnindices) } else { - //delete old buffer, keep GL buffer for now if (!useVBOs()) { - U8* old = mMappedData; - mMappedData = new U8[newsize]; - if (old) - { - memcpy(mMappedData, old, llmin(newsize, oldsize)); - if (newsize > oldsize) - { - memset(mMappedData+oldsize, 0, newsize-oldsize); - } - - delete [] old; - } - else - { - memset(mMappedData, 0, newsize); - mEmpty = TRUE; - } + FREE_MEM(sPrivatePoolp, mMappedData); + mMappedData = (U8*)ALLOCATE_MEM(sPrivatePoolp, newsize); } mResized = TRUE; } @@ -792,24 +972,8 @@ void LLVertexBuffer::resizeBuffer(S32 newnverts, S32 newnindices) { if (!useVBOs()) { - //delete old buffer, keep GL buffer for now - U8* old = mMappedIndexData; - mMappedIndexData = new U8[new_index_size]; - - if (old) - { - memcpy(mMappedIndexData, old, llmin(new_index_size, old_index_size)); - if (new_index_size > old_index_size) - { - memset(mMappedIndexData+old_index_size, 0, new_index_size - old_index_size); - } - delete [] old; - } - else - { - memset(mMappedIndexData, 0, new_index_size); - mEmpty = TRUE; - } + FREE_MEM(sPrivatePoolp, mMappedIndexData) ; + mMappedIndexData = (U8*)ALLOCATE_MEM(sPrivatePoolp, new_index_size); } mResized = TRUE; } @@ -831,17 +995,11 @@ BOOL LLVertexBuffer::useVBOs() const { //it's generally ineffective to use VBO for things that are streaming on apple -#if LL_DARWIN - if (!mUsage || mUsage == GL_STREAM_DRAW_ARB) - { - return FALSE; - } -#else if (!mUsage) { return FALSE; } -#endif + return TRUE; } @@ -850,8 +1008,8 @@ void LLVertexBuffer::freeClientBuffer() { if(useVBOs() && sDisableVBOMapping && (mMappedData || mMappedIndexData)) { - delete[] mMappedData ; - delete[] mMappedIndexData ; + FREE_MEM(sPrivatePoolp, mMappedData) ; + FREE_MEM(sPrivatePoolp, mMappedIndexData) ; mMappedData = NULL ; mMappedIndexData = NULL ; } @@ -861,9 +1019,7 @@ void LLVertexBuffer::allocateClientVertexBuffer() { if(!mMappedData) { - U32 size = getSize() ; - mMappedData = new U8[size]; - memset(mMappedData, 0, size); + mMappedData = (U8*)ALLOCATE_MEM(sPrivatePoolp, getSize()); } } @@ -871,14 +1027,30 @@ void LLVertexBuffer::allocateClientIndexBuffer() { if(!mMappedIndexData) { - U32 size = getIndicesSize(); - mMappedIndexData = new U8[size]; - memset(mMappedIndexData, 0, size); + mMappedIndexData = (U8*)ALLOCATE_MEM(sPrivatePoolp, getIndicesSize()); + } +} + +bool expand_region(LLVertexBuffer::MappedRegion& region, S32 index, S32 count) +{ + S32 end = index+count; + S32 region_end = region.mIndex+region.mCount; + + if (end < region.mIndex || + index > region_end) + { //gap exists, do not merge + return false; } + + S32 new_end = llmax(end, region_end); + S32 new_index = llmin(index, region.mIndex); + region.mIndex = new_index; + region.mCount = new_end-new_index; + return true; } // Map for data access -U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 access) +U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, bool map_range) { LLMemType mt2(LLMemType::MTYPE_VERTEX_MAP_BUFFER); if (mFinal) @@ -890,67 +1062,159 @@ U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 access) llerrs << "LLVertexBuffer::mapVertexBuffer() called on unallocated buffer." << llendl; } - if (!mVertexLocked && useVBOs()) + if (useVBOs()) { + if (sDisableVBOMapping || gGLManager.mHasMapBufferRange || gGLManager.mHasFlushBufferRange) + { + if (count == -1) + { + count = mNumVerts-index; + } + + bool mapped = false; + //see if range is already mapped + for (U32 i = 0; i < mMappedVertexRegions.size(); ++i) + { + MappedRegion& region = mMappedVertexRegions[i]; + if (region.mType == type) + { + if (expand_region(region, index, count)) + { + mapped = true; + break; + } + } + } + + if (!mapped) + { + //not already mapped, map new region + MappedRegion region(type, !sDisableVBOMapping && map_range ? -1 : index, count); + mMappedVertexRegions.push_back(region); + } + } + + if (mVertexLocked && map_range) + { + llerrs << "Attempted to map a specific range of a buffer that was already mapped." << llendl; + } + + if (!mVertexLocked) { LLMemType mt_v(LLMemType::MTYPE_VERTEX_MAP_BUFFER_VERTICES); setBuffer(0, type); mVertexLocked = TRUE; + sMappedCount++; stop_glerror(); if(sDisableVBOMapping) { + map_range = false; allocateClientVertexBuffer() ; } else { - mMappedData = (U8*) glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB); - } - stop_glerror(); - } - - if (!mMappedData) - { - log_glerror(); + U8* src = NULL; + waitFence(); + if (gGLManager.mHasMapBufferRange) + { + if (map_range) + { +#ifdef GL_ARB_map_buffer_range + S32 offset = mOffsets[type] + sTypeSize[type]*index; + S32 length = (sTypeSize[type]*count+0xF) & ~0xF; + src = (U8*) glMapBufferRange(GL_ARRAY_BUFFER_ARB, offset, length, + GL_MAP_WRITE_BIT | + GL_MAP_FLUSH_EXPLICIT_BIT | + GL_MAP_INVALIDATE_RANGE_BIT); +#endif + } + else + { +#ifdef GL_ARB_map_buffer_range + src = (U8*) glMapBufferRange(GL_ARRAY_BUFFER_ARB, 0, mSize, + GL_MAP_WRITE_BIT | + GL_MAP_FLUSH_EXPLICIT_BIT); +#endif + } + } + else if (gGLManager.mHasFlushBufferRange) + { + if (map_range) + { + glBufferParameteriAPPLE(GL_ARRAY_BUFFER_ARB, GL_BUFFER_SERIALIZED_MODIFY_APPLE, GL_FALSE); + glBufferParameteriAPPLE(GL_ARRAY_BUFFER_ARB, GL_BUFFER_FLUSHING_UNMAP_APPLE, GL_FALSE); + src = (U8*) glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB); + } + else + { + src = (U8*) glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB); + } + } + else + { + map_range = false; + src = (U8*) glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB); + } - //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; + llassert(src != NULL); - if(!sDisableVBOMapping) + mMappedData = LL_NEXT_ALIGNED_ADDRESS<U8>(src); + mAlignedOffset = mMappedData - src; + + stop_glerror(); + } + + if (!mMappedData) { - //-------------------- - //print out more debug info before crash - llinfos << "vertex buffer size: (num verts : num indices) = " << getNumVerts() << " : " << getNumIndices() << llendl ; - GLint size ; - glGetBufferParameterivARB(GL_ARRAY_BUFFER_ARB, GL_BUFFER_SIZE_ARB, &size) ; - llinfos << "GL_ARRAY_BUFFER_ARB size is " << size << llendl ; - //-------------------- + log_glerror(); - GLint buff; - glGetIntegerv(GL_ARRAY_BUFFER_BINDING_ARB, &buff); - if ((GLuint)buff != mGLBuffer) + //check the availability of memory + LLMemory::logMemoryInfo(TRUE) ; + + if(!sDisableVBOMapping) + { + //-------------------- + //print out more debug info before crash + llinfos << "vertex buffer size: (num verts : num indices) = " << getNumVerts() << " : " << getNumIndices() << llendl ; + GLint size ; + glGetBufferParameterivARB(GL_ARRAY_BUFFER_ARB, GL_BUFFER_SIZE_ARB, &size) ; + llinfos << "GL_ARRAY_BUFFER_ARB size is " << size << llendl ; + //-------------------- + + GLint buff; + glGetIntegerv(GL_ARRAY_BUFFER_BINDING_ARB, &buff); + if ((GLuint)buff != mGLBuffer) + { + llerrs << "Invalid GL vertex buffer bound: " << buff << llendl; + } + + + llerrs << "glMapBuffer returned NULL (no vertex data)" << llendl; + } + else { - llerrs << "Invalid GL vertex buffer bound: " << buff << llendl; + llerrs << "memory allocation for vertex data failed." << llendl ; } - - - llerrs << "glMapBuffer returned NULL (no vertex data)" << llendl; - } - else - { - llerrs << "memory allocation for vertex data failed." << llendl ; } } - sMappedCount++; + } + else + { + map_range = false; } - return mMappedData; + if (map_range && gGLManager.mHasMapBufferRange && !sDisableVBOMapping) + { + return mMappedData; + } + else + { + return mMappedData+mOffsets[type]+sTypeSize[type]*index; + } } -U8* LLVertexBuffer::mapIndexBuffer(S32 access) +U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range) { LLMemType mt2(LLMemType::MTYPE_VERTEX_MAP_BUFFER); if (mFinal) @@ -962,29 +1226,112 @@ U8* LLVertexBuffer::mapIndexBuffer(S32 access) llerrs << "LLVertexBuffer::mapIndexBuffer() called on unallocated buffer." << llendl; } - if (!mIndexLocked && useVBOs()) + if (useVBOs()) { + if (sDisableVBOMapping || gGLManager.mHasMapBufferRange || gGLManager.mHasFlushBufferRange) + { + if (count == -1) + { + count = mNumIndices-index; + } + + bool mapped = false; + //see if range is already mapped + for (U32 i = 0; i < mMappedIndexRegions.size(); ++i) + { + MappedRegion& region = mMappedIndexRegions[i]; + if (expand_region(region, index, count)) + { + mapped = true; + break; + } + } + + if (!mapped) + { + //not already mapped, map new region + MappedRegion region(TYPE_INDEX, !sDisableVBOMapping && map_range ? -1 : index, count); + mMappedIndexRegions.push_back(region); + } + } + + if (mIndexLocked && map_range) + { + llerrs << "Attempted to map a specific range of a buffer that was already mapped." << llendl; + } + + if (!mIndexLocked) { LLMemType mt_v(LLMemType::MTYPE_VERTEX_MAP_BUFFER_INDICES); setBuffer(0, TYPE_INDEX); mIndexLocked = TRUE; + sMappedCount++; stop_glerror(); if(sDisableVBOMapping) { + map_range = false; allocateClientIndexBuffer() ; } else { - mMappedIndexData = (U8*) glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB); + U8* src = NULL; + waitFence(); + if (gGLManager.mHasMapBufferRange) + { + if (map_range) + { +#ifdef GL_ARB_map_buffer_range + S32 offset = sizeof(U16)*index; + S32 length = sizeof(U16)*count; + src = (U8*) glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER_ARB, offset, length, + GL_MAP_WRITE_BIT | + GL_MAP_FLUSH_EXPLICIT_BIT | + GL_MAP_INVALIDATE_RANGE_BIT); +#endif + } + else + { +#ifdef GL_ARB_map_buffer_range + src = (U8*) glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER_ARB, 0, sizeof(U16)*mNumIndices, + GL_MAP_WRITE_BIT | + GL_MAP_FLUSH_EXPLICIT_BIT); +#endif + } + } + else if (gGLManager.mHasFlushBufferRange) + { + if (map_range) + { + glBufferParameteriAPPLE(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_BUFFER_SERIALIZED_MODIFY_APPLE, GL_FALSE); + glBufferParameteriAPPLE(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_BUFFER_FLUSHING_UNMAP_APPLE, GL_FALSE); + src = (U8*) glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB); + } + else + { + src = (U8*) glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB); + } + } + else + { + map_range = false; + src = (U8*) glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB); + } + + llassert(src != NULL); + + + mMappedIndexData = src; //LL_NEXT_ALIGNED_ADDRESS<U8>(src); + mAlignedIndexOffset = mMappedIndexData - src; + stop_glerror(); } - stop_glerror(); } if (!mMappedIndexData) { log_glerror(); + LLMemory::logMemoryInfo(TRUE) ; if(!sDisableVBOMapping) { @@ -1002,34 +1349,87 @@ U8* LLVertexBuffer::mapIndexBuffer(S32 access) llerrs << "memory allocation for Index data failed. " << llendl ; } } - - sMappedCount++; + } + else + { + map_range = false; } - return mMappedIndexData ; + if (map_range && gGLManager.mHasMapBufferRange && !sDisableVBOMapping) + { + return mMappedIndexData; + } + else + { + return mMappedIndexData + sizeof(U16)*index; + } } void LLVertexBuffer::unmapBuffer(S32 type) { LLMemType mt2(LLMemType::MTYPE_VERTEX_UNMAP_BUFFER); - if (!useVBOs()) + if (!useVBOs() || type == -2) { return ; //nothing to unmap } bool updated_all = false ; + if (mMappedData && mVertexLocked && type != TYPE_INDEX) { updated_all = (mIndexLocked && type < 0) ; //both vertex and index buffers done updating if(sDisableVBOMapping) { - stop_glerror(); - glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, getSize(), mMappedData); - stop_glerror(); + if (!mMappedVertexRegions.empty()) + { + stop_glerror(); + for (U32 i = 0; i < mMappedVertexRegions.size(); ++i) + { + const MappedRegion& region = mMappedVertexRegions[i]; + S32 offset = region.mIndex >= 0 ? mOffsets[region.mType]+sTypeSize[region.mType]*region.mIndex : 0; + S32 length = sTypeSize[region.mType]*region.mCount; + glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, offset, length, mMappedData+offset); + stop_glerror(); + } + + mMappedVertexRegions.clear(); + } + else + { + stop_glerror(); + glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, getSize(), mMappedData); + stop_glerror(); + } } else { + if (gGLManager.mHasMapBufferRange || gGLManager.mHasFlushBufferRange) + { + if (!mMappedVertexRegions.empty()) + { + stop_glerror(); + for (U32 i = 0; i < mMappedVertexRegions.size(); ++i) + { + const MappedRegion& region = mMappedVertexRegions[i]; + S32 offset = region.mIndex >= 0 ? mOffsets[region.mType]+sTypeSize[region.mType]*region.mIndex : 0; + S32 length = sTypeSize[region.mType]*region.mCount; + if (gGLManager.mHasMapBufferRange) + { +#ifdef GL_ARB_map_buffer_range + glFlushMappedBufferRange(GL_ARRAY_BUFFER_ARB, offset, length); +#endif + } + else if (gGLManager.mHasFlushBufferRange) + { + glFlushMappedBufferRangeAPPLE(GL_ARRAY_BUFFER_ARB, offset, length); + } + stop_glerror(); + } + + mMappedVertexRegions.clear(); + } + } stop_glerror(); glUnmapBufferARB(GL_ARRAY_BUFFER_ARB); stop_glerror(); @@ -1040,17 +1440,60 @@ void LLVertexBuffer::unmapBuffer(S32 type) mVertexLocked = FALSE ; sMappedCount--; } - - if(mMappedIndexData && mIndexLocked && (type < 0 || type == TYPE_INDEX)) + + if (mMappedIndexData && mIndexLocked && (type < 0 || type == TYPE_INDEX)) { if(sDisableVBOMapping) { - stop_glerror(); - glBufferSubDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0, getIndicesSize(), mMappedIndexData); - stop_glerror(); + if (!mMappedIndexRegions.empty()) + { + for (U32 i = 0; i < mMappedIndexRegions.size(); ++i) + { + const MappedRegion& region = mMappedIndexRegions[i]; + S32 offset = region.mIndex >= 0 ? sizeof(U16)*region.mIndex : 0; + S32 length = sizeof(U16)*region.mCount; + glBufferSubDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, offset, length, mMappedIndexData+offset); + stop_glerror(); + } + + mMappedIndexRegions.clear(); + } + else + { + stop_glerror(); + glBufferSubDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0, getIndicesSize(), mMappedIndexData); + stop_glerror(); + } } else { + if (gGLManager.mHasMapBufferRange || gGLManager.mHasFlushBufferRange) + { + if (!mMappedIndexRegions.empty()) + { + for (U32 i = 0; i < mMappedIndexRegions.size(); ++i) + { + const MappedRegion& region = mMappedIndexRegions[i]; + S32 offset = region.mIndex >= 0 ? sizeof(U16)*region.mIndex : 0; + S32 length = sizeof(U16)*region.mCount; + if (gGLManager.mHasMapBufferRange) + { +#ifdef GL_ARB_map_buffer_range + glFlushMappedBufferRange(GL_ELEMENT_ARRAY_BUFFER_ARB, offset, length); +#endif + } + else if (gGLManager.mHasFlushBufferRange) + { +#ifdef GL_APPLE_flush_buffer_range + glFlushMappedBufferRangeAPPLE(GL_ELEMENT_ARRAY_BUFFER_ARB, offset, length); +#endif + } + stop_glerror(); + } + + mMappedIndexRegions.clear(); + } + } stop_glerror(); glUnmapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB); stop_glerror(); @@ -1070,7 +1513,6 @@ void LLVertexBuffer::unmapBuffer(S32 type) //throw out client data (we won't be using it again) mEmpty = TRUE; mFinal = TRUE; - if(sDisableVBOMapping) { freeClientBuffer() ; @@ -1090,33 +1532,35 @@ template <class T,S32 type> struct VertexBufferStrider typedef LLStrider<T> strider_t; static bool get(LLVertexBuffer& vbo, strider_t& strider, - S32 index) + S32 index, S32 count, bool map_range) { if (type == LLVertexBuffer::TYPE_INDEX) { - S32 stride = sizeof(T); + U8* ptr = vbo.mapIndexBuffer(index, count, map_range); - if (vbo.mapIndexBuffer() == NULL) + if (ptr == NULL) { llwarns << "mapIndexBuffer failed!" << llendl; return FALSE; } - strider = (T*)(vbo.getMappedIndices() + index*stride); + strider = (T*)ptr; strider.setStride(0); return TRUE; } else if (vbo.hasDataType(type)) { - S32 stride = vbo.getStride(); + S32 stride = LLVertexBuffer::sTypeSize[type]; - if (vbo.mapVertexBuffer(type) == NULL) + U8* ptr = vbo.mapVertexBuffer(type, index, count, map_range); + + if (ptr == NULL) { llwarns << "mapVertexBuffer failed!" << llendl; return FALSE; } - strider = (T*)(vbo.getMappedData() + vbo.getOffset(type) + index*stride); + strider = (T*)ptr; strider.setStride(stride); return TRUE; } @@ -1128,69 +1572,48 @@ template <class T,S32 type> struct VertexBufferStrider } }; - -bool LLVertexBuffer::getVertexStrider(LLStrider<LLVector3>& strider, S32 index) +bool LLVertexBuffer::getVertexStrider(LLStrider<LLVector3>& strider, S32 index, S32 count, bool map_range) { - return VertexBufferStrider<LLVector3,TYPE_VERTEX>::get(*this, strider, index); + return VertexBufferStrider<LLVector3,TYPE_VERTEX>::get(*this, strider, index, count, map_range); } -bool LLVertexBuffer::getIndexStrider(LLStrider<U16>& strider, S32 index) +bool LLVertexBuffer::getIndexStrider(LLStrider<U16>& strider, S32 index, S32 count, bool map_range) { - return VertexBufferStrider<U16,TYPE_INDEX>::get(*this, strider, index); + return VertexBufferStrider<U16,TYPE_INDEX>::get(*this, strider, index, count, map_range); } -bool LLVertexBuffer::getTexCoord0Strider(LLStrider<LLVector2>& strider, S32 index) +bool LLVertexBuffer::getTexCoord0Strider(LLStrider<LLVector2>& strider, S32 index, S32 count, bool map_range) { - return VertexBufferStrider<LLVector2,TYPE_TEXCOORD0>::get(*this, strider, index); + return VertexBufferStrider<LLVector2,TYPE_TEXCOORD0>::get(*this, strider, index, count, map_range); } -bool LLVertexBuffer::getTexCoord1Strider(LLStrider<LLVector2>& strider, S32 index) +bool LLVertexBuffer::getTexCoord1Strider(LLStrider<LLVector2>& strider, S32 index, S32 count, bool map_range) { - return VertexBufferStrider<LLVector2,TYPE_TEXCOORD1>::get(*this, strider, index); + return VertexBufferStrider<LLVector2,TYPE_TEXCOORD1>::get(*this, strider, index, count, map_range); } -/*bool LLVertexBuffer::getTexCoord2Strider(LLStrider<LLVector2>& strider, S32 index) -{ - return VertexBufferStrider<LLVector2,TYPE_TEXCOORD2>::get(*this, strider, index); -} -bool LLVertexBuffer::getTexCoord3Strider(LLStrider<LLVector2>& strider, S32 index) -{ - return VertexBufferStrider<LLVector2,TYPE_TEXCOORD3>::get(*this, strider, index); -}*/ -bool LLVertexBuffer::getNormalStrider(LLStrider<LLVector3>& strider, S32 index) + +bool LLVertexBuffer::getNormalStrider(LLStrider<LLVector3>& strider, S32 index, S32 count, bool map_range) { - return VertexBufferStrider<LLVector3,TYPE_NORMAL>::get(*this, strider, index); + return VertexBufferStrider<LLVector3,TYPE_NORMAL>::get(*this, strider, index, count, map_range); } -bool LLVertexBuffer::getBinormalStrider(LLStrider<LLVector3>& strider, S32 index) +bool LLVertexBuffer::getBinormalStrider(LLStrider<LLVector3>& strider, S32 index, S32 count, bool map_range) { - return VertexBufferStrider<LLVector3,TYPE_BINORMAL>::get(*this, strider, index); + return VertexBufferStrider<LLVector3,TYPE_BINORMAL>::get(*this, strider, index, count, map_range); } -bool LLVertexBuffer::getColorStrider(LLStrider<LLColor4U>& strider, S32 index) +bool LLVertexBuffer::getColorStrider(LLStrider<LLColor4U>& strider, S32 index, S32 count, bool map_range) { - return VertexBufferStrider<LLColor4U,TYPE_COLOR>::get(*this, strider, index); + return VertexBufferStrider<LLColor4U,TYPE_COLOR>::get(*this, strider, index, count, map_range); } -bool LLVertexBuffer::getWeightStrider(LLStrider<F32>& strider, S32 index) +bool LLVertexBuffer::getWeightStrider(LLStrider<F32>& strider, S32 index, S32 count, bool map_range) { - return VertexBufferStrider<F32,TYPE_WEIGHT>::get(*this, strider, index); + return VertexBufferStrider<F32,TYPE_WEIGHT>::get(*this, strider, index, count, map_range); } -bool LLVertexBuffer::getClothWeightStrider(LLStrider<LLVector4>& strider, S32 index) + +bool LLVertexBuffer::getWeight4Strider(LLStrider<LLVector4>& strider, S32 index, S32 count, bool map_range) { - return VertexBufferStrider<LLVector4,TYPE_CLOTHWEIGHT>::get(*this, strider, index); + return VertexBufferStrider<LLVector4,TYPE_WEIGHT4>::get(*this, strider, index, count, map_range); } -void LLVertexBuffer::setStride(S32 type, S32 new_stride) +bool LLVertexBuffer::getClothWeightStrider(LLStrider<LLVector4>& strider, S32 index, S32 count, bool map_range) { - LLMemType mt2(LLMemType::MTYPE_VERTEX_SET_STRIDE); - if (mNumVerts) - { - llerrs << "LLVertexBuffer::setOffset called with mNumVerts = " << mNumVerts << llendl; - } - // This code assumes that setStride() will only be called once per VBO per type. - S32 delta = new_stride - sTypeOffsets[type]; - for (S32 i=type+1; i<TYPE_MAX; i++) - { - if (mTypeMask & (1<<i)) - { - mOffsets[i] += delta; - } - } - mStride += delta; + return VertexBufferStrider<LLVector4,TYPE_CLOTHWEIGHT>::get(*this, strider, index, count, map_range); } //---------------------------------------------------------------------------- @@ -1389,8 +1812,7 @@ void LLVertexBuffer::setupVertexBuffer(U32 data_mask) const { LLMemType mt2(LLMemType::MTYPE_VERTEX_SETUP_VERTEX_BUFFER); stop_glerror(); - U8* base = useVBOs() ? NULL : mMappedData; - S32 stride = mStride; + U8* base = useVBOs() ? (U8*) mAlignedOffset : mMappedData; if ((data_mask & mTypeMask) != data_mask) { @@ -1399,62 +1821,67 @@ void LLVertexBuffer::setupVertexBuffer(U32 data_mask) const if (data_mask & MAP_NORMAL) { - glNormalPointer(GL_FLOAT, stride, (void*)(base + mOffsets[TYPE_NORMAL])); + glNormalPointer(GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_NORMAL], (void*)(base + mOffsets[TYPE_NORMAL])); } if (data_mask & MAP_TEXCOORD3) { glClientActiveTextureARB(GL_TEXTURE3_ARB); - glTexCoordPointer(2,GL_FLOAT, stride, (void*)(base + mOffsets[TYPE_TEXCOORD3])); + glTexCoordPointer(2,GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD3], (void*)(base + mOffsets[TYPE_TEXCOORD3])); glClientActiveTextureARB(GL_TEXTURE0_ARB); } if (data_mask & MAP_TEXCOORD2) { glClientActiveTextureARB(GL_TEXTURE2_ARB); - glTexCoordPointer(2,GL_FLOAT, stride, (void*)(base + mOffsets[TYPE_TEXCOORD2])); + glTexCoordPointer(2,GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD2], (void*)(base + mOffsets[TYPE_TEXCOORD2])); glClientActiveTextureARB(GL_TEXTURE0_ARB); } if (data_mask & MAP_TEXCOORD1) { glClientActiveTextureARB(GL_TEXTURE1_ARB); - glTexCoordPointer(2,GL_FLOAT, stride, (void*)(base + mOffsets[TYPE_TEXCOORD1])); + glTexCoordPointer(2,GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD1], (void*)(base + mOffsets[TYPE_TEXCOORD1])); glClientActiveTextureARB(GL_TEXTURE0_ARB); } if (data_mask & MAP_BINORMAL) { glClientActiveTextureARB(GL_TEXTURE2_ARB); - glTexCoordPointer(3,GL_FLOAT, stride, (void*)(base + mOffsets[TYPE_BINORMAL])); + glTexCoordPointer(3,GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_BINORMAL], (void*)(base + mOffsets[TYPE_BINORMAL])); glClientActiveTextureARB(GL_TEXTURE0_ARB); } if (data_mask & MAP_TEXCOORD0) { - glTexCoordPointer(2,GL_FLOAT, stride, (void*)(base + mOffsets[TYPE_TEXCOORD0])); + glTexCoordPointer(2,GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD0], (void*)(base + mOffsets[TYPE_TEXCOORD0])); } if (data_mask & MAP_COLOR) { - glColorPointer(4, GL_UNSIGNED_BYTE, stride, (void*)(base + mOffsets[TYPE_COLOR])); + glColorPointer(4, GL_UNSIGNED_BYTE, LLVertexBuffer::sTypeSize[TYPE_COLOR], (void*)(base + mOffsets[TYPE_COLOR])); } if (data_mask & MAP_WEIGHT) { - glVertexAttribPointerARB(1, 1, GL_FLOAT, FALSE, stride, (void*)(base + mOffsets[TYPE_WEIGHT])); + glVertexAttribPointerARB(1, 1, GL_FLOAT, FALSE, LLVertexBuffer::sTypeSize[TYPE_WEIGHT], (void*)(base + mOffsets[TYPE_WEIGHT])); + } + + if (data_mask & MAP_WEIGHT4 && sWeight4Loc != -1) + { + glVertexAttribPointerARB(sWeight4Loc, 4, GL_FLOAT, FALSE, LLVertexBuffer::sTypeSize[TYPE_WEIGHT4], (void*)(base+mOffsets[TYPE_WEIGHT4])); } + if (data_mask & MAP_CLOTHWEIGHT) { - glVertexAttribPointerARB(4, 4, GL_FLOAT, TRUE, stride, (void*)(base + mOffsets[TYPE_CLOTHWEIGHT])); + glVertexAttribPointerARB(4, 4, GL_FLOAT, TRUE, LLVertexBuffer::sTypeSize[TYPE_CLOTHWEIGHT], (void*)(base + mOffsets[TYPE_CLOTHWEIGHT])); } if (data_mask & MAP_VERTEX) { - glVertexPointer(3,GL_FLOAT, stride, (void*)(base + 0)); + if (data_mask & MAP_TEXTURE_INDEX) + { + glVertexPointer(4,GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_VERTEX], (void*)(base + 0)); + } + else + { + glVertexPointer(3,GL_FLOAT, LLVertexBuffer::sTypeSize[TYPE_VERTEX], (void*)(base + 0)); + } } llglassertok(); } -void LLVertexBuffer::markDirty(U32 vert_index, U32 vert_count, U32 indices_index, U32 indices_count) -{ - // TODO: use GL_APPLE_flush_buffer_range here - /*if (useVBOs() && !mFilthy) - { - - }*/ -} diff --git a/indra/llrender/llvertexbuffer.h b/indra/llrender/llvertexbuffer.h index c51ce7ac4e..578cec3885 100644 --- a/indra/llrender/llvertexbuffer.h +++ b/indra/llrender/llvertexbuffer.h @@ -56,42 +56,83 @@ protected: virtual GLuint allocateName() { GLuint name; + stop_glerror(); glGenBuffersARB(1, &name); + stop_glerror(); return name; } virtual void releaseName(GLuint name) { + stop_glerror(); glDeleteBuffersARB(1, &name); + stop_glerror(); } }; +class LLGLFence +{ +public: + virtual void placeFence() = 0; + virtual void wait() = 0; +}; //============================================================================ -// base class - +// base class +class LLPrivateMemoryPool ; class LLVertexBuffer : public LLRefCount { public: + class MappedRegion + { + public: + S32 mType; + S32 mIndex; + S32 mCount; + + MappedRegion(S32 type, S32 index, S32 count) + : mType(type), mIndex(index), mCount(count) + { } + }; + + LLVertexBuffer(const LLVertexBuffer& rhs) + { + *this = rhs; + } + + const LLVertexBuffer& operator=(const LLVertexBuffer& rhs) + { + llerrs << "Illegal operation!" << llendl; + return *this; + } + static LLVBOPool sStreamVBOPool; static LLVBOPool sDynamicVBOPool; static LLVBOPool sStreamIBOPool; static LLVBOPool sDynamicIBOPool; + static S32 sWeight4Loc; + static BOOL sUseStreamDraw; + static BOOL sPreferStreamDraw; static void initClass(bool use_vbo, bool no_vbo_mapping); static void cleanupClass(); static void setupClientArrays(U32 data_mask); + static void drawArrays(U32 mode, const std::vector<LLVector3>& pos, const std::vector<LLVector3>& norm); + static void clientCopy(F64 max_time = 0.005); //copy data from client to GL static void unbind(); //unbind any bound vertex buffer //get the size of a vertex with the given typemask - //if offsets is not NULL, its contents will be filled - //with the offset of each vertex component in the buffer, + static S32 calcVertexSize(const U32& typemask); + + //get the size of a buffer with the given typemask and vertex count + //fill offsets with the offset of each vertex component array into the buffer // indexed by the following enum - static S32 calcStride(const U32& typemask, S32* offsets = NULL); + static S32 calcOffsets(const U32& typemask, S32* offsets, S32 num_vertices); + enum { TYPE_VERTEX, TYPE_NORMAL, @@ -103,9 +144,13 @@ public: // These use VertexAttribPointer and should possibly be made generic TYPE_BINORMAL, TYPE_WEIGHT, + TYPE_WEIGHT4, TYPE_CLOTHWEIGHT, TYPE_MAX, TYPE_INDEX, + + //no actual additional data, but indicates position.w is texture index + TYPE_TEXTURE_INDEX, }; enum { MAP_VERTEX = (1<<TYPE_VERTEX), @@ -118,7 +163,9 @@ public: // These use VertexAttribPointer and should possibly be made generic MAP_BINORMAL = (1<<TYPE_BINORMAL), MAP_WEIGHT = (1<<TYPE_WEIGHT), + MAP_WEIGHT4 = (1<<TYPE_WEIGHT4), MAP_CLOTHWEIGHT = (1<<TYPE_CLOTHWEIGHT), + MAP_TEXTURE_INDEX = (1<<TYPE_TEXTURE_INDEX), }; protected: @@ -148,8 +195,8 @@ public: LLVertexBuffer(U32 typemask, S32 usage); // map for data access - U8* mapVertexBuffer(S32 type = -1, S32 access = -1); - U8* mapIndexBuffer(S32 access = -1); + U8* mapVertexBuffer(S32 type, S32 index, S32 count, bool map_range); + U8* mapIndexBuffer(S32 index, S32 count, bool map_range); // set for rendering virtual void setBuffer(U32 data_mask, S32 type = -1); // calls setupVertexBuffer() if data_mask is not 0 @@ -164,15 +211,16 @@ public: // vb->getNormalStrider(norms); // setVertsNorms(verts, norms); // vb->unmapBuffer(); - bool getVertexStrider(LLStrider<LLVector3>& strider, S32 index=0); - bool getIndexStrider(LLStrider<U16>& strider, S32 index=0); - bool getTexCoord0Strider(LLStrider<LLVector2>& strider, S32 index=0); - bool getTexCoord1Strider(LLStrider<LLVector2>& strider, S32 index=0); - bool getNormalStrider(LLStrider<LLVector3>& strider, S32 index=0); - bool getBinormalStrider(LLStrider<LLVector3>& strider, S32 index=0); - bool getColorStrider(LLStrider<LLColor4U>& strider, S32 index=0); - bool getWeightStrider(LLStrider<F32>& strider, S32 index=0); - bool getClothWeightStrider(LLStrider<LLVector4>& strider, S32 index=0); + bool getVertexStrider(LLStrider<LLVector3>& strider, S32 index=0, S32 count = -1, bool map_range = false); + bool getIndexStrider(LLStrider<U16>& strider, S32 index=0, S32 count = -1, bool map_range = false); + bool getTexCoord0Strider(LLStrider<LLVector2>& strider, S32 index=0, S32 count = -1, bool map_range = false); + bool getTexCoord1Strider(LLStrider<LLVector2>& strider, S32 index=0, S32 count = -1, bool map_range = false); + bool getNormalStrider(LLStrider<LLVector3>& strider, S32 index=0, S32 count = -1, bool map_range = false); + bool getBinormalStrider(LLStrider<LLVector3>& strider, S32 index=0, S32 count = -1, bool map_range = false); + bool getColorStrider(LLStrider<LLColor4U>& strider, S32 index=0, S32 count = -1, bool map_range = false); + bool getWeightStrider(LLStrider<F32>& strider, S32 index=0, S32 count = -1, bool map_range = false); + bool getWeight4Strider(LLStrider<LLVector4>& strider, S32 index=0, S32 count = -1, bool map_range = false); + bool getClothWeightStrider(LLStrider<LLVector4>& strider, S32 index=0, S32 count = -1, bool map_range = false); BOOL isEmpty() const { return mEmpty; } BOOL isLocked() const { return mVertexLocked || mIndexLocked; } @@ -181,33 +229,35 @@ public: S32 getRequestedVerts() const { return mRequestedNumVerts; } S32 getRequestedIndices() const { return mRequestedNumIndices; } - U8* getIndicesPointer() const { return useVBOs() ? NULL : mMappedIndexData; } - U8* getVerticesPointer() const { return useVBOs() ? NULL : mMappedData; } - S32 getStride() const { return mStride; } - S32 getTypeMask() const { return mTypeMask; } - BOOL hasDataType(S32 type) const { return ((1 << type) & getTypeMask()) ? TRUE : FALSE; } - S32 getSize() const { return mNumVerts*mStride; } + U8* getIndicesPointer() const { return useVBOs() ? (U8*) mAlignedIndexOffset : mMappedIndexData; } + U8* getVerticesPointer() const { return useVBOs() ? (U8*) mAlignedOffset : mMappedData; } + U32 getTypeMask() const { return mTypeMask; } + bool hasDataType(S32 type) const { return ((1 << type) & getTypeMask()); } + S32 getSize() const; S32 getIndicesSize() const { return mNumIndices * sizeof(U16); } U8* getMappedData() const { return mMappedData; } U8* getMappedIndices() const { return mMappedIndexData; } S32 getOffset(S32 type) const { return mOffsets[type]; } S32 getUsage() const { return mUsage; } - void setStride(S32 type, S32 new_stride); - - void markDirty(U32 vert_index, U32 vert_count, U32 indices_index, U32 indices_count); - void draw(U32 mode, U32 count, U32 indices_offset) const; void drawArrays(U32 mode, U32 offset, U32 count) const; void drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indices_offset) const; + //for debugging, validate data in given range is valid + void validateRange(U32 start, U32 end, U32 count, U32 offset) const; + + + protected: S32 mNumVerts; // Number of vertices allocated S32 mNumIndices; // Number of indices allocated S32 mRequestedNumVerts; // Number of vertices requested S32 mRequestedNumIndices; // Number of indices requested - S32 mStride; + ptrdiff_t mAlignedOffset; + ptrdiff_t mAlignedIndexOffset; + S32 mSize; U32 mTypeMask; S32 mUsage; // GL usage U32 mGLBuffer; // GL VBO handle @@ -223,20 +273,17 @@ protected: BOOL mDynamicSize; // if TRUE, buffer has been resized at least once (and should be padded) S32 mOffsets[TYPE_MAX]; - class DirtyRegion - { - public: - U32 mIndex; - U32 mCount; - U32 mIndicesIndex; - U32 mIndicesCount; + std::vector<MappedRegion> mMappedVertexRegions; + std::vector<MappedRegion> mMappedIndexRegions; + + mutable LLGLFence* mFence; + + void placeFence() const; + void waitFence() const; - DirtyRegion(U32 vi, U32 vc, U32 ii, U32 ic) - : mIndex(vi), mCount(vc), mIndicesIndex(ii), mIndicesCount(ic) - { } - }; - std::vector<DirtyRegion> mDirtyRegions; //vector of dirty regions to rebuild +private: + static LLPrivateMemoryPool* sPrivatePoolp ; public: static S32 sCount; @@ -248,12 +295,12 @@ public: static BOOL sDisableVBOMapping; //disable glMapBufferARB static BOOL sEnableVBOs; - static BOOL sVBOActive; - static BOOL sIBOActive; - static S32 sTypeOffsets[TYPE_MAX]; + static S32 sTypeSize[TYPE_MAX]; static U32 sGLMode[LLRender::NUM_MODES]; static U32 sGLRenderBuffer; - static U32 sGLRenderIndices; + static U32 sGLRenderIndices; + static BOOL sVBOActive; + static BOOL sIBOActive; static U32 sLastMask; static U32 sAllocatedBytes; static U32 sBindCount; |