diff options
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();  	} | 
