diff options
author | Eric Tulla <tulla@lindenlab.com> | 2008-06-30 17:57:00 +0000 |
---|---|---|
committer | Eric Tulla <tulla@lindenlab.com> | 2008-06-30 17:57:00 +0000 |
commit | 939a506569433db7bff96c12200f03b3f85f40de (patch) | |
tree | c9f308949400b0a4ce00c82a6a33f2868e31a1d1 | |
parent | 1a14cd34a9a4e6f51c445d477aaeeef0322d5853 (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
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 ¢er, 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(); } |