summaryrefslogtreecommitdiff
path: root/indra/llrender
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llrender')
-rw-r--r--indra/llrender/llfontfreetype.cpp2
-rw-r--r--indra/llrender/llfontgl.cpp3
-rw-r--r--indra/llrender/llgl.cpp461
-rw-r--r--indra/llrender/llgl.h93
-rw-r--r--indra/llrender/llglheaders.h189
-rw-r--r--indra/llrender/llglslshader.cpp96
-rw-r--r--indra/llrender/llglslshader.h7
-rw-r--r--indra/llrender/llglstates.h32
-rw-r--r--indra/llrender/llimagegl.cpp24
-rw-r--r--indra/llrender/llimagegl.h2
-rw-r--r--indra/llrender/llrender.cpp233
-rw-r--r--indra/llrender/llrender.h40
-rw-r--r--indra/llrender/llrendertarget.cpp574
-rw-r--r--indra/llrender/llrendertarget.h42
-rw-r--r--indra/llrender/llshadermgr.cpp331
-rw-r--r--indra/llrender/llshadermgr.h5
-rw-r--r--indra/llrender/llvertexbuffer.cpp671
-rw-r--r--indra/llrender/llvertexbuffer.h120
18 files changed, 1952 insertions, 973 deletions
diff --git a/indra/llrender/llfontfreetype.cpp b/indra/llrender/llfontfreetype.cpp
index b84e696e2d..91c8a37022 100644
--- a/indra/llrender/llfontfreetype.cpp
+++ b/indra/llrender/llfontfreetype.cpp
@@ -482,7 +482,7 @@ void LLFontFreetype::renderGlyph(U32 glyph_index) const
if (mFTFace == NULL)
return;
- int error = FT_Load_Glyph(mFTFace, glyph_index, FT_LOAD_DEFAULT );
+ int error = FT_Load_Glyph(mFTFace, glyph_index, FT_LOAD_FORCE_AUTOHINT );
llassert(!error);
error = FT_Render_Glyph(mFTFace->glyph, gFontRenderMode);
diff --git a/indra/llrender/llfontgl.cpp b/indra/llrender/llfontgl.cpp
index 13008292f6..180ae4dfa6 100644
--- a/indra/llrender/llfontgl.cpp
+++ b/indra/llrender/llfontgl.cpp
@@ -271,7 +271,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 +554,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 6ea63809f8..c224ab0e9b 100644
--- a/indra/llrender/llgl.cpp
+++ b/indra/llrender/llgl.cpp
@@ -57,9 +57,12 @@
BOOL gDebugSession = FALSE;
BOOL gDebugGL = FALSE;
BOOL gClothRipple = FALSE;
-BOOL gNoRender = FALSE;
+BOOL gHeadlessClient = FALSE;
BOOL gGLActive = FALSE;
+static const std::string HEADLESS_VENDOR_STRING("Linden Lab");
+static const std::string HEADLESS_RENDERER_STRING("Headless");
+static const std::string HEADLESS_VERSION_STRING("1.0");
std::ofstream gFailLog;
@@ -102,7 +105,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
@@ -125,6 +127,11 @@ PFNGLUNMAPBUFFERARBPROC glUnmapBufferARB = NULL;
PFNGLGETBUFFERPARAMETERIVARBPROC glGetBufferParameterivARB = NULL;
PFNGLGETBUFFERPOINTERVARBPROC glGetBufferPointervARB = NULL;
+// GL_ARB_map_buffer_range
+PFNGLMAPBUFFERRANGEPROC glMapBufferRange;
+PFNGLFLUSHMAPPEDBUFFERRANGEPROC glFlushMappedBufferRange;
+
+
// vertex object prototypes
PFNGLNEWOBJECTBUFFERATIPROC glNewObjectBufferATI = NULL;
PFNGLISOBJECTBUFFERATIPROC glIsObjectBufferATI = NULL;
@@ -154,30 +161,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;
@@ -316,22 +326,32 @@ LLGLManager::LLGLManager() :
mIsDisabled(FALSE),
mHasMultitexture(FALSE),
+ mHasATIMemInfo(FALSE),
+ mHasNVXMemInfo(FALSE),
mNumTextureUnits(1),
mHasMipMapGeneration(FALSE),
mHasCompressedTextures(FALSE),
mHasFramebufferObject(FALSE),
- mHasFramebufferMultisample(FALSE),
+ mMaxSamples(0),
mHasBlendFuncSeparate(FALSE),
mHasVertexBufferObject(FALSE),
+ mHasMapBufferRange(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),
@@ -500,6 +520,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;
@@ -519,6 +553,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();
@@ -538,9 +599,19 @@ void LLGLManager::setToDebugGPU()
void LLGLManager::getGLInfo(LLSD& info)
{
- info["GLInfo"]["GLVendor"] = std::string((const char *)glGetString(GL_VENDOR));
- info["GLInfo"]["GLRenderer"] = std::string((const char *)glGetString(GL_RENDERER));
- info["GLInfo"]["GLVersion"] = std::string((const char *)glGetString(GL_VERSION));
+ if (gHeadlessClient)
+ {
+ info["GLInfo"]["GLVendor"] = HEADLESS_VENDOR_STRING;
+ info["GLInfo"]["GLRenderer"] = HEADLESS_RENDERER_STRING;
+ info["GLInfo"]["GLVersion"] = HEADLESS_VERSION_STRING;
+ return;
+ }
+ else
+ {
+ info["GLInfo"]["GLVendor"] = std::string((const char *)glGetString(GL_VENDOR));
+ info["GLInfo"]["GLRenderer"] = std::string((const char *)glGetString(GL_RENDERER));
+ info["GLInfo"]["GLVersion"] = std::string((const char *)glGetString(GL_VERSION));
+ }
#if !LL_MESA_HEADLESS
std::string all_exts = ll_safe_string((const char *)gGLHExts.mSysExts);
@@ -556,14 +627,22 @@ void LLGLManager::getGLInfo(LLSD& info)
std::string LLGLManager::getGLInfoString()
{
std::string info_str;
- std::string all_exts, line;
- info_str += std::string("GL_VENDOR ") + ll_safe_string((const char *)glGetString(GL_VENDOR)) + std::string("\n");
- info_str += std::string("GL_RENDERER ") + ll_safe_string((const char *)glGetString(GL_RENDERER)) + std::string("\n");
- info_str += std::string("GL_VERSION ") + ll_safe_string((const char *)glGetString(GL_VERSION)) + std::string("\n");
+ if (gHeadlessClient)
+ {
+ info_str += std::string("GL_VENDOR ") + HEADLESS_VENDOR_STRING + std::string("\n");
+ info_str += std::string("GL_RENDERER ") + HEADLESS_RENDERER_STRING + std::string("\n");
+ info_str += std::string("GL_VERSION ") + HEADLESS_VERSION_STRING + std::string("\n");
+ }
+ else
+ {
+ info_str += std::string("GL_VENDOR ") + ll_safe_string((const char *)glGetString(GL_VENDOR)) + std::string("\n");
+ info_str += std::string("GL_RENDERER ") + ll_safe_string((const char *)glGetString(GL_RENDERER)) + std::string("\n");
+ info_str += std::string("GL_VERSION ") + ll_safe_string((const char *)glGetString(GL_VERSION)) + std::string("\n");
+ }
#if !LL_MESA_HEADLESS
- all_exts = (const char *)gGLHExts.mSysExts;
+ std::string all_exts= ll_safe_string(((const char *)gGLHExts.mSysExts));
LLStringUtil::replaceChar(all_exts, ' ', '\n');
info_str += std::string("GL_EXTENSIONS:\n") + all_exts + std::string("\n");
#endif
@@ -573,15 +652,21 @@ std::string LLGLManager::getGLInfoString()
void LLGLManager::printGLInfoString()
{
- std::string info_str;
- std::string all_exts, line;
-
- LL_INFOS("RenderInit") << "GL_VENDOR: " << ((const char *)glGetString(GL_VENDOR)) << LL_ENDL;
- LL_INFOS("RenderInit") << "GL_RENDERER: " << ((const char *)glGetString(GL_RENDERER)) << LL_ENDL;
- LL_INFOS("RenderInit") << "GL_VERSION: " << ((const char *)glGetString(GL_VERSION)) << LL_ENDL;
+ if (gHeadlessClient)
+ {
+ LL_INFOS("RenderInit") << "GL_VENDOR: " << HEADLESS_VENDOR_STRING << LL_ENDL;
+ LL_INFOS("RenderInit") << "GL_RENDERER: " << HEADLESS_RENDERER_STRING << LL_ENDL;
+ LL_INFOS("RenderInit") << "GL_VERSION: " << HEADLESS_VERSION_STRING << LL_ENDL;
+ }
+ else
+ {
+ LL_INFOS("RenderInit") << "GL_VENDOR: " << ((const char *)glGetString(GL_VENDOR)) << LL_ENDL;
+ LL_INFOS("RenderInit") << "GL_RENDERER: " << ((const char *)glGetString(GL_RENDERER)) << LL_ENDL;
+ LL_INFOS("RenderInit") << "GL_VERSION: " << ((const char *)glGetString(GL_VERSION)) << LL_ENDL;
+ }
#if !LL_MESA_HEADLESS
- all_exts = std::string(gGLHExts.mSysExts);
+ std::string all_exts= ll_safe_string(((const char *)gGLHExts.mSysExts));
LLStringUtil::replaceChar(all_exts, ' ', '\n');
LL_DEBUGS("RenderInit") << "GL_EXTENSIONS:\n" << all_exts << LL_ENDL;
#endif
@@ -590,10 +675,25 @@ void LLGLManager::printGLInfoString()
std::string LLGLManager::getRawGLString()
{
std::string gl_string;
- gl_string = ll_safe_string((char*)glGetString(GL_VENDOR)) + " " + ll_safe_string((char*)glGetString(GL_RENDERER));
+ if (gHeadlessClient)
+ {
+ gl_string = HEADLESS_VENDOR_STRING + " " + HEADLESS_RENDERER_STRING;
+ }
+ else
+ {
+ gl_string = ll_safe_string((char*)glGetString(GL_VENDOR)) + " " + ll_safe_string((char*)glGetString(GL_RENDERER));
+ }
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)
@@ -614,47 +714,42 @@ void LLGLManager::initExtensions()
mHasMultitexture = TRUE;
# else
mHasMultitexture = FALSE;
-# endif
+# endif // GL_ARB_multitexture
# ifdef GL_ARB_texture_env_combine
mHasARBEnvCombine = TRUE;
# else
mHasARBEnvCombine = FALSE;
-# endif
+# endif // GL_ARB_texture_env_combine
# ifdef GL_ARB_texture_compression
mHasCompressedTextures = TRUE;
# else
mHasCompressedTextures = FALSE;
-# endif
+# endif // GL_ARB_texture_compression
# ifdef GL_ARB_vertex_buffer_object
mHasVertexBufferObject = TRUE;
# else
mHasVertexBufferObject = FALSE;
-# endif
+# endif // GL_ARB_vertex_buffer_object
# ifdef GL_EXT_framebuffer_object
mHasFramebufferObject = TRUE;
# else
mHasFramebufferObject = FALSE;
-# endif
-# ifdef GL_EXT_framebuffer_multisample
- mHasFramebufferMultisample = TRUE;
-# else
- mHasFramebufferMultisample = FALSE;
-# endif
+# endif // GL_EXT_framebuffer_object
# ifdef GL_ARB_draw_buffers
mHasDrawBuffers = TRUE;
#else
mHasDrawBuffers = FALSE;
-# endif
+# endif // GL_ARB_draw_buffers
# if defined(GL_NV_depth_clamp) || defined(GL_ARB_depth_clamp)
mHasDepthClamp = TRUE;
#else
mHasDepthClamp = FALSE;
-#endif
+#endif // defined(GL_NV_depth_clamp) || defined(GL_ARB_depth_clamp)
# if GL_EXT_blend_func_separate
mHasBlendFuncSeparate = TRUE;
#else
mHasBlendFuncSeparate = FALSE;
-# endif
+# endif // GL_EXT_blend_func_separate
mHasMipMapGeneration = FALSE;
mHasSeparateSpecularColor = FALSE;
mHasAnisotropic = FALSE;
@@ -667,6 +762,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");
@@ -675,15 +772,24 @@ 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);
+ mHasMapBufferRange = ExtensionExists("GL_ARB_map_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
@@ -705,7 +811,6 @@ void LLGLManager::initExtensions()
mHasCompressedTextures = FALSE;
mHasVertexBufferObject = FALSE;
mHasFramebufferObject = FALSE;
- mHasFramebufferMultisample = FALSE;
mHasDrawBuffers = FALSE;
mHasBlendFuncSeparate = FALSE;
mHasMipMapGeneration = FALSE;
@@ -759,10 +864,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
@@ -795,6 +899,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;
@@ -826,11 +934,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);
@@ -859,31 +969,34 @@ void LLGLManager::initExtensions()
mHasVertexBufferObject = FALSE;
}
}
+ 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)
{
@@ -893,6 +1006,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");
@@ -1145,7 +1265,7 @@ void assert_glerror()
}
}
- if (!gNoRender && gDebugGL)
+ if (gDebugGL)
{
do_assert_glerror();
}
@@ -1310,10 +1430,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",
@@ -1324,7 +1440,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[] =
@@ -1337,7 +1454,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;
@@ -1346,68 +1464,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();
@@ -1841,12 +1987,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;
+
+ if (mApply)
+ {
+ mModelview = modelview;
+ mProjection = projection;
- setPlane(p.mV[0], p.mV[1], p.mV[2], p.mV[3]);
+ setPlane(p[0], p[1], p[2], p[3]);
+ }
}
void LLGLUserClipPlane::setPlane(F32 a, F32 b, F32 c, F32 d)
@@ -1877,31 +2028,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()
@@ -1970,20 +2110,22 @@ 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)
+ tracker_t::LLInstanceTrackerScopedGuard guard;
+ for (tracker_t::instance_iter iter = guard.beginInstances(); iter != guard.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)
+ tracker_t::LLInstanceTrackerScopedGuard guard;
+ for (tracker_t::instance_iter iter = guard.beginInstances(); iter != guard.endInstances(); ++iter)
{
- LLGLNamePool* pool = *iter;
- pool->cleanup();
+ LLGLNamePool & pool = *iter;
+ pool.cleanup();
}
}
@@ -2072,11 +2214,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 85fab7a0f8..d1bee00161 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,34 @@ 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 mHasMapBufferRange;
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 +146,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 +311,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 +334,7 @@ private:
class LLGLSquashToFarClip
{
public:
- LLGLSquashToFarClip(glh::matrix4f projection);
+ LLGLSquashToFarClip(glh::matrix4f projection, U32 layer = 0);
~LLGLSquashToFarClip();
};
@@ -328,9 +342,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 +373,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;
@@ -415,7 +429,70 @@ void set_binormals(const S32 index, const U32 stride, const LLVector3 *binormals
void parse_gl_version( S32* major, S32* minor, S32* release, std::string* vendor_specific );
extern BOOL gClothRipple;
-extern BOOL gNoRender;
+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..f35f329f00 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,10 @@ extern PFNGLUNMAPBUFFERARBPROC glUnmapBufferARB;
extern PFNGLGETBUFFERPARAMETERIVARBPROC glGetBufferParameterivARB;
extern PFNGLGETBUFFERPOINTERVARBPROC glGetBufferPointervARB;
+// GL_ARB_map_buffer_range
+extern PFNGLMAPBUFFERRANGEPROC glMapBufferRange;
+extern PFNGLFLUSHMAPPEDBUFFERRANGEPROC glFlushMappedBufferRange;
+
// GL_ATI_vertex_array_object
extern PFNGLNEWOBJECTBUFFERATIPROC glNewObjectBufferATI;
extern PFNGLISOBJECTBUFFERATIPROC glIsObjectBufferATI;
@@ -306,6 +310,10 @@ extern PFNGLUNMAPBUFFERARBPROC glUnmapBufferARB;
extern PFNGLGETBUFFERPARAMETERIVARBPROC glGetBufferParameterivARB;
extern PFNGLGETBUFFERPOINTERVARBPROC glGetBufferPointervARB;
+// GL_ARB_map_buffer_range
+extern PFNGLMAPBUFFERRANGEPROC glMapBufferRange;
+extern PFNGLFLUSHMAPPEDBUFFERRANGEPROC glFlushMappedBufferRange;
+
// GL_ATI_vertex_array_object
extern PFNGLNEWOBJECTBUFFERATIPROC glNewObjectBufferATI;
extern PFNGLISOBJECTBUFFERATIPROC glIsObjectBufferATI;
@@ -449,34 +457,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 +519,10 @@ extern PFNGLUNMAPBUFFERARBPROC glUnmapBufferARB;
extern PFNGLGETBUFFERPARAMETERIVARBPROC glGetBufferParameterivARB;
extern PFNGLGETBUFFERPOINTERVARBPROC glGetBufferPointervARB;
+// GL_ARB_map_buffer_range
+extern PFNGLMAPBUFFERRANGEPROC glMapBufferRange;
+extern PFNGLFLUSHMAPPEDBUFFERRANGEPROC glFlushMappedBufferRange;
+
// GL_ATI_vertex_array_object
extern PFNGLNEWOBJECTBUFFERATIPROC glNewObjectBufferATI;
extern PFNGLISOBJECTBUFFERATIPROC glIsObjectBufferATI;
@@ -651,34 +665,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 +713,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 +734,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 +821,7 @@ extern "C" {
#define GL_DYNAMIC_READ_ARB 0x88E9
#define GL_DYNAMIC_COPY_ARB 0x88EA
#endif
-
+
#ifndef GL_ARB_vertex_buffer_object
@@ -840,4 +901,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..ad2c662dfc 100644
--- a/indra/llrender/llglslshader.cpp
+++ b/indra/llrender/llglslshader.cpp
@@ -48,6 +48,8 @@ using std::pair;
using std::make_pair;
using std::string;
+GLhandleARB LLGLSLShader::sCurBoundShader = 0;
+
BOOL shouldChange(const LLVector4& v1, const LLVector4& v2)
{
return v1 != v2;
@@ -55,8 +57,8 @@ 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)
{
}
@@ -107,18 +109,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 +130,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 +162,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 +329,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;
@@ -342,7 +379,7 @@ void LLGLSLShader::bind()
if (gGLManager.mHasShaderObjects)
{
glUseProgramObjectARB(mProgramObject);
-
+ sCurBoundShader = mProgramObject;
if (mUniformsDirty)
{
LLShaderMgr::instance()->updateShaderUniforms(this);
@@ -365,6 +402,7 @@ void LLGLSLShader::unbind()
}
}
glUseProgramObjectARB(0);
+ sCurBoundShader = 0;
stop_glerror();
}
}
@@ -372,6 +410,7 @@ void LLGLSLShader::unbind()
void LLGLSLShader::bindNoShader(void)
{
glUseProgramObjectARB(0);
+ sCurBoundShader = 0;
}
S32 LLGLSLShader::enableTexture(S32 uniform, LLTexUnit::eTextureType mode)
@@ -698,17 +737,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 +950,9 @@ void LLGLSLShader::uniformMatrix4fv(const string& uniform, U32 count, GLboolean
if (location >= 0)
{
+ stop_glerror();
glUniformMatrix4fvARB(location, count, transpose, v);
+ stop_glerror();
}
}
diff --git a/indra/llrender/llglslshader.h b/indra/llrender/llglslshader.h
index c11bd50716..4922eb6d67 100644
--- a/indra/llrender/llglslshader.h
+++ b/indra/llrender/llglslshader.h
@@ -42,8 +42,11 @@ 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;
// char numLights;
@@ -63,6 +66,8 @@ public:
LLGLSLShader();
+ static GLhandleARB sCurBoundShader;
+
void unload();
BOOL createShader(std::vector<std::string> * attributes,
std::vector<std::string> * uniforms);
@@ -103,7 +108,7 @@ public:
void vertexAttrib4fv(U32 index, GLfloat* v);
GLint getUniformLocation(const std::string& uniform);
-
+ GLint getAttribLocation(U32 attrib);
GLint mapUniformTextureChannel(GLint location, GLenum type);
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 e8e98211f1..60a5962234 100644
--- a/indra/llrender/llimagegl.cpp
+++ b/indra/llrender/llimagegl.cpp
@@ -967,12 +967,14 @@ BOOL LLImageGL::setSubImage(const U8* datap, S32 data_width, S32 data_height, S3
}
if (mTexName == 0)
{
- llwarns << "Setting subimage on image without GL texture" << llendl;
+ // *TODO: Re-enable warning? Ran into thread locking issues? DK 2011-02-18
+ //llwarns << "Setting subimage on image without GL texture" << llendl;
return FALSE;
}
if (datap == NULL)
{
- llwarns << "Setting subimage on image with NULL datap" << llendl;
+ // *TODO: Re-enable warning? Ran into thread locking issues? DK 2011-02-18
+ //llwarns << "Setting subimage on image with NULL datap" << llendl;
return FALSE;
}
@@ -1081,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
@@ -1100,6 +1107,7 @@ void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 widt
//the texture is assiciate with some image by calling glTexImage outside LLImageGL
BOOL LLImageGL::createGLTexture()
{
+ if (gHeadlessClient) return FALSE;
if (gGLManager.mIsDisabled)
{
llwarns << "Trying to create a texture while GL is disabled!" << llendl;
@@ -1128,6 +1136,7 @@ BOOL LLImageGL::createGLTexture()
BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename/*=0*/, BOOL to_create, S32 category)
{
+ if (gHeadlessClient) return FALSE;
if (gGLManager.mIsDisabled)
{
llwarns << "Trying to create a texture while GL is disabled!" << llendl;
@@ -1409,11 +1418,13 @@ void LLImageGL::deleteDeadTextures()
{
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->getCurrTexture() == tex)
{
- gGL.getTexUnit(i)->unbind(LLTexUnit::TT_TEXTURE);
+ tex_unit->unbind(tex_unit->getCurrType());
stop_glerror();
}
}
@@ -1706,6 +1717,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
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 fd899d7f87..bf59423adc 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"
@@ -46,13 +47,15 @@ S32 gGLViewport[4];
U32 LLRender::sUICalls = 0;
U32 LLRender::sUIVerts = 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 +121,29 @@ 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 = (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 +184,11 @@ void LLTexUnit::enable(eTextureType type)
mCurrTexType = type;
gGL.flush();
- glEnable(sGLTextureType[type]);
+ if (type != LLTexUnit::TT_MULTISAMPLE_TEXTURE &&
+ mIndex < gGLManager.mNumTextureUnits)
+ {
+ glEnable(sGLTextureType[type]);
+ }
}
}
@@ -179,7 +201,12 @@ void LLTexUnit::disable(void)
activate();
unbind(mCurrTexType);
gGL.flush();
- glDisable(sGLTextureType[mCurrTexType]);
+ if (mCurrTexType != LLTexUnit::TT_MULTISAMPLE_TEXTURE &&
+ mIndex < gGLManager.mNumTextureUnits)
+ {
+ glDisable(sGLTextureType[mCurrTexType]);
+ }
+
mCurrTexType = TT_NONE;
}
}
@@ -377,6 +404,7 @@ void LLTexUnit::unbind(eTextureType type)
activate();
mCurrTexture = 0;
glBindTexture(sGLTextureType[type], 0);
+ stop_glerror();
}
}
@@ -398,7 +426,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();
@@ -747,6 +775,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),
@@ -762,6 +914,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;
@@ -800,6 +957,12 @@ void LLRender::shutdown()
mTexUnits.clear();
delete mDummyTexUnit;
mDummyTexUnit = NULL;
+
+ for (U32 i = 0; i < mLightState.size(); ++i)
+ {
+ delete mLightState[i];
+ }
+ mLightState.clear();
mBuffer = NULL ;
}
@@ -904,7 +1067,7 @@ LLVector3 LLRender::getUITranslation()
{
if (mUIOffset.empty())
{
- return LLVector3::zero;
+ return LLVector3(0,0,0);
}
return mUIOffset.back();
}
@@ -913,7 +1076,7 @@ LLVector3 LLRender::getUIScale()
{
if (mUIScale.empty())
{
- return LLVector3(1.f, 1.f, 1.f);
+ return LLVector3(1,1,1);
}
return mUIScale.back();
}
@@ -938,15 +1101,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)
@@ -984,15 +1153,19 @@ void LLRender::setAlphaRejectSettings(eCompareFunc func, F32 value)
{
flush();
- mCurrAlphaFunc = func;
- mCurrAlphaFuncVal = value;
- if (func == CF_DEFAULT)
- {
- glAlphaFunc(GL_GREATER, 0.01f);
- }
- else
+ 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);
+ }
}
}
@@ -1051,6 +1224,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 611066a960..6327849dbb 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"
@@ -56,6 +57,7 @@ public:
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 +214,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;
@@ -328,6 +365,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; }
@@ -364,6 +403,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..b6463309e1 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,23 +72,32 @@ 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)
+void LLRenderTarget::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil, LLTexUnit::eTextureType usage, bool use_fbo, S32 samples)
{
stop_glerror();
+
+ release();
+
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)
{
@@ -99,24 +108,24 @@ void LLRenderTarget::allocate(U32 resx, U32 resy, U32 color_fmt, BOOL depth, BOO
stop_glerror();
}
- 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();
@@ -145,41 +154,69 @@ 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);
+ glTexImage2DMultisample(LLTexUnit::getInternalType(mUsage), mSamples, color_fmt, mResX, mResY, GL_TRUE);
}
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);
+ LLImageGL::setManualImage(LLTexUnit::getInternalType(mUsage), 0, color_fmt, mResX, mResY, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
}
- 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();
+ }
+
}
void LLRenderTarget::allocateDepth()
@@ -187,18 +224,29 @@ void 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);
+ 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);
+ LLImageGL::setManualImage(internal_type, 0, GL_DEPTH_COMPONENT32, mResX, mResY, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL);
+ }
+#ifdef GL_ARB_texture_multisample
+ else
+ {
+ glTexImage2DMultisample(LLTexUnit::getInternalType(mUsage), mSamples, GL_DEPTH_COMPONENT32, mResX, mResY, GL_TRUE);
+ }
+#else
+ llassert_always(mSamples <= 1);
+#endif
}
}
@@ -209,65 +257,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 +349,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 +381,7 @@ void LLRenderTarget::unbindTarget()
{
if (gGLManager.mHasFramebufferObject)
{
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
sBoundTarget = NULL;
}
@@ -349,19 +415,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 +443,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 +451,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 +511,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 +541,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..094b58b562 100644
--- a/indra/llrender/llrendertarget.h
+++ b/indra/llrender/llrendertarget.h
@@ -63,7 +63,7 @@ class LLRenderTarget
{
public:
//whether or not to use FBO implementation
- static BOOL sUseFBO;
+ static bool sUseFBO;
LLRenderTarget();
virtual ~LLRenderTarget();
@@ -71,10 +71,7 @@ public:
//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);
+ void 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
@@ -88,7 +85,7 @@ public:
//free any allocated resources
//safe to call redundantly
- void release();
+ virtual void release();
//bind target for rendering
//applies appropriate viewport
@@ -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..751b250d96 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
@@ -201,17 +209,39 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
if (features->hasWaterFog)
{
- if (!shader->attachObject("lighting/lightWaterF.glsl"))
+ if (features->disableTextureIndex)
{
- return FALSE;
+ if (!shader->attachObject("lighting/lightWaterNonIndexedF.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 (!shader->attachObject("lighting/lightNonIndexedF.glsl"))
+ {
+ return FALSE;
+ }
+ }
+ else
+ {
+ if (!shader->attachObject("lighting/lightF.glsl"))
+ {
+ return FALSE;
+ }
+ shader->mFeatures.mIndexedTextureChannels = gGLManager.mNumTextureImageUnits-1;
}
}
}
@@ -220,27 +250,78 @@ 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 (!shader->attachObject("lighting/lightFullbrightWaterNonIndexedF.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 (!shader->attachObject("lighting/lightFullbrightNonIndexedF.glsl"))
+ {
+ return FALSE;
+ }
+ }
+ else
+ {
+ if (!shader->attachObject("lighting/lightFullbrightF.glsl"))
+ {
+ return FALSE;
+ }
+ shader->mFeatures.mIndexedTextureChannels = gGLManager.mNumTextureImageUnits-1;
}
}
}
@@ -251,17 +332,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;
}
}
}
@@ -305,13 +408,16 @@ void LLShaderMgr::dumpObjectLog(GLhandleARB ret, BOOL warns)
}
}
-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 +462,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 +583,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 +649,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 +667,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 67417aea43..3bf8e84cd6 100644
--- a/indra/llrender/llvertexbuffer.cpp
+++ b/indra/llrender/llvertexbuffer.cpp
@@ -33,6 +33,7 @@
#include "llglheaders.h"
#include "llmemtype.h"
#include "llrender.h"
+#include "llvector4a.h"
#include "llmemory.h"
//============================================================================
@@ -59,20 +60,24 @@ 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] =
+
+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,
};
@@ -141,11 +146,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)
{
@@ -207,18 +212,53 @@ 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(norm.size() >= pos.size());
+
+ 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);
@@ -229,6 +269,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;
@@ -245,16 +304,17 @@ 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();
}
void LLVertexBuffer::draw(U32 mode, U32 count, U32 indices_offset) const
{
llassert(mRequestedNumIndices >= 0);
-
if (indices_offset >= (U32) mRequestedNumIndices ||
indices_offset + count > (U32) mRequestedNumIndices)
{
@@ -286,7 +346,6 @@ void LLVertexBuffer::draw(U32 mode, U32 count, U32 indices_offset) const
void LLVertexBuffer::drawArrays(U32 mode, U32 first, U32 count) const
{
llassert(mRequestedNumVerts >= 0);
-
if (first >= (U32) mRequestedNumVerts ||
first + count > (U32) mRequestedNumVerts)
{
@@ -312,12 +371,19 @@ void LLVertexBuffer::drawArrays(U32 mode, U32 first, U32 count) const
//static
void LLVertexBuffer::initClass(bool use_vbo, bool no_vbo_mapping)
{
- sEnableVBOs = use_vbo;
+ sEnableVBOs = use_vbo && gGLManager.mHasVertexBufferObject ;
+ if(sEnableVBOs)
+ {
+ //llassert_always(glBindBufferARB) ; //double check the extention for VBO is loaded.
+
+ llinfos << "VBO is enabled." << llendl ;
+ }
+ else
+ {
+ llinfos << "VBO is disabled." << llendl ;
+ }
+
sDisableVBOMapping = sEnableVBOs && no_vbo_mapping ;
- LLGLNamePool::registerPool(&sDynamicVBOPool);
- LLGLNamePool::registerPool(&sDynamicIBOPool);
- LLGLNamePool::registerPool(&sStreamVBOPool);
- LLGLNamePool::registerPool(&sStreamIBOPool);
if(!sPrivatePoolp)
{
@@ -401,22 +467,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;
@@ -424,13 +497,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()
@@ -545,7 +640,6 @@ void LLVertexBuffer::createGLBuffer()
static int gl_buffer_idx = 0;
mGLBuffer = ++gl_buffer_idx;
mMappedData = (U8*)ALLOCATE_MEM(sPrivatePoolp, size);
- memset(mMappedData, 0, size);
}
}
@@ -566,8 +660,13 @@ 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;
@@ -575,7 +674,6 @@ void LLVertexBuffer::createGLIndices()
else
{
mMappedIndexData = (U8*)ALLOCATE_MEM(sPrivatePoolp, size);
- memset(mMappedIndexData, 0, size);
static int gl_buffer_idx = 0;
mGLIndices = ++gl_buffer_idx;
}
@@ -607,7 +705,7 @@ void LLVertexBuffer::destroyGLBuffer()
}
mGLBuffer = 0;
- unbind();
+ //unbind();
}
void LLVertexBuffer::destroyGLIndices()
@@ -623,7 +721,7 @@ void LLVertexBuffer::destroyGLIndices()
{
llerrs << "Vertex buffer destroyed while mapped." << llendl;
}
- releaseIndices();
+ releaseIndices();
}
else
{
@@ -636,7 +734,7 @@ void LLVertexBuffer::destroyGLIndices()
}
mGLIndices = 0;
- unbind();
+ //unbind();
}
void LLVertexBuffer::updateNumVerts(S32 nverts)
@@ -652,7 +750,7 @@ void LLVertexBuffer::updateNumVerts(S32 nverts)
}
mRequestedNumVerts = nverts;
-
+
if (!mDynamicSize)
{
mNumVerts = nverts;
@@ -667,7 +765,7 @@ void LLVertexBuffer::updateNumVerts(S32 nverts)
}
mNumVerts = nverts;
}
-
+ mSize = calcOffsets(mTypeMask, mOffsets, mNumVerts);
}
void LLVertexBuffer::updateNumIndices(S32 nindices)
@@ -698,6 +796,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);
@@ -736,9 +840,6 @@ void LLVertexBuffer::resizeBuffer(S32 newnverts, S32 newnindices)
{
sAllocatedBytes -= getSize() + getIndicesSize();
- S32 oldsize = getSize();
- S32 old_index_size = getIndicesSize();
-
updateNumVerts(newnverts);
updateNumIndices(newnindices);
@@ -755,26 +856,10 @@ void LLVertexBuffer::resizeBuffer(S32 newnverts, S32 newnindices)
}
else
{
- //delete old buffer, keep GL buffer for now
if (!useVBOs())
{
- U8* old = mMappedData;
+ FREE_MEM(sPrivatePoolp, mMappedData);
mMappedData = (U8*)ALLOCATE_MEM(sPrivatePoolp, newsize);
- if (old)
- {
- memcpy(mMappedData, old, llmin(newsize, oldsize));
- if (newsize > oldsize)
- {
- memset(mMappedData+oldsize, 0, newsize-oldsize);
- }
-
- FREE_MEM(sPrivatePoolp, old);
- }
- else
- {
- memset(mMappedData, 0, newsize);
- mEmpty = TRUE;
- }
}
mResized = TRUE;
}
@@ -794,24 +879,8 @@ void LLVertexBuffer::resizeBuffer(S32 newnverts, S32 newnindices)
{
if (!useVBOs())
{
- //delete old buffer, keep GL buffer for now
- U8* old = mMappedIndexData;
+ FREE_MEM(sPrivatePoolp, mMappedIndexData) ;
mMappedIndexData = (U8*)ALLOCATE_MEM(sPrivatePoolp, 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);
- }
- FREE_MEM(sPrivatePoolp, old);
- }
- else
- {
- memset(mMappedIndexData, 0, new_index_size);
- mEmpty = TRUE;
- }
}
mResized = TRUE;
}
@@ -863,9 +932,7 @@ void LLVertexBuffer::allocateClientVertexBuffer()
{
if(!mMappedData)
{
- U32 size = getSize() ;
- mMappedData = (U8*)ALLOCATE_MEM(sPrivatePoolp, size);
- memset(mMappedData, 0, size);
+ mMappedData = (U8*)ALLOCATE_MEM(sPrivatePoolp, getSize());
}
}
@@ -873,14 +940,30 @@ void LLVertexBuffer::allocateClientIndexBuffer()
{
if(!mMappedIndexData)
{
- U32 size = getIndicesSize();
- mMappedIndexData = (U8*)ALLOCATE_MEM(sPrivatePoolp, 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)
@@ -892,8 +975,45 @@ U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 access)
llerrs << "LLVertexBuffer::mapVertexBuffer() called on unallocated buffer." << llendl;
}
- if (!mVertexLocked && useVBOs())
+ if (useVBOs())
{
+
+ if (sDisableVBOMapping || gGLManager.mHasMapBufferRange)
+ {
+ 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);
@@ -902,54 +1022,92 @@ U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 access)
if(sDisableVBOMapping)
{
+ map_range = false;
allocateClientVertexBuffer() ;
}
else
{
- mMappedData = (U8*) glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
+ U8* src = NULL;
+#ifdef GL_ARB_map_buffer_range
+ if (gGLManager.mHasMapBufferRange)
+ {
+ if (map_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);
+ }
+ else
+ {
+ src = (U8*) glMapBufferRange(GL_ARRAY_BUFFER_ARB, 0, mSize, GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT);
+ }
+ }
+ else
+#else
+ llassert_always(!gGLManager.mHasMapBufferRange);
+#endif
+ {
+ map_range = false;
+ src = (U8*) glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
+ }
+
+ mMappedData = LL_NEXT_ALIGNED_ADDRESS<U8>(src);
+ mAlignedOffset = mMappedData - src;
+
+ stop_glerror();
}
- stop_glerror();
- }
-
- if (!mMappedData)
- {
- log_glerror();
+
+ if (!mMappedData)
+ {
+ log_glerror();
//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 ;
- //--------------------
+ 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;
+ }
- GLint buff;
- glGetIntegerv(GL_ARRAY_BUFFER_BINDING_ARB, &buff);
- if ((GLuint)buff != mGLBuffer)
+
+ 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++;
}
- sMappedCount++;
+ }
+ else
+ {
+ map_range = false;
}
- return mMappedData;
+ if (map_range && !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)
@@ -961,8 +1119,41 @@ U8* LLVertexBuffer::mapIndexBuffer(S32 access)
llerrs << "LLVertexBuffer::mapIndexBuffer() called on unallocated buffer." << llendl;
}
- if (!mIndexLocked && useVBOs())
+ if (useVBOs())
{
+ if (sDisableVBOMapping || gGLManager.mHasMapBufferRange)
+ {
+ 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);
@@ -972,13 +1163,39 @@ U8* LLVertexBuffer::mapIndexBuffer(S32 access)
if(sDisableVBOMapping)
{
+ map_range = false;
allocateClientIndexBuffer() ;
}
else
{
- mMappedIndexData = (U8*) glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
+ U8* src = NULL;
+#ifdef GL_ARB_map_buffer_range
+ if (gGLManager.mHasMapBufferRange)
+ {
+ if (map_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);
+ }
+ else
+ {
+ src = (U8*) glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER_ARB, 0, sizeof(U16)*mNumIndices, GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT);
+ }
+ }
+ else
+#else
+ llassert_always(!gGLManager.mHasMapBufferRange);
+#endif
+ {
+ map_range = false;
+ src = (U8*) glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
+ }
+
+ mMappedIndexData = src; //LL_NEXT_ALIGNED_ADDRESS<U8>(src);
+ mAlignedIndexOffset = mMappedIndexData - src;
+ stop_glerror();
}
- stop_glerror();
}
if (!mMappedIndexData)
@@ -1005,31 +1222,81 @@ U8* LLVertexBuffer::mapIndexBuffer(S32 access)
sMappedCount++;
}
+ else
+ {
+ map_range = false;
+ }
- return mMappedIndexData ;
+ if (map_range && !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
{
+#ifdef GL_ARB_map_buffer_range
+ if (gGLManager.mHasMapBufferRange)
+ {
+ 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;
+ glFlushMappedBufferRange(GL_ARRAY_BUFFER_ARB, offset, length);
+ stop_glerror();
+ }
+
+ mMappedVertexRegions.clear();
+ }
+ }
+#else
+ llassert_always(!gGLManager.mHasMapBufferRange);
+#endif
stop_glerror();
glUnmapBufferARB(GL_ARRAY_BUFFER_ARB);
stop_glerror();
@@ -1040,17 +1307,53 @@ 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
{
+#ifdef GL_ARB_map_buffer_range
+ if (gGLManager.mHasMapBufferRange)
+ {
+ 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;
+ glFlushMappedBufferRange(GL_ELEMENT_ARRAY_BUFFER_ARB, offset, length);
+ stop_glerror();
+ }
+
+ mMappedIndexRegions.clear();
+ }
+ }
+#else
+ llassert_always(!gGLManager.mHasMapBufferRange);
+#endif
stop_glerror();
glUnmapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB);
stop_glerror();
@@ -1070,7 +1373,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 +1392,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 +1432,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 +1672,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 +1681,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 a4b0d5558e..cc6468880b 100644
--- a/indra/llrender/llvertexbuffer.h
+++ b/indra/llrender/llvertexbuffer.h
@@ -56,42 +56,77 @@ 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();
}
};
//============================================================================
-// 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 +138,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 +157,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 +189,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 +205,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 +223,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 +267,8 @@ 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;
-
- 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
+ std::vector<MappedRegion> mMappedVertexRegions;
+ std::vector<MappedRegion> mMappedIndexRegions;
private:
static LLPrivateMemoryPool* sPrivatePoolp ;
@@ -251,12 +283,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;