summaryrefslogtreecommitdiff
path: root/indra
diff options
context:
space:
mode:
authorEric Tulla <tulla@lindenlab.com>2008-06-30 17:57:00 +0000
committerEric Tulla <tulla@lindenlab.com>2008-06-30 17:57:00 +0000
commit939a506569433db7bff96c12200f03b3f85f40de (patch)
treec9f308949400b0a4ce00c82a6a33f2868e31a1d1 /indra
parent1a14cd34a9a4e6f51c445d477aaeeef0322d5853 (diff)
Merging in file-move-merge ( QAR-649 )
Result of "svn merge -r 90669:90786 $tulla/file-move-merge ." Be careful of future merges involving changes to any of these moved files as SVN usually does the wrong thing: newview/llglslshader.* -> llrender/llglslshader.*, llrender/llshadermgr.*, newview/llviewershadermgr.* (gets split into 3 separate files) newview/llpostprocess.* -> llrender/llpostprocess.* newview/llrendersphere.* -> llrender/llrendersphere.* newview/llcubemap.* -> llrender/llcubemap.* llwindow/llgl.* -> llrender/llgl.* llwindow/llglstates.h -> llrender/llglstates.h llwindow/llgltypes.h -> llrender/llgltypes.h llwindow/llglheaders.h -> llrender/llglheaders.h
Diffstat (limited to 'indra')
-rw-r--r--indra/cmake/LLRender.cmake21
-rw-r--r--indra/llrender/CMakeLists.txt34
-rw-r--r--indra/llrender/llcubemap.cpp532
-rw-r--r--indra/llrender/llcubemap.h89
-rw-r--r--indra/llrender/llgl.cpp1726
-rw-r--r--indra/llrender/llgl.h377
-rw-r--r--indra/llrender/llglheaders.h588
-rw-r--r--indra/llrender/llglslshader.cpp823
-rw-r--r--indra/llrender/llglslshader.h139
-rw-r--r--indra/llrender/llglstates.h302
-rw-r--r--indra/llrender/llgltypes.h44
-rw-r--r--indra/llrender/llpostprocess.cpp574
-rw-r--r--indra/llrender/llpostprocess.h268
-rw-r--r--indra/llrender/llrender.cpp6
-rw-r--r--indra/llrender/llrender.h5
-rw-r--r--indra/llrender/llrendersphere.cpp159
-rw-r--r--indra/llrender/llrendersphere.h34
-rw-r--r--indra/llrender/llshadermgr.cpp513
-rw-r--r--indra/llrender/llshadermgr.h75
-rw-r--r--indra/llrender/llvertexbuffer.h1
-rw-r--r--indra/llwindow/CMakeLists.txt18
-rw-r--r--indra/newview/CMakeLists.txt10
-rw-r--r--indra/newview/llappviewer.cpp6
-rw-r--r--indra/newview/lldrawpoolalpha.cpp4
-rw-r--r--indra/newview/lldrawpoolavatar.cpp44
-rw-r--r--indra/newview/lldrawpoolbump.cpp30
-rw-r--r--indra/newview/lldrawpoolground.cpp4
-rw-r--r--indra/newview/lldrawpoolsimple.cpp10
-rw-r--r--indra/newview/lldrawpoolsky.cpp4
-rw-r--r--indra/newview/lldrawpoolterrain.cpp24
-rw-r--r--indra/newview/lldrawpooltree.cpp4
-rw-r--r--indra/newview/lldrawpoolwater.cpp52
-rw-r--r--indra/newview/llhudrender.cpp1
-rw-r--r--indra/newview/llviewercamera.cpp12
-rw-r--r--indra/newview/llviewercamera.h7
-rw-r--r--indra/newview/llviewercontrol.cpp4
-rw-r--r--indra/newview/llviewerdisplay.cpp3
-rw-r--r--indra/newview/llviewerjointmesh.cpp4
-rw-r--r--indra/newview/llviewershadermgr.cpp1094
-rw-r--r--indra/newview/llviewershadermgr.h313
-rw-r--r--indra/newview/llvoavatar.cpp10
-rw-r--r--indra/newview/llvosky.cpp4
-rw-r--r--indra/newview/llwaterparammanager.cpp16
-rw-r--r--indra/newview/llwaterparamset.h2
-rw-r--r--indra/newview/llwlparammanager.cpp16
-rw-r--r--indra/newview/llwlparamset.h2
-rw-r--r--indra/newview/pipeline.cpp26
47 files changed, 7857 insertions, 177 deletions
diff --git a/indra/cmake/LLRender.cmake b/indra/cmake/LLRender.cmake
index 8fda6c1d6a..bbcf4cd57d 100644
--- a/indra/cmake/LLRender.cmake
+++ b/indra/cmake/LLRender.cmake
@@ -6,6 +6,27 @@ set(LLRENDER_INCLUDE_DIRS
${LIBS_OPEN_DIR}/llrender
)
+if (SERVER AND LINUX)
+ set(LLRENDER_LIBRARIES
+ llrenderheadless
+ )
+else (SERVER AND LINUX)
set(LLRENDER_LIBRARIES
llrender
)
+endif (SERVER AND LINUX)
+
+# mapserver requires certain files to be copied so LL_MESA_HEADLESS can be set
+# differently for different object files.
+macro (copy_server_sources _copied_SOURCES)
+ foreach (PREFIX ${_copied_SOURCES})
+ add_custom_command(
+ OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_server.cpp
+ COMMAND ${CMAKE_COMMAND}
+ ARGS -E copy ${CMAKE_CURRENT_SOURCE_DIR}/${PREFIX}.cpp
+ ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_server.cpp
+ DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${PREFIX}.cpp
+ )
+ list(APPEND server_SOURCE_FILES ${PREFIX}_server.cpp)
+ endforeach (PREFIX ${_copied_SOURCES})
+endmacro (copy_server_sources _copied_SOURCES)
diff --git a/indra/llrender/CMakeLists.txt b/indra/llrender/CMakeLists.txt
index 2dba8ef60d..76858d9839 100644
--- a/indra/llrender/CMakeLists.txt
+++ b/indra/llrender/CMakeLists.txt
@@ -20,24 +20,38 @@ include_directories(
)
set(llrender_SOURCE_FILES
+ llcubemap.cpp
llfont.cpp
llfontgl.cpp
llgldbg.cpp
+ llglslshader.cpp
llimagegl.cpp
+ llpostprocess.cpp
llrender.cpp
+ llrendersphere.cpp
llrendertarget.cpp
+ llshadermgr.cpp
llvertexbuffer.cpp
)
set(llrender_HEADER_FILES
CMakeLists.txt
+ llcubemap.h
llfontgl.h
llfont.h
+ llgl.h
llgldbg.h
+ llglheaders.h
+ llglslshader.h
+ llglstates.h
+ llgltypes.h
llimagegl.h
+ llpostprocess.h
llrender.h
+ llrendersphere.h
llrendertarget.h
+ llshadermgr.h
llvertexbuffer.h
)
@@ -46,4 +60,24 @@ set_source_files_properties(${llrender_HEADER_FILES}
list(APPEND llrender_SOURCE_FILES ${llrender_HEADER_FILES})
+if (SERVER AND NOT WINDOWS AND NOT DARWIN)
+ copy_server_sources(
+ llgl
+ )
+
+
+ set_source_files_properties(
+ ${server_SOURCE_FILES}
+ PROPERTIES
+ COMPILE_FLAGS "-DLL_MESA=1 -DLL_MESA_HEADLESS=1"
+ )
+ add_library (llrenderheadless
+ ${llrender_SOURCE_FILES}
+ ${server_SOURCE_FILES}
+ )
+else (SERVER AND NOT WINDOWS AND NOT DARWIN)
+ list(APPEND llrender_SOURCE_FILES
+ llgl.cpp
+ )
+endif (SERVER AND NOT WINDOWS AND NOT DARWIN)
add_library (llrender ${llrender_SOURCE_FILES})
diff --git a/indra/llrender/llcubemap.cpp b/indra/llrender/llcubemap.cpp
new file mode 100644
index 0000000000..f19992eeab
--- /dev/null
+++ b/indra/llrender/llcubemap.cpp
@@ -0,0 +1,532 @@
+/**
+ * @file llcubemap.cpp
+ * @brief LLCubeMap class implementation
+ *
+ * $LicenseInfo:firstyear=2002&license=viewergpl$
+ *
+ * Copyright (c) 2002-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$
+ */
+#include "linden_common.h"
+
+#include "llworkerthread.h"
+
+#include "llcubemap.h"
+
+#include "v4coloru.h"
+#include "v3math.h"
+#include "v3dmath.h"
+#include "m3math.h"
+#include "m4math.h"
+#include "llcamera.h"
+
+#include "llrender.h"
+
+#include "llglheaders.h"
+
+const F32 epsilon = 1e-7f;
+const U16 RESOLUTION = 64;
+
+#if LL_DARWIN
+// mipmap generation on cubemap textures seems to be broken on the Mac for at least some cards.
+// Since the cubemap is small (64x64 per face) and doesn't have any fine detail, turning off mipmaps is a usable workaround.
+const BOOL use_cube_mipmaps = FALSE;
+#else
+const BOOL use_cube_mipmaps = FALSE; //current build works best without cube mipmaps
+#endif
+
+bool LLCubeMap::sUseCubeMaps = true;
+
+LLCubeMap::LLCubeMap()
+ : mTextureStage(0),
+ mTextureCoordStage(0),
+ mMatrixStage(0)
+{
+}
+
+LLCubeMap::~LLCubeMap()
+{
+}
+
+void LLCubeMap::initGL()
+{
+ llassert(gGLManager.mInited);
+
+ if (gGLManager.mHasCubeMap && LLCubeMap::sUseCubeMaps)
+ {
+ mTargets[0] = GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB;
+ mTargets[1] = GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB;
+ mTargets[2] = GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB;
+ mTargets[3] = GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB;
+ mTargets[4] = GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB;
+ mTargets[5] = GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB;
+
+ // Not initialized, do stuff.
+ if (mImages[0].isNull())
+ {
+ GLuint texname = 0;
+
+ glGenTextures(1, &texname);
+
+ for (int i = 0; i < 6; i++)
+ {
+ mImages[i] = new LLImageGL(64, 64, 4, (use_cube_mipmaps? TRUE : FALSE));
+ mImages[i]->setTarget(mTargets[i], GL_TEXTURE_CUBE_MAP_ARB);
+ mRawImages[i] = new LLImageRaw(64, 64, 4);
+ mImages[i]->createGLTexture(0, mRawImages[i], texname);
+
+ glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, texname);
+ mImages[i]->setClampCubemap (TRUE, TRUE, TRUE);
+ stop_glerror();
+ }
+ }
+ disable();
+ }
+ else
+ {
+ llwarns << "Using cube map without extension!" << llendl
+ }
+}
+
+void LLCubeMap::initRawData(const std::vector<LLPointer<LLImageRaw> >& rawimages)
+{
+ bool flip_x[6] = { false, true, false, false, true, false };
+ bool flip_y[6] = { true, true, true, false, true, true };
+ bool transpose[6] = { false, false, false, false, true, true };
+
+ // Yes, I know that this is inefficient! - djs 08/08/02
+ for (int i = 0; i < 6; i++)
+ {
+ const U8 *sd = rawimages[i]->getData();
+ U8 *td = mRawImages[i]->getData();
+
+ S32 offset = 0;
+ S32 sx, sy, so;
+ for (int y = 0; y < 64; y++)
+ {
+ for (int x = 0; x < 64; x++)
+ {
+ sx = x;
+ sy = y;
+ if (flip_y[i])
+ {
+ sy = 63 - y;
+ }
+ if (flip_x[i])
+ {
+ sx = 63 - x;
+ }
+ if (transpose[i])
+ {
+ S32 temp = sx;
+ sx = sy;
+ sy = temp;
+ }
+
+ so = 64*sy + sx;
+ so *= 4;
+ *(td + offset++) = *(sd + so++);
+ *(td + offset++) = *(sd + so++);
+ *(td + offset++) = *(sd + so++);
+ *(td + offset++) = *(sd + so++);
+ }
+ }
+ }
+}
+
+void LLCubeMap::initGLData()
+{
+ for (int i = 0; i < 6; i++)
+ {
+ mImages[i]->setSubImage(mRawImages[i], 0, 0, 64, 64);
+ }
+}
+
+void LLCubeMap::init(const std::vector<LLPointer<LLImageRaw> >& rawimages)
+{
+ if (!gGLManager.mIsDisabled)
+ {
+ initGL();
+ initRawData(rawimages);
+ initGLData();
+ }
+}
+
+GLuint LLCubeMap::getGLName()
+{
+ return mImages[0]->getTexName();
+}
+
+void LLCubeMap::bind()
+{
+ if (gGLManager.mHasCubeMap && LLCubeMap::sUseCubeMaps)
+ {
+ // We assume that if they have cube mapping, they have multitexturing.
+ if (mTextureStage > 0)
+ {
+ gGL.getTexUnit(mTextureStage)->activate();
+ }
+ glEnable(GL_TEXTURE_CUBE_MAP_ARB);
+ glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, mImages[0]->getTexName());
+
+ mImages[0]->setMipFilterNearest (FALSE, FALSE);
+ if (mTextureStage > 0)
+ {
+ gGL.getTexUnit(0)->activate();
+ }
+ }
+ else
+ {
+ llwarns << "Using cube map without extension!" << llendl
+ }
+}
+
+void LLCubeMap::enable(S32 stage)
+{
+ enableTexture(stage);
+ enableTextureCoords(stage);
+}
+
+void LLCubeMap::enableTexture(S32 stage)
+{
+ mTextureStage = stage;
+ if (gGLManager.mHasCubeMap && stage >= 0 && LLCubeMap::sUseCubeMaps)
+ {
+ if (stage > 0)
+ {
+ gGL.getTexUnit(stage)->activate();
+ }
+
+ glEnable(GL_TEXTURE_CUBE_MAP_ARB);
+
+ if (stage > 0)
+ {
+ gGL.getTexUnit(0)->activate();
+ }
+ }
+}
+
+void LLCubeMap::enableTextureCoords(S32 stage)
+{
+ mTextureCoordStage = stage;
+ if (gGLManager.mHasCubeMap && stage >= 0 && LLCubeMap::sUseCubeMaps)
+ {
+ if (stage > 0)
+ {
+ gGL.getTexUnit(stage)->activate();
+ }
+
+ glEnable(GL_TEXTURE_GEN_R);
+ glEnable(GL_TEXTURE_GEN_S);
+ glEnable(GL_TEXTURE_GEN_T);
+
+ glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP);
+ glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP);
+ glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP);
+
+ if (stage > 0)
+ {
+ gGL.getTexUnit(0)->activate();
+ }
+ }
+}
+
+void LLCubeMap::disable(void)
+{
+ disableTexture();
+ disableTextureCoords();
+}
+
+void LLCubeMap::disableTexture(void)
+{
+ if (gGLManager.mHasCubeMap && mTextureStage >= 0 && LLCubeMap::sUseCubeMaps)
+ {
+ if (mTextureStage > 0)
+ {
+ gGL.getTexUnit(mTextureStage)->activate();
+ }
+ glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, 0);
+ glDisable(GL_TEXTURE_CUBE_MAP_ARB);
+ if (mTextureStage > 0)
+ {
+ gGL.getTexUnit(0)->activate();
+ }
+ }
+}
+
+void LLCubeMap::disableTextureCoords(void)
+{
+ if (gGLManager.mHasCubeMap && mTextureCoordStage >= 0 && LLCubeMap::sUseCubeMaps)
+ {
+ if (mTextureCoordStage > 0)
+ {
+ gGL.getTexUnit(mTextureCoordStage)->activate();
+ }
+ glDisable(GL_TEXTURE_GEN_S);
+ glDisable(GL_TEXTURE_GEN_T);
+ glDisable(GL_TEXTURE_GEN_R);
+ if (mTextureCoordStage > 0)
+ {
+ gGL.getTexUnit(0)->activate();
+ }
+ }
+}
+
+void LLCubeMap::setMatrix(S32 stage)
+{
+ mMatrixStage = stage;
+
+ if (stage > 0)
+ {
+ gGL.getTexUnit(stage)->activate();
+ }
+
+ LLVector3 x(LLVector3d(gGLModelView+0));
+ LLVector3 y(LLVector3d(gGLModelView+4));
+ LLVector3 z(LLVector3d(gGLModelView+8));
+
+ LLMatrix3 mat3;
+ mat3.setRows(x,y,z);
+ LLMatrix4 trans(mat3);
+ trans.transpose();
+
+ glMatrixMode(GL_TEXTURE);
+ glPushMatrix();
+ glLoadMatrixf((F32 *)trans.mMatrix);
+ glMatrixMode(GL_MODELVIEW);
+
+ if (stage > 0)
+ {
+ gGL.getTexUnit(0)->activate();
+ }
+}
+
+void LLCubeMap::restoreMatrix()
+{
+ if (mMatrixStage > 0)
+ {
+ gGL.getTexUnit(mMatrixStage)->activate();
+ }
+ glMatrixMode(GL_TEXTURE);
+ glPopMatrix();
+ glMatrixMode(GL_MODELVIEW);
+
+ if (mMatrixStage > 0)
+ {
+ gGL.getTexUnit(0)->activate();
+ }
+}
+
+void LLCubeMap::setReflection (void)
+{
+ glBindTexture (GL_TEXTURE_CUBE_MAP_ARB, getGLName());
+ mImages[0]->setMipFilterNearest (FALSE, FALSE);
+ mImages[0]->setClampCubemap (TRUE, TRUE);
+}
+
+LLVector3 LLCubeMap::map(U8 side, U16 v_val, U16 h_val) const
+{
+ LLVector3 dir;
+
+ const U8 curr_coef = side >> 1; // 0/1 = X axis, 2/3 = Y, 4/5 = Z
+ const S8 side_dir = (((side & 1) << 1) - 1); // even = -1, odd = 1
+ const U8 i_coef = (curr_coef + 1) % 3;
+ const U8 j_coef = (i_coef + 1) % 3;
+
+ dir.mV[curr_coef] = side_dir;
+
+ switch (side)
+ {
+ case 0: // negative X
+ dir.mV[i_coef] = -F32((v_val<<1) + 1) / RESOLUTION + 1;
+ dir.mV[j_coef] = F32((h_val<<1) + 1) / RESOLUTION - 1;
+ break;
+ case 1: // positive X
+ dir.mV[i_coef] = -F32((v_val<<1) + 1) / RESOLUTION + 1;
+ dir.mV[j_coef] = -F32((h_val<<1) + 1) / RESOLUTION + 1;
+ break;
+ case 2: // negative Y
+ dir.mV[i_coef] = -F32((v_val<<1) + 1) / RESOLUTION + 1;
+ dir.mV[j_coef] = F32((h_val<<1) + 1) / RESOLUTION - 1;
+ break;
+ case 3: // positive Y
+ dir.mV[i_coef] = F32((v_val<<1) + 1) / RESOLUTION - 1;
+ dir.mV[j_coef] = F32((h_val<<1) + 1) / RESOLUTION - 1;
+ break;
+ case 4: // negative Z
+ dir.mV[i_coef] = -F32((h_val<<1) + 1) / RESOLUTION + 1;
+ dir.mV[j_coef] = -F32((v_val<<1) + 1) / RESOLUTION + 1;
+ break;
+ case 5: // positive Z
+ dir.mV[i_coef] = -F32((h_val<<1) + 1) / RESOLUTION + 1;
+ dir.mV[j_coef] = F32((v_val<<1) + 1) / RESOLUTION - 1;
+ break;
+ default:
+ dir.mV[i_coef] = F32((v_val<<1) + 1) / RESOLUTION - 1;
+ dir.mV[j_coef] = F32((h_val<<1) + 1) / RESOLUTION - 1;
+ }
+
+ dir.normVec();
+ return dir;
+}
+
+
+BOOL LLCubeMap::project(F32& v_val, F32& h_val, BOOL& outside,
+ U8 side, const LLVector3& dir) const
+{
+ const U8 curr_coef = side >> 1; // 0/1 = X axis, 2/3 = Y, 4/5 = Z
+ const S8 side_dir = (((side & 1) << 1) - 1); // even = -1, odd = 1
+ const U8 i_coef = (curr_coef + 1) % 3;
+ const U8 j_coef = (i_coef + 1) % 3;
+
+ outside = TRUE;
+ if (side_dir * dir.mV[curr_coef] < 0)
+ return FALSE;
+
+ LLVector3 ray;
+
+ F32 norm_val = fabs(dir.mV[curr_coef]);
+
+ if (norm_val < epsilon)
+ norm_val = 1e-5f;
+
+ ray.mV[curr_coef] = side_dir;
+ ray.mV[i_coef] = dir.mV[i_coef] / norm_val;
+ ray.mV[j_coef] = dir.mV[j_coef] / norm_val;
+
+
+ const F32 i_val = (ray.mV[i_coef] + 1) * 0.5f * RESOLUTION;
+ const F32 j_val = (ray.mV[j_coef] + 1) * 0.5f * RESOLUTION;
+
+ switch (side)
+ {
+ case 0: // negative X
+ v_val = RESOLUTION - i_val;
+ h_val = j_val;
+ break;
+ case 1: // positive X
+ v_val = RESOLUTION - i_val;
+ h_val = RESOLUTION - j_val;
+ break;
+ case 2: // negative Y
+ v_val = RESOLUTION - i_val;
+ h_val = j_val;
+ break;
+ case 3: // positive Y
+ v_val = i_val;
+ h_val = j_val;
+ break;
+ case 4: // negative Z
+ v_val = RESOLUTION - j_val;
+ h_val = RESOLUTION - i_val;
+ break;
+ case 5: // positive Z
+ v_val = RESOLUTION - j_val;
+ h_val = i_val;
+ break;
+ default:
+ v_val = i_val;
+ h_val = j_val;
+ }
+
+ outside = ((v_val < 0) || (v_val > RESOLUTION) ||
+ (h_val < 0) || (h_val > RESOLUTION));
+
+ return TRUE;
+}
+
+BOOL LLCubeMap::project(F32& v_min, F32& v_max, F32& h_min, F32& h_max,
+ U8 side, LLVector3 dir[4]) const
+{
+ v_min = h_min = RESOLUTION;
+ v_max = h_max = 0;
+
+ BOOL fully_outside = TRUE;
+ for (U8 vtx = 0; vtx < 4; ++vtx)
+ {
+ F32 v_val, h_val;
+ BOOL outside;
+ BOOL consider = project(v_val, h_val, outside, side, dir[vtx]);
+ if (!outside)
+ fully_outside = FALSE;
+ if (consider)
+ {
+ if (v_val < v_min) v_min = v_val;
+ if (v_val > v_max) v_max = v_val;
+ if (h_val < h_min) h_min = h_val;
+ if (h_val > h_max) h_max = h_val;
+ }
+ }
+
+ v_min = llmax(0.0f, v_min);
+ v_max = llmin(RESOLUTION - epsilon, v_max);
+ h_min = llmax(0.0f, h_min);
+ h_max = llmin(RESOLUTION - epsilon, h_max);
+
+ return !fully_outside;
+}
+
+
+void LLCubeMap::paintIn(LLVector3 dir[4], const LLColor4U& col)
+{
+ F32 v_min, v_max, h_min, h_max;
+ LLVector3 center = dir[0] + dir[1] + dir[2] + dir[3];
+ center.normVec();
+
+ for (U8 side = 0; side < 6; ++side)
+ {
+ if (!project(v_min, v_max, h_min, h_max, side, dir))
+ continue;
+
+ U8 *td = mRawImages[side]->getData();
+
+ U16 v_minu = (U16) v_min;
+ U16 v_maxu = (U16) (ceil(v_max) + 0.5);
+ U16 h_minu = (U16) h_min;
+ U16 h_maxu = (U16) (ceil(h_max) + 0.5);
+
+ for (U16 v = v_minu; v < v_maxu; ++v)
+ for (U16 h = h_minu; h < h_maxu; ++h)
+ //for (U16 v = 0; v < RESOLUTION; ++v)
+ // for (U16 h = 0; h < RESOLUTION; ++h)
+ {
+ const LLVector3 ray = map(side, v, h);
+ if (ray * center > 0.999)
+ {
+ const U32 offset = (RESOLUTION * v + h) * 4;
+ for (U8 cc = 0; cc < 3; ++cc)
+ td[offset + cc] = U8((td[offset + cc] + col.mV[cc]) * 0.5);
+ }
+ }
+ mImages[side]->setSubImage(mRawImages[side], 0, 0, 64, 64);
+ }
+}
+
+void LLCubeMap::destroyGL()
+{
+ for (S32 i = 0; i < 6; i++)
+ {
+ mImages[i] = NULL;
+ }
+}
diff --git a/indra/llrender/llcubemap.h b/indra/llrender/llcubemap.h
new file mode 100644
index 0000000000..c273ab40ec
--- /dev/null
+++ b/indra/llrender/llcubemap.h
@@ -0,0 +1,89 @@
+/**
+ * @file llcubemap.h
+ * @brief LLCubeMap class definition
+ *
+ * $LicenseInfo:firstyear=2002&license=viewergpl$
+ *
+ * Copyright (c) 2002-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$
+ */
+
+#ifndef LL_LLCUBEMAP_H
+#define LL_LLCUBEMAP_H
+
+#include "llgl.h"
+
+#include <vector>
+
+class LLVector3;
+
+// Environment map hack!
+class LLCubeMap : public LLRefCount
+{
+public:
+ LLCubeMap();
+ void init(const std::vector<LLPointer<LLImageRaw> >& rawimages);
+ void initGL();
+ void initRawData(const std::vector<LLPointer<LLImageRaw> >& rawimages);
+ void initGLData();
+
+ void bind();
+ void enable(S32 stage);
+
+ void enableTexture(S32 stage);
+ void enableTextureCoords(S32 stage);
+
+ void disable(void);
+ void disableTexture(void);
+ void disableTextureCoords(void);
+ void setMatrix(S32 stage);
+ void restoreMatrix();
+ void setReflection (void);
+
+ void finishPaint();
+
+ GLuint getGLName();
+
+ LLVector3 map(U8 side, U16 v_val, U16 h_val) const;
+ BOOL project(F32& v_val, F32& h_val, BOOL& outside,
+ U8 side, const LLVector3& dir) const;
+ BOOL project(F32& v_min, F32& v_max, F32& h_min, F32& h_max,
+ U8 side, LLVector3 dir[4]) const;
+ void paintIn(LLVector3 dir[4], const LLColor4U& col);
+ void destroyGL();
+
+public:
+ static bool sUseCubeMaps;
+
+protected:
+ ~LLCubeMap();
+ LLGLenum mTargets[6];
+ LLPointer<LLImageGL> mImages[6];
+ LLPointer<LLImageRaw> mRawImages[6];
+ S32 mTextureStage;
+ S32 mTextureCoordStage;
+ S32 mMatrixStage;
+};
+
+#endif
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);
+}
+
diff --git a/indra/llrender/llgl.h b/indra/llrender/llgl.h
new file mode 100644
index 0000000000..e9b4c7929e
--- /dev/null
+++ b/indra/llrender/llgl.h
@@ -0,0 +1,377 @@
+/**
+ * @file llgl.h
+ * @brief LLGL definition
+ *
+ * $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$
+ */
+
+#ifndef LL_LLGL_H
+#define LL_LLGL_H
+
+// This file contains various stuff for handling gl extensions and other gl related stuff.
+
+#include <string>
+#include <map>
+
+#include "llerror.h"
+#include "v4color.h"
+#include "llstring.h"
+#include "stdtypes.h"
+#include "v4math.h"
+#include "llplane.h"
+#include "llgltypes.h"
+
+#include "llglheaders.h"
+#include "glh/glh_linear.h"
+
+extern BOOL gDebugGL;
+
+#define LL_GL_ERRS LL_ERRS("RenderState")
+
+class LLSD;
+
+// Manage GL extensions...
+class LLGLManager
+{
+public:
+ LLGLManager();
+
+ bool initGL();
+ void shutdownGL();
+
+ void initWGL(); // Initializes stupid WGL extensions
+
+ std::string getRawGLString(); // For sending to simulator
+
+ BOOL mInited;
+ BOOL mIsDisabled;
+
+ // Extensions used by everyone
+ BOOL mHasMultitexture;
+ S32 mNumTextureUnits;
+ BOOL mHasMipMapGeneration;
+ BOOL mHasPalettedTextures;
+ BOOL mHasCompressedTextures;
+ BOOL mHasFramebufferObject;
+
+ // ARB Extensions
+ BOOL mHasVertexBufferObject;
+ BOOL mHasPBuffer;
+ BOOL mHasShaderObjects;
+ BOOL mHasVertexShader;
+ BOOL mHasFragmentShader;
+ BOOL mHasOcclusionQuery;
+ BOOL mHasPointParameters;
+
+ // Other extensions.
+ BOOL mHasAnisotropic;
+ BOOL mHasARBEnvCombine;
+ BOOL mHasCubeMap;
+
+ // Vendor-specific extensions
+ BOOL mIsATI;
+ BOOL mIsNVIDIA;
+ BOOL mIsIntel;
+ BOOL mIsGF2or4MX;
+ BOOL mIsGF3;
+ BOOL mIsGFFX;
+ BOOL mATIOffsetVerticalLines;
+
+ // Whether this version of GL is good enough for SL to use
+ BOOL mHasRequirements;
+
+ // Misc extensions
+ BOOL mHasSeparateSpecularColor;
+
+ S32 mDriverVersionMajor;
+ S32 mDriverVersionMinor;
+ S32 mDriverVersionRelease;
+ F32 mGLVersion; // e.g = 1.4
+ std::string mDriverVersionVendorString;
+
+ S32 mVRAM; // VRAM in MB
+ S32 mGLMaxVertexRange;
+ S32 mGLMaxIndexRange;
+
+ void getPixelFormat(); // Get the best pixel format
+
+ std::string getGLInfoString();
+ void printGLInfoString();
+ void getGLInfo(LLSD& info);
+
+ // In ALL CAPS
+ std::string mGLVendor;
+ std::string mGLVendorShort;
+
+ // In ALL CAPS
+ std::string mGLRenderer;
+
+private:
+ void initExtensions();
+ void initGLStates();
+ void initGLImages();
+};
+
+extern LLGLManager gGLManager;
+
+class LLQuaternion;
+class LLMatrix4;
+
+void rotate_quat(LLQuaternion& rotation);
+
+void flush_glerror(); // Flush GL errors when we know we're handling them correctly.
+
+void assert_glerror();
+
+void clear_glerror();
+
+//#if LL_DEBUG
+# define stop_glerror() assert_glerror()
+# define llglassertok() assert_glerror()
+//#else
+//# define stop_glerror()
+//# define llglassertok()
+//#endif
+
+#define llglassertok_always() assert_glerror()
+
+////////////////////////
+//
+// Note: U32's are GLEnum's...
+//
+
+// This is a class for GL state management
+
+/*
+ GL STATE MANAGEMENT DESCRIPTION
+
+ LLGLState and its two subclasses, LLGLEnable and LLGLDisable, manage the current
+ enable/disable states of the GL to prevent redundant setting of state within a
+ render path or the accidental corruption of what state the next path expects.
+
+ Essentially, wherever you would call glEnable set a state and then
+ subsequently reset it by calling glDisable (or vice versa), make an instance of
+ LLGLEnable with the state you want to set, and assume it will be restored to its
+ original state when that instance of LLGLEnable is destroyed. It is good practice
+ to exploit stack frame controls for optimal setting/unsetting and readability of
+ code. In llglstates.h, there are a collection of helper classes that define groups
+ of enables/disables that can cause multiple states to be set with the creation of
+ one instance.
+
+ Sample usage:
+
+ //disable lighting for rendering hud objects
+ //INCORRECT USAGE
+ LLGLEnable lighting(GL_LIGHTING);
+ renderHUD();
+ LLGLDisable lighting(GL_LIGHTING);
+
+ //CORRECT USAGE
+ {
+ LLGLEnable lighting(GL_LIGHTING);
+ renderHUD();
+ }
+
+ If a state is to be set on a conditional, the following mechanism
+ is useful:
+
+ {
+ LLGLEnable lighting(light_hud ? GL_LIGHTING : 0);
+ renderHUD();
+ }
+
+ A LLGLState initialized with a parameter of 0 does nothing.
+
+ LLGLState works by maintaining a map of the current GL states, and ignoring redundant
+ enables/disables. If a redundant call is attempted, it becomes a noop, otherwise,
+ it is set in the constructor and reset in the destructor.
+
+ For debugging GL state corruption, running with debug enabled will trigger asserts
+ if the existing GL state does not match the expected GL state.
+
+*/
+class LLGLState
+{
+public:
+ static void initClass();
+ static void restoreGL();
+
+ static void resetTextureStates();
+ static void dumpStates();
+ static void checkStates();
+ static void checkTextureChannels();
+ static void checkClientArrays(U32 data_mask = 0x0001);
+
+protected:
+ static std::map<LLGLenum, LLGLboolean> sStateMap;
+
+public:
+ enum { CURRENT_STATE = -2 };
+ LLGLState(LLGLenum state, S32 enabled = CURRENT_STATE);
+ ~LLGLState();
+ void setEnabled(S32 enabled);
+ void enable() { setEnabled(TRUE); }
+ void disable() { setEnabled(FALSE); }
+protected:
+ LLGLenum mState;
+ BOOL mWasEnabled;
+ BOOL mIsEnabled;
+};
+
+// New LLGLState class wrappers that don't depend on actual GL flags.
+class LLGLEnableBlending : public LLGLState
+{
+public:
+ LLGLEnableBlending(bool enable);
+};
+
+class LLGLEnableAlphaReject : public LLGLState
+{
+public:
+ LLGLEnableAlphaReject(bool enable);
+};
+
+/// TODO: Being deprecated.
+class LLGLEnable : public LLGLState
+{
+public:
+ LLGLEnable(LLGLenum state) : LLGLState(state, TRUE) {}
+};
+
+/// TODO: Being deprecated.
+class LLGLDisable : public LLGLState
+{
+public:
+ LLGLDisable(LLGLenum state) : LLGLState(state, FALSE) {}
+};
+
+/*
+ Store and modify projection matrix to create an oblique
+ projection that clips to the specified plane. Oblique
+ projections alter values in the depth buffer, so this
+ class should not be used mid-renderpass.
+
+ Restores projection matrix on destruction.
+ GL_MODELVIEW_MATRIX is active whenever program execution
+ leaves this class.
+ Does not stack.
+ Caches inverse of projection matrix used in gGLObliqueProjectionInverse
+*/
+class LLGLUserClipPlane
+{
+public:
+
+ LLGLUserClipPlane(const LLPlane& plane, const glh::matrix4f& modelview, const glh::matrix4f& projection);
+ ~LLGLUserClipPlane();
+
+ void setPlane(F32 a, F32 b, F32 c, F32 d);
+
+private:
+ glh::matrix4f mProjection;
+ glh::matrix4f mModelview;
+};
+
+/*
+ Modify and load projection matrix to push depth values to far clip plane.
+
+ Restores projection matrix on destruction.
+ GL_MODELVIEW_MATRIX is active whenever program execution
+ leaves this class.
+ Does not stack.
+*/
+class LLGLClampToFarClip
+{
+public:
+ LLGLClampToFarClip(glh::matrix4f projection);
+ ~LLGLClampToFarClip();
+};
+
+/*
+ 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
+{
+public:
+ typedef struct
+ {
+ GLuint name;
+ BOOL used;
+ } NameEntry;
+
+ struct CompareUsed
+ {
+ bool operator()(const NameEntry& lhs, const NameEntry& rhs)
+ {
+ return lhs.used < rhs.used; //FALSE entries first
+ }
+ };
+
+ typedef std::vector<NameEntry> name_list_t;
+ name_list_t mNameList;
+
+ LLGLNamePool();
+ virtual ~LLGLNamePool();
+
+ void upkeep();
+ void cleanup();
+
+ 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;
+};
+
+extern LLMatrix4 gGLObliqueProjectionInverse;
+
+#include "llglstates.h"
+
+void init_glstates();
+void enable_vertex_weighting(const S32 index);
+void disable_vertex_weighting(const S32 index);
+void enable_binormals(const S32 index);
+void disable_binormals(const S32 index);
+void enable_cloth_weights(const S32 index);
+void disable_cloth_weights(const S32 index);
+void set_vertex_weights(const S32 index, const U32 stride, const F32 *weights);
+void set_vertex_clothing_weights(const S32 index, const U32 stride, const LLVector4 *weights);
+void set_binormals(const S32 index, const U32 stride, const LLVector3 *binormals);
+void set_palette(U8* palette_data);
+void parse_gl_version( S32* major, S32* minor, S32* release, std::string* vendor_specific );
+
+extern BOOL gClothRipple;
+extern BOOL gNoRender;
+#endif // LL_LLGL_H
diff --git a/indra/llrender/llglheaders.h b/indra/llrender/llglheaders.h
new file mode 100644
index 0000000000..01578245ac
--- /dev/null
+++ b/indra/llrender/llglheaders.h
@@ -0,0 +1,588 @@
+/**
+ * @file llglheaders.h
+ * @brief LLGL definitions
+ *
+ * $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$
+ */
+
+#ifndef LL_LLGLHEADERS_H
+#define LL_LLGLHEADERS_H
+
+#if LL_MESA
+//----------------------------------------------------------------------------
+// MESA headers
+// quotes so we get libraries/.../GL/ version
+#define GL_GLEXT_PROTOTYPES
+#include "GL/gl.h"
+#include "GL/glext.h"
+#include "GL/glu.h"
+
+// The __APPLE__ kludge is to make glh_extensions.h not symbol-clash horribly
+# define __APPLE__
+# include "GL/glh_extensions.h"
+# undef __APPLE__
+
+#elif LL_LINUX
+//----------------------------------------------------------------------------
+// Linux, MESA headers, but not necessarily assuming MESA runtime.
+// quotes so we get libraries/.../GL/ version
+#include "GL/gl.h"
+#include "GL/glext.h"
+#include "GL/glu.h"
+
+
+#if LL_LINUX && !LL_MESA_HEADLESS
+// The __APPLE__ kludge is to make glh_extensions.h not symbol-clash horribly
+# define __APPLE__
+# include "GL/glh_extensions.h"
+# undef __APPLE__
+
+/* Although SDL very likely ends up calling glXGetProcAddress() itself,
+ if we use SDL_GL_GetProcAddress() then we get bogus addresses back on
+ some systems. Weird. */
+/*# include "SDL/SDL.h"
+ # define GLH_EXT_GET_PROC_ADDRESS(p) SDL_GL_GetProcAddress(p) */
+#define GLX_GLXEXT_PROTOTYPES 1
+# include "GL/glx.h"
+# include "GL/glxext.h"
+// Use glXGetProcAddressARB instead of glXGetProcAddress - the ARB symbol
+// is considered 'legacy' but works on more machines.
+# define GLH_EXT_GET_PROC_ADDRESS(p) glXGetProcAddressARB((const GLubyte*)(p))
+// Whee, the X headers define 'Status'. Undefine to avoid confusion.
+#undef Status
+#endif // LL_LINUX && !LL_MESA_HEADLESS
+
+
+// GL_ARB_vertex_buffer_object
+extern PFNGLBINDBUFFERARBPROC glBindBufferARB;
+extern PFNGLDELETEBUFFERSARBPROC glDeleteBuffersARB;
+extern PFNGLGENBUFFERSARBPROC glGenBuffersARB;
+extern PFNGLISBUFFERARBPROC glIsBufferARB;
+extern PFNGLBUFFERDATAARBPROC glBufferDataARB;
+extern PFNGLBUFFERSUBDATAARBPROC glBufferSubDataARB;
+extern PFNGLGETBUFFERSUBDATAARBPROC glGetBufferSubDataARB;
+extern PFNGLMAPBUFFERARBPROC glMapBufferARB;
+extern PFNGLUNMAPBUFFERARBPROC glUnmapBufferARB;
+extern PFNGLGETBUFFERPARAMETERIVARBPROC glGetBufferParameterivARB;
+extern PFNGLGETBUFFERPOINTERVARBPROC glGetBufferPointervARB;
+
+// GL_ATI_vertex_array_object
+extern PFNGLNEWOBJECTBUFFERATIPROC glNewObjectBufferATI;
+extern PFNGLISOBJECTBUFFERATIPROC glIsObjectBufferATI;
+extern PFNGLUPDATEOBJECTBUFFERATIPROC glUpdateObjectBufferATI;
+extern PFNGLGETOBJECTBUFFERFVATIPROC glGetObjectBufferfvATI;
+extern PFNGLGETOBJECTBUFFERIVATIPROC glGetObjectBufferivATI;
+extern PFNGLFREEOBJECTBUFFERATIPROC glFreeObjectBufferATI;
+extern PFNGLARRAYOBJECTATIPROC glArrayObjectATI;
+extern PFNGLVERTEXATTRIBARRAYOBJECTATIPROC glVertexAttribArrayObjectATI;
+extern PFNGLGETARRAYOBJECTFVATIPROC glGetArrayObjectfvATI;
+extern PFNGLGETARRAYOBJECTIVATIPROC glGetArrayObjectivATI;
+extern PFNGLVARIANTARRAYOBJECTATIPROC glVariantObjectArrayATI;
+extern PFNGLGETVARIANTARRAYOBJECTFVATIPROC glGetVariantArrayObjectfvATI;
+extern PFNGLGETVARIANTARRAYOBJECTIVATIPROC glGetVariantArrayObjectivATI;
+
+// GL_ARB_occlusion_query
+extern PFNGLGENQUERIESARBPROC glGenQueriesARB;
+extern PFNGLDELETEQUERIESARBPROC glDeleteQueriesARB;
+extern PFNGLISQUERYARBPROC glIsQueryARB;
+extern PFNGLBEGINQUERYARBPROC glBeginQueryARB;
+extern PFNGLENDQUERYARBPROC glEndQueryARB;
+extern PFNGLGETQUERYIVARBPROC glGetQueryivARB;
+extern PFNGLGETQUERYOBJECTIVARBPROC glGetQueryObjectivARB;
+extern PFNGLGETQUERYOBJECTUIVARBPROC glGetQueryObjectuivARB;
+
+// GL_ARB_point_parameters
+extern PFNGLPOINTPARAMETERFARBPROC glPointParameterfARB;
+extern PFNGLPOINTPARAMETERFVARBPROC glPointParameterfvARB;
+
+// GL_ARB_shader_objects
+extern PFNGLDELETEOBJECTARBPROC glDeleteObjectARB;
+extern PFNGLGETHANDLEARBPROC glGetHandleARB;
+extern PFNGLDETACHOBJECTARBPROC glDetachObjectARB;
+extern PFNGLCREATESHADEROBJECTARBPROC glCreateShaderObjectARB;
+extern PFNGLSHADERSOURCEARBPROC glShaderSourceARB;
+extern PFNGLCOMPILESHADERARBPROC glCompileShaderARB;
+extern PFNGLCREATEPROGRAMOBJECTARBPROC glCreateProgramObjectARB;
+extern PFNGLATTACHOBJECTARBPROC glAttachObjectARB;
+extern PFNGLLINKPROGRAMARBPROC glLinkProgramARB;
+extern PFNGLUSEPROGRAMOBJECTARBPROC glUseProgramObjectARB;
+extern PFNGLVALIDATEPROGRAMARBPROC glValidateProgramARB;
+extern PFNGLUNIFORM1FARBPROC glUniform1fARB;
+extern PFNGLUNIFORM2FARBPROC glUniform2fARB;
+extern PFNGLUNIFORM3FARBPROC glUniform3fARB;
+extern PFNGLUNIFORM4FARBPROC glUniform4fARB;
+extern PFNGLUNIFORM1IARBPROC glUniform1iARB;
+extern PFNGLUNIFORM2IARBPROC glUniform2iARB;
+extern PFNGLUNIFORM3IARBPROC glUniform3iARB;
+extern PFNGLUNIFORM4IARBPROC glUniform4iARB;
+extern PFNGLUNIFORM1FVARBPROC glUniform1fvARB;
+extern PFNGLUNIFORM2FVARBPROC glUniform2fvARB;
+extern PFNGLUNIFORM3FVARBPROC glUniform3fvARB;
+extern PFNGLUNIFORM4FVARBPROC glUniform4fvARB;
+extern PFNGLUNIFORM1IVARBPROC glUniform1ivARB;
+extern PFNGLUNIFORM2IVARBPROC glUniform2ivARB;
+extern PFNGLUNIFORM3IVARBPROC glUniform3ivARB;
+extern PFNGLUNIFORM4IVARBPROC glUniform4ivARB;
+extern PFNGLUNIFORMMATRIX2FVARBPROC glUniformMatrix2fvARB;
+extern PFNGLUNIFORMMATRIX3FVARBPROC glUniformMatrix3fvARB;
+extern PFNGLUNIFORMMATRIX4FVARBPROC glUniformMatrix4fvARB;
+extern PFNGLGETOBJECTPARAMETERFVARBPROC glGetObjectParameterfvARB;
+extern PFNGLGETOBJECTPARAMETERIVARBPROC glGetObjectParameterivARB;
+extern PFNGLGETINFOLOGARBPROC glGetInfoLogARB;
+extern PFNGLGETATTACHEDOBJECTSARBPROC glGetAttachedObjectsARB;
+extern PFNGLGETUNIFORMLOCATIONARBPROC glGetUniformLocationARB;
+extern PFNGLGETACTIVEUNIFORMARBPROC glGetActiveUniformARB;
+extern PFNGLGETUNIFORMFVARBPROC glGetUniformfvARB;
+extern PFNGLGETUNIFORMIVARBPROC glGetUniformivARB;
+extern PFNGLGETSHADERSOURCEARBPROC glGetShaderSourceARB;
+
+// GL_ARB_vertex_shader
+extern PFNGLVERTEXATTRIB1DARBPROC glVertexAttrib1dARB;
+extern PFNGLVERTEXATTRIB1DVARBPROC glVertexAttrib1dvARB;
+extern PFNGLVERTEXATTRIB1FARBPROC glVertexAttrib1fARB;
+extern PFNGLVERTEXATTRIB1FVARBPROC glVertexAttrib1fvARB;
+extern PFNGLVERTEXATTRIB1SARBPROC glVertexAttrib1sARB;
+extern PFNGLVERTEXATTRIB1SVARBPROC glVertexAttrib1svARB;
+extern PFNGLVERTEXATTRIB2DARBPROC glVertexAttrib2dARB;
+extern PFNGLVERTEXATTRIB2DVARBPROC glVertexAttrib2dvARB;
+extern PFNGLVERTEXATTRIB2FARBPROC glVertexAttrib2fARB;
+extern PFNGLVERTEXATTRIB2FVARBPROC glVertexAttrib2fvARB;
+extern PFNGLVERTEXATTRIB2SARBPROC glVertexAttrib2sARB;
+extern PFNGLVERTEXATTRIB2SVARBPROC glVertexAttrib2svARB;
+extern PFNGLVERTEXATTRIB3DARBPROC glVertexAttrib3dARB;
+extern PFNGLVERTEXATTRIB3DVARBPROC glVertexAttrib3dvARB;
+extern PFNGLVERTEXATTRIB3FARBPROC glVertexAttrib3fARB;
+extern PFNGLVERTEXATTRIB3FVARBPROC glVertexAttrib3fvARB;
+extern PFNGLVERTEXATTRIB3SARBPROC glVertexAttrib3sARB;
+extern PFNGLVERTEXATTRIB3SVARBPROC glVertexAttrib3svARB;
+extern PFNGLVERTEXATTRIB4NBVARBPROC glVertexAttrib4nbvARB;
+extern PFNGLVERTEXATTRIB4NIVARBPROC glVertexAttrib4nivARB;
+extern PFNGLVERTEXATTRIB4NSVARBPROC glVertexAttrib4nsvARB;
+extern PFNGLVERTEXATTRIB4NUBARBPROC glVertexAttrib4nubARB;
+extern PFNGLVERTEXATTRIB4NUBVARBPROC glVertexAttrib4nubvARB;
+extern PFNGLVERTEXATTRIB4NUIVARBPROC glVertexAttrib4nuivARB;
+extern PFNGLVERTEXATTRIB4NUSVARBPROC glVertexAttrib4nusvARB;
+extern PFNGLVERTEXATTRIB4BVARBPROC glVertexAttrib4bvARB;
+extern PFNGLVERTEXATTRIB4DARBPROC glVertexAttrib4dARB;
+extern PFNGLVERTEXATTRIB4DVARBPROC glVertexAttrib4dvARB;
+extern PFNGLVERTEXATTRIB4FARBPROC glVertexAttrib4fARB;
+extern PFNGLVERTEXATTRIB4FVARBPROC glVertexAttrib4fvARB;
+extern PFNGLVERTEXATTRIB4IVARBPROC glVertexAttrib4ivARB;
+extern PFNGLVERTEXATTRIB4SARBPROC glVertexAttrib4sARB;
+extern PFNGLVERTEXATTRIB4SVARBPROC glVertexAttrib4svARB;
+extern PFNGLVERTEXATTRIB4UBVARBPROC glVertexAttrib4ubvARB;
+extern PFNGLVERTEXATTRIB4UIVARBPROC glVertexAttrib4uivARB;
+extern PFNGLVERTEXATTRIB4USVARBPROC glVertexAttrib4usvARB;
+extern PFNGLVERTEXATTRIBPOINTERARBPROC glVertexAttribPointerARB;
+extern PFNGLENABLEVERTEXATTRIBARRAYARBPROC glEnableVertexAttribArrayARB;
+extern PFNGLDISABLEVERTEXATTRIBARRAYARBPROC glDisableVertexAttribArrayARB;
+extern PFNGLPROGRAMSTRINGARBPROC glProgramStringARB;
+extern PFNGLBINDPROGRAMARBPROC glBindProgramARB;
+extern PFNGLDELETEPROGRAMSARBPROC glDeleteProgramsARB;
+extern PFNGLGENPROGRAMSARBPROC glGenProgramsARB;
+extern PFNGLPROGRAMENVPARAMETER4DARBPROC glProgramEnvParameter4dARB;
+extern PFNGLPROGRAMENVPARAMETER4DVARBPROC glProgramEnvParameter4dvARB;
+extern PFNGLPROGRAMENVPARAMETER4FARBPROC glProgramEnvParameter4fARB;
+extern PFNGLPROGRAMENVPARAMETER4FVARBPROC glProgramEnvParameter4fvARB;
+extern PFNGLPROGRAMLOCALPARAMETER4DARBPROC glProgramLocalParameter4dARB;
+extern PFNGLPROGRAMLOCALPARAMETER4DVARBPROC glProgramLocalParameter4dvARB;
+extern PFNGLPROGRAMLOCALPARAMETER4FARBPROC glProgramLocalParameter4fARB;
+extern PFNGLPROGRAMLOCALPARAMETER4FVARBPROC glProgramLocalParameter4fvARB;
+extern PFNGLGETPROGRAMENVPARAMETERDVARBPROC glGetProgramEnvParameterdvARB;
+extern PFNGLGETPROGRAMENVPARAMETERFVARBPROC glGetProgramEnvParameterfvARB;
+extern PFNGLGETPROGRAMLOCALPARAMETERDVARBPROC glGetProgramLocalParameterdvARB;
+extern PFNGLGETPROGRAMLOCALPARAMETERFVARBPROC glGetProgramLocalParameterfvARB;
+extern PFNGLGETPROGRAMIVARBPROC glGetProgramivARB;
+extern PFNGLGETPROGRAMSTRINGARBPROC glGetProgramStringARB;
+extern PFNGLGETVERTEXATTRIBDVARBPROC glGetVertexAttribdvARB;
+extern PFNGLGETVERTEXATTRIBFVARBPROC glGetVertexAttribfvARB;
+extern PFNGLGETVERTEXATTRIBIVARBPROC glGetVertexAttribivARB;
+extern PFNGLGETVERTEXATTRIBPOINTERVARBPROC glGetVertexAttribPointervARB;
+extern PFNGLISPROGRAMARBPROC glIsProgramARB;
+extern PFNGLBINDATTRIBLOCATIONARBPROC glBindAttribLocationARB;
+extern PFNGLGETACTIVEATTRIBARBPROC glGetActiveAttribARB;
+extern PFNGLGETATTRIBLOCATIONARBPROC glGetAttribLocationARB;
+
+extern PFNGLCOMPRESSEDTEXIMAGE2DARBPROC glCompressedTexImage2DARB;
+extern PFNGLGETCOMPRESSEDTEXIMAGEARBPROC glGetCompressedTexImageARB;
+
+extern PFNGLCOLORTABLEEXTPROC glColorTableEXT;
+
+//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;
+
+
+#elif LL_WINDOWS
+
+// windows gl headers depend on things like APIENTRY, so include windows.
+#define WIN32_LEAN_AND_MEAN
+#include <winsock2.h>
+#include <windows.h>
+
+//----------------------------------------------------------------------------
+#include <GL/gl.h>
+#include <GL/glu.h>
+
+// quotes so we get libraries/.../GL/ version
+#include "GL/glext.h"
+#include "GL/glh_extensions.h"
+
+
+// GL_ARB_vertex_buffer_object
+extern PFNGLBINDBUFFERARBPROC glBindBufferARB;
+extern PFNGLDELETEBUFFERSARBPROC glDeleteBuffersARB;
+extern PFNGLGENBUFFERSARBPROC glGenBuffersARB;
+extern PFNGLISBUFFERARBPROC glIsBufferARB;
+extern PFNGLBUFFERDATAARBPROC glBufferDataARB;
+extern PFNGLBUFFERSUBDATAARBPROC glBufferSubDataARB;
+extern PFNGLGETBUFFERSUBDATAARBPROC glGetBufferSubDataARB;
+extern PFNGLMAPBUFFERARBPROC glMapBufferARB;
+extern PFNGLUNMAPBUFFERARBPROC glUnmapBufferARB;
+extern PFNGLGETBUFFERPARAMETERIVARBPROC glGetBufferParameterivARB;
+extern PFNGLGETBUFFERPOINTERVARBPROC glGetBufferPointervARB;
+
+// GL_ATI_vertex_array_object
+extern PFNGLNEWOBJECTBUFFERATIPROC glNewObjectBufferATI;
+extern PFNGLISOBJECTBUFFERATIPROC glIsObjectBufferATI;
+extern PFNGLUPDATEOBJECTBUFFERATIPROC glUpdateObjectBufferATI;
+extern PFNGLGETOBJECTBUFFERFVATIPROC glGetObjectBufferfvATI;
+extern PFNGLGETOBJECTBUFFERIVATIPROC glGetObjectBufferivATI;
+extern PFNGLFREEOBJECTBUFFERATIPROC glFreeObjectBufferATI;
+extern PFNGLARRAYOBJECTATIPROC glArrayObjectATI;
+extern PFNGLVERTEXATTRIBARRAYOBJECTATIPROC glVertexAttribArrayObjectATI;
+extern PFNGLGETARRAYOBJECTFVATIPROC glGetArrayObjectfvATI;
+extern PFNGLGETARRAYOBJECTIVATIPROC glGetArrayObjectivATI;
+extern PFNGLVARIANTARRAYOBJECTATIPROC glVariantObjectArrayATI;
+extern PFNGLGETVARIANTARRAYOBJECTFVATIPROC glGetVariantArrayObjectfvATI;
+extern PFNGLGETVARIANTARRAYOBJECTIVATIPROC glGetVariantArrayObjectivATI;
+
+extern PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT;
+
+// GL_ARB_occlusion_query
+extern PFNGLGENQUERIESARBPROC glGenQueriesARB;
+extern PFNGLDELETEQUERIESARBPROC glDeleteQueriesARB;
+extern PFNGLISQUERYARBPROC glIsQueryARB;
+extern PFNGLBEGINQUERYARBPROC glBeginQueryARB;
+extern PFNGLENDQUERYARBPROC glEndQueryARB;
+extern PFNGLGETQUERYIVARBPROC glGetQueryivARB;
+extern PFNGLGETQUERYOBJECTIVARBPROC glGetQueryObjectivARB;
+extern PFNGLGETQUERYOBJECTUIVARBPROC glGetQueryObjectuivARB;
+
+// GL_ARB_point_parameters
+extern PFNGLPOINTPARAMETERFARBPROC glPointParameterfARB;
+extern PFNGLPOINTPARAMETERFVARBPROC glPointParameterfvARB;
+
+// GL_ARB_shader_objects
+extern PFNGLDELETEOBJECTARBPROC glDeleteObjectARB;
+extern PFNGLGETHANDLEARBPROC glGetHandleARB;
+extern PFNGLDETACHOBJECTARBPROC glDetachObjectARB;
+extern PFNGLCREATESHADEROBJECTARBPROC glCreateShaderObjectARB;
+extern PFNGLSHADERSOURCEARBPROC glShaderSourceARB;
+extern PFNGLCOMPILESHADERARBPROC glCompileShaderARB;
+extern PFNGLCREATEPROGRAMOBJECTARBPROC glCreateProgramObjectARB;
+extern PFNGLATTACHOBJECTARBPROC glAttachObjectARB;
+extern PFNGLLINKPROGRAMARBPROC glLinkProgramARB;
+extern PFNGLUSEPROGRAMOBJECTARBPROC glUseProgramObjectARB;
+extern PFNGLVALIDATEPROGRAMARBPROC glValidateProgramARB;
+extern PFNGLUNIFORM1FARBPROC glUniform1fARB;
+extern PFNGLUNIFORM2FARBPROC glUniform2fARB;
+extern PFNGLUNIFORM3FARBPROC glUniform3fARB;
+extern PFNGLUNIFORM4FARBPROC glUniform4fARB;
+extern PFNGLUNIFORM1IARBPROC glUniform1iARB;
+extern PFNGLUNIFORM2IARBPROC glUniform2iARB;
+extern PFNGLUNIFORM3IARBPROC glUniform3iARB;
+extern PFNGLUNIFORM4IARBPROC glUniform4iARB;
+extern PFNGLUNIFORM1FVARBPROC glUniform1fvARB;
+extern PFNGLUNIFORM2FVARBPROC glUniform2fvARB;
+extern PFNGLUNIFORM3FVARBPROC glUniform3fvARB;
+extern PFNGLUNIFORM4FVARBPROC glUniform4fvARB;
+extern PFNGLUNIFORM1IVARBPROC glUniform1ivARB;
+extern PFNGLUNIFORM2IVARBPROC glUniform2ivARB;
+extern PFNGLUNIFORM3IVARBPROC glUniform3ivARB;
+extern PFNGLUNIFORM4IVARBPROC glUniform4ivARB;
+extern PFNGLUNIFORMMATRIX2FVARBPROC glUniformMatrix2fvARB;
+extern PFNGLUNIFORMMATRIX3FVARBPROC glUniformMatrix3fvARB;
+extern PFNGLUNIFORMMATRIX4FVARBPROC glUniformMatrix4fvARB;
+extern PFNGLGETOBJECTPARAMETERFVARBPROC glGetObjectParameterfvARB;
+extern PFNGLGETOBJECTPARAMETERIVARBPROC glGetObjectParameterivARB;
+extern PFNGLGETINFOLOGARBPROC glGetInfoLogARB;
+extern PFNGLGETATTACHEDOBJECTSARBPROC glGetAttachedObjectsARB;
+extern PFNGLGETUNIFORMLOCATIONARBPROC glGetUniformLocationARB;
+extern PFNGLGETACTIVEUNIFORMARBPROC glGetActiveUniformARB;
+extern PFNGLGETUNIFORMFVARBPROC glGetUniformfvARB;
+extern PFNGLGETUNIFORMIVARBPROC glGetUniformivARB;
+extern PFNGLGETSHADERSOURCEARBPROC glGetShaderSourceARB;
+
+// GL_ARB_vertex_shader
+extern PFNGLVERTEXATTRIB1DARBPROC glVertexAttrib1dARB;
+extern PFNGLVERTEXATTRIB1DVARBPROC glVertexAttrib1dvARB;
+extern PFNGLVERTEXATTRIB1FARBPROC glVertexAttrib1fARB;
+extern PFNGLVERTEXATTRIB1FVARBPROC glVertexAttrib1fvARB;
+extern PFNGLVERTEXATTRIB1SARBPROC glVertexAttrib1sARB;
+extern PFNGLVERTEXATTRIB1SVARBPROC glVertexAttrib1svARB;
+extern PFNGLVERTEXATTRIB2DARBPROC glVertexAttrib2dARB;
+extern PFNGLVERTEXATTRIB2DVARBPROC glVertexAttrib2dvARB;
+extern PFNGLVERTEXATTRIB2FARBPROC glVertexAttrib2fARB;
+extern PFNGLVERTEXATTRIB2FVARBPROC glVertexAttrib2fvARB;
+extern PFNGLVERTEXATTRIB2SARBPROC glVertexAttrib2sARB;
+extern PFNGLVERTEXATTRIB2SVARBPROC glVertexAttrib2svARB;
+extern PFNGLVERTEXATTRIB3DARBPROC glVertexAttrib3dARB;
+extern PFNGLVERTEXATTRIB3DVARBPROC glVertexAttrib3dvARB;
+extern PFNGLVERTEXATTRIB3FARBPROC glVertexAttrib3fARB;
+extern PFNGLVERTEXATTRIB3FVARBPROC glVertexAttrib3fvARB;
+extern PFNGLVERTEXATTRIB3SARBPROC glVertexAttrib3sARB;
+extern PFNGLVERTEXATTRIB3SVARBPROC glVertexAttrib3svARB;
+extern PFNGLVERTEXATTRIB4NBVARBPROC glVertexAttrib4nbvARB;
+extern PFNGLVERTEXATTRIB4NIVARBPROC glVertexAttrib4nivARB;
+extern PFNGLVERTEXATTRIB4NSVARBPROC glVertexAttrib4nsvARB;
+extern PFNGLVERTEXATTRIB4NUBARBPROC glVertexAttrib4nubARB;
+extern PFNGLVERTEXATTRIB4NUBVARBPROC glVertexAttrib4nubvARB;
+extern PFNGLVERTEXATTRIB4NUIVARBPROC glVertexAttrib4nuivARB;
+extern PFNGLVERTEXATTRIB4NUSVARBPROC glVertexAttrib4nusvARB;
+extern PFNGLVERTEXATTRIB4BVARBPROC glVertexAttrib4bvARB;
+extern PFNGLVERTEXATTRIB4DARBPROC glVertexAttrib4dARB;
+extern PFNGLVERTEXATTRIB4DVARBPROC glVertexAttrib4dvARB;
+extern PFNGLVERTEXATTRIB4FARBPROC glVertexAttrib4fARB;
+extern PFNGLVERTEXATTRIB4FVARBPROC glVertexAttrib4fvARB;
+extern PFNGLVERTEXATTRIB4IVARBPROC glVertexAttrib4ivARB;
+extern PFNGLVERTEXATTRIB4SARBPROC glVertexAttrib4sARB;
+extern PFNGLVERTEXATTRIB4SVARBPROC glVertexAttrib4svARB;
+extern PFNGLVERTEXATTRIB4UBVARBPROC glVertexAttrib4ubvARB;
+extern PFNGLVERTEXATTRIB4UIVARBPROC glVertexAttrib4uivARB;
+extern PFNGLVERTEXATTRIB4USVARBPROC glVertexAttrib4usvARB;
+extern PFNGLVERTEXATTRIBPOINTERARBPROC glVertexAttribPointerARB;
+extern PFNGLENABLEVERTEXATTRIBARRAYARBPROC glEnableVertexAttribArrayARB;
+extern PFNGLDISABLEVERTEXATTRIBARRAYARBPROC glDisableVertexAttribArrayARB;
+extern PFNGLPROGRAMSTRINGARBPROC glProgramStringARB;
+extern PFNGLBINDPROGRAMARBPROC glBindProgramARB;
+extern PFNGLDELETEPROGRAMSARBPROC glDeleteProgramsARB;
+extern PFNGLGENPROGRAMSARBPROC glGenProgramsARB;
+extern PFNGLPROGRAMENVPARAMETER4DARBPROC glProgramEnvParameter4dARB;
+extern PFNGLPROGRAMENVPARAMETER4DVARBPROC glProgramEnvParameter4dvARB;
+extern PFNGLPROGRAMENVPARAMETER4FARBPROC glProgramEnvParameter4fARB;
+extern PFNGLPROGRAMENVPARAMETER4FVARBPROC glProgramEnvParameter4fvARB;
+extern PFNGLPROGRAMLOCALPARAMETER4DARBPROC glProgramLocalParameter4dARB;
+extern PFNGLPROGRAMLOCALPARAMETER4DVARBPROC glProgramLocalParameter4dvARB;
+extern PFNGLPROGRAMLOCALPARAMETER4FARBPROC glProgramLocalParameter4fARB;
+extern PFNGLPROGRAMLOCALPARAMETER4FVARBPROC glProgramLocalParameter4fvARB;
+extern PFNGLGETPROGRAMENVPARAMETERDVARBPROC glGetProgramEnvParameterdvARB;
+extern PFNGLGETPROGRAMENVPARAMETERFVARBPROC glGetProgramEnvParameterfvARB;
+extern PFNGLGETPROGRAMLOCALPARAMETERDVARBPROC glGetProgramLocalParameterdvARB;
+extern PFNGLGETPROGRAMLOCALPARAMETERFVARBPROC glGetProgramLocalParameterfvARB;
+extern PFNGLGETPROGRAMIVARBPROC glGetProgramivARB;
+extern PFNGLGETPROGRAMSTRINGARBPROC glGetProgramStringARB;
+extern PFNGLGETVERTEXATTRIBDVARBPROC glGetVertexAttribdvARB;
+extern PFNGLGETVERTEXATTRIBFVARBPROC glGetVertexAttribfvARB;
+extern PFNGLGETVERTEXATTRIBIVARBPROC glGetVertexAttribivARB;
+extern PFNGLGETVERTEXATTRIBPOINTERVARBPROC glGetVertexAttribPointervARB;
+extern PFNGLISPROGRAMARBPROC glIsProgramARB;
+extern PFNGLBINDATTRIBLOCATIONARBPROC glBindAttribLocationARB;
+extern PFNGLGETACTIVEATTRIBARBPROC glGetActiveAttribARB;
+extern PFNGLGETATTRIBLOCATIONARBPROC glGetAttribLocationARB;
+
+//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;
+
+
+#elif LL_DARWIN
+//----------------------------------------------------------------------------
+// LL_DARWIN
+
+#include <OpenGL/gl.h>
+#include <OpenGL/glu.h>
+
+#define GL_EXT_separate_specular_color 1
+#include <OpenGL/glext.h>
+
+#include "GL/glh_extensions.h"
+
+// These symbols don't exist on 10.3.9, so they have to be declared weak. Redeclaring them here fixes the problem.
+// Note that they also must not be called on 10.3.9. This should be taken care of by a runtime check for the existence of the GL extension.
+#include <AvailabilityMacros.h>
+
+// GL_EXT_framebuffer_object
+extern GLboolean glIsRenderbufferEXT(GLuint renderbuffer) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+extern void glBindRenderbufferEXT(GLenum target, GLuint renderbuffer) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+extern void glDeleteRenderbuffersEXT(GLsizei n, const GLuint *renderbuffers) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+extern void glGenRenderbuffersEXT(GLsizei n, GLuint *renderbuffers) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+extern void glRenderbufferStorageEXT(GLenum target, GLenum internalformat, GLsizei width, GLsizei height) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+extern void glGetRenderbufferParameterivEXT(GLenum target, GLenum pname, GLint *params) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+extern GLboolean glIsFramebufferEXT(GLuint framebuffer) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+extern void glBindFramebufferEXT(GLenum target, GLuint framebuffer) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+extern void glDeleteFramebuffersEXT(GLsizei n, const GLuint *framebuffers) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+extern void glGenFramebuffersEXT(GLsizei n, GLuint *framebuffers) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+extern GLenum glCheckFramebufferStatusEXT(GLenum target) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+extern void glFramebufferTexture1DEXT(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+extern void glFramebufferTexture2DEXT(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+extern void glFramebufferTexture3DEXT(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+extern void glFramebufferRenderbufferEXT(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER;
+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;
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+//
+// Define vertex buffer object headers on Mac
+//
+#ifndef GL_ARB_vertex_buffer_object
+#define GL_BUFFER_SIZE_ARB 0x8764
+#define GL_BUFFER_USAGE_ARB 0x8765
+#define GL_ARRAY_BUFFER_ARB 0x8892
+#define GL_ELEMENT_ARRAY_BUFFER_ARB 0x8893
+#define GL_ARRAY_BUFFER_BINDING_ARB 0x8894
+#define GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB 0x8895
+#define GL_VERTEX_ARRAY_BUFFER_BINDING_ARB 0x8896
+#define GL_NORMAL_ARRAY_BUFFER_BINDING_ARB 0x8897
+#define GL_COLOR_ARRAY_BUFFER_BINDING_ARB 0x8898
+#define GL_INDEX_ARRAY_BUFFER_BINDING_ARB 0x8899
+#define GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING_ARB 0x889A
+#define GL_EDGE_FLAG_ARRAY_BUFFER_BINDING_ARB 0x889B
+#define GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING_ARB 0x889C
+#define GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING_ARB 0x889D
+#define GL_WEIGHT_ARRAY_BUFFER_BINDING_ARB 0x889E
+#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB 0x889F
+#define GL_READ_ONLY_ARB 0x88B8
+#define GL_WRITE_ONLY_ARB 0x88B9
+#define GL_READ_WRITE_ARB 0x88BA
+#define GL_BUFFER_ACCESS_ARB 0x88BB
+#define GL_BUFFER_MAPPED_ARB 0x88BC
+#define GL_BUFFER_MAP_POINTER_ARB 0x88BD
+#define GL_STREAM_DRAW_ARB 0x88E0
+#define GL_STREAM_READ_ARB 0x88E1
+#define GL_STREAM_COPY_ARB 0x88E2
+#define GL_STATIC_DRAW_ARB 0x88E4
+#define GL_STATIC_READ_ARB 0x88E5
+#define GL_STATIC_COPY_ARB 0x88E6
+#define GL_DYNAMIC_DRAW_ARB 0x88E8
+#define GL_DYNAMIC_READ_ARB 0x88E9
+#define GL_DYNAMIC_COPY_ARB 0x88EA
+#endif
+
+
+
+#ifndef GL_ARB_vertex_buffer_object
+/* GL types for handling large vertex buffer objects */
+typedef intptr_t GLintptrARB;
+typedef intptr_t GLsizeiptrARB;
+#endif
+
+
+#ifndef GL_ARB_vertex_buffer_object
+#define GL_ARB_vertex_buffer_object 1
+#ifdef GL_GLEXT_FUNCTION_POINTERS
+typedef void (* glBindBufferARBProcPtr) (GLenum target, GLuint buffer);
+typedef void (* glDeleteBufferARBProcPtr) (GLsizei n, const GLuint *buffers);
+typedef void (* glGenBuffersARBProcPtr) (GLsizei n, GLuint *buffers);
+typedef GLboolean (* glIsBufferARBProcPtr) (GLuint buffer);
+typedef void (* glBufferDataARBProcPtr) (GLenum target, GLsizeiptrARB size, const GLvoid *data, GLenum usage);
+typedef void (* glBufferSubDataARBProcPtr) (GLenum target, GLintptrARB offset, GLsizeiptrARB size, const GLvoid *data);
+typedef void (* glGetBufferSubDataARBProcPtr) (GLenum target, GLintptrARB offset, GLsizeiptrARB size, GLvoid *data);
+typedef GLvoid* (* glMapBufferARBProcPtr) (GLenum target, GLenum access); /* Flawfinder: ignore */
+typedef GLboolean (* glUnmapBufferARBProcPtr) (GLenum target);
+typedef void (* glGetBufferParameterivARBProcPtr) (GLenum target, GLenum pname, GLint *params);
+typedef void (* glGetBufferPointervARBProcPtr) (GLenum target, GLenum pname, GLvoid* *params);
+#else
+extern void glBindBufferARB (GLenum, GLuint);
+extern void glDeleteBuffersARB (GLsizei, const GLuint *);
+extern void glGenBuffersARB (GLsizei, GLuint *);
+extern GLboolean glIsBufferARB (GLuint);
+extern void glBufferDataARB (GLenum, GLsizeiptrARB, const GLvoid *, GLenum);
+extern void glBufferSubDataARB (GLenum, GLintptrARB, GLsizeiptrARB, const GLvoid *);
+extern void glGetBufferSubDataARB (GLenum, GLintptrARB, GLsizeiptrARB, GLvoid *);
+extern GLvoid* glMapBufferARB (GLenum, GLenum);
+extern GLboolean glUnmapBufferARB (GLenum);
+extern void glGetBufferParameterivARB (GLenum, GLenum, GLint *);
+extern void glGetBufferPointervARB (GLenum, GLenum, GLvoid* *);
+#endif /* GL_GLEXT_FUNCTION_POINTERS */
+#endif
+
+// May be needed for DARWIN...
+// #ifndef GL_ARB_compressed_tex_image
+// #define GL_ARB_compressed_tex_image 1
+// #ifdef GL_GLEXT_FUNCTION_POINTERS
+// typedef void (* glCompressedTexImage1D) (GLenum, GLint, GLenum, GLsizei, GLint, GLsizei, const GLvoid*);
+// typedef void (* glCompressedTexImage2D) (GLenum, GLint, GLenum, GLsizei, GLsizei, GLint, GLsizei, const GLvoid*);
+// typedef void (* glCompressedTexImage3D) (GLenum, GLint, GLenum, GLsizei, GLsizei, GLsizei, GLint, GLsizei, const GLvoid*);
+// typedef void (* glCompressedTexSubImage1D) (GLenum, GLint, GLint, GLsizei, GLenum, GLsizei, const GLvoid*);
+// typedef void (* glCompressedTexSubImage2D) (GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLsizei, const GLvoid*);
+// typedef void (* glCompressedTexSubImage3D) (GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLsizei, const GLvoid*);
+// typedef void (* glGetCompressedTexImage) (GLenum, GLint, GLvoid*);
+// #else
+// extern void glCompressedTexImage1D (GLenum, GLint, GLenum, GLsizei, GLint, GLsizei, const GLvoid*);
+// extern void glCompressedTexImage2D (GLenum, GLint, GLenum, GLsizei, GLsizei, GLint, GLsizei, const GLvoid*);
+// extern void glCompressedTexImage3D (GLenum, GLint, GLenum, GLsizei, GLsizei, GLsizei, GLint, GLsizei, const GLvoid*);
+// extern void glCompressedTexSubImage1D (GLenum, GLint, GLint, GLsizei, GLenum, GLsizei, const GLvoid*);
+// extern void glCompressedTexSubImage2D (GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLsizei, const GLvoid*);
+// extern void glCompressedTexSubImage3D (GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLsizei, const GLvoid*);
+// extern void glGetCompressedTexImage (GLenum, GLint, GLvoid*);
+// #endif /* GL_GLEXT_FUNCTION_POINTERS */
+// #endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#include <AGL/gl.h>
+
+#endif // LL_MESA / LL_WINDOWS / LL_DARWIN
+
+
+#endif // LL_LLGLHEADERS_H
diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp
new file mode 100644
index 0000000000..7b03944918
--- /dev/null
+++ b/indra/llrender/llglslshader.cpp
@@ -0,0 +1,823 @@
+/**
+ * @file llglslshader.cpp
+ * @brief GLSL helper functions and state.
+ *
+ * $LicenseInfo:firstyear=2005&license=viewergpl$
+ *
+ * Copyright (c) 2005-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$
+ */
+
+#include "linden_common.h"
+
+#include "llglslshader.h"
+
+#include "llshadermgr.h"
+#include "llfile.h"
+#include "llrender.h"
+
+#if LL_DARWIN
+#include "OpenGL/OpenGL.h"
+#endif
+
+#ifdef LL_RELEASE_FOR_DOWNLOAD
+#define UNIFORM_ERRS LL_WARNS_ONCE("Shader")
+#else
+#define UNIFORM_ERRS LL_ERRS("Shader")
+#endif
+
+// Lots of STL stuff in here, using namespace std to keep things more readable
+using std::vector;
+using std::pair;
+using std::make_pair;
+using std::string;
+
+BOOL shouldChange(const LLVector4& v1, const LLVector4& v2)
+{
+ return v1 != 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)
+{
+}
+
+//===============================
+// LLGLSL Shader implementation
+//===============================
+LLGLSLShader::LLGLSLShader()
+: mProgramObject(0), mShaderLevel(0), mShaderGroup(SG_DEFAULT)
+{
+}
+
+void LLGLSLShader::unload()
+{
+ stop_glerror();
+ mAttribute.clear();
+ mTexture.clear();
+ mUniform.clear();
+ mShaderFiles.clear();
+
+ if (mProgramObject)
+ {
+ GLhandleARB obj[1024];
+ GLsizei count;
+
+ glGetAttachedObjectsARB(mProgramObject, 1024, &count, obj);
+ for (GLsizei i = 0; i < count; i++)
+ {
+ glDeleteObjectARB(obj[i]);
+ }
+
+ glDeleteObjectARB(mProgramObject);
+
+ mProgramObject = 0;
+ }
+
+ //hack to make apple not complain
+ glGetError();
+
+ stop_glerror();
+}
+
+BOOL LLGLSLShader::createShader(vector<string> * attributes,
+ vector<string> * uniforms)
+{
+ llassert_always(!mShaderFiles.empty());
+ BOOL success = TRUE;
+
+ // Create program
+ mProgramObject = glCreateProgramObjectARB();
+
+ // Attach existing objects
+ if (!LLShaderMgr::instance()->attachShaderFeatures(this))
+ {
+ return FALSE;
+ }
+
+ vector< pair<string,GLenum> >::iterator fileIter = mShaderFiles.begin();
+ for ( ; fileIter != mShaderFiles.end(); fileIter++ )
+ {
+ GLhandleARB shaderhandle = LLShaderMgr::instance()->loadShaderFile((*fileIter).first, mShaderLevel, (*fileIter).second);
+ LL_DEBUGS("ShaderLoading") << "SHADER FILE: " << (*fileIter).first << " mShaderLevel=" << mShaderLevel << LL_ENDL;
+ if (mShaderLevel > 0)
+ {
+ attachObject(shaderhandle);
+ }
+ else
+ {
+ success = FALSE;
+ }
+ }
+
+ // Map attributes and uniforms
+ if (success)
+ {
+ success = mapAttributes(attributes);
+ }
+ if (success)
+ {
+ success = mapUniforms(uniforms);
+ }
+ if( !success )
+ {
+ LL_WARNS("ShaderLoading") << "Failed to link shader: " << mName << LL_ENDL;
+
+ // Try again using a lower shader level;
+ if (mShaderLevel > 0)
+ {
+ LL_WARNS("ShaderLoading") << "Failed to link using shader level " << mShaderLevel << " trying again using shader level " << (mShaderLevel - 1) << LL_ENDL;
+ mShaderLevel--;
+ return createShader(attributes,uniforms);
+ }
+ }
+ return success;
+}
+
+BOOL LLGLSLShader::attachObject(std::string object)
+{
+ if (LLShaderMgr::instance()->mShaderObjects.count(object) > 0)
+ {
+ stop_glerror();
+ glAttachObjectARB(mProgramObject, LLShaderMgr::instance()->mShaderObjects[object]);
+ stop_glerror();
+ return TRUE;
+ }
+ else
+ {
+ LL_WARNS("ShaderLoading") << "Attempting to attach shader object that hasn't been compiled: " << object << LL_ENDL;
+ return FALSE;
+ }
+}
+
+void LLGLSLShader::attachObject(GLhandleARB object)
+{
+ if (object != 0)
+ {
+ stop_glerror();
+ glAttachObjectARB(mProgramObject, object);
+ stop_glerror();
+ }
+ else
+ {
+ LL_WARNS("ShaderLoading") << "Attempting to attach non existing shader object. " << LL_ENDL;
+ }
+}
+
+void LLGLSLShader::attachObjects(GLhandleARB* objects, S32 count)
+{
+ for (S32 i = 0; i < count; i++)
+ {
+ attachObject(objects[i]);
+ }
+}
+
+BOOL LLGLSLShader::mapAttributes(const vector<string> * attributes)
+{
+ //link the program
+ BOOL res = link();
+
+ mAttribute.clear();
+ U32 numAttributes = (attributes == NULL) ? 0 : attributes->size();
+ mAttribute.resize(LLShaderMgr::instance()->mReservedAttribs.size() + numAttributes, -1);
+
+ if (res)
+ { //read back channel locations
+
+ //read back reserved channels first
+ for (U32 i = 0; i < (S32) LLShaderMgr::instance()->mReservedAttribs.size(); i++)
+ {
+ const char* name = LLShaderMgr::instance()->mReservedAttribs[i].c_str();
+ S32 index = glGetAttribLocationARB(mProgramObject, (const GLcharARB *)name);
+ if (index != -1)
+ {
+ mAttribute[i] = index;
+ LL_DEBUGS("ShaderLoading") << "Attribute " << name << " assigned to channel " << index << LL_ENDL;
+ }
+ }
+ if (attributes != NULL)
+ {
+ for (U32 i = 0; i < numAttributes; i++)
+ {
+ const char* name = (*attributes)[i].c_str();
+ S32 index = glGetAttribLocationARB(mProgramObject, name);
+ if (index != -1)
+ {
+ mAttribute[LLShaderMgr::instance()->mReservedAttribs.size() + i] = index;
+ LL_DEBUGS("ShaderLoading") << "Attribute " << name << " assigned to channel " << index << LL_ENDL;
+ }
+ }
+ }
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+void LLGLSLShader::mapUniform(GLint index, const vector<string> * uniforms)
+{
+ if (index == -1)
+ {
+ return;
+ }
+
+ GLenum type;
+ GLsizei length;
+ GLint size;
+ char name[1024]; /* Flawfinder: ignore */
+ name[0] = 0;
+
+ glGetActiveUniformARB(mProgramObject, index, 1024, &length, &size, &type, (GLcharARB *)name);
+ S32 location = glGetUniformLocationARB(mProgramObject, name);
+ if (location != -1)
+ {
+ mUniformMap[name] = location;
+ LL_DEBUGS("ShaderLoading") << "Uniform " << name << " is at location " << location << LL_ENDL;
+
+ //find the index of this uniform
+ for (S32 i = 0; i < (S32) LLShaderMgr::instance()->mReservedUniforms.size(); i++)
+ {
+ if ( (mUniform[i] == -1)
+ && (LLShaderMgr::instance()->mReservedUniforms[i].compare(0, length, name, LLShaderMgr::instance()->mReservedUniforms[i].length()) == 0))
+ {
+ //found it
+ mUniform[i] = location;
+ mTexture[i] = mapUniformTextureChannel(location, type);
+ return;
+ }
+ }
+
+ if (uniforms != NULL)
+ {
+ for (U32 i = 0; i < uniforms->size(); i++)
+ {
+ if ( (mUniform[i+LLShaderMgr::instance()->mReservedUniforms.size()] == -1)
+ && ((*uniforms)[i].compare(0, length, name, (*uniforms)[i].length()) == 0))
+ {
+ //found it
+ mUniform[i+LLShaderMgr::instance()->mReservedUniforms.size()] = location;
+ mTexture[i+LLShaderMgr::instance()->mReservedUniforms.size()] = mapUniformTextureChannel(location, type);
+ return;
+ }
+ }
+ }
+ }
+ }
+
+GLint LLGLSLShader::mapUniformTextureChannel(GLint location, GLenum type)
+{
+ if (type >= GL_SAMPLER_1D_ARB && type <= GL_SAMPLER_2D_RECT_SHADOW_ARB)
+ { //this here is a texture
+ glUniform1iARB(location, mActiveTextureChannels);
+ LL_DEBUGS("ShaderLoading") << "Assigned to texture channel " << mActiveTextureChannels << LL_ENDL;
+ return mActiveTextureChannels++;
+ }
+ return -1;
+}
+
+BOOL LLGLSLShader::mapUniforms(const vector<string> * uniforms)
+{
+ BOOL res = TRUE;
+
+ mActiveTextureChannels = 0;
+ mUniform.clear();
+ mUniformMap.clear();
+ mTexture.clear();
+ mValue.clear();
+ //initialize arrays
+ U32 numUniforms = (uniforms == NULL) ? 0 : uniforms->size();
+ mUniform.resize(numUniforms + LLShaderMgr::instance()->mReservedUniforms.size(), -1);
+ mTexture.resize(numUniforms + LLShaderMgr::instance()->mReservedUniforms.size(), -1);
+
+ bind();
+
+ //get the number of active uniforms
+ GLint activeCount;
+ glGetObjectParameterivARB(mProgramObject, GL_OBJECT_ACTIVE_UNIFORMS_ARB, &activeCount);
+
+ for (S32 i = 0; i < activeCount; i++)
+ {
+ mapUniform(i, uniforms);
+ }
+
+ unbind();
+
+ return res;
+}
+
+BOOL LLGLSLShader::link(BOOL suppress_errors)
+{
+ return LLShaderMgr::instance()->linkProgramObject(mProgramObject, suppress_errors);
+}
+
+void LLGLSLShader::bind()
+{
+ if (gGLManager.mHasShaderObjects)
+ {
+ glUseProgramObjectARB(mProgramObject);
+
+ if (mUniformsDirty)
+ {
+ LLShaderMgr::instance()->updateShaderUniforms(this);
+ mUniformsDirty = FALSE;
+ }
+ }
+}
+
+void LLGLSLShader::unbind()
+{
+ if (gGLManager.mHasShaderObjects)
+ {
+ for (U32 i = 0; i < mAttribute.size(); ++i)
+ {
+ vertexAttrib4f(i, 0,0,0,1);
+ }
+ glUseProgramObjectARB(0);
+ }
+}
+
+void LLGLSLShader::bindNoShader(void)
+{
+ glUseProgramObjectARB(0);
+}
+
+S32 LLGLSLShader::enableTexture(S32 uniform, S32 mode)
+{
+ if (uniform < 0 || uniform >= (S32)mTexture.size())
+ {
+ UNIFORM_ERRS << "Uniform out of range: " << uniform << LL_ENDL;
+ return -1;
+ }
+ S32 index = mTexture[uniform];
+ if (index != -1)
+ {
+ gGL.getTexUnit(index)->activate();
+ glEnable(mode);
+ }
+ return index;
+}
+
+S32 LLGLSLShader::disableTexture(S32 uniform, S32 mode)
+{
+ if (uniform < 0 || uniform >= (S32)mTexture.size())
+ {
+ UNIFORM_ERRS << "Uniform out of range: " << uniform << LL_ENDL;
+ return -1;
+ }
+ S32 index = mTexture[uniform];
+ if (index != -1)
+ {
+ gGL.getTexUnit(index)->activate();
+ glDisable(mode);
+ }
+ return index;
+}
+
+void LLGLSLShader::uniform1f(U32 index, GLfloat x)
+{
+ if (mProgramObject > 0)
+ {
+ if (mUniform.size() <= index)
+ {
+ UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL;
+ return;
+ }
+
+ if (mUniform[index] >= 0)
+ {
+ std::map<GLint, LLVector4>::iterator iter = mValue.find(mUniform[index]);
+ if (iter == mValue.end() || iter->second.mV[0] != x)
+ {
+ glUniform1fARB(mUniform[index], x);
+ mValue[mUniform[index]] = LLVector4(x,0.f,0.f,0.f);
+ }
+ }
+ }
+}
+
+void LLGLSLShader::uniform2f(U32 index, GLfloat x, GLfloat y)
+{
+ if (mProgramObject > 0)
+ {
+ if (mUniform.size() <= index)
+ {
+ UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL;
+ return;
+ }
+
+ if (mUniform[index] >= 0)
+ {
+ std::map<GLint, LLVector4>::iterator iter = mValue.find(mUniform[index]);
+ LLVector4 vec(x,y,0.f,0.f);
+ if (iter == mValue.end() || shouldChange(iter->second,vec))
+ {
+ glUniform2fARB(mUniform[index], x, y);
+ mValue[mUniform[index]] = vec;
+ }
+ }
+ }
+}
+
+void LLGLSLShader::uniform3f(U32 index, GLfloat x, GLfloat y, GLfloat z)
+{
+ if (mProgramObject > 0)
+ {
+ if (mUniform.size() <= index)
+ {
+ UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL;
+ return;
+ }
+
+ if (mUniform[index] >= 0)
+ {
+ std::map<GLint, LLVector4>::iterator iter = mValue.find(mUniform[index]);
+ LLVector4 vec(x,y,z,0.f);
+ if (iter == mValue.end() || shouldChange(iter->second,vec))
+ {
+ glUniform3fARB(mUniform[index], x, y, z);
+ mValue[mUniform[index]] = vec;
+ }
+ }
+ }
+}
+
+void LLGLSLShader::uniform4f(U32 index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+ if (mProgramObject > 0)
+ {
+ if (mUniform.size() <= index)
+ {
+ UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL;
+ return;
+ }
+
+ if (mUniform[index] >= 0)
+ {
+ std::map<GLint, LLVector4>::iterator iter = mValue.find(mUniform[index]);
+ LLVector4 vec(x,y,z,w);
+ if (iter == mValue.end() || shouldChange(iter->second,vec))
+ {
+ glUniform4fARB(mUniform[index], x, y, z, w);
+ mValue[mUniform[index]] = vec;
+ }
+ }
+ }
+}
+
+void LLGLSLShader::uniform1fv(U32 index, U32 count, const GLfloat* v)
+{
+ if (mProgramObject > 0)
+ {
+ if (mUniform.size() <= index)
+ {
+ UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL;
+ return;
+ }
+
+ if (mUniform[index] >= 0)
+ {
+ std::map<GLint, LLVector4>::iterator iter = mValue.find(mUniform[index]);
+ LLVector4 vec(v[0],0.f,0.f,0.f);
+ if (iter == mValue.end() || shouldChange(iter->second,vec) || count != 1)
+ {
+ glUniform1fvARB(mUniform[index], count, v);
+ mValue[mUniform[index]] = vec;
+ }
+ }
+ }
+}
+
+void LLGLSLShader::uniform2fv(U32 index, U32 count, const GLfloat* v)
+{
+ if (mProgramObject > 0)
+ {
+ if (mUniform.size() <= index)
+ {
+ UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL;
+ return;
+ }
+
+ if (mUniform[index] >= 0)
+ {
+ std::map<GLint, LLVector4>::iterator iter = mValue.find(mUniform[index]);
+ LLVector4 vec(v[0],v[1],0.f,0.f);
+ if (iter == mValue.end() || shouldChange(iter->second,vec) || count != 1)
+ {
+ glUniform2fvARB(mUniform[index], count, v);
+ mValue[mUniform[index]] = vec;
+ }
+ }
+ }
+}
+
+void LLGLSLShader::uniform3fv(U32 index, U32 count, const GLfloat* v)
+{
+ if (mProgramObject > 0)
+ {
+ if (mUniform.size() <= index)
+ {
+ UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL;
+ return;
+ }
+
+ if (mUniform[index] >= 0)
+ {
+ std::map<GLint, LLVector4>::iterator iter = mValue.find(mUniform[index]);
+ LLVector4 vec(v[0],v[1],v[2],0.f);
+ if (iter == mValue.end() || shouldChange(iter->second,vec) || count != 1)
+ {
+ glUniform3fvARB(mUniform[index], count, v);
+ mValue[mUniform[index]] = vec;
+ }
+ }
+ }
+}
+
+void LLGLSLShader::uniform4fv(U32 index, U32 count, const GLfloat* v)
+{
+ if (mProgramObject > 0)
+ {
+ if (mUniform.size() <= index)
+ {
+ UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL;
+ return;
+ }
+
+ if (mUniform[index] >= 0)
+ {
+ std::map<GLint, LLVector4>::iterator iter = mValue.find(mUniform[index]);
+ LLVector4 vec(v[0],v[1],v[2],v[3]);
+ if (iter == mValue.end() || shouldChange(iter->second,vec) || count != 1)
+ {
+ glUniform4fvARB(mUniform[index], count, v);
+ mValue[mUniform[index]] = vec;
+ }
+ }
+ }
+}
+
+void LLGLSLShader::uniformMatrix2fv(U32 index, U32 count, GLboolean transpose, const GLfloat *v)
+{
+ if (mProgramObject > 0)
+ {
+ if (mUniform.size() <= index)
+ {
+ UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL;
+ return;
+ }
+
+ if (mUniform[index] >= 0)
+ {
+ glUniformMatrix2fvARB(mUniform[index], count, transpose, v);
+ }
+ }
+}
+
+void LLGLSLShader::uniformMatrix3fv(U32 index, U32 count, GLboolean transpose, const GLfloat *v)
+{
+ if (mProgramObject > 0)
+ {
+ if (mUniform.size() <= index)
+ {
+ UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL;
+ return;
+ }
+
+ if (mUniform[index] >= 0)
+ {
+ glUniformMatrix3fvARB(mUniform[index], count, transpose, v);
+ }
+ }
+}
+
+void LLGLSLShader::uniformMatrix4fv(U32 index, U32 count, GLboolean transpose, const GLfloat *v)
+{
+ if (mProgramObject > 0)
+ {
+ if (mUniform.size() <= index)
+ {
+ UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL;
+ return;
+ }
+
+ if (mUniform[index] >= 0)
+ {
+ glUniformMatrix4fvARB(mUniform[index], count, transpose, v);
+ }
+ }
+}
+
+GLint LLGLSLShader::getUniformLocation(const string& uniform)
+{
+ 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;
+ }
+ }
+
+ return -1;
+}
+
+void LLGLSLShader::uniform1f(const string& uniform, GLfloat v)
+{
+ GLint location = getUniformLocation(uniform);
+
+ if (location >= 0)
+ {
+ std::map<GLint, LLVector4>::iterator iter = mValue.find(location);
+ LLVector4 vec(v,0.f,0.f,0.f);
+ if (iter == mValue.end() || shouldChange(iter->second,vec))
+ {
+ glUniform1fARB(location, v);
+ mValue[location] = vec;
+ }
+ }
+}
+
+void LLGLSLShader::uniform2f(const string& uniform, GLfloat x, GLfloat y)
+{
+ GLint location = getUniformLocation(uniform);
+
+ if (location >= 0)
+ {
+ std::map<GLint, LLVector4>::iterator iter = mValue.find(location);
+ LLVector4 vec(x,y,0.f,0.f);
+ if (iter == mValue.end() || shouldChange(iter->second,vec))
+ {
+ glUniform2fARB(location, x,y);
+ mValue[location] = vec;
+ }
+ }
+
+}
+
+void LLGLSLShader::uniform3f(const string& uniform, GLfloat x, GLfloat y, GLfloat z)
+{
+ GLint location = getUniformLocation(uniform);
+
+ if (location >= 0)
+ {
+ std::map<GLint, LLVector4>::iterator iter = mValue.find(location);
+ LLVector4 vec(x,y,z,0.f);
+ if (iter == mValue.end() || shouldChange(iter->second,vec))
+ {
+ glUniform3fARB(location, x,y,z);
+ mValue[location] = vec;
+ }
+ }
+}
+
+void LLGLSLShader::uniform4f(const string& uniform, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+ GLint location = getUniformLocation(uniform);
+
+ if (location >= 0)
+ {
+ std::map<GLint, LLVector4>::iterator iter = mValue.find(location);
+ LLVector4 vec(x,y,z,w);
+ if (iter == mValue.end() || shouldChange(iter->second,vec))
+ {
+ glUniform4fARB(location, x,y,z,w);
+ mValue[location] = vec;
+ }
+ }
+}
+
+void LLGLSLShader::uniform1fv(const string& uniform, U32 count, const GLfloat* v)
+{
+ GLint location = getUniformLocation(uniform);
+
+ if (location >= 0)
+ {
+ std::map<GLint, LLVector4>::iterator iter = mValue.find(location);
+ LLVector4 vec(v[0],0.f,0.f,0.f);
+ if (iter == mValue.end() || shouldChange(iter->second,vec) || count != 1)
+ {
+ glUniform1fvARB(location, count, v);
+ mValue[location] = vec;
+ }
+ }
+}
+
+void LLGLSLShader::uniform2fv(const string& uniform, U32 count, const GLfloat* v)
+{
+ GLint location = getUniformLocation(uniform);
+
+ if (location >= 0)
+ {
+ std::map<GLint, LLVector4>::iterator iter = mValue.find(location);
+ LLVector4 vec(v[0],v[1],0.f,0.f);
+ if (iter == mValue.end() || shouldChange(iter->second,vec) || count != 1)
+ {
+ glUniform2fvARB(location, count, v);
+ mValue[location] = vec;
+ }
+ }
+}
+
+void LLGLSLShader::uniform3fv(const string& uniform, U32 count, const GLfloat* v)
+{
+ GLint location = getUniformLocation(uniform);
+
+ if (location >= 0)
+ {
+ std::map<GLint, LLVector4>::iterator iter = mValue.find(location);
+ LLVector4 vec(v[0],v[1],v[2],0.f);
+ if (iter == mValue.end() || shouldChange(iter->second,vec) || count != 1)
+ {
+ glUniform3fvARB(location, count, v);
+ mValue[location] = vec;
+ }
+ }
+}
+
+void LLGLSLShader::uniform4fv(const string& uniform, U32 count, const GLfloat* v)
+{
+ GLint location = getUniformLocation(uniform);
+
+ if (location >= 0)
+ {
+ LLVector4 vec(v);
+ std::map<GLint, LLVector4>::iterator iter = mValue.find(location);
+ if (iter == mValue.end() || shouldChange(iter->second,vec) || count != 1)
+ {
+ glUniform4fvARB(location, count, v);
+ mValue[location] = vec;
+ }
+ }
+}
+
+void LLGLSLShader::uniformMatrix2fv(const string& uniform, U32 count, GLboolean transpose, const GLfloat* v)
+{
+ GLint location = getUniformLocation(uniform);
+
+ if (location >= 0)
+ {
+ glUniformMatrix2fvARB(location, count, transpose, v);
+ }
+}
+
+void LLGLSLShader::uniformMatrix3fv(const string& uniform, U32 count, GLboolean transpose, const GLfloat* v)
+{
+ GLint location = getUniformLocation(uniform);
+
+ if (location >= 0)
+ {
+ glUniformMatrix3fvARB(location, count, transpose, v);
+ }
+}
+
+void LLGLSLShader::uniformMatrix4fv(const string& uniform, U32 count, GLboolean transpose, const GLfloat* v)
+{
+ GLint location = getUniformLocation(uniform);
+
+ if (location >= 0)
+ {
+ glUniformMatrix4fvARB(location, count, transpose, v);
+ }
+}
+
+
+void LLGLSLShader::vertexAttrib4f(U32 index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+ if (mAttribute[index] > 0)
+ {
+ glVertexAttrib4fARB(mAttribute[index], x, y, z, w);
+ }
+}
+
+void LLGLSLShader::vertexAttrib4fv(U32 index, GLfloat* v)
+{
+ if (mAttribute[index] > 0)
+ {
+ glVertexAttrib4fvARB(mAttribute[index], v);
+ }
+}
diff --git a/indra/llrender/llglslshader.h b/indra/llrender/llglslshader.h
new file mode 100644
index 0000000000..c78188ba87
--- /dev/null
+++ b/indra/llrender/llglslshader.h
@@ -0,0 +1,139 @@
+/**
+ * @file llglslshader.h
+ * @brief GLSL shader wrappers
+ *
+ * $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$
+ */
+
+#ifndef LL_LLGLSLSHADER_H
+#define LL_LLGLSLSHADER_H
+
+#include "llgl.h"
+
+class LLShaderFeatures
+{
+public:
+ bool calculatesLighting;
+ bool calculatesAtmospherics;
+ bool hasLighting; // implies no transport (it's possible to have neither though)
+ bool isShiny;
+ bool isFullbright; // implies no lighting
+ bool isSpecular;
+ bool hasWaterFog; // implies no gamma
+ bool hasTransport; // implies no lighting (it's possible to have neither though)
+ bool hasSkinning;
+ bool hasAtmospherics;
+ bool hasGamma;
+
+ // char numLights;
+
+ LLShaderFeatures();
+};
+
+class LLGLSLShader
+{
+public:
+
+ enum
+ {
+ SG_DEFAULT = 0,
+ SG_SKY,
+ SG_WATER
+ };
+
+ LLGLSLShader();
+
+ void unload();
+ BOOL createShader(std::vector<std::string> * attributes,
+ std::vector<std::string> * uniforms);
+ BOOL attachObject(std::string object);
+ void attachObject(GLhandleARB object);
+ void attachObjects(GLhandleARB* objects = NULL, S32 count = 0);
+ BOOL mapAttributes(const std::vector<std::string> * attributes);
+ BOOL mapUniforms(const std::vector<std::string> * uniforms);
+ void mapUniform(GLint index, const std::vector<std::string> * uniforms);
+ void uniform1f(U32 index, GLfloat v);
+ void uniform2f(U32 index, GLfloat x, GLfloat y);
+ void uniform3f(U32 index, GLfloat x, GLfloat y, GLfloat z);
+ void uniform4f(U32 index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+ void uniform1fv(U32 index, U32 count, const GLfloat* v);
+ void uniform2fv(U32 index, U32 count, const GLfloat* v);
+ void uniform3fv(U32 index, U32 count, const GLfloat* v);
+ void uniform4fv(U32 index, U32 count, const GLfloat* v);
+ void uniform1f(const std::string& uniform, GLfloat v);
+ void uniform2f(const std::string& uniform, GLfloat x, GLfloat y);
+ void uniform3f(const std::string& uniform, GLfloat x, GLfloat y, GLfloat z);
+ void uniform4f(const std::string& uniform, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+ void uniform1fv(const std::string& uniform, U32 count, const GLfloat* v);
+ void uniform2fv(const std::string& uniform, U32 count, const GLfloat* v);
+ void uniform3fv(const std::string& uniform, U32 count, const GLfloat* v);
+ void uniform4fv(const std::string& uniform, U32 count, const GLfloat* v);
+ void uniformMatrix2fv(U32 index, U32 count, GLboolean transpose, const GLfloat *v);
+ void uniformMatrix3fv(U32 index, U32 count, GLboolean transpose, const GLfloat *v);
+ void uniformMatrix4fv(U32 index, U32 count, GLboolean transpose, const GLfloat *v);
+ void uniformMatrix2fv(const std::string& uniform, U32 count, GLboolean transpose, const GLfloat *v);
+ void uniformMatrix3fv(const std::string& uniform, U32 count, GLboolean transpose, const GLfloat *v);
+ void uniformMatrix4fv(const std::string& uniform, U32 count, GLboolean transpose, const GLfloat *v);
+
+ void vertexAttrib4f(U32 index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+ void vertexAttrib4fv(U32 index, GLfloat* v);
+
+ GLint getUniformLocation(const std::string& uniform);
+
+ GLint mapUniformTextureChannel(GLint location, GLenum type);
+
+
+ //enable/disable texture channel for specified uniform
+ //if given texture uniform is active in the shader,
+ //the corresponding channel will be active upon return
+ //returns channel texture is enabled in from [0-MAX)
+ S32 enableTexture(S32 uniform, S32 mode = GL_TEXTURE_2D);
+ S32 disableTexture(S32 uniform, S32 mode = GL_TEXTURE_2D);
+
+ BOOL link(BOOL suppress_errors = FALSE);
+ void bind();
+ void unbind();
+
+ // Unbinds any previously bound shader by explicitly binding no shader.
+ static void bindNoShader(void);
+
+ GLhandleARB mProgramObject;
+ std::vector<GLint> mAttribute; //lookup table of attribute enum to attribute channel
+ std::vector<GLint> mUniform; //lookup table of uniform enum to uniform location
+ std::map<std::string, GLint> mUniformMap; //lookup map of uniform name to uniform location
+ std::map<GLint, LLVector4> mValue; //lookup map of uniform location to last known value
+ std::vector<GLint> mTexture;
+ S32 mActiveTextureChannels;
+ S32 mShaderLevel;
+ S32 mShaderGroup;
+ BOOL mUniformsDirty;
+ LLShaderFeatures mFeatures;
+ std::vector< std::pair< std::string, GLenum > > mShaderFiles;
+ std::string mName;
+};
+
+#endif
diff --git a/indra/llrender/llglstates.h b/indra/llrender/llglstates.h
new file mode 100644
index 0000000000..907e4ee2e6
--- /dev/null
+++ b/indra/llrender/llglstates.h
@@ -0,0 +1,302 @@
+/**
+ * @file llglstates.h
+ * @brief LLGL states definitions
+ *
+ * $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 HEADER SHOULD ONLY BE INCLUDED FROM llgl.h
+#ifndef LL_LLGLSTATES_H
+#define LL_LLGLSTATES_H
+
+#include "llimagegl.h"
+
+//----------------------------------------------------------------------------
+
+class LLGLDepthTest
+{
+ // Enabled by default
+public:
+ LLGLDepthTest(GLboolean depth_enabled, GLboolean write_enabled = GL_TRUE, GLenum depth_func = GL_LEQUAL);
+
+ ~LLGLDepthTest();
+
+ GLboolean mPrevDepthEnabled;
+ GLenum mPrevDepthFunc;
+ GLboolean mPrevWriteEnabled;
+private:
+ static GLboolean sDepthEnabled; // defaults to GL_FALSE
+ static GLenum sDepthFunc; // defaults to GL_LESS
+ static GLboolean sWriteEnabled; // defaults to GL_TRUE
+};
+
+//----------------------------------------------------------------------------
+
+class LLGLSDefault
+{
+protected:
+ LLGLEnable mColorMaterial;
+ LLGLDisable mAlphaTest, mBlend, mCullFace, mDither, mFog,
+ mLineSmooth, mLineStipple, mNormalize, mPolygonSmooth,
+ mTextureGenQ, mTextureGenR, mTextureGenS, mTextureGenT,
+ mGLMultisample;
+public:
+ LLGLSDefault()
+ :
+ // Enable
+ mColorMaterial(GL_COLOR_MATERIAL),
+ // Disable
+ mAlphaTest(GL_ALPHA_TEST),
+ mBlend(GL_BLEND),
+ mCullFace(GL_CULL_FACE),
+ mDither(GL_DITHER),
+ mFog(GL_FOG),
+ mLineSmooth(GL_LINE_SMOOTH),
+ mLineStipple(GL_LINE_STIPPLE),
+ mNormalize(GL_NORMALIZE),
+ mPolygonSmooth(GL_POLYGON_SMOOTH),
+ mTextureGenQ(GL_TEXTURE_GEN_Q),
+ mTextureGenR(GL_TEXTURE_GEN_R),
+ mTextureGenS(GL_TEXTURE_GEN_S),
+ mTextureGenT(GL_TEXTURE_GEN_T),
+ mGLMultisample(GL_MULTISAMPLE_ARB)
+ { }
+};
+
+class LLGLSNoTexture
+{
+public:
+ LLGLSNoTexture()
+ { LLImageGL::unbindTexture(0); }
+};
+
+class LLGLSObjectSelect
+{
+protected:
+ LLGLDisable mBlend, mFog, mAlphaTest;
+ LLGLEnable mCullFace;
+public:
+ LLGLSObjectSelect()
+ : mBlend(GL_BLEND), mFog(GL_FOG),
+ mAlphaTest(GL_ALPHA_TEST),
+ mCullFace(GL_CULL_FACE)
+ { LLImageGL::unbindTexture(0); }
+};
+
+class LLGLSObjectSelectAlpha
+{
+protected:
+ LLGLEnable mAlphaTest;
+public:
+ LLGLSObjectSelectAlpha()
+ : mAlphaTest(GL_ALPHA_TEST)
+ {}
+};
+
+//----------------------------------------------------------------------------
+
+class LLGLSUIDefault
+{
+protected:
+ LLGLEnable mBlend, mAlphaTest;
+ LLGLDisable mCullFace;
+ LLGLDepthTest mDepthTest;
+public:
+ LLGLSUIDefault()
+ : mBlend(GL_BLEND), mAlphaTest(GL_ALPHA_TEST),
+ mCullFace(GL_CULL_FACE),
+ mDepthTest(GL_FALSE, GL_TRUE, GL_LEQUAL)
+ {}
+};
+
+class LLGLSNoAlphaTest // : public LLGLSUIDefault
+{
+protected:
+ LLGLDisable mAlphaTest;
+public:
+ LLGLSNoAlphaTest()
+ : mAlphaTest(GL_ALPHA_TEST)
+ {}
+};
+
+class LLGLSNoTextureNoAlphaTest // : public LLGLSUIDefault
+{
+protected:
+ LLGLDisable mAlphaTest;
+public:
+ LLGLSNoTextureNoAlphaTest()
+ : mAlphaTest(GL_ALPHA_TEST)
+
+ { LLImageGL::unbindTexture(0); }
+};
+
+//----------------------------------------------------------------------------
+
+class LLGLSFog
+{
+protected:
+ LLGLEnable mFog;
+public:
+ LLGLSFog()
+ : mFog(GL_FOG)
+ {}
+};
+
+class LLGLSNoFog
+{
+protected:
+ LLGLDisable mFog;
+public:
+ LLGLSNoFog()
+ : mFog(GL_FOG)
+ {}
+};
+
+//----------------------------------------------------------------------------
+
+class LLGLSPipeline
+{
+protected:
+ LLGLEnable mCullFace;
+ LLGLDepthTest mDepthTest;
+public:
+ LLGLSPipeline()
+ : mCullFace(GL_CULL_FACE),
+ mDepthTest(GL_TRUE, GL_TRUE, GL_LEQUAL)
+ { }
+};
+
+class LLGLSPipelineAlpha // : public LLGLSPipeline
+{
+protected:
+ LLGLEnable mBlend, mAlphaTest;
+public:
+ LLGLSPipelineAlpha()
+ : mBlend(GL_BLEND),
+ mAlphaTest(GL_ALPHA_TEST)
+ { }
+};
+
+class LLGLSPipelineEmbossBump
+{
+protected:
+ LLGLDisable mFog;
+public:
+ LLGLSPipelineEmbossBump()
+ : mFog(GL_FOG)
+ { }
+};
+
+class LLGLSPipelineSelection
+{
+protected:
+ LLGLDisable mCullFace;
+public:
+ LLGLSPipelineSelection()
+ : mCullFace(GL_CULL_FACE)
+ {}
+};
+
+class LLGLSPipelineAvatar
+{
+protected:
+ LLGLEnable mNormalize;
+public:
+ LLGLSPipelineAvatar()
+ : mNormalize(GL_NORMALIZE)
+ {}
+};
+
+class LLGLSPipelineSkyBox
+{
+protected:
+ LLGLDisable mAlphaTest, mCullFace, mFog;
+public:
+ LLGLSPipelineSkyBox()
+ : mAlphaTest(GL_ALPHA_TEST), mCullFace(GL_CULL_FACE), mFog(GL_FOG)
+ { }
+};
+
+class LLGLSTracker
+{
+protected:
+ LLGLEnable mCullFace, mBlend, mAlphaTest;
+public:
+ LLGLSTracker() :
+ mCullFace(GL_CULL_FACE),
+ mBlend(GL_BLEND),
+ mAlphaTest(GL_ALPHA_TEST)
+
+ { LLImageGL::unbindTexture(0); }
+};
+
+//----------------------------------------------------------------------------
+
+class LLGLSSpecular
+{
+public:
+ LLGLSSpecular(const LLColor4& color, F32 shininess)
+ {
+ if (shininess > 0.0f)
+ {
+ glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, color.mV);
+ S32 shiny = (S32)(shininess*128.f);
+ shiny = llclamp(shiny,0,128);
+ glMateriali(GL_FRONT_AND_BACK, GL_SHININESS, shiny);
+ }
+ }
+ ~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);
+ }
+};
+
+//----------------------------------------------------------------------------
+
+
+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/llgltypes.h b/indra/llrender/llgltypes.h
new file mode 100644
index 0000000000..42050cf90f
--- /dev/null
+++ b/indra/llrender/llgltypes.h
@@ -0,0 +1,44 @@
+/**
+ * @file llgltypes.h
+ * @brief LLGL definition
+ *
+ * $LicenseInfo:firstyear=2006&license=viewergpl$
+ *
+ * Copyright (c) 2006-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$
+ */
+
+#ifndef LLGLTYPES_H
+#define LLGLTYPES_H
+
+#define MAX_GL_TEXTURE_UNITS 16
+
+typedef U32 LLGLenum;
+typedef U32 LLGLuint;
+typedef S32 LLGLint;
+typedef F32 LLGLfloat;
+typedef F64 LLGLdouble;
+typedef U8 LLGLboolean;
+
+#endif
diff --git a/indra/llrender/llpostprocess.cpp b/indra/llrender/llpostprocess.cpp
new file mode 100644
index 0000000000..7c14b57fff
--- /dev/null
+++ b/indra/llrender/llpostprocess.cpp
@@ -0,0 +1,574 @@
+/**
+ * @file llpostprocess.cpp
+ * @brief LLPostProcess class implementation
+ *
+ * $LicenseInfo:firstyear=2007&license=viewergpl$
+ *
+ * Copyright (c) 2007-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$
+ */
+
+#include "linden_common.h"
+
+#include "llpostprocess.h"
+#include "llglslshader.h"
+#include "llsdserialize.h"
+#include "llrender.h"
+
+
+LLPostProcess * gPostProcess = NULL;
+
+
+static const unsigned int NOISE_SIZE = 512;
+
+/// CALCULATING LUMINANCE (Using NTSC lum weights)
+/// http://en.wikipedia.org/wiki/Luma_%28video%29
+static const float LUMINANCE_R = 0.299f;
+static const float LUMINANCE_G = 0.587f;
+static const float LUMINANCE_B = 0.114f;
+
+static const char * const XML_FILENAME = "postprocesseffects.xml";
+
+LLPostProcess::LLPostProcess(void) :
+ sceneRenderTexture(0), noiseTexture(0),
+ tempBloomTexture(0),
+ initialized(false),
+ mAllEffects(LLSD::emptyMap()),
+ screenW(1), screenH(1)
+{
+ /* Do nothing. Needs to be updated to use our current shader system, and to work with the move into llrender.
+ std::string pathName(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "windlight", XML_FILENAME));
+ LL_DEBUGS2("AppInit", "Shaders") << "Loading PostProcess Effects settings from " << pathName << LL_ENDL;
+
+ llifstream effectsXML(pathName);
+
+ if (effectsXML)
+ {
+ LLPointer<LLSDParser> parser = new LLSDXMLParser();
+
+ parser->parse(effectsXML, mAllEffects, LLSDSerialize::SIZE_UNLIMITED);
+ }
+
+ if (!mAllEffects.has("default"))
+ {
+ LLSD & defaultEffect = (mAllEffects["default"] = LLSD::emptyMap());
+
+ defaultEffect["enable_night_vision"] = LLSD::Boolean(false);
+ defaultEffect["enable_bloom"] = LLSD::Boolean(false);
+ defaultEffect["enable_color_filter"] = LLSD::Boolean(false);
+
+ /// NVG Defaults
+ defaultEffect["brightness_multiplier"] = 3.0;
+ defaultEffect["noise_size"] = 25.0;
+ defaultEffect["noise_strength"] = 0.4;
+
+ // TODO BTest potentially add this to tweaks?
+ noiseTextureScale = 1.0f;
+
+ /// Bloom Defaults
+ defaultEffect["extract_low"] = 0.95;
+ defaultEffect["extract_high"] = 1.0;
+ defaultEffect["bloom_width"] = 2.25;
+ defaultEffect["bloom_strength"] = 1.5;
+
+ /// Color Filter Defaults
+ defaultEffect["brightness"] = 1.0;
+ defaultEffect["contrast"] = 1.0;
+ defaultEffect["saturation"] = 1.0;
+
+ LLSD& contrastBase = (defaultEffect["contrast_base"] = LLSD::emptyArray());
+ contrastBase.append(1.0);
+ contrastBase.append(1.0);
+ contrastBase.append(1.0);
+ contrastBase.append(0.5);
+ }
+
+ setSelectedEffect("default");
+ */
+}
+
+LLPostProcess::~LLPostProcess(void)
+{
+ glDeleteTextures(1, &sceneRenderTexture);
+ glDeleteTextures(1, &noiseTexture);
+ glDeleteTextures(1, &tempBloomTexture);
+}
+
+// static
+void LLPostProcess::initClass(void)
+{
+ //this will cause system to crash at second time login
+ //if first time login fails due to network connection --- bao
+ //***llassert_always(gPostProcess == NULL);
+ //replaced by the following line:
+ if(gPostProcess)
+ return ;
+
+
+ gPostProcess = new LLPostProcess();
+}
+
+// static
+void LLPostProcess::cleanupClass()
+{
+ delete gPostProcess;
+ gPostProcess = NULL;
+}
+
+void LLPostProcess::setSelectedEffect(std::string const & effectName)
+{
+ mSelectedEffectName = effectName;
+ static_cast<LLSD &>(tweaks) = mAllEffects[effectName];
+}
+
+void LLPostProcess::saveEffect(std::string const & effectName)
+{
+ /* Do nothing. Needs to be updated to use our current shader system, and to work with the move into llrender.
+ mAllEffects[effectName] = tweaks;
+
+ std::string pathName(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "windlight", XML_FILENAME));
+ //llinfos << "Saving PostProcess Effects settings to " << pathName << llendl;
+
+ llofstream effectsXML(pathName);
+
+ LLPointer<LLSDFormatter> formatter = new LLSDXMLFormatter();
+
+ formatter->format(mAllEffects, effectsXML);
+ */
+}
+
+void LLPostProcess::apply(unsigned int width, unsigned int height)
+{
+ if (!initialized || width != screenW || height != screenH){
+ initialize(width, height);
+ }
+ if (shadersEnabled()){
+ doEffects();
+ }
+}
+
+void LLPostProcess::initialize(unsigned int width, unsigned int height)
+{
+ screenW = width;
+ screenH = height;
+ createTexture(sceneRenderTexture, screenW, screenH);
+ initialized = true;
+
+ checkError();
+ createNightVisionShader();
+ createBloomShader();
+ createColorFilterShader();
+ checkError();
+}
+
+inline bool LLPostProcess::shadersEnabled(void)
+{
+ return (tweaks.useColorFilter().asBoolean() ||
+ tweaks.useNightVisionShader().asBoolean() ||
+ tweaks.useBloomShader().asBoolean() );
+
+}
+
+void LLPostProcess::applyShaders(void)
+{
+ if (tweaks.useColorFilter()){
+ applyColorFilterShader();
+ checkError();
+ }
+ if (tweaks.useNightVisionShader()){
+ /// If any of the above shaders have been called update the frame buffer;
+ if (tweaks.useColorFilter()){
+ copyFrameBuffer(sceneRenderTexture, screenW, screenH);
+ }
+ applyNightVisionShader();
+ checkError();
+ }
+ if (tweaks.useBloomShader()){
+ /// If any of the above shaders have been called update the frame buffer;
+ if (tweaks.useColorFilter().asBoolean() || tweaks.useNightVisionShader().asBoolean()){
+ copyFrameBuffer(sceneRenderTexture, screenW, screenH);
+ }
+ applyBloomShader();
+ checkError();
+ }
+}
+
+void LLPostProcess::applyColorFilterShader(void)
+{
+ /* Do nothing. Needs to be updated to use our current shader system, and to work with the move into llrender.
+ gPostColorFilterProgram.bind();
+
+ gGL.getTexUnit(0)->activate();
+ glEnable(GL_TEXTURE_RECTANGLE_ARB);
+
+ glBindTexture(GL_TEXTURE_RECTANGLE_ARB, sceneRenderTexture);
+
+ getShaderUniforms(colorFilterUniforms, gPostColorFilterProgram.mProgramObject);
+ glUniform1iARB(colorFilterUniforms["RenderTexture"], 0);
+ glUniform1fARB(colorFilterUniforms["brightness"], tweaks.getBrightness());
+ glUniform1fARB(colorFilterUniforms["contrast"], tweaks.getContrast());
+ float baseI = (tweaks.getContrastBaseR() + tweaks.getContrastBaseG() + tweaks.getContrastBaseB()) / 3.0f;
+ baseI = tweaks.getContrastBaseIntensity() / ((baseI < 0.001f) ? 0.001f : baseI);
+ float baseR = tweaks.getContrastBaseR() * baseI;
+ float baseG = tweaks.getContrastBaseG() * baseI;
+ float baseB = tweaks.getContrastBaseB() * baseI;
+ glUniform3fARB(colorFilterUniforms["contrastBase"], baseR, baseG, baseB);
+ glUniform1fARB(colorFilterUniforms["saturation"], tweaks.getSaturation());
+ glUniform3fARB(colorFilterUniforms["lumWeights"], LUMINANCE_R, LUMINANCE_G, LUMINANCE_B);
+
+ LLGLEnable blend(GL_BLEND);
+ gGL.setSceneBlendType(LLRender::BT_REPLACE);
+ LLGLDepthTest depth(GL_FALSE);
+
+ /// Draw a screen space quad
+ drawOrthoQuad(screenW, screenH, QUAD_NORMAL);
+ gPostColorFilterProgram.unbind();
+ */
+}
+
+void LLPostProcess::createColorFilterShader(void)
+{
+ /// Define uniform names
+ colorFilterUniforms["RenderTexture"] = 0;
+ colorFilterUniforms["brightness"] = 0;
+ colorFilterUniforms["contrast"] = 0;
+ colorFilterUniforms["contrastBase"] = 0;
+ colorFilterUniforms["saturation"] = 0;
+ colorFilterUniforms["lumWeights"] = 0;
+}
+
+void LLPostProcess::applyNightVisionShader(void)
+{
+ /* Do nothing. Needs to be updated to use our current shader system, and to work with the move into llrender.
+ gPostNightVisionProgram.bind();
+
+ gGL.getTexUnit(0)->activate();
+ glEnable(GL_TEXTURE_RECTANGLE_ARB);
+
+ getShaderUniforms(nightVisionUniforms, gPostNightVisionProgram.mProgramObject);
+ glBindTexture(GL_TEXTURE_RECTANGLE_ARB, sceneRenderTexture);
+ glUniform1iARB(nightVisionUniforms["RenderTexture"], 0);
+
+ gGL.getTexUnit(1)->activate();
+ glEnable(GL_TEXTURE_2D);
+
+ glBindTexture(GL_TEXTURE_2D, noiseTexture);
+ glUniform1iARB(nightVisionUniforms["NoiseTexture"], 1);
+
+
+ glUniform1fARB(nightVisionUniforms["brightMult"], tweaks.getBrightMult());
+ glUniform1fARB(nightVisionUniforms["noiseStrength"], tweaks.getNoiseStrength());
+ noiseTextureScale = 0.01f + ((101.f - tweaks.getNoiseSize()) / 100.f);
+ noiseTextureScale *= (screenH / NOISE_SIZE);
+
+
+ glUniform3fARB(nightVisionUniforms["lumWeights"], LUMINANCE_R, LUMINANCE_G, LUMINANCE_B);
+
+ LLGLEnable blend(GL_BLEND);
+ gGL.setSceneBlendType(LLRender::BT_REPLACE);
+ LLGLDepthTest depth(GL_FALSE);
+
+ /// Draw a screen space quad
+ drawOrthoQuad(screenW, screenH, QUAD_NOISE);
+ gPostNightVisionProgram.unbind();
+ gGL.getTexUnit(0)->activate();
+ */
+}
+
+void LLPostProcess::createNightVisionShader(void)
+{
+ /// Define uniform names
+ nightVisionUniforms["RenderTexture"] = 0;
+ nightVisionUniforms["NoiseTexture"] = 0;
+ nightVisionUniforms["brightMult"] = 0;
+ nightVisionUniforms["noiseStrength"] = 0;
+ nightVisionUniforms["lumWeights"] = 0;
+
+ createNoiseTexture(noiseTexture);
+}
+
+void LLPostProcess::applyBloomShader(void)
+{
+
+}
+
+void LLPostProcess::createBloomShader(void)
+{
+ createTexture(tempBloomTexture, unsigned(screenW * 0.5), unsigned(screenH * 0.5));
+
+ /// Create Bloom Extract Shader
+ bloomExtractUniforms["RenderTexture"] = 0;
+ bloomExtractUniforms["extractLow"] = 0;
+ bloomExtractUniforms["extractHigh"] = 0;
+ bloomExtractUniforms["lumWeights"] = 0;
+
+ /// Create Bloom Blur Shader
+ bloomBlurUniforms["RenderTexture"] = 0;
+ bloomBlurUniforms["bloomStrength"] = 0;
+ bloomBlurUniforms["texelSize"] = 0;
+ bloomBlurUniforms["blurDirection"] = 0;
+ bloomBlurUniforms["blurWidth"] = 0;
+}
+
+void LLPostProcess::getShaderUniforms(glslUniforms & uniforms, GLhandleARB & prog)
+{
+ /// Find uniform locations and insert into map
+ std::map<const char *, GLuint>::iterator i;
+ for (i = uniforms.begin(); i != uniforms.end(); ++i){
+ i->second = glGetUniformLocationARB(prog, i->first);
+ }
+}
+
+void LLPostProcess::doEffects(void)
+{
+ /// Save GL State
+ glPushAttrib(GL_ALL_ATTRIB_BITS);
+ glPushClientAttrib(GL_ALL_ATTRIB_BITS);
+
+ /// Copy the screen buffer to the render texture
+ copyFrameBuffer(sceneRenderTexture, screenW, screenH);
+
+ /// Clear the frame buffer.
+ glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ /// Change to an orthogonal view
+ viewOrthogonal(screenW, screenH);
+
+ checkError();
+ applyShaders();
+
+ LLGLSLShader::bindNoShader();
+ checkError();
+
+ /// Change to a perspective view
+ viewPerspective();
+
+ /// Reset GL State
+ glPopClientAttrib();
+ glPopAttrib();
+ checkError();
+}
+
+void LLPostProcess::copyFrameBuffer(GLuint & texture, unsigned int width, unsigned int height)
+{
+ glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texture);
+ glCopyTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, 0, 0, width, height, 0);
+}
+
+void LLPostProcess::drawOrthoQuad(unsigned int width, unsigned int height, QuadType type)
+{
+#if 0
+ float noiseX = 0.f;
+ float noiseY = 0.f;
+ float screenRatio = 1.0f;
+
+ if (type == QUAD_NOISE){
+ noiseX = ((float) rand() / (float) RAND_MAX);
+ noiseY = ((float) rand() / (float) RAND_MAX);
+ screenRatio = (float) width / (float) height;
+ }
+
+
+ glBegin(GL_QUADS);
+ if (type != QUAD_BLOOM_EXTRACT){
+ glMultiTexCoord2fARB(GL_TEXTURE0_ARB, 0.f, (GLfloat) height);
+ } else {
+ glMultiTexCoord2fARB(GL_TEXTURE0_ARB, 0.f, (GLfloat) height * 2.0f);
+ }
+ if (type == QUAD_NOISE){
+ glMultiTexCoord2fARB(GL_TEXTURE1_ARB,
+ noiseX,
+ noiseTextureScale + noiseY);
+ } else if (type == QUAD_BLOOM_COMBINE){
+ glMultiTexCoord2fARB(GL_TEXTURE1_ARB, 0.f, (GLfloat) height * 0.5f);
+ }
+ glVertex2f(0.f, (GLfloat) screenH - height);
+
+ if (type != QUAD_BLOOM_EXTRACT){
+ glMultiTexCoord2fARB(GL_TEXTURE0_ARB, 0.f, 0.f);
+ } else {
+ glMultiTexCoord2fARB(GL_TEXTURE0_ARB, 0.f, 0.f);
+ }
+ if (type == QUAD_NOISE){
+ glMultiTexCoord2fARB(GL_TEXTURE1_ARB,
+ noiseX,
+ noiseY);
+ } else if (type == QUAD_BLOOM_COMBINE){
+ glMultiTexCoord2fARB(GL_TEXTURE1_ARB, 0.f, 0.f);
+ }
+ glVertex2f(0.f, (GLfloat) height + (screenH - height));
+
+
+ if (type != QUAD_BLOOM_EXTRACT){
+ glMultiTexCoord2fARB(GL_TEXTURE0_ARB, (GLfloat) width, 0.f);
+ } else {
+ glMultiTexCoord2fARB(GL_TEXTURE0_ARB, (GLfloat) width * 2.0f, 0.f);
+ }
+ if (type == QUAD_NOISE){
+ glMultiTexCoord2fARB(GL_TEXTURE1_ARB,
+ screenRatio * noiseTextureScale + noiseX,
+ noiseY);
+ } else if (type == QUAD_BLOOM_COMBINE){
+ glMultiTexCoord2fARB(GL_TEXTURE1_ARB, (GLfloat) width * 0.5f, 0.f);
+ }
+ glVertex2f((GLfloat) width, (GLfloat) height + (screenH - height));
+
+
+ if (type != QUAD_BLOOM_EXTRACT){
+ glMultiTexCoord2fARB(GL_TEXTURE0_ARB, (GLfloat) width, (GLfloat) height);
+ } else {
+ glMultiTexCoord2fARB(GL_TEXTURE0_ARB, (GLfloat) width * 2.0f, (GLfloat) height * 2.0f);
+ }
+ if (type == QUAD_NOISE){
+ glMultiTexCoord2fARB(GL_TEXTURE1_ARB,
+ screenRatio * noiseTextureScale + noiseX,
+ noiseTextureScale + noiseY);
+ } else if (type == QUAD_BLOOM_COMBINE){
+ glMultiTexCoord2fARB(GL_TEXTURE1_ARB, (GLfloat) width * 0.5f, (GLfloat) height * 0.5f);
+ }
+ glVertex2f((GLfloat) width, (GLfloat) screenH - height);
+ glEnd();
+#endif
+}
+
+void LLPostProcess::viewOrthogonal(unsigned int width, unsigned int height)
+{
+ glMatrixMode(GL_PROJECTION);
+ glPushMatrix();
+ glLoadIdentity();
+ glOrtho( 0.f, (GLdouble) width , (GLdouble) height , 0.f, -1.f, 1.f );
+ glMatrixMode(GL_MODELVIEW);
+ glPushMatrix();
+ glLoadIdentity();
+}
+
+void LLPostProcess::viewPerspective(void)
+{
+ glMatrixMode( GL_PROJECTION );
+ glPopMatrix();
+ glMatrixMode( GL_MODELVIEW );
+ glPopMatrix();
+}
+
+void LLPostProcess::changeOrthogonal(unsigned int width, unsigned int height)
+{
+ viewPerspective();
+ viewOrthogonal(width, height);
+}
+
+void LLPostProcess::createTexture(GLuint & texture, unsigned int width, unsigned int height)
+{
+ if (texture != 0){
+ glDeleteTextures(1, &texture);
+ }
+
+ std::vector<GLubyte> data(width * height * 4, 0);
+
+ glGenTextures(1, &texture);
+ glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texture);
+ glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 4, width, height, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, &data[0]);
+ glTexParameteri(GL_TEXTURE_RECTANGLE_ARB,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_RECTANGLE_ARB,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_RECTANGLE_ARB,GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_RECTANGLE_ARB,GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+}
+
+void LLPostProcess::createNoiseTexture(GLuint & texture)
+{
+ if (texture != 0){
+ glDeleteTextures(1, &texture);
+ }
+ glGenTextures(1, &texture);
+
+ std::vector<GLubyte> buffer(NOISE_SIZE * NOISE_SIZE);
+ for (unsigned int i = 0; i < NOISE_SIZE; i++){
+ for (unsigned int k = 0; k < NOISE_SIZE; k++){
+ buffer[(i * NOISE_SIZE) + k] = (GLubyte)((double) rand() / ((double) RAND_MAX + 1.f) * 255.f);
+ }
+ }
+ glBindTexture(GL_TEXTURE_2D, texture);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, NOISE_SIZE, NOISE_SIZE, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, &buffer[0]);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+}
+
+bool LLPostProcess::checkError(void)
+{
+ GLenum glErr;
+ bool retCode = false;
+
+ glErr = glGetError();
+ while (glErr != GL_NO_ERROR)
+ {
+ // shaderErrorLog << (const char *) gluErrorString(glErr) << std::endl;
+ char const * err_str_raw = (const char *) gluErrorString(glErr);
+
+ if(err_str_raw == NULL)
+ {
+ std::ostringstream err_builder;
+ err_builder << "unknown error number " << glErr;
+ mShaderErrorString = err_builder.str();
+ }
+ else
+ {
+ mShaderErrorString = err_str_raw;
+ }
+
+ retCode = true;
+ glErr = glGetError();
+ }
+ return retCode;
+}
+
+void LLPostProcess::checkShaderError(GLhandleARB shader)
+{
+ GLint infologLength = 0;
+ GLint charsWritten = 0;
+ GLchar *infoLog;
+
+ checkError(); // Check for OpenGL errors
+
+ glGetObjectParameterivARB(shader, GL_OBJECT_INFO_LOG_LENGTH_ARB, &infologLength);
+
+ checkError(); // Check for OpenGL errors
+
+ if (infologLength > 0)
+ {
+ infoLog = (GLchar *)malloc(infologLength);
+ if (infoLog == NULL)
+ {
+ /// Could not allocate infolog buffer
+ return;
+ }
+ glGetInfoLogARB(shader, infologLength, &charsWritten, infoLog);
+ // shaderErrorLog << (char *) infoLog << std::endl;
+ mShaderErrorString = (char *) infoLog;
+ free(infoLog);
+ }
+ checkError(); // Check for OpenGL errors
+}
diff --git a/indra/llrender/llpostprocess.h b/indra/llrender/llpostprocess.h
new file mode 100644
index 0000000000..b31333a28b
--- /dev/null
+++ b/indra/llrender/llpostprocess.h
@@ -0,0 +1,268 @@
+/**
+ * @file llpostprocess.h
+ * @brief LLPostProcess class definition
+ *
+ * $LicenseInfo:firstyear=2007&license=viewergpl$
+ *
+ * Copyright (c) 2007-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$
+ */
+
+#ifndef LL_POSTPROCESS_H
+#define LL_POSTPROCESS_H
+
+#include <map>
+#include <fstream>
+#include "llgl.h"
+#include "llglheaders.h"
+
+class LLPostProcess
+{
+public:
+
+ typedef enum _QuadType {
+ QUAD_NORMAL,
+ QUAD_NOISE,
+ QUAD_BLOOM_EXTRACT,
+ QUAD_BLOOM_COMBINE
+ } QuadType;
+
+ /// GLSL Shader Encapsulation Struct
+ typedef std::map<const char *, GLuint> glslUniforms;
+
+ struct PostProcessTweaks : public LLSD {
+ inline PostProcessTweaks() : LLSD(LLSD::emptyMap())
+ {
+ }
+
+ inline LLSD & brightMult() {
+ return (*this)["brightness_multiplier"];
+ }
+
+ inline LLSD & noiseStrength() {
+ return (*this)["noise_strength"];
+ }
+
+ inline LLSD & noiseSize() {
+ return (*this)["noise_size"];
+ }
+
+ inline LLSD & extractLow() {
+ return (*this)["extract_low"];
+ }
+
+ inline LLSD & extractHigh() {
+ return (*this)["extract_high"];
+ }
+
+ inline LLSD & bloomWidth() {
+ return (*this)["bloom_width"];
+ }
+
+ inline LLSD & bloomStrength() {
+ return (*this)["bloom_strength"];
+ }
+
+ inline LLSD & brightness() {
+ return (*this)["brightness"];
+ }
+
+ inline LLSD & contrast() {
+ return (*this)["contrast"];
+ }
+
+ inline LLSD & contrastBaseR() {
+ return (*this)["contrast_base"][0];
+ }
+
+ inline LLSD & contrastBaseG() {
+ return (*this)["contrast_base"][1];
+ }
+
+ inline LLSD & contrastBaseB() {
+ return (*this)["contrast_base"][2];
+ }
+
+ inline LLSD & contrastBaseIntensity() {
+ return (*this)["contrast_base"][3];
+ }
+
+ inline LLSD & saturation() {
+ return (*this)["saturation"];
+ }
+
+ inline LLSD & useNightVisionShader() {
+ return (*this)["enable_night_vision"];
+ }
+
+ inline LLSD & useBloomShader() {
+ return (*this)["enable_bloom"];
+ }
+
+ inline LLSD & useColorFilter() {
+ return (*this)["enable_color_filter"];
+ }
+
+
+ inline F32 getBrightMult() const {
+ return F32((*this)["brightness_multiplier"].asReal());
+ }
+
+ inline F32 getNoiseStrength() const {
+ return F32((*this)["noise_strength"].asReal());
+ }
+
+ inline F32 getNoiseSize() const {
+ return F32((*this)["noise_size"].asReal());
+ }
+
+ inline F32 getExtractLow() const {
+ return F32((*this)["extract_low"].asReal());
+ }
+
+ inline F32 getExtractHigh() const {
+ return F32((*this)["extract_high"].asReal());
+ }
+
+ inline F32 getBloomWidth() const {
+ return F32((*this)["bloom_width"].asReal());
+ }
+
+ inline F32 getBloomStrength() const {
+ return F32((*this)["bloom_strength"].asReal());
+ }
+
+ inline F32 getBrightness() const {
+ return F32((*this)["brightness"].asReal());
+ }
+
+ inline F32 getContrast() const {
+ return F32((*this)["contrast"].asReal());
+ }
+
+ inline F32 getContrastBaseR() const {
+ return F32((*this)["contrast_base"][0].asReal());
+ }
+
+ inline F32 getContrastBaseG() const {
+ return F32((*this)["contrast_base"][1].asReal());
+ }
+
+ inline F32 getContrastBaseB() const {
+ return F32((*this)["contrast_base"][2].asReal());
+ }
+
+ inline F32 getContrastBaseIntensity() const {
+ return F32((*this)["contrast_base"][3].asReal());
+ }
+
+ inline F32 getSaturation() const {
+ return F32((*this)["saturation"].asReal());
+ }
+
+ };
+
+ GLuint sceneRenderTexture;
+ GLuint noiseTexture;
+ GLuint tempBloomTexture;
+ bool initialized;
+ PostProcessTweaks tweaks;
+
+ // the map of all availible effects
+ LLSD mAllEffects;
+
+public:
+ LLPostProcess(void);
+
+ ~LLPostProcess(void);
+
+ void apply(unsigned int width, unsigned int height);
+
+ /// Perform global initialization for this class.
+ static void initClass(void);
+
+ // Cleanup of global data that's only inited once per class.
+ static void cleanupClass();
+
+ void setSelectedEffect(std::string const & effectName);
+
+ inline std::string const & getSelectedEffect(void) const {
+ return mSelectedEffectName;
+ }
+
+ void saveEffect(std::string const & effectName);
+
+private:
+ /// read in from file
+ std::string mShaderErrorString;
+ unsigned int screenW;
+ unsigned int screenH;
+
+ float noiseTextureScale;
+
+ /// Shader Uniforms
+ glslUniforms nightVisionUniforms;
+ glslUniforms bloomExtractUniforms;
+ glslUniforms bloomBlurUniforms;
+ glslUniforms colorFilterUniforms;
+
+ // the name of currently selected effect in mAllEffects
+ // invariant: tweaks == mAllEffects[mSelectedEffectName]
+ std::string mSelectedEffectName;
+
+ /// General functions
+ void initialize(unsigned int width, unsigned int height);
+ void doEffects(void);
+ void applyShaders(void);
+ bool shadersEnabled(void);
+
+ /// Night Vision Functions
+ void createNightVisionShader(void);
+ void applyNightVisionShader(void);
+
+ /// Bloom Functions
+ void createBloomShader(void);
+ void applyBloomShader(void);
+
+ /// Color Filter Functions
+ void createColorFilterShader(void);
+ void applyColorFilterShader(void);
+
+ /// OpenGL Helper Functions
+ void getShaderUniforms(glslUniforms & uniforms, GLhandleARB & prog);
+ void createTexture(GLuint & texture, unsigned int width, unsigned int height);
+ void copyFrameBuffer(GLuint & texture, unsigned int width, unsigned int height);
+ void createNoiseTexture(GLuint & texture);
+ bool checkError(void);
+ void checkShaderError(GLhandleARB shader);
+ void drawOrthoQuad(unsigned int width, unsigned int height, QuadType type);
+ void viewOrthogonal(unsigned int width, unsigned int height);
+ void changeOrthogonal(unsigned int width, unsigned int height);
+ void viewPerspective(void);
+};
+
+extern LLPostProcess * gPostProcess;
+
+
+#endif // LL_POSTPROCESS_H
diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp
index 1168155f8b..fc911de46b 100644
--- a/indra/llrender/llrender.cpp
+++ b/indra/llrender/llrender.cpp
@@ -36,6 +36,12 @@
LLRender gGL;
+// Handy copies of last good GL matrices
+F64 gGLModelView[16];
+F64 gGLLastModelView[16];
+F64 gGLProjection[16];
+S32 gGLViewport[4];
+
static const U32 LL_NUM_TEXTURE_LAYERS = 8;
static GLenum sGLCompareFunc[] =
diff --git a/indra/llrender/llrender.h b/indra/llrender/llrender.h
index 2fa3237ef9..a0a492bc73 100644
--- a/indra/llrender/llrender.h
+++ b/indra/llrender/llrender.h
@@ -232,7 +232,10 @@ private:
std::vector<LLTexUnit*> mTexUnits;
};
-
+extern F64 gGLModelView[16];
+extern F64 gGLLastModelView[16];
+extern F64 gGLProjection[16];
+extern S32 gGLViewport[4];
extern LLRender gGL;
diff --git a/indra/llrender/llrendersphere.cpp b/indra/llrender/llrendersphere.cpp
new file mode 100644
index 0000000000..296fa77184
--- /dev/null
+++ b/indra/llrender/llrendersphere.cpp
@@ -0,0 +1,159 @@
+/**
+ * @file llrendersphere.cpp
+ * @brief implementation of the LLRenderSphere class.
+ *
+ * Copyright (c) 2001-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+// Sphere creates a set of display lists that can then be called to create
+// a lit sphere at different LOD levels. You only need one instance of sphere
+// per viewer - then call the appropriate list.
+
+#include "linden_common.h"
+
+#include "llrendersphere.h"
+#include "llerror.h"
+
+#include "llglheaders.h"
+
+GLUquadricObj *gQuadObj2 = NULL;
+LLRenderSphere gSphere;
+
+void drawSolidSphere(GLdouble radius, GLint slices, GLint stacks);
+
+void drawSolidSphere(GLdouble radius, GLint slices, GLint stacks)
+{
+ if (!gQuadObj2)
+ {
+ gQuadObj2 = gluNewQuadric();
+ if (!gQuadObj2)
+ {
+ llwarns << "drawSolidSphere couldn't allocate quadric" << llendl;
+ return;
+ }
+ }
+
+ gluQuadricDrawStyle(gQuadObj2, GLU_FILL);
+ gluQuadricNormals(gQuadObj2, GLU_SMOOTH);
+ // If we ever changed/used the texture or orientation state
+ // of quadObj, we'd need to change it to the defaults here
+ // with gluQuadricTexture and/or gluQuadricOrientation.
+ gluQuadricTexture(gQuadObj2, GL_TRUE);
+ gluSphere(gQuadObj2, radius, slices, stacks);
+}
+
+
+// lat = 0 is Z-axis
+// lon = 0, lat = 90 at X-axis
+void lat2xyz(LLVector3 * result, F32 lat, F32 lon)
+{
+ // Convert a latitude and longitude to x,y,z on a normal sphere and return it in result
+ F32 r;
+ result->mV[VX] = (F32) (cos(lon * DEG_TO_RAD) * sin(lat * DEG_TO_RAD));
+ result->mV[VY] = (F32) (sin(lon * DEG_TO_RAD) * sin(lat * DEG_TO_RAD));
+ r = (F32) pow(result->mV[VX] * result->mV[VX] + result->mV[VY] * result->mV[VY], 0.5f);
+ if (r == 1.0f)
+ {
+ result->mV[VZ] = 0.0f;
+ }
+ else
+ {
+ result->mV[VZ] = (F32) pow(1 - r*r, 0.5f);
+ if (lat > 90.01)
+ {
+ result->mV[VZ] *= -1.0;
+ }
+ }
+}
+
+void lat2xyz_rad(LLVector3 * result, F32 lat, F32 lon)
+{
+ // Convert a latitude and longitude to x,y,z on a normal sphere and return it in result
+ F32 r;
+ result->mV[VX] = (F32) (cos(lon) * sin(lat));
+ result->mV[VY] = (F32) (sin(lon) * sin(lat));
+ r = (F32) pow(result->mV[VX] * result->mV[VX] + result->mV[VY] * result->mV[VY], 0.5f);
+ if (r == 1.0f)
+ result->mV[VZ] = 0.0f;
+ else
+ {
+ result->mV[VZ] = (F32) pow(1 - r*r, 0.5f);
+ if (lat > F_PI_BY_TWO) result->mV[VZ] *= -1.0;
+ }
+}
+
+// A couple thoughts on sphere drawing:
+// 1) You need more slices than stacks, but little less than 2:1
+// 2) At low LOD, setting stacks to an odd number avoids a "band" around the equator, making things look smoother
+void LLRenderSphere::prerender()
+{
+ // Create a series of display lists for different LODs
+ mDList[0] = glGenLists(1);
+ glNewList(mDList[0], GL_COMPILE);
+ drawSolidSphere(1.0, 30, 20);
+ glEndList();
+
+ mDList[1] = glGenLists(1);
+ glNewList(mDList[1], GL_COMPILE);
+ drawSolidSphere(1.0, 20, 15);
+ glEndList();
+
+ mDList[2] = glGenLists(1);
+ glNewList(mDList[2], GL_COMPILE);
+ drawSolidSphere(1.0, 12, 8);
+ glEndList();
+
+ mDList[3] = glGenLists(1);
+ glNewList(mDList[3], GL_COMPILE);
+ drawSolidSphere(1.0, 8, 5);
+ glEndList();
+}
+
+void LLRenderSphere::cleanupGL()
+{
+ for (S32 detail = 0; detail < 4; detail++)
+ {
+ glDeleteLists(mDList[detail], 1);
+ mDList[detail] = 0;
+ }
+
+ if (gQuadObj2)
+ {
+ gluDeleteQuadric(gQuadObj2);
+ gQuadObj2 = NULL;
+ }
+}
+
+// Constants here are empirically derived from my eyeballs, JNC
+//
+// The toughest adjustment is the cutoff for the lowest LOD
+// Maybe we should have more LODs at the low end?
+void LLRenderSphere::render(F32 pixel_area)
+{
+ S32 level_of_detail;
+
+ if (pixel_area > 10000.f)
+ {
+ level_of_detail = 0;
+ }
+ else if (pixel_area > 800.f)
+ {
+ level_of_detail = 1;
+ }
+ else if (pixel_area > 100.f)
+ {
+ level_of_detail = 2;
+ }
+ else
+ {
+ level_of_detail = 3;
+ }
+ glCallList(mDList[level_of_detail]);
+}
+
+
+void LLRenderSphere::render()
+{
+ glCallList(mDList[0]);
+}
diff --git a/indra/llrender/llrendersphere.h b/indra/llrender/llrendersphere.h
new file mode 100644
index 0000000000..3e58f6fb31
--- /dev/null
+++ b/indra/llrender/llrendersphere.h
@@ -0,0 +1,34 @@
+/**
+ * @file llrendersphere.h
+ * @brief interface for the LLRenderSphere class.
+ *
+ * Copyright (c) 2001-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+#ifndef LL_LLRENDERSPHERE_H
+#define LL_LLRENDERSPHERE_H
+
+#include "llmath.h"
+#include "v3math.h"
+#include "v4math.h"
+#include "m3math.h"
+#include "m4math.h"
+#include "v4color.h"
+#include "llgl.h"
+
+void lat2xyz(LLVector3 * result, F32 lat, F32 lon); // utility routine
+
+class LLRenderSphere
+{
+public:
+ LLGLuint mDList[5];
+
+ void prerender();
+ void cleanupGL();
+ void render(F32 pixel_area); // of a box of size 1.0 at that position
+ void render(); // render at highest LOD
+};
+
+extern LLRenderSphere gSphere;
+#endif
diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp
new file mode 100644
index 0000000000..3bdc36c677
--- /dev/null
+++ b/indra/llrender/llshadermgr.cpp
@@ -0,0 +1,513 @@
+/**
+ * @file llshadermgr.cpp
+ * @brief Shader manager implementation.
+ *
+ * $LicenseInfo:firstyear=2005&license=viewergpl$
+ *
+ * Copyright (c) 2005-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$
+ */
+
+#include "linden_common.h"
+
+#include "llshadermgr.h"
+
+#include "llfile.h"
+#include "llrender.h"
+
+#if LL_DARWIN
+#include "OpenGL/OpenGL.h"
+#endif
+
+#ifdef LL_RELEASE_FOR_DOWNLOAD
+#define UNIFORM_ERRS LL_WARNS_ONCE("Shader")
+#else
+#define UNIFORM_ERRS LL_ERRS("Shader")
+#endif
+
+// Lots of STL stuff in here, using namespace std to keep things more readable
+using std::vector;
+using std::pair;
+using std::make_pair;
+using std::string;
+
+LLShaderMgr * LLShaderMgr::sInstance = NULL;
+
+LLShaderMgr::LLShaderMgr()
+{
+}
+
+
+LLShaderMgr::~LLShaderMgr()
+{
+}
+
+// static
+LLShaderMgr * LLShaderMgr::instance()
+{
+ if(NULL == sInstance)
+ {
+ LL_ERRS("Shaders") << "LLShaderMgr should already have been instantiated by the application!" << LL_ENDL;
+ }
+
+ return sInstance;
+}
+
+BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
+{
+ llassert_always(shader != NULL);
+ LLShaderFeatures *features = & shader->mFeatures;
+
+ //////////////////////////////////////
+ // Attach Vertex Shader Features First
+ //////////////////////////////////////
+
+ // NOTE order of shader object attaching is VERY IMPORTANT!!!
+ if (features->calculatesAtmospherics)
+ {
+ if (!shader->attachObject("windlight/atmosphericsVarsV.glsl"))
+ {
+ return FALSE;
+ }
+ }
+
+ if (features->calculatesLighting)
+ {
+ if (!shader->attachObject("windlight/atmosphericsHelpersV.glsl"))
+ {
+ return FALSE;
+ }
+
+ if (features->isSpecular)
+ {
+ if (!shader->attachObject("lighting/lightFuncSpecularV.glsl"))
+ {
+ return FALSE;
+ }
+
+ if (!shader->attachObject("lighting/sumLightsSpecularV.glsl"))
+ {
+ return FALSE;
+ }
+
+ if (!shader->attachObject("lighting/lightSpecularV.glsl"))
+ {
+ return FALSE;
+ }
+ }
+ else
+ {
+ if (!shader->attachObject("lighting/lightFuncV.glsl"))
+ {
+ return FALSE;
+ }
+
+ if (!shader->attachObject("lighting/sumLightsV.glsl"))
+ {
+ return FALSE;
+ }
+
+ if (!shader->attachObject("lighting/lightV.glsl"))
+ {
+ return FALSE;
+ }
+ }
+ }
+
+ // NOTE order of shader object attaching is VERY IMPORTANT!!!
+ if (features->calculatesAtmospherics)
+ {
+ if (!shader->attachObject("windlight/atmosphericsV.glsl"))
+ {
+ return FALSE;
+ }
+ }
+
+ if (features->hasSkinning)
+ {
+ if (!shader->attachObject("avatar/avatarSkinV.glsl"))
+ {
+ return FALSE;
+ }
+ }
+
+ ///////////////////////////////////////
+ // Attach Fragment Shader Features Next
+ ///////////////////////////////////////
+
+ if(features->calculatesAtmospherics)
+ {
+ if (!shader->attachObject("windlight/atmosphericsVarsF.glsl"))
+ {
+ return FALSE;
+ }
+ }
+
+ // NOTE order of shader object attaching is VERY IMPORTANT!!!
+ if (features->hasGamma)
+ {
+ if (!shader->attachObject("windlight/gammaF.glsl"))
+ {
+ return FALSE;
+ }
+ }
+
+ if (features->hasAtmospherics)
+ {
+ if (!shader->attachObject("windlight/atmosphericsF.glsl"))
+ {
+ return FALSE;
+ }
+ }
+
+ if (features->hasTransport)
+ {
+ if (!shader->attachObject("windlight/transportF.glsl"))
+ {
+ return FALSE;
+ }
+
+ // Test hasFullbright and hasShiny and attach fullbright and
+ // fullbright shiny atmos transport if we split them out.
+ }
+
+ // NOTE order of shader object attaching is VERY IMPORTANT!!!
+ if (features->hasWaterFog)
+ {
+ if (!shader->attachObject("environment/waterFogF.glsl"))
+ {
+ return FALSE;
+ }
+ }
+
+ if (features->hasLighting)
+ {
+
+ if (features->hasWaterFog)
+ {
+ if (!shader->attachObject("lighting/lightWaterF.glsl"))
+ {
+ return FALSE;
+ }
+ }
+
+ else
+ {
+ if (!shader->attachObject("lighting/lightF.glsl"))
+ {
+ return FALSE;
+ }
+ }
+ }
+
+ // NOTE order of shader object attaching is VERY IMPORTANT!!!
+ else if (features->isFullbright)
+ {
+
+ if (features->hasWaterFog)
+ {
+ if (!shader->attachObject("lighting/lightFullbrightWaterF.glsl"))
+ {
+ return FALSE;
+ }
+ }
+
+ else if (features->isShiny)
+ {
+ if (!shader->attachObject("lighting/lightFullbrightShinyF.glsl"))
+ {
+ return FALSE;
+ }
+ }
+
+ else
+ {
+ if (!shader->attachObject("lighting/lightFullbrightF.glsl"))
+ {
+ return FALSE;
+ }
+ }
+ }
+
+ // NOTE order of shader object attaching is VERY IMPORTANT!!!
+ else if (features->isShiny)
+ {
+
+ if (features->hasWaterFog)
+ {
+ if (!shader->attachObject("lighting/lightShinyWaterF.glsl"))
+ {
+ return FALSE;
+ }
+ }
+
+ else
+ {
+ if (!shader->attachObject("lighting/lightShinyF.glsl"))
+ {
+ return FALSE;
+ }
+ }
+ }
+ return TRUE;
+}
+
+//============================================================================
+// Load Shader
+
+static std::string get_object_log(GLhandleARB ret)
+{
+ std::string res;
+
+ //get log length
+ GLint length;
+ glGetObjectParameterivARB(ret, GL_OBJECT_INFO_LOG_LENGTH_ARB, &length);
+ if (length > 0)
+ {
+ //the log could be any size, so allocate appropriately
+ GLcharARB* log = new GLcharARB[length];
+ glGetInfoLogARB(ret, length, &length, log);
+ res = std::string((char *)log);
+ delete[] log;
+ }
+ return res;
+}
+
+void LLShaderMgr::dumpObjectLog(GLhandleARB ret, BOOL warns)
+{
+ std::string log = get_object_log(ret);
+ if ( log.length() > 0 )
+ {
+ if (warns)
+ {
+ LL_WARNS("ShaderLoading") << log << LL_ENDL;
+ }
+ else
+ {
+ LL_DEBUGS("ShaderLoading") << log << LL_ENDL;
+ }
+}
+}
+
+GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_level, GLenum type)
+{
+ GLenum error;
+ 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;
+
+ if (filename.empty())
+ {
+ return 0;
+ }
+
+
+ //read in from file
+ LLFILE* file = NULL;
+
+ S32 try_gpu_class = shader_level;
+ S32 gpu_class;
+
+ //find the most relevant file
+ for (gpu_class = try_gpu_class; gpu_class > 0; gpu_class--)
+ { //search from the current gpu class down to class 1 to find the most relevant shader
+ std::stringstream fname;
+ fname << getShaderDirPrefix();
+ fname << gpu_class << "/" << filename;
+
+ LL_DEBUGS("ShaderLoading") << "Looking in " << fname.str() << LL_ENDL;
+ file = LLFile::fopen(fname.str(), "r"); /* Flawfinder: ignore */
+ if (file)
+ {
+ LL_INFOS("ShaderLoading") << "Loading file: shaders/class" << gpu_class << "/" << filename << " (Want class " << gpu_class << ")" << LL_ENDL;
+ break; // done
+ }
+ }
+
+ if (file == NULL)
+ {
+ LL_WARNS("ShaderLoading") << "GLSL Shader file not found: " << filename << LL_ENDL;
+ return 0;
+ }
+
+ //we can't have any lines longer than 1024 characters
+ //or any shaders longer than 1024 lines... deal - DaveP
+ GLcharARB buff[1024];
+ GLcharARB* text[1024];
+ GLuint count = 0;
+
+
+ //copy file into memory
+ while(fgets((char *)buff, 1024, file) != NULL && count < (sizeof(buff)/sizeof(buff[0])))
+ {
+ text[count++] = (GLcharARB *)strdup((char *)buff);
+ }
+ fclose(file);
+
+ //create shader object
+ GLhandleARB ret = glCreateShaderObjectARB(type);
+ 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);
+ 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++)
+ {
+ free(text[i]);
+ }
+ 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)
+ {
+ //an error occured, print log
+ LL_WARNS("ShaderLoading") << "GLSL Compilation Error: (" << error << ") in " << filename << LL_ENDL;
+ dumpObjectLog(ret);
+ ret = 0;
+ }
+ }
+ else
+ {
+ ret = 0;
+ }
+ stop_glerror();
+
+ //successfully loaded, save results
+ if (ret)
+ {
+ // Add shader file to map
+ mShaderObjects[filename] = ret;
+ shader_level = try_gpu_class;
+ }
+ else
+ {
+ if (shader_level > 1)
+ {
+ shader_level--;
+ return loadShaderFile(filename,shader_level,type);
+ }
+ LL_WARNS("ShaderLoading") << "Failed to load " << filename << LL_ENDL;
+ }
+ return ret;
+}
+
+BOOL LLShaderMgr::linkProgramObject(GLhandleARB obj, BOOL suppress_errors)
+{
+ //check for errors
+ glLinkProgramARB(obj);
+ GLint success = GL_TRUE;
+ glGetObjectParameterivARB(obj, GL_OBJECT_LINK_STATUS_ARB, &success);
+ if (!suppress_errors && success == GL_FALSE)
+ {
+ //an error occured, print log
+ LL_WARNS("ShaderLoading") << "GLSL Linker Error:" << LL_ENDL;
+ }
+
+// NOTE: Removing LL_DARWIN block as it doesn't seem to actually give the correct answer,
+// but want it for reference once I move it.
+#if 0
+ // Force an evaluation of the gl state so the driver can tell if the shader will run in hardware or software
+ // per Apple's suggestion
+ glBegin(gGL.mMode);
+ glEnd();
+
+ // Query whether the shader can or cannot run in hardware
+ // http://developer.apple.com/qa/qa2007/qa1502.html
+ long vertexGPUProcessing;
+ CGLContextObj ctx = CGLGetCurrentContext();
+ CGLGetParameter (ctx, kCGLCPGPUVertexProcessing, &vertexGPUProcessing);
+ long fragmentGPUProcessing;
+ CGLGetParameter (ctx, kCGLCPGPUFragmentProcessing, &fragmentGPUProcessing);
+ if (!fragmentGPUProcessing || !vertexGPUProcessing)
+ {
+ LL_WARNS("ShaderLoading") << "GLSL Linker: Running in Software:" << LL_ENDL;
+ success = GL_FALSE;
+ suppress_errors = FALSE;
+ }
+
+#else
+ std::string log = get_object_log(obj);
+ LLStringUtil::toLower(log);
+ if (log.find("software") != std::string::npos)
+ {
+ LL_WARNS("ShaderLoading") << "GLSL Linker: Running in Software:" << LL_ENDL;
+ success = GL_FALSE;
+ suppress_errors = FALSE;
+ }
+#endif
+ if (!suppress_errors)
+ {
+ dumpObjectLog(obj, !success);
+ }
+
+ return success;
+}
+
+BOOL LLShaderMgr::validateProgramObject(GLhandleARB obj)
+{
+ //check program validity against current GL
+ glValidateProgramARB(obj);
+ GLint success = GL_TRUE;
+ glGetObjectParameterivARB(obj, GL_OBJECT_VALIDATE_STATUS_ARB, &success);
+ if (success == GL_FALSE)
+ {
+ LL_WARNS("ShaderLoading") << "GLSL program not valid: " << LL_ENDL;
+ dumpObjectLog(obj);
+ }
+ else
+ {
+ dumpObjectLog(obj, FALSE);
+ }
+
+ return success;
+}
+
diff --git a/indra/llrender/llshadermgr.h b/indra/llrender/llshadermgr.h
new file mode 100644
index 0000000000..09b9ca812e
--- /dev/null
+++ b/indra/llrender/llshadermgr.h
@@ -0,0 +1,75 @@
+/**
+ * @file llshadermgr.h
+ * @brief Shader Manager
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2008, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlife.com/developers/opensource/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlife.com/developers/opensource/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_SHADERMGR_H
+#define LL_SHADERMGR_H
+
+#include "llgl.h"
+#include "llglslshader.h"
+
+class LLShaderMgr
+{
+public:
+ LLShaderMgr();
+ virtual ~LLShaderMgr();
+
+ // singleton pattern implementation
+ static LLShaderMgr * instance();
+
+ BOOL attachShaderFeatures(LLGLSLShader * shader);
+ 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);
+
+ // Implemented in the application to actually point to the shader directory.
+ virtual std::string getShaderDirPrefix(void) = 0; // Pure Virtual
+
+ // Implemented in the application to actually update out of date uniforms for a particular shader
+ virtual void updateShaderUniforms(LLGLSLShader * shader) = 0; // Pure Virtual
+
+public:
+ // Map of shader names to compiled
+ std::map<std::string, GLhandleARB> mShaderObjects;
+
+ //global (reserved slot) shader parameters
+ std::vector<std::string> mReservedAttribs;
+
+ std::vector<std::string> mReservedUniforms;
+
+protected:
+
+ // our parameter manager singleton instance
+ static LLShaderMgr * sInstance;
+
+}; //LLShaderMgr
+
+#endif
diff --git a/indra/llrender/llvertexbuffer.h b/indra/llrender/llvertexbuffer.h
index 2b5f4e200b..45f501fe1e 100644
--- a/indra/llrender/llvertexbuffer.h
+++ b/indra/llrender/llvertexbuffer.h
@@ -41,6 +41,7 @@
#include "llmemory.h"
#include <set>
#include <vector>
+#include <list>
//============================================================================
// NOTES
diff --git a/indra/llwindow/CMakeLists.txt b/indra/llwindow/CMakeLists.txt
index acfeb6484f..95e315f38e 100644
--- a/indra/llwindow/CMakeLists.txt
+++ b/indra/llwindow/CMakeLists.txt
@@ -45,16 +45,11 @@ set(llwindows_HEADER_FILES
)
set(viewer_SOURCE_FILES
- llgl.cpp
llwindow.cpp
)
set(viewer_HEADER_FILES
- llgl.h
llwindow.h
- llglheaders.h
- llglstates.h
- llgltypes.h
llpreeditor.h
llmousehandler.h
)
@@ -123,21 +118,10 @@ if (SERVER AND NOT WINDOWS AND NOT DARWIN)
set(server_HEADER_FILES
llwindowmesaheadless.h
)
- set(copied_SOURCES
- llgl
+ copy_server_sources(
llwindow
)
- foreach (PREFIX ${copied_SOURCES})
- add_custom_command(
- OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_server.cpp
- COMMAND ${CMAKE_COMMAND}
- ARGS -E copy ${CMAKE_CURRENT_SOURCE_DIR}/${PREFIX}.cpp
- ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_server.cpp
- DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${PREFIX}.cpp
- )
- list(APPEND server_SOURCE_FILES ${PREFIX}_server.cpp)
- endforeach (PREFIX ${copied_SOURCES})
set_source_files_properties(
${server_SOURCE_FILES}
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index a1515abf9d..46fb6a6246 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -85,7 +85,6 @@ set(viewer_SOURCE_FILES
llconfirmationmanager.cpp
llconsole.cpp
llcontainerview.cpp
- llcubemap.cpp
llcurrencyuimanager.cpp
llcylinder.cpp
lldebugmessagebox.cpp
@@ -196,7 +195,6 @@ set(viewer_SOURCE_FILES
llgesturemgr.cpp
llgivemoney.cpp
llglsandbox.cpp
- llglslshader.cpp
llgroupmgr.cpp
llgroupnotify.cpp
llhoverview.cpp
@@ -285,7 +283,6 @@ set(viewer_SOURCE_FILES
llpatchvertexarray.cpp
llpolymesh.cpp
llpolymorph.cpp
- llpostprocess.cpp
llprefschat.cpp
llprefsim.cpp
llprefsvoice.cpp
@@ -299,7 +296,6 @@ set(viewer_SOURCE_FILES
llpreviewtexture.cpp
llprogressview.cpp
llregionposition.cpp
- llrendersphere.cpp
llremoteparcelrequest.cpp
llsavedsettingsglue.cpp
llselectmgr.cpp
@@ -385,6 +381,7 @@ set(viewer_SOURCE_FILES
llviewerpartsim.cpp
llviewerpartsource.cpp
llviewerregion.cpp
+ llviewershadermgr.cpp
llviewerstats.cpp
llviewertexteditor.cpp
llviewertextureanim.cpp
@@ -475,7 +472,6 @@ set(viewer_HEADER_FILES
llconfirmationmanager.h
llconsole.h
llcontainerview.h
- llcubemap.h
llcurrencyuimanager.h
llcylinder.h
lldebugmessagebox.h
@@ -586,7 +582,6 @@ set(viewer_HEADER_FILES
llgenepool.h
llgesturemgr.h
llgivemoney.h
- llglslshader.h
llgroupmgr.h
llgroupnotify.h
llhoverview.h
@@ -674,7 +669,6 @@ set(viewer_HEADER_FILES
llpanelweb.h
llparcelselection.h
llpatchvertexarray.h
- llpostprocess.h
llpolymesh.h
llpolymorph.h
llprefschat.h
@@ -691,7 +685,6 @@ set(viewer_HEADER_FILES
llprogressview.h
llregionposition.h
llremoteparcelrequest.h
- llrendersphere.h
llresourcedata.h
llsavedsettingsglue.h
llselectmgr.h
@@ -778,6 +771,7 @@ set(viewer_HEADER_FILES
llviewerpartsource.h
llviewerprecompiledheaders.h
llviewerregion.h
+ llviewershadermgr.h
llviewerstats.h
llviewertexteditor.h
llviewertextureanim.h
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index c040dae469..30634a3f2c 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -408,7 +408,7 @@ bool handleCrashSubmitBehaviorChanged(const LLSD& newvalue)
else if(gSavedSettings.getBOOL("WatchdogEnabled") == TRUE)
{
// Don't re-enable the watchdog when we change the setting; this may get called before it's started
-// LLWatchdog::getInstance()->init();
+// LLWatchdog::getInstance()->init();
}
return true;
}
@@ -459,6 +459,8 @@ static void settings_to_globals()
gMiniMapScale = gSavedSettings.getF32("MiniMapScale");
gHandleKeysAsync = gSavedSettings.getBOOL("AsyncKeyboard");
LLHoverView::sShowHoverTips = gSavedSettings.getBOOL("ShowHoverTips");
+
+ LLCubeMap::sUseCubeMaps = LLFeatureManager::getInstance()->isFeatureAvailable("RenderCubeMap");
}
static void settings_modify()
@@ -2225,7 +2227,7 @@ void LLAppViewer::writeSystemInfo()
gDebugInfo["RAMInfo"]["Physical"] = (LLSD::Integer)(gSysMemory.getPhysicalMemoryKB());
gDebugInfo["RAMInfo"]["Allocated"] = (LLSD::Integer)(gMemoryAllocated>>10); // MB -> KB
gDebugInfo["OSInfo"] = getOSInfo().getOSStringSimple();
-
+
// The user is not logged on yet, but record the current grid choice login url
// which may have been the intended grid. This can b
gDebugInfo["GridName"] = LLViewerLogin::getInstance()->getGridLabel();
diff --git a/indra/newview/lldrawpoolalpha.cpp b/indra/newview/lldrawpoolalpha.cpp
index fe2c2041ae..e7c8903561 100644
--- a/indra/newview/lldrawpoolalpha.cpp
+++ b/indra/newview/lldrawpoolalpha.cpp
@@ -49,7 +49,7 @@
#include "llviewerobjectlist.h" // For debugging
#include "llviewerwindow.h"
#include "pipeline.h"
-#include "llglslshader.h"
+#include "llviewershadermgr.h"
#include "llviewerregion.h"
#include "lldrawpoolwater.h"
#include "llspatialpartition.h"
@@ -72,7 +72,7 @@ LLDrawPoolAlpha::~LLDrawPoolAlpha()
void LLDrawPoolAlpha::prerender()
{
- mVertexShaderLevel = LLShaderMgr::getVertexShaderLevel(LLShaderMgr::SHADER_OBJECT);
+ mVertexShaderLevel = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_OBJECT);
}
void LLDrawPoolAlpha::beginRenderPass(S32 pass)
diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp
index 04a7cfd8a0..422c0dc9a8 100644
--- a/indra/newview/lldrawpoolavatar.cpp
+++ b/indra/newview/lldrawpoolavatar.cpp
@@ -45,7 +45,7 @@
#include "llviewerregion.h"
#include "noise.h"
#include "pipeline.h"
-#include "llglslshader.h"
+#include "llviewershadermgr.h"
#include "llappviewer.h"
static U32 sDataMask = LLDrawPoolAvatar::VERTEX_DATA_MASK;
@@ -107,12 +107,12 @@ BOOL gRenderAvatar = TRUE;
S32 LLDrawPoolAvatar::getVertexShaderLevel() const
{
return sShaderLevel;
- //return (S32) LLShaderMgr::getVertexShaderLevel(LLShaderMgr::SHADER_AVATAR);
+ //return (S32) LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_AVATAR);
}
void LLDrawPoolAvatar::prerender()
{
- mVertexShaderLevel = LLShaderMgr::getVertexShaderLevel(LLShaderMgr::SHADER_AVATAR);
+ mVertexShaderLevel = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_AVATAR);
sShaderLevel = mVertexShaderLevel;
if (sShaderLevel > 0)
@@ -289,16 +289,16 @@ void LLDrawPoolAvatar::beginSkinned()
sVertexProgram->bind();
if (sShaderLevel >= SHADER_LEVEL_CLOTH)
{
- enable_cloth_weights(sVertexProgram->mAttribute[LLShaderMgr::AVATAR_CLOTHING]);
+ enable_cloth_weights(sVertexProgram->mAttribute[LLViewerShaderMgr::AVATAR_CLOTHING]);
}
- enable_vertex_weighting(sVertexProgram->mAttribute[LLShaderMgr::AVATAR_WEIGHT]);
+ enable_vertex_weighting(sVertexProgram->mAttribute[LLViewerShaderMgr::AVATAR_WEIGHT]);
if (sShaderLevel >= SHADER_LEVEL_BUMP)
{
- enable_binormals(sVertexProgram->mAttribute[LLShaderMgr::BINORMAL]);
+ enable_binormals(sVertexProgram->mAttribute[LLViewerShaderMgr::BINORMAL]);
}
- sVertexProgram->enableTexture(LLShaderMgr::BUMP_MAP);
+ sVertexProgram->enableTexture(LLViewerShaderMgr::BUMP_MAP);
gGL.getTexUnit(0)->activate();
}
else
@@ -318,16 +318,16 @@ void LLDrawPoolAvatar::endSkinned()
if (sShaderLevel > 0)
{
sRenderingSkinned = FALSE;
- sVertexProgram->disableTexture(LLShaderMgr::BUMP_MAP);
+ sVertexProgram->disableTexture(LLViewerShaderMgr::BUMP_MAP);
gGL.getTexUnit(0)->activate();
- disable_vertex_weighting(sVertexProgram->mAttribute[LLShaderMgr::AVATAR_WEIGHT]);
+ disable_vertex_weighting(sVertexProgram->mAttribute[LLViewerShaderMgr::AVATAR_WEIGHT]);
if (sShaderLevel >= SHADER_LEVEL_BUMP)
{
- disable_binormals(sVertexProgram->mAttribute[LLShaderMgr::BINORMAL]);
+ disable_binormals(sVertexProgram->mAttribute[LLViewerShaderMgr::BINORMAL]);
}
if ((sShaderLevel >= SHADER_LEVEL_CLOTH))
{
- disable_cloth_weights(sVertexProgram->mAttribute[LLShaderMgr::AVATAR_CLOTHING]);
+ disable_cloth_weights(sVertexProgram->mAttribute[LLViewerShaderMgr::AVATAR_CLOTHING]);
}
sVertexProgram->unbind();
@@ -466,7 +466,7 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass)
if (sShaderLevel > 0)
{
- gAvatarMatrixParam = sVertexProgram->mUniform[LLShaderMgr::AVATAR_MATRIX];
+ gAvatarMatrixParam = sVertexProgram->mUniform[LLViewerShaderMgr::AVATAR_MATRIX];
}
if ((sShaderLevel >= SHADER_LEVEL_CLOTH))
@@ -482,16 +482,16 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass)
wind = wind * rot_mat;
wind.mV[VW] = avatarp->mWindVec.mV[VW];
- sVertexProgram->vertexAttrib4fv(LLShaderMgr::AVATAR_WIND, wind.mV);
+ sVertexProgram->vertexAttrib4fv(LLViewerShaderMgr::AVATAR_WIND, wind.mV);
F32 phase = -1.f * (avatarp->mRipplePhase);
F32 freq = 7.f + (noise1(avatarp->mRipplePhase) * 2.f);
LLVector4 sin_params(freq, freq, freq, phase);
- sVertexProgram->vertexAttrib4fv(LLShaderMgr::AVATAR_SINWAVE, sin_params.mV);
+ sVertexProgram->vertexAttrib4fv(LLViewerShaderMgr::AVATAR_SINWAVE, sin_params.mV);
LLVector4 gravity(0.f, 0.f, -CLOTHING_GRAVITY_EFFECT, 0.f);
gravity = gravity * rot_mat;
- sVertexProgram->vertexAttrib4fv(LLShaderMgr::AVATAR_GRAVITY, gravity.mV);
+ sVertexProgram->vertexAttrib4fv(LLViewerShaderMgr::AVATAR_GRAVITY, gravity.mV);
}
if( !single_avatar || (avatarp == single_avatar) )
@@ -611,7 +611,7 @@ void LLDrawPoolAvatar::renderForSelect()
sVertexProgram = &gAvatarPickProgram;
if (sShaderLevel > 0)
{
- gAvatarMatrixParam = sVertexProgram->mUniform[LLShaderMgr::AVATAR_MATRIX];
+ gAvatarMatrixParam = sVertexProgram->mUniform[LLViewerShaderMgr::AVATAR_MATRIX];
}
gGL.setAlphaRejectSettings(LLRender::CF_GREATER_EQUAL, 0.2f);
gGL.setSceneBlendType(LLRender::BT_REPLACE);
@@ -622,7 +622,7 @@ void LLDrawPoolAvatar::renderForSelect()
{
sRenderingSkinned = TRUE;
sVertexProgram->bind();
- enable_vertex_weighting(sVertexProgram->mAttribute[LLShaderMgr::AVATAR_WEIGHT]);
+ enable_vertex_weighting(sVertexProgram->mAttribute[LLViewerShaderMgr::AVATAR_WEIGHT]);
}
avatarp->renderSkinned(AVATAR_RENDER_PASS_SINGLE);
@@ -632,7 +632,7 @@ void LLDrawPoolAvatar::renderForSelect()
{
sRenderingSkinned = FALSE;
sVertexProgram->unbind();
- disable_vertex_weighting(sVertexProgram->mAttribute[LLShaderMgr::AVATAR_WEIGHT]);
+ disable_vertex_weighting(sVertexProgram->mAttribute[LLViewerShaderMgr::AVATAR_WEIGHT]);
}
gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT);
@@ -670,7 +670,7 @@ LLColor3 LLDrawPoolAvatar::getDebugColor() const
LLVertexBufferAvatar::LLVertexBufferAvatar()
: LLVertexBuffer(sDataMask,
- LLShaderMgr::getVertexShaderLevel(LLShaderMgr::SHADER_AVATAR) > 0 ?
+ LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_AVATAR) > 0 ?
GL_STATIC_DRAW_ARB :
GL_STREAM_DRAW_ARB)
{
@@ -692,16 +692,16 @@ void LLVertexBufferAvatar::setupVertexBuffer(U32 data_mask) const
glClientActiveTextureARB(GL_TEXTURE0_ARB);
glTexCoordPointer(2,GL_FLOAT, mStride, (void*)(base + mOffsets[TYPE_TEXCOORD]));
- set_vertex_weights(sVertexProgram->mAttribute[LLShaderMgr::AVATAR_WEIGHT], mStride, (F32*)(base + mOffsets[TYPE_WEIGHT]));
+ set_vertex_weights(sVertexProgram->mAttribute[LLViewerShaderMgr::AVATAR_WEIGHT], mStride, (F32*)(base + mOffsets[TYPE_WEIGHT]));
if (sShaderLevel >= LLDrawPoolAvatar::SHADER_LEVEL_BUMP)
{
- set_binormals(sVertexProgram->mAttribute[LLShaderMgr::BINORMAL], mStride, (LLVector3*)(base + mOffsets[TYPE_BINORMAL]));
+ set_binormals(sVertexProgram->mAttribute[LLViewerShaderMgr::BINORMAL], mStride, (LLVector3*)(base + mOffsets[TYPE_BINORMAL]));
}
if (sShaderLevel >= LLDrawPoolAvatar::SHADER_LEVEL_CLOTH)
{
- set_vertex_clothing_weights(sVertexProgram->mAttribute[LLShaderMgr::AVATAR_CLOTHING], mStride, (LLVector4*)(base + mOffsets[TYPE_CLOTHWEIGHT]));
+ set_vertex_clothing_weights(sVertexProgram->mAttribute[LLViewerShaderMgr::AVATAR_CLOTHING], mStride, (LLVector4*)(base + mOffsets[TYPE_CLOTHWEIGHT]));
}
}
else
diff --git a/indra/newview/lldrawpoolbump.cpp b/indra/newview/lldrawpoolbump.cpp
index 56dc61c1a3..11391ee6fb 100644
--- a/indra/newview/lldrawpoolbump.cpp
+++ b/indra/newview/lldrawpoolbump.cpp
@@ -53,7 +53,7 @@
#include "llviewerimagelist.h"
#include "pipeline.h"
#include "llspatialpartition.h"
-#include "llglslshader.h"
+#include "llviewershadermgr.h"
//#include "llimagebmp.h"
//#include "../tools/imdebug/imdebug.h"
@@ -177,7 +177,7 @@ LLDrawPoolBump::LLDrawPoolBump()
void LLDrawPoolBump::prerender()
{
- mVertexShaderLevel = LLShaderMgr::getVertexShaderLevel(LLShaderMgr::SHADER_OBJECT);
+ mVertexShaderLevel = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_OBJECT);
}
// static
@@ -333,7 +333,7 @@ void LLDrawPoolBump::beginShiny(bool invisible)
LLCubeMap* cube_map = gSky.mVOSkyp ? gSky.mVOSkyp->getCubeMap() : NULL;
if( cube_map )
{
- if (!invisible && LLShaderMgr::getVertexShaderLevel(LLShaderMgr::SHADER_OBJECT) > 0 )
+ if (!invisible && LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_OBJECT) > 0 )
{
LLMatrix4 mat;
mat.initRows(LLVector4(gGLModelView+0),
@@ -343,23 +343,23 @@ void LLDrawPoolBump::beginShiny(bool invisible)
shader->bind();
LLVector3 vec = LLVector3(gShinyOrigin) * mat;
LLVector4 vec4(vec, gShinyOrigin.mV[3]);
- shader->uniform4fv(LLShaderMgr::SHINY_ORIGIN, 1, vec4.mV);
+ shader->uniform4fv(LLViewerShaderMgr::SHINY_ORIGIN, 1, vec4.mV);
if (mVertexShaderLevel > 1)
{
cube_map->setMatrix(1);
// Make sure that texture coord generation happens for tex unit 1, as that's the one we use for
// the cube map in the one pass shiny shaders
- cube_channel = shader->enableTexture(LLShaderMgr::ENVIRONMENT_MAP, GL_TEXTURE_CUBE_MAP_ARB);
+ cube_channel = shader->enableTexture(LLViewerShaderMgr::ENVIRONMENT_MAP, GL_TEXTURE_CUBE_MAP_ARB);
cube_map->enableTexture(cube_channel);
cube_map->enableTextureCoords(1);
- diffuse_channel = shader->enableTexture(LLShaderMgr::DIFFUSE_MAP);
+ diffuse_channel = shader->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
}
else
{
cube_channel = 0;
diffuse_channel = -1;
cube_map->setMatrix(0);
- cube_map->enable(shader->enableTexture(LLShaderMgr::ENVIRONMENT_MAP, GL_TEXTURE_CUBE_MAP_ARB));
+ cube_map->enable(shader->enableTexture(LLViewerShaderMgr::ENVIRONMENT_MAP, GL_TEXTURE_CUBE_MAP_ARB));
}
cube_map->bind();
}
@@ -423,13 +423,13 @@ void LLDrawPoolBump::endShiny(bool invisible)
if (!invisible && mVertexShaderLevel > 1)
{
- shader->disableTexture(LLShaderMgr::ENVIRONMENT_MAP, GL_TEXTURE_CUBE_MAP_ARB);
+ shader->disableTexture(LLViewerShaderMgr::ENVIRONMENT_MAP, GL_TEXTURE_CUBE_MAP_ARB);
- if (LLShaderMgr::getVertexShaderLevel(LLShaderMgr::SHADER_OBJECT) > 0)
+ if (LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_OBJECT) > 0)
{
if (diffuse_channel != 0)
{
- shader->disableTexture(LLShaderMgr::DIFFUSE_MAP);
+ shader->disableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
}
}
@@ -483,15 +483,15 @@ void LLDrawPoolBump::beginFullbrightShiny()
shader->bind();
LLVector3 vec = LLVector3(gShinyOrigin) * mat;
LLVector4 vec4(vec, gShinyOrigin.mV[3]);
- shader->uniform4fv(LLShaderMgr::SHINY_ORIGIN, 1, vec4.mV);
+ shader->uniform4fv(LLViewerShaderMgr::SHINY_ORIGIN, 1, vec4.mV);
cube_map->setMatrix(1);
// Make sure that texture coord generation happens for tex unit 1, as that's the one we use for
// the cube map in the one pass shiny shaders
- cube_channel = shader->enableTexture(LLShaderMgr::ENVIRONMENT_MAP, GL_TEXTURE_CUBE_MAP_ARB);
+ cube_channel = shader->enableTexture(LLViewerShaderMgr::ENVIRONMENT_MAP, GL_TEXTURE_CUBE_MAP_ARB);
cube_map->enableTexture(cube_channel);
cube_map->enableTextureCoords(1);
- diffuse_channel = shader->enableTexture(LLShaderMgr::DIFFUSE_MAP);
+ diffuse_channel = shader->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
cube_map->bind();
}
@@ -531,7 +531,7 @@ void LLDrawPoolBump::endFullbrightShiny()
if (diffuse_channel != 0)
{
- shader->disableTexture(LLShaderMgr::DIFFUSE_MAP);
+ shader->disableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
}
gGL.getTexUnit(0)->activate();
glEnable(GL_TEXTURE_2D);
@@ -556,7 +556,7 @@ void LLDrawPoolBump::renderGroup(LLSpatialGroup* group, U32 type, U32 mask, BOOL
for (LLSpatialGroup::drawmap_elem_t::iterator k = draw_info.begin(); k != draw_info.end(); ++k)
{
LLDrawInfo& params = **k;
-
+
applyModelMatrix(params);
params.mVertexBuffer->setBuffer(mask);
diff --git a/indra/newview/lldrawpoolground.cpp b/indra/newview/lldrawpoolground.cpp
index 3500d9471f..c7e8aa32b7 100644
--- a/indra/newview/lldrawpoolground.cpp
+++ b/indra/newview/lldrawpoolground.cpp
@@ -44,7 +44,7 @@
#include "pipeline.h"
#include "llagent.h"
#include "llviewerregion.h"
-#include "llglslshader.h"
+#include "llviewershadermgr.h"
LLDrawPoolGround::LLDrawPoolGround() :
LLFacePool(POOL_GROUND)
@@ -58,7 +58,7 @@ LLDrawPool *LLDrawPoolGround::instancePool()
void LLDrawPoolGround::prerender()
{
- mVertexShaderLevel = LLShaderMgr::getVertexShaderLevel(LLShaderMgr::SHADER_ENVIRONMENT);
+ mVertexShaderLevel = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_ENVIRONMENT);
}
void LLDrawPoolGround::render(S32 pass)
diff --git a/indra/newview/lldrawpoolsimple.cpp b/indra/newview/lldrawpoolsimple.cpp
index b534886047..2015535b30 100644
--- a/indra/newview/lldrawpoolsimple.cpp
+++ b/indra/newview/lldrawpoolsimple.cpp
@@ -40,7 +40,7 @@
#include "llsky.h"
#include "pipeline.h"
#include "llspatialpartition.h"
-#include "llglslshader.h"
+#include "llviewershadermgr.h"
#include "llrender.h"
@@ -54,7 +54,7 @@ void LLDrawPoolGlow::render(S32 pass)
LLGLDisable test(GL_ALPHA_TEST);
gGL.setSceneBlendType(LLRender::BT_ADD);
- U32 shader_level = LLShaderMgr::getVertexShaderLevel(LLShaderMgr::SHADER_OBJECT);
+ U32 shader_level = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_OBJECT);
if (shader_level > 0 && fullbright_shader)
{
@@ -92,7 +92,7 @@ LLDrawPoolSimple::LLDrawPoolSimple() :
void LLDrawPoolSimple::prerender()
{
- mVertexShaderLevel = LLShaderMgr::getVertexShaderLevel(LLShaderMgr::SHADER_OBJECT);
+ mVertexShaderLevel = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_OBJECT);
}
void LLDrawPoolSimple::beginRenderPass(S32 pass)
@@ -113,7 +113,7 @@ void LLDrawPoolSimple::beginRenderPass(S32 pass)
if (mVertexShaderLevel > 0)
{
simple_shader->bind();
- simple_shader->uniform1f(LLShaderMgr::FULLBRIGHT, 0.f);
+ simple_shader->uniform1f(LLViewerShaderMgr::FULLBRIGHT, 0.f);
}
else
{
@@ -161,7 +161,7 @@ void LLDrawPoolSimple::render(S32 pass)
if (mVertexShaderLevel > 0)
{
fullbright_shader->bind();
- fullbright_shader->uniform1f(LLShaderMgr::FULLBRIGHT, 1.f);
+ fullbright_shader->uniform1f(LLViewerShaderMgr::FULLBRIGHT, 1.f);
}
else
{
diff --git a/indra/newview/lldrawpoolsky.cpp b/indra/newview/lldrawpoolsky.cpp
index 585af6c47f..2687e6d2c0 100644
--- a/indra/newview/lldrawpoolsky.cpp
+++ b/indra/newview/lldrawpoolsky.cpp
@@ -46,7 +46,7 @@
#include "llvosky.h"
#include "llworld.h" // To get water height
#include "pipeline.h"
-#include "llglslshader.h"
+#include "llviewershadermgr.h"
LLDrawPoolSky::LLDrawPoolSky() :
LLFacePool(POOL_SKY), mShader(NULL)
@@ -60,7 +60,7 @@ LLDrawPool *LLDrawPoolSky::instancePool()
void LLDrawPoolSky::prerender()
{
- mVertexShaderLevel = LLShaderMgr::getVertexShaderLevel(LLShaderMgr::SHADER_ENVIRONMENT);
+ mVertexShaderLevel = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_ENVIRONMENT);
gSky.mVOSkyp->updateGeometry(gSky.mVOSkyp->mDrawable);
}
diff --git a/indra/newview/lldrawpoolterrain.cpp b/indra/newview/lldrawpoolterrain.cpp
index 854067a32d..e5850a0057 100644
--- a/indra/newview/lldrawpoolterrain.cpp
+++ b/indra/newview/lldrawpoolterrain.cpp
@@ -51,7 +51,7 @@
#include "llviewerimagelist.h" // To get alpha gradients
#include "llworld.h"
#include "pipeline.h"
-#include "llglslshader.h"
+#include "llviewershadermgr.h"
#include "llrender.h"
const F32 DETAIL_SCALE = 1.f/16.f;
@@ -101,7 +101,7 @@ LLDrawPool *LLDrawPoolTerrain::instancePool()
void LLDrawPoolTerrain::prerender()
{
- mVertexShaderLevel = LLShaderMgr::getVertexShaderLevel(LLShaderMgr::SHADER_ENVIRONMENT);
+ mVertexShaderLevel = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_ENVIRONMENT);
if (mVertexShaderLevel > 0)
{
sDetailMode = 1;
@@ -239,7 +239,7 @@ void LLDrawPoolTerrain::renderFullShader()
//
// detail texture 0
//
- S32 detail0 = sShader->enableTexture(LLShaderMgr::TERRAIN_DETAIL0);
+ S32 detail0 = sShader->enableTexture(LLViewerShaderMgr::TERRAIN_DETAIL0);
LLViewerImage::bindTexture(detail_texture0p,detail0);
gGL.getTexUnit(0)->activate();
@@ -257,7 +257,7 @@ void LLDrawPoolTerrain::renderFullShader()
//
// detail texture 1
//
- S32 detail1 = sShader->enableTexture(LLShaderMgr::TERRAIN_DETAIL1);
+ S32 detail1 = sShader->enableTexture(LLViewerShaderMgr::TERRAIN_DETAIL1);
LLViewerImage::bindTexture(detail_texture1p,detail1);
/// ALPHA TEXTURE COORDS 0:
@@ -268,7 +268,7 @@ void LLDrawPoolTerrain::renderFullShader()
// detail texture 2
//
- S32 detail2 = sShader->enableTexture(LLShaderMgr::TERRAIN_DETAIL2);
+ S32 detail2 = sShader->enableTexture(LLViewerShaderMgr::TERRAIN_DETAIL2);
LLViewerImage::bindTexture(detail_texture2p,detail2);
glEnable(GL_TEXTURE_2D);
@@ -282,7 +282,7 @@ void LLDrawPoolTerrain::renderFullShader()
//
// detail texture 3
//
- S32 detail3 = sShader->enableTexture(LLShaderMgr::TERRAIN_DETAIL3);
+ S32 detail3 = sShader->enableTexture(LLViewerShaderMgr::TERRAIN_DETAIL3);
LLViewerImage::bindTexture(detail_texture3p,detail3);
/// ALPHA TEXTURE COORDS 2:
@@ -295,18 +295,18 @@ void LLDrawPoolTerrain::renderFullShader()
//
// Alpha Ramp
//
- S32 alpha_ramp = sShader->enableTexture(LLShaderMgr::TERRAIN_ALPHARAMP);
+ S32 alpha_ramp = sShader->enableTexture(LLViewerShaderMgr::TERRAIN_ALPHARAMP);
LLViewerImage::bindTexture(m2DAlphaRampImagep,alpha_ramp);
// GL_BLEND disabled by default
drawLoop();
// Disable multitexture
- sShader->disableTexture(LLShaderMgr::TERRAIN_ALPHARAMP);
- sShader->disableTexture(LLShaderMgr::TERRAIN_DETAIL0);
- sShader->disableTexture(LLShaderMgr::TERRAIN_DETAIL1);
- sShader->disableTexture(LLShaderMgr::TERRAIN_DETAIL2);
- sShader->disableTexture(LLShaderMgr::TERRAIN_DETAIL3);
+ sShader->disableTexture(LLViewerShaderMgr::TERRAIN_ALPHARAMP);
+ sShader->disableTexture(LLViewerShaderMgr::TERRAIN_DETAIL0);
+ sShader->disableTexture(LLViewerShaderMgr::TERRAIN_DETAIL1);
+ sShader->disableTexture(LLViewerShaderMgr::TERRAIN_DETAIL2);
+ sShader->disableTexture(LLViewerShaderMgr::TERRAIN_DETAIL3);
LLImageGL::unbindTexture(alpha_ramp, GL_TEXTURE_2D);
gGL.getTexUnit(4)->activate();
diff --git a/indra/newview/lldrawpooltree.cpp b/indra/newview/lldrawpooltree.cpp
index 1ebd0772a8..33f23ab6fa 100644
--- a/indra/newview/lldrawpooltree.cpp
+++ b/indra/newview/lldrawpooltree.cpp
@@ -40,7 +40,7 @@
#include "llvotree.h"
#include "pipeline.h"
#include "llviewercamera.h"
-#include "llglslshader.h"
+#include "llviewershadermgr.h"
#include "llrender.h"
S32 LLDrawPoolTree::sDiffTex = 0;
@@ -61,7 +61,7 @@ LLDrawPool *LLDrawPoolTree::instancePool()
void LLDrawPoolTree::prerender()
{
- mVertexShaderLevel = LLShaderMgr::getVertexShaderLevel(LLShaderMgr::SHADER_OBJECT);
+ mVertexShaderLevel = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_OBJECT);
}
void LLDrawPoolTree::beginRenderPass(S32 pass)
diff --git a/indra/newview/lldrawpoolwater.cpp b/indra/newview/lldrawpoolwater.cpp
index e76423c8eb..f7770f001c 100644
--- a/indra/newview/lldrawpoolwater.cpp
+++ b/indra/newview/lldrawpoolwater.cpp
@@ -51,7 +51,7 @@
#include "llvowater.h"
#include "llworld.h"
#include "pipeline.h"
-#include "llglslshader.h"
+#include "llviewershadermgr.h"
#include "llwaterparammanager.h"
const LLUUID WATER_TEST("2bfd3884-7e27-69b9-ba3a-3e673f680004");
@@ -100,8 +100,8 @@ LLDrawPool *LLDrawPoolWater::instancePool()
void LLDrawPoolWater::prerender()
{
- mVertexShaderLevel = (gGLManager.mHasCubeMap && LLFeatureManager::getInstance()->isFeatureAvailable("RenderCubeMap")) ?
- LLShaderMgr::getVertexShaderLevel(LLShaderMgr::SHADER_WATER) : 0;
+ mVertexShaderLevel = (gGLManager.mHasCubeMap && LLCubeMap::sUseCubeMaps) ?
+ LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_WATER) : 0;
// got rid of modulation by light color since it got a little too
// green at sunset and sl-57047 (underwater turns black at 8:00)
@@ -385,7 +385,7 @@ void LLDrawPoolWater::shade()
sTime = (F32)LLFrameTimer::getElapsedSeconds()*0.5f;
- S32 reftex = shader->enableTexture(LLShaderMgr::WATER_REFTEX);
+ S32 reftex = shader->enableTexture(LLViewerShaderMgr::WATER_REFTEX);
if (reftex > -1)
{
@@ -395,7 +395,7 @@ void LLDrawPoolWater::shade()
}
//bind normal map
- S32 bumpTex = shader->enableTexture(LLShaderMgr::BUMP_MAP);
+ S32 bumpTex = shader->enableTexture(LLViewerShaderMgr::BUMP_MAP);
LLWaterParamManager * param_mgr = LLWaterParamManager::instance();
@@ -410,15 +410,15 @@ void LLDrawPoolWater::shade()
mWaterNormp->setMipFilterNearest (mWaterNormp->getMipFilterNearest(),
!gSavedSettings.getBOOL("RenderWaterMipNormal"));
- S32 screentex = shader->enableTexture(LLShaderMgr::WATER_SCREENTEX);
+ S32 screentex = shader->enableTexture(LLViewerShaderMgr::WATER_SCREENTEX);
stop_glerror();
shader->bind();
if (screentex > -1)
{
- shader->uniform4fv(LLShaderMgr::WATER_FOGCOLOR, 1, sWaterFogColor.mV);
- shader->uniform1f(LLShaderMgr::WATER_FOGDENSITY,
+ shader->uniform4fv(LLViewerShaderMgr::WATER_FOGCOLOR, 1, sWaterFogColor.mV);
+ shader->uniform1f(LLViewerShaderMgr::WATER_FOGDENSITY,
param_mgr->getFogDensity());
}
@@ -427,7 +427,7 @@ void LLDrawPoolWater::shade()
if (mVertexShaderLevel == 1)
{
sWaterFogColor.mV[3] = param_mgr->mDensitySliderValue;
- shader->uniform4fv(LLShaderMgr::WATER_FOGCOLOR, 1, sWaterFogColor.mV);
+ shader->uniform4fv(LLViewerShaderMgr::WATER_FOGCOLOR, 1, sWaterFogColor.mV);
}
F32 screenRes[] =
@@ -438,7 +438,7 @@ void LLDrawPoolWater::shade()
shader->uniform2fv("screenRes", 1, screenRes);
stop_glerror();
- S32 diffTex = shader->enableTexture(LLShaderMgr::DIFFUSE_MAP);
+ S32 diffTex = shader->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
stop_glerror();
light_dir.normVec();
@@ -447,14 +447,14 @@ void LLDrawPoolWater::shade()
light_diffuse *= 6.f;
//shader->uniformMatrix4fv("inverse_ref", 1, GL_FALSE, (GLfloat*) gGLObliqueProjectionInverse.mMatrix);
- shader->uniform1f(LLShaderMgr::WATER_WATERHEIGHT, eyedepth);
- shader->uniform1f(LLShaderMgr::WATER_TIME, sTime);
- shader->uniform3fv(LLShaderMgr::WATER_EYEVEC, 1, LLViewerCamera::getInstance()->getOrigin().mV);
- shader->uniform3fv(LLShaderMgr::WATER_SPECULAR, 1, light_diffuse.mV);
- shader->uniform1f(LLShaderMgr::WATER_SPECULAR_EXP, light_exp);
- shader->uniform2fv(LLShaderMgr::WATER_WAVE_DIR1, 1, param_mgr->getWave1Dir().mV);
- shader->uniform2fv(LLShaderMgr::WATER_WAVE_DIR2, 1, param_mgr->getWave2Dir().mV);
- shader->uniform3fv(LLShaderMgr::WATER_LIGHT_DIR, 1, light_dir.mV);
+ shader->uniform1f(LLViewerShaderMgr::WATER_WATERHEIGHT, eyedepth);
+ shader->uniform1f(LLViewerShaderMgr::WATER_TIME, sTime);
+ shader->uniform3fv(LLViewerShaderMgr::WATER_EYEVEC, 1, LLViewerCamera::getInstance()->getOrigin().mV);
+ shader->uniform3fv(LLViewerShaderMgr::WATER_SPECULAR, 1, light_diffuse.mV);
+ shader->uniform1f(LLViewerShaderMgr::WATER_SPECULAR_EXP, light_exp);
+ shader->uniform2fv(LLViewerShaderMgr::WATER_WAVE_DIR1, 1, param_mgr->getWave1Dir().mV);
+ shader->uniform2fv(LLViewerShaderMgr::WATER_WAVE_DIR2, 1, param_mgr->getWave2Dir().mV);
+ shader->uniform3fv(LLViewerShaderMgr::WATER_LIGHT_DIR, 1, light_dir.mV);
shader->uniform3fv("normScale", 1, param_mgr->getNormalScale().mV);
shader->uniform1f("fresnelScale", param_mgr->getFresnelScale());
@@ -474,12 +474,12 @@ void LLDrawPoolWater::shade()
if (LLViewerCamera::getInstance()->cameraUnderWater())
{
water_color.setVec(1.f, 1.f, 1.f, 0.4f);
- shader->uniform1f(LLShaderMgr::WATER_REFSCALE, param_mgr->getScaleBelow());
+ shader->uniform1f(LLViewerShaderMgr::WATER_REFSCALE, param_mgr->getScaleBelow());
}
else
{
water_color.setVec(1.f, 1.f, 1.f, 0.5f*(1.f + up_dot));
- shader->uniform1f(LLShaderMgr::WATER_REFSCALE, param_mgr->getScaleAbove());
+ shader->uniform1f(LLViewerShaderMgr::WATER_REFSCALE, param_mgr->getScaleAbove());
}
if (water_color.mV[3] > 0.9f)
@@ -527,12 +527,12 @@ void LLDrawPoolWater::shade()
}
}
- shader->disableTexture(LLShaderMgr::ENVIRONMENT_MAP, GL_TEXTURE_CUBE_MAP_ARB);
- shader->disableTexture(LLShaderMgr::WATER_SCREENTEX);
- shader->disableTexture(LLShaderMgr::BUMP_MAP);
- shader->disableTexture(LLShaderMgr::DIFFUSE_MAP);
- shader->disableTexture(LLShaderMgr::WATER_REFTEX);
- shader->disableTexture(LLShaderMgr::WATER_SCREENDEPTH);
+ shader->disableTexture(LLViewerShaderMgr::ENVIRONMENT_MAP, GL_TEXTURE_CUBE_MAP_ARB);
+ shader->disableTexture(LLViewerShaderMgr::WATER_SCREENTEX);
+ shader->disableTexture(LLViewerShaderMgr::BUMP_MAP);
+ shader->disableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
+ shader->disableTexture(LLViewerShaderMgr::WATER_REFTEX);
+ shader->disableTexture(LLViewerShaderMgr::WATER_SCREENDEPTH);
shader->unbind();
gGL.getTexUnit(0)->activate();
diff --git a/indra/newview/llhudrender.cpp b/indra/newview/llhudrender.cpp
index 0f83da8240..0668655ac3 100644
--- a/indra/newview/llhudrender.cpp
+++ b/indra/newview/llhudrender.cpp
@@ -33,6 +33,7 @@
#include "llhudrender.h"
+#include "llrender.h"
#include "llgl.h"
#include "llviewercamera.h"
#include "v3math.h"
diff --git a/indra/newview/llviewercamera.cpp b/indra/newview/llviewercamera.cpp
index a1a2c34222..5f6fcb70e3 100644
--- a/indra/newview/llviewercamera.cpp
+++ b/indra/newview/llviewercamera.cpp
@@ -50,9 +50,6 @@
#include "lltoolmgr.h"
#include "llviewerjoystick.h"
-GLfloat gGLZFar;
-GLfloat gGLZNear;
-
//glu pick matrix implementation borrowed from Mesa3D
glh::matrix4f gl_pick_matrix(GLfloat x, GLfloat y, GLfloat width, GLfloat height, GLint* viewport)
{
@@ -146,12 +143,6 @@ void LLViewerCamera::updateCameraLocation(const LLVector3 &center,
mScreenPixelArea =(S32)((F32)mViewHeightInPixels * ((F32)mViewHeightInPixels * mAspect));
}
-// Handy copies of last good GL matrices
-F64 gGLModelView[16];
-F64 gGLLastModelView[16];
-F64 gGLProjection[16];
-S32 gGLViewport[4];
-
const LLMatrix4 &LLViewerCamera::getProjection() const
{
calcProjection(getFar());
@@ -343,9 +334,6 @@ void LLViewerCamera::setPerspective(BOOL for_selection,
gGLProjection[i] = proj_mat.m[i];
}
- gGLZNear = z_near;
- gGLZFar = z_far;
-
glMatrixMode( GL_MODELVIEW );
glh::matrix4f modelview((GLfloat*) OGL_TO_CFR_ROTATION);
diff --git a/indra/newview/llviewercamera.h b/indra/newview/llviewercamera.h
index a16f25ff81..cc37851d05 100644
--- a/indra/newview/llviewercamera.h
+++ b/indra/newview/llviewercamera.h
@@ -111,11 +111,4 @@ protected:
public:
};
-extern F64 gGLModelView[16];
-extern F64 gGLLastModelView[16];
-extern F64 gGLProjection[16];
-extern S32 gGLViewport[4];
-extern F32 gGLZNear;
-extern F32 gGLZFar;
-
#endif // LL_LLVIEWERCAMERA_H
diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp
index 422546c811..f3acad35da 100644
--- a/indra/newview/llviewercontrol.cpp
+++ b/indra/newview/llviewercontrol.cpp
@@ -43,7 +43,7 @@
#include "lldrawpoolterrain.h"
#include "llflexibleobject.h"
#include "llfeaturemanager.h"
-#include "llglslshader.h"
+#include "llviewershadermgr.h"
#include "llnetmap.h"
#include "llpanelgeneral.h"
#include "llpanelinput.h"
@@ -114,7 +114,7 @@ static bool handleTerrainDetailChanged(const LLSD& newvalue)
static bool handleSetShaderChanged(const LLSD& newvalue)
{
- LLShaderMgr::setShaders();
+ LLViewerShaderMgr::instance()->setShaders();
return true;
}
diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp
index d4249ce135..b2cf873a21 100644
--- a/indra/newview/llviewerdisplay.cpp
+++ b/indra/newview/llviewerdisplay.cpp
@@ -68,6 +68,7 @@
#include "llspatialpartition.h"
#include "llappviewer.h"
#include "llstartup.h"
+#include "llviewershadermgr.h"
#include "llfasttimer.h"
#include "llfloatertools.h"
#include "llviewerimagelist.h"
@@ -531,7 +532,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
gFrameStats.start(LLFrameStats::UPDATE_CULL);
S32 water_clip = 0;
- if ((LLShaderMgr::getVertexShaderLevel(LLShaderMgr::SHADER_ENVIRONMENT) > 1) &&
+ if ((LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_ENVIRONMENT) > 1) &&
gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_WATER))
{
if (LLViewerCamera::getInstance()->cameraUnderWater())
diff --git a/indra/newview/llviewerjointmesh.cpp b/indra/newview/llviewerjointmesh.cpp
index 95166278d5..f975e56b95 100644
--- a/indra/newview/llviewerjointmesh.cpp
+++ b/indra/newview/llviewerjointmesh.cpp
@@ -56,7 +56,7 @@
#include "llvoavatar.h"
#include "llsky.h"
#include "pipeline.h"
-#include "llglslshader.h"
+#include "llviewershadermgr.h"
#include "llmath.h"
#include "v4math.h"
#include "m3math.h"
@@ -880,7 +880,7 @@ void LLViewerJointMesh::updateJointGeometry()
&& mFace
&& mMesh->hasWeights()
&& mFace->mVertexBuffer.notNull()
- && LLShaderMgr::getVertexShaderLevel(LLShaderMgr::SHADER_AVATAR) == 0))
+ && LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_AVATAR) == 0))
{
return;
}
diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp
new file mode 100644
index 0000000000..fe0f3f12a6
--- /dev/null
+++ b/indra/newview/llviewershadermgr.cpp
@@ -0,0 +1,1094 @@
+/**
+ * @file llviewershadermgr.cpp
+ * @brief Viewer shader manager implementation.
+ *
+ * $LicenseInfo:firstyear=2005&license=viewergpl$
+ *
+ * Copyright (c) 2005-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$
+ */
+
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llfeaturemanager.h"
+#include "llviewershadermgr.h"
+
+#include "llfile.h"
+#include "llviewerwindow.h"
+#include "llviewercontrol.h"
+#include "pipeline.h"
+#include "llworld.h"
+#include "llwlparammanager.h"
+#include "llwaterparammanager.h"
+#include "llsky.h"
+#include "llvosky.h"
+#include "llrender.h"
+
+#if LL_DARWIN
+#include "OpenGL/OpenGL.h"
+#endif
+
+#ifdef LL_RELEASE_FOR_DOWNLOAD
+#define UNIFORM_ERRS LL_WARNS_ONCE("Shader")
+#else
+#define UNIFORM_ERRS LL_ERRS("Shader")
+#endif
+
+// Lots of STL stuff in here, using namespace std to keep things more readable
+using std::vector;
+using std::pair;
+using std::make_pair;
+using std::string;
+
+LLVector4 gShinyOrigin;
+
+//object shaders
+LLGLSLShader gObjectSimpleProgram;
+LLGLSLShader gObjectSimpleWaterProgram;
+LLGLSLShader gObjectFullbrightProgram;
+LLGLSLShader gObjectFullbrightWaterProgram;
+
+LLGLSLShader gObjectFullbrightShinyProgram;
+LLGLSLShader gObjectShinyProgram;
+LLGLSLShader gObjectShinyWaterProgram;
+
+//environment shaders
+LLGLSLShader gTerrainProgram;
+LLGLSLShader gTerrainWaterProgram;
+LLGLSLShader gWaterProgram;
+LLGLSLShader gUnderWaterProgram;
+
+//interface shaders
+LLGLSLShader gHighlightProgram;
+
+//avatar shader handles
+LLGLSLShader gAvatarProgram;
+LLGLSLShader gAvatarWaterProgram;
+LLGLSLShader gAvatarEyeballProgram;
+LLGLSLShader gAvatarPickProgram;
+
+// WindLight shader handles
+LLGLSLShader gWLSkyProgram;
+LLGLSLShader gWLCloudProgram;
+
+// Effects Shaders
+LLGLSLShader gGlowProgram;
+LLGLSLShader gGlowExtractProgram;
+LLGLSLShader gPostColorFilterProgram;
+LLGLSLShader gPostNightVisionProgram;
+
+// Deferred rendering shaders
+LLGLSLShader gDeferredDiffuseProgram;
+
+//current avatar shader parameter pointer
+GLint gAvatarMatrixParam;
+
+LLViewerShaderMgr::LLViewerShaderMgr() :
+ mVertexShaderLevel(SHADER_COUNT, 0)
+{
+/// Make sure WL Sky is the first program
+ mShaderList.push_back(&gWLSkyProgram);
+ mShaderList.push_back(&gWLCloudProgram);
+ mShaderList.push_back(&gAvatarProgram);
+ mShaderList.push_back(&gObjectShinyProgram);
+ mShaderList.push_back(&gWaterProgram);
+ mShaderList.push_back(&gAvatarEyeballProgram);
+ mShaderList.push_back(&gObjectSimpleProgram);
+ mShaderList.push_back(&gObjectFullbrightProgram);
+ mShaderList.push_back(&gObjectFullbrightShinyProgram);
+ mShaderList.push_back(&gTerrainProgram);
+ mShaderList.push_back(&gTerrainWaterProgram);
+ mShaderList.push_back(&gObjectSimpleWaterProgram);
+ mShaderList.push_back(&gObjectFullbrightWaterProgram);
+ mShaderList.push_back(&gAvatarWaterProgram);
+ mShaderList.push_back(&gObjectShinyWaterProgram);
+ mShaderList.push_back(&gUnderWaterProgram);
+}
+
+LLViewerShaderMgr::~LLViewerShaderMgr()
+{
+ mVertexShaderLevel.clear();
+ mShaderList.clear();
+}
+
+// static
+LLViewerShaderMgr * LLViewerShaderMgr::instance()
+{
+ if(NULL == sInstance)
+ {
+ sInstance = new LLViewerShaderMgr();
+ }
+
+ return static_cast<LLViewerShaderMgr*>(sInstance);
+ }
+
+void LLViewerShaderMgr::initAttribsAndUniforms(void)
+ {
+ if (mReservedAttribs.empty())
+ {
+ mReservedAttribs.push_back("materialColor");
+ mReservedAttribs.push_back("specularColor");
+ mReservedAttribs.push_back("binormal");
+
+ mAvatarAttribs.reserve(5);
+ mAvatarAttribs.push_back("weight");
+ mAvatarAttribs.push_back("clothing");
+ mAvatarAttribs.push_back("gWindDir");
+ mAvatarAttribs.push_back("gSinWaveParams");
+ mAvatarAttribs.push_back("gGravity");
+
+ mAvatarUniforms.push_back("matrixPalette");
+
+ mReservedUniforms.reserve(24);
+ mReservedUniforms.push_back("diffuseMap");
+ mReservedUniforms.push_back("specularMap");
+ mReservedUniforms.push_back("bumpMap");
+ mReservedUniforms.push_back("environmentMap");
+ mReservedUniforms.push_back("cloude_noise_texture");
+ mReservedUniforms.push_back("fullbright");
+ mReservedUniforms.push_back("lightnorm");
+ mReservedUniforms.push_back("sunlight_color");
+ mReservedUniforms.push_back("ambient");
+ mReservedUniforms.push_back("blue_horizon");
+ mReservedUniforms.push_back("blue_density");
+ mReservedUniforms.push_back("haze_horizon");
+ mReservedUniforms.push_back("haze_density");
+ mReservedUniforms.push_back("cloud_shadow");
+ mReservedUniforms.push_back("density_multiplier");
+ mReservedUniforms.push_back("distance_multiplier");
+ mReservedUniforms.push_back("max_y");
+ mReservedUniforms.push_back("glow");
+ mReservedUniforms.push_back("cloud_color");
+ mReservedUniforms.push_back("cloud_pos_density1");
+ mReservedUniforms.push_back("cloud_pos_density2");
+ mReservedUniforms.push_back("cloud_scale");
+ mReservedUniforms.push_back("gamma");
+ mReservedUniforms.push_back("scene_light_strength");
+
+ mWLUniforms.push_back("camPosLocal");
+
+ mTerrainUniforms.reserve(5);
+ mTerrainUniforms.push_back("detail_0");
+ mTerrainUniforms.push_back("detail_1");
+ mTerrainUniforms.push_back("detail_2");
+ mTerrainUniforms.push_back("detail_3");
+ mTerrainUniforms.push_back("alpha_ramp");
+
+ mGlowUniforms.push_back("glowDelta");
+ mGlowUniforms.push_back("glowStrength");
+
+ mGlowExtractUniforms.push_back("minLuminance");
+ mGlowExtractUniforms.push_back("maxExtractAlpha");
+ mGlowExtractUniforms.push_back("lumWeights");
+ mGlowExtractUniforms.push_back("warmthWeights");
+ mGlowExtractUniforms.push_back("warmthAmount");
+
+ mShinyUniforms.push_back("origin");
+
+ mWaterUniforms.reserve(12);
+ mWaterUniforms.push_back("screenTex");
+ mWaterUniforms.push_back("screenDepth");
+ mWaterUniforms.push_back("refTex");
+ mWaterUniforms.push_back("eyeVec");
+ mWaterUniforms.push_back("time");
+ mWaterUniforms.push_back("d1");
+ mWaterUniforms.push_back("d2");
+ mWaterUniforms.push_back("lightDir");
+ mWaterUniforms.push_back("specular");
+ mWaterUniforms.push_back("lightExp");
+ mWaterUniforms.push_back("fogCol");
+ mWaterUniforms.push_back("kd");
+ mWaterUniforms.push_back("refScale");
+ mWaterUniforms.push_back("waterHeight");
+ }
+ }
+
+
+//============================================================================
+// Set Levels
+
+S32 LLViewerShaderMgr::getVertexShaderLevel(S32 type)
+{
+ return LLPipeline::sDisableShaders ? 0 : mVertexShaderLevel[type];
+}
+
+//============================================================================
+// Shader Management
+
+void LLViewerShaderMgr::setShaders()
+{
+ if (!gPipeline.mInitialized)
+ {
+ return;
+ }
+ // Make sure the compiled shader map is cleared before we recompile shaders.
+ mShaderObjects.clear();
+
+ initAttribsAndUniforms();
+ gPipeline.releaseGLBuffers();
+
+ if (gSavedSettings.getBOOL("VertexShaderEnable"))
+ {
+ LLPipeline::sWaterReflections = gGLManager.mHasCubeMap;
+ LLPipeline::sRenderGlow = gSavedSettings.getBOOL("RenderGlow");
+ }
+ else
+ {
+ LLPipeline::sRenderGlow =
+ LLPipeline::sWaterReflections = FALSE;
+ }
+
+ //hack to reset buffers that change behavior with shaders
+ gPipeline.resetVertexBuffers();
+
+ if (gViewerWindow)
+ {
+ gViewerWindow->setCursor(UI_CURSOR_WAIT);
+ }
+
+ // Lighting
+ gPipeline.setLightingDetail(-1);
+
+ // Shaders
+ LL_INFOS("ShaderLoading") << "\n~~~~~~~~~~~~~~~~~~\n Loading Shaders:\n~~~~~~~~~~~~~~~~~~" << LL_ENDL;
+ for (S32 i = 0; i < SHADER_COUNT; i++)
+ {
+ mVertexShaderLevel[i] = 0;
+ }
+ mMaxAvatarShaderLevel = 0;
+
+ if (LLFeatureManager::getInstance()->isFeatureAvailable("VertexShaderEnable")
+ && gSavedSettings.getBOOL("VertexShaderEnable"))
+ {
+ S32 light_class = 2;
+ S32 env_class = 2;
+ S32 obj_class = 2;
+ S32 effect_class = 2;
+ S32 wl_class = 2;
+ S32 water_class = 2;
+ S32 deferred_class = 0;
+ if (!gSavedSettings.getBOOL("WindLightUseAtmosShaders"))
+ {
+ // user has disabled WindLight in their settings, downgrade
+ // windlight shaders to stub versions.
+ wl_class = 1;
+
+ // if class one or less, turn off more shaders
+ // since higher end cards won't see any real gain
+ // from turning off most of the shaders,
+ // but class one would
+ // TODO: Make water on class one cards color things
+ // beneath it properly
+ if(LLFeatureManager::getInstance()->getGPUClass() < GPU_CLASS_2)
+ {
+ // use lesser water and other stuff
+ light_class = 2;
+ env_class = 0;
+ obj_class = 0;
+ effect_class = 1;
+ water_class = 1;
+ }
+ }
+
+ if (gSavedSettings.getBOOL("RenderDeferred"))
+ {
+ light_class = 1;
+ env_class = 0;
+ obj_class = 0;
+ water_class = 1;
+ effect_class = 1;
+ deferred_class = 1;
+ }
+
+ if(!gSavedSettings.getBOOL("EnableRippleWater"))
+ {
+ water_class = 0;
+ }
+
+ // Trigger a full rebuild of the fallback skybox / cubemap if we've toggled windlight shaders
+ if (mVertexShaderLevel[SHADER_WINDLIGHT] != wl_class && gSky.mVOSkyp.notNull())
+ {
+ gSky.mVOSkyp->forceSkyUpdate();
+ }
+
+ // Load lighting shaders
+ mVertexShaderLevel[SHADER_LIGHTING] = light_class;
+ mVertexShaderLevel[SHADER_INTERFACE] = light_class;
+ mVertexShaderLevel[SHADER_ENVIRONMENT] = env_class;
+ mVertexShaderLevel[SHADER_WATER] = water_class;
+ mVertexShaderLevel[SHADER_OBJECT] = obj_class;
+ mVertexShaderLevel[SHADER_EFFECT] = effect_class;
+ mVertexShaderLevel[SHADER_WINDLIGHT] = wl_class;
+ mVertexShaderLevel[SHADER_DEFERRED] = deferred_class;
+
+ BOOL loaded = loadBasicShaders();
+
+ if (loaded)
+ {
+ gPipeline.mVertexShadersEnabled = TRUE;
+ gPipeline.mVertexShadersLoaded = 1;
+
+ // Load all shaders to set max levels
+ loadShadersEnvironment();
+ loadShadersWater();
+ loadShadersObject();
+ loadShadersWindLight();
+ loadShadersEffects();
+ loadShadersInterface();
+ loadShadersDeferred();
+
+ // Load max avatar shaders to set the max level
+ mVertexShaderLevel[SHADER_AVATAR] = 3;
+ mMaxAvatarShaderLevel = 3;
+ loadShadersAvatar();
+
+#if 0 && LL_DARWIN // force avatar shaders off for mac
+ mVertexShaderLevel[SHADER_AVATAR] = 0;
+ sMaxAvatarShaderLevel = 0;
+#else
+ if (gSavedSettings.getBOOL("RenderAvatarVP"))
+ {
+ BOOL avatar_cloth = gSavedSettings.getBOOL("RenderAvatarCloth");
+ S32 avatar_class = 1;
+
+ // cloth is a class3 shader
+ if(avatar_cloth)
+ {
+ avatar_class = 3;
+ }
+
+ // Set the actual level
+ mVertexShaderLevel[SHADER_AVATAR] = avatar_class;
+ loadShadersAvatar();
+ if (mVertexShaderLevel[SHADER_AVATAR] != avatar_class)
+ {
+ if (mVertexShaderLevel[SHADER_AVATAR] == 0)
+ {
+ gSavedSettings.setBOOL("RenderAvatarVP", FALSE);
+ }
+ if(llmax(mVertexShaderLevel[SHADER_AVATAR]-1,0) >= 3)
+ {
+ avatar_cloth = true;
+ }
+ else
+ {
+ avatar_cloth = false;
+ }
+ gSavedSettings.setBOOL("RenderAvatarCloth", avatar_cloth);
+ }
+ }
+ else
+ {
+ mVertexShaderLevel[SHADER_AVATAR] = 0;
+ gSavedSettings.setBOOL("RenderAvatarCloth", FALSE);
+ loadShadersAvatar(); // unloads
+ }
+#endif
+ }
+ else
+ {
+ gPipeline.mVertexShadersEnabled = FALSE;
+ gPipeline.mVertexShadersLoaded = 0;
+ mVertexShaderLevel[SHADER_LIGHTING] = 0;
+ mVertexShaderLevel[SHADER_INTERFACE] = 0;
+ mVertexShaderLevel[SHADER_ENVIRONMENT] = 0;
+ mVertexShaderLevel[SHADER_WATER] = 0;
+ mVertexShaderLevel[SHADER_OBJECT] = 0;
+ mVertexShaderLevel[SHADER_EFFECT] = 0;
+ mVertexShaderLevel[SHADER_WINDLIGHT] = 0;
+ }
+ }
+ else
+ {
+ gPipeline.mVertexShadersEnabled = FALSE;
+ gPipeline.mVertexShadersLoaded = 0;
+ mVertexShaderLevel[SHADER_LIGHTING] = 0;
+ mVertexShaderLevel[SHADER_INTERFACE] = 0;
+ mVertexShaderLevel[SHADER_ENVIRONMENT] = 0;
+ mVertexShaderLevel[SHADER_WATER] = 0;
+ mVertexShaderLevel[SHADER_OBJECT] = 0;
+ mVertexShaderLevel[SHADER_EFFECT] = 0;
+ mVertexShaderLevel[SHADER_WINDLIGHT] = 0;
+ }
+
+ if (gViewerWindow)
+ {
+ gViewerWindow->setCursor(UI_CURSOR_ARROW);
+ }
+ gPipeline.createGLBuffers();
+}
+
+void LLViewerShaderMgr::unloadShaders()
+{
+ gObjectSimpleProgram.unload();
+ gObjectSimpleWaterProgram.unload();
+ gObjectFullbrightProgram.unload();
+ gObjectFullbrightWaterProgram.unload();
+
+ gObjectShinyProgram.unload();
+ gObjectFullbrightShinyProgram.unload();
+ gObjectShinyWaterProgram.unload();
+ gWaterProgram.unload();
+ gUnderWaterProgram.unload();
+ gTerrainProgram.unload();
+ gTerrainWaterProgram.unload();
+ gGlowProgram.unload();
+ gGlowExtractProgram.unload();
+ gAvatarProgram.unload();
+ gAvatarWaterProgram.unload();
+ gAvatarEyeballProgram.unload();
+ gAvatarPickProgram.unload();
+ gHighlightProgram.unload();
+
+ gWLSkyProgram.unload();
+ gWLCloudProgram.unload();
+
+ gPostColorFilterProgram.unload();
+ gPostNightVisionProgram.unload();
+
+ gDeferredDiffuseProgram.unload();
+
+ mVertexShaderLevel[SHADER_LIGHTING] = 0;
+ mVertexShaderLevel[SHADER_OBJECT] = 0;
+ mVertexShaderLevel[SHADER_AVATAR] = 0;
+ mVertexShaderLevel[SHADER_ENVIRONMENT] = 0;
+ mVertexShaderLevel[SHADER_WATER] = 0;
+ mVertexShaderLevel[SHADER_INTERFACE] = 0;
+
+ gPipeline.mVertexShadersLoaded = 0;
+}
+
+BOOL LLViewerShaderMgr::loadBasicShaders()
+{
+ // Load basic dependency shaders first
+ // All of these have to load for any shaders to function
+
+#if LL_DARWIN // Mac can't currently handle all 8 lights,
+ S32 sum_lights_class = 2;
+#else
+ S32 sum_lights_class = 3;
+
+ // class one cards will get the lower sum lights
+ // class zero we're not going to think about
+ // since a class zero card COULD be a ridiculous new card
+ // and old cards should have the features masked
+ if(LLFeatureManager::getInstance()->getGPUClass() == GPU_CLASS_1)
+ {
+ sum_lights_class = 2;
+ }
+#endif
+
+ // If we have sun and moon only checked, then only sum those lights.
+ if (gPipeline.getLightingDetail() == 0)
+ {
+ sum_lights_class = 1;
+ }
+
+ // Load the Basic Vertex Shaders at the appropriate level.
+ // (in order of shader function call depth for reference purposes, deepest level first)
+
+ vector< pair<string, S32> > shaders;
+ shaders.reserve(10);
+ shaders.push_back( make_pair( "windlight/atmosphericsVarsV.glsl", mVertexShaderLevel[SHADER_WINDLIGHT] ) );
+ shaders.push_back( make_pair( "windlight/atmosphericsHelpersV.glsl", mVertexShaderLevel[SHADER_WINDLIGHT] ) );
+ shaders.push_back( make_pair( "lighting/lightFuncV.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) );
+ shaders.push_back( make_pair( "lighting/sumLightsV.glsl", sum_lights_class ) );
+ shaders.push_back( make_pair( "lighting/lightV.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) );
+ shaders.push_back( make_pair( "lighting/lightFuncSpecularV.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) );
+ shaders.push_back( make_pair( "lighting/sumLightsSpecularV.glsl", sum_lights_class ) );
+ shaders.push_back( make_pair( "lighting/lightSpecularV.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) );
+ shaders.push_back( make_pair( "windlight/atmosphericsV.glsl", mVertexShaderLevel[SHADER_WINDLIGHT] ) );
+ shaders.push_back( make_pair( "avatar/avatarSkinV.glsl", 1 ) );
+
+ // We no longer have to bind the shaders to global glhandles, they are automatically added to a map now.
+ for (U32 i = 0; i < shaders.size(); i++)
+ {
+ // Note usage of GL_VERTEX_SHADER_ARB
+ if (loadShaderFile(shaders[i].first, shaders[i].second, GL_VERTEX_SHADER_ARB) == 0)
+ {
+ return FALSE;
+ }
+ }
+
+ // Load the Basic Fragment Shaders at the appropriate level.
+ // (in order of shader function call depth for reference purposes, deepest level first)
+
+ shaders.clear();
+ shaders.reserve(12);
+ shaders.push_back( make_pair( "windlight/atmosphericsVarsF.glsl", mVertexShaderLevel[SHADER_WINDLIGHT] ) );
+ shaders.push_back( make_pair( "windlight/gammaF.glsl", mVertexShaderLevel[SHADER_WINDLIGHT]) );
+ shaders.push_back( make_pair( "windlight/atmosphericsF.glsl", mVertexShaderLevel[SHADER_WINDLIGHT] ) );
+ shaders.push_back( make_pair( "windlight/transportF.glsl", mVertexShaderLevel[SHADER_WINDLIGHT] ) );
+ shaders.push_back( make_pair( "environment/waterFogF.glsl", mVertexShaderLevel[SHADER_WATER] ) );
+ shaders.push_back( make_pair( "lighting/lightF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) );
+ shaders.push_back( make_pair( "lighting/lightFullbrightF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) );
+ shaders.push_back( make_pair( "lighting/lightWaterF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) );
+ shaders.push_back( make_pair( "lighting/lightFullbrightWaterF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) );
+ shaders.push_back( make_pair( "lighting/lightShinyF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) );
+ shaders.push_back( make_pair( "lighting/lightFullbrightShinyF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) );
+ shaders.push_back( make_pair( "lighting/lightShinyWaterF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) );
+
+ for (U32 i = 0; i < shaders.size(); i++)
+ {
+ // Note usage of GL_FRAGMENT_SHADER_ARB
+ if (loadShaderFile(shaders[i].first, shaders[i].second, GL_FRAGMENT_SHADER_ARB) == 0)
+ {
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+BOOL LLViewerShaderMgr::loadShadersEnvironment()
+{
+ BOOL success = TRUE;
+
+ if (mVertexShaderLevel[SHADER_ENVIRONMENT] == 0)
+ {
+ gTerrainProgram.unload();
+ return FALSE;
+ }
+
+ if (success)
+ {
+ gTerrainProgram.mName = "Terrain Shader";
+ gTerrainProgram.mFeatures.calculatesLighting = true;
+ gTerrainProgram.mFeatures.calculatesAtmospherics = true;
+ gTerrainProgram.mFeatures.hasAtmospherics = true;
+ gTerrainProgram.mFeatures.hasGamma = true;
+ gTerrainProgram.mShaderFiles.clear();
+ gTerrainProgram.mShaderFiles.push_back(make_pair("environment/terrainV.glsl", GL_VERTEX_SHADER_ARB));
+ gTerrainProgram.mShaderFiles.push_back(make_pair("environment/terrainF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gTerrainProgram.mShaderLevel = mVertexShaderLevel[SHADER_ENVIRONMENT];
+ success = gTerrainProgram.createShader(NULL, &mTerrainUniforms);
+ }
+
+ if (!success)
+ {
+ mVertexShaderLevel[SHADER_ENVIRONMENT] = 0;
+ return FALSE;
+ }
+
+ LLWorld::getInstance()->updateWaterObjects();
+
+ return TRUE;
+}
+
+BOOL LLViewerShaderMgr::loadShadersWater()
+{
+ BOOL success = TRUE;
+ BOOL terrainWaterSuccess = TRUE;
+
+ if (mVertexShaderLevel[SHADER_WATER] == 0)
+ {
+ gWaterProgram.unload();
+ gUnderWaterProgram.unload();
+ gTerrainWaterProgram.unload();
+ return FALSE;
+ }
+
+ if (success)
+ {
+ // load water shader
+ gWaterProgram.mName = "Water Shader";
+ gWaterProgram.mFeatures.calculatesAtmospherics = true;
+ gWaterProgram.mFeatures.hasGamma = true;
+ gWaterProgram.mFeatures.hasTransport = true;
+ gWaterProgram.mShaderFiles.clear();
+ gWaterProgram.mShaderFiles.push_back(make_pair("environment/waterV.glsl", GL_VERTEX_SHADER_ARB));
+ gWaterProgram.mShaderFiles.push_back(make_pair("environment/waterF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_WATER];
+ success = gWaterProgram.createShader(NULL, &mWaterUniforms);
+ }
+
+ if (success)
+ {
+ //load under water vertex shader
+ gUnderWaterProgram.mName = "Underwater Shader";
+ gUnderWaterProgram.mFeatures.calculatesAtmospherics = true;
+ gUnderWaterProgram.mShaderFiles.clear();
+ gUnderWaterProgram.mShaderFiles.push_back(make_pair("environment/waterV.glsl", GL_VERTEX_SHADER_ARB));
+ gUnderWaterProgram.mShaderFiles.push_back(make_pair("environment/underWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gUnderWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_WATER];
+ gUnderWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
+
+ success = gUnderWaterProgram.createShader(NULL, &mWaterUniforms);
+ }
+
+ if (success)
+ {
+ //load terrain water shader
+ gTerrainWaterProgram.mName = "Terrain Water Shader";
+ gTerrainWaterProgram.mFeatures.calculatesLighting = true;
+ gTerrainWaterProgram.mFeatures.calculatesAtmospherics = true;
+ gTerrainWaterProgram.mFeatures.hasAtmospherics = true;
+ gTerrainWaterProgram.mFeatures.hasWaterFog = true;
+ gTerrainWaterProgram.mShaderFiles.clear();
+ gTerrainWaterProgram.mShaderFiles.push_back(make_pair("environment/terrainV.glsl", GL_VERTEX_SHADER_ARB));
+ gTerrainWaterProgram.mShaderFiles.push_back(make_pair("environment/terrainWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gTerrainWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_ENVIRONMENT];
+ gTerrainWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
+ terrainWaterSuccess = gTerrainWaterProgram.createShader(NULL, &mTerrainUniforms);
+ }
+
+ /// Keep track of water shader levels
+ if (gWaterProgram.mShaderLevel != mVertexShaderLevel[SHADER_WATER]
+ || gUnderWaterProgram.mShaderLevel != mVertexShaderLevel[SHADER_WATER])
+ {
+ mVertexShaderLevel[SHADER_WATER] = llmin(gWaterProgram.mShaderLevel, gUnderWaterProgram.mShaderLevel);
+ }
+
+ if (!success)
+ {
+ mVertexShaderLevel[SHADER_WATER] = 0;
+ return FALSE;
+ }
+
+ // if we failed to load the terrain water shaders and we need them (using class2 water),
+ // then drop down to class1 water.
+ if (mVertexShaderLevel[SHADER_WATER] > 1 && !terrainWaterSuccess)
+ {
+ mVertexShaderLevel[SHADER_WATER]--;
+ return loadShadersWater();
+ }
+
+ LLWorld::getInstance()->updateWaterObjects();
+
+ return TRUE;
+}
+
+BOOL LLViewerShaderMgr::loadShadersEffects()
+{
+ BOOL success = TRUE;
+
+ if (mVertexShaderLevel[SHADER_EFFECT] == 0)
+ {
+ gGlowProgram.unload();
+ gGlowExtractProgram.unload();
+ gPostColorFilterProgram.unload();
+ gPostNightVisionProgram.unload();
+ return FALSE;
+ }
+
+ if (success)
+ {
+ gGlowProgram.mName = "Glow Shader (Post)";
+ gGlowProgram.mShaderFiles.clear();
+ gGlowProgram.mShaderFiles.push_back(make_pair("effects/glowV.glsl", GL_VERTEX_SHADER_ARB));
+ gGlowProgram.mShaderFiles.push_back(make_pair("effects/glowF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gGlowProgram.mShaderLevel = mVertexShaderLevel[SHADER_EFFECT];
+ success = gGlowProgram.createShader(NULL, &mGlowUniforms);
+ if (!success)
+ {
+ LLPipeline::sRenderGlow = FALSE;
+ }
+ }
+
+ if (success)
+ {
+ gGlowExtractProgram.mName = "Glow Extract Shader (Post)";
+ gGlowExtractProgram.mShaderFiles.clear();
+ gGlowExtractProgram.mShaderFiles.push_back(make_pair("effects/glowExtractV.glsl", GL_VERTEX_SHADER_ARB));
+ gGlowExtractProgram.mShaderFiles.push_back(make_pair("effects/glowExtractF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gGlowExtractProgram.mShaderLevel = mVertexShaderLevel[SHADER_EFFECT];
+ success = gGlowExtractProgram.createShader(NULL, &mGlowExtractUniforms);
+ if (!success)
+ {
+ LLPipeline::sRenderGlow = FALSE;
+ }
+ }
+
+#if 0
+ // disabling loading of postprocess shaders until we fix
+ // ATI sampler2DRect compatibility.
+
+ //load Color Filter Shader
+ if (success)
+ {
+ vector<string> shaderUniforms;
+ shaderUniforms.reserve(7);
+ shaderUniforms.push_back("RenderTexture");
+ shaderUniforms.push_back("gamma");
+ shaderUniforms.push_back("brightness");
+ shaderUniforms.push_back("contrast");
+ shaderUniforms.push_back("contrastBase");
+ shaderUniforms.push_back("saturation");
+ shaderUniforms.push_back("lumWeights");
+
+ gPostColorFilterProgram.mName = "Color Filter Shader (Post)";
+ gPostColorFilterProgram.mShaderFiles.clear();
+ gPostColorFilterProgram.mShaderFiles.push_back(make_pair("effects/colorFilterF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gPostColorFilterProgram.mShaderFiles.push_back(make_pair("effects/drawQuadV.glsl", GL_VERTEX_SHADER_ARB));
+ gPostColorFilterProgram.mShaderLevel = mVertexShaderLevel[SHADER_EFFECT];
+ success = gPostColorFilterProgram.createShader(NULL, &shaderUniforms);
+ }
+
+ //load Night Vision Shader
+ if (success)
+ {
+ vector<string> shaderUniforms;
+ shaderUniforms.reserve(5);
+ shaderUniforms.push_back("RenderTexture");
+ shaderUniforms.push_back("NoiseTexture");
+ shaderUniforms.push_back("brightMult");
+ shaderUniforms.push_back("noiseStrength");
+ shaderUniforms.push_back("lumWeights");
+
+ gPostNightVisionProgram.mName = "Night Vision Shader (Post)";
+ gPostNightVisionProgram.mShaderFiles.clear();
+ gPostNightVisionProgram.mShaderFiles.push_back(make_pair("effects/nightVisionF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gPostNightVisionProgram.mShaderFiles.push_back(make_pair("effects/drawQuadV.glsl", GL_VERTEX_SHADER_ARB));
+ gPostNightVisionProgram.mShaderLevel = mVertexShaderLevel[SHADER_EFFECT];
+ success = gPostNightVisionProgram.createShader(NULL, &shaderUniforms);
+ }
+ #endif
+
+ return success;
+
+}
+
+BOOL LLViewerShaderMgr::loadShadersDeferred()
+{
+ if (mVertexShaderLevel[SHADER_DEFERRED] == 0)
+ {
+ gDeferredDiffuseProgram.unload();
+ return FALSE;
+ }
+
+ BOOL success = TRUE;
+
+ if (success)
+ {
+ gDeferredDiffuseProgram.mName = "Deffered Diffuse Shader";
+ gDeferredDiffuseProgram.mShaderFiles.clear();
+ gDeferredDiffuseProgram.mShaderFiles.push_back(make_pair("deferred/diffuseV.glsl", GL_VERTEX_SHADER_ARB));
+ gDeferredDiffuseProgram.mShaderFiles.push_back(make_pair("deferred/diffuseF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gDeferredDiffuseProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+ success = gDeferredDiffuseProgram.createShader(NULL, NULL);
+ }
+
+ return success;
+}
+
+BOOL LLViewerShaderMgr::loadShadersObject()
+{
+ BOOL success = TRUE;
+
+ if (mVertexShaderLevel[SHADER_OBJECT] == 0)
+ {
+ gObjectShinyProgram.unload();
+ gObjectFullbrightShinyProgram.unload();
+ gObjectShinyWaterProgram.unload();
+ gObjectSimpleProgram.unload();
+ gObjectSimpleWaterProgram.unload();
+ gObjectFullbrightProgram.unload();
+ gObjectFullbrightWaterProgram.unload();
+ return FALSE;
+ }
+
+ if (success)
+ {
+ gObjectSimpleProgram.mName = "Simple Shader";
+ gObjectSimpleProgram.mFeatures.calculatesLighting = true;
+ gObjectSimpleProgram.mFeatures.calculatesAtmospherics = true;
+ gObjectSimpleProgram.mFeatures.hasGamma = true;
+ gObjectSimpleProgram.mFeatures.hasAtmospherics = true;
+ gObjectSimpleProgram.mFeatures.hasLighting = true;
+ gObjectSimpleProgram.mShaderFiles.clear();
+ gObjectSimpleProgram.mShaderFiles.push_back(make_pair("objects/simpleV.glsl", GL_VERTEX_SHADER_ARB));
+ gObjectSimpleProgram.mShaderFiles.push_back(make_pair("objects/simpleF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gObjectSimpleProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+ success = gObjectSimpleProgram.createShader(NULL, NULL);
+ }
+
+ if (success)
+ {
+ gObjectSimpleWaterProgram.mName = "Simple Water Shader";
+ gObjectSimpleWaterProgram.mFeatures.calculatesLighting = true;
+ gObjectSimpleWaterProgram.mFeatures.calculatesAtmospherics = true;
+ gObjectSimpleWaterProgram.mFeatures.hasWaterFog = true;
+ gObjectSimpleWaterProgram.mFeatures.hasAtmospherics = true;
+ gObjectSimpleWaterProgram.mFeatures.hasLighting = true;
+ gObjectSimpleWaterProgram.mShaderFiles.clear();
+ gObjectSimpleWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleV.glsl", GL_VERTEX_SHADER_ARB));
+ gObjectSimpleWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gObjectSimpleWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+ gObjectSimpleWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
+ success = gObjectSimpleWaterProgram.createShader(NULL, NULL);
+ }
+
+ if (success)
+ {
+ gObjectFullbrightProgram.mName = "Fullbright Shader";
+ gObjectFullbrightProgram.mFeatures.calculatesAtmospherics = true;
+ gObjectFullbrightProgram.mFeatures.hasGamma = true;
+ gObjectFullbrightProgram.mFeatures.hasTransport = true;
+ gObjectFullbrightProgram.mFeatures.isFullbright = true;
+ gObjectFullbrightProgram.mShaderFiles.clear();
+ gObjectFullbrightProgram.mShaderFiles.push_back(make_pair("objects/fullbrightV.glsl", GL_VERTEX_SHADER_ARB));
+ gObjectFullbrightProgram.mShaderFiles.push_back(make_pair("objects/fullbrightF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gObjectFullbrightProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+ success = gObjectFullbrightProgram.createShader(NULL, NULL);
+ }
+
+ if (success)
+ {
+ gObjectFullbrightWaterProgram.mName = "Fullbright Water Shader";
+ gObjectFullbrightWaterProgram.mFeatures.calculatesAtmospherics = true;
+ gObjectFullbrightWaterProgram.mFeatures.isFullbright = true;
+ gObjectFullbrightWaterProgram.mFeatures.hasWaterFog = true;
+ gObjectFullbrightWaterProgram.mFeatures.hasTransport = true;
+ gObjectFullbrightWaterProgram.mShaderFiles.clear();
+ gObjectFullbrightWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightV.glsl", GL_VERTEX_SHADER_ARB));
+ gObjectFullbrightWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gObjectFullbrightWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+ gObjectFullbrightWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
+ success = gObjectFullbrightWaterProgram.createShader(NULL, NULL);
+ }
+
+ if (success)
+ {
+ gObjectShinyProgram.mName = "Shiny Shader";
+ gObjectShinyProgram.mFeatures.calculatesAtmospherics = true;
+ gObjectShinyProgram.mFeatures.calculatesLighting = true;
+ gObjectShinyProgram.mFeatures.hasGamma = true;
+ gObjectShinyProgram.mFeatures.hasAtmospherics = true;
+ gObjectShinyProgram.mFeatures.isShiny = true;
+ gObjectShinyProgram.mShaderFiles.clear();
+ gObjectShinyProgram.mShaderFiles.push_back(make_pair("objects/shinyV.glsl", GL_VERTEX_SHADER_ARB));
+ gObjectShinyProgram.mShaderFiles.push_back(make_pair("objects/shinyF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gObjectShinyProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+ success = gObjectShinyProgram.createShader(NULL, &mShinyUniforms);
+ }
+
+ if (success)
+ {
+ gObjectShinyWaterProgram.mName = "Shiny Water Shader";
+ gObjectShinyWaterProgram.mFeatures.calculatesAtmospherics = true;
+ gObjectShinyWaterProgram.mFeatures.calculatesLighting = true;
+ gObjectShinyWaterProgram.mFeatures.isShiny = true;
+ gObjectShinyWaterProgram.mFeatures.hasWaterFog = true;
+ gObjectShinyWaterProgram.mFeatures.hasAtmospherics = true;
+ gObjectShinyWaterProgram.mShaderFiles.clear();
+ gObjectShinyWaterProgram.mShaderFiles.push_back(make_pair("objects/shinyWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gObjectShinyWaterProgram.mShaderFiles.push_back(make_pair("objects/shinyV.glsl", GL_VERTEX_SHADER_ARB));
+ gObjectShinyWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+ gObjectShinyWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
+ success = gObjectShinyWaterProgram.createShader(NULL, &mShinyUniforms);
+ }
+
+ if (success)
+ {
+ gObjectFullbrightShinyProgram.mName = "Fullbright Shiny Shader";
+ gObjectFullbrightShinyProgram.mFeatures.calculatesAtmospherics = true;
+ gObjectFullbrightShinyProgram.mFeatures.isFullbright = true;
+ gObjectFullbrightShinyProgram.mFeatures.isShiny = true;
+ gObjectFullbrightShinyProgram.mFeatures.hasGamma = true;
+ gObjectFullbrightShinyProgram.mFeatures.hasTransport = true;
+ gObjectFullbrightShinyProgram.mShaderFiles.clear();
+ gObjectFullbrightShinyProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyV.glsl", GL_VERTEX_SHADER_ARB));
+ gObjectFullbrightShinyProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gObjectFullbrightShinyProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+ success = gObjectFullbrightShinyProgram.createShader(NULL, &mShinyUniforms);
+ }
+
+
+ if( !success )
+ {
+ mVertexShaderLevel[SHADER_OBJECT] = 0;
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+BOOL LLViewerShaderMgr::loadShadersAvatar()
+{
+ BOOL success = TRUE;
+
+ if (mVertexShaderLevel[SHADER_AVATAR] == 0)
+ {
+ gAvatarProgram.unload();
+ gAvatarWaterProgram.unload();
+ gAvatarEyeballProgram.unload();
+ gAvatarPickProgram.unload();
+ return FALSE;
+ }
+
+ if (success)
+ {
+ gAvatarProgram.mName = "Avatar Shader";
+ gAvatarProgram.mFeatures.hasSkinning = true;
+ gAvatarProgram.mFeatures.calculatesAtmospherics = true;
+ gAvatarProgram.mFeatures.calculatesLighting = true;
+ gAvatarProgram.mFeatures.hasGamma = true;
+ gAvatarProgram.mFeatures.hasAtmospherics = true;
+ gAvatarProgram.mFeatures.hasLighting = true;
+ gAvatarProgram.mShaderFiles.clear();
+ gAvatarProgram.mShaderFiles.push_back(make_pair("avatar/avatarV.glsl", GL_VERTEX_SHADER_ARB));
+ gAvatarProgram.mShaderFiles.push_back(make_pair("avatar/avatarF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gAvatarProgram.mShaderLevel = mVertexShaderLevel[SHADER_AVATAR];
+ success = gAvatarProgram.createShader(&mAvatarAttribs, &mAvatarUniforms);
+
+ if (success)
+ {
+ gAvatarWaterProgram.mName = "Avatar Water Shader";
+ gAvatarWaterProgram.mFeatures.hasSkinning = true;
+ gAvatarWaterProgram.mFeatures.calculatesAtmospherics = true;
+ gAvatarWaterProgram.mFeatures.calculatesLighting = true;
+ gAvatarWaterProgram.mFeatures.hasWaterFog = true;
+ gAvatarWaterProgram.mFeatures.hasAtmospherics = true;
+ gAvatarWaterProgram.mFeatures.hasLighting = true;
+ gAvatarWaterProgram.mShaderFiles.clear();
+ gAvatarWaterProgram.mShaderFiles.push_back(make_pair("avatar/avatarV.glsl", GL_VERTEX_SHADER_ARB));
+ gAvatarWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
+ // Note: no cloth under water:
+ gAvatarWaterProgram.mShaderLevel = llmin(mVertexShaderLevel[SHADER_AVATAR], 1);
+ gAvatarWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
+ success = gAvatarWaterProgram.createShader(&mAvatarAttribs, &mAvatarUniforms);
+ }
+
+ /// Keep track of avatar levels
+ if (gAvatarProgram.mShaderLevel != mVertexShaderLevel[SHADER_AVATAR])
+ {
+ mMaxAvatarShaderLevel = mVertexShaderLevel[SHADER_AVATAR] = gAvatarProgram.mShaderLevel;
+ }
+ }
+
+ if (success)
+ {
+ gAvatarPickProgram.mName = "Avatar Pick Shader";
+ gAvatarPickProgram.mFeatures.hasSkinning = true;
+ gAvatarPickProgram.mShaderFiles.clear();
+ gAvatarPickProgram.mShaderFiles.push_back(make_pair("avatar/pickAvatarV.glsl", GL_VERTEX_SHADER_ARB));
+ gAvatarPickProgram.mShaderFiles.push_back(make_pair("avatar/pickAvatarF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gAvatarPickProgram.mShaderLevel = mVertexShaderLevel[SHADER_AVATAR];
+ success = gAvatarPickProgram.createShader(&mAvatarAttribs, &mAvatarUniforms);
+ }
+
+ if (success)
+ {
+ gAvatarEyeballProgram.mName = "Avatar Eyeball Program";
+ gAvatarEyeballProgram.mFeatures.calculatesLighting = true;
+ gAvatarEyeballProgram.mFeatures.isSpecular = true;
+ gAvatarEyeballProgram.mFeatures.calculatesAtmospherics = true;
+ gAvatarEyeballProgram.mFeatures.hasGamma = true;
+ gAvatarEyeballProgram.mFeatures.hasAtmospherics = true;
+ gAvatarEyeballProgram.mFeatures.hasLighting = true;
+ gAvatarEyeballProgram.mShaderFiles.clear();
+ gAvatarEyeballProgram.mShaderFiles.push_back(make_pair("avatar/eyeballV.glsl", GL_VERTEX_SHADER_ARB));
+ gAvatarEyeballProgram.mShaderFiles.push_back(make_pair("avatar/eyeballF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gAvatarEyeballProgram.mShaderLevel = mVertexShaderLevel[SHADER_AVATAR];
+ success = gAvatarEyeballProgram.createShader(NULL, NULL);
+ }
+
+ if( !success )
+ {
+ mVertexShaderLevel[SHADER_AVATAR] = 0;
+ mMaxAvatarShaderLevel = 0;
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+BOOL LLViewerShaderMgr::loadShadersInterface()
+{
+ BOOL success = TRUE;
+
+ if (mVertexShaderLevel[SHADER_INTERFACE] == 0)
+ {
+ gHighlightProgram.unload();
+ return FALSE;
+ }
+
+ if (success)
+ {
+ gHighlightProgram.mName = "Highlight Shader";
+ gHighlightProgram.mShaderFiles.clear();
+ gHighlightProgram.mShaderFiles.push_back(make_pair("interface/highlightV.glsl", GL_VERTEX_SHADER_ARB));
+ gHighlightProgram.mShaderFiles.push_back(make_pair("interface/highlightF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gHighlightProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE];
+ success = gHighlightProgram.createShader(NULL, NULL);
+ }
+
+ if( !success )
+ {
+ mVertexShaderLevel[SHADER_INTERFACE] = 0;
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+BOOL LLViewerShaderMgr::loadShadersWindLight()
+{
+ BOOL success = TRUE;
+
+ if (mVertexShaderLevel[SHADER_WINDLIGHT] < 2)
+ {
+ gWLSkyProgram.unload();
+ gWLCloudProgram.unload();
+ return FALSE;
+ }
+
+ if (success)
+ {
+ gWLSkyProgram.mName = "Windlight Sky Shader";
+ //gWLSkyProgram.mFeatures.hasGamma = true;
+ gWLSkyProgram.mShaderFiles.clear();
+ gWLSkyProgram.mShaderFiles.push_back(make_pair("windlight/skyV.glsl", GL_VERTEX_SHADER_ARB));
+ gWLSkyProgram.mShaderFiles.push_back(make_pair("windlight/skyF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gWLSkyProgram.mShaderLevel = mVertexShaderLevel[SHADER_WINDLIGHT];
+ gWLSkyProgram.mShaderGroup = LLGLSLShader::SG_SKY;
+ success = gWLSkyProgram.createShader(NULL, &mWLUniforms);
+ }
+
+ if (success)
+ {
+ gWLCloudProgram.mName = "Windlight Cloud Program";
+ //gWLCloudProgram.mFeatures.hasGamma = true;
+ gWLCloudProgram.mShaderFiles.clear();
+ gWLCloudProgram.mShaderFiles.push_back(make_pair("windlight/cloudsV.glsl", GL_VERTEX_SHADER_ARB));
+ gWLCloudProgram.mShaderFiles.push_back(make_pair("windlight/cloudsF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gWLCloudProgram.mShaderLevel = mVertexShaderLevel[SHADER_WINDLIGHT];
+ gWLCloudProgram.mShaderGroup = LLGLSLShader::SG_SKY;
+ success = gWLCloudProgram.createShader(NULL, &mWLUniforms);
+ }
+
+ return success;
+}
+
+std::string LLViewerShaderMgr::getShaderDirPrefix(void)
+ {
+ return gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "shaders/class");
+ }
+
+void LLViewerShaderMgr::updateShaderUniforms(LLGLSLShader * shader)
+ {
+ LLWLParamManager::instance()->updateShaderUniforms(shader);
+ LLWaterParamManager::instance()->updateShaderUniforms(shader);
+}
diff --git a/indra/newview/llviewershadermgr.h b/indra/newview/llviewershadermgr.h
new file mode 100644
index 0000000000..6b8189b4a6
--- /dev/null
+++ b/indra/newview/llviewershadermgr.h
@@ -0,0 +1,313 @@
+/**
+ * @file llviewershadermgr.h
+ * @brief Viewer Shader Manager
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2008, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlife.com/developers/opensource/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlife.com/developers/opensource/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_VIEWER_SHADER_MGR_H
+#define LL_VIEWER_SHADER_MGR_H
+
+#include "llshadermgr.h"
+
+class LLViewerShaderMgr: public LLShaderMgr
+{
+public:
+ LLViewerShaderMgr();
+ /* virtual */ ~LLViewerShaderMgr();
+
+ // singleton pattern implementation
+ static LLViewerShaderMgr * instance();
+
+ void initAttribsAndUniforms(void);
+ void setShaders();
+ void unloadShaders();
+ S32 getVertexShaderLevel(S32 type);
+ BOOL loadBasicShaders();
+ BOOL loadShadersEffects();
+ BOOL loadShadersDeferred();
+ BOOL loadShadersObject();
+ BOOL loadShadersAvatar();
+ BOOL loadShadersEnvironment();
+ BOOL loadShadersWater();
+ BOOL loadShadersInterface();
+ BOOL loadShadersWindLight();
+
+ std::vector<S32> mVertexShaderLevel;
+ S32 mMaxAvatarShaderLevel;
+
+ enum EShaderClass
+ {
+ SHADER_LIGHTING,
+ SHADER_OBJECT,
+ SHADER_AVATAR,
+ SHADER_ENVIRONMENT,
+ SHADER_INTERFACE,
+ SHADER_EFFECT,
+ SHADER_WINDLIGHT,
+ SHADER_WATER,
+ SHADER_DEFERRED,
+ SHADER_COUNT
+ };
+
+ typedef enum
+ {
+ MATERIAL_COLOR = 0,
+ SPECULAR_COLOR,
+ BINORMAL,
+ END_RESERVED_ATTRIBS
+ } eGLSLReservedAttribs;
+
+ typedef enum
+ {
+ DIFFUSE_MAP = 0,
+ SPECULAR_MAP,
+ BUMP_MAP,
+ ENVIRONMENT_MAP,
+ CLOUD_NOISE_MAP,
+ FULLBRIGHT,
+ LIGHTNORM,
+ SUNLIGHT_COLOR,
+ AMBIENT,
+ BLUE_HORIZON,
+ BLUE_DENSITY,
+ HAZE_HORIZON,
+ HAZE_DENSITY,
+ CLOUD_SHADOW,
+ DENSITY_MULTIPLIER,
+ DISTANCE_MULTIPLIER,
+ MAX_Y,
+ GLOW,
+ CLOUD_COLOR,
+ CLOUD_POS_DENSITY1,
+ CLOUD_POS_DENSITY2,
+ CLOUD_SCALE,
+ GAMMA,
+ SCENE_LIGHT_STRENGTH,
+ END_RESERVED_UNIFORMS
+ } eGLSLReservedUniforms;
+
+ typedef enum
+ {
+ SHINY_ORIGIN = END_RESERVED_UNIFORMS
+ } eShinyUniforms;
+
+ typedef enum
+ {
+ WATER_SCREENTEX = END_RESERVED_UNIFORMS,
+ WATER_SCREENDEPTH,
+ WATER_REFTEX,
+ WATER_EYEVEC,
+ WATER_TIME,
+ WATER_WAVE_DIR1,
+ WATER_WAVE_DIR2,
+ WATER_LIGHT_DIR,
+ WATER_SPECULAR,
+ WATER_SPECULAR_EXP,
+ WATER_FOGCOLOR,
+ WATER_FOGDENSITY,
+ WATER_REFSCALE,
+ WATER_WATERHEIGHT,
+ } eWaterUniforms;
+
+ typedef enum
+ {
+ WL_CAMPOSLOCAL = END_RESERVED_UNIFORMS,
+ WL_WATERHEIGHT
+ } eWLUniforms;
+
+ typedef enum
+ {
+ TERRAIN_DETAIL0 = END_RESERVED_UNIFORMS,
+ TERRAIN_DETAIL1,
+ TERRAIN_DETAIL2,
+ TERRAIN_DETAIL3,
+ TERRAIN_ALPHARAMP
+ } eTerrainUniforms;
+
+ typedef enum
+ {
+ GLOW_DELTA = END_RESERVED_UNIFORMS
+ } eGlowUniforms;
+
+ typedef enum
+ {
+ AVATAR_WEIGHT = END_RESERVED_ATTRIBS,
+ AVATAR_CLOTHING,
+ AVATAR_WIND,
+ AVATAR_SINWAVE,
+ AVATAR_GRAVITY
+ } eAvatarAttribs;
+
+ typedef enum
+ {
+ AVATAR_MATRIX = END_RESERVED_UNIFORMS
+ } eAvatarUniforms;
+
+ // simple model of forward iterator
+ // http://www.sgi.com/tech/stl/ForwardIterator.html
+ class shader_iter
+ {
+ private:
+ friend bool operator == (shader_iter const & a, shader_iter const & b);
+ friend bool operator != (shader_iter const & a, shader_iter const & b);
+
+ typedef std::vector<LLGLSLShader *>::const_iterator base_iter_t;
+ public:
+ shader_iter()
+ {
+ }
+
+ shader_iter(base_iter_t iter) : mIter(iter)
+ {
+ }
+
+ LLGLSLShader & operator * () const
+ {
+ return **mIter;
+ }
+
+ LLGLSLShader * operator -> () const
+ {
+ return *mIter;
+ }
+
+ shader_iter & operator++ ()
+ {
+ ++mIter;
+ return *this;
+ }
+
+ shader_iter operator++ (int)
+ {
+ return mIter++;
+ }
+
+ private:
+ base_iter_t mIter;
+ };
+
+ shader_iter beginShaders() const
+ {
+ return mShaderList.begin();
+ }
+
+ shader_iter endShaders() const
+ {
+ return mShaderList.end();
+ }
+
+
+ /* virtual */ std::string getShaderDirPrefix(void); // Virtual
+
+ /* virtual */ void updateShaderUniforms(LLGLSLShader * shader); // Virtual
+
+private:
+
+ std::vector<std::string> mShinyUniforms;
+
+ //water parameters
+ std::vector<std::string> mWaterUniforms;
+
+ std::vector<std::string> mWLUniforms;
+
+ //terrain parameters
+ std::vector<std::string> mTerrainUniforms;
+
+ //glow parameters
+ std::vector<std::string> mGlowUniforms;
+
+ std::vector<std::string> mGlowExtractUniforms;
+
+ //avatar shader parameter tables
+ std::vector<std::string> mAvatarAttribs;
+
+ std::vector<std::string> mAvatarUniforms;
+
+ // the list of shaders we need to propagate parameters to.
+ std::vector<LLGLSLShader *> mShaderList;
+
+}; //LLViewerShaderMgr
+
+inline bool operator == (LLViewerShaderMgr::shader_iter const & a, LLViewerShaderMgr::shader_iter const & b)
+{
+ return a.mIter == b.mIter;
+}
+
+inline bool operator != (LLViewerShaderMgr::shader_iter const & a, LLViewerShaderMgr::shader_iter const & b)
+{
+ return a.mIter != b.mIter;
+}
+
+extern LLVector4 gShinyOrigin;
+
+//object shaders
+extern LLGLSLShader gObjectSimpleProgram;
+extern LLGLSLShader gObjectSimpleWaterProgram;
+extern LLGLSLShader gObjectFullbrightProgram;
+extern LLGLSLShader gObjectFullbrightWaterProgram;
+
+extern LLGLSLShader gObjectSimpleLODProgram;
+extern LLGLSLShader gObjectFullbrightLODProgram;
+
+extern LLGLSLShader gObjectFullbrightShinyProgram;
+extern LLGLSLShader gObjectShinyProgram;
+extern LLGLSLShader gObjectShinyWaterProgram;
+
+//environment shaders
+extern LLGLSLShader gTerrainProgram;
+extern LLGLSLShader gTerrainWaterProgram;
+extern LLGLSLShader gWaterProgram;
+extern LLGLSLShader gUnderWaterProgram;
+extern LLGLSLShader gGlowProgram;
+extern LLGLSLShader gGlowExtractProgram;
+
+//interface shaders
+extern LLGLSLShader gHighlightProgram;
+
+// avatar shader handles
+extern LLGLSLShader gAvatarProgram;
+extern LLGLSLShader gAvatarWaterProgram;
+extern LLGLSLShader gAvatarEyeballProgram;
+extern LLGLSLShader gAvatarPickProgram;
+
+// WindLight shader handles
+extern LLGLSLShader gWLSkyProgram;
+extern LLGLSLShader gWLCloudProgram;
+
+// Post Process Shaders
+extern LLGLSLShader gPostColorFilterProgram;
+extern LLGLSLShader gPostNightVisionProgram;
+
+// Deferred rendering shaders
+extern LLGLSLShader gDeferredDiffuseProgram;
+
+//current avatar shader parameter pointer
+extern GLint gAvatarMatrixParam;
+
+
+#endif
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index cf2c094ded..287f063757 100644
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -114,7 +114,7 @@
#include "llworld.h"
#include "pipeline.h"
#include "llspatialpartition.h"
-#include "llglslshader.h"
+#include "llviewershadermgr.h"
#include "llappviewer.h"
#include "llsky.h"
#include "llanimstatelabels.h"
@@ -2824,7 +2824,7 @@ void LLVOAvatar::idleUpdateLoadingEffect()
void LLVOAvatar::idleUpdateWindEffect()
{
// update wind effect
- if ((LLShaderMgr::getVertexShaderLevel(LLShaderMgr::SHADER_AVATAR) >= LLDrawPoolAvatar::SHADER_LEVEL_CLOTH))
+ if ((LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_AVATAR) >= LLDrawPoolAvatar::SHADER_LEVEL_CLOTH))
{
F32 hover_strength = 0.f;
F32 time_delta = mRippleTimer.getElapsedTimeF32() - mRippleTimeLast;
@@ -3388,7 +3388,7 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
return FALSE;
}
}
-
+
// change animation time quanta based on avatar render load
if (!mIsSelf && !mIsDummy)
{
@@ -4000,7 +4000,7 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass)
mDrawable->clearState(LLDrawable::REBUILD_GEOMETRY);
}
- if (LLShaderMgr::getVertexShaderLevel(LLShaderMgr::SHADER_AVATAR) <= 0)
+ if (LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_AVATAR) <= 0)
{
if (mNeedsSkin)
{
@@ -9714,7 +9714,7 @@ BOOL LLVOAvatar::updateLOD()
}
updateVisibility();
-
+
return res;
}
diff --git a/indra/newview/llvosky.cpp b/indra/newview/llvosky.cpp
index 1ef721e918..330d5c370d 100644
--- a/indra/newview/llvosky.cpp
+++ b/indra/newview/llvosky.cpp
@@ -441,7 +441,7 @@ void LLVOSky::initCubeMap()
{
mCubeMap->init(images);
}
- else if (gSavedSettings.getBOOL("RenderWater") && gGLManager.mHasCubeMap && LLFeatureManager::getInstance()->isFeatureAvailable("RenderCubeMap"))
+ else if (gSavedSettings.getBOOL("RenderWater") && gGLManager.mHasCubeMap && LLCubeMap::sUseCubeMaps)
{
mCubeMap = new LLCubeMap();
mCubeMap->init(images);
@@ -479,7 +479,7 @@ void LLVOSky::restoreGL()
calcAtmospherics();
if (gSavedSettings.getBOOL("RenderWater") && gGLManager.mHasCubeMap
- && LLFeatureManager::getInstance()->isFeatureAvailable("RenderCubeMap"))
+ && LLCubeMap::sUseCubeMaps)
{
LLCubeMap* cube_map = getCubeMap();
diff --git a/indra/newview/llwaterparammanager.cpp b/indra/newview/llwaterparammanager.cpp
index 4f2dd663ed..29f086b7f9 100644
--- a/indra/newview/llwaterparammanager.cpp
+++ b/indra/newview/llwaterparammanager.cpp
@@ -33,6 +33,8 @@
#include "llwaterparammanager.h"
+#include "llrender.h"
+
#include "pipeline.h"
#include "llsky.h"
@@ -205,9 +207,9 @@ void LLWaterParamManager::propagateParameters(void)
// bind the variables only if we're using shaders
if(gPipeline.canUseVertexShaders())
{
- LLShaderMgr::shader_iter shaders_iter, end_shaders;
- end_shaders = LLShaderMgr::endShaders();
- for(shaders_iter = LLShaderMgr::beginShaders(); shaders_iter != end_shaders; ++shaders_iter)
+ LLViewerShaderMgr::shader_iter shaders_iter, end_shaders;
+ end_shaders = LLViewerShaderMgr::instance()->endShaders();
+ for(shaders_iter = LLViewerShaderMgr::instance()->beginShaders(); shaders_iter != end_shaders; ++shaders_iter)
{
if (shaders_iter->mProgramObject != 0
&& shaders_iter->mShaderGroup == LLGLSLShader::SG_WATER)
@@ -229,7 +231,7 @@ void LLWaterParamManager::updateShaderUniforms(LLGLSLShader * shader)
{
if (shader->mShaderGroup == LLGLSLShader::SG_WATER)
{
- shader->uniform4fv(LLShaderMgr::LIGHTNORM, 1, LLWLParamManager::instance()->getRotatedLightDir().mV);
+ shader->uniform4fv(LLViewerShaderMgr::LIGHTNORM, 1, LLWLParamManager::instance()->getRotatedLightDir().mV);
shader->uniform3fv("camPosLocal", 1, LLViewerCamera::getInstance()->getOrigin().mV);
shader->uniform4fv("waterFogColor", 1, LLDrawPoolWater::sWaterFogColor.mV);
shader->uniform4fv("waterPlane", 1, mWaterPlane.mV);
@@ -289,9 +291,9 @@ void LLWaterParamManager::update(LLViewerCamera * cam)
sunMoonDir.normVec();
mWaterFogKS = 1.f/llmax(sunMoonDir.mV[2], WATER_FOG_LIGHT_CLAMP);
- LLShaderMgr::shader_iter shaders_iter, end_shaders;
- end_shaders = LLShaderMgr::endShaders();
- for(shaders_iter = LLShaderMgr::beginShaders(); shaders_iter != end_shaders; ++shaders_iter)
+ LLViewerShaderMgr::shader_iter shaders_iter, end_shaders;
+ end_shaders = LLViewerShaderMgr::instance()->endShaders();
+ for(shaders_iter = LLViewerShaderMgr::instance()->beginShaders(); shaders_iter != end_shaders; ++shaders_iter)
{
if (shaders_iter->mProgramObject != 0
&& shaders_iter->mShaderGroup == LLGLSLShader::SG_WATER)
diff --git a/indra/newview/llwaterparamset.h b/indra/newview/llwaterparamset.h
index b733160dff..c16901a4cd 100644
--- a/indra/newview/llwaterparamset.h
+++ b/indra/newview/llwaterparamset.h
@@ -37,7 +37,7 @@
#include "v4math.h"
#include "v4color.h"
-#include "llglslshader.h"
+#include "llviewershadermgr.h"
class LLFloaterWater;
class LLWaterParamSet;
diff --git a/indra/newview/llwlparammanager.cpp b/indra/newview/llwlparammanager.cpp
index 24ddb6fc08..b55c3e5b6d 100644
--- a/indra/newview/llwlparammanager.cpp
+++ b/indra/newview/llwlparammanager.cpp
@@ -281,13 +281,13 @@ void LLWLParamManager::updateShaderUniforms(LLGLSLShader * shader)
if (shader->mShaderGroup == LLGLSLShader::SG_DEFAULT)
{
- shader->uniform4fv(LLShaderMgr::LIGHTNORM, 1, mRotatedLightDir.mV);
+ shader->uniform4fv(LLViewerShaderMgr::LIGHTNORM, 1, mRotatedLightDir.mV);
shader->uniform3fv("camPosLocal", 1, LLViewerCamera::getInstance()->getOrigin().mV);
}
else if (shader->mShaderGroup == LLGLSLShader::SG_SKY)
{
- shader->uniform4fv(LLShaderMgr::LIGHTNORM, 1, mClampedLightDir.mV);
+ shader->uniform4fv(LLViewerShaderMgr::LIGHTNORM, 1, mClampedLightDir.mV);
}
shader->uniform1f("scene_light_strength", mSceneLightStrength);
@@ -345,9 +345,9 @@ void LLWLParamManager::propagateParameters(void)
mCurParams.set("lightnorm", mLightDir);
// bind the variables for all shaders only if we're using WindLight
- LLShaderMgr::shader_iter shaders_iter, end_shaders;
- end_shaders = LLShaderMgr::endShaders();
- for(shaders_iter = LLShaderMgr::beginShaders(); shaders_iter != end_shaders; ++shaders_iter)
+ LLViewerShaderMgr::shader_iter shaders_iter, end_shaders;
+ end_shaders = LLViewerShaderMgr::instance()->endShaders();
+ for(shaders_iter = LLViewerShaderMgr::instance()->beginShaders(); shaders_iter != end_shaders; ++shaders_iter)
{
if (shaders_iter->mProgramObject != 0
&& (gPipeline.canUseWindLightShaders()
@@ -408,9 +408,9 @@ void LLWLParamManager::update(LLViewerCamera * cam)
lightNorm3 *= LLQuaternion(-(camYaw + camYawDelta), LLVector3(0.f, 1.f, 0.f));
mRotatedLightDir = LLVector4(lightNorm3, 0.f);
- LLShaderMgr::shader_iter shaders_iter, end_shaders;
- end_shaders = LLShaderMgr::endShaders();
- for(shaders_iter = LLShaderMgr::beginShaders(); shaders_iter != end_shaders; ++shaders_iter)
+ LLViewerShaderMgr::shader_iter shaders_iter, end_shaders;
+ end_shaders = LLViewerShaderMgr::instance()->endShaders();
+ for(shaders_iter = LLViewerShaderMgr::instance()->beginShaders(); shaders_iter != end_shaders; ++shaders_iter)
{
if (shaders_iter->mProgramObject != 0
&& (gPipeline.canUseWindLightShaders()
diff --git a/indra/newview/llwlparamset.h b/indra/newview/llwlparamset.h
index 15afeaf364..76a7b8a189 100644
--- a/indra/newview/llwlparamset.h
+++ b/indra/newview/llwlparamset.h
@@ -37,7 +37,7 @@
#include "v4math.h"
#include "v4color.h"
-#include "llglslshader.h"
+#include "llviewershadermgr.h"
class LLFloaterWindLight;
class LLWLParamSet;
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index 3679b57da8..f9a18bf192 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -93,7 +93,7 @@
#include "llworld.h"
#include "llcubemap.h"
#include "lldebugmessagebox.h"
-#include "llglslshader.h"
+#include "llviewershadermgr.h"
#include "llviewerjoystick.h"
#include "llviewerdisplay.h"
#include "llwlparammanager.h"
@@ -300,7 +300,7 @@ void LLPipeline::init()
// Enable features
- LLShaderMgr::setShaders();
+ LLViewerShaderMgr::instance()->setShaders();
stop_glerror();
}
@@ -565,7 +565,7 @@ void LLPipeline::restoreGL()
if (mVertexShadersEnabled)
{
- LLShaderMgr::setShaders();
+ LLViewerShaderMgr::instance()->setShaders();
}
for (LLWorld::region_list_t::iterator iter = LLWorld::getInstance()->getRegionList().begin();
@@ -603,18 +603,18 @@ BOOL LLPipeline::canUseWindLightShaders() const
{
return (!LLPipeline::sDisableShaders &&
gWLSkyProgram.mProgramObject != 0 &&
- LLShaderMgr::getVertexShaderLevel(LLShaderMgr::SHADER_WINDLIGHT) > 1);
+ LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_WINDLIGHT) > 1);
}
BOOL LLPipeline::canUseWindLightShadersOnObjects() const
{
return (canUseWindLightShaders()
- && LLShaderMgr::getVertexShaderLevel(LLShaderMgr::SHADER_OBJECT) > 0);
+ && LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_OBJECT) > 0);
}
void LLPipeline::unloadShaders()
{
- LLShaderMgr::unloadShaders();
+ LLViewerShaderMgr::instance()->unloadShaders();
mVertexShadersLoaded = 0;
}
@@ -660,7 +660,7 @@ S32 LLPipeline::setLightingDetail(S32 level)
if (mVertexShadersLoaded == 1)
{
- LLShaderMgr::setShaders();
+ LLViewerShaderMgr::instance()->setShaders();
}
}
return mLightingDetail;
@@ -1795,7 +1795,7 @@ void LLPipeline::stateSort(LLDrawable* drawablep, LLCamera& camera)
else if (drawablep->isAvatar())
{
drawablep->updateDistance(camera); // calls vobj->updateLOD() which calls LLVOAvatar::updateVisibility()
- }
+ }
}
}
@@ -2192,10 +2192,10 @@ void LLPipeline::renderHighlights()
LLGLEnable color_mat(GL_COLOR_MATERIAL);
disableLights();
- if ((LLShaderMgr::sVertexShaderLevel[LLShaderMgr::SHADER_INTERFACE] > 0))
+ if ((LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0))
{
gHighlightProgram.bind();
- gHighlightProgram.vertexAttrib4f(LLShaderMgr::MATERIAL_COLOR,1,1,1,0.5f);
+ gHighlightProgram.vertexAttrib4f(LLViewerShaderMgr::MATERIAL_COLOR,1,1,1,0.5f);
}
if (hasRenderDebugFeatureMask(RENDER_DEBUG_FEATURE_SELECTED))
@@ -2225,9 +2225,9 @@ void LLPipeline::renderHighlights()
{
// Paint 'em red!
color.setVec(1.f, 0.f, 0.f, 0.5f);
- if ((LLShaderMgr::sVertexShaderLevel[LLShaderMgr::SHADER_INTERFACE] > 0))
+ if ((LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0))
{
- gHighlightProgram.vertexAttrib4f(LLShaderMgr::MATERIAL_COLOR,1,0,0,0.5f);
+ gHighlightProgram.vertexAttrib4f(LLViewerShaderMgr::MATERIAL_COLOR,1,0,0,0.5f);
}
int count = mHighlightFaces.size();
for (S32 i = 0; i < count; i++)
@@ -2241,7 +2241,7 @@ void LLPipeline::renderHighlights()
// have touch-handlers.
mHighlightFaces.clear();
- if (LLShaderMgr::sVertexShaderLevel[LLShaderMgr::SHADER_INTERFACE] > 0)
+ if (LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0)
{
gHighlightProgram.unbind();
}