diff options
Diffstat (limited to 'indra/llrender')
| -rw-r--r-- | indra/llrender/llfontgl.cpp | 2 | ||||
| -rw-r--r-- | indra/llrender/llgl.cpp | 102 | ||||
| -rw-r--r-- | indra/llrender/llgl.h | 2 | ||||
| -rw-r--r-- | indra/llrender/llglheaders.h | 13 | ||||
| -rw-r--r-- | indra/llrender/llglslshader.cpp | 7 | ||||
| -rw-r--r-- | indra/llrender/llimagegl.cpp | 99 | ||||
| -rw-r--r-- | indra/llrender/llrender.cpp | 205 | ||||
| -rw-r--r-- | indra/llrender/llrender.h | 1 | ||||
| -rw-r--r-- | indra/llrender/llvertexbuffer.cpp | 191 | ||||
| -rw-r--r-- | indra/llrender/llvertexbuffer.h | 10 | 
10 files changed, 551 insertions, 81 deletions
| diff --git a/indra/llrender/llfontgl.cpp b/indra/llrender/llfontgl.cpp index 607473d416..54f72d103e 100644 --- a/indra/llrender/llfontgl.cpp +++ b/indra/llrender/llfontgl.cpp @@ -329,7 +329,7 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons  		if (glyph_count >= GLYPH_BATCH_SIZE)  		{ -			gGL.begin(LLRender::QUADS); +			gGL.begin(LLRender::TRIANGLES);  			{  				gGL.vertexBatchPreTransformed(vertices, uvs, colors, glyph_count * 4);  			} diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp index 718de346f6..6875674e79 100644 --- a/indra/llrender/llgl.cpp +++ b/indra/llrender/llgl.cpp @@ -67,6 +67,22 @@ static const std::string HEADLESS_VERSION_STRING("1.0");  std::ofstream gFailLog; +void APIENTRY gl_debug_callback(GLenum source, +                                GLenum type, +                                GLuint id, +                                GLenum severity, +                                GLsizei length, +                                const GLchar* message, +                                GLvoid* userParam) +{ +	llwarns << "----- GL ERROR --------" << llendl; +	llwarns << "Type: " << std::hex << type << llendl; +	llwarns << "ID: " << std::hex << id << llendl; +	llwarns << "Severity: " << std::hex << severity << llendl; +	llwarns << "Message: " << message << llendl; +	llwarns << "-----------------------" << llendl; +} +  void ll_init_fail_log(std::string filename)  {  	gFailLog.open(filename.c_str()); @@ -110,6 +126,9 @@ std::list<LLGLUpdate*> LLGLUpdate::sGLQ;  #if (LL_WINDOWS || LL_LINUX || LL_SOLARIS)  && !LL_MESA_HEADLESS  // ATI prototypes + +PFNGLGETSTRINGIPROC glGetStringi = NULL; +  // vertex blending prototypes  PFNGLWEIGHTPOINTERARBPROC			glWeightPointerARB = NULL;  PFNGLVERTEXBLENDARBPROC				glVertexBlendARB = NULL; @@ -128,6 +147,12 @@ PFNGLUNMAPBUFFERARBPROC				glUnmapBufferARB = NULL;  PFNGLGETBUFFERPARAMETERIVARBPROC	glGetBufferParameterivARB = NULL;  PFNGLGETBUFFERPOINTERVARBPROC		glGetBufferPointervARB = NULL; +//GL_ARB_vertex_array_object +PFNGLBINDVERTEXARRAYPROC glBindVertexArray = NULL; +PFNGLDELETEVERTEXARRAYSPROC glDeleteVertexArrays = NULL; +PFNGLGENVERTEXARRAYSPROC glGenVertexArrays = NULL; +PFNGLISVERTEXARRAYPROC glIsVertexArray = NULL; +  // GL_ARB_map_buffer_range  PFNGLMAPBUFFERRANGEPROC			glMapBufferRange = NULL;  PFNGLFLUSHMAPPEDBUFFERRANGEPROC	glFlushMappedBufferRange = NULL; @@ -197,10 +222,16 @@ PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC glRenderbufferStorageMultisample = NULL;  PFNGLFRAMEBUFFERTEXTURELAYERPROC glFramebufferTextureLayer = NULL;  //GL_ARB_texture_multisample -PFNGLTEXIMAGE2DMULTISAMPLEPROC glTexImage2DMultisample; -PFNGLTEXIMAGE3DMULTISAMPLEPROC glTexImage3DMultisample; -PFNGLGETMULTISAMPLEFVPROC glGetMultisamplefv; -PFNGLSAMPLEMASKIPROC glSampleMaski; +PFNGLTEXIMAGE2DMULTISAMPLEPROC glTexImage2DMultisample = NULL; +PFNGLTEXIMAGE3DMULTISAMPLEPROC glTexImage3DMultisample = NULL; +PFNGLGETMULTISAMPLEFVPROC glGetMultisamplefv = NULL; +PFNGLSAMPLEMASKIPROC glSampleMaski = NULL; + +//GL_ARB_debug_output +PFNGLDEBUGMESSAGECONTROLARBPROC glDebugMessageControlARB = NULL; +PFNGLDEBUGMESSAGEINSERTARBPROC glDebugMessageInsertARB = NULL; +PFNGLDEBUGMESSAGECALLBACKARBPROC glDebugMessageCallbackARB = NULL; +PFNGLGETDEBUGMESSAGELOGARBPROC glGetDebugMessageLogARB = NULL;  // GL_EXT_blend_func_separate  PFNGLBLENDFUNCSEPARATEEXTPROC glBlendFuncSeparateEXT = NULL; @@ -353,6 +384,7 @@ LLGLManager::LLGLManager() :  	mHasBlendFuncSeparate(FALSE),  	mHasSync(FALSE),  	mHasVertexBufferObject(FALSE), +	mHasVertexArrayObject(FALSE),  	mHasMapBufferRange(FALSE),  	mHasFlushBufferRange(FALSE),  	mHasPBuffer(FALSE), @@ -374,6 +406,7 @@ LLGLManager::LLGLManager() :  	mHasAnisotropic(FALSE),  	mHasARBEnvCombine(FALSE),  	mHasCubeMap(FALSE), +	mHasDebugOutput(FALSE),  	mIsATI(FALSE),  	mIsNVIDIA(FALSE), @@ -451,13 +484,39 @@ bool LLGLManager::initGL()  		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 ) +	if (!glGetStringi)  	{ -		LL_WARNS("RenderInit") << "Frame buffer has less than 8 bits of alpha.  Avatar texture compositing will fail." << LL_ENDL; +		glGetStringi = (PFNGLGETSTRINGIPROC) GLH_EXT_GET_PROC_ADDRESS("glGetStringi");  	} +	//reload extensions string (may have changed after using wglCreateContextAttrib) +	if (glGetStringi) +	{ +		std::stringstream str; + +		GLint count = 0; +		glGetIntegerv(GL_NUM_EXTENSIONS, &count); +		for (GLint i = 0; i < count; ++i) +		{ +			str << (const char*) glGetStringi(GL_EXTENSIONS, i) << " "; +		} +		 +#if LL_WINDOWS +		{ +			PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetExtensionsStringARB = 0; +			wglGetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC)wglGetProcAddress("wglGetExtensionsStringARB"); +			if(wglGetExtensionsStringARB) +			{ +				str << (const char*) wglGetExtensionsStringARB(wglGetCurrentDC()); +			} +		} +#endif +		free(gGLHExts.mSysExts); +		std::string extensions = str.str(); +		gGLHExts.mSysExts = strdup(extensions.c_str()); +		 +	} +	  	// 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)); @@ -595,6 +654,12 @@ bool LLGLManager::initGL()  		glGetIntegerv(GL_MAX_SAMPLE_MASK_WORDS, &mMaxSampleMaskWords);  	} +	if (mHasDebugOutput && gDebugGL) +	{ //setup debug output callback +		glDebugMessageCallbackARB((GLDEBUGPROCARB) gl_debug_callback, NULL); +		glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB); +	} +  	//HACK always disable texture multisample, use FXAA instead  	mHasTextureMultisample = FALSE;  #if LL_WINDOWS @@ -789,7 +854,7 @@ void LLGLManager::initExtensions()  	mHasVertexShader = FALSE;  	mHasFragmentShader = FALSE;  	mHasTextureRectangle = FALSE; -#else // LL_MESA_HEADLESS +#else // LL_MESA_HEADLESS //important, gGLHExts.mSysExts is uninitialized until after glh_init_extensions is called  	mHasMultitexture = glh_init_extensions("GL_ARB_multitexture");  	mHasATIMemInfo = ExtensionExists("GL_ATI_meminfo", gGLHExts.mSysExts);  	mHasNVXMemInfo = ExtensionExists("GL_NVX_gpu_memory_info", gGLHExts.mSysExts); @@ -803,6 +868,7 @@ void LLGLManager::initExtensions()  	mHasOcclusionQuery = ExtensionExists("GL_ARB_occlusion_query", gGLHExts.mSysExts);  	mHasOcclusionQuery2 = ExtensionExists("GL_ARB_occlusion_query2", gGLHExts.mSysExts);  	mHasVertexBufferObject = ExtensionExists("GL_ARB_vertex_buffer_object", gGLHExts.mSysExts); +	mHasVertexArrayObject = ExtensionExists("GL_ARB_vertex_array_object", gGLHExts.mSysExts);  	mHasSync = ExtensionExists("GL_ARB_sync", gGLHExts.mSysExts);  	mHasMapBufferRange = ExtensionExists("GL_ARB_map_buffer_range", gGLHExts.mSysExts);  	mHasFlushBufferRange = ExtensionExists("GL_APPLE_flush_buffer_range", gGLHExts.mSysExts); @@ -821,6 +887,7 @@ void LLGLManager::initExtensions()  	mHasBlendFuncSeparate = ExtensionExists("GL_EXT_blend_func_separate", gGLHExts.mSysExts);  	mHasTextureRectangle = ExtensionExists("GL_ARB_texture_rectangle", gGLHExts.mSysExts);  	mHasTextureMultisample = ExtensionExists("GL_ARB_texture_multisample", gGLHExts.mSysExts); +	mHasDebugOutput = ExtensionExists("GL_ARB_debug_output", gGLHExts.mSysExts);  #if !LL_DARWIN  	mHasPointParameters = !mIsATI && ExtensionExists("GL_ARB_point_parameters", gGLHExts.mSysExts);  #endif @@ -1000,6 +1067,13 @@ void LLGLManager::initExtensions()  			mHasVertexBufferObject = FALSE;  		}  	} +	if (mHasVertexArrayObject) +	{ +		glBindVertexArray = (PFNGLBINDVERTEXARRAYPROC) GLH_EXT_GET_PROC_ADDRESS("glBindVertexArray"); +		glDeleteVertexArrays = (PFNGLDELETEVERTEXARRAYSPROC) GLH_EXT_GET_PROC_ADDRESS("glDeleteVertexArrays"); +		glGenVertexArrays = (PFNGLGENVERTEXARRAYSPROC) GLH_EXT_GET_PROC_ADDRESS("glGenVertexArrays"); +		glIsVertexArray = (PFNGLISVERTEXARRAYPROC) GLH_EXT_GET_PROC_ADDRESS("glIsVertexArray"); +	}  	if (mHasSync)  	{  		glFenceSync = (PFNGLFENCESYNCPROC) GLH_EXT_GET_PROC_ADDRESS("glFenceSync"); @@ -1054,6 +1128,13 @@ void LLGLManager::initExtensions()  		glGetMultisamplefv = (PFNGLGETMULTISAMPLEFVPROC) GLH_EXT_GET_PROC_ADDRESS("glGetMultisamplefv");  		glSampleMaski = (PFNGLSAMPLEMASKIPROC) GLH_EXT_GET_PROC_ADDRESS("glSampleMaski");  	}	 +	if (mHasDebugOutput) +	{ +		glDebugMessageControlARB = (PFNGLDEBUGMESSAGECONTROLARBPROC) GLH_EXT_GET_PROC_ADDRESS("glDebugMessageControlARB"); +		glDebugMessageInsertARB = (PFNGLDEBUGMESSAGEINSERTARBPROC) GLH_EXT_GET_PROC_ADDRESS("glDebugMessageInsertARB"); +		glDebugMessageCallbackARB = (PFNGLDEBUGMESSAGECALLBACKARBPROC) GLH_EXT_GET_PROC_ADDRESS("glDebugMessageCallbackARB"); +		glGetDebugMessageLogARB = (PFNGLGETDEBUGMESSAGELOGARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetDebugMessageLogARB"); +	}  #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"); @@ -1341,9 +1422,6 @@ void LLGLState::initClass()  	//make sure multisample defaults to disabled  	sStateMap[GL_MULTISAMPLE_ARB] = GL_FALSE;  	glDisable(GL_MULTISAMPLE_ARB); - -	sStateMap[GL_MULTISAMPLE_ARB] = GL_FALSE; -	glDisable(GL_MULTISAMPLE_ARB);  }  //static diff --git a/indra/llrender/llgl.h b/indra/llrender/llgl.h index 495e523c31..dee7ec0739 100644 --- a/indra/llrender/llgl.h +++ b/indra/llrender/llgl.h @@ -88,6 +88,7 @@ public:  	// ARB Extensions  	BOOL mHasVertexBufferObject; +	BOOL mHasVertexArrayObject;  	BOOL mHasSync;  	BOOL mHasMapBufferRange;  	BOOL mHasFlushBufferRange; @@ -112,6 +113,7 @@ public:  	BOOL mHasAnisotropic;  	BOOL mHasARBEnvCombine;  	BOOL mHasCubeMap; +	BOOL mHasDebugOutput;  	// Vendor-specific extensions  	BOOL mIsATI; diff --git a/indra/llrender/llglheaders.h b/indra/llrender/llglheaders.h index f319009bc8..ede1983651 100644 --- a/indra/llrender/llglheaders.h +++ b/indra/llrender/llglheaders.h @@ -533,6 +533,7 @@ extern PFNGLSAMPLEMASKIPROC glSampleMaski;  // WGL_ARB_create_context  extern PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB; +extern PFNGLGETSTRINGIPROC glGetStringi;  // GL_ARB_vertex_buffer_object  extern PFNGLBINDBUFFERARBPROC		glBindBufferARB; @@ -547,6 +548,12 @@ extern PFNGLUNMAPBUFFERARBPROC		glUnmapBufferARB;  extern PFNGLGETBUFFERPARAMETERIVARBPROC	glGetBufferParameterivARB;  extern PFNGLGETBUFFERPOINTERVARBPROC	glGetBufferPointervARB; +// GL_ARB_vertex_array_object +extern PFNGLBINDVERTEXARRAYPROC glBindVertexArray; +extern PFNGLDELETEVERTEXARRAYSPROC glDeleteVertexArrays; +extern PFNGLGENVERTEXARRAYSPROC glGenVertexArrays; +extern PFNGLISVERTEXARRAYPROC glIsVertexArray; +  // GL_ARB_sync  extern PFNGLFENCESYNCPROC				glFenceSync;  extern PFNGLISSYNCPROC					glIsSync; @@ -737,6 +744,12 @@ extern PFNGLTEXIMAGE3DMULTISAMPLEPROC glTexImage3DMultisample;  extern PFNGLGETMULTISAMPLEFVPROC glGetMultisamplefv;  extern PFNGLSAMPLEMASKIPROC glSampleMaski; +//GL_ARB_debug_output +extern PFNGLDEBUGMESSAGECONTROLARBPROC glDebugMessageControlARB; +extern PFNGLDEBUGMESSAGEINSERTARBPROC glDebugMessageInsertARB; +extern PFNGLDEBUGMESSAGECALLBACKARBPROC glDebugMessageCallbackARB; +extern PFNGLGETDEBUGMESSAGELOGARBPROC glGetDebugMessageLogARB; +  #elif LL_DARWIN  //----------------------------------------------------------------------------  // LL_DARWIN diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp index 0dcf563491..da4658dc03 100644 --- a/indra/llrender/llglslshader.cpp +++ b/indra/llrender/llglslshader.cpp @@ -243,6 +243,13 @@ void LLGLSLShader::attachObjects(GLhandleARB* objects, S32 count)  BOOL LLGLSLShader::mapAttributes(const vector<string> * attributes)  { +	//before linking, make sure reserved attributes always have consistent locations +	for (U32 i = 0; i < LLShaderMgr::instance()->mReservedAttribs.size(); i++) +	{ +		const char* name = LLShaderMgr::instance()->mReservedAttribs[i].c_str(); +		glBindAttribLocationARB(mProgramObject, i, (const GLcharARB *) name); +	} +	  	//link the program  	BOOL res = link(); diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index 0fb4a7784a..4da796dd1e 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -725,7 +725,7 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips)  		}  		else if (!is_compressed)  		{ -			if (mAutoGenMips) //auto-generating mipmaps is deprecated in GL 3.0 +			if (mAutoGenMips && !LLRender::sGLCoreProfile) //auto-generating mipmaps is deprecated in GL 3.0  			{  				glTexParameteri(LLTexUnit::getInternalType(mBindTarget), GL_GENERATE_MIPMAP_SGIS, TRUE);  				stop_glerror(); @@ -877,6 +877,9 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips)  BOOL LLImageGL::preAddToAtlas(S32 discard_level, const LLImageRaw* raw_image)  { +	//not compatible with core GL profile +	llassert(!LLRender::sGLCoreProfile); +  	if (gGLManager.mIsDisabled)  	{  		llwarns << "Trying to create a texture while GL is disabled!" << llendl; @@ -903,29 +906,29 @@ BOOL LLImageGL::preAddToAtlas(S32 discard_level, const LLImageRaw* raw_image)  	{  		switch (mComponents)  		{ -		  case 1: +			case 1:  			// Use luminance alpha (for fonts)  			mFormatInternal = GL_LUMINANCE8;  			mFormatPrimary = GL_LUMINANCE;  			mFormatType = GL_UNSIGNED_BYTE;  			break; -		  case 2: +			case 2:  			// Use luminance alpha (for fonts)  			mFormatInternal = GL_LUMINANCE8_ALPHA8;  			mFormatPrimary = GL_LUMINANCE_ALPHA;  			mFormatType = GL_UNSIGNED_BYTE;  			break; -		  case 3: +			case 3:  			mFormatInternal = GL_RGB8;  			mFormatPrimary = GL_RGB;  			mFormatType = GL_UNSIGNED_BYTE;  			break; -		  case 4: +			case 4:  			mFormatInternal = GL_RGBA8;  			mFormatPrimary = GL_RGBA;  			mFormatType = GL_UNSIGNED_BYTE;  			break; -		  default: +			default:  			llerrs << "Bad number of components for texture: " << (U32)getComponents() << llendl;  		}  	} @@ -1101,8 +1104,76 @@ void LLImageGL::deleteTextures(S32 numTextures, U32 *textures, bool immediate)  // static  void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 width, S32 height, U32 pixformat, U32 pixtype, const void *pixels)  { -	glTexImage2D(target, miplevel, intformat, width, height, 0, pixformat, pixtype, pixels); +	bool use_scratch = false; +	U32* scratch = NULL; +	if (LLRender::sGLCoreProfile) +	{ +		if (intformat == GL_ALPHA8 && pixformat == GL_ALPHA && pixtype == GL_UNSIGNED_BYTE)  +		{ //GL_ALPHA is deprecated, convert to RGBA +			use_scratch = true; +			scratch = new U32[width*height]; + +			U32 pixel_count = (U32) (width*height); +			for (U32 i = 0; i < pixel_count; i++) +			{ +				U8* pix = (U8*) &scratch[i]; +				pix[0] = pix[1] = pix[2] = 0; +				pix[3] = ((U8*) pixels)[i]; +			}				 +			 +			pixformat = GL_RGBA; +			intformat = GL_RGBA8; +		} + +		if (intformat == GL_LUMINANCE8_ALPHA8 && pixformat == GL_LUMINANCE_ALPHA && pixtype == GL_UNSIGNED_BYTE)  +		{ //GL_LUMINANCE_ALPHA is deprecated, convert to RGBA +			use_scratch = true; +			scratch = new U32[width*height]; + +			U32 pixel_count = (U32) (width*height); +			for (U32 i = 0; i < pixel_count; i++) +			{ +				U8 lum = ((U8*) pixels)[i*2+0]; +				U8 alpha = ((U8*) pixels)[i*2+1]; + +				U8* pix = (U8*) &scratch[i]; +				pix[0] = pix[1] = pix[2] = lum; +				pix[3] = alpha; +			}				 +			 +			pixformat = GL_RGBA; +			intformat = GL_RGBA8; +		} + +		if (intformat == GL_LUMINANCE8 && pixformat == GL_LUMINANCE && pixtype == GL_UNSIGNED_BYTE)  +		{ //GL_LUMINANCE_ALPHA is deprecated, convert to RGB +			use_scratch = true; +			scratch = new U32[width*height]; + +			U32 pixel_count = (U32) (width*height); +			for (U32 i = 0; i < pixel_count; i++) +			{ +				U8 lum = ((U8*) pixels)[i*2+0]; +				U8 alpha = ((U8*) pixels)[i*2+1]; + +				U8* pix = (U8*) &scratch[i]; +				pix[0] = pix[1] = pix[2] = lum; +				pix[3] = 255; +			}				 +			 +			pixformat = GL_RGBA; +			intformat = GL_RGB8; +		} +	} + +	stop_glerror(); +	glTexImage2D(target, miplevel, intformat, width, height, 0, pixformat, pixtype, use_scratch ? scratch : pixels);  	stop_glerror(); + +	if (use_scratch) +	{ +		delete [] scratch; +	}  }  //create an empty GL texture: just create a texture name @@ -1169,29 +1240,29 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S  	{  		switch (mComponents)  		{ -		  case 1: +			case 1:  			// Use luminance alpha (for fonts)  			mFormatInternal = GL_LUMINANCE8;  			mFormatPrimary = GL_LUMINANCE;  			mFormatType = GL_UNSIGNED_BYTE;  			break; -		  case 2: +			case 2:  			// Use luminance alpha (for fonts)  			mFormatInternal = GL_LUMINANCE8_ALPHA8;  			mFormatPrimary = GL_LUMINANCE_ALPHA;  			mFormatType = GL_UNSIGNED_BYTE;  			break; -		  case 3: +			case 3:  			mFormatInternal = GL_RGB8;  			mFormatPrimary = GL_RGB;  			mFormatType = GL_UNSIGNED_BYTE;  			break; -		  case 4: +			case 4:  			mFormatInternal = GL_RGBA8;  			mFormatPrimary = GL_RGBA;  			mFormatType = GL_UNSIGNED_BYTE;  			break; -		  default: +			default:  			llerrs << "Bad number of components for texture: " << (U32)getComponents() << llendl;  		} @@ -1214,6 +1285,7 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S  BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_hasmips, S32 usename)  {  	llassert(data_in); +	stop_glerror();  	if (discard_level < 0)  	{ @@ -1242,8 +1314,11 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_  		stop_glerror();  		{  			llverify(gGL.getTexUnit(0)->bind(this)); +			stop_glerror();  			glTexParameteri(LLTexUnit::getInternalType(mBindTarget), GL_TEXTURE_BASE_LEVEL, 0); +			stop_glerror();  			glTexParameteri(LLTexUnit::getInternalType(mBindTarget), GL_TEXTURE_MAX_LEVEL,  mMaxDiscardLevel-discard_level); +			stop_glerror();  		}  	}  	if (!mTexName) diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index efeb7709a4..daeb58b279 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -179,10 +179,13 @@ void LLTexUnit::enable(eTextureType type)  	if ( (mCurrTexType != type || gGL.mDirty) && (type != TT_NONE) )  	{ +		stop_glerror();  		activate(); +		stop_glerror();  		if (mCurrTexType != TT_NONE && !gGL.mDirty)  		{  			disable(); // Force a disable of a previous texture type if it's enabled. +			stop_glerror();  		}  		mCurrTexType = type; @@ -191,7 +194,9 @@ void LLTexUnit::enable(eTextureType type)  			type != LLTexUnit::TT_MULTISAMPLE_TEXTURE &&  			mIndex < gGLManager.mNumTextureUnits)  		{ +			stop_glerror();  			glEnable(sGLTextureType[type]); +			stop_glerror();  		}  	}  } @@ -287,26 +292,35 @@ bool LLTexUnit::bind(LLImageGL* texture, bool for_rendering, bool forceBind)  		{  			return bind(LLImageGL::sDefaultGLTexture) ;  		} +		stop_glerror();  		return false ;  	}  	if ((mCurrTexture != texture->getTexName()) || forceBind)  	{  		gGL.flush(); +		stop_glerror();  		activate(); +		stop_glerror();  		enable(texture->getTarget()); +		stop_glerror();  		mCurrTexture = texture->getTexName();  		glBindTexture(sGLTextureType[texture->getTarget()], mCurrTexture); +		stop_glerror();  		texture->updateBindStats(texture->mTextureMemory);		  		mHasMipMaps = texture->mHasMipMaps;  		if (texture->mTexOptionsDirty)  		{ +			stop_glerror();  			texture->mTexOptionsDirty = false;  			setTextureAddressMode(texture->mAddressMode);  			setTextureFilteringOption(texture->mFilterOption); +			stop_glerror();  		}  	} +	stop_glerror(); +  	return true;  } @@ -989,6 +1003,7 @@ void LLLightState::setSpotDirection(const LLVector3& direction)  LLRender::LLRender()    : mDirty(false),      mCount(0), +	mQuadCycle(0),      mMode(LLRender::TRIANGLES),      mCurrTextureUnitIndex(0),      mMaxAnisotropy(0.f)  @@ -1678,6 +1693,11 @@ void LLRender::begin(const GLuint& mode)  {  	if (mode != mMode)  	{ +		if (mode == LLRender::QUADS) +		{ +			mQuadCycle = 1; +		} +  		if (mMode == LLRender::QUADS ||  			mMode == LLRender::LINES ||  			mMode == LLRender::TRIANGLES || @@ -1765,7 +1785,7 @@ void LLRender::flush()  		if (gDebugGL)  		{ -			if (mMode == LLRender::QUADS) +			if (mMode == LLRender::QUADS && !sGLCoreProfile)  			{  				if (mCount%4 != 0)  				{ @@ -1794,12 +1814,30 @@ void LLRender::flush()  		U32 count = mCount;  		mCount = 0; +		if (mBuffer->useVBOs() && !mBuffer->isLocked()) +		{ //hack to only flush the part of the buffer that was updated (relies on stream draw using buffersubdata) +			mBuffer->getVertexStrider(mVerticesp, 0, count); +			mBuffer->getTexCoord0Strider(mTexcoordsp, 0, count); +			mBuffer->getColorStrider(mColorsp, 0, count); +		} +		 +		//only flush the part of the   		mBuffer->setBuffer(immediate_mask); -		mBuffer->drawArrays(mMode, 0, count); + +		if (mMode == LLRender::QUADS && sGLCoreProfile) +		{ +			mBuffer->drawArrays(LLRender::TRIANGLES, 0, count); +			mQuadCycle = 1; +		} +		else +		{ +			mBuffer->drawArrays(mMode, 0, count); +		}  		mVerticesp[0] = mVerticesp[count];  		mTexcoordsp[0] = mTexcoordsp[count];  		mColorsp[0] = mColorsp[count]; +		  		mCount = 0;  	}  } @@ -1823,10 +1861,29 @@ void LLRender::vertex3f(const GLfloat& x, const GLfloat& y, const GLfloat& z)  		mVerticesp[mCount] = vert;  	} +	if (mMode == LLRender::QUADS && LLRender::sGLCoreProfile) +	{ +		mQuadCycle++; +		if (mQuadCycle == 4) +		{ //copy two vertices so fourth quad element will add a triangle +			mQuadCycle = 0; +	 +			mCount++; +			mVerticesp[mCount] = mVerticesp[mCount-3]; +			mColorsp[mCount] = mColorsp[mCount-3]; +			mTexcoordsp[mCount] = mTexcoordsp[mCount-3]; + +			mCount++; +			mVerticesp[mCount] = mVerticesp[mCount-2]; +			mColorsp[mCount] = mColorsp[mCount-2]; +			mTexcoordsp[mCount] = mTexcoordsp[mCount-2]; +		} +	} +  	mCount++;  	mVerticesp[mCount] = mVerticesp[mCount-1];  	mColorsp[mCount] = mColorsp[mCount-1]; -	mTexcoordsp[mCount] = mTexcoordsp[mCount-1]; +	mTexcoordsp[mCount] = mTexcoordsp[mCount-1];	  }  void LLRender::vertexBatchPreTransformed(LLVector3* verts, S32 vert_count) @@ -1837,13 +1894,50 @@ void LLRender::vertexBatchPreTransformed(LLVector3* verts, S32 vert_count)  		return;  	} -	for (S32 i = 0; i < vert_count; i++) +	if (sGLCoreProfile && mMode == LLRender::QUADS) +	{ //quads are deprecated, convert to triangle list +		S32 i = 0; +		 +		while (i < vert_count) +		{ +			//read first three +			mVerticesp[mCount++] = verts[i++]; +			mTexcoordsp[mCount] = mTexcoordsp[mCount-1]; +			mColorsp[mCount] = mColorsp[mCount-1]; + +			mVerticesp[mCount++] = verts[i++]; +			mTexcoordsp[mCount] = mTexcoordsp[mCount-1]; +			mColorsp[mCount] = mColorsp[mCount-1]; + +			mVerticesp[mCount++] = verts[i++]; +			mTexcoordsp[mCount] = mTexcoordsp[mCount-1]; +			mColorsp[mCount] = mColorsp[mCount-1]; + +			//copy two +			mVerticesp[mCount++] = verts[i-3]; +			mTexcoordsp[mCount] = mTexcoordsp[mCount-1]; +			mColorsp[mCount] = mColorsp[mCount-1]; + +			mVerticesp[mCount++] = verts[i-1]; +			mTexcoordsp[mCount] = mTexcoordsp[mCount-1]; +			mColorsp[mCount] = mColorsp[mCount-1]; +			 +			//copy last one +			mVerticesp[mCount++] = verts[i++]; +			mTexcoordsp[mCount] = mTexcoordsp[mCount-1]; +			mColorsp[mCount] = mColorsp[mCount-1]; +		} +	} +	else  	{ -		mVerticesp[mCount] = verts[i]; +		for (S32 i = 0; i < vert_count; i++) +		{ +			mVerticesp[mCount] = verts[i]; -		mCount++; -		mTexcoordsp[mCount] = mTexcoordsp[mCount-1]; -		mColorsp[mCount] = mColorsp[mCount-1]; +			mCount++; +			mTexcoordsp[mCount] = mTexcoordsp[mCount-1]; +			mColorsp[mCount] = mColorsp[mCount-1]; +		}  	}  	mVerticesp[mCount] = mVerticesp[mCount-1]; @@ -1857,13 +1951,50 @@ void LLRender::vertexBatchPreTransformed(LLVector3* verts, LLVector2* uvs, S32 v  		return;  	} -	for (S32 i = 0; i < vert_count; i++) +	if (sGLCoreProfile && mMode == LLRender::QUADS) +	{ //quads are deprecated, convert to triangle list +		S32 i = 0; + +		while (i < vert_count) +		{ +			//read first three +			mVerticesp[mCount] = verts[i]; +			mTexcoordsp[mCount++] = uvs[i++]; +			mColorsp[mCount] = mColorsp[mCount-1]; + +			mVerticesp[mCount] = verts[i]; +			mTexcoordsp[mCount++] = uvs[i++]; +			mColorsp[mCount] = mColorsp[mCount-1]; + +			mVerticesp[mCount] = verts[i]; +			mTexcoordsp[mCount++] = uvs[i++]; +			mColorsp[mCount] = mColorsp[mCount-1]; + +			//copy last two +			mVerticesp[mCount] = verts[i-3]; +			mTexcoordsp[mCount++] = uvs[i-3]; +			mColorsp[mCount] = mColorsp[mCount-1]; + +			mVerticesp[mCount] = verts[i-1]; +			mTexcoordsp[mCount++] = uvs[i-1]; +			mColorsp[mCount] = mColorsp[mCount-1]; + +			//copy last one +			mVerticesp[mCount] = verts[i]; +			mTexcoordsp[mCount++] = uvs[i++]; +			mColorsp[mCount] = mColorsp[mCount-1]; +		} +	} +	else  	{ -		mVerticesp[mCount] = verts[i]; -		mTexcoordsp[mCount] = uvs[i]; +		for (S32 i = 0; i < vert_count; i++) +		{ +			mVerticesp[mCount] = verts[i]; +			mTexcoordsp[mCount] = uvs[i]; -		mCount++; -		mColorsp[mCount] = mColorsp[mCount-1]; +			mCount++; +			mColorsp[mCount] = mColorsp[mCount-1]; +		}  	}  	mVerticesp[mCount] = mVerticesp[mCount-1]; @@ -1878,13 +2009,51 @@ void LLRender::vertexBatchPreTransformed(LLVector3* verts, LLVector2* uvs, LLCol  		return;  	} -	for (S32 i = 0; i < vert_count; i++) +	 +	if (sGLCoreProfile && mMode == LLRender::QUADS) +	{ //quads are deprecated, convert to triangle list +		S32 i = 0; + +		while (i < vert_count) +		{ +			//read first three +			mVerticesp[mCount] = verts[i]; +			mTexcoordsp[mCount] = uvs[i]; +			mColorsp[mCount++] = colors[i++]; + +			mVerticesp[mCount] = verts[i]; +			mTexcoordsp[mCount] = uvs[i]; +			mColorsp[mCount++] = colors[i++]; + +			mVerticesp[mCount] = verts[i]; +			mTexcoordsp[mCount] = uvs[i]; +			mColorsp[mCount++] = colors[i++]; + +			//copy last two +			mVerticesp[mCount] = verts[i-3]; +			mTexcoordsp[mCount] = uvs[i-3]; +			mColorsp[mCount++] = colors[i-3]; + +			mVerticesp[mCount] = verts[i-1]; +			mTexcoordsp[mCount] = uvs[i-1]; +			mColorsp[mCount++] = colors[i-1]; + +			//copy last one +			mVerticesp[mCount] = verts[i]; +			mTexcoordsp[mCount] = uvs[i]; +			mColorsp[mCount++] = colors[i++]; +		} +	} +	else  	{ -		mVerticesp[mCount] = verts[i]; -		mTexcoordsp[mCount] = uvs[i]; -		mColorsp[mCount] = colors[i]; +		for (S32 i = 0; i < vert_count; i++) +		{ +			mVerticesp[mCount] = verts[i]; +			mTexcoordsp[mCount] = uvs[i]; +			mColorsp[mCount] = colors[i]; -		mCount++; +			mCount++; +		}  	}  	mVerticesp[mCount] = mVerticesp[mCount-1]; diff --git a/indra/llrender/llrender.h b/indra/llrender/llrender.h index 44d9ec1f15..61e503d384 100644 --- a/indra/llrender/llrender.h +++ b/indra/llrender/llrender.h @@ -442,6 +442,7 @@ private:  	LLColor4 mAmbientLightColor;  	bool			mDirty; +	U32				mQuadCycle;  	U32				mCount;  	U32				mMode;  	U32				mCurrTextureUnitIndex; diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index 090da765ac..f822a7babd 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -55,6 +55,7 @@ S32 LLVertexBuffer::sMappedCount = 0;  BOOL LLVertexBuffer::sDisableVBOMapping = FALSE ;  BOOL LLVertexBuffer::sEnableVBOs = TRUE;  U32 LLVertexBuffer::sGLRenderBuffer = 0; +U32 LLVertexBuffer::sGLRenderArray = 0;  U32 LLVertexBuffer::sGLRenderIndices = 0;  U32 LLVertexBuffer::sLastMask = 0;  BOOL LLVertexBuffer::sVBOActive = FALSE; @@ -149,7 +150,7 @@ U32 LLVertexBuffer::sGLMode[LLRender::NUM_MODES] =  //static -void LLVertexBuffer::setupClientArrays(U32 data_mask) +void LLVertexBuffer::setupClientArrays(U32 data_mask, U32& ref_mask)  {  	/*if (LLGLImmediate::sStarted)  	{ @@ -158,13 +159,10 @@ void LLVertexBuffer::setupClientArrays(U32 data_mask)  	LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr; -	if (sLastMask != data_mask) +	if (ref_mask != data_mask)  	{  		llassert(!LLGLSLShader::sNoFixedFunction || shader != NULL); -		static LLGLSLShader* last_shader = LLGLSLShader::sCurBoundShaderPtr; -		llassert(sLastMask == 0 || last_shader == shader); -		last_shader = shader; - +		  		U32 mask[] =  		{  			MAP_VERTEX, @@ -213,7 +211,7 @@ void LLVertexBuffer::setupClientArrays(U32 data_mask)  				loc = shader->getAttribLocation(type[i]);  			} -			if (sLastMask & mask[i]) +			if (ref_mask & mask[i])  			{ //was enabled  				if (!(data_mask & mask[i]))  				{ //needs to be disabled @@ -297,7 +295,7 @@ void LLVertexBuffer::setupClientArrays(U32 data_mask)  				loc = shader->getAttribLocation(type_tc[i]);  			} -			if (sLastMask & map_tc[i]) +			if (ref_mask & map_tc[i])  			{  				if (!(data_mask & map_tc[i]))  				{ //disable @@ -330,7 +328,7 @@ void LLVertexBuffer::setupClientArrays(U32 data_mask)  		if (!shader)  		{ -			if (sLastMask & MAP_BINORMAL) +			if (ref_mask & MAP_BINORMAL)  			{  				if (!(data_mask & MAP_BINORMAL))  				{ @@ -347,7 +345,7 @@ void LLVertexBuffer::setupClientArrays(U32 data_mask)  			}  		} -		sLastMask = data_mask; +		ref_mask = data_mask;  	}  } @@ -589,6 +587,12 @@ void LLVertexBuffer::initClass(bool use_vbo, bool no_vbo_mapping)  //static   void LLVertexBuffer::unbind()  { +	if (sGLRenderArray) +	{ +		glBindVertexArray(0); +		sGLRenderArray = 0; +	} +  	if (sVBOActive)  	{  		glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); @@ -640,6 +644,8 @@ LLVertexBuffer::LLVertexBuffer(U32 typemask, S32 usage) :  	mRequestedNumIndices(-1),  	mUsage(usage),  	mGLBuffer(0), +	mGLArray(0), +	mLastMask(0),  	mGLIndices(0),   	mMappedData(NULL),  	mMappedIndexData(NULL),  @@ -669,12 +675,23 @@ LLVertexBuffer::LLVertexBuffer(U32 typemask, S32 usage) :  		mUsage = GL_STREAM_DRAW_ARB;  	} +	if (mUsage == 0 && LLRender::sGLCoreProfile) +	{ //MUST use VBOs for all rendering +		mUsage = GL_STREAM_DRAW_ARB; +	} +  	//zero out offsets  	for (U32 i = 0; i < TYPE_MAX; i++)  	{  		mOffsets[i] = 0;  	} +	//initialize cached attrib pointers +	for (U32 i = 0; i < LL_MAX_VERTEX_ATTRIB_LOCATION; i++) +	{ +		mLastPointer[i] = (void*) 0xFFFFFFFF; +	} +  	mTypeMask = typemask;  	mSize = 0;  	mAlignedOffset = 0; @@ -732,6 +749,12 @@ LLVertexBuffer::~LLVertexBuffer()  	LLMemType mt2(LLMemType::MTYPE_VERTEX_DESTRUCTOR);  	destroyGLBuffer();  	destroyGLIndices(); + +	if (mGLArray) +	{ +		glDeleteVertexArrays(1, &mGLArray); +	} +  	sCount--;  	if (mFence) @@ -1041,6 +1064,11 @@ void LLVertexBuffer::allocateBuffer(S32 nverts, S32 nindices, bool create)  	{  		createGLBuffer();  		createGLIndices(); + +		if (gGLManager.mHasVertexArrayObject && useVBOs()) +		{ +			glGenVertexArrays(1, &mGLArray); +		}  	}  	sAllocatedBytes += getSize() + getIndicesSize(); @@ -1762,7 +1790,8 @@ void LLVertexBuffer::setBuffer(U32 data_mask, S32 type)  {  	LLMemType mt2(LLMemType::MTYPE_VERTEX_SET_BUFFER);  	//set up pointers if the data mask is different ... -	BOOL setup = (sLastMask != data_mask); +	U32& ref_mask = mGLArray ? mLastMask : sLastMask; +	BOOL setup = (ref_mask != data_mask);  	if (gDebugGL && data_mask != 0)  	{ @@ -1794,15 +1823,19 @@ void LLVertexBuffer::setBuffer(U32 data_mask, S32 type)  	if (useVBOs())  	{ +		if (mGLArray && mGLArray != sGLRenderArray) +		{ +			glBindVertexArray(mGLArray); +			sGLRenderArray = mGLArray; +		} +  		if (mGLBuffer && (mGLBuffer != sGLRenderBuffer || !sVBOActive))  		{  			/*if (sMapped)  			{  				llerrs << "VBO bound while another VBO mapped!" << llendl;  			}*/ -			stop_glerror();  			glBindBufferARB(GL_ARRAY_BUFFER_ARB, mGLBuffer); -			stop_glerror();  			sBindCount++;  			sVBOActive = TRUE;  			setup = TRUE; // ... or the bound buffer changed @@ -1813,13 +1846,12 @@ void LLVertexBuffer::setBuffer(U32 data_mask, S32 type)  			{  				llerrs << "VBO bound while another VBO mapped!" << llendl;  			}*/ -			stop_glerror();  			glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, mGLIndices);  			stop_glerror();  			sBindCount++;  			sIBOActive = TRUE;  		} -		 +  		BOOL error = FALSE;  		if (gDebugGL)  		{ @@ -1957,7 +1989,10 @@ void LLVertexBuffer::setBuffer(U32 data_mask, S32 type)  		}  	} -	setupClientArrays(data_mask); +	if (data_mask) +	{ +		setupClientArrays(data_mask, ref_mask); +	}  	if (mGLIndices)  	{ @@ -1998,10 +2033,18 @@ void LLVertexBuffer::setupVertexBuffer(U32 data_mask) const  		{  			loc = shader->getAttribLocation(TYPE_NORMAL);  		} - +		  		if (loc >= 0)  		{ -			glVertexAttribPointerARB(loc, 3, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_NORMAL], (void*)(base + mOffsets[TYPE_NORMAL])); +			void* ptr = (void*)(base + mOffsets[TYPE_NORMAL]); +			if (mLastPointer[loc] != ptr) +			{ +				glVertexAttribPointerARB(loc, 3, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_NORMAL], ptr); +			} +			if (mGLArray) +			{ +				mLastPointer[loc] = ptr; +			}  		}  		else if (!shader)  		{ @@ -2018,7 +2061,15 @@ void LLVertexBuffer::setupVertexBuffer(U32 data_mask) const  		if (loc >= 0)  		{ -			glVertexAttribPointerARB(loc,2,GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD3], (void*)(base + mOffsets[TYPE_TEXCOORD3])); +			void* ptr = (void*)(base + mOffsets[TYPE_TEXCOORD3]); +			if (mLastPointer[loc] != ptr) +			{ +				glVertexAttribPointerARB(loc,2,GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD3], ptr); +			} +			if (mGLArray) +			{ +				mLastPointer[loc] = ptr; +			}  		}  		else if (!shader)  		{ @@ -2037,7 +2088,15 @@ void LLVertexBuffer::setupVertexBuffer(U32 data_mask) const  		if (loc >= 0)  		{ -			glVertexAttribPointerARB(loc,2,GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD2], (void*)(base + mOffsets[TYPE_TEXCOORD2])); +			void* ptr = (void*)(base + mOffsets[TYPE_TEXCOORD2]); +			if (mLastPointer[loc] != ptr) +			{ +				glVertexAttribPointerARB(loc,2,GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD2], ptr); +			} +			if (mGLArray) +			{ +				mLastPointer[loc] = ptr; +			}  		}  		else if (!shader)  		{ @@ -2056,7 +2115,15 @@ void LLVertexBuffer::setupVertexBuffer(U32 data_mask) const  		if (loc >= 0)  		{ -			glVertexAttribPointerARB(loc,2,GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD1], (void*)(base + mOffsets[TYPE_TEXCOORD1])); +			void* ptr = (void*)(base + mOffsets[TYPE_TEXCOORD1]); +			if (mLastPointer[loc] != ptr) +			{ +				glVertexAttribPointerARB(loc,2,GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD1], ptr); +			} +			if (mGLArray) +			{ +				mLastPointer[loc] = ptr; +			}  		}  		else if (!shader)  		{ @@ -2075,7 +2142,15 @@ void LLVertexBuffer::setupVertexBuffer(U32 data_mask) const  		if (loc >= 0)  		{ -			glVertexAttribPointerARB(loc, 3,GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_BINORMAL], (void*)(base + mOffsets[TYPE_BINORMAL])); +			void* ptr = (void*)(base + mOffsets[TYPE_BINORMAL]); +			if (mLastPointer[loc] != ptr) +			{ +				glVertexAttribPointerARB(loc, 3,GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_BINORMAL], ptr); +			} +			if (mGLArray) +			{ +				mLastPointer[loc] = ptr; +			}  		}  		else if (!shader)  		{ @@ -2094,7 +2169,15 @@ void LLVertexBuffer::setupVertexBuffer(U32 data_mask) const  		if (loc >= 0)  		{ -			glVertexAttribPointerARB(loc,2,GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD0], (void*)(base + mOffsets[TYPE_TEXCOORD0])); +			void* ptr = (void*)(base + mOffsets[TYPE_TEXCOORD0]); +			if (mLastPointer[loc] != ptr) +			{ +				glVertexAttribPointerARB(loc,2,GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_TEXCOORD0], ptr); +			} +			if (mGLArray) +			{ +				mLastPointer[loc] = ptr; +			}  		}  		else if (!shader)  		{ @@ -2111,7 +2194,15 @@ void LLVertexBuffer::setupVertexBuffer(U32 data_mask) const  		if (loc >= 0)  		{ -			glVertexAttribPointerARB(loc, 4, GL_UNSIGNED_BYTE, GL_TRUE, LLVertexBuffer::sTypeSize[TYPE_COLOR], (void*)(base + mOffsets[TYPE_COLOR])); +			void* ptr = (void*)(base + mOffsets[TYPE_COLOR]); +			if (mLastPointer[loc] != ptr) +			{ +				glVertexAttribPointerARB(loc, 4, GL_UNSIGNED_BYTE, GL_TRUE, LLVertexBuffer::sTypeSize[TYPE_COLOR], ptr); +			} +			if (mGLArray) +			{ +				mLastPointer[loc] = ptr; +			}  		}  		else if (!shader)  		{ @@ -2128,7 +2219,15 @@ void LLVertexBuffer::setupVertexBuffer(U32 data_mask) const  		if (loc >= 0)  		{ -			glVertexAttribPointerARB(loc, 1, GL_UNSIGNED_BYTE, GL_TRUE, LLVertexBuffer::sTypeSize[TYPE_EMISSIVE], (void*)(base + mOffsets[TYPE_EMISSIVE])); +			void* ptr = (void*)(base + mOffsets[TYPE_EMISSIVE]); +			if (mLastPointer[loc] != ptr) +			{ +				glVertexAttribPointerARB(loc, 1, GL_UNSIGNED_BYTE, GL_TRUE, LLVertexBuffer::sTypeSize[TYPE_EMISSIVE], ptr); +			} +			if (mGLArray) +			{ +				mLastPointer[loc] = ptr; +			}  		}  	}  	if (data_mask & MAP_WEIGHT) @@ -2139,13 +2238,18 @@ void LLVertexBuffer::setupVertexBuffer(U32 data_mask) const  			loc = shader->getAttribLocation(TYPE_WEIGHT);  		} -		if (loc < 0) -		{ //legacy behavior, some shaders have weight hardcoded to location 1 -			loc = 1; +		if (loc > -1) +		{ +			void* ptr = (void*)(base + mOffsets[TYPE_WEIGHT]); +			if (mLastPointer[loc] != ptr) +			{ +				glVertexAttribPointerARB(loc, 1, GL_FLOAT, FALSE, LLVertexBuffer::sTypeSize[TYPE_WEIGHT], ptr); +			} +			if (mGLArray) +			{ +				mLastPointer[loc] = ptr; +			}  		} -		 -		glVertexAttribPointerARB(loc, 1, GL_FLOAT, FALSE, LLVertexBuffer::sTypeSize[TYPE_WEIGHT], (void*)(base + mOffsets[TYPE_WEIGHT])); -		  	}  	if (data_mask & MAP_WEIGHT4) @@ -2155,7 +2259,15 @@ void LLVertexBuffer::setupVertexBuffer(U32 data_mask) const  			S32 loc = shader->getAttribLocation(TYPE_WEIGHT4);  			if (loc > -1)  			{ -				glVertexAttribPointerARB(loc, 4, GL_FLOAT, FALSE, LLVertexBuffer::sTypeSize[TYPE_WEIGHT4], (void*)(base+mOffsets[TYPE_WEIGHT4])); +				void* ptr = (void*)(base+mOffsets[TYPE_WEIGHT4]); +				if (mLastPointer[loc] != ptr) +				{ +					glVertexAttribPointerARB(loc, 4, GL_FLOAT, FALSE, LLVertexBuffer::sTypeSize[TYPE_WEIGHT4], ptr); +				} +				if (mGLArray) +				{ +					mLastPointer[loc] = ptr; +				}  			}  		}  	} @@ -2168,11 +2280,18 @@ void LLVertexBuffer::setupVertexBuffer(U32 data_mask) const  			loc = shader->getAttribLocation(TYPE_CLOTHWEIGHT);  		} -		if (loc < 0) -		{ //legacy behavior, some shaders have weight hardcoded to location 4 -			loc = 4; +		if (loc > -1) +		{ +			void* ptr = (void*)(base + mOffsets[TYPE_CLOTHWEIGHT]); +			if (mLastPointer[loc] != ptr) +			{ +				glVertexAttribPointerARB(loc, 4, GL_FLOAT, TRUE,  LLVertexBuffer::sTypeSize[TYPE_CLOTHWEIGHT], ptr); +			} +			if (mGLArray) +			{ +				mLastPointer[loc] = ptr; +			}  		} -		glVertexAttribPointerARB(loc, 4, GL_FLOAT, TRUE,  LLVertexBuffer::sTypeSize[TYPE_CLOTHWEIGHT], (void*)(base + mOffsets[TYPE_CLOTHWEIGHT]));  	}  	if (data_mask & MAP_VERTEX)  	{ diff --git a/indra/llrender/llvertexbuffer.h b/indra/llrender/llvertexbuffer.h index 7aa5928524..60cfde39f5 100644 --- a/indra/llrender/llvertexbuffer.h +++ b/indra/llrender/llvertexbuffer.h @@ -38,6 +38,8 @@  #include <vector>  #include <list> +#define LL_MAX_VERTEX_ATTRIB_LOCATION 64 +  //============================================================================  // NOTES  // Threading: @@ -49,7 +51,6 @@  //============================================================================  // gl name pools for dynamic and streaming buffers -  class LLVBOPool : public LLGLNamePool  {  protected: @@ -116,7 +117,7 @@ public:  	static void initClass(bool use_vbo, bool no_vbo_mapping);  	static void cleanupClass(); -	static void setupClientArrays(U32 data_mask); +	static void setupClientArrays(U32 data_mask, U32& ref_mask = LLVertexBuffer::sLastMask);  	static void drawArrays(U32 mode, const std::vector<LLVector3>& pos, const std::vector<LLVector3>& norm);  	static void drawElements(U32 mode, const LLVector4a* pos, const LLVector2* tc, S32 num_indices, const U16* indicesp); @@ -271,6 +272,10 @@ protected:  	S32		mUsage;			// GL usage  	U32		mGLBuffer;		// GL VBO handle  	U32		mGLIndices;		// GL IBO handle +	U32		mGLArray;		// GL VAO handle +	U32		mLastMask;		 +	mutable void*   mLastPointer[LL_MAX_VERTEX_ATTRIB_LOCATION]; +  	U8*		mMappedData;	// pointer to currently mapped data (NULL if unmapped)  	U8*		mMappedIndexData;	// pointer to currently mapped indices (NULL if unmapped)  	BOOL	mVertexLocked;			// if TRUE, vertex buffer is being or has been written to in client memory @@ -307,6 +312,7 @@ public:  	static S32 sTypeSize[TYPE_MAX];  	static U32 sGLMode[LLRender::NUM_MODES];  	static U32 sGLRenderBuffer; +	static U32 sGLRenderArray;  	static U32 sGLRenderIndices;  	static BOOL sVBOActive;  	static BOOL sIBOActive; | 
