diff options
Diffstat (limited to 'indra/llrender')
| -rw-r--r-- | indra/llrender/llgl.cpp | 69 | ||||
| -rw-r--r-- | indra/llrender/llgl.h | 1 | ||||
| -rw-r--r-- | indra/llrender/llglheaders.h | 22 | ||||
| -rw-r--r-- | indra/llrender/llimagegl.cpp | 89 | ||||
| -rw-r--r-- | indra/llrender/llimagegl.h | 2 | ||||
| -rw-r--r-- | indra/llrender/llrender.cpp | 41 | ||||
| -rw-r--r-- | indra/llrender/llrender.h | 10 | ||||
| -rw-r--r-- | indra/llrender/llvertexbuffer.cpp | 5 | 
8 files changed, 197 insertions, 42 deletions
| diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp index a3f7a946ec..7ff68fe34b 100644 --- a/indra/llrender/llgl.cpp +++ b/indra/llrender/llgl.cpp @@ -185,6 +185,9 @@ PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC glRenderbufferStorageMultisampleEXT =  // GL_EXT_framebuffer_blit  PFNGLBLITFRAMEBUFFEREXTPROC glBlitFramebufferEXT = NULL; +// GL_EXT_blend_func_separate +PFNGLBLENDFUNCSEPARATEEXTPROC glBlendFuncSeparateEXT = NULL; +  // GL_ARB_draw_buffers  PFNGLDRAWBUFFERSARBPROC glDrawBuffersARB = NULL; @@ -324,6 +327,7 @@ LLGLManager::LLGLManager() :  	mHasCompressedTextures(FALSE),  	mHasFramebufferObject(FALSE),  	mHasFramebufferMultisample(FALSE), +	mHasBlendFuncSeparate(FALSE),  	mHasVertexBufferObject(FALSE),  	mHasPBuffer(FALSE), @@ -633,6 +637,11 @@ void LLGLManager::initExtensions()  #else  	mHasDrawBuffers = FALSE;  # endif +# if GL_EXT_blend_func_separate +	mHasBlendFuncSeparate = TRUE; +#else +	mHasBlendFuncSeparate = FALSE; +# endif  	mHasMipMapGeneration = FALSE;  	mHasSeparateSpecularColor = FALSE;  	mHasAnisotropic = FALSE; @@ -659,6 +668,7 @@ void LLGLManager::initExtensions()  		&& ExtensionExists("GL_EXT_packed_depth_stencil", gGLHExts.mSysExts);  	mHasFramebufferMultisample = mHasFramebufferObject && ExtensionExists("GL_EXT_framebuffer_multisample", gGLHExts.mSysExts);  	mHasDrawBuffers = ExtensionExists("GL_ARB_draw_buffers", gGLHExts.mSysExts); +	mHasBlendFuncSeparate = ExtensionExists("GL_EXT_blend_func_separate", gGLHExts.mSysExts);  	mHasTextureRectangle = ExtensionExists("GL_ARB_texture_rectangle", gGLHExts.mSysExts);  #if !LL_DARWIN  	mHasPointParameters = !mIsATI && ExtensionExists("GL_ARB_point_parameters", gGLHExts.mSysExts); @@ -682,6 +692,7 @@ void LLGLManager::initExtensions()  		mHasFramebufferObject = FALSE;  		mHasFramebufferMultisample = FALSE;  		mHasDrawBuffers = FALSE; +		mHasBlendFuncSeparate = FALSE;  		mHasMipMapGeneration = FALSE;  		mHasSeparateSpecularColor = FALSE;  		mHasAnisotropic = FALSE; @@ -706,6 +717,7 @@ void LLGLManager::initExtensions()  		mHasShaderObjects = FALSE;  		mHasVertexShader = FALSE;  		mHasFragmentShader = FALSE; +		mHasBlendFuncSeparate = FALSE;  		LL_WARNS("RenderInit") << "GL extension support forced to SIMPLE level via LL_GL_BASICEXT" << LL_ENDL;  	}  	if (getenv("LL_GL_BLACKLIST"))	/* Flawfinder: ignore */ @@ -734,7 +746,8 @@ void LLGLManager::initExtensions()  		if (strchr(blacklist,'r')) mHasDrawBuffers = FALSE;//S  		if (strchr(blacklist,'s')) mHasFramebufferMultisample = FALSE;  		if (strchr(blacklist,'t')) mHasTextureRectangle = FALSE; - +		if (strchr(blacklist,'u')) mHasBlendFuncSeparate = FALSE;//S +		  	}  #endif // LL_LINUX || LL_SOLARIS @@ -782,6 +795,14 @@ void LLGLManager::initExtensions()  	{  		LL_INFOS("RenderInit") << "Couldn't initialize GL_ARB_fragment_shader" << LL_ENDL;  	} +	if (!mHasBlendFuncSeparate) +	{ +		LL_INFOS("RenderInit") << "Couldn't initialize GL_EXT_blend_func_separate" << LL_ENDL; +	} +	if (!mHasDrawBuffers) +	{ +		LL_INFOS("RenderInit") << "Couldn't initialize GL_ARB_draw_buffers" << LL_ENDL; +	}  	// Disable certain things due to known bugs  	if (mIsIntel && mHasMipMapGeneration) @@ -852,6 +873,10 @@ void LLGLManager::initExtensions()  	{  		glDrawBuffersARB = (PFNGLDRAWBUFFERSARBPROC) GLH_EXT_GET_PROC_ADDRESS("glDrawBuffersARB");  	} +	if (mHasBlendFuncSeparate) +	{ +		glBlendFuncSeparateEXT = (PFNGLBLENDFUNCSEPARATEEXTPROC) GLH_EXT_GET_PROC_ADDRESS("glBlendFuncSeparateEXT"); +	}  #if (!LL_LINUX && !LL_SOLARIS) || LL_LINUX_NV_GL_HEADERS  	// This is expected to be a static symbol on Linux GL implementations, except if we use the nvidia headers - bah  	glDrawRangeElements = (PFNGLDRAWRANGEELEMENTSPROC)GLH_EXT_GET_PROC_ADDRESS("glDrawRangeElements"); @@ -1014,24 +1039,9 @@ void flush_glerror()  	glGetError();  } -void assert_glerror() +void do_assert_glerror()  { -	if (!gGLActive) -	{ -		//llwarns << "GL used while not active!" << llendl; - -		if (gDebugSession) -		{ -			//ll_fail("GL used while not active"); -		} -	} - -	if (gNoRender || !gDebugGL)  -	{ -		return; -	} -	 -	if (!gGLManager.mInited) +	if (LL_UNLIKELY(!gGLManager.mInited))  	{  		LL_ERRS("RenderInit") << "GL not initialized" << LL_ENDL;  	} @@ -1039,10 +1049,9 @@ void assert_glerror()  	GLenum error;  	error = glGetError();  	BOOL quit = FALSE; -	while (error) +	while (LL_UNLIKELY(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)  		{ @@ -1066,7 +1075,6 @@ void assert_glerror()  			}  		}  		error = glGetError(); -#endif  	}  	if (quit) @@ -1082,6 +1090,25 @@ void assert_glerror()  	}  } +void assert_glerror() +{ +	if (!gGLActive) +	{ +		//llwarns << "GL used while not active!" << llendl; + +		if (gDebugSession) +		{ +			//ll_fail("GL used while not active"); +		} +	} + +	if (!gNoRender && gDebugGL)  +	{ +		do_assert_glerror(); +	} +} +	 +  void clear_glerror()  {  	//  Create or update texture to be used with this data  diff --git a/indra/llrender/llgl.h b/indra/llrender/llgl.h index 91421f3c95..0c2da7dd08 100644 --- a/indra/llrender/llgl.h +++ b/indra/llrender/llgl.h @@ -87,6 +87,7 @@ public:  	BOOL mHasCompressedTextures;  	BOOL mHasFramebufferObject;  	BOOL mHasFramebufferMultisample; +	BOOL mHasBlendFuncSeparate;  	// ARB Extensions  	BOOL mHasVertexBufferObject; diff --git a/indra/llrender/llglheaders.h b/indra/llrender/llglheaders.h index f33ae7d8f0..f6d35bc766 100644 --- a/indra/llrender/llglheaders.h +++ b/indra/llrender/llglheaders.h @@ -216,6 +216,9 @@ extern PFNGLGETCOMPRESSEDTEXIMAGEARBPROC glGetCompressedTexImageARB;  extern PFNGLCOLORTABLEEXTPROC glColorTableEXT; +//GL_EXT_blend_func_separate +extern PFNGLBLENDFUNCSEPARATEEXTPROC glBlendFuncSeparateEXT; +  //GL_EXT_framebuffer_object  extern PFNGLISRENDERBUFFEREXTPROC glIsRenderbufferEXT;  extern PFNGLBINDRENDERBUFFEREXTPROC glBindRenderbufferEXT; @@ -249,7 +252,10 @@ extern PFNGLGENERATEMIPMAPEXTPROC glGenerateMipmapEXT;  # include "GL/glh_extensions.h"  # undef __APPLE__ -#elif LL_LINUX  +#elif LL_LINUX +//---------------------------------------------------------------------------- +// LL_LINUX +  //----------------------------------------------------------------------------  // Linux, MESA headers, but not necessarily assuming MESA runtime.  // quotes so we get libraries/.../GL/ version @@ -285,6 +291,7 @@ extern PFNGLGENERATEMIPMAPEXTPROC glGenerateMipmapEXT;  # define LL_LINUX_NV_GL_HEADERS 0  #endif // LL_LINUX && defined(WINGDIAPI) +  #if LL_LINUX_NV_GL_HEADERS  // Missing functions when using nvidia headers:  extern PFNGLACTIVETEXTUREARBPROC	glActiveTextureARB; @@ -445,6 +452,9 @@ extern PFNGLGETATTRIBLOCATIONARBPROC glGetAttribLocationARB;  extern PFNGLCOMPRESSEDTEXIMAGE2DARBPROC glCompressedTexImage2DARB;  extern PFNGLGETCOMPRESSEDTEXIMAGEARBPROC glGetCompressedTexImageARB; +//GL_EXT_blend_func_separate +extern PFNGLBLENDFUNCSEPARATEEXTPROC glBlendFuncSeparateEXT; +  //GL_EXT_framebuffer_object  extern PFNGLISRENDERBUFFEREXTPROC glIsRenderbufferEXT;  extern PFNGLBINDRENDERBUFFEREXTPROC glBindRenderbufferEXT; @@ -473,7 +483,10 @@ extern PFNGLBLITFRAMEBUFFEREXTPROC glBlitFramebufferEXT;  //GL_ARB_draw_buffers  extern PFNGLDRAWBUFFERSARBPROC glDrawBuffersARB; +  #elif LL_WINDOWS +//---------------------------------------------------------------------------- +// LL_WINDOWS  // windows gl headers depend on things like APIENTRY, so include windows.  #define WIN32_LEAN_AND_MEAN @@ -641,6 +654,9 @@ extern PFNGLBINDATTRIBLOCATIONARBPROC glBindAttribLocationARB;  extern PFNGLGETACTIVEATTRIBARBPROC glGetActiveAttribARB;  extern PFNGLGETATTRIBLOCATIONARBPROC glGetAttribLocationARB; +//GL_EXT_blend_func_separate +extern PFNGLBLENDFUNCSEPARATEEXTPROC glBlendFuncSeparateEXT; +  //GL_EXT_framebuffer_object  extern PFNGLISRENDERBUFFEREXTPROC glIsRenderbufferEXT;  extern PFNGLBINDRENDERBUFFEREXTPROC glBindRenderbufferEXT; @@ -669,6 +685,7 @@ extern PFNGLBLITFRAMEBUFFEREXTPROC glBlitFramebufferEXT;  //GL_ARB_draw_buffers  extern PFNGLDRAWBUFFERSARBPROC glDrawBuffersARB; +  #elif LL_DARWIN  //----------------------------------------------------------------------------  // LL_DARWIN @@ -685,6 +702,9 @@ extern PFNGLDRAWBUFFERSARBPROC glDrawBuffersARB;  // 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_blend_func_separate +extern void glBlendFuncSeparateEXT(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER; +  // 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; diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index 69ef3f9ed7..1a48c8a06c 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -1654,7 +1654,7 @@ void LLImageGL::calcAlphaChannelOffsetAndStride()  	}  } -void LLImageGL::analyzeAlpha(const void* data_in, S32 w, S32 h) +void LLImageGL::analyzeAlpha(const void* data_in, U32 w, U32 h)  {  	if(!mNeedsAlphaAndPickMask)  	{ @@ -1662,26 +1662,91 @@ void LLImageGL::analyzeAlpha(const void* data_in, S32 w, S32 h)  	}  	U32 length = w * h; -	const GLubyte* current = ((const GLubyte*) data_in) + mAlphaOffset ; +	U32 alphatotal = 0; -	S32 sample[16]; -	memset(sample, 0, sizeof(S32)*16); - -	for (U32 i = 0; i < length; i++) +	U32 sample[16]; +	memset(sample, 0, sizeof(U32)*16); + +	// generate histogram of quantized alpha. +	// also add-in the histogram of a 2x2 box-sampled version.  The idea is +	// this will mid-skew the data (and thus increase the chances of not +	// being used as a mask) from high-frequency alpha maps which +	// suffer the worst from aliasing when used as alpha masks. +	if (w >= 2 && h >= 2) +	{ +		llassert(w%2 == 0); +		llassert(h%2 == 0); +		const GLubyte* rowstart = ((const GLubyte*) data_in) + mAlphaOffset; +		for (U32 y = 0; y < h; y+=2) +		{ +			const GLubyte* current = rowstart; +			for (U32 x = 0; x < w; x+=2) +			{ +				const U32 s1 = current[0]; +				alphatotal += s1; +				const U32 s2 = current[w * mAlphaStride]; +				alphatotal += s2; +				current += mAlphaStride; +				const U32 s3 = current[0]; +				alphatotal += s3; +				const U32 s4 = current[w * mAlphaStride]; +				alphatotal += s4; +				current += mAlphaStride; + +				++sample[s1/16]; +				++sample[s2/16]; +				++sample[s3/16]; +				++sample[s4/16]; + +				const U32 asum = (s1+s2+s3+s4); +				alphatotal += asum; +				sample[asum/(16*4)] += 4; +			} +			 +			rowstart += 2 * w * mAlphaStride; +		} +		length *= 2; // we sampled everything twice, essentially +	} +	else  	{ -		++sample[*current/16]; -		current += mAlphaStride ; +		const GLubyte* current = ((const GLubyte*) data_in) + mAlphaOffset; +		for (U32 i = 0; i < length; i++) +		{ +			const U32 s1 = *current; +			alphatotal += s1; +			++sample[s1/16]; +			current += mAlphaStride; +		}  	} +	 +	// if more than 1/16th of alpha samples are mid-range, this +	// shouldn't be treated as a 1-bit mask -	U32 total = 0; +	// also, if all of the alpha samples are clumped on one half +	// of the range (but not at an absolute extreme), then consider +	// this to be an intentional effect and don't treat as a mask. + +	U32 midrangetotal = 0;  	for (U32 i = 4; i < 11; i++)  	{ -		total += sample[i]; +		midrangetotal += sample[i]; +	} +	U32 lowerhalftotal = 0; +	for (U32 i = 0; i < 8; i++) +	{ +		lowerhalftotal += sample[i]; +	} +	U32 upperhalftotal = 0; +	for (U32 i = 8; i < 16; i++) +	{ +		upperhalftotal += sample[i];  	} -	if (total > length/16) +	if (midrangetotal > length/16 || // lots of midrange, or +	    (lowerhalftotal == length && alphatotal != 0) || // all close to transparent but not all totally transparent, or +	    (upperhalftotal == length && alphatotal != 255*length)) // all close to opaque but not all totally opaque  	{ -		mIsMask = FALSE; +		mIsMask = FALSE; // not suitable for masking  	}  	else  	{ diff --git a/indra/llrender/llimagegl.h b/indra/llrender/llimagegl.h index 41239d24c8..03939888a5 100644 --- a/indra/llrender/llimagegl.h +++ b/indra/llrender/llimagegl.h @@ -91,7 +91,7 @@ public:  protected:  	virtual ~LLImageGL(); -	void analyzeAlpha(const void* data_in, S32 w, S32 h); +	void analyzeAlpha(const void* data_in, U32 w, U32 h);  	void calcAlphaChannelOffsetAndStride();  public: diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index c3540a717c..5597b23c69 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -778,8 +778,10 @@ LLRender::LLRender()  	mCurrAlphaFunc = CF_DEFAULT;  	mCurrAlphaFuncVal = 0.01f; -	mCurrBlendSFactor = BF_UNDEF; -	mCurrBlendDFactor = BF_UNDEF; +	mCurrBlendColorSFactor = BF_UNDEF; +	mCurrBlendAlphaSFactor = BF_UNDEF; +	mCurrBlendColorDFactor = BF_UNDEF; +	mCurrBlendAlphaDFactor = BF_UNDEF;  }  LLRender::~LLRender() @@ -995,15 +997,44 @@ void LLRender::blendFunc(eBlendFactor sfactor, eBlendFactor dfactor)  {  	llassert(sfactor < BF_UNDEF);  	llassert(dfactor < BF_UNDEF); -	if (mCurrBlendSFactor != sfactor || mCurrBlendDFactor != dfactor) +	if (mCurrBlendColorSFactor != sfactor || mCurrBlendColorDFactor != dfactor || +	    mCurrBlendAlphaSFactor != sfactor || mCurrBlendAlphaDFactor != dfactor)  	{ -		mCurrBlendSFactor = sfactor; -		mCurrBlendDFactor = dfactor; +		mCurrBlendColorSFactor = sfactor; +		mCurrBlendAlphaSFactor = sfactor; +		mCurrBlendColorDFactor = dfactor; +		mCurrBlendAlphaDFactor = dfactor;  		flush();  		glBlendFunc(sGLBlendFactor[sfactor], sGLBlendFactor[dfactor]);  	}  } +void LLRender::blendFunc(eBlendFactor color_sfactor, eBlendFactor color_dfactor, +			 eBlendFactor alpha_sfactor, eBlendFactor alpha_dfactor) +{ +	llassert(color_sfactor < BF_UNDEF); +	llassert(color_dfactor < BF_UNDEF); +	llassert(alpha_sfactor < BF_UNDEF); +	llassert(alpha_dfactor < BF_UNDEF); +	if (!gGLManager.mHasBlendFuncSeparate) +	{ +		LL_WARNS_ONCE("render") << "no glBlendFuncSeparateEXT(), using color-only blend func" << llendl; +		blendFunc(color_sfactor, color_dfactor); +		return; +	} +	if (mCurrBlendColorSFactor != color_sfactor || mCurrBlendColorDFactor != color_dfactor || +	    mCurrBlendAlphaSFactor != alpha_sfactor || mCurrBlendAlphaDFactor != alpha_dfactor) +	{ +		mCurrBlendColorSFactor = color_sfactor; +		mCurrBlendAlphaSFactor = alpha_sfactor; +		mCurrBlendColorDFactor = color_dfactor; +		mCurrBlendAlphaDFactor = alpha_dfactor; +		flush(); +		glBlendFuncSeparateEXT(sGLBlendFactor[color_sfactor], sGLBlendFactor[color_dfactor], +				       sGLBlendFactor[alpha_sfactor], sGLBlendFactor[alpha_dfactor]); +	} +} +  LLTexUnit* LLRender::getTexUnit(U32 index)  {  	if (index < mTexUnits.size()) diff --git a/indra/llrender/llrender.h b/indra/llrender/llrender.h index a90fbd4a5c..f6c87aa1db 100644 --- a/indra/llrender/llrender.h +++ b/indra/llrender/llrender.h @@ -323,7 +323,11 @@ public:  	void setAlphaRejectSettings(eCompareFunc func, F32 value = 0.01f); +	// applies blend func to both color and alpha  	void blendFunc(eBlendFactor sfactor, eBlendFactor dfactor); +	// applies separate blend functions to color and alpha +	void blendFunc(eBlendFactor color_sfactor, eBlendFactor color_dfactor, +		       eBlendFactor alpha_sfactor, eBlendFactor alpha_dfactor);  	LLTexUnit* getTexUnit(U32 index); @@ -362,8 +366,10 @@ private:  	std::vector<LLTexUnit*>		mTexUnits;  	LLTexUnit*			mDummyTexUnit; -	eBlendFactor mCurrBlendSFactor; -	eBlendFactor mCurrBlendDFactor; +	eBlendFactor mCurrBlendColorSFactor; +	eBlendFactor mCurrBlendColorDFactor; +	eBlendFactor mCurrBlendAlphaSFactor; +	eBlendFactor mCurrBlendAlphaDFactor;  	F32				mMaxAnisotropy; diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index 8ac51ee581..8012bbb6c8 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -382,6 +382,11 @@ LLVertexBuffer::LLVertexBuffer(U32 typemask, S32 usage) :  	{  		mUsage = 0 ;   	} + +	if (mUsage == GL_STREAM_DRAW_ARB && !sUseStreamDraw) +	{ +		mUsage = 0; +	}  	if (mUsage == GL_STREAM_DRAW_ARB && !sUseStreamDraw)  	{ | 
