summaryrefslogtreecommitdiff
path: root/indra/llrender/llgl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llrender/llgl.cpp')
-rw-r--r--indra/llrender/llgl.cpp1726
1 files changed, 1726 insertions, 0 deletions
diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp
new file mode 100644
index 0000000000..8c63122cb8
--- /dev/null
+++ b/indra/llrender/llgl.cpp
@@ -0,0 +1,1726 @@
+/**
+ * @file llgl.cpp
+ * @brief LLGL implementation
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2007, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlife.com/developers/opensource/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlife.com/developers/opensource/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+// This file sets some global GL parameters, and implements some
+// useful functions for GL operations.
+
+#define GLH_EXT_SINGLE_FILE
+
+#include "linden_common.h"
+
+#include "boost/tokenizer.hpp"
+
+#include "llsys.h"
+
+#include "llgl.h"
+#include "llrender.h"
+
+#include "llerror.h"
+#include "llquaternion.h"
+#include "llmath.h"
+#include "m4math.h"
+#include "llstring.h"
+
+#include "llglheaders.h"
+
+#ifdef _DEBUG
+//#define GL_STATE_VERIFY
+#endif
+
+BOOL gDebugGL = FALSE;
+BOOL gClothRipple = FALSE;
+BOOL gNoRender = FALSE;
+LLMatrix4 gGLObliqueProjectionInverse;
+
+LLGLNamePool::pool_list_t LLGLNamePool::sInstances;
+
+#if (LL_WINDOWS || LL_LINUX) && !LL_MESA_HEADLESS
+// ATI prototypes
+// vertex blending prototypes
+PFNGLWEIGHTPOINTERARBPROC glWeightPointerARB = NULL;
+PFNGLVERTEXBLENDARBPROC glVertexBlendARB = NULL;
+PFNGLWEIGHTFVARBPROC glWeightfvARB = NULL;
+
+// Vertex buffer object prototypes
+PFNGLBINDBUFFERARBPROC glBindBufferARB = NULL;
+PFNGLDELETEBUFFERSARBPROC glDeleteBuffersARB = NULL;
+PFNGLGENBUFFERSARBPROC glGenBuffersARB = NULL;
+PFNGLISBUFFERARBPROC glIsBufferARB = NULL;
+PFNGLBUFFERDATAARBPROC glBufferDataARB = NULL;
+PFNGLBUFFERSUBDATAARBPROC glBufferSubDataARB = NULL;
+PFNGLGETBUFFERSUBDATAARBPROC glGetBufferSubDataARB = NULL;
+PFNGLMAPBUFFERARBPROC glMapBufferARB = NULL;
+PFNGLUNMAPBUFFERARBPROC glUnmapBufferARB = NULL;
+PFNGLGETBUFFERPARAMETERIVARBPROC glGetBufferParameterivARB = NULL;
+PFNGLGETBUFFERPOINTERVARBPROC glGetBufferPointervARB = NULL;
+
+// vertex object prototypes
+PFNGLNEWOBJECTBUFFERATIPROC glNewObjectBufferATI = NULL;
+PFNGLISOBJECTBUFFERATIPROC glIsObjectBufferATI = NULL;
+PFNGLUPDATEOBJECTBUFFERATIPROC glUpdateObjectBufferATI = NULL;
+PFNGLGETOBJECTBUFFERFVATIPROC glGetObjectBufferfvATI = NULL;
+PFNGLGETOBJECTBUFFERIVATIPROC glGetObjectBufferivATI = NULL;
+PFNGLFREEOBJECTBUFFERATIPROC glFreeObjectBufferATI = NULL;
+PFNGLARRAYOBJECTATIPROC glArrayObjectATI = NULL;
+PFNGLVERTEXATTRIBARRAYOBJECTATIPROC glVertexAttribArrayObjectATI = NULL;
+PFNGLGETARRAYOBJECTFVATIPROC glGetArrayObjectfvATI = NULL;
+PFNGLGETARRAYOBJECTIVATIPROC glGetArrayObjectivATI = NULL;
+PFNGLVARIANTARRAYOBJECTATIPROC glVariantObjectArrayATI = NULL;
+PFNGLGETVARIANTARRAYOBJECTFVATIPROC glGetVariantArrayObjectfvATI = NULL;
+PFNGLGETVARIANTARRAYOBJECTIVATIPROC glGetVariantArrayObjectivATI = NULL;
+
+// GL_ARB_occlusion_query
+PFNGLGENQUERIESARBPROC glGenQueriesARB = NULL;
+PFNGLDELETEQUERIESARBPROC glDeleteQueriesARB = NULL;
+PFNGLISQUERYARBPROC glIsQueryARB = NULL;
+PFNGLBEGINQUERYARBPROC glBeginQueryARB = NULL;
+PFNGLENDQUERYARBPROC glEndQueryARB = NULL;
+PFNGLGETQUERYIVARBPROC glGetQueryivARB = NULL;
+PFNGLGETQUERYOBJECTIVARBPROC glGetQueryObjectivARB = NULL;
+PFNGLGETQUERYOBJECTUIVARBPROC glGetQueryObjectuivARB = NULL;
+
+// GL_ARB_point_parameters
+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;
+
+//shader object prototypes
+PFNGLDELETEOBJECTARBPROC glDeleteObjectARB = NULL;
+PFNGLGETHANDLEARBPROC glGetHandleARB = NULL;
+PFNGLDETACHOBJECTARBPROC glDetachObjectARB = NULL;
+PFNGLCREATESHADEROBJECTARBPROC glCreateShaderObjectARB = NULL;
+PFNGLSHADERSOURCEARBPROC glShaderSourceARB = NULL;
+PFNGLCOMPILESHADERARBPROC glCompileShaderARB = NULL;
+PFNGLCREATEPROGRAMOBJECTARBPROC glCreateProgramObjectARB = NULL;
+PFNGLATTACHOBJECTARBPROC glAttachObjectARB = NULL;
+PFNGLLINKPROGRAMARBPROC glLinkProgramARB = NULL;
+PFNGLUSEPROGRAMOBJECTARBPROC glUseProgramObjectARB = NULL;
+PFNGLVALIDATEPROGRAMARBPROC glValidateProgramARB = NULL;
+PFNGLUNIFORM1FARBPROC glUniform1fARB = NULL;
+PFNGLUNIFORM2FARBPROC glUniform2fARB = NULL;
+PFNGLUNIFORM3FARBPROC glUniform3fARB = NULL;
+PFNGLUNIFORM4FARBPROC glUniform4fARB = NULL;
+PFNGLUNIFORM1IARBPROC glUniform1iARB = NULL;
+PFNGLUNIFORM2IARBPROC glUniform2iARB = NULL;
+PFNGLUNIFORM3IARBPROC glUniform3iARB = NULL;
+PFNGLUNIFORM4IARBPROC glUniform4iARB = NULL;
+PFNGLUNIFORM1FVARBPROC glUniform1fvARB = NULL;
+PFNGLUNIFORM2FVARBPROC glUniform2fvARB = NULL;
+PFNGLUNIFORM3FVARBPROC glUniform3fvARB = NULL;
+PFNGLUNIFORM4FVARBPROC glUniform4fvARB = NULL;
+PFNGLUNIFORM1IVARBPROC glUniform1ivARB = NULL;
+PFNGLUNIFORM2IVARBPROC glUniform2ivARB = NULL;
+PFNGLUNIFORM3IVARBPROC glUniform3ivARB = NULL;
+PFNGLUNIFORM4IVARBPROC glUniform4ivARB = NULL;
+PFNGLUNIFORMMATRIX2FVARBPROC glUniformMatrix2fvARB = NULL;
+PFNGLUNIFORMMATRIX3FVARBPROC glUniformMatrix3fvARB = NULL;
+PFNGLUNIFORMMATRIX4FVARBPROC glUniformMatrix4fvARB = NULL;
+PFNGLGETOBJECTPARAMETERFVARBPROC glGetObjectParameterfvARB = NULL;
+PFNGLGETOBJECTPARAMETERIVARBPROC glGetObjectParameterivARB = NULL;
+PFNGLGETINFOLOGARBPROC glGetInfoLogARB = NULL;
+PFNGLGETATTACHEDOBJECTSARBPROC glGetAttachedObjectsARB = NULL;
+PFNGLGETUNIFORMLOCATIONARBPROC glGetUniformLocationARB = NULL;
+PFNGLGETACTIVEUNIFORMARBPROC glGetActiveUniformARB = NULL;
+PFNGLGETUNIFORMFVARBPROC glGetUniformfvARB = NULL;
+PFNGLGETUNIFORMIVARBPROC glGetUniformivARB = NULL;
+PFNGLGETSHADERSOURCEARBPROC glGetShaderSourceARB = NULL;
+
+// vertex shader prototypes
+#if LL_LINUX
+PFNGLVERTEXATTRIB1DARBPROC glVertexAttrib1dARB = NULL;
+PFNGLVERTEXATTRIB1DVARBPROC glVertexAttrib1dvARB = NULL;
+PFNGLVERTEXATTRIB1FARBPROC glVertexAttrib1fARB = NULL;
+PFNGLVERTEXATTRIB1FVARBPROC glVertexAttrib1fvARB = NULL;
+PFNGLVERTEXATTRIB1SARBPROC glVertexAttrib1sARB = NULL;
+PFNGLVERTEXATTRIB1SVARBPROC glVertexAttrib1svARB = NULL;
+PFNGLVERTEXATTRIB2DARBPROC glVertexAttrib2dARB = NULL;
+PFNGLVERTEXATTRIB2DVARBPROC glVertexAttrib2dvARB = NULL;
+PFNGLVERTEXATTRIB2FARBPROC glVertexAttrib2fARB = NULL;
+PFNGLVERTEXATTRIB2FVARBPROC glVertexAttrib2fvARB = NULL;
+PFNGLVERTEXATTRIB2SARBPROC glVertexAttrib2sARB = NULL;
+PFNGLVERTEXATTRIB2SVARBPROC glVertexAttrib2svARB = NULL;
+PFNGLVERTEXATTRIB3DARBPROC glVertexAttrib3dARB = NULL;
+PFNGLVERTEXATTRIB3DVARBPROC glVertexAttrib3dvARB = NULL;
+PFNGLVERTEXATTRIB3FARBPROC glVertexAttrib3fARB = NULL;
+PFNGLVERTEXATTRIB3FVARBPROC glVertexAttrib3fvARB = NULL;
+PFNGLVERTEXATTRIB3SARBPROC glVertexAttrib3sARB = NULL;
+PFNGLVERTEXATTRIB3SVARBPROC glVertexAttrib3svARB = NULL;
+#endif // LL_LINUX
+PFNGLVERTEXATTRIB4NBVARBPROC glVertexAttrib4nbvARB = NULL;
+PFNGLVERTEXATTRIB4NIVARBPROC glVertexAttrib4nivARB = NULL;
+PFNGLVERTEXATTRIB4NSVARBPROC glVertexAttrib4nsvARB = NULL;
+PFNGLVERTEXATTRIB4NUBARBPROC glVertexAttrib4nubARB = NULL;
+PFNGLVERTEXATTRIB4NUBVARBPROC glVertexAttrib4nubvARB = NULL;
+PFNGLVERTEXATTRIB4NUIVARBPROC glVertexAttrib4nuivARB = NULL;
+PFNGLVERTEXATTRIB4NUSVARBPROC glVertexAttrib4nusvARB = NULL;
+#if LL_LINUX
+PFNGLVERTEXATTRIB4BVARBPROC glVertexAttrib4bvARB = NULL;
+PFNGLVERTEXATTRIB4DARBPROC glVertexAttrib4dARB = NULL;
+PFNGLVERTEXATTRIB4DVARBPROC glVertexAttrib4dvARB = NULL;
+PFNGLVERTEXATTRIB4FARBPROC glVertexAttrib4fARB = NULL;
+PFNGLVERTEXATTRIB4FVARBPROC glVertexAttrib4fvARB = NULL;
+PFNGLVERTEXATTRIB4IVARBPROC glVertexAttrib4ivARB = NULL;
+PFNGLVERTEXATTRIB4SARBPROC glVertexAttrib4sARB = NULL;
+PFNGLVERTEXATTRIB4SVARBPROC glVertexAttrib4svARB = NULL;
+PFNGLVERTEXATTRIB4UBVARBPROC glVertexAttrib4ubvARB = NULL;
+PFNGLVERTEXATTRIB4UIVARBPROC glVertexAttrib4uivARB = NULL;
+PFNGLVERTEXATTRIB4USVARBPROC glVertexAttrib4usvARB = NULL;
+PFNGLVERTEXATTRIBPOINTERARBPROC glVertexAttribPointerARB = NULL;
+PFNGLENABLEVERTEXATTRIBARRAYARBPROC glEnableVertexAttribArrayARB = NULL;
+PFNGLDISABLEVERTEXATTRIBARRAYARBPROC glDisableVertexAttribArrayARB = NULL;
+PFNGLPROGRAMSTRINGARBPROC glProgramStringARB = NULL;
+PFNGLBINDPROGRAMARBPROC glBindProgramARB = NULL;
+PFNGLDELETEPROGRAMSARBPROC glDeleteProgramsARB = NULL;
+PFNGLGENPROGRAMSARBPROC glGenProgramsARB = NULL;
+PFNGLPROGRAMENVPARAMETER4DARBPROC glProgramEnvParameter4dARB = NULL;
+PFNGLPROGRAMENVPARAMETER4DVARBPROC glProgramEnvParameter4dvARB = NULL;
+PFNGLPROGRAMENVPARAMETER4FARBPROC glProgramEnvParameter4fARB = NULL;
+PFNGLPROGRAMENVPARAMETER4FVARBPROC glProgramEnvParameter4fvARB = NULL;
+PFNGLPROGRAMLOCALPARAMETER4DARBPROC glProgramLocalParameter4dARB = NULL;
+PFNGLPROGRAMLOCALPARAMETER4DVARBPROC glProgramLocalParameter4dvARB = NULL;
+PFNGLPROGRAMLOCALPARAMETER4FARBPROC glProgramLocalParameter4fARB = NULL;
+PFNGLPROGRAMLOCALPARAMETER4FVARBPROC glProgramLocalParameter4fvARB = NULL;
+PFNGLGETPROGRAMENVPARAMETERDVARBPROC glGetProgramEnvParameterdvARB = NULL;
+PFNGLGETPROGRAMENVPARAMETERFVARBPROC glGetProgramEnvParameterfvARB = NULL;
+PFNGLGETPROGRAMLOCALPARAMETERDVARBPROC glGetProgramLocalParameterdvARB = NULL;
+PFNGLGETPROGRAMLOCALPARAMETERFVARBPROC glGetProgramLocalParameterfvARB = NULL;
+PFNGLGETPROGRAMIVARBPROC glGetProgramivARB = NULL;
+PFNGLGETPROGRAMSTRINGARBPROC glGetProgramStringARB = NULL;
+PFNGLGETVERTEXATTRIBDVARBPROC glGetVertexAttribdvARB = NULL;
+PFNGLGETVERTEXATTRIBFVARBPROC glGetVertexAttribfvARB = NULL;
+PFNGLGETVERTEXATTRIBIVARBPROC glGetVertexAttribivARB = NULL;
+PFNGLGETVERTEXATTRIBPOINTERVARBPROC glGetVertexAttribPointervARB = NULL;
+PFNGLISPROGRAMARBPROC glIsProgramARB = NULL;
+#endif // LL_LINUX
+PFNGLBINDATTRIBLOCATIONARBPROC glBindAttribLocationARB = NULL;
+PFNGLGETACTIVEATTRIBARBPROC glGetActiveAttribARB = NULL;
+PFNGLGETATTRIBLOCATIONARBPROC glGetAttribLocationARB = NULL;
+
+#if LL_WINDOWS
+PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT = NULL;
+#endif
+
+#if LL_LINUX
+PFNGLCOLORTABLEEXTPROC glColorTableEXT = NULL;
+#endif // LL_LINUX
+
+#endif
+
+LLGLManager gGLManager;
+
+LLGLManager::LLGLManager() :
+ mInited(FALSE),
+ mIsDisabled(FALSE),
+
+ mHasMultitexture(FALSE),
+ mNumTextureUnits(1),
+ mHasMipMapGeneration(FALSE),
+ mHasPalettedTextures(FALSE),
+ mHasCompressedTextures(FALSE),
+ mHasFramebufferObject(FALSE),
+
+ mHasVertexBufferObject(FALSE),
+ mHasPBuffer(FALSE),
+ mHasShaderObjects(FALSE),
+ mHasVertexShader(FALSE),
+ mHasFragmentShader(FALSE),
+ mHasOcclusionQuery(FALSE),
+ mHasPointParameters(FALSE),
+
+ mHasAnisotropic(FALSE),
+ mHasARBEnvCombine(FALSE),
+ mHasCubeMap(FALSE),
+
+ mIsATI(FALSE),
+ mIsNVIDIA(FALSE),
+ mIsIntel(FALSE),
+ mIsGF2or4MX(FALSE),
+ mIsGF3(FALSE),
+ mIsGFFX(FALSE),
+ mATIOffsetVerticalLines(FALSE),
+
+ mHasRequirements(TRUE),
+
+ mHasSeparateSpecularColor(FALSE),
+
+ mDriverVersionMajor(1),
+ mDriverVersionMinor(0),
+ mDriverVersionRelease(0),
+ mGLVersion(1.0f),
+
+ mVRAM(0),
+ mGLMaxVertexRange(0),
+ mGLMaxIndexRange(0)
+{
+}
+
+//---------------------------------------------------------------------
+// Global initialization for GL
+//---------------------------------------------------------------------
+void LLGLManager::initWGL()
+{
+ mHasPBuffer = FALSE;
+#if LL_WINDOWS && !LL_MESA_HEADLESS
+ if (!glh_init_extensions("WGL_ARB_pixel_format"))
+ {
+ LL_WARNS("RenderInit") << "No ARB pixel format extensions" << LL_ENDL;
+ }
+
+ if (ExtensionExists("WGL_EXT_swap_control", gGLHExts.mSysExts))
+ {
+ GLH_EXT_NAME(wglSwapIntervalEXT) = (PFNWGLSWAPINTERVALEXTPROC)GLH_EXT_GET_PROC_ADDRESS("wglSwapIntervalEXT");
+ }
+
+ if( !glh_init_extensions("WGL_ARB_pbuffer") )
+ {
+ LL_WARNS("RenderInit") << "No ARB WGL PBuffer extensions" << LL_ENDL;
+ }
+
+ if( !glh_init_extensions("WGL_ARB_render_texture") )
+ {
+ LL_WARNS("RenderInit") << "No ARB WGL render texture extensions" << LL_ENDL;
+ }
+
+ mHasPBuffer = ExtensionExists("WGL_ARB_pbuffer", gGLHExts.mSysExts) &&
+ ExtensionExists("WGL_ARB_render_texture", gGLHExts.mSysExts) &&
+ ExtensionExists("WGL_ARB_pixel_format", gGLHExts.mSysExts);
+#endif
+}
+
+// return false if unable (or unwilling due to old drivers) to init GL
+bool LLGLManager::initGL()
+{
+ if (mInited)
+ {
+ LL_ERRS("RenderInit") << "Calling init on LLGLManager after already initialized!" << LL_ENDL;
+ }
+
+ GLint alpha_bits;
+ glGetIntegerv( GL_ALPHA_BITS, &alpha_bits );
+ if( 8 != alpha_bits )
+ {
+ LL_WARNS("RenderInit") << "Frame buffer has less than 8 bits of alpha. Avatar texture compositing will fail." << LL_ENDL;
+ }
+
+ // Extract video card strings and convert to upper case to
+ // work around driver-to-driver variation in capitalization.
+ mGLVendor = std::string((const char *)glGetString(GL_VENDOR));
+ LLStringUtil::toUpper(mGLVendor);
+
+ mGLRenderer = std::string((const char *)glGetString(GL_RENDERER));
+ LLStringUtil::toUpper(mGLRenderer);
+
+ parse_gl_version( &mDriverVersionMajor,
+ &mDriverVersionMinor,
+ &mDriverVersionRelease,
+ &mDriverVersionVendorString );
+
+ mGLVersion = mDriverVersionMajor + mDriverVersionMinor * .1f;
+
+ // Trailing space necessary to keep "nVidia Corpor_ati_on" cards
+ // from being recognized as ATI.
+ if (mGLVendor.substr(0,4) == "ATI ")
+ {
+ mGLVendorShort = "ATI";
+ BOOL mobile = FALSE;
+ if (mGLRenderer.find("MOBILITY") != std::string::npos)
+ {
+ mobile = TRUE;
+ }
+ mIsATI = TRUE;
+
+#if LL_WINDOWS && !LL_MESA_HEADLESS
+ if (mDriverVersionRelease < 3842)
+ {
+ mATIOffsetVerticalLines = TRUE;
+ }
+#endif // LL_WINDOWS
+ }
+ else if (mGLVendor.find("NVIDIA ") != std::string::npos)
+ {
+ mGLVendorShort = "NVIDIA";
+ mIsNVIDIA = TRUE;
+ if ( mGLRenderer.find("GEFORCE4 MX") != std::string::npos
+ || mGLRenderer.find("GEFORCE2") != std::string::npos
+ || mGLRenderer.find("GEFORCE 2") != std::string::npos
+ || mGLRenderer.find("GEFORCE4 460 GO") != std::string::npos
+ || mGLRenderer.find("GEFORCE4 440 GO") != std::string::npos
+ || mGLRenderer.find("GEFORCE4 420 GO") != std::string::npos)
+ {
+ mIsGF2or4MX = TRUE;
+ }
+ else if (mGLRenderer.find("GEFORCE FX") != std::string::npos
+ || mGLRenderer.find("QUADRO FX") != std::string::npos
+ || mGLRenderer.find("NV34") != std::string::npos)
+ {
+ mIsGFFX = TRUE;
+ }
+ else if(mGLRenderer.find("GEFORCE3") != std::string::npos)
+ {
+ mIsGF3 = TRUE;
+ }
+
+ }
+ else if (mGLVendor.find("INTEL") != std::string::npos
+#if LL_LINUX
+ // The Mesa-based drivers put this in the Renderer string,
+ // not the Vendor string.
+ || mGLRenderer.find("INTEL") != std::string::npos
+#endif //LL_LINUX
+ )
+ {
+ mGLVendorShort = "INTEL";
+ mIsIntel = TRUE;
+ }
+ else
+ {
+ mGLVendorShort = "MISC";
+ }
+
+ // This is called here because it depends on the setting of mIsGF2or4MX, and sets up mHasMultitexture.
+ initExtensions();
+
+ if (mHasMultitexture)
+ {
+ GLint num_tex_units;
+ glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &num_tex_units);
+ mNumTextureUnits = llmin(num_tex_units, (GLint)MAX_GL_TEXTURE_UNITS);
+ if (mIsIntel)
+ {
+ mNumTextureUnits = llmin(mNumTextureUnits, 2);
+ }
+ }
+ else
+ {
+ mHasRequirements = FALSE;
+
+ // We don't support cards that don't support the GL_ARB_multitexture extension
+ LL_WARNS("RenderInit") << "GL Drivers do not support GL_ARB_multitexture" << LL_ENDL;
+ return false;
+ }
+
+
+ initGLStates();
+ return true;
+}
+
+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 !LL_MESA_HEADLESS
+ std::string all_exts = ll_safe_string((const char *)gGLHExts.mSysExts);
+ boost::char_separator<char> sep(" ");
+ boost::tokenizer<boost::char_separator<char> > tok(all_exts, sep);
+ for(boost::tokenizer<boost::char_separator<char> >::iterator i = tok.begin(); i != tok.end(); ++i)
+ {
+ info["GLInfo"]["GLExtensions"].append(*i);
+ }
+#endif
+}
+
+std::string LLGLManager::getGLInfoString()
+{
+ std::string info_str;
+ std::string all_exts, line;
+
+ info_str += std::string("GL_VENDOR ") + ll_safe_string((const char *)glGetString(GL_VENDOR)) + std::string("\n");
+ info_str += std::string("GL_RENDERER ") + ll_safe_string((const char *)glGetString(GL_RENDERER)) + std::string("\n");
+ info_str += std::string("GL_VERSION ") + ll_safe_string((const char *)glGetString(GL_VERSION)) + std::string("\n");
+
+#if !LL_MESA_HEADLESS
+ all_exts = (const char *)gGLHExts.mSysExts;
+ LLStringUtil::replaceChar(all_exts, ' ', '\n');
+ info_str += std::string("GL_EXTENSIONS:\n") + all_exts + std::string("\n");
+#endif
+
+ return info_str;
+}
+
+void LLGLManager::printGLInfoString()
+{
+ std::string info_str;
+ std::string all_exts, line;
+
+ LL_INFOS("RenderInit") << "GL_VENDOR: " << ((const char *)glGetString(GL_VENDOR)) << LL_ENDL;
+ LL_INFOS("RenderInit") << "GL_RENDERER: " << ((const char *)glGetString(GL_RENDERER)) << LL_ENDL;
+ LL_INFOS("RenderInit") << "GL_VERSION: " << ((const char *)glGetString(GL_VERSION)) << LL_ENDL;
+
+#if !LL_MESA_HEADLESS
+ all_exts = std::string(gGLHExts.mSysExts);
+ LLStringUtil::replaceChar(all_exts, ' ', '\n');
+ LL_DEBUGS("RenderInit") << "GL_EXTENSIONS:\n" << all_exts << LL_ENDL;
+#endif
+}
+
+std::string LLGLManager::getRawGLString()
+{
+ std::string gl_string;
+ gl_string = ll_safe_string((char*)glGetString(GL_VENDOR)) + " " + ll_safe_string((char*)glGetString(GL_RENDERER));
+ return gl_string;
+}
+
+void LLGLManager::shutdownGL()
+{
+ if (mInited)
+ {
+ glFinish();
+ stop_glerror();
+ mInited = FALSE;
+ }
+}
+
+// these are used to turn software blending on. They appear in the Debug/Avatar menu
+// presence of vertex skinning/blending or vertex programs will set these to FALSE by default.
+
+extern LLCPUInfo gSysCPU;
+
+void LLGLManager::initExtensions()
+{
+#if LL_MESA_HEADLESS
+# if GL_ARB_multitexture
+ mHasMultitexture = TRUE;
+# else
+ mHasMultitexture = FALSE;
+# endif
+# if GL_ARB_texture_env_combine
+ mHasARBEnvCombine = TRUE;
+# else
+ mHasARBEnvCombine = FALSE;
+# endif
+# if GL_ARB_texture_compression
+ mHasCompressedTextures = TRUE;
+# else
+ mHasCompressedTextures = FALSE;
+# endif
+# if GL_ARB_vertex_buffer_object
+ mHasVertexBufferObject = TRUE;
+# else
+ mHasVertexBufferObject = FALSE;
+# endif
+# if GL_EXT_framebuffer_object
+ mHasFramebufferObject = TRUE;
+# else
+ mHasFramebufferObject = FALSE;
+# endif
+ mHasMipMapGeneration = FALSE;
+ mHasPalettedTextures = FALSE;
+ mHasSeparateSpecularColor = FALSE;
+ mHasAnisotropic = FALSE;
+ mHasCubeMap = FALSE;
+ mHasOcclusionQuery = FALSE;
+ mHasPointParameters = FALSE;
+ mHasShaderObjects = FALSE;
+ mHasVertexShader = FALSE;
+ mHasFragmentShader = FALSE;
+#else // LL_MESA_HEADLESS
+ mHasMultitexture = glh_init_extensions("GL_ARB_multitexture");
+ mHasMipMapGeneration = glh_init_extensions("GL_SGIS_generate_mipmap");
+ mHasPalettedTextures = glh_init_extension("GL_EXT_paletted_texture");
+ mHasSeparateSpecularColor = glh_init_extensions("GL_EXT_separate_specular_color");
+ mHasAnisotropic = glh_init_extensions("GL_EXT_texture_filter_anisotropic");
+ glh_init_extensions("GL_ARB_texture_cube_map");
+ mHasCubeMap = ExtensionExists("GL_ARB_texture_cube_map", gGLHExts.mSysExts);
+ 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);
+ mHasVertexBufferObject = ExtensionExists("GL_ARB_vertex_buffer_object", 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);
+#if !LL_DARWIN
+ mHasPointParameters = !mIsATI && ExtensionExists("GL_ARB_point_parameters", gGLHExts.mSysExts);
+#endif
+ mHasShaderObjects = ExtensionExists("GL_ARB_shader_objects", gGLHExts.mSysExts) && ExtensionExists("GL_ARB_shading_language_100", gGLHExts.mSysExts);
+ mHasVertexShader = ExtensionExists("GL_ARB_vertex_program", gGLHExts.mSysExts) && ExtensionExists("GL_ARB_vertex_shader", gGLHExts.mSysExts)
+ && ExtensionExists("GL_ARB_shading_language_100", gGLHExts.mSysExts);
+ mHasFragmentShader = ExtensionExists("GL_ARB_fragment_shader", gGLHExts.mSysExts) && ExtensionExists("GL_ARB_shading_language_100", gGLHExts.mSysExts);
+#endif
+
+#if LL_LINUX
+ // Our extension support for the Linux Client is very young with some
+ // potential driver gotchas, so offer a semi-secret way to turn it off.
+ if (getenv("LL_GL_NOEXT")) /* Flawfinder: ignore */
+ {
+ //mHasMultitexture = FALSE; // NEEDED!
+ mHasARBEnvCombine = FALSE;
+ mHasCompressedTextures = FALSE;
+ mHasVertexBufferObject = FALSE;
+ mHasFramebufferObject = FALSE;
+ mHasMipMapGeneration = FALSE;
+ mHasPalettedTextures = FALSE;
+ mHasSeparateSpecularColor = FALSE;
+ mHasAnisotropic = FALSE;
+ mHasCubeMap = FALSE;
+ mHasOcclusionQuery = FALSE;
+ mHasPointParameters = FALSE;
+ mHasShaderObjects = FALSE;
+ mHasVertexShader = FALSE;
+ mHasFragmentShader = FALSE;
+ LL_WARNS("RenderInit") << "GL extension support DISABLED via LL_GL_NOEXT" << LL_ENDL;
+ }
+ else if (getenv("LL_GL_BASICEXT")) /* Flawfinder: ignore */
+ {
+ // This switch attempts to turn off all support for exotic
+ // extensions which I believe correspond to fatal driver
+ // bug reports. This should be the default until we get a
+ // proper blacklist/whitelist on Linux.
+ mHasMipMapGeneration = FALSE;
+ mHasPalettedTextures = FALSE;
+ mHasAnisotropic = FALSE;
+ //mHasCubeMap = FALSE; // apparently fatal on Intel 915 & similar
+ //mHasOcclusionQuery = FALSE; // source of many ATI system hangs
+ mHasShaderObjects = FALSE;
+ mHasVertexShader = FALSE;
+ mHasFragmentShader = FALSE;
+ LL_WARNS("RenderInit") << "GL extension support forced to SIMPLE level via LL_GL_BASICEXT" << LL_ENDL;
+ }
+ if (getenv("LL_GL_BLACKLIST")) /* Flawfinder: ignore */
+ {
+ // This lets advanced troubleshooters disable specific
+ // GL extensions to isolate problems with their hardware.
+ // SL-28126
+ const char *const blacklist = getenv("LL_GL_BLACKLIST"); /* Flawfinder: ignore */
+ LL_WARNS("RenderInit") << "GL extension support partially disabled via LL_GL_BLACKLIST: " << blacklist << LL_ENDL;
+ if (strchr(blacklist,'a')) mHasARBEnvCombine = FALSE;
+ if (strchr(blacklist,'b')) mHasCompressedTextures = FALSE;
+ if (strchr(blacklist,'c')) mHasVertexBufferObject = FALSE;
+ if (strchr(blacklist,'d')) mHasMipMapGeneration = FALSE;//S
+ if (strchr(blacklist,'e')) mHasPalettedTextures = FALSE;//S
+// if (strchr(blacklist,'f')) mHasNVVertexArrayRange = FALSE;//S
+// if (strchr(blacklist,'g')) mHasNVFence = FALSE;//S
+ if (strchr(blacklist,'h')) mHasSeparateSpecularColor = FALSE;
+ if (strchr(blacklist,'i')) mHasAnisotropic = FALSE;//S
+ if (strchr(blacklist,'j')) mHasCubeMap = FALSE;//S
+// if (strchr(blacklist,'k')) mHasATIVAO = FALSE;//S
+ if (strchr(blacklist,'l')) mHasOcclusionQuery = FALSE;
+ if (strchr(blacklist,'m')) mHasShaderObjects = FALSE;//S
+ if (strchr(blacklist,'n')) mHasVertexShader = FALSE;//S
+ if (strchr(blacklist,'o')) mHasFragmentShader = FALSE;//S
+ if (strchr(blacklist,'p')) mHasPointParameters = FALSE;//S
+ if (strchr(blacklist,'q')) mHasFramebufferObject = FALSE;//S
+ }
+#endif // LL_LINUX
+
+#if LL_DARWIN || LL_LINUX
+ // MBW -- 12/4/2003 -- Using paletted textures causes a bunch of avatar rendering problems on the Mac.
+ // Not sure if this is due to driver problems or incorrect use of the extension, but I'm disabling it for now.
+ // Tofu - 2006-10-03 -- Same problem on Linux.
+ mHasPalettedTextures = false;
+#endif
+
+ if (!mHasMultitexture)
+ {
+ LL_INFOS("RenderInit") << "Couldn't initialize multitexturing" << LL_ENDL;
+ }
+ if (!mHasMipMapGeneration)
+ {
+ LL_INFOS("RenderInit") << "Couldn't initialize mipmap generation" << LL_ENDL;
+ }
+ if (!mHasARBEnvCombine)
+ {
+ LL_INFOS("RenderInit") << "Couldn't initialize GL_ARB_texture_env_combine" << LL_ENDL;
+ }
+ if (!mHasPalettedTextures)
+ {
+ LL_INFOS("RenderInit") << "Couldn't initialize GL_EXT_paletted_texture" << LL_ENDL;
+ }
+ if (!mHasSeparateSpecularColor)
+ {
+ LL_INFOS("RenderInit") << "Couldn't initialize separate specular color" << LL_ENDL;
+ }
+ if (!mHasAnisotropic)
+ {
+ LL_INFOS("RenderInit") << "Couldn't initialize anisotropic filtering" << LL_ENDL;
+ }
+ if (!mHasCompressedTextures)
+ {
+ LL_INFOS("RenderInit") << "Couldn't initialize GL_ARB_texture_compression" << LL_ENDL;
+ }
+ if (!mHasOcclusionQuery)
+ {
+ LL_INFOS("RenderInit") << "Couldn't initialize GL_ARB_occlusion_query" << LL_ENDL;
+ }
+ if (!mHasPointParameters)
+ {
+ LL_INFOS("RenderInit") << "Couldn't initialize GL_ARB_point_parameters" << LL_ENDL;
+ }
+ if (!mHasShaderObjects)
+ {
+ LL_INFOS("RenderInit") << "Couldn't initialize GL_ARB_shader_objects" << LL_ENDL;
+ }
+ if (!mHasVertexShader)
+ {
+ LL_INFOS("RenderInit") << "Couldn't initialize GL_ARB_vertex_shader" << LL_ENDL;
+ }
+ if (!mHasFragmentShader)
+ {
+ LL_INFOS("RenderInit") << "Couldn't initialize GL_ARB_fragment_shader" << LL_ENDL;
+ }
+
+ // Disable certain things due to known bugs
+ if (mIsIntel && mHasMipMapGeneration)
+ {
+ LL_INFOS("RenderInit") << "Disabling mip-map generation for Intel GPUs" << LL_ENDL;
+ mHasMipMapGeneration = FALSE;
+ }
+ if (mIsATI && mHasMipMapGeneration)
+ {
+ LL_INFOS("RenderInit") << "Disabling mip-map generation for ATI GPUs (performance opt)" << LL_ENDL;
+ mHasMipMapGeneration = FALSE;
+ }
+
+ // Misc
+ glGetIntegerv(GL_MAX_ELEMENTS_VERTICES, (GLint*) &mGLMaxVertexRange);
+ glGetIntegerv(GL_MAX_ELEMENTS_INDICES, (GLint*) &mGLMaxIndexRange);
+
+#if (LL_WINDOWS || LL_LINUX) && !LL_MESA_HEADLESS
+ LL_DEBUGS("RenderInit") << "GL Probe: Getting symbols" << LL_ENDL;
+ if (mHasVertexBufferObject)
+ {
+ glBindBufferARB = (PFNGLBINDBUFFERARBPROC)GLH_EXT_GET_PROC_ADDRESS("glBindBufferARB");
+ if (glBindBufferARB)
+ {
+ glDeleteBuffersARB = (PFNGLDELETEBUFFERSARBPROC)GLH_EXT_GET_PROC_ADDRESS("glDeleteBuffersARB");
+ glGenBuffersARB = (PFNGLGENBUFFERSARBPROC)GLH_EXT_GET_PROC_ADDRESS("glGenBuffersARB");
+ glIsBufferARB = (PFNGLISBUFFERARBPROC)GLH_EXT_GET_PROC_ADDRESS("glIsBufferARB");
+ glBufferDataARB = (PFNGLBUFFERDATAARBPROC)GLH_EXT_GET_PROC_ADDRESS("glBufferDataARB");
+ glBufferSubDataARB = (PFNGLBUFFERSUBDATAARBPROC)GLH_EXT_GET_PROC_ADDRESS("glBufferSubDataARB");
+ glGetBufferSubDataARB = (PFNGLGETBUFFERSUBDATAARBPROC)GLH_EXT_GET_PROC_ADDRESS("glGetBufferSubDataARB");
+ glMapBufferARB = (PFNGLMAPBUFFERARBPROC)GLH_EXT_GET_PROC_ADDRESS("glMapBufferARB");
+ glUnmapBufferARB = (PFNGLUNMAPBUFFERARBPROC)GLH_EXT_GET_PROC_ADDRESS("glUnmapBufferARB");
+ glGetBufferParameterivARB = (PFNGLGETBUFFERPARAMETERIVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glGetBufferParameterivARB");
+ glGetBufferPointervARB = (PFNGLGETBUFFERPOINTERVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glGetBufferPointervARB");
+ }
+ else
+ {
+ mHasVertexBufferObject = FALSE;
+ }
+ }
+ if (mHasFramebufferObject)
+ {
+ 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 !LL_LINUX
+ // This is expected to be a static symbol on Linux GL implementations
+ glDrawRangeElements = (PFNGLDRAWRANGEELEMENTSPROC)GLH_EXT_GET_PROC_ADDRESS("glDrawRangeElements");
+ if (!glDrawRangeElements)
+ {
+ mGLMaxVertexRange = 0;
+ mGLMaxIndexRange = 0;
+ }
+#endif // !LL_LINUX
+#if LL_LINUX
+ // On Linux we need to get glColorTableEXT dynamically.
+ if (mHasPalettedTextures)
+ {
+ glColorTableEXT = (PFNGLCOLORTABLEEXTPROC)GLH_EXT_GET_PROC_ADDRESS("glColorTableEXT");
+ }
+#endif // LL_LINUX
+ if (mHasOcclusionQuery)
+ {
+ glGenQueriesARB = (PFNGLGENQUERIESARBPROC)GLH_EXT_GET_PROC_ADDRESS("glGenQueriesARB");
+ glDeleteQueriesARB = (PFNGLDELETEQUERIESARBPROC)GLH_EXT_GET_PROC_ADDRESS("glDeleteQueriesARB");
+ glIsQueryARB = (PFNGLISQUERYARBPROC)GLH_EXT_GET_PROC_ADDRESS("glIsQueryARB");
+ glBeginQueryARB = (PFNGLBEGINQUERYARBPROC)GLH_EXT_GET_PROC_ADDRESS("glBeginQueryARB");
+ glEndQueryARB = (PFNGLENDQUERYARBPROC)GLH_EXT_GET_PROC_ADDRESS("glEndQueryARB");
+ glGetQueryivARB = (PFNGLGETQUERYIVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glGetQueryivARB");
+ glGetQueryObjectivARB = (PFNGLGETQUERYOBJECTIVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glGetQueryObjectivARB");
+ glGetQueryObjectuivARB = (PFNGLGETQUERYOBJECTUIVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glGetQueryObjectuivARB");
+ }
+ if (mHasPointParameters)
+ {
+ glPointParameterfARB = (PFNGLPOINTPARAMETERFARBPROC)GLH_EXT_GET_PROC_ADDRESS("glPointParameterfARB");
+ glPointParameterfvARB = (PFNGLPOINTPARAMETERFVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glPointParameterfvARB");
+ }
+ if (mHasShaderObjects)
+ {
+ glDeleteObjectARB = (PFNGLDELETEOBJECTARBPROC) GLH_EXT_GET_PROC_ADDRESS("glDeleteObjectARB");
+ glGetHandleARB = (PFNGLGETHANDLEARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetHandleARB");
+ glDetachObjectARB = (PFNGLDETACHOBJECTARBPROC) GLH_EXT_GET_PROC_ADDRESS("glDetachObjectARB");
+ glCreateShaderObjectARB = (PFNGLCREATESHADEROBJECTARBPROC) GLH_EXT_GET_PROC_ADDRESS("glCreateShaderObjectARB");
+ glShaderSourceARB = (PFNGLSHADERSOURCEARBPROC) GLH_EXT_GET_PROC_ADDRESS("glShaderSourceARB");
+ glCompileShaderARB = (PFNGLCOMPILESHADERARBPROC) GLH_EXT_GET_PROC_ADDRESS("glCompileShaderARB");
+ glCreateProgramObjectARB = (PFNGLCREATEPROGRAMOBJECTARBPROC) GLH_EXT_GET_PROC_ADDRESS("glCreateProgramObjectARB");
+ glAttachObjectARB = (PFNGLATTACHOBJECTARBPROC) GLH_EXT_GET_PROC_ADDRESS("glAttachObjectARB");
+ glLinkProgramARB = (PFNGLLINKPROGRAMARBPROC) GLH_EXT_GET_PROC_ADDRESS("glLinkProgramARB");
+ glUseProgramObjectARB = (PFNGLUSEPROGRAMOBJECTARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUseProgramObjectARB");
+ glValidateProgramARB = (PFNGLVALIDATEPROGRAMARBPROC) GLH_EXT_GET_PROC_ADDRESS("glValidateProgramARB");
+ glUniform1fARB = (PFNGLUNIFORM1FARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform1fARB");
+ glUniform2fARB = (PFNGLUNIFORM2FARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform2fARB");
+ glUniform3fARB = (PFNGLUNIFORM3FARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform3fARB");
+ glUniform4fARB = (PFNGLUNIFORM4FARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform4fARB");
+ glUniform1iARB = (PFNGLUNIFORM1IARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform1iARB");
+ glUniform2iARB = (PFNGLUNIFORM2IARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform2iARB");
+ glUniform3iARB = (PFNGLUNIFORM3IARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform3iARB");
+ glUniform4iARB = (PFNGLUNIFORM4IARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform4iARB");
+ glUniform1fvARB = (PFNGLUNIFORM1FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform1fvARB");
+ glUniform2fvARB = (PFNGLUNIFORM2FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform2fvARB");
+ glUniform3fvARB = (PFNGLUNIFORM3FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform3fvARB");
+ glUniform4fvARB = (PFNGLUNIFORM4FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform4fvARB");
+ glUniform1ivARB = (PFNGLUNIFORM1IVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform1ivARB");
+ glUniform2ivARB = (PFNGLUNIFORM2IVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform2ivARB");
+ glUniform3ivARB = (PFNGLUNIFORM3IVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform3ivARB");
+ glUniform4ivARB = (PFNGLUNIFORM4IVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniform4ivARB");
+ glUniformMatrix2fvARB = (PFNGLUNIFORMMATRIX2FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniformMatrix2fvARB");
+ glUniformMatrix3fvARB = (PFNGLUNIFORMMATRIX3FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniformMatrix3fvARB");
+ glUniformMatrix4fvARB = (PFNGLUNIFORMMATRIX4FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glUniformMatrix4fvARB");
+ glGetObjectParameterfvARB = (PFNGLGETOBJECTPARAMETERFVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetObjectParameterfvARB");
+ glGetObjectParameterivARB = (PFNGLGETOBJECTPARAMETERIVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetObjectParameterivARB");
+ glGetInfoLogARB = (PFNGLGETINFOLOGARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetInfoLogARB");
+ glGetAttachedObjectsARB = (PFNGLGETATTACHEDOBJECTSARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetAttachedObjectsARB");
+ glGetUniformLocationARB = (PFNGLGETUNIFORMLOCATIONARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetUniformLocationARB");
+ glGetActiveUniformARB = (PFNGLGETACTIVEUNIFORMARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetActiveUniformARB");
+ glGetUniformfvARB = (PFNGLGETUNIFORMFVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetUniformfvARB");
+ glGetUniformivARB = (PFNGLGETUNIFORMIVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetUniformivARB");
+ glGetShaderSourceARB = (PFNGLGETSHADERSOURCEARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetShaderSourceARB");
+ }
+ if (mHasVertexShader)
+ {
+ glGetAttribLocationARB = (PFNGLGETATTRIBLOCATIONARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetAttribLocationARB");
+ glBindAttribLocationARB = (PFNGLBINDATTRIBLOCATIONARBPROC) GLH_EXT_GET_PROC_ADDRESS("glBindAttribLocationARB");
+ glGetActiveAttribARB = (PFNGLGETACTIVEATTRIBARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetActiveAttribARB");
+ glVertexAttrib1dARB = (PFNGLVERTEXATTRIB1DARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib1dARB");
+ glVertexAttrib1dvARB = (PFNGLVERTEXATTRIB1DVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib1dvARB");
+ glVertexAttrib1fARB = (PFNGLVERTEXATTRIB1FARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib1fARB");
+ glVertexAttrib1fvARB = (PFNGLVERTEXATTRIB1FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib1fvARB");
+ glVertexAttrib1sARB = (PFNGLVERTEXATTRIB1SARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib1sARB");
+ glVertexAttrib1svARB = (PFNGLVERTEXATTRIB1SVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib1svARB");
+ glVertexAttrib2dARB = (PFNGLVERTEXATTRIB2DARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib2dARB");
+ glVertexAttrib2dvARB = (PFNGLVERTEXATTRIB2DVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib2dvARB");
+ glVertexAttrib2fARB = (PFNGLVERTEXATTRIB2FARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib2fARB");
+ glVertexAttrib2fvARB = (PFNGLVERTEXATTRIB2FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib2fvARB");
+ glVertexAttrib2sARB = (PFNGLVERTEXATTRIB2SARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib2sARB");
+ glVertexAttrib2svARB = (PFNGLVERTEXATTRIB2SVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib2svARB");
+ glVertexAttrib3dARB = (PFNGLVERTEXATTRIB3DARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib3dARB");
+ glVertexAttrib3dvARB = (PFNGLVERTEXATTRIB3DVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib3dvARB");
+ glVertexAttrib3fARB = (PFNGLVERTEXATTRIB3FARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib3fARB");
+ glVertexAttrib3fvARB = (PFNGLVERTEXATTRIB3FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib3fvARB");
+ glVertexAttrib3sARB = (PFNGLVERTEXATTRIB3SARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib3sARB");
+ glVertexAttrib3svARB = (PFNGLVERTEXATTRIB3SVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib3svARB");
+ glVertexAttrib4nbvARB = (PFNGLVERTEXATTRIB4NBVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4nbvARB");
+ glVertexAttrib4nivARB = (PFNGLVERTEXATTRIB4NIVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4nivARB");
+ glVertexAttrib4nsvARB = (PFNGLVERTEXATTRIB4NSVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4nsvARB");
+ glVertexAttrib4nubARB = (PFNGLVERTEXATTRIB4NUBARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4nubARB");
+ glVertexAttrib4nubvARB = (PFNGLVERTEXATTRIB4NUBVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4nubvARB");
+ glVertexAttrib4nuivARB = (PFNGLVERTEXATTRIB4NUIVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4nuivARB");
+ glVertexAttrib4nusvARB = (PFNGLVERTEXATTRIB4NUSVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4nusvARB");
+ glVertexAttrib4bvARB = (PFNGLVERTEXATTRIB4BVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4bvARB");
+ glVertexAttrib4dARB = (PFNGLVERTEXATTRIB4DARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4dARB");
+ glVertexAttrib4dvARB = (PFNGLVERTEXATTRIB4DVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4dvARB");
+ glVertexAttrib4fARB = (PFNGLVERTEXATTRIB4FARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4fARB");
+ glVertexAttrib4fvARB = (PFNGLVERTEXATTRIB4FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4fvARB");
+ glVertexAttrib4ivARB = (PFNGLVERTEXATTRIB4IVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4ivARB");
+ glVertexAttrib4sARB = (PFNGLVERTEXATTRIB4SARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4sARB");
+ glVertexAttrib4svARB = (PFNGLVERTEXATTRIB4SVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4svARB");
+ glVertexAttrib4ubvARB = (PFNGLVERTEXATTRIB4UBVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4ubvARB");
+ glVertexAttrib4uivARB = (PFNGLVERTEXATTRIB4UIVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4uivARB");
+ glVertexAttrib4usvARB = (PFNGLVERTEXATTRIB4USVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttrib4usvARB");
+ glVertexAttribPointerARB = (PFNGLVERTEXATTRIBPOINTERARBPROC) GLH_EXT_GET_PROC_ADDRESS("glVertexAttribPointerARB");
+ glEnableVertexAttribArrayARB = (PFNGLENABLEVERTEXATTRIBARRAYARBPROC) GLH_EXT_GET_PROC_ADDRESS("glEnableVertexAttribArrayARB");
+ glDisableVertexAttribArrayARB = (PFNGLDISABLEVERTEXATTRIBARRAYARBPROC) GLH_EXT_GET_PROC_ADDRESS("glDisableVertexAttribArrayARB");
+ glProgramStringARB = (PFNGLPROGRAMSTRINGARBPROC) GLH_EXT_GET_PROC_ADDRESS("glProgramStringARB");
+ glBindProgramARB = (PFNGLBINDPROGRAMARBPROC) GLH_EXT_GET_PROC_ADDRESS("glBindProgramARB");
+ glDeleteProgramsARB = (PFNGLDELETEPROGRAMSARBPROC) GLH_EXT_GET_PROC_ADDRESS("glDeleteProgramsARB");
+ glGenProgramsARB = (PFNGLGENPROGRAMSARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGenProgramsARB");
+ glProgramEnvParameter4dARB = (PFNGLPROGRAMENVPARAMETER4DARBPROC) GLH_EXT_GET_PROC_ADDRESS("glProgramEnvParameter4dARB");
+ glProgramEnvParameter4dvARB = (PFNGLPROGRAMENVPARAMETER4DVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glProgramEnvParameter4dvARB");
+ glProgramEnvParameter4fARB = (PFNGLPROGRAMENVPARAMETER4FARBPROC) GLH_EXT_GET_PROC_ADDRESS("glProgramEnvParameter4fARB");
+ glProgramEnvParameter4fvARB = (PFNGLPROGRAMENVPARAMETER4FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glProgramEnvParameter4fvARB");
+ glProgramLocalParameter4dARB = (PFNGLPROGRAMLOCALPARAMETER4DARBPROC) GLH_EXT_GET_PROC_ADDRESS("glProgramLocalParameter4dARB");
+ glProgramLocalParameter4dvARB = (PFNGLPROGRAMLOCALPARAMETER4DVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glProgramLocalParameter4dvARB");
+ glProgramLocalParameter4fARB = (PFNGLPROGRAMLOCALPARAMETER4FARBPROC) GLH_EXT_GET_PROC_ADDRESS("glProgramLocalParameter4fARB");
+ glProgramLocalParameter4fvARB = (PFNGLPROGRAMLOCALPARAMETER4FVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glProgramLocalParameter4fvARB");
+ glGetProgramEnvParameterdvARB = (PFNGLGETPROGRAMENVPARAMETERDVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetProgramEnvParameterdvARB");
+ glGetProgramEnvParameterfvARB = (PFNGLGETPROGRAMENVPARAMETERFVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetProgramEnvParameterfvARB");
+ glGetProgramLocalParameterdvARB = (PFNGLGETPROGRAMLOCALPARAMETERDVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetProgramLocalParameterdvARB");
+ glGetProgramLocalParameterfvARB = (PFNGLGETPROGRAMLOCALPARAMETERFVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetProgramLocalParameterfvARB");
+ glGetProgramivARB = (PFNGLGETPROGRAMIVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetProgramivARB");
+ glGetProgramStringARB = (PFNGLGETPROGRAMSTRINGARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetProgramStringARB");
+ glGetVertexAttribdvARB = (PFNGLGETVERTEXATTRIBDVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetVertexAttribdvARB");
+ glGetVertexAttribfvARB = (PFNGLGETVERTEXATTRIBFVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetVertexAttribfvARB");
+ glGetVertexAttribivARB = (PFNGLGETVERTEXATTRIBIVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetVertexAttribivARB");
+ glGetVertexAttribPointervARB = (PFNGLGETVERTEXATTRIBPOINTERVARBPROC) GLH_EXT_GET_PROC_ADDRESS("glgetVertexAttribPointervARB");
+ glIsProgramARB = (PFNGLISPROGRAMARBPROC) GLH_EXT_GET_PROC_ADDRESS("glIsProgramARB");
+ }
+ LL_DEBUGS("RenderInit") << "GL Probe: Got symbols" << LL_ENDL;
+#endif
+
+ mInited = TRUE;
+}
+
+void rotate_quat(LLQuaternion& rotation)
+{
+ F32 angle_radians, x, y, z;
+ rotation.getAngleAxis(&angle_radians, &x, &y, &z);
+ glRotatef(angle_radians * RAD_TO_DEG, x, y, z);
+}
+
+void flush_glerror()
+{
+ glGetError();
+}
+
+void assert_glerror()
+{
+ if (gNoRender || !gDebugGL)
+ {
+ return;
+ }
+ if (!gGLManager.mInited)
+ {
+ LL_ERRS("RenderInit") << "GL not initialized" << LL_ENDL;
+ }
+ // Create or update texture to be used with this data
+ GLenum error;
+ error = glGetError();
+ BOOL quit = FALSE;
+ while (error)
+ {
+ quit = TRUE;
+#ifndef LL_LINUX // *FIX: ! This should be an error for linux as well.
+ GLubyte const * gl_error_msg = gluErrorString(error);
+ if (NULL != gl_error_msg)
+ {
+ LL_WARNS("RenderState") << "GL Error:" << gl_error_msg << LL_ENDL;
+ }
+ else
+ {
+ // gluErrorString returns NULL for some extensions' error codes.
+ // you'll probably have to grep for the number in glext.h.
+ LL_WARNS("RenderState") << "GL Error: UNKNOWN 0x" << std::hex << error << LL_ENDL;
+ }
+ error = glGetError();
+#endif
+ }
+
+ if (quit)
+ {
+ llerrs << "One or more unhandled GL errors." << llendl;
+ }
+}
+
+void clear_glerror()
+{
+ // Create or update texture to be used with this data
+ GLenum error;
+ error = glGetError();
+}
+
+///////////////////////////////////////////////////////////////
+//
+// LLGLState
+//
+
+// Static members
+std::map<LLGLenum, LLGLboolean> LLGLState::sStateMap;
+
+GLboolean LLGLDepthTest::sDepthEnabled = GL_FALSE; // OpenGL default
+GLenum LLGLDepthTest::sDepthFunc = GL_LESS; // OpenGL default
+GLboolean LLGLDepthTest::sWriteEnabled = GL_TRUE; // OpenGL default
+
+//static
+void LLGLState::initClass()
+{
+ sStateMap[GL_DITHER] = GL_TRUE;
+ sStateMap[GL_TEXTURE_2D] = GL_TRUE;
+}
+
+//static
+void LLGLState::restoreGL()
+{
+ sStateMap.clear();
+ initClass();
+}
+
+//static
+// Really shouldn't be needed, but seems we sometimes do.
+void LLGLState::resetTextureStates()
+{
+ gGL.flush();
+ GLint maxTextureUnits;
+
+ glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &maxTextureUnits);
+ for (S32 j = maxTextureUnits-1; j >=0; j--)
+ {
+ gGL.getTexUnit(j)->activate();
+ glClientActiveTextureARB(GL_TEXTURE0_ARB+j);
+ j == 0 ? glEnable(GL_TEXTURE_2D) : glDisable(GL_TEXTURE_2D);
+ }
+}
+
+void LLGLState::dumpStates()
+{
+ LL_INFOS("RenderState") << "GL States:" << LL_ENDL;
+ for (std::map<LLGLenum, LLGLboolean>::iterator iter = sStateMap.begin();
+ iter != sStateMap.end(); ++iter)
+ {
+ LL_INFOS("RenderState") << llformat(" 0x%04x : %s",(S32)iter->first,iter->second?"TRUE":"FALSE") << LL_ENDL;
+ }
+}
+
+void LLGLState::checkStates()
+{
+ if (!gDebugGL)
+ {
+ return;
+ }
+
+ stop_glerror();
+
+ GLint activeTexture;
+ glGetIntegerv(GL_ACTIVE_TEXTURE_ARB, &activeTexture);
+
+ if (activeTexture != GL_TEXTURE0_ARB)
+ {
+ LL_GL_ERRS << "Texture channel corrupted. " << LL_ENDL;
+ }
+
+ GLint src;
+ GLint dst;
+ glGetIntegerv(GL_BLEND_SRC, &src);
+ glGetIntegerv(GL_BLEND_DST, &dst);
+
+ if (src != GL_SRC_ALPHA || dst != GL_ONE_MINUS_SRC_ALPHA)
+ {
+ LL_GL_ERRS << "Blend function corrupted: " << std::hex << src << " " << std::hex << dst << LL_ENDL;
+ }
+
+ for (std::map<LLGLenum, LLGLboolean>::iterator iter = sStateMap.begin();
+ iter != sStateMap.end(); ++iter)
+ {
+ LLGLenum state = iter->first;
+ LLGLboolean cur_state = iter->second;
+ LLGLboolean gl_state = glIsEnabled(state);
+ if(cur_state != gl_state)
+ {
+ dumpStates();
+ LL_GL_ERRS << llformat("LLGLState error. State: 0x%04x",state) << LL_ENDL;
+ }
+ }
+
+ stop_glerror();
+}
+
+void LLGLState::checkTextureChannels()
+{
+ if (!gDebugGL)
+ {
+ return;
+ }
+
+ GLint activeTexture;
+ glGetIntegerv(GL_ACTIVE_TEXTURE_ARB, &activeTexture);
+
+ BOOL error = FALSE;
+
+ if (activeTexture != GL_TEXTURE0_ARB)
+ {
+ error = TRUE;
+ LL_WARNS("RenderState") << "Active texture channel corrupted. " << LL_ENDL;
+ }
+ else if (!glIsEnabled(GL_TEXTURE_2D))
+ {
+ error = TRUE;
+ LL_WARNS("RenderState") << "GL_TEXTURE_2D not enabled on texture channel 0." << LL_ENDL;
+ }
+ else
+ {
+ GLint tex_env_mode = 0;
+
+ glGetTexEnviv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &tex_env_mode);
+ if (tex_env_mode != GL_MODULATE)
+ {
+ error = TRUE;
+ LL_WARNS("RenderState") << "GL_TEXTURE_ENV_MODE invalid: " << std::hex << tex_env_mode << LL_ENDL;
+ }
+ }
+
+ GLint maxTextureUnits;
+ glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &maxTextureUnits);
+
+ static const char* label[] =
+ {
+ "GL_TEXTURE_2D",
+ "GL_TEXTURE_COORD_ARRAY",
+ "GL_TEXTURE_1D",
+ "GL_TEXTURE_CUBE_MAP_ARB",
+ "GL_TEXTURE_GEN_S",
+ "GL_TEXTURE_GEN_T",
+ "GL_TEXTURE_GEN_Q",
+ "GL_TEXTURE_GEN_R"
+ };
+
+ static GLint value[] =
+ {
+ GL_TEXTURE_2D,
+ GL_TEXTURE_COORD_ARRAY,
+ GL_TEXTURE_1D,
+ GL_TEXTURE_CUBE_MAP_ARB,
+ GL_TEXTURE_GEN_S,
+ GL_TEXTURE_GEN_T,
+ GL_TEXTURE_GEN_Q,
+ GL_TEXTURE_GEN_R
+ };
+
+ GLint stackDepth = 0;
+ LLMatrix4 identity;
+ LLMatrix4 matrix;
+
+ for (GLint i = 0; i < maxTextureUnits; i++)
+ {
+ gGL.getTexUnit(i)->activate();
+ glClientActiveTextureARB(GL_TEXTURE0_ARB+i);
+
+ glGetIntegerv(GL_TEXTURE_STACK_DEPTH, &stackDepth);
+
+ if (stackDepth != 1)
+ {
+ error = TRUE;
+ LL_WARNS("RenderState") << "Texture matrix stack corrupted." << LL_ENDL;
+ }
+
+ glGetFloatv(GL_TEXTURE_MATRIX, (GLfloat*) matrix.mMatrix);
+
+ if (matrix != identity)
+ {
+ error = TRUE;
+ LL_WARNS("RenderState") << "Texture matrix in channel " << i << " corrupt." << LL_ENDL;
+ }
+
+ for (S32 j = (i == 0 ? 1 : 0); j < 8; j++)
+ {
+ if (glIsEnabled(value[j]))
+ {
+ error = TRUE;
+ LL_WARNS("RenderState") << "Texture channel " << i << " still has " << label[j] << " enabled." << LL_ENDL;
+ }
+ }
+ }
+
+ gGL.getTexUnit(0)->activate();
+ glClientActiveTextureARB(GL_TEXTURE0_ARB);
+
+ if (error)
+ {
+ LL_GL_ERRS << "GL texture state corruption detected." << LL_ENDL;
+ }
+}
+
+void LLGLState::checkClientArrays(U32 data_mask)
+{
+ if (!gDebugGL)
+ {
+ return;
+ }
+
+ stop_glerror();
+ BOOL error = FALSE;
+
+ GLint active_texture;
+ glGetIntegerv(GL_CLIENT_ACTIVE_TEXTURE_ARB, &active_texture);
+
+ if (active_texture != GL_TEXTURE0_ARB)
+ {
+ llwarns << "Client active texture corrupted: " << active_texture << llendl;
+ error = TRUE;
+ }
+
+ glGetIntegerv(GL_ACTIVE_TEXTURE_ARB, &active_texture);
+ if (active_texture != GL_TEXTURE0_ARB)
+ {
+ llwarns << "Active texture corrupted: " << active_texture << llendl;
+ error = TRUE;
+ }
+
+ static const char* label[] =
+ {
+ "GL_VERTEX_ARRAY",
+ "GL_NORMAL_ARRAY",
+ "GL_COLOR_ARRAY",
+ "GL_TEXTURE_COORD_ARRAY"
+ };
+
+ static GLint value[] =
+ {
+ GL_VERTEX_ARRAY,
+ GL_NORMAL_ARRAY,
+ GL_COLOR_ARRAY,
+ GL_TEXTURE_COORD_ARRAY
+ };
+
+ U32 mask[] =
+ { //copied from llvertexbuffer.h
+ 0x0001, //MAP_VERTEX,
+ 0x0002, //MAP_NORMAL,
+ 0x0010, //MAP_COLOR,
+ 0x0004, //MAP_TEXCOORD
+ };
+
+
+ for (S32 j = 0; j < 4; j++)
+ {
+ if (glIsEnabled(value[j]))
+ {
+ if (!(mask[j] & data_mask))
+ {
+ error = TRUE;
+ LL_WARNS("RenderState") << "GL still has " << label[j] << " enabled." << LL_ENDL;
+ }
+ }
+ else
+ {
+ if (mask[j] & data_mask)
+ {
+ error = TRUE;
+ LL_WARNS("RenderState") << "GL does not have " << label[j] << " enabled." << LL_ENDL;
+ }
+ }
+ }
+
+ glClientActiveTextureARB(GL_TEXTURE1_ARB);
+ gGL.getTexUnit(1)->activate();
+ if (glIsEnabled(GL_TEXTURE_COORD_ARRAY))
+ {
+ if (!(data_mask & 0x0008))
+ {
+ error = TRUE;
+ LL_WARNS("RenderState") << "GL still has GL_TEXTURE_COORD_ARRAY enabled on channel 1." << LL_ENDL;
+ }
+ }
+ else
+ {
+ if (data_mask & 0x0008)
+ {
+ error = TRUE;
+ LL_WARNS("RenderState") << "GL does not have GL_TEXTURE_COORD_ARRAY enabled on channel 1." << LL_ENDL;
+ }
+ }
+
+ if (glIsEnabled(GL_TEXTURE_2D))
+ {
+ if (!(data_mask & 0x0008))
+ {
+ error = TRUE;
+ LL_WARNS("RenderState") << "GL still has GL_TEXTURE_2D enabled on channel 1." << LL_ENDL;
+ }
+ }
+ else
+ {
+ if (data_mask & 0x0008)
+ {
+ error = TRUE;
+ LL_WARNS("RenderState") << "GL does not have GL_TEXTURE_2D enabled on channel 1." << LL_ENDL;
+ }
+ }
+
+ glClientActiveTextureARB(GL_TEXTURE0_ARB);
+ gGL.getTexUnit(0)->activate();
+
+ if (error)
+ {
+ LL_GL_ERRS << "GL client array corruption detected." << LL_ENDL;
+ }
+}
+
+///////////////////////////////////////////////////////////////////////
+
+LLGLState::LLGLState(LLGLenum state, S32 enabled) :
+ mState(state), mWasEnabled(FALSE), mIsEnabled(FALSE)
+{
+ stop_glerror();
+ if (state)
+ {
+ mWasEnabled = sStateMap[state];
+ llassert(mWasEnabled == glIsEnabled(state));
+ setEnabled(enabled);
+ stop_glerror();
+ }
+}
+
+void LLGLState::setEnabled(S32 enabled)
+{
+ if (!mState)
+ {
+ return;
+ }
+ if (enabled == CURRENT_STATE)
+ {
+ enabled = sStateMap[mState] == GL_TRUE ? TRUE : FALSE;
+ }
+ else if (enabled == TRUE && sStateMap[mState] != GL_TRUE)
+ {
+ gGL.flush();
+ glEnable(mState);
+ sStateMap[mState] = GL_TRUE;
+ }
+ else if (enabled == FALSE && sStateMap[mState] != GL_FALSE)
+ {
+ gGL.flush();
+ glDisable(mState);
+ sStateMap[mState] = GL_FALSE;
+ }
+ mIsEnabled = enabled;
+}
+
+LLGLState::~LLGLState()
+{
+ stop_glerror();
+ if (mState)
+ {
+ if (gDebugGL)
+ {
+ llassert_always(sStateMap[mState] == glIsEnabled(mState));
+ }
+
+ if (mIsEnabled != mWasEnabled)
+ {
+ gGL.flush();
+ if (mWasEnabled)
+ {
+ glEnable(mState);
+ sStateMap[mState] = GL_TRUE;
+ }
+ else
+ {
+ glDisable(mState);
+ sStateMap[mState] = GL_FALSE;
+ }
+ }
+ }
+ stop_glerror();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+void LLGLManager::initGLStates()
+{
+ //gl states moved to classes in llglstates.h
+ LLGLState::initClass();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+void enable_vertex_weighting(const S32 index)
+{
+#if GL_ARB_vertex_program
+ if (index > 0) glEnableVertexAttribArrayARB(index); // vertex weights
+#endif
+}
+
+void disable_vertex_weighting(const S32 index)
+{
+#if GL_ARB_vertex_program
+ if (index > 0) glDisableVertexAttribArrayARB(index); // vertex weights
+#endif
+}
+
+void enable_binormals(const S32 index)
+{
+#if GL_ARB_vertex_program
+ if (index > 0)
+ {
+ glEnableVertexAttribArrayARB(index); // binormals
+ }
+#endif
+}
+
+void disable_binormals(const S32 index)
+{
+#if GL_ARB_vertex_program
+ if (index > 0)
+ {
+ glDisableVertexAttribArrayARB(index); // binormals
+ }
+#endif
+}
+
+
+void enable_cloth_weights(const S32 index)
+{
+#if GL_ARB_vertex_program
+ if (index > 0) glEnableVertexAttribArrayARB(index);
+#endif
+}
+
+void disable_cloth_weights(const S32 index)
+{
+#if GL_ARB_vertex_program
+ if (index > 0) glDisableVertexAttribArrayARB(index);
+#endif
+}
+
+void set_vertex_weights(const S32 index, const U32 stride, const F32 *weights)
+{
+#if GL_ARB_vertex_program
+ if (index > 0) glVertexAttribPointerARB(index, 1, GL_FLOAT, FALSE, stride, weights);
+ stop_glerror();
+#endif
+}
+
+void set_vertex_clothing_weights(const S32 index, const U32 stride, const LLVector4 *weights)
+{
+#if GL_ARB_vertex_program
+ if (index > 0) glVertexAttribPointerARB(index, 4, GL_FLOAT, TRUE, stride, weights);
+ stop_glerror();
+#endif
+}
+
+void set_binormals(const S32 index, const U32 stride,const LLVector3 *binormals)
+{
+#if GL_ARB_vertex_program
+ if (index > 0) glVertexAttribPointerARB(index, 3, GL_FLOAT, FALSE, stride, binormals);
+ stop_glerror();
+#endif
+}
+
+
+void set_palette(U8 *palette_data)
+{
+ if (gGLManager.mHasPalettedTextures)
+ {
+ glColorTableEXT(GL_TEXTURE_2D, GL_RGBA8, 256, GL_RGBA, GL_UNSIGNED_BYTE, palette_data);
+ }
+}
+
+
+void parse_gl_version( S32* major, S32* minor, S32* release, std::string* vendor_specific )
+{
+ // GL_VERSION returns a null-terminated string with the format:
+ // <major>.<minor>[.<release>] [<vendor specific>]
+
+ const char* version = (const char*) glGetString(GL_VERSION);
+ *major = 0;
+ *minor = 0;
+ *release = 0;
+ vendor_specific->assign("");
+
+ if( !version )
+ {
+ return;
+ }
+
+ std::string ver_copy( version );
+ S32 len = (S32)strlen( version ); /* Flawfinder: ignore */
+ S32 i = 0;
+ S32 start;
+ // Find the major version
+ start = i;
+ for( ; i < len; i++ )
+ {
+ if( '.' == version[i] )
+ {
+ break;
+ }
+ }
+ std::string major_str = ver_copy.substr(start,i-start);
+ LLStringUtil::convertToS32(major_str, *major);
+
+ if( '.' == version[i] )
+ {
+ i++;
+ }
+
+ // Find the minor version
+ start = i;
+ for( ; i < len; i++ )
+ {
+ if( ('.' == version[i]) || isspace(version[i]) )
+ {
+ break;
+ }
+ }
+ std::string minor_str = ver_copy.substr(start,i-start);
+ LLStringUtil::convertToS32(minor_str, *minor);
+
+ // Find the release number (optional)
+ if( '.' == version[i] )
+ {
+ i++;
+
+ start = i;
+ for( ; i < len; i++ )
+ {
+ if( isspace(version[i]) )
+ {
+ break;
+ }
+ }
+
+ std::string release_str = ver_copy.substr(start,i-start);
+ LLStringUtil::convertToS32(release_str, *release);
+ }
+
+ // Skip over any white space
+ while( version[i] && isspace( version[i] ) )
+ {
+ i++;
+ }
+
+ // Copy the vendor-specific string (optional)
+ if( version[i] )
+ {
+ vendor_specific->assign( version + i );
+ }
+}
+
+LLGLUserClipPlane::LLGLUserClipPlane(const LLPlane& p, const glh::matrix4f& modelview, const glh::matrix4f& projection)
+{
+ mModelview = modelview;
+ mProjection = projection;
+
+ setPlane(p.mV[0], p.mV[1], p.mV[2], p.mV[3]);
+}
+
+void LLGLUserClipPlane::setPlane(F32 a, F32 b, F32 c, F32 d)
+{
+ glh::matrix4f& P = mProjection;
+ glh::matrix4f& M = mModelview;
+
+ glh::matrix4f invtrans_MVP = (P * M).inverse().transpose();
+ glh::vec4f oplane(a,b,c,d);
+ glh::vec4f cplane;
+ invtrans_MVP.mult_matrix_vec(oplane, cplane);
+
+ cplane /= fabs(cplane[2]); // normalize such that depth is not scaled
+ cplane[3] -= 1;
+
+ if(cplane[2] < 0)
+ cplane *= -1;
+
+ glh::matrix4f suffix;
+ suffix.set_row(2, cplane);
+ glh::matrix4f newP = suffix * P;
+ glMatrixMode(GL_PROJECTION);
+ glPushMatrix();
+ glLoadMatrixf(newP.m);
+ gGLObliqueProjectionInverse = LLMatrix4(newP.inverse().transpose().m);
+ glMatrixMode(GL_MODELVIEW);
+}
+
+LLGLUserClipPlane::~LLGLUserClipPlane()
+{
+ 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()
+{
+ std::sort(mNameList.begin(), mNameList.end(), CompareUsed());
+}
+
+void LLGLNamePool::cleanup()
+{
+ for (name_list_t::iterator iter = mNameList.begin(); iter != mNameList.end(); ++iter)
+ {
+ releaseName(iter->name);
+ }
+
+ mNameList.clear();
+}
+
+GLuint LLGLNamePool::allocate()
+{
+ for (name_list_t::iterator iter = mNameList.begin(); iter != mNameList.end(); ++iter)
+ {
+ if (!iter->used)
+ {
+ iter->used = TRUE;
+ return iter->name;
+ }
+ }
+
+ NameEntry entry;
+ entry.name = allocateName();
+ entry.used = TRUE;
+ mNameList.push_back(entry);
+
+ return entry.name;
+}
+
+void LLGLNamePool::release(GLuint name)
+{
+ for (name_list_t::iterator iter = mNameList.begin(); iter != mNameList.end(); ++iter)
+ {
+ if (iter->name == name)
+ {
+ iter->used = FALSE;
+ return;
+ }
+ }
+}
+
+//static
+void LLGLNamePool::upkeepPools()
+{
+ for (pool_list_t::iterator iter = sInstances.begin(); iter != sInstances.end(); ++iter)
+ {
+ LLGLNamePool* pool = *iter;
+ pool->upkeep();
+ }
+}
+
+//static
+void LLGLNamePool::cleanupPools()
+{
+ for (pool_list_t::iterator iter = sInstances.begin(); iter != sInstances.end(); ++iter)
+ {
+ LLGLNamePool* pool = *iter;
+ pool->cleanup();
+ }
+}
+
+LLGLDepthTest::LLGLDepthTest(GLboolean depth_enabled, GLboolean write_enabled, GLenum depth_func)
+: mPrevDepthEnabled(sDepthEnabled), mPrevDepthFunc(sDepthFunc), mPrevWriteEnabled(sWriteEnabled)
+{
+ if (depth_enabled != sDepthEnabled)
+ {
+ gGL.flush();
+ if (depth_enabled) glEnable(GL_DEPTH_TEST);
+ else glDisable(GL_DEPTH_TEST);
+ sDepthEnabled = depth_enabled;
+ }
+ if (depth_func != sDepthFunc)
+ {
+ gGL.flush();
+ glDepthFunc(depth_func);
+ sDepthFunc = depth_func;
+ }
+ if (write_enabled != sWriteEnabled)
+ {
+ gGL.flush();
+ glDepthMask(write_enabled);
+ sWriteEnabled = write_enabled;
+ }
+}
+
+LLGLDepthTest::~LLGLDepthTest()
+{
+ if (sDepthEnabled != mPrevDepthEnabled )
+ {
+ gGL.flush();
+ if (mPrevDepthEnabled) glEnable(GL_DEPTH_TEST);
+ else glDisable(GL_DEPTH_TEST);
+ sDepthEnabled = mPrevDepthEnabled;
+ }
+ if (sDepthFunc != mPrevDepthFunc)
+ {
+ gGL.flush();
+ glDepthFunc(mPrevDepthFunc);
+ sDepthFunc = mPrevDepthFunc;
+ }
+ if (sWriteEnabled != mPrevWriteEnabled )
+ {
+ gGL.flush();
+ glDepthMask(mPrevWriteEnabled);
+ sWriteEnabled = mPrevWriteEnabled;
+ }
+}
+
+LLGLClampToFarClip::LLGLClampToFarClip(glh::matrix4f P)
+{
+ for (U32 i = 0; i < 4; i++)
+ {
+ P.element(2, i) = P.element(3, i) * 0.99999f;
+ }
+
+ glMatrixMode(GL_PROJECTION);
+ glPushMatrix();
+ glLoadMatrixf(P.m);
+ glMatrixMode(GL_MODELVIEW);
+}
+
+LLGLClampToFarClip::~LLGLClampToFarClip()
+{
+ glMatrixMode(GL_PROJECTION);
+ glPopMatrix();
+ glMatrixMode(GL_MODELVIEW);
+}
+