diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp
index ae753fc0f37341646b4a5ae338b7803f9f5f52b4..559d790d774e5b09e5cf63dc1b02f823a5d87f76 100644
--- a/indra/llmath/llvolume.cpp
+++ b/indra/llmath/llvolume.cpp
@@ -2783,7 +2783,7 @@ bool LLVolume::unpackVolumeFaces(std::istream& is, S32 size)
 		}
 	}
 
-	if (!cacheOptimize())
+	if (!cacheOptimize(true))
 	{
 		// Out of memory?
 		LL_WARNS() << "Failed to optimize!" << LL_ENDL;
@@ -2824,11 +2824,11 @@ void LLVolume::copyVolumeFaces(const LLVolume* volume)
 	mSculptLevel = 0;
 }
 
-bool LLVolume::cacheOptimize()
+bool LLVolume::cacheOptimize(bool gen_tangents)
 {
 	for (S32 i = 0; i < mVolumeFaces.size(); ++i)
 	{
-		if (!mVolumeFaces[i].cacheOptimize())
+		if (!mVolumeFaces[i].cacheOptimize(gen_tangents))
 		{
 			return false;
 		}
@@ -5478,18 +5478,13 @@ struct MikktData
 };
 
 
-bool LLVolumeFace::cacheOptimize()
+bool LLVolumeFace::cacheOptimize(bool gen_tangents)
 { //optimize for vertex cache according to Forsyth method: 
     LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME;
 	llassert(!mOptimized);
 	mOptimized = TRUE;
 
-    if (!mNormals || !mTexCoords)
-    { // can't perform this operation without normals and texture coordinates
-        return false;
-    }
-
-    if (mMikktSpaceTangents == nullptr)
+    if (mMikktSpaceTangents == nullptr && gen_tangents && mNormals && mTexCoords)
     { // make sure to generate mikkt space tangents for cache optimizing since the index buffer may change
         allocateTangents(mNumVertices, true);
 
diff --git a/indra/llmath/llvolume.h b/indra/llmath/llvolume.h
index e373d0175d33910ea9b675efec63101d01e5f5f4..6ea12c6920fc3b8350f0cd4e0fb97f1b8048c7d5 100644
--- a/indra/llmath/llvolume.h
+++ b/indra/llmath/llvolume.h
@@ -907,7 +907,7 @@ class LLVolumeFace
     void remap();
 
 	void optimize(F32 angle_cutoff = 2.f);
-	bool cacheOptimize();
+	bool cacheOptimize(bool gen_tangents = false);
 
 	void createOctree(F32 scaler = 0.25f, const LLVector4a& center = LLVector4a(0,0,0), const LLVector4a& size = LLVector4a(0.5f,0.5f,0.5f));
 
@@ -957,10 +957,6 @@ class LLVolumeFace
     // indexes for mPositions/mNormals/mTexCoords
 	U16* mIndices;
 
-	// vertex buffer filled in by LLFace to cache this volume face geometry in vram 
-	// (declared as a LLPointer to LLRefCount to avoid dependency on LLVertexBuffer)
-	mutable LLPointer<LLRefCount> mVertexBuffer; 
-
 	std::vector<S32>	mEdge;
 
 	//list of skin weights for rigged volumes
@@ -1089,7 +1085,10 @@ class LLVolume : public LLRefCount
 	void copyVolumeFaces(const LLVolume* volume);
 	void copyFacesTo(std::vector<LLVolumeFace> &faces) const;
 	void copyFacesFrom(const std::vector<LLVolumeFace> &faces);
-	bool cacheOptimize();
+
+    // use meshoptimizer to optimize index buffer for vertex shader cache
+    //  gen_tangents - if true, generate MikkTSpace tangents if needed before optimizing index buffer
+	bool cacheOptimize(bool gen_tangents = false);
 
 private:
 	void sculptGenerateMapVertices(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data, U8 sculpt_type);
diff --git a/indra/llprimitive/lldaeloader.cpp b/indra/llprimitive/lldaeloader.cpp
index 9470146ce4a7510c5caadcac4bd577fbe33be102..dbb34ab60bae94686d74f38b691c167014ec98d8 100644
--- a/indra/llprimitive/lldaeloader.cpp
+++ b/indra/llprimitive/lldaeloader.cpp
@@ -2551,9 +2551,6 @@ bool LLDAELoader::loadModelsFromDomMesh(domMesh* mesh, std::vector<LLModel*>& mo
 	LLVolume::face_list_t remainder;
 	do 
 	{
-        // generate tangents and cache optimize before normalizing
-        ret->preprocessVolumeFaces();
-
 		// Insure we do this once with the whole gang and not per-model
 		//
 		if (!normalized && !mNoNormalize)
@@ -2565,10 +2562,10 @@ bool LLDAELoader::loadModelsFromDomMesh(domMesh* mesh, std::vector<LLModel*>& mo
 		ret->trimVolumeFacesToSize(LL_SCULPT_MESH_MAX_FACES, &remainder);
 
         // remove unused/redundant vertices after normalizing
-		//if (!mNoOptimize)
-		//{
-		//	ret->remapVolumeFaces();
-		//}
+		if (!mNoOptimize)
+		{
+			ret->remapVolumeFaces();
+		}
 
 		volume_faces = remainder.size();
 
diff --git a/indra/llprimitive/llmodel.cpp b/indra/llprimitive/llmodel.cpp
index ab507edc4029deb62f951eb9da5bdbc3b699a633..eff47d9d9817841bbcfc82404d2a28072c010550 100644
--- a/indra/llprimitive/llmodel.cpp
+++ b/indra/llprimitive/llmodel.cpp
@@ -187,15 +187,6 @@ void LLModel::trimVolumeFacesToSize(U32 new_count, LLVolume::face_list_t* remain
 	}
 }
 
-// generate mikkt space tangents and cache optimize
-void LLModel::preprocessVolumeFaces()
-{
-    for (auto& face : mVolumeFaces)
-    {
-        face.cacheOptimize();
-    }
-}
-
 // Shrink the model to fit
 // on a 1x1x1 cube centered at the origin.
 // The positions and extents
diff --git a/indra/llprimitive/llmodel.h b/indra/llprimitive/llmodel.h
index ea97851ce85eca878a9138bb270e8efaac207ec4..354ceb26b7e831361eb7467cbd80795ac683588f 100644
--- a/indra/llprimitive/llmodel.h
+++ b/indra/llprimitive/llmodel.h
@@ -182,7 +182,6 @@ class LLModel : public LLVolume
 	void addFace(const LLVolumeFace& face);
 
 	void sortVolumeFacesByMaterialName();
-    void preprocessVolumeFaces();
 	void normalizeVolumeFaces();
 	void trimVolumeFacesToSize(U32 new_count = LL_SCULPT_MESH_MAX_FACES, LLVolume::face_list_t* remainder = NULL);
     void remapVolumeFaces();
diff --git a/indra/llrender/llcubemap.cpp b/indra/llrender/llcubemap.cpp
index e41765622f5c757c7af2f5516920e79c3918c55a..254288a86ec77c8928777223a1e01fea62cb5dce 100644
--- a/indra/llrender/llcubemap.cpp
+++ b/indra/llrender/llcubemap.cpp
@@ -67,7 +67,7 @@ void LLCubeMap::initGL()
 {
 	llassert(gGLManager.mInited);
 
-	if (gGLManager.mHasCubeMap && LLCubeMap::sUseCubeMaps)
+	if (LLCubeMap::sUseCubeMaps)
 	{
 		// Not initialized, do stuff.
 		if (mImages[0].isNull())
@@ -252,7 +252,7 @@ void LLCubeMap::enable(S32 stage)
 void LLCubeMap::enableTexture(S32 stage)
 {
 	mTextureStage = stage;
-	if (gGLManager.mHasCubeMap && stage >= 0 && LLCubeMap::sUseCubeMaps)
+	if (stage >= 0 && LLCubeMap::sUseCubeMaps)
 	{
 		gGL.getTexUnit(stage)->enable(LLTexUnit::TT_CUBE_MAP);
 	}
@@ -265,7 +265,7 @@ void LLCubeMap::disable(void)
 
 void LLCubeMap::disableTexture(void)
 {
-	if (gGLManager.mHasCubeMap && mTextureStage >= 0 && LLCubeMap::sUseCubeMaps)
+	if (mTextureStage >= 0 && LLCubeMap::sUseCubeMaps)
 	{
 		gGL.getTexUnit(mTextureStage)->disable();
 		if (mTextureStage == 0)
diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp
index 5253ed3d51f1b1ec56727f34e091c9dafa9baf2c..71303b0517ffff84a344d021a5d9e6b1ca59b61b 100644
--- a/indra/llrender/llgl.cpp
+++ b/indra/llrender/llgl.cpp
@@ -86,15 +86,15 @@ void APIENTRY gl_debug_callback(GLenum source,
                                 const GLchar* message,
                                 GLvoid* userParam)
 {
-    /*if (severity != GL_DEBUG_SEVERITY_HIGH_ARB // &&
-        severity != GL_DEBUG_SEVERITY_MEDIUM_ARB &&
-        severity != GL_DEBUG_SEVERITY_LOW_ARB
+    /*if (severity != GL_DEBUG_SEVERITY_HIGH // &&
+        severity != GL_DEBUG_SEVERITY_MEDIUM &&
+        severity != GL_DEBUG_SEVERITY_LOW
         )
     { //suppress out-of-spec messages sent by nvidia driver (mostly vertexbuffer hints)
         return;
     }*/
 
-    if (severity == GL_DEBUG_SEVERITY_HIGH_ARB)
+    if (severity == GL_DEBUG_SEVERITY_HIGH)
     {
         LL_WARNS() << "----- GL ERROR --------" << LL_ENDL;
     }
@@ -107,7 +107,15 @@ void APIENTRY gl_debug_callback(GLenum source,
     LL_WARNS() << "Severity: " << std::hex << severity << LL_ENDL;
     LL_WARNS() << "Message: " << message << LL_ENDL;
     LL_WARNS() << "-----------------------" << LL_ENDL;
-    if (severity == GL_DEBUG_SEVERITY_HIGH_ARB)
+
+    GLint vao = 0;
+    glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &vao);
+    GLint vbo = 0;
+    glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &vbo);
+    GLint ibo = 0;
+    glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &ibo);
+
+    if (severity == GL_DEBUG_SEVERITY_HIGH)
     {
         LL_ERRS() << "Halting on GL Error" << LL_ENDL;
     }
@@ -931,44 +939,12 @@ LLGLManager gGLManager;
 LLGLManager::LLGLManager() :
 	mInited(FALSE),
 	mIsDisabled(FALSE),
-
-	mHasMultitexture(FALSE),
-	mHasATIMemInfo(FALSE),
-	mHasAMDAssociations(FALSE),
-	mHasNVXMemInfo(FALSE),
-	mNumTextureUnits(1),
-	mHasMipMapGeneration(FALSE),
-	mHasCompressedTextures(FALSE),
-	mHasFramebufferObject(FALSE),
 	mMaxSamples(0),
-	mHasBlendFuncSeparate(FALSE),
-	mHasSync(FALSE),
-	mHasVertexBufferObject(FALSE),
-	mHasVertexArrayObject(FALSE),
-	mHasMapBufferRange(FALSE),
-	mHasFlushBufferRange(FALSE),
-	mHasPBuffer(FALSE),
-	mNumTextureImageUnits(0),
-	mHasOcclusionQuery(FALSE),
-	mHasTimerQuery(FALSE),
-	mHasOcclusionQuery2(FALSE),
-	mHasPointParameters(FALSE),
-	mHasDrawBuffers(FALSE),
-	mHasTextureRectangle(FALSE),
-	mHasTextureMultisample(FALSE),
-	mHasTransformFeedback(FALSE),
-    mHasUniformBufferObject(FALSE),
+	mNumTextureImageUnits(1),
 	mMaxSampleMaskWords(0),
 	mMaxColorTextureSamples(0),
 	mMaxDepthTextureSamples(0),
 	mMaxIntegerSamples(0),
-
-	mHasAnisotropic(FALSE),
-	mHasARBEnvCombine(FALSE),
-	mHasCubeMap(FALSE),
-	mHasCubeMapArray(FALSE),
-	mHasDebugOutput(FALSE),
-
 	mIsAMD(FALSE),
 	mIsNVIDIA(FALSE),
 	mIsIntel(FALSE),
@@ -976,9 +952,6 @@ LLGLManager::LLGLManager() :
 	mIsMobileGF(FALSE),
 #endif
 	mHasRequirements(TRUE),
-
-	mHasSeparateSpecularColor(FALSE),
-
 	mDriverVersionMajor(1),
 	mDriverVersionMinor(0),
 	mDriverVersionRelease(0),
@@ -996,7 +969,6 @@ LLGLManager::LLGLManager() :
 //---------------------------------------------------------------------
 void LLGLManager::initWGL()
 {
-	mHasPBuffer = FALSE;
 #if LL_WINDOWS && !LL_MESA_HEADLESS
 	if (!glh_init_extensions("WGL_ARB_pixel_format"))
 	{
@@ -1035,10 +1007,6 @@ void LLGLManager::initWGL()
 	{
 		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
 }
 
@@ -1052,7 +1020,7 @@ bool LLGLManager::initGL()
 
 	stop_glerror();
 
-#if LL_WINDOWS
+#if 0 && LL_WINDOWS
 	if (!glGetStringi)
 	{
 		glGetStringi = (PFNGLGETSTRINGIPROC) GLH_EXT_GET_PROC_ADDRESS("glGetStringi");
@@ -1199,23 +1167,6 @@ bool LLGLManager::initGL()
 	}
 #endif
 
-	if (mHasATIMemInfo && mVRAM == 0)
-	{ //ask the gl how much vram is free at startup and attempt to use no more than half of that
-		S32 meminfo[4];
-		glGetIntegerv(GL_TEXTURE_FREE_MEMORY_ATI, meminfo);
-
-		mVRAM = meminfo[0] / 1024;
-		LL_WARNS("RenderInit") << "VRAM Detected (ATIMemInfo):" << mVRAM << LL_ENDL;
-	}
-
-	if (mHasNVXMemInfo && mVRAM == 0)
-	{
-		S32 dedicated_memory;
-		glGetIntegerv(GL_GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX, &dedicated_memory);
-		mVRAM = dedicated_memory/1024;
-		LL_WARNS("RenderInit") << "VRAM Detected (NVXMemInfo):" << mVRAM << LL_ENDL;
-	}
-
 #if LL_WINDOWS
 	if (mVRAM < 256)
 	{
@@ -1243,62 +1194,22 @@ bool LLGLManager::initGL()
 
 	stop_glerror();
 
-	GLint num_tex_image_units;
-	glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &num_tex_image_units);
-	mNumTextureImageUnits = llmin(num_tex_image_units, 32);
-
-    if (mHasMultitexture)
+	glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &mNumTextureImageUnits);
+    stop_glerror();
+	glGetIntegerv(GL_MAX_COLOR_TEXTURE_SAMPLES, &mMaxColorTextureSamples);
+    stop_glerror();
+	glGetIntegerv(GL_MAX_DEPTH_TEXTURE_SAMPLES, &mMaxDepthTextureSamples);
+    stop_glerror();
+	glGetIntegerv(GL_MAX_INTEGER_SAMPLES, &mMaxIntegerSamples);
+    stop_glerror();
+	glGetIntegerv(GL_MAX_SAMPLE_MASK_WORDS, &mMaxSampleMaskWords);
+    stop_glerror();
+    glGetIntegerv(GL_MAX_SAMPLES, &mMaxSamples);
+    stop_glerror();
+    if (mGLVersion >= 4.59f)
     {
-        if (LLRender::sGLCoreProfile)
-        {
-            mNumTextureUnits = llmin(mNumTextureImageUnits, MAX_GL_TEXTURE_UNITS);
-        }
-        else
-        {
-            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);
-            }
-        }
+        glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY, &mMaxAnisotropy);
     }
-	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;
-	}
-	
-	stop_glerror();
-
-	if (mHasTextureMultisample)
-	{
-		glGetIntegerv(GL_MAX_COLOR_TEXTURE_SAMPLES, &mMaxColorTextureSamples);
-		glGetIntegerv(GL_MAX_DEPTH_TEXTURE_SAMPLES, &mMaxDepthTextureSamples);
-		glGetIntegerv(GL_MAX_INTEGER_SAMPLES, &mMaxIntegerSamples);
-		glGetIntegerv(GL_MAX_SAMPLE_MASK_WORDS, &mMaxSampleMaskWords);
-	}
-
-	stop_glerror();
-
-	//HACK always disable texture multisample, use FXAA instead
-	mHasTextureMultisample = FALSE;
-#if LL_WINDOWS
-	if (mIsIntel && mGLVersion <= 3.f)
-	{ //never try to use framebuffer objects on older intel drivers (crashy)
-		mHasFramebufferObject = FALSE;
-	}
-#endif
-
-	if (mHasFramebufferObject)
-	{
-		glGetIntegerv(GL_MAX_SAMPLES, &mMaxSamples);
-	}
-
 	stop_glerror();
 	
 	initGLStates();
@@ -1406,62 +1317,22 @@ void LLGLManager::asLLSD(LLSD& info)
 
 	info["vram"] = mVRAM;
 
-	// Extensions used by everyone
-	info["has_multitexture"] = mHasMultitexture;
-	info["has_ati_mem_info"] = mHasATIMemInfo;
-	info["has_nvx_mem_info"] = mHasNVXMemInfo;
-	info["num_texture_units"] = mNumTextureUnits;
-	info["has_mip_map_generation"] = mHasMipMapGeneration;
-	info["has_compressed_textures"] = mHasCompressedTextures;
-	info["has_framebuffer_object"] = mHasFramebufferObject;
+	// OpenGL limits
 	info["max_samples"] = mMaxSamples;
-	info["has_blend_func_separate"] = mHasBlendFuncSeparate || LLRender::sGLCoreProfile;
-
-	// ARB Extensions
-	info["has_vertex_buffer_object"] = mHasVertexBufferObject;
-	info["has_vertex_array_object"] = mHasVertexArrayObject;
-	info["has_sync"] = mHasSync;
-	info["has_map_buffer_range"] = mHasMapBufferRange;
-	info["has_flush_buffer_range"] = mHasFlushBufferRange;
-	info["has_pbuffer"] = mHasPBuffer;
-    info["has_shader_objects"] = std::string("Assumed TRUE");   // was mHasShaderObjects;
-	info["has_vertex_shader"] = std::string("Assumed TRUE");    // was mHasVertexShader;
-	info["has_fragment_shader"] = std::string("Assumed TRUE");  // was mHasFragmentShader;
 	info["num_texture_image_units"] =  mNumTextureImageUnits;
-	info["has_occlusion_query"] = mHasOcclusionQuery;
-	info["has_timer_query"] = mHasTimerQuery;
-	info["has_occlusion_query2"] = mHasOcclusionQuery2;
-	info["has_point_parameters"] = mHasPointParameters;
-	info["has_draw_buffers"] = mHasDrawBuffers;
-	info["has_depth_clamp"] = mHasDepthClamp;
-	info["has_texture_rectangle"] = mHasTextureRectangle;
-	info["has_texture_multisample"] = mHasTextureMultisample;
-	info["has_transform_feedback"] = mHasTransformFeedback;
 	info["max_sample_mask_words"] = mMaxSampleMaskWords;
 	info["max_color_texture_samples"] = mMaxColorTextureSamples;
 	info["max_depth_texture_samples"] = mMaxDepthTextureSamples;
 	info["max_integer_samples"] = mMaxIntegerSamples;
+    info["max_vertex_range"] = mGLMaxVertexRange;
+    info["max_index_range"] = mGLMaxIndexRange;
+    info["max_texture_size"] = mGLMaxTextureSize;
 
-	// Other extensions.
-	info["has_anisotropic"] = mHasAnisotropic;
-	info["has_arb_env_combine"] = mHasARBEnvCombine;
-	info["has_cube_map"] = mHasCubeMap;
-	info["has_debug_output"] = mHasDebugOutput;
-	info["has_srgb_texture"] = mHassRGBTexture;
-	info["has_srgb_framebuffer"] = mHassRGBFramebuffer;
-    info["has_texture_srgb_decode"] = mHasTexturesRGBDecode;
-
-	// Vendor-specific extensions
+	// Which vendor
 	info["is_ati"] = mIsAMD;  // note, do not rename is_ati to is_amd without coordinating with DW
 	info["is_nvidia"] = mIsNVIDIA;
 	info["is_intel"] = mIsIntel;
 
-	// Other fields
-	info["has_requirements"] = mHasRequirements;
-	info["has_separate_specular_color"] = mHasSeparateSpecularColor;
-	info["max_vertex_range"] = mGLMaxVertexRange;
-	info["max_index_range"] = mGLMaxIndexRange;
-	info["max_texture_size"] = mGLMaxTextureSize;
 	info["gl_renderer"] = mGLRenderer;
 }
 
@@ -1480,60 +1351,6 @@ void LLGLManager::shutdownGL()
 
 void LLGLManager::initExtensions()
 {
-#if LL_MESA_HEADLESS
-# ifdef GL_ARB_multitexture
-	mHasMultitexture = TRUE;
-# else
-	mHasMultitexture = FALSE;
-# endif // GL_ARB_multitexture
-# ifdef GL_ARB_texture_env_combine
-	mHasARBEnvCombine = TRUE;	
-# else
-	mHasARBEnvCombine = FALSE;
-# endif // GL_ARB_texture_env_combine
-# ifdef GL_ARB_texture_compression
-	mHasCompressedTextures = TRUE;
-# else
-	mHasCompressedTextures = FALSE;
-# endif // GL_ARB_texture_compression
-# ifdef GL_ARB_vertex_buffer_object
-	mHasVertexBufferObject = TRUE;
-# else
-	mHasVertexBufferObject = FALSE;
-# endif // GL_ARB_vertex_buffer_object
-# ifdef GL_EXT_framebuffer_object
-	mHasFramebufferObject = TRUE;
-# else
-	mHasFramebufferObject = FALSE;
-# endif // GL_EXT_framebuffer_object
-# ifdef GL_ARB_draw_buffers
-	mHasDrawBuffers = TRUE;
-#else
-	mHasDrawBuffers = FALSE;
-# endif // GL_ARB_draw_buffers
-# if defined(GL_NV_depth_clamp) || defined(GL_ARB_depth_clamp)
-	mHasDepthClamp = TRUE;
-#else
-	mHasDepthClamp = FALSE;
-#endif // defined(GL_NV_depth_clamp) || defined(GL_ARB_depth_clamp)
-# if GL_EXT_blend_func_separate
-	mHasBlendFuncSeparate = TRUE;
-#else
-	mHasBlendFuncSeparate = FALSE;
-# endif // GL_EXT_blend_func_separate
-	mHasMipMapGeneration = FALSE;
-	mHasSeparateSpecularColor = FALSE;
-	mHasAnisotropic = FALSE;
-	mHasCubeMap = FALSE;
-	mHasOcclusionQuery = FALSE;
-	mHasPointParameters = FALSE;
-	mHasTextureRectangle = FALSE;
-#else // LL_MESA_HEADLESS //important, gGLHExts.mSysExts is uninitialized until after glh_init_extensions is called
-
-    mHasMultitexture = TRUE;
-    mHasCubeMap = TRUE;
-    mHasCompressedTextures = TRUE;
-
 #if LL_DARWIN
     GLint num_extensions = 0;
     std::string all_extensions{""};
@@ -1550,173 +1367,12 @@ void LLGLManager::initExtensions()
     }
 #endif
 
-    mHasSeparateSpecularColor = ExtensionExists("GL_EXT_separate_specular_color", gGLHExts.mSysExts);
-    mHasAnisotropic = ExtensionExists("GL_EXT_texture_filter_anisotropic", gGLHExts.mSysExts);
-
-    // In core profile
-    mHasARBEnvCombine = TRUE; //ExtensionExists("GL_ARB_texture_env_combine", gGLHExts.mSysExts);
-    mHasTimerQuery = FALSE; //FIXME //ExtensionExists("GL_ARB_timer_query", gGLHExts.mSysExts);
-    mHasOcclusionQuery = TRUE; //ExtensionExists("GL_ARB_occlusion_query", gGLHExts.mSysExts);
-    mHasOcclusionQuery2 = TRUE; // ExtensionExists("GL_ARB_occlusion_query2", gGLHExts.mSysExts);
-    mHasVertexBufferObject = TRUE; //ExtensionExists("GL_ARB_vertex_buffer_object", gGLHExts.mSysExts);
-    mHasVertexArrayObject = TRUE; //ExtensionExists("GL_ARB_vertex_array_object", gGLHExts.mSysExts);
-    mHasMapBufferRange = TRUE; ExtensionExists("GL_ARB_map_buffer_range", gGLHExts.mSysExts);
-    mHasFlushBufferRange = ExtensionExists("GL_APPLE_flush_buffer_range", gGLHExts.mSysExts); // Apple has mHasMapBufferRange now
-    mHasSync = TRUE; //ExtensionExists("GL_ARB_sync", gGLHExts.mSysExts);
-    mHasFramebufferObject = TRUE; //ExtensionExists("GL_ARB_framebuffer_object", gGLHExts.mSysExts);
-    mHassRGBFramebuffer = TRUE; //ExtensionExists("GL_ARB_framebuffer_sRGB", gGLHExts.mSysExts);
-    mHasDrawBuffers = TRUE; //ExtensionExists("GL_ARB_draw_buffers", gGLHExts.mSysExts);
-    mHasTextureRectangle = TRUE; //ExtensionExists("GL_ARB_texture_rectangle", gGLHExts.mSysExts);
-    mHasTextureMultisample = TRUE; //ExtensionExists("GL_ARB_texture_multisample", gGLHExts.mSysExts);
-    mHasUniformBufferObject = TRUE; //ExtensionExists("GL_ARB_uniform_buffer_object", gGLHExts.mSysExts);
-    mHasCubeMapArray = TRUE; //ExtensionExists("GL_ARB_texture_cube_map_array", gGLHExts.mSysExts);
-    mHasPointParameters = TRUE; //ExtensionExists("GL_ARB_point_parameters", gGLHExts.mSysExts);
-
-    mHasATIMemInfo = ExtensionExists("GL_ATI_meminfo", gGLHExts.mSysExts); //Basic AMD method, also see mHasAMDAssociations
-    mHasNVXMemInfo = ExtensionExists("GL_NVX_gpu_memory_info", gGLHExts.mSysExts);
-    // NOTE: Using extensions breaks reflections when Shadows are set to projector.  See: SL-16727
-    //mHasDepthClamp = ExtensionExists("GL_ARB_depth_clamp", gGLHExts.mSysExts) || ExtensionExists("GL_NV_depth_clamp", gGLHExts.mSysExts);
-    mHasDepthClamp = FALSE;
-    // mask out FBO support when packed_depth_stencil isn't there 'cause we need it for LLRenderTarget -Brad
-
-#ifdef GL_EXT_texture_sRGB
-    mHassRGBTexture = ExtensionExists("GL_EXT_texture_sRGB", gGLHExts.mSysExts);
-#endif
-    
-    
-#ifdef GL_EXT_texture_sRGB_decode
-    mHasTexturesRGBDecode = ExtensionExists("GL_EXT_texture_sRGB_decode", gGLHExts.mSysExts);
-#else
-    mHasTexturesRGBDecode = ExtensionExists("GL_ARB_texture_sRGB_decode", gGLHExts.mSysExts);
-#endif
-
-    mHasMipMapGeneration = mHasFramebufferObject || mGLVersion >= 1.4f;
+    // OpenGL 4.x capabilities
+    mHasCubeMapArray = mGLVersion >= 3.99f; 
+    mHasTransformFeedback = mGLVersion >= 3.99f;
+    mHasDebugOutput = mGLVersion >= 4.29f;
 
-    mHasBlendFuncSeparate = ExtensionExists("GL_EXT_blend_func_separate", gGLHExts.mSysExts);
-    mHasDebugOutput = mGLVersion >= 4.3f ? TRUE : FALSE;
-    mHasTransformFeedback = mGLVersion >= 4.f ? TRUE : FALSE;
-#endif
-
-#if LL_LINUX
-	LL_INFOS() << "initExtensions() checking shell variables to adjust features..." << LL_ENDL;
-	// 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"))
-	{
-		//mHasMultitexture = FALSE; // NEEDED!
-		mHasDepthClamp = FALSE;
-		mHasARBEnvCombine = FALSE;
-		mHasCompressedTextures = FALSE;
-		mHasVertexBufferObject = FALSE;
-		mHasFramebufferObject = FALSE;
-		mHasDrawBuffers = FALSE;
-		mHasBlendFuncSeparate = FALSE;
-		mHasMipMapGeneration = FALSE;
-		mHasSeparateSpecularColor = FALSE;
-		mHasAnisotropic = FALSE;
-		mHasCubeMap = FALSE;
-		mHasOcclusionQuery = FALSE;
-		mHasPointParameters = 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;
-		mHasAnisotropic = FALSE;
-		//mHasCubeMap = FALSE; // apparently fatal on Intel 915 & similar
-		//mHasOcclusionQuery = FALSE; // source of many ATI system hangs
-		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 */
-	{
-		// 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,'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,'p')) mHasPointParameters = FALSE;//S
-		if (strchr(blacklist,'q')) mHasFramebufferObject = FALSE;//S
-		if (strchr(blacklist,'r')) mHasDrawBuffers = FALSE;//S
-		if (strchr(blacklist,'s')) mHasTextureRectangle = FALSE;
-		if (strchr(blacklist,'t')) mHasBlendFuncSeparate = FALSE;//S
-		if (strchr(blacklist,'u')) mHasDepthClamp = FALSE;
-		
-	}
-#endif // LL_LINUX
-	
-	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 (!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 (!mHasOcclusionQuery2)
-	{
-		LL_INFOS("RenderInit") << "Couldn't initialize GL_ARB_occlusion_query2" << LL_ENDL;
-	}
-	if (!mHasPointParameters)
-	{
-		LL_INFOS("RenderInit") << "Couldn't initialize GL_ARB_point_parameters" << LL_ENDL;
-	}
-	if (!mHasBlendFuncSeparate && !LLRender::sGLCoreProfile)
-	{
-		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;
-	}
-	if (!mHasCubeMapArray)
-	{
-		LL_INFOS("RenderInit") << "Couldn't initialize GL_ARB_texture_cube_map_array" << 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;
-	}
-
-	// Misc
+    // Misc
 	glGetIntegerv(GL_MAX_ELEMENTS_VERTICES, (GLint*) &mGLMaxVertexRange);
 	glGetIntegerv(GL_MAX_ELEMENTS_INDICES, (GLint*) &mGLMaxIndexRange);
 	glGetIntegerv(GL_MAX_TEXTURE_SIZE, (GLint*) &mGLMaxTextureSize);
@@ -2795,7 +2451,7 @@ void LLGLState::checkTextureChannels(const std::string& msg)
 	glh::matrix4f identity;
 	identity.identity();
 
-	for (GLint i = 1; i < gGLManager.mNumTextureUnits; i++)
+	for (GLint i = 1; i < gGLManager.mNumTextureImageUnits; i++)
 	{
 		gGL.getTexUnit(i)->activate();
 
@@ -2833,12 +2489,6 @@ void LLGLState::checkTextureChannels(const std::string& msg)
 			for (S32 j = (i == 0 ? 1 : 0); 
 				j < 9; j++)
 			{
-				if (j == 8 && !gGLManager.mHasTextureRectangle ||
-					j == 9 && !gGLManager.mHasTextureMultisample)
-				{
-					continue;
-				}
-				
 				if (glIsEnabled(value[j]))
 				{
 					error = TRUE;
@@ -3329,36 +2979,29 @@ LLGLSquashToFarClip::~LLGLSquashToFarClip()
 	
 LLGLSyncFence::LLGLSyncFence()
 {
-#ifdef GL_ARB_sync
 	mSync = 0;
-#endif
 }
 
 LLGLSyncFence::~LLGLSyncFence()
 {
-#ifdef GL_ARB_sync
 	if (mSync)
 	{
 		glDeleteSync(mSync);
 	}
-#endif
 }
 
 void LLGLSyncFence::placeFence()
 {
-#ifdef GL_ARB_sync
 	if (mSync)
 	{
 		glDeleteSync(mSync);
 	}
 	mSync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
-#endif
 }
 
 bool LLGLSyncFence::isCompleted()
 {
 	bool ret = true;
-#ifdef GL_ARB_sync
 	if (mSync)
 	{
 		GLenum status = glClientWaitSync(mSync, 0, 1);
@@ -3367,13 +3010,11 @@ bool LLGLSyncFence::isCompleted()
 			ret = false;
 		}
 	}
-#endif
 	return ret;
 }
 
 void LLGLSyncFence::wait()
 {
-#ifdef GL_ARB_sync
 	if (mSync)
 	{
 		while (glClientWaitSync(mSync, 0, FENCE_WAIT_TIME_NANOSECONDS) == GL_TIMEOUT_EXPIRED)
@@ -3382,7 +3023,6 @@ void LLGLSyncFence::wait()
 			waits++;
 		}
 	}
-#endif
 }
 
 LLGLSPipelineSkyBox::LLGLSPipelineSkyBox()
diff --git a/indra/llrender/llgl.h b/indra/llrender/llgl.h
index 3c40f85654237d82b8fbad3e05a699127ee8dc65..e3c07604aa75a46c32778bc85b5f6f86ebb6b65a 100644
--- a/indra/llrender/llgl.h
+++ b/indra/llrender/llgl.h
@@ -76,52 +76,27 @@ class LLGLManager
 	BOOL mInited;
 	BOOL mIsDisabled;
 
-	// Extensions used by everyone
-	BOOL mHasMultitexture;
-	BOOL mHasATIMemInfo;
-	BOOL mHasAMDAssociations;
-	BOOL mHasNVXMemInfo;
-	S32	 mNumTextureUnits;
-	BOOL mHasMipMapGeneration;
-	BOOL mHasCompressedTextures;
-	BOOL mHasFramebufferObject;
+	// OpenGL limits
 	S32 mMaxSamples;
-	BOOL mHasBlendFuncSeparate;
-		
-	// ARB Extensions
-	BOOL mHasVertexBufferObject;
-	BOOL mHasVertexArrayObject;
-	BOOL mHasSync;
-	BOOL mHasMapBufferRange;
-	BOOL mHasFlushBufferRange;
-	BOOL mHasPBuffer;
-	S32  mNumTextureImageUnits;
-	BOOL mHasOcclusionQuery;
-	BOOL mHasTimerQuery;
-	BOOL mHasOcclusionQuery2;
-	BOOL mHasPointParameters;
-	BOOL mHasDrawBuffers;
-	BOOL mHasDepthClamp;
-	BOOL mHasTextureRectangle;
-	BOOL mHasTextureMultisample;
-	BOOL mHasTransformFeedback;
-    BOOL mHasUniformBufferObject;
+	S32 mNumTextureImageUnits;
 	S32 mMaxSampleMaskWords;
 	S32 mMaxColorTextureSamples;
 	S32 mMaxDepthTextureSamples;
 	S32 mMaxIntegerSamples;
-
-	// Other extensions.
-	BOOL mHasAnisotropic;
-	BOOL mHasARBEnvCombine;
-	BOOL mHasCubeMap;
-	BOOL mHasCubeMapArray;
-	BOOL mHasDebugOutput;
-	BOOL mHassRGBTexture;
-	BOOL mHassRGBFramebuffer;
-    BOOL mHasTexturesRGBDecode;
-
+    S32 mGLMaxVertexRange;
+    S32 mGLMaxIndexRange;
+    S32 mGLMaxTextureSize;
+    F32 mMaxAnisotropy = 0.f;
+
+	// GL 4.x capabilities
+	bool mHasCubeMapArray = false;
+	bool mHasDebugOutput = false;
+    bool mHasTransformFeedback = false;
+    bool mHasAnisotropic = false;
+	
 	// Vendor-specific extensions
+    bool mHasAMDAssociations = false;
+
 	BOOL mIsAMD;
 	BOOL mIsNVIDIA;
 	BOOL mIsIntel;
@@ -134,9 +109,6 @@ class LLGLManager
 	// Whether this version of GL is good enough for SL to use
 	BOOL mHasRequirements;
 
-	// Misc extensions
-	BOOL mHasSeparateSpecularColor;
-
 	S32 mDriverVersionMajor;
 	S32 mDriverVersionMinor;
 	S32 mDriverVersionRelease;
@@ -147,9 +119,6 @@ class LLGLManager
 	std::string mGLVersionString;
 
 	S32 mVRAM; // VRAM in MB
-	S32 mGLMaxVertexRange;
-	S32 mGLMaxIndexRange;
-	S32 mGLMaxTextureSize;
 	
 	void getPixelFormat(); // Get the best pixel format
 
@@ -415,9 +384,7 @@ class LLGLFence
 class LLGLSyncFence : public LLGLFence
 {
 public:
-#ifdef GL_ARB_sync
 	GLsync mSync;
-#endif
 	
 	LLGLSyncFence();
 	virtual ~LLGLSyncFence();
diff --git a/indra/llrender/llglheaders.h b/indra/llrender/llglheaders.h
index f2b51fbafb32e44b21d4b6903c59e4be3cf31513..0aacf3bf0e7b88a55031b6f4413a7626729245ad 100644
--- a/indra/llrender/llglheaders.h
+++ b/indra/llrender/llglheaders.h
@@ -41,277 +41,6 @@
 # include "GL/glh_extensions.h"
 # undef __APPLE__
 
-#elif LL_LINUX
-//----------------------------------------------------------------------------
-// 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) glXGetProcAddress((const GLubyte*)(p))
-#endif // LL_LINUX && !LL_MESA_HEADLESS
-
-#if LL_LINUX && defined(WINGDIAPI)
-// WINGDIAPI gets set if we are using the linux nvidia gl.h header which needs
-// the functions below setting up.
-# define LL_LINUX_NV_GL_HEADERS 1
-#else
-# 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 PFNGLACTIVETEXTUREPROC	glActiveTexture;
-extern PFNGLCLIENTACTIVETEXTUREPROC	glClientActiveTexture;
-extern PFNGLDRAWRANGEELEMENTSPROC 	glDrawRangeElements;
-#endif // LL_LINUX_NV_GL_HEADERS
-
-// GL_ARB_vertex_array_object
-extern PFNGLBINDVERTEXARRAYPROC glBindVertexArray;
-extern PFNGLDELETEVERTEXARRAYSPROC glDeleteVertexArrays;
-extern PFNGLGENVERTEXARRAYSPROC glGenVertexArrays;
-extern PFNGLISVERTEXARRAYPROC glIsVertexArray;
-
-// GL_ARB_vertex_buffer_object
-extern PFNGLBINDBUFFERPROC		glBindBuffer;
-extern PFNGLDELETEBUFFERSPROC	glDeleteBuffers;
-extern PFNGLGENBUFFERSPROC		glGenBuffers;
-extern PFNGLISBUFFERPROC			glIsBuffer;
-extern PFNGLBUFFERDATAPROC		glBufferData;
-extern PFNGLBUFFERSUBDATAPROC	glBufferSubData;
-extern PFNGLGETBUFFERSUBDATAPROC glGetBufferSubData;
-extern PFNGLMAPBUFFERPROC		glMapBuffer;
-extern PFNGLUNMAPBUFFERPROC		glUnmapBuffer;
-extern PFNGLGETBUFFERPARAMETERIVPROC	glGetBufferParameteriv;
-extern PFNGLGETBUFFERPOINTERVPROC	glGetBufferPointerv;
-
-// GL_ARB_sync
-extern PFNGLFENCESYNCPROC				glFenceSync;
-extern PFNGLISSYNCPROC					glIsSync;
-extern PFNGLDELETESYNCPROC				glDeleteSync;
-extern PFNGLCLIENTWAITSYNCPROC			glClientWaitSync;
-extern PFNGLWAITSYNCPROC				glWaitSync;
-extern PFNGLGETINTEGER64VPROC			glGetInteger64v;
-extern PFNGLGETSYNCIVPROC				glGetSynciv;
-
-// GL_APPLE_flush_buffer_range
-extern PFNGLBUFFERPARAMETERIAPPLEPROC	glBufferParameteriAPPLE;
-extern PFNGLFLUSHMAPPEDBUFFERRANGEAPPLEPROC glFlushMappedBufferRangeAPPLE;
-
-// GL_ARB_map_buffer_range
-extern PFNGLMAPBUFFERRANGEPROC			glMapBufferRange;
-extern PFNGLFLUSHMAPPEDBUFFERRANGEPROC	glFlushMappedBufferRange;
-
-// 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 PFNGLGENQUERIESPROC glGenQueries;
-extern PFNGLDELETEQUERIESPROC glDeleteQueries;
-extern PFNGLISQUERYPROC glIsQuery;
-extern PFNGLBEGINQUERYPROC glBeginQuery;
-extern PFNGLENDQUERYPROC glEndQuery;
-extern PFNGLGETQUERYIVPROC glGetQueryiv;
-extern PFNGLGETQUERYOBJECTIVPROC glGetQueryObjectiv;
-extern PFNGLGETQUERYOBJECTUIVPROC glGetQueryObjectuiv;
-
-// GL_ARB_timer_query
-extern PFNGLQUERYCOUNTERPROC glQueryCounter;
-extern PFNGLGETQUERYOBJECTI64VPROC glGetQueryObjecti64v;
-extern PFNGLGETQUERYOBJECTUI64VPROC glGetQueryObjectui64v;
-
-// GL_ARB_point_parameters
-extern PFNGLPOINTPARAMETERFPROC glPointParameterf;
-extern PFNGLPOINTPARAMETERFVPROC glPointParameterfv;
-
-// GL_ARB_shader_objects
-extern PFNGLDELETEOBJECTPROC glDeleteObject;
-extern PFNGLGETHANDLEPROC glGetHandle;
-extern PFNGLDETACHOBJECTPROC glDetachObject;
-extern PFNGLCREATESHADEROBJECTPROC glCreateShaderObject;
-extern PFNGLSHADERSOURCEPROC glShaderSource;
-extern PFNGLCOMPILESHADERPROC glCompileShader;
-extern PFNGLCREATEPROGRAMOBJECTPROC glCreateProgramObject;
-extern PFNGLATTACHOBJECTPROC glAttachObject;
-extern PFNGLLINKPROGRAMPROC glLinkProgram;
-extern PFNGLUSEPROGRAMOBJECTPROC glUseProgramObject;
-extern PFNGLVALIDATEPROGRAMPROC glValidateProgram;
-extern PFNGLUNIFORM1FPROC glUniform1f;
-extern PFNGLUNIFORM2FPROC glUniform2f;
-extern PFNGLUNIFORM3FPROC glUniform3f;
-extern PFNGLUNIFORM4FPROC glUniform4f;
-extern PFNGLUNIFORM1IPROC glUniform1i;
-extern PFNGLUNIFORM2IPROC glUniform2i;
-extern PFNGLUNIFORM3IPROC glUniform3i;
-extern PFNGLUNIFORM4IPROC glUniform4i;
-extern PFNGLUNIFORM1FVPROC glUniform1fv;
-extern PFNGLUNIFORM2FVPROC glUniform2fv;
-extern PFNGLUNIFORM3FVPROC glUniform3fv;
-extern PFNGLUNIFORM4FVPROC glUniform4fv;
-extern PFNGLUNIFORM1IVPROC glUniform1iv;
-extern PFNGLUNIFORM2IVPROC glUniform2iv;
-extern PFNGLUNIFORM3IVPROC glUniform3iv;
-extern PFNGLUNIFORM4IVPROC glUniform4iv;
-extern PFNGLUNIFORMMATRIX2FVPROC glUniformMatrix2fv;
-extern PFNGLUNIFORMMATRIX3FVPROC glUniformMatrix3fv;
-extern PFNGLUNIFORMMATRIX3X4FVPROC glUniformMatrix3x4fv;
-extern PFNGLUNIFORMMATRIX4FVPROC glUniformMatrix4fv;
-extern PFNGLGETOBJECTPARAMETERFVPROC glGetObjectParameterfv;
-extern PFNGLGETOBJECTPARAMETERIVPROC glGetObjectParameteriv;
-extern PFNGLGETINFOLOGPROC glGetInfoLog;
-extern PFNGLGETATTACHEDOBJECTSPROC glGetAttachedObjects;
-extern PFNGLGETUNIFORMLOCATIONPROC glGetUniformLocation;
-extern PFNGLGETACTIVEUNIFORMPROC glGetActiveUniform;
-extern PFNGLGETUNIFORMFVPROC glGetUniformfv;
-extern PFNGLGETUNIFORMIVPROC glGetUniformiv;
-extern PFNGLGETSHADERSOURCEPROC glGetShaderSource;
-
-// GL_ARB_vertex_shader
-extern PFNGLVERTEXATTRIB1DPROC glVertexAttrib1d;
-extern PFNGLVERTEXATTRIB1DVPROC glVertexAttrib1dv;
-extern PFNGLVERTEXATTRIB1FPROC glVertexAttrib1f;
-extern PFNGLVERTEXATTRIB1FVPROC glVertexAttrib1fv;
-extern PFNGLVERTEXATTRIB1SPROC glVertexAttrib1s;
-extern PFNGLVERTEXATTRIB1SVPROC glVertexAttrib1sv;
-extern PFNGLVERTEXATTRIB2DPROC glVertexAttrib2d;
-extern PFNGLVERTEXATTRIB2DVPROC glVertexAttrib2dv;
-extern PFNGLVERTEXATTRIB2FPROC glVertexAttrib2f;
-extern PFNGLVERTEXATTRIB2FVPROC glVertexAttrib2fv;
-extern PFNGLVERTEXATTRIB2SPROC glVertexAttrib2s;
-extern PFNGLVERTEXATTRIB2SVPROC glVertexAttrib2sv;
-extern PFNGLVERTEXATTRIB3DPROC glVertexAttrib3d;
-extern PFNGLVERTEXATTRIB3DVPROC glVertexAttrib3dv;
-extern PFNGLVERTEXATTRIB3FPROC glVertexAttrib3f;
-extern PFNGLVERTEXATTRIB3FVPROC glVertexAttrib3fv;
-extern PFNGLVERTEXATTRIB3SPROC glVertexAttrib3s;
-extern PFNGLVERTEXATTRIB3SVPROC glVertexAttrib3sv;
-extern PFNGLVERTEXATTRIB4NBVPROC glVertexAttrib4nbv;
-extern PFNGLVERTEXATTRIB4NIVPROC glVertexAttrib4niv;
-extern PFNGLVERTEXATTRIB4NSVPROC glVertexAttrib4nsv;
-extern PFNGLVERTEXATTRIB4NUBPROC glVertexAttrib4nub;
-extern PFNGLVERTEXATTRIB4NUBVPROC glVertexAttrib4nubv;
-extern PFNGLVERTEXATTRIB4NUIVPROC glVertexAttrib4nuiv;
-extern PFNGLVERTEXATTRIB4NUSVPROC glVertexAttrib4nusv;
-extern PFNGLVERTEXATTRIB4BVPROC glVertexAttrib4bv;
-extern PFNGLVERTEXATTRIB4DPROC glVertexAttrib4d;
-extern PFNGLVERTEXATTRIB4DVPROC glVertexAttrib4dv;
-extern PFNGLVERTEXATTRIB4FPROC glVertexAttrib4f;
-extern PFNGLVERTEXATTRIB4FVPROC glVertexAttrib4fv;
-extern PFNGLVERTEXATTRIB4IVPROC glVertexAttrib4iv;
-extern PFNGLVERTEXATTRIB4SPROC glVertexAttrib4s;
-extern PFNGLVERTEXATTRIB4SVPROC glVertexAttrib4sv;
-extern PFNGLVERTEXATTRIB4UBVPROC glVertexAttrib4ubv;
-extern PFNGLVERTEXATTRIB4UIVPROC glVertexAttrib4uiv;
-extern PFNGLVERTEXATTRIB4USVPROC glVertexAttrib4usv;
-extern PFNGLVERTEXATTRIBPOINTERPROC glVertexAttribPointer;
-extern PFNGLVERTEXATTRIBIPOINTERPROC glVertexAttribIPointer;
-extern PFNGLENABLEVERTEXATTRIBARRAYPROC glEnableVertexAttribArray;
-extern PFNGLDISABLEVERTEXATTRIBARRAYPROC glDisableVertexAttribArray;
-extern PFNGLPROGRAMSTRINGPROC glProgramString;
-extern PFNGLBINDPROGRAMPROC glBindProgram;
-extern PFNGLDELETEPROGRAMSPROC glDeletePrograms;
-extern PFNGLGENPROGRAMSPROC glGenPrograms;
-extern PFNGLPROGRAMENVPARAMETER4DPROC glProgramEnvParameter4d;
-extern PFNGLPROGRAMENVPARAMETER4DVPROC glProgramEnvParameter4dv;
-extern PFNGLPROGRAMENVPARAMETER4FPROC glProgramEnvParameter4f;
-extern PFNGLPROGRAMENVPARAMETER4FVPROC glProgramEnvParameter4fv;
-extern PFNGLPROGRAMLOCALPARAMETER4DPROC glProgramLocalParameter4d;
-extern PFNGLPROGRAMLOCALPARAMETER4DVPROC glProgramLocalParameter4dv;
-extern PFNGLPROGRAMLOCALPARAMETER4FPROC glProgramLocalParameter4f;
-extern PFNGLPROGRAMLOCALPARAMETER4FVPROC glProgramLocalParameter4fv;
-extern PFNGLGETPROGRAMENVPARAMETERDVPROC glGetProgramEnvParameterdv;
-extern PFNGLGETPROGRAMENVPARAMETERFVPROC glGetProgramEnvParameterfv;
-extern PFNGLGETPROGRAMLOCALPARAMETERDVPROC glGetProgramLocalParameterdv;
-extern PFNGLGETPROGRAMLOCALPARAMETERFVPROC glGetProgramLocalParameterfv;
-extern PFNGLGETPROGRAMIVPROC glGetProgramiv;
-extern PFNGLGETPROGRAMSTRINGPROC glGetProgramString;
-extern PFNGLGETVERTEXATTRIBDVPROC glGetVertexAttribdv;
-extern PFNGLGETVERTEXATTRIBFVPROC glGetVertexAttribfv;
-extern PFNGLGETVERTEXATTRIBIVPROC glGetVertexAttribiv;
-extern PFNGLGETVERTEXATTRIBPOINTERVPROC glGetVertexAttribPointerv;
-extern PFNGLISPROGRAMPROC glIsProgram;
-extern PFNGLBINDATTRIBLOCATIONPROC glBindAttribLocation;
-extern PFNGLGETACTIVEATTRIBPROC glGetActiveAttrib;
-extern PFNGLGETATTRIBLOCATIONPROC glGetAttribLocation;
-
-extern PFNGLCOMPRESSEDTEXIMAGE2DPROC glCompressedTexImage2D;
-extern PFNGLGETCOMPRESSEDTEXIMAGEPROC glGetCompressedTexImage;
-
-//GL_EXT_blend_func_separate
-extern PFNGLBLENDFUNCSEPARATEEXTPROC glBlendFuncSeparateEXT;
-
-//GL_ARB_framebuffer_object
-extern PFNGLISRENDERBUFFERPROC glIsRenderbuffer;
-extern PFNGLBINDRENDERBUFFERPROC glBindRenderbuffer;
-extern PFNGLDELETERENDERBUFFERSPROC glDeleteRenderbuffers;
-extern PFNGLGENRENDERBUFFERSPROC glGenRenderbuffers;
-extern PFNGLRENDERBUFFERSTORAGEPROC glRenderbufferStorage;
-extern PFNGLGETRENDERBUFFERPARAMETERIVPROC glGetRenderbufferParameteriv;
-extern PFNGLISFRAMEBUFFERPROC glIsFramebuffer;
-extern PFNGLBINDFRAMEBUFFERPROC glBindFramebuffer;
-extern PFNGLDELETEFRAMEBUFFERSPROC glDeleteFramebuffers;
-extern PFNGLGENFRAMEBUFFERSPROC glGenFramebuffers;
-extern PFNGLCHECKFRAMEBUFFERSTATUSPROC glCheckFramebufferStatus;
-extern PFNGLFRAMEBUFFERTEXTURE1DPROC glFramebufferTexture1D;
-extern PFNGLFRAMEBUFFERTEXTURE2DPROC glFramebufferTexture2D;
-extern PFNGLFRAMEBUFFERTEXTURE3DPROC glFramebufferTexture3D;
-extern PFNGLFRAMEBUFFERRENDERBUFFERPROC glFramebufferRenderbuffer;
-extern PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC glGetFramebufferAttachmentParameteriv;
-extern PFNGLGENERATEMIPMAPPROC glGenerateMipmap;
-extern PFNGLBLITFRAMEBUFFERPROC glBlitFramebuffer;
-extern PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC glRenderbufferStorageMultisample;
-extern PFNGLFRAMEBUFFERTEXTURELAYERPROC glFramebufferTextureLayer;
-
-//GL_ARB_draw_buffers
-extern PFNGLDRAWBUFFERSPROC glDrawBuffers;
-
-//GL_ARB_texture_multisample
-extern PFNGLTEXIMAGE2DMULTISAMPLEPROC glTexImage2DMultisample;
-extern PFNGLTEXIMAGE3DMULTISAMPLEPROC glTexImage3DMultisample;
-extern PFNGLGETMULTISAMPLEFVPROC glGetMultisamplefv;
-extern PFNGLSAMPLEMASKIPROC glSampleMaski;
-
-//transform feedback (4.0 core)
-extern PFNGLBEGINTRANSFORMFEEDBACKPROC glBeginTransformFeedback;
-extern PFNGLENDTRANSFORMFEEDBACKPROC glEndTransformFeedback;
-extern PFNGLTRANSFORMFEEDBACKVARYINGSPROC glTransformFeedbackVaryings;
-extern PFNGLBINDBUFFERRANGEPROC glBindBufferRange;
-extern PFNGLBINDBUFFERBASEPROC glBindBufferBase;
-
 #elif LL_WINDOWS
 //----------------------------------------------------------------------------
 // LL_WINDOWS
@@ -345,12 +74,6 @@ extern PFNWGLGETSWAPINTERVALEXTPROC wglGetSwapIntervalEXT;
 // WGL_ARB_create_context
 extern PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB;
 
-// GL_VERSION_1_2
-//extern PFNGLDRAWRANGEELEMENTSPROC  glDrawRangeElements;
-//extern PFNGLTEXIMAGE3DPROC         glTexImage3D;
-//extern PFNGLTEXSUBIMAGE3DPROC      glTexSubImage3D;
-//extern PFNGLCOPYTEXSUBIMAGE3DPROC  glCopyTexSubImage3D;
-
 // GL_VERSION_1_3
 extern PFNGLACTIVETEXTUREPROC               glActiveTexture;
 extern PFNGLSAMPLECOVERAGEPROC              glSampleCoverage;
diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp
index d8e312106cf2b152cb074f90e2c96884ad904aa2..6eb7da302f8a7714c62a81eba224cf5600073a69 100644
--- a/indra/llrender/llimagegl.cpp
+++ b/indra/llrender/llimagegl.cpp
@@ -352,7 +352,7 @@ void LLImageGL::updateStats(F32 current_time)
 //static 
 void LLImageGL::destroyGL(BOOL save_state)
 {
-	for (S32 stage = 0; stage < gGLManager.mNumTextureUnits; stage++)
+	for (S32 stage = 0; stage < gGLManager.mNumTextureImageUnits; stage++)
 	{
 		gGL.getTexUnit(stage)->unbind(LLTexUnit::TT_TEXTURE);
 	}
@@ -520,7 +520,6 @@ void LLImageGL::init(BOOL usemipmaps)
 	mPickMaskHeight = 0;
 	mUseMipMaps = usemipmaps;
 	mHasExplicitFormat = FALSE;
-	mAutoGenMips = FALSE;
 
 	mIsMask = FALSE;
 	mNeedsAlphaAndPickMask = TRUE ;
@@ -1069,30 +1068,12 @@ BOOL LLImageGL::preAddToAtlas(S32 discard_level, const LLImageRaw* raw_image)
                 mFormatType     = GL_UNSIGNED_BYTE;
                 break;
             case 3:
-#if USE_SRGB_DECODE
-                if (gGLManager.mHasTexturesRGBDecode)
-                {
-                    mFormatInternal = GL_SRGB8;
-                }
-                else
-#endif
-                {
-                    mFormatInternal = GL_RGB8;
-                }
+                mFormatInternal = GL_RGB8;
                 mFormatPrimary = GL_RGB;
                 mFormatType    = GL_UNSIGNED_BYTE;
                 break;
             case 4:
-#if USE_SRGB_DECODE
-                if (gGLManager.mHasTexturesRGBDecode)
-                {
-                    mFormatInternal = GL_SRGB8_ALPHA8;
-                }
-                else
-#endif
-                {
-                    mFormatInternal = GL_RGBA8;
-                }
+                mFormatInternal = GL_RGBA8;
                 mFormatPrimary = GL_RGBA;
                 mFormatType    = GL_UNSIGNED_BYTE;
                 break;
@@ -1525,30 +1506,12 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S
             mFormatType = GL_UNSIGNED_BYTE;
             break;
         case 3:
-        #if USE_SRGB_DECODE
-            if (gGLManager.mHasTexturesRGBDecode)
-            {
-                mFormatInternal = GL_SRGB8;
-            }
-            else
-        #endif
-            {
-                mFormatInternal = GL_RGB8;
-            }
+            mFormatInternal = GL_RGB8;
             mFormatPrimary = GL_RGB;
             mFormatType = GL_UNSIGNED_BYTE;
             break;
         case 4:
-        #if USE_SRGB_DECODE
-            if (gGLManager.mHasTexturesRGBDecode)
-            {
-                mFormatInternal = GL_SRGB8_ALPHA8;
-            }
-            else
-        #endif
-            {
-                mFormatInternal = GL_RGBA8;
-            }
+            mFormatInternal = GL_RGBA8;
             mFormatPrimary = GL_RGBA;
             mFormatType = GL_UNSIGNED_BYTE;
             break;
@@ -1637,7 +1600,7 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_
 
     if (mUseMipMaps)
     {
-        mAutoGenMips = gGLManager.mHasMipMapGeneration;
+        mAutoGenMips = true;
     }
 
     mCurrentDiscardLevel = discard_level;
@@ -1694,44 +1657,37 @@ void LLImageGL::syncToMainThread(LLGLuint new_tex_name)
 
     {
         LL_PROFILE_ZONE_NAMED("cglt - sync");
-        if (gGLManager.mHasSync)
+        if (gGLManager.mIsNVIDIA)
         {
-            if (gGLManager.mIsNVIDIA)
-            {
-                // wait for texture upload to finish before notifying main thread
-                // upload is complete
-                auto sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
-                glFlush();
-                glClientWaitSync(sync, 0, GL_TIMEOUT_IGNORED);
-                glDeleteSync(sync);
-            }
-            else
-            {
-                // post a sync to the main thread (will execute before tex name swap lambda below)
-                // glFlush calls here are partly superstitious and partly backed by observation
-                // on AMD hardware
-                glFlush();
-                auto sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
-                glFlush();
-                LL::WorkQueue::postMaybe(
-                    mMainQueue,
-                    [=]()
-                    {
-                        LL_PROFILE_ZONE_NAMED("cglt - wait sync");
-                        {
-                            LL_PROFILE_ZONE_NAMED("glWaitSync");
-                            glWaitSync(sync, 0, GL_TIMEOUT_IGNORED);
-                        }
-                        {
-                            LL_PROFILE_ZONE_NAMED("glDeleteSync");
-                            glDeleteSync(sync);
-                        }
-                    });
-            }
+            // wait for texture upload to finish before notifying main thread
+            // upload is complete
+            auto sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
+            glFlush();
+            glClientWaitSync(sync, 0, GL_TIMEOUT_IGNORED);
+            glDeleteSync(sync);
         }
         else
         {
-            glFinish();
+            // post a sync to the main thread (will execute before tex name swap lambda below)
+            // glFlush calls here are partly superstitious and partly backed by observation
+            // on AMD hardware
+            glFlush();
+            auto sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
+            glFlush();
+            LL::WorkQueue::postMaybe(
+                mMainQueue,
+                [=]()
+                {
+                    LL_PROFILE_ZONE_NAMED("cglt - wait sync");
+                    {
+                        LL_PROFILE_ZONE_NAMED("glWaitSync");
+                        glWaitSync(sync, 0, GL_TIMEOUT_IGNORED);
+                    }
+                    {
+                        LL_PROFILE_ZONE_NAMED("glDeleteSync");
+                        glDeleteSync(sync);
+                    }
+                });
         }
     }
 
diff --git a/indra/llrender/llimagegl.h b/indra/llrender/llimagegl.h
index b4618fd35cd9c1c7e6ca7e8085ce7023ff95e3ac..bbd024abd9d131dfb18fa52931e6fbbe5e48086d 100644
--- a/indra/llrender/llimagegl.h
+++ b/indra/llrender/llimagegl.h
@@ -219,7 +219,7 @@ class LLImageGL : public LLRefCount
 	U16 mPickMaskHeight;
 	S8 mUseMipMaps;
 	BOOL mHasExplicitFormat; // If false (default), GL format is f(mComponents)
-	S8 mAutoGenMips;
+	bool mAutoGenMips = false;
 
 	BOOL mIsMask;
 	BOOL mNeedsAlphaAndPickMask;
diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp
index 554721399a5533150ada03a01890d18e85eb1860..6e659641fecf8c4fc33ab2a4a81c9ead870b0e19 100644
--- a/indra/llrender/llrender.cpp
+++ b/indra/llrender/llrender.cpp
@@ -335,7 +335,7 @@ bool LLTexUnit::bind(LLCubeMap* cubeMap)
 
 	if (mCurrTexture != cubeMap->mImages[0]->getTexName())
 	{
-		if (gGLManager.mHasCubeMap && LLCubeMap::sUseCubeMaps)
+		if (LLCubeMap::sUseCubeMaps)
 		{
 			activate();
 			enable(LLTexUnit::TT_CUBE_MAP);
@@ -516,22 +516,15 @@ void LLTexUnit::setTextureFilteringOption(LLTexUnit::eTextureFilterOptions optio
 		}
 	}
 
-	if (gGLManager.mHasAnisotropic)
+	if (gGLManager.mGLVersion >= 4.59f)
 	{
 		if (LLImageGL::sGlobalUseAnisotropic && option == TFO_ANISOTROPIC)
 		{
-			if (gGL.mMaxAnisotropy < 1.f)
-			{
-				glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &gGL.mMaxAnisotropy);
-
-				LL_INFOS() << "gGL.mMaxAnisotropy: " << gGL.mMaxAnisotropy << LL_ENDL ;
-				gGL.mMaxAnisotropy = llmax(1.f, gGL.mMaxAnisotropy) ;
-			}
-			glTexParameterf(sGLTextureType[mCurrTexType], GL_TEXTURE_MAX_ANISOTROPY_EXT, gGL.mMaxAnisotropy);
+			glTexParameterf(sGLTextureType[mCurrTexType], GL_TEXTURE_MAX_ANISOTROPY, gGLManager.mMaxAnisotropy);
 		}
 		else
 		{
-			glTexParameterf(sGLTextureType[mCurrTexType], GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.f);
+			glTexParameterf(sGLTextureType[mCurrTexType], GL_TEXTURE_MAX_ANISOTROPY, 1.f);
 		}
 	}
 }
@@ -650,29 +643,6 @@ void LLTexUnit::debugTextureUnit(void)
 void LLTexUnit::setTextureColorSpace(eTextureColorSpace space)
 {
     mTexColorSpace = space;
-
-#if USE_SRGB_DECODE
-    if (gGLManager.mHasTexturesRGBDecode)
-    {
-        if (space == TCS_SRGB)
-        {
-            glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_SRGB_DECODE_EXT, GL_DECODE_EXT);
-        }
-        else
-        {
-            glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_SRGB_DECODE_EXT, GL_SKIP_DECODE_EXT);
-        }
-
-        if (gDebugGL)
-        {
-            assert_glerror();
-        }
-    }
-    else
-    {
-        glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_SRGB_DECODE_EXT, GL_SKIP_DECODE_EXT);
-    }
-#endif
 }
 
 LLLightState::LLLightState(S32 index)
@@ -846,8 +816,7 @@ LLRender::LLRender()
     mCount(0),
 	mQuadCycle(0),
     mMode(LLRender::TRIANGLES),
-    mCurrTextureUnitIndex(0),
-    mMaxAnisotropy(0.f) 
+    mCurrTextureUnitIndex(0)
 {	
 	mTexUnits.reserve(LL_NUM_TEXTURE_LAYERS);
 	for (U32 i = 0; i < LL_NUM_TEXTURE_LAYERS; i++)
@@ -912,11 +881,9 @@ void LLRender::init()
 
 	if (sGLCoreProfile && !LLVertexBuffer::sUseVAO)
 	{ //bind a dummy vertex array object so we're core profile compliant
-#ifdef GL_ARB_vertex_array_object
 		U32 ret;
 		glGenVertexArrays(1, &ret);
 		glBindVertexArray(ret);
-#endif
 	}
 
 
@@ -1492,12 +1459,7 @@ void LLRender::blendFunc(eBlendFactor color_sfactor, eBlendFactor color_dfactor,
 	llassert(color_dfactor < BF_UNDEF);
 	llassert(alpha_sfactor < BF_UNDEF);
 	llassert(alpha_dfactor < BF_UNDEF);
-	if (!LLRender::sGLCoreProfile && !gGLManager.mHasBlendFuncSeparate)
-	{
-		LL_WARNS_ONCE("render") << "no glBlendFuncSeparateEXT(), using color-only blend func" << LL_ENDL;
-		blendFunc(color_sfactor, color_dfactor);
-		return;
-	}
+	
 	if (mCurrBlendColorSFactor != color_sfactor || mCurrBlendColorDFactor != color_dfactor ||
 	    mCurrBlendAlphaSFactor != alpha_sfactor || mCurrBlendAlphaDFactor != alpha_dfactor)
 	{
diff --git a/indra/llrender/llrender.h b/indra/llrender/llrender.h
index b1fb60cf922c5974c327b731014f633010136113..3e4a1fe933c1d780008e8d4eea0427469731a0c0 100644
--- a/indra/llrender/llrender.h
+++ b/indra/llrender/llrender.h
@@ -493,8 +493,6 @@ class LLRender
 	eBlendFactor mCurrBlendAlphaSFactor;
 	eBlendFactor mCurrBlendAlphaDFactor;
 
-	F32				mMaxAnisotropy;
-
 	std::vector<LLVector3> mUIOffset;
 	std::vector<LLVector3> mUIScale;
 
diff --git a/indra/llrender/llrendertarget.cpp b/indra/llrender/llrendertarget.cpp
index fa236549782800584911c67f8d1ea8b5cd7cbdad..015312e570dfc8a6302d44f46062959757e3d48c 100644
--- a/indra/llrender/llrendertarget.cpp
+++ b/indra/llrender/llrendertarget.cpp
@@ -134,7 +134,7 @@ bool LLRenderTarget::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, boo
 	mUsage = usage;
 	mUseDepth = depth;
 
-	if ((sUseFBO || use_fbo) && gGLManager.mHasFramebufferObject)
+	if ((sUseFBO || use_fbo))
 	{
 		if (depth)
 		{
@@ -234,11 +234,9 @@ bool LLRenderTarget::addColorAttachment(U32 color_fmt)
 		llassert( offset < 4 );
 		return false;
 	}
-	if( offset > 0 && (mFBO == 0 || !gGLManager.mHasDrawBuffers) )
+	if( offset > 0 && (mFBO == 0) )
 	{
-		LL_WARNS() << "FBO not used or no drawbuffers available; mFBO=" << (U32)mFBO << " gGLManager.mHasDrawBuffers=" << (U32)gGLManager.mHasDrawBuffers << LL_ENDL;
 		llassert(  mFBO != 0 );
-		llassert( gGLManager.mHasDrawBuffers );
 		return false;
 	}
 
@@ -484,14 +482,12 @@ void LLRenderTarget::bindTarget()
 		sCurFBO = mFBO;
 		
 		stop_glerror();
-		if (gGLManager.mHasDrawBuffers)
-		{ //setup multiple render targets
-			GLenum drawbuffers[] = {GL_COLOR_ATTACHMENT0,
-									GL_COLOR_ATTACHMENT1,
-									GL_COLOR_ATTACHMENT2,
-									GL_COLOR_ATTACHMENT3};
-			glDrawBuffers(mTex.size(), drawbuffers);
-		}
+		//setup multiple render targets
+		GLenum drawbuffers[] = {GL_COLOR_ATTACHMENT0,
+								GL_COLOR_ATTACHMENT1,
+								GL_COLOR_ATTACHMENT2,
+								GL_COLOR_ATTACHMENT3};
+		glDrawBuffers(mTex.size(), drawbuffers);
 			
 		if (mTex.empty())
 		{ //no color buffer to draw to
diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp
index a40ea2eb1e9c78138a593d5d1c10cf7017e9a0f1..d05f916d95aa0dc0f634c1319f4223b27dc847ae 100644
--- a/indra/llrender/llvertexbuffer.cpp
+++ b/indra/llrender/llvertexbuffer.cpp
@@ -744,7 +744,7 @@ void LLVertexBuffer::drawArrays(U32 mode, U32 first, U32 count) const
 //static
 void LLVertexBuffer::initClass(bool use_vbo, bool no_vbo_mapping)
 {
-	sEnableVBOs = use_vbo && gGLManager.mHasVertexBufferObject;
+    sEnableVBOs = use_vbo;
 	sDisableVBOMapping = sEnableVBOs && no_vbo_mapping;
 }
 
@@ -753,9 +753,7 @@ void LLVertexBuffer::unbind()
 {
 	if (sGLRenderArray)
 	{
-#if GL_ARB_vertex_array_object
 		glBindVertexArray(0);
-#endif
 		sGLRenderArray = 0;
 		sGLRenderIndices = 0;
 		sIBOActive = false;
@@ -923,9 +921,7 @@ LLVertexBuffer::~LLVertexBuffer()
 
 	if (mGLArray)
 	{
-#if GL_ARB_vertex_array_object
 		releaseVAOName(mGLArray);
-#endif
 	}
 
 	sCount--;
@@ -956,10 +952,7 @@ void LLVertexBuffer::placeFence() const
 {
 	/*if (!mFence && useVBOs())
 	{
-		if (gGLManager.mHasSync)
-		{
-			mFence = new LLGLSyncFence();
-		}
+	    mFence = new LLGLSyncFence();
 	}
 
 	if (mFence)
@@ -1234,11 +1227,9 @@ bool LLVertexBuffer::allocateBuffer(S32 nverts, S32 nindices, bool create)
 		//actually allocate space for the vertex buffer if using VBO mapping
 		flush(); //unmap
 
-		if (gGLManager.mHasVertexArrayObject && useVBOs() && sUseVAO)
+		if (useVBOs() && sUseVAO)
 		{
-#if GL_ARB_vertex_array_object
 			mGLArray = getVAOName();
-#endif
 			setupVertexArray();
 		}
 	}
@@ -1254,9 +1245,7 @@ void LLVertexBuffer::setupVertexArray()
 	}
 
     LL_PROFILE_ZONE_SCOPED_CATEGORY_VERTEX;
-#if GL_ARB_vertex_array_object
 	glBindVertexArray(mGLArray);
-#endif
 	sGLRenderArray = mGLArray;
 
 	static const U32 attrib_size[] = 
@@ -1443,7 +1432,7 @@ U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, bool map_ran
 		
 	if (useVBOs())
 	{
-		if (!mMappable || gGLManager.mHasMapBufferRange || gGLManager.mHasFlushBufferRange)
+		if (!mMappable)
 		{
 			if (count == -1)
 			{
@@ -1492,58 +1481,34 @@ U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, bool map_ran
 			{
 				U8* src = NULL;
 				waitFence();
-				if (gGLManager.mHasMapBufferRange)
+				if (map_range)
 				{
-					if (map_range)
-					{
-#ifdef GL_ARB_map_buffer_range
-						S32 offset = mOffsets[type] + sTypeSize[type]*index;
-						S32 length = (sTypeSize[type]*count+0xF) & ~0xF;
-						src = (U8*) glMapBufferRange(GL_ARRAY_BUFFER, offset, length,
-							GL_MAP_WRITE_BIT | 
-							GL_MAP_FLUSH_EXPLICIT_BIT | 
-							GL_MAP_INVALIDATE_RANGE_BIT);
-#endif
-					}
-					else
+					S32 offset = mOffsets[type] + sTypeSize[type]*index;
+					S32 length = (sTypeSize[type]*count+0xF) & ~0xF;
+					src = (U8*) glMapBufferRange(GL_ARRAY_BUFFER, offset, length,
+						GL_MAP_WRITE_BIT | 
+						GL_MAP_FLUSH_EXPLICIT_BIT | 
+						GL_MAP_INVALIDATE_RANGE_BIT);
+				}
+				else
+				{
+					if (gDebugGL)
 					{
-#ifdef GL_ARB_map_buffer_range
+						GLint size = 0;
+						glGetBufferParameteriv(GL_ARRAY_BUFFER, GL_BUFFER_SIZE, &size);
 
-						if (gDebugGL)
+						if (size < mSize)
 						{
-							GLint size = 0;
-							glGetBufferParameteriv(GL_ARRAY_BUFFER, GL_BUFFER_SIZE, &size);
-
-							if (size < mSize)
-							{
-								LL_ERRS() << "Invalid buffer size." << LL_ENDL;
-							}
+							LL_ERRS() << "Invalid buffer size." << LL_ENDL;
 						}
-
-						src = (U8*) glMapBufferRange(GL_ARRAY_BUFFER, 0, mSize,
-							GL_MAP_WRITE_BIT | 
-							GL_MAP_FLUSH_EXPLICIT_BIT);
-#endif
-					}
-				}
-				else if (gGLManager.mHasFlushBufferRange)
-				{
-					if (map_range)
-					{
-						src = (U8*) glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
-					}
-					else
-					{
-						src = (U8*) glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
 					}
-				}
-				else
-				{
-					map_range = false;
-					src = (U8*) glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
+
+					src = (U8*) glMapBufferRange(GL_ARRAY_BUFFER, 0, mSize,
+						GL_MAP_WRITE_BIT | 
+						GL_MAP_FLUSH_EXPLICIT_BIT);
 				}
 
-				llassert(src != NULL);
+                llassert(src != NULL);
 
 				mMappedData = LL_NEXT_ALIGNED_ADDRESS<U8>(src);
 				mAlignedOffset = mMappedData - src;
@@ -1569,7 +1534,7 @@ U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, bool map_ran
 					//--------------------
 
 					GLint buff;
-					glGetIntegerv(GL_ARRAY_BUFFER_BINDING_ARB, &buff);
+					glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &buff);
 					if ((GLuint)buff != mGLBuffer)
 					{
 						LL_ERRS() << "Invalid GL vertex buffer bound: " << buff << LL_ENDL;
@@ -1590,7 +1555,7 @@ U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, bool map_ran
 		map_range = false;
 	}
 	
-	if (map_range && gGLManager.mHasMapBufferRange && mMappable)
+	if (map_range && mMappable)
 	{
 		return mMappedData;
 	}
@@ -1616,7 +1581,7 @@ U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range)
 
 	if (useVBOs())
 	{
-		if (!mMappable || gGLManager.mHasMapBufferRange || gGLManager.mHasFlushBufferRange)
+		if (!mMappable)
 		{
 			if (count == -1)
 			{
@@ -1657,7 +1622,7 @@ U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range)
 			if (gDebugGL && useVBOs())
 			{
 				GLint elem = 0;
-				glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB, &elem);
+				glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &elem);
 
 				if (elem != mGLIndices)
 				{
@@ -1673,48 +1638,24 @@ U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range)
 			{
 				U8* src = NULL;
 				waitFence();
-				if (gGLManager.mHasMapBufferRange)
+				if (map_range)
 				{
-					if (map_range)
-					{
-#ifdef GL_ARB_map_buffer_range
-						S32 offset = sizeof(U16)*index;
-						S32 length = sizeof(U16)*count;
-						src = (U8*) glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER, offset, length,
-							GL_MAP_WRITE_BIT | 
-							GL_MAP_FLUSH_EXPLICIT_BIT | 
-							GL_MAP_INVALIDATE_RANGE_BIT);
-#endif
-					}
-					else
-					{
-#ifdef GL_ARB_map_buffer_range
-						src = (U8*) glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER, 0, sizeof(U16)*mNumIndices,
-							GL_MAP_WRITE_BIT | 
-							GL_MAP_FLUSH_EXPLICIT_BIT);
-#endif
-					}
-				}
-				else if (gGLManager.mHasFlushBufferRange)
-				{
-					if (map_range)
-					{
-						src = (U8*) glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY);
-					}
-					else
-					{
-						src = (U8*) glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY);
-					}
+					S32 offset = sizeof(U16)*index;
+					S32 length = sizeof(U16)*count;
+					src = (U8*) glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER, offset, length,
+						GL_MAP_WRITE_BIT | 
+						GL_MAP_FLUSH_EXPLICIT_BIT | 
+						GL_MAP_INVALIDATE_RANGE_BIT);
 				}
 				else
 				{
-					map_range = false;
-					src = (U8*) glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY);
+					src = (U8*) glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER, 0, sizeof(U16)*mNumIndices,
+						GL_MAP_WRITE_BIT | 
+						GL_MAP_FLUSH_EXPLICIT_BIT);
 				}
-
+		
 				llassert(src != NULL);
 
-
 				mMappedIndexData = src; //LL_NEXT_ALIGNED_ADDRESS<U8>(src);
 				mAlignedIndexOffset = mMappedIndexData - src;
 				stop_glerror();
@@ -1729,7 +1670,7 @@ U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range)
 			if(mMappable)
 			{
 				GLint buff;
-				glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB, &buff);
+				glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &buff);
 				if ((GLuint)buff != mGLIndices)
 				{
 					LL_ERRS() << "Invalid GL index buffer bound: " << buff << LL_ENDL;
@@ -1748,7 +1689,7 @@ U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range)
 		map_range = false;
 	}
 
-	if (map_range && gGLManager.mHasMapBufferRange && mMappable)
+	if (map_range && mMappable)
 	{
 		return mMappedIndexData;
 	}
@@ -1812,25 +1753,20 @@ void LLVertexBuffer::unmapBuffer()
 		}
 		else
 		{
-			if (gGLManager.mHasMapBufferRange || gGLManager.mHasFlushBufferRange)
+			if (!mMappedVertexRegions.empty())
 			{
-				if (!mMappedVertexRegions.empty())
+                LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("unmapBuffer - flush vertex");
+				for (U32 i = 0; i < mMappedVertexRegions.size(); ++i)
 				{
-                    LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("unmapBuffer - flush vertex");
-					for (U32 i = 0; i < mMappedVertexRegions.size(); ++i)
-					{
-						const MappedRegion& region = mMappedVertexRegions[i];
-						S32 offset = region.mIndex >= 0 ? mOffsets[region.mType]+sTypeSize[region.mType]*region.mIndex : 0;
-						S32 length = sTypeSize[region.mType]*region.mCount;
-						if (gGLManager.mHasMapBufferRange)
-						{
-							glFlushMappedBufferRange(GL_ARRAY_BUFFER, offset, length);
-						}
-					}
-
-					mMappedVertexRegions.clear();
+					const MappedRegion& region = mMappedVertexRegions[i];
+					S32 offset = region.mIndex >= 0 ? mOffsets[region.mType]+sTypeSize[region.mType]*region.mIndex : 0;
+					S32 length = sTypeSize[region.mType]*region.mCount;
+			    	glFlushMappedBufferRange(GL_ARRAY_BUFFER, offset, length);
 				}
+
+				mMappedVertexRegions.clear();
 			}
+			
 			stop_glerror();
 			glUnmapBuffer(GL_ARRAY_BUFFER);
 			stop_glerror();
@@ -1884,25 +1820,19 @@ void LLVertexBuffer::unmapBuffer()
 		}
 		else
 		{
-			if (gGLManager.mHasMapBufferRange || gGLManager.mHasFlushBufferRange)
+			if (!mMappedIndexRegions.empty())
 			{
-				if (!mMappedIndexRegions.empty())
+				for (U32 i = 0; i < mMappedIndexRegions.size(); ++i)
 				{
-					for (U32 i = 0; i < mMappedIndexRegions.size(); ++i)
-					{
-                        LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("unmapBuffer - flush index");
-						const MappedRegion& region = mMappedIndexRegions[i];
-						S32 offset = region.mIndex >= 0 ? sizeof(U16)*region.mIndex : 0;
-						S32 length = sizeof(U16)*region.mCount;
-						if (gGLManager.mHasMapBufferRange)
-						{
-							glFlushMappedBufferRange(GL_ELEMENT_ARRAY_BUFFER, offset, length);
-						}
-						stop_glerror();
-					}
-
-					mMappedIndexRegions.clear();
+                    LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("unmapBuffer - flush index");
+					const MappedRegion& region = mMappedIndexRegions[i];
+					S32 offset = region.mIndex >= 0 ? sizeof(U16)*region.mIndex : 0;
+					S32 length = sizeof(U16)*region.mCount;
+					glFlushMappedBufferRange(GL_ELEMENT_ARRAY_BUFFER, offset, length);
+					stop_glerror();
 				}
+
+				mMappedIndexRegions.clear();
 			}
 			
             glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);
@@ -2034,9 +1964,7 @@ bool LLVertexBuffer::bindGLArray()
 	{
 		{
             LL_PROFILE_ZONE_SCOPED_CATEGORY_VERTEX;
-#if GL_ARB_vertex_array_object
 			glBindVertexArray(mGLArray);
-#endif
 			sGLRenderArray = mGLArray;
 		}
 
@@ -2228,7 +2156,7 @@ void LLVertexBuffer::setBuffer(U32 data_mask)
 		if (gDebugGL && !mGLArray)
 		{
 			GLint buff;
-			glGetIntegerv(GL_ARRAY_BUFFER_BINDING_ARB, &buff);
+			glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &buff);
 			if ((GLuint)buff != mGLBuffer)
 			{
 				if (gDebugSession)
@@ -2243,7 +2171,7 @@ void LLVertexBuffer::setBuffer(U32 data_mask)
 
 			if (mGLIndices)
 			{
-				glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB, &buff);
+				glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &buff);
 				if ((GLuint)buff != mGLIndices)
 				{
 					if (gDebugSession)
@@ -2264,9 +2192,7 @@ void LLVertexBuffer::setBuffer(U32 data_mask)
 	{	
 		if (sGLRenderArray)
 		{
-#if GL_ARB_vertex_array_object
 			glBindVertexArray(0);
-#endif
 			sGLRenderArray = 0;
 			sGLRenderIndices = 0;
 			sIBOActive = false;
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 9508c1dc2d3b02dd30d57f68d1dfcc45f3fe908c..100bcf7ab9297740eda4959bc145fad95ecb578d 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -10784,18 +10784,6 @@
       <key>Value</key>
       <integer>0</integer>
     </map>
-  <key>RenderUseTransformFeedback</key>
-  <map>
-    <key>Comment</key>
-    <string>[EXPERIMENTAL] Use transform feedback shaders for LoD updates</string>
-    <key>Persist</key>
-    <integer>1</integer>
-    <key>Type</key>
-    <string>Boolean</string>
-    <key>Value</key>
-    <integer>0</integer>
-  </map>
-
   <key>RenderVBOMappingDisable</key>
     <map>
       <key>Comment</key>
diff --git a/indra/newview/featuretable.txt b/indra/newview/featuretable.txt
index 6b4ab1be17da11262f308d8395a96db9e667b6e2..abc379a44fade6472c317bc4fd8637c2e3fa3eba 100644
--- a/indra/newview/featuretable.txt
+++ b/indra/newview/featuretable.txt
@@ -1,4 +1,4 @@
-version 36
+version 37
 // The version number above should be incremented IF AND ONLY IF some
 // change has been made that is sufficiently important to justify
 // resetting the graphics preferences of all users to the recommended
@@ -287,14 +287,9 @@ list Intel
 RenderAnisotropic			1	0
 RenderFSAASamples			1	0
 RenderGLMultiThreaded       1   0
-RenderGLContextCoreProfile         1   0
 
-// AMD cards generally perform better when not using VBOs for streaming data
-// AMD cards also prefer an OpenGL Compatibility Profile Context
 // HACK: Current AMD drivers have bugged cubemap arrays, limit number of reflection probes to 16
 list AMD
-RenderUseStreamVBO			1	0
-RenderGLContextCoreProfile         1   0
 RenderReflectionProbeCount  1   16
 
 
diff --git a/indra/newview/lldrawpoolterrain.cpp b/indra/newview/lldrawpoolterrain.cpp
index be33e1b30a0a6c7d6c7c9b61b6b240d9a57d0a86..55c8d848388dd261c14c1aff064bf08aa0fd61d6 100644
--- a/indra/newview/lldrawpoolterrain.cpp
+++ b/indra/newview/lldrawpoolterrain.cpp
@@ -165,19 +165,6 @@ void LLDrawPoolTerrain::render(S32 pass)
 
 	LLOverrideFaceColor override(this, 1.f, 1.f, 1.f, 1.f);
 
-	if (!gGLManager.mHasMultitexture)
-	{
-		// No multitexture, render simple land.
-		renderSimple(); // Render without multitexture
-		return;
-	}
-	// Render simplified land if video card can't do sufficient multitexturing
-	if (!gGLManager.mHasARBEnvCombine || (gGLManager.mNumTextureUnits < 2))
-	{
-		renderSimple(); // Render without multitexture
-		return;
-	}
-
 	LLGLSPipeline gls;
 	
 	if (mShaderLevel > 1 && sShader->mShaderLevel > 0)
@@ -194,10 +181,6 @@ void LLDrawPoolTerrain::render(S32 pass)
 		{
 			renderSimple();
 		} 
-		else if (gGLManager.mNumTextureUnits < 4)
-		{
-			renderFull2TU();
-		} 
 		else 
 		{
 			renderFull4TU();
diff --git a/indra/newview/lldrawpoolwater.cpp b/indra/newview/lldrawpoolwater.cpp
index a84f62036e45c9739d4b0f60b5f4ec9e85405711..576024ead3aa3474d7145c7145d45f2439ce4936 100644
--- a/indra/newview/lldrawpoolwater.cpp
+++ b/indra/newview/lldrawpoolwater.cpp
@@ -104,7 +104,7 @@ void LLDrawPoolWater::restoreGL()
 
 void LLDrawPoolWater::prerender()
 {
-	mShaderLevel = (gGLManager.mHasCubeMap && LLCubeMap::sUseCubeMaps) ? LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_WATER) : 0;
+	mShaderLevel = LLCubeMap::sUseCubeMaps ? LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_WATER) : 0;
 }
 
 S32 LLDrawPoolWater::getNumPasses()
@@ -188,12 +188,6 @@ void LLDrawPoolWater::render(S32 pass)
 
 	stop_glerror();
 
-	if (!gGLManager.mHasMultitexture)
-	{
-		// Ack!  No multitexture!  Bail!
-		return;
-	}
-
 	LLFace* refl_face = voskyp->getReflFace();
 
 	gPipeline.disableLights();
diff --git a/indra/newview/lldynamictexture.cpp b/indra/newview/lldynamictexture.cpp
index 63e7887d816d6cd645e584df34cd946072355e6f..361a7666fabe4177bbd614ab9fcda17cc517f8d2 100644
--- a/indra/newview/lldynamictexture.cpp
+++ b/indra/newview/lldynamictexture.cpp
@@ -125,7 +125,7 @@ void LLViewerDynamicTexture::preRender(BOOL clear_depth)
 		llassert(mFullHeight <= static_cast<S32>(gPipeline.mPhysicsDisplay.getHeight()));
 	}
 
-	if (gGLManager.mHasFramebufferObject && gPipeline.mPhysicsDisplay.isComplete() && !gGLManager.mIsAMD)
+	if (gPipeline.mPhysicsDisplay.isComplete() && !gGLManager.mIsAMD)
 	{ //using offscreen render target, just use the bottom left corner
 		mOrigin.set(0, 0);
 	}
@@ -212,7 +212,7 @@ BOOL LLViewerDynamicTexture::updateAllInstances()
 		return TRUE;
 	}
 
-	bool use_fbo = gGLManager.mHasFramebufferObject && gPipeline.mBake.isComplete() && !gGLManager.mIsAMD;
+	bool use_fbo = gPipeline.mBake.isComplete() && !gGLManager.mIsAMD;
 
 	if (use_fbo)
 	{
diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp
index 3f69815e380782c2d88dad4fc1ae983d21376a90..5562f1d057ebc31c92dc5247c5ebaeeb3deab367 100644
--- a/indra/newview/llface.cpp
+++ b/indra/newview/llface.cpp
@@ -1211,55 +1211,6 @@ bool LLFace::canRenderAsMask()
 	return false;
 }
 
-
-//static 
-void LLFace::cacheFaceInVRAM(const LLVolumeFace& vf)
-{
-    LL_PROFILE_ZONE_SCOPED_CATEGORY_FACE;
-	U32 mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 |
-				LLVertexBuffer::MAP_TANGENT | LLVertexBuffer::MAP_NORMAL;
-	
-	if (vf.mWeights)
-	{
-		mask |= LLVertexBuffer::MAP_WEIGHT4;
-	}
-
-	LLVertexBuffer* buff = new LLVertexBuffer(mask, GL_STATIC_DRAW);
-	vf.mVertexBuffer = buff;
-
-	buff->allocateBuffer(vf.mNumVertices, 0, true);
-
-	LLStrider<LLVector4a> f_vert;
-	LLStrider<LLVector4a> f_tangent;
-	LLStrider<LLVector3> f_norm;
-	LLStrider<LLVector2> f_tc;
-
-	buff->getTangentStrider(f_tangent);
-	buff->getVertexStrider(f_vert);
-	buff->getNormalStrider(f_norm);
-	buff->getTexCoord0Strider(f_tc);
-
-	for (U32 i = 0; i < vf.mNumVertices; ++i)
-	{
-		*f_vert++ = vf.mPositions[i];
-		*f_tangent++ = vf.mTangents[i];
-		*f_tc++ = vf.mTexCoords[i];
-		(*f_norm++).set(vf.mNormals[i].getF32ptr());
-	}
-
-	if (vf.mWeights)
-	{
-		LLStrider<LLVector4> f_wght;
-		buff->getWeight4Strider(f_wght);
-		for (U32 i = 0; i < vf.mNumVertices; ++i)
-		{
-			(*f_wght++).set(vf.mWeights[i].getF32ptr());
-		}
-	}
-
-	buff->flush();
-}
-
 //helper function for pushing primitives for transform shaders and cleaning up
 //uninitialized data on the tail, plus tracking number of expected primitives
 void push_for_transform(LLVertexBuffer* buff, U32 source_count, U32 dest_count)
@@ -1304,7 +1255,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 
 
 	//don't use map range (generates many redundant unmap calls)
-	bool map_range = false; //gGLManager.mHasMapBufferRange || gGLManager.mHasFlushBufferRange;
+	bool map_range = false;
 
 	if (mVertexBuffer.notNull())
 	{
@@ -1535,155 +1486,6 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
         }
     }
 
-	static LLCachedControl<bool> use_transform_feedback(gSavedSettings, "RenderUseTransformFeedback", false);
-
-#ifdef GL_TRANSFORM_FEEDBACK_BUFFER
-	if (use_transform_feedback &&
-		mVertexBuffer->getUsage() == GL_DYNAMIC_COPY &&
-		gTransformPositionProgram.mProgramObject && //transform shaders are loaded
-		mVertexBuffer->useVBOs() && //target buffer is in VRAM
-		!rebuild_weights && //TODO: add support for weights
-		!volume.isUnique()) //source volume is NOT flexi
-	{ //use transform feedback to pack vertex buffer
-
-        LL_PROFILE_ZONE_NAMED_CATEGORY_FACE("getGeometryVolume - transform feedback");
-		LLGLEnable discard(GL_RASTERIZER_DISCARD);
-		LLVertexBuffer* buff = (LLVertexBuffer*) vf.mVertexBuffer.get();
-
-		if (vf.mVertexBuffer.isNull() || buff->getNumVerts() != vf.mNumVertices)
-		{
-			mVObjp->getVolume()->genTangents(f);
-			LLFace::cacheFaceInVRAM(vf);
-			buff = (LLVertexBuffer*) vf.mVertexBuffer.get();
-		}		
-
-		LLGLSLShader* cur_shader = LLGLSLShader::sCurBoundShaderPtr;
-		
-		gGL.pushMatrix();
-		gGL.loadMatrix((GLfloat*) mat_vert_in.mMatrix);
-
-		if (rebuild_pos)
-		{
-            LL_PROFILE_ZONE_NAMED_CATEGORY_FACE("getGeometryVolume - tf position");
-			gTransformPositionProgram.bind();
-
-			mVertexBuffer->bindForFeedback(0, LLVertexBuffer::TYPE_VERTEX, mGeomIndex, mGeomCount);
-
-			U8 index = mTextureIndex < FACE_DO_NOT_BATCH_TEXTURES ? mTextureIndex : 0;
-
-			S32 val = 0;
-			U8* vp = (U8*) &val;
-			vp[0] = index;
-			vp[1] = 0;
-			vp[2] = 0;
-			vp[3] = 0;
-			
-			gTransformPositionProgram.uniform1i(sTextureIndexIn, val);
-			glBeginTransformFeedback(GL_POINTS);
-			buff->setBuffer(LLVertexBuffer::MAP_VERTEX);
-
-			push_for_transform(buff, vf.mNumVertices, mGeomCount);
-
-			glEndTransformFeedback();
-		}
-
-		if (rebuild_color)
-		{
-            LL_PROFILE_ZONE_NAMED_CATEGORY_FACE("getGeometryVolume - tf color");
-			gTransformColorProgram.bind();
-			
-			mVertexBuffer->bindForFeedback(0, LLVertexBuffer::TYPE_COLOR, mGeomIndex, mGeomCount);
-
-			S32 val = *((S32*) color.mV);
-
-			gTransformColorProgram.uniform1i(sColorIn, val);
-			glBeginTransformFeedback(GL_POINTS);
-			buff->setBuffer(LLVertexBuffer::MAP_VERTEX);
-			push_for_transform(buff, vf.mNumVertices, mGeomCount);
-			glEndTransformFeedback();
-		}
-
-		if (rebuild_emissive)
-		{
-            LL_PROFILE_ZONE_NAMED_CATEGORY_FACE("getGeometryVolume - tf emissive");
-			gTransformColorProgram.bind();
-			
-			mVertexBuffer->bindForFeedback(0, LLVertexBuffer::TYPE_EMISSIVE, mGeomIndex, mGeomCount);
-
-			U8 glow = (U8) llclamp((S32) (getTextureEntry()->getGlow()*255), 0, 255);
-
-			S32 glow32 = glow |
-						 (glow << 8) |
-						 (glow << 16) |
-						 (glow << 24);
-
-			gTransformColorProgram.uniform1i(sColorIn, glow32);
-			glBeginTransformFeedback(GL_POINTS);
-			buff->setBuffer(LLVertexBuffer::MAP_VERTEX);
-			push_for_transform(buff, vf.mNumVertices, mGeomCount);
-			glEndTransformFeedback();
-		}
-
-		if (rebuild_normal)
-		{
-            LL_PROFILE_ZONE_NAMED_CATEGORY_FACE("getGeometryVolume - tf normal");
-			gTransformNormalProgram.bind();
-			
-			mVertexBuffer->bindForFeedback(0, LLVertexBuffer::TYPE_NORMAL, mGeomIndex, mGeomCount);
-						
-			glBeginTransformFeedback(GL_POINTS);
-			buff->setBuffer(LLVertexBuffer::MAP_NORMAL);
-			push_for_transform(buff, vf.mNumVertices, mGeomCount);
-			glEndTransformFeedback();
-		}
-
-		if (rebuild_tangent)
-		{
-            LL_PROFILE_ZONE_NAMED_CATEGORY_FACE("getGeometryVolume - tf tangent");
-			gTransformTangentProgram.bind();
-			
-			mVertexBuffer->bindForFeedback(0, LLVertexBuffer::TYPE_TANGENT, mGeomIndex, mGeomCount);
-						
-			glBeginTransformFeedback(GL_POINTS);
-			buff->setBuffer(LLVertexBuffer::MAP_TANGENT);
-			push_for_transform(buff, vf.mNumVertices, mGeomCount);
-			glEndTransformFeedback();
-		}
-
-		if (rebuild_tcoord)
-		{
-            LL_PROFILE_ZONE_NAMED_CATEGORY_FACE("getGeometryVolume - tf tcoord");
-			gTransformTexCoordProgram.bind();
-			
-			mVertexBuffer->bindForFeedback(0, LLVertexBuffer::TYPE_TEXCOORD0, mGeomIndex, mGeomCount);
-						
-			glBeginTransformFeedback(GL_POINTS);
-			buff->setBuffer(LLVertexBuffer::MAP_TEXCOORD0);
-			push_for_transform(buff, vf.mNumVertices, mGeomCount);
-			glEndTransformFeedback();
-
-			bool do_bump = bump_code && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_TEXCOORD1);
-
-			if (do_bump)
-			{
-				mVertexBuffer->bindForFeedback(0, LLVertexBuffer::TYPE_TEXCOORD1, mGeomIndex, mGeomCount);
-				glBeginTransformFeedback(GL_POINTS);
-				buff->setBuffer(LLVertexBuffer::MAP_TEXCOORD0);
-				push_for_transform(buff, vf.mNumVertices, mGeomCount);
-				glEndTransformFeedback();
-			}				
-		}
-
-		glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0);
-		gGL.popMatrix();
-
-		if (cur_shader)
-		{
-			cur_shader->bind();
-		}
-	}
-	else
-#endif
 	{
 		//if it's not fullbright and has no normals, bake sunlight based on face normal
 		//bool bake_sunlight = !getTextureEntry()->getFullbright() &&
diff --git a/indra/newview/llface.h b/indra/newview/llface.h
index aa00c9d052630c73c84ba55fffd9516301647468..4778a8110b66663a8796090c9e1d972c0ebd86d9 100644
--- a/indra/newview/llface.h
+++ b/indra/newview/llface.h
@@ -81,8 +81,6 @@ class alignas(16) LLFace
 		PARTICLE		= 0x0080,
 	};
 
-	static void cacheFaceInVRAM(const LLVolumeFace& vf);
-
 public:
 	LLFace(LLDrawable* drawablep, LLViewerObject* objp)
 	{
diff --git a/indra/newview/llfeaturemanager.cpp b/indra/newview/llfeaturemanager.cpp
index 826d4892ef838b686961eeed5ed72d95d0cd2dc1..2c770f6ab82813cd9036069850ba1892316b37d9 100644
--- a/indra/newview/llfeaturemanager.cpp
+++ b/indra/newview/llfeaturemanager.cpp
@@ -431,41 +431,9 @@ bool LLFeatureManager::loadGPUClass()
 		LL_WARNS("RenderInit") << "Unable to get an accurate benchmark; defaulting to class 3" << LL_ENDL;
 		mGPUClass = GPU_CLASS_3;
 	#else
-			if (gGLManager.mGLVersion <= 2.f)
-			{
-				mGPUClass = GPU_CLASS_0;
-			}
-			else if (gGLManager.mGLVersion <= 3.f)
-			{
-				mGPUClass = GPU_CLASS_1;
-			}
-			else if (gGLManager.mGLVersion < 3.3f)
-			{
-				mGPUClass = GPU_CLASS_2;
-			}
-			else if (gGLManager.mGLVersion < 4.f)
-			{
-				mGPUClass = GPU_CLASS_3;
-			}
-			else 
-			{
-				mGPUClass = GPU_CLASS_4;
-			}
-			if (gGLManager.mIsIntel && mGPUClass > GPU_CLASS_1)
-			{
-				// Intels are generally weaker then other GPUs despite having advanced features
-				mGPUClass = (EGPUClass)(mGPUClass - 1);
-			}
+			mGPUClass = GPU_CLASS_2;
 	#endif
 		}
-		else if (gGLManager.mGLVersion <= 2.f)
-		{
-			mGPUClass = GPU_CLASS_0;
-		}
-		else if (gGLManager.mGLVersion <= 3.f)
-		{
-			mGPUClass = GPU_CLASS_1;
-		}
 		else if (gbps <= 5.f)
 		{
 			mGPUClass = GPU_CLASS_0;
@@ -679,10 +647,6 @@ void LLFeatureManager::applyBaseMasks()
 	{
 		maskFeatures("TexUnit8orLess");
 	}
-	if (gGLManager.mHasMapBufferRange)
-	{
-		maskFeatures("MapBufferRange");
-	}
 	if (gGLManager.mVRAM > 512)
 	{
 		maskFeatures("VRAMGT512");
diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp
index 68928e9c8f85166a10152bf86ea349dc4eb6432d..7b01e9050ba21ce52dc4178c380bae59bba2ff72 100644
--- a/indra/newview/llfloaterpreference.cpp
+++ b/indra/newview/llfloaterpreference.cpp
@@ -1198,7 +1198,7 @@ void LLFloaterPreferenceGraphicsAdvanced::refreshEnabledState()
 	LLTextBox* reflections_text = getChild<LLTextBox>("ReflectionsText");
 
 	// Reflections
-    BOOL reflections = gGLManager.mHasCubeMap && LLCubeMap::sUseCubeMaps;
+    BOOL reflections = LLCubeMap::sUseCubeMaps;
 	ctrl_reflections->setEnabled(reflections);
 	reflections_text->setEnabled(reflections);
 
@@ -1227,14 +1227,7 @@ void LLFloaterPreferenceGraphicsAdvanced::refreshEnabledState()
 
 	// Hardware settings
 	
-	if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderVBOEnable") ||
-		!gGLManager.mHasVertexBufferObject)
-	{
-		getChildView("vbo")->setEnabled(FALSE);
-	}
-
-	if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderCompressTextures") ||
-		!gGLManager.mHasVertexBufferObject)
+	if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderCompressTextures"))
 	{
 		getChildView("texture compression")->setEnabled(FALSE);
 	}
diff --git a/indra/newview/llglsandbox.cpp b/indra/newview/llglsandbox.cpp
index d75f3eef6fa4199ca2601fea21b05926970b3072..38ec24cae87a481adc86aa5f7e706f8094783216 100644
--- a/indra/newview/llglsandbox.cpp
+++ b/indra/newview/llglsandbox.cpp
@@ -987,9 +987,8 @@ class ShaderBinder
 //-----------------------------------------------------------------------------
 F32 gpu_benchmark()
 {
-	if (!gGLManager.mHasTimerQuery)
+	if (gGLManager.mGLVersion < 3.3f)
 	{ // don't bother benchmarking venerable drivers which don't support accurate timing anyway
-      // and are likely to be correctly identified by the GPU table already.
 		return -1.f;
 	}
 
@@ -1115,16 +1114,6 @@ F32 gpu_benchmark()
 	// ensure matched pair of bind() and unbind() calls
 	ShaderBinder binder(gBenchmarkProgram);
 
-#ifdef GL_ARB_vertex_array_object
-    U32 glarray = 0;
-
-    if (LLRender::sGLCoreProfile)
-    {
-        glGenVertexArrays(1, &glarray);
-        glBindVertexArray(glarray);
-    }
-#endif
-
 	buff->setBuffer(LLVertexBuffer::MAP_VERTEX);
 	glFinish();
 
@@ -1157,15 +1146,6 @@ F32 gpu_benchmark()
 		}
 	}
 
-#ifdef GL_ARB_vertex_array_object
-    if (LLRender::sGLCoreProfile)
-    {
-        glBindVertexArray(0);
-        glDeleteVertexArrays(1, &glarray);
-    }
-#endif
-
-
 	std::sort(results.begin(), results.end());
 
 	F32 gbps = results[results.size()/2];
diff --git a/indra/newview/llscenemonitor.cpp b/indra/newview/llscenemonitor.cpp
index 6a2f53aa42a250e2c5cdf1c02d7f93d7c762adce..49d5aa3e14d1275af400fbdd729dd276b449f9ff 100644
--- a/indra/newview/llscenemonitor.cpp
+++ b/indra/newview/llscenemonitor.cpp
@@ -445,14 +445,14 @@ void LLSceneMonitor::calcDiffAggregate()
 
 	if(mDiffState == EXECUTE_DIFF)
 	{
-		glBeginQuery(GL_SAMPLES_PASSED_ARB, mQueryObject);
+		glBeginQuery(GL_SAMPLES_PASSED, mQueryObject);
 	}
 
 	gl_draw_scaled_target(0, 0, S32(mDiff->getWidth() * mDiffPixelRatio), S32(mDiff->getHeight() * mDiffPixelRatio), mDiff);
 
 	if(mDiffState == EXECUTE_DIFF)
 	{
-		glEndQuery(GL_SAMPLES_PASSED_ARB);
+		glEndQuery(GL_SAMPLES_PASSED);
 		mDiffState = WAIT_ON_RESULT;
 	}
 		
@@ -483,11 +483,11 @@ void LLSceneMonitor::fetchQueryResult()
 		mDiffState = WAITING_FOR_NEXT_DIFF;
 
 		GLuint available = 0;
-		glGetQueryObjectuiv(mQueryObject, GL_QUERY_RESULT_AVAILABLE_ARB, &available);
+		glGetQueryObjectuiv(mQueryObject, GL_QUERY_RESULT_AVAILABLE, &available);
 		if(available)
 		{
 			GLuint count = 0;
-			glGetQueryObjectuiv(mQueryObject, GL_QUERY_RESULT_ARB, &count);
+			glGetQueryObjectuiv(mQueryObject, GL_QUERY_RESULT, &count);
 	
 			mDiffResult = sqrtf(count * 0.5f / (mDiff->getWidth() * mDiff->getHeight() * mDiffPixelRatio * mDiffPixelRatio)); //0.5 -> (front face + back face)
 
diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp
index 9682945208c158226f385e86912056b1ae99f2f6..2413d7705ae7fa9fa9933e26e3ae16a3e2e73c24 100644
--- a/indra/newview/llviewercontrol.cpp
+++ b/indra/newview/llviewercontrol.cpp
@@ -381,7 +381,7 @@ static bool handleJoystickChanged(const LLSD& newvalue)
 
 static bool handleUseOcclusionChanged(const LLSD& newvalue)
 {
-	LLPipeline::sUseOcclusion = (newvalue.asBoolean() && gGLManager.mHasOcclusionQuery
+	LLPipeline::sUseOcclusion = (newvalue.asBoolean()
 		&& LLFeatureManager::getInstance()->isFeatureAvailable("UseOcclusion") && !gUseWireframe) ? 2 : 0;
 	return true;
 }
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index dd82d43ab2477bf2be9505e184aec2d95150396c..f10cb329a9c01d75859f1c8b1594a4a8f33a45eb 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -2309,44 +2309,6 @@ class LLAdvancedCheckViewAdminOptions : public view_listener_t
 	}
 };
 
-/////////////////////////////////////
-// Enable Object Object Occlusion ///
-/////////////////////////////////////
-class LLAdvancedEnableObjectObjectOcclusion: public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-	
-		bool new_value = gGLManager.mHasOcclusionQuery; // && LLFeatureManager::getInstance()->isFeatureAvailable(userdata.asString());
-		return new_value;
-}
-};
-
-/////////////////////////////////////
-// Enable Framebuffer Objects	  ///
-/////////////////////////////////////
-class LLAdvancedEnableRenderFBO: public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		bool new_value = gGLManager.mHasFramebufferObject;
-		return new_value;
-	}
-};
-
-/////////////////////////////////////
-// Enable Deferred Rendering	  ///
-/////////////////////////////////////
-class LLAdvancedEnableRenderDeferred: public view_listener_t
-{
-	bool handleEvent(const LLSD& userdata)
-	{
-		bool new_value = gGLManager.mHasFramebufferObject && LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_WINDLIGHT) > 1 &&
-			LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_AVATAR) > 0;
-		return new_value;
-	}
-};
-
 //////////////////
 // ADMIN STATUS //
 //////////////////
@@ -9367,8 +9329,6 @@ void initialize_menus()
 	view_listener_t::addMenu(new LLAdvancedToggleWireframe(), "Advanced.ToggleWireframe");
 	view_listener_t::addMenu(new LLAdvancedCheckWireframe(), "Advanced.CheckWireframe");
 	// Develop > Render
-	view_listener_t::addMenu(new LLAdvancedEnableObjectObjectOcclusion(), "Advanced.EnableObjectObjectOcclusion");
-	
 	view_listener_t::addMenu(new LLAdvancedToggleRandomizeFramerate(), "Advanced.ToggleRandomizeFramerate");
 	view_listener_t::addMenu(new LLAdvancedCheckRandomizeFramerate(), "Advanced.CheckRandomizeFramerate");
 	view_listener_t::addMenu(new LLAdvancedTogglePeriodicSlowFrame(), "Advanced.TogglePeriodicSlowFrame");
diff --git a/indra/newview/llvieweroctree.cpp b/indra/newview/llvieweroctree.cpp
index c785c80cea290acbe846672b4594c2cd4391510e..a75eb518f341da52086d17ae63cbe5e3e4b6d89f 100644
--- a/indra/newview/llvieweroctree.cpp
+++ b/indra/newview/llvieweroctree.cpp
@@ -917,15 +917,12 @@ void LLOcclusionCullingGroup::handleChildAddition(const OctreeNode* parent, Octr
 
 void LLOcclusionCullingGroup::releaseOcclusionQueryObjectNames()
 {
-	if (gGLManager.mHasOcclusionQuery)
+	for (U32 i = 0; i < LLViewerCamera::NUM_CAMERAS; ++i)
 	{
-		for (U32 i = 0; i < LLViewerCamera::NUM_CAMERAS; ++i)
+		if (mOcclusionQuery[i])
 		{
-			if (mOcclusionQuery[i])
-			{
-				releaseOcclusionQueryObjectName(mOcclusionQuery[i]);
-				mOcclusionQuery[i] = 0;
-			}
+			releaseOcclusionQueryObjectName(mOcclusionQuery[i]);
+			mOcclusionQuery[i] = 0;
 		}
 	}
 }
@@ -1129,7 +1126,7 @@ void LLOcclusionCullingGroup::checkOcclusion()
             GLuint available;
             {
                 LL_PROFILE_ZONE_NAMED_CATEGORY_OCTREE("co - query available");
-                glGetQueryObjectuiv(mOcclusionQuery[LLViewerCamera::sCurCameraID], GL_QUERY_RESULT_AVAILABLE_ARB, &available);
+                glGetQueryObjectuiv(mOcclusionQuery[LLViewerCamera::sCurCameraID], GL_QUERY_RESULT_AVAILABLE, &available);
             }
 
             if (available)
@@ -1137,7 +1134,7 @@ void LLOcclusionCullingGroup::checkOcclusion()
                 GLuint query_result;    // Will be # samples drawn, or a boolean depending on mHasOcclusionQuery2 (both are type GLuint)
                 {
                     LL_PROFILE_ZONE_NAMED_CATEGORY_OCTREE("co - query result");
-                    glGetQueryObjectuiv(mOcclusionQuery[LLViewerCamera::sCurCameraID], GL_QUERY_RESULT_ARB, &query_result);
+                    glGetQueryObjectuiv(mOcclusionQuery[LLViewerCamera::sCurCameraID], GL_QUERY_RESULT, &query_result);
                 }
 #if LL_TRACK_PENDING_OCCLUSION_QUERIES
                 sPendingQueries.erase(mOcclusionQuery[LLViewerCamera::sCurCameraID]);
@@ -1197,7 +1194,6 @@ void LLOcclusionCullingGroup::doOcclusion(LLCamera* camera, const LLVector4a* sh
 			OCCLUSION_FUDGE_Z = 1.;
 		}
 
-		// Don't cull hole/edge water, unless we have the GL_ARB_depth_clamp extension
 		if (earlyFail(camera, bounds))
 		{
             LL_PROFILE_ZONE_NAMED_CATEGORY_OCTREE("doOcclusion - early fail");
@@ -1221,17 +1217,12 @@ void LLOcclusionCullingGroup::doOcclusion(LLCamera* camera, const LLVector4a* sh
 					// Depth clamp all water to avoid it being culled as a result of being
 					// behind the far clip plane, and in the case of edge water to avoid
 					// it being culled while still visible.
-					bool const use_depth_clamp = gGLManager.mHasDepthClamp &&
-												(mSpatialPartition->mDrawableType == LLPipeline::RENDER_TYPE_WATER ||
+					bool const use_depth_clamp = (mSpatialPartition->mDrawableType == LLPipeline::RENDER_TYPE_WATER ||
 												mSpatialPartition->mDrawableType == LLPipeline::RENDER_TYPE_VOIDWATER);
 
-					LLGLEnable clamp(use_depth_clamp ? GL_DEPTH_CLAMP : 0);				
+					LLGLEnable clamp(use_depth_clamp ? GL_DEPTH_CLAMP : 0);
 						
-#if !LL_DARWIN					
-					U32 mode = gGLManager.mHasOcclusionQuery2 ? GL_ANY_SAMPLES_PASSED : GL_SAMPLES_PASSED_ARB;
-#else
-					U32 mode = GL_SAMPLES_PASSED_ARB;
-#endif
+					U32 mode = gGLManager.mGLVersion >= 3.3f ? GL_ANY_SAMPLES_PASSED : GL_SAMPLES_PASSED;
 					
 #if LL_TRACK_PENDING_OCCLUSION_QUERIES
 					sPendingQueries.insert(mOcclusionQuery[LLViewerCamera::sCurCameraID]);
diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp
index 2ebe0f826f4114a972b01a15e7c118c0ef882ca3..296a383ed0d6a0d40a154f5735eef8294a55b325 100644
--- a/indra/newview/llviewershadermgr.cpp
+++ b/indra/newview/llviewershadermgr.cpp
@@ -70,13 +70,6 @@ bool				LLViewerShaderMgr::sSkipReload = false;
 
 LLVector4			gShinyOrigin;
 
-//transform shaders
-LLGLSLShader			gTransformPositionProgram;
-LLGLSLShader			gTransformTexCoordProgram;
-LLGLSLShader			gTransformNormalProgram;
-LLGLSLShader			gTransformColorProgram;
-LLGLSLShader			gTransformTangentProgram;
-
 //utility shaders
 LLGLSLShader	gOcclusionProgram;
 LLGLSLShader    gSkinnedOcclusionProgram;
@@ -469,7 +462,7 @@ void LLViewerShaderMgr::setShaders()
     initAttribsAndUniforms();
     gPipeline.releaseGLBuffers();
 
-    LLPipeline::sWaterReflections = gGLManager.mHasCubeMap && LLPipeline::sRenderTransparentWater;
+    LLPipeline::sWaterReflections = LLPipeline::sRenderTransparentWater;
     LLPipeline::sRenderGlow = gSavedSettings.getBOOL("RenderGlow"); 
     LLPipeline::updateRenderDeferred();
     
@@ -513,13 +506,6 @@ void LLViewerShaderMgr::setShaders()
     S32 wl_class = 1;
     S32 water_class = 2;
     S32 deferred_class = 0;
-    S32 transform_class = gGLManager.mHasTransformFeedback ? 1 : 0;
-
-    static LLCachedControl<bool> use_transform_feedback(gSavedSettings, "RenderUseTransformFeedback", false);
-    if (!use_transform_feedback)
-    {
-        transform_class = 0;
-    }
 
     if (useRenderDeferred)
     {
@@ -572,7 +558,6 @@ void LLViewerShaderMgr::setShaders()
     mShaderLevel[SHADER_EFFECT] = effect_class;
     mShaderLevel[SHADER_WINDLIGHT] = wl_class;
     mShaderLevel[SHADER_DEFERRED] = deferred_class;
-    mShaderLevel[SHADER_TRANSFORM] = transform_class;
 
     std::string shader_name = loadBasicShaders();
     if (shader_name.empty())
@@ -657,20 +642,6 @@ void LLViewerShaderMgr::setShaders()
         }
     }
 
-    if (loaded)
-    {
-        loaded = loadTransformShaders();
-        if (loaded)
-        {
-            LL_INFOS() << "Loaded transform shaders." << LL_ENDL;
-        }
-        else
-        {
-            LL_WARNS() << "Failed to load transform shaders." << LL_ENDL;
-            llassert(loaded);
-        }
-    }
-
     if (loaded)
     {
         // Load max avatar shaders to set the max level
@@ -816,12 +787,6 @@ void LLViewerShaderMgr::unloadShaders()
 	gDeferredSkinnedDiffuseProgram.unload();
 	gDeferredSkinnedBumpProgram.unload();
 	
-	gTransformPositionProgram.unload();
-	gTransformTexCoordProgram.unload();
-	gTransformNormalProgram.unload();
-	gTransformColorProgram.unload();
-	gTransformTangentProgram.unload();
-
 	mShaderLevel[SHADER_LIGHTING] = 0;
 	mShaderLevel[SHADER_OBJECT] = 0;
 	mShaderLevel[SHADER_AVATAR] = 0;
@@ -830,7 +795,6 @@ void LLViewerShaderMgr::unloadShaders()
 	mShaderLevel[SHADER_INTERFACE] = 0;
 	mShaderLevel[SHADER_EFFECT] = 0;
 	mShaderLevel[SHADER_WINDLIGHT] = 0;
-	mShaderLevel[SHADER_TRANSFORM] = 0;
 
 	gPipeline.mShadersLoaded = false;
 }
@@ -1643,8 +1607,8 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
         shader->mFeatures.hasReflectionProbes = mShaderLevel[SHADER_DEFERRED];
 
         shader->mShaderFiles.clear();
-        shader->mShaderFiles.push_back(make_pair("deferred/pbralphaV.glsl", GL_VERTEX_SHADER_ARB));
-        shader->mShaderFiles.push_back(make_pair("deferred/pbralphaF.glsl", GL_FRAGMENT_SHADER_ARB));
+        shader->mShaderFiles.push_back(make_pair("deferred/pbralphaV.glsl", GL_VERTEX_SHADER));
+        shader->mShaderFiles.push_back(make_pair("deferred/pbralphaF.glsl", GL_FRAGMENT_SHADER));
 
         shader->clearPermutations();
 
@@ -2437,10 +2401,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 		gDeferredShadowProgram.mShaderFiles.push_back(make_pair("deferred/shadowV.glsl", GL_VERTEX_SHADER));
 		gDeferredShadowProgram.mShaderFiles.push_back(make_pair("deferred/shadowF.glsl", GL_FRAGMENT_SHADER));
 		gDeferredShadowProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
-		if (gGLManager.mHasDepthClamp)
-		{
-			gDeferredShadowProgram.addPermutation("DEPTH_CLAMP", "1");
-		}
+		// gDeferredShadowProgram.addPermutation("DEPTH_CLAMP", "1"); // disable depth clamp for now
         gDeferredShadowProgram.mRiggedVariant = &gDeferredSkinnedShadowProgram;
 		success = gDeferredShadowProgram.createShader(NULL, NULL);
 		llassert(success);
@@ -2456,10 +2417,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
         gDeferredSkinnedShadowProgram.mShaderFiles.push_back(make_pair("deferred/shadowSkinnedV.glsl", GL_VERTEX_SHADER));
         gDeferredSkinnedShadowProgram.mShaderFiles.push_back(make_pair("deferred/shadowF.glsl", GL_FRAGMENT_SHADER));
         gDeferredSkinnedShadowProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
-        if (gGLManager.mHasDepthClamp)
-        {
-            gDeferredSkinnedShadowProgram.addPermutation("DEPTH_CLAMP", "1");
-        }
+        // gDeferredSkinnedShadowProgram.addPermutation("DEPTH_CLAMP", "1"); // disable depth clamp for now
         success = gDeferredSkinnedShadowProgram.createShader(NULL, NULL);
         llassert(success);
     }
@@ -2472,10 +2430,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 		gDeferredShadowCubeProgram.mShaderFiles.clear();
 		gDeferredShadowCubeProgram.mShaderFiles.push_back(make_pair("deferred/shadowCubeV.glsl", GL_VERTEX_SHADER));
 		gDeferredShadowCubeProgram.mShaderFiles.push_back(make_pair("deferred/shadowF.glsl", GL_FRAGMENT_SHADER));
-		if (gGLManager.mHasDepthClamp)
-		{
-			gDeferredShadowCubeProgram.addPermutation("DEPTH_CLAMP", "1");
-		}
+		// gDeferredShadowCubeProgram.addPermutation("DEPTH_CLAMP", "1");
 		gDeferredShadowCubeProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
 		success = gDeferredShadowCubeProgram.createShader(NULL, NULL);
 		llassert(success);
@@ -2491,10 +2446,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 		gDeferredShadowFullbrightAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/shadowAlphaMaskF.glsl", GL_FRAGMENT_SHADER));
 
         gDeferredShadowFullbrightAlphaMaskProgram.clearPermutations();
-		if (gGLManager.mHasDepthClamp)
-		{
-			gDeferredShadowFullbrightAlphaMaskProgram.addPermutation("DEPTH_CLAMP", "1");
-		}
+		gDeferredShadowFullbrightAlphaMaskProgram.addPermutation("DEPTH_CLAMP", "1");
         gDeferredShadowFullbrightAlphaMaskProgram.addPermutation("IS_FULLBRIGHT", "1");
 		gDeferredShadowFullbrightAlphaMaskProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
         gDeferredShadowFullbrightAlphaMaskProgram.mRiggedVariant = &gDeferredSkinnedShadowFullbrightAlphaMaskProgram;
@@ -2512,10 +2464,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
         gDeferredSkinnedShadowFullbrightAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/shadowAlphaMaskF.glsl", GL_FRAGMENT_SHADER));
 
         gDeferredSkinnedShadowFullbrightAlphaMaskProgram.clearPermutations();
-        if (gGLManager.mHasDepthClamp)
-        {
-            gDeferredSkinnedShadowFullbrightAlphaMaskProgram.addPermutation("DEPTH_CLAMP", "1");
-        }
+        gDeferredSkinnedShadowFullbrightAlphaMaskProgram.addPermutation("DEPTH_CLAMP", "1");
         gDeferredSkinnedShadowFullbrightAlphaMaskProgram.addPermutation("IS_FULLBRIGHT", "1");
         gDeferredSkinnedShadowFullbrightAlphaMaskProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
         success = gDeferredSkinnedShadowFullbrightAlphaMaskProgram.createShader(NULL, NULL);
@@ -2530,10 +2479,6 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 		gDeferredShadowAlphaMaskProgram.mShaderFiles.clear();
 		gDeferredShadowAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/shadowAlphaMaskV.glsl", GL_VERTEX_SHADER));
 		gDeferredShadowAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/shadowAlphaMaskF.glsl", GL_FRAGMENT_SHADER));
-		if (gGLManager.mHasDepthClamp)
-		{
-			gDeferredShadowAlphaMaskProgram.addPermutation("DEPTH_CLAMP", "1");
-		}
 		gDeferredShadowAlphaMaskProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
         gDeferredShadowAlphaMaskProgram.mRiggedVariant = &gDeferredSkinnedShadowAlphaMaskProgram;
 		success = gDeferredShadowAlphaMaskProgram.createShader(NULL, NULL);
@@ -2548,10 +2493,6 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
         gDeferredSkinnedShadowAlphaMaskProgram.mShaderFiles.clear();
         gDeferredSkinnedShadowAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/shadowAlphaMaskSkinnedV.glsl", GL_VERTEX_SHADER));
         gDeferredSkinnedShadowAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/shadowAlphaMaskF.glsl", GL_FRAGMENT_SHADER));
-        if (gGLManager.mHasDepthClamp)
-        {
-            gDeferredSkinnedShadowAlphaMaskProgram.addPermutation("DEPTH_CLAMP", "1");
-        }
         gDeferredSkinnedShadowAlphaMaskProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
         success = gDeferredSkinnedShadowAlphaMaskProgram.createShader(NULL, NULL);
         llassert(success);
@@ -2565,10 +2506,6 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 		gDeferredAvatarShadowProgram.mShaderFiles.clear();
 		gDeferredAvatarShadowProgram.mShaderFiles.push_back(make_pair("deferred/avatarShadowV.glsl", GL_VERTEX_SHADER));
 		gDeferredAvatarShadowProgram.mShaderFiles.push_back(make_pair("deferred/avatarShadowF.glsl", GL_FRAGMENT_SHADER));
-		if (gGLManager.mHasDepthClamp)
-		{
-			gDeferredAvatarShadowProgram.addPermutation("DEPTH_CLAMP", "1");
-		}
 		gDeferredAvatarShadowProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
 		success = gDeferredAvatarShadowProgram.createShader(NULL, NULL);
 		llassert(success);
@@ -2581,7 +2518,6 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 		gDeferredAvatarAlphaShadowProgram.mShaderFiles.clear();
 		gDeferredAvatarAlphaShadowProgram.mShaderFiles.push_back(make_pair("deferred/avatarAlphaShadowV.glsl", GL_VERTEX_SHADER));
 		gDeferredAvatarAlphaShadowProgram.mShaderFiles.push_back(make_pair("deferred/avatarAlphaShadowF.glsl", GL_FRAGMENT_SHADER));
-		gDeferredAvatarAlphaShadowProgram.addPermutation("DEPTH_CLAMP", gGLManager.mHasDepthClamp ? "1" : "0");
 		gDeferredAvatarAlphaShadowProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
 		success = gDeferredAvatarAlphaShadowProgram.createShader(NULL, NULL);
         llassert(success);
@@ -2594,7 +2530,6 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 		gDeferredAvatarAlphaMaskShadowProgram.mShaderFiles.clear();
 		gDeferredAvatarAlphaMaskShadowProgram.mShaderFiles.push_back(make_pair("deferred/avatarAlphaShadowV.glsl", GL_VERTEX_SHADER));
 		gDeferredAvatarAlphaMaskShadowProgram.mShaderFiles.push_back(make_pair("deferred/avatarAlphaMaskShadowF.glsl", GL_FRAGMENT_SHADER));
-		gDeferredAvatarAlphaMaskShadowProgram.addPermutation("DEPTH_CLAMP", gGLManager.mHasDepthClamp ? "1" : "0");
 		gDeferredAvatarAlphaMaskShadowProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
 		success = gDeferredAvatarAlphaMaskShadowProgram.createShader(NULL, NULL);
         llassert(success);
@@ -2608,10 +2543,6 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 		gDeferredAttachmentShadowProgram.mShaderFiles.clear();
 		gDeferredAttachmentShadowProgram.mShaderFiles.push_back(make_pair("deferred/attachmentShadowV.glsl", GL_VERTEX_SHADER));
 		gDeferredAttachmentShadowProgram.mShaderFiles.push_back(make_pair("deferred/attachmentShadowF.glsl", GL_FRAGMENT_SHADER));
-		if (gGLManager.mHasDepthClamp)
-		{
-			gDeferredAttachmentShadowProgram.addPermutation("DEPTH_CLAMP", "1");
-		}
 		gDeferredAttachmentShadowProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
 		success = gDeferredAttachmentShadowProgram.createShader(NULL, NULL);
 		llassert(success);
@@ -2624,7 +2555,6 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 		gDeferredAttachmentAlphaShadowProgram.mShaderFiles.clear();
 		gDeferredAttachmentAlphaShadowProgram.mShaderFiles.push_back(make_pair("deferred/attachmentAlphaShadowV.glsl", GL_VERTEX_SHADER));
 		gDeferredAttachmentAlphaShadowProgram.mShaderFiles.push_back(make_pair("deferred/attachmentAlphaShadowF.glsl", GL_FRAGMENT_SHADER));
-		gDeferredAttachmentAlphaShadowProgram.addPermutation("DEPTH_CLAMP", gGLManager.mHasDepthClamp ? "1" : "0");
 		gDeferredAttachmentAlphaShadowProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
 		success = gDeferredAttachmentAlphaShadowProgram.createShader(NULL, NULL);
         llassert(success);
@@ -2637,7 +2567,6 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 		gDeferredAttachmentAlphaMaskShadowProgram.mShaderFiles.clear();
 		gDeferredAttachmentAlphaMaskShadowProgram.mShaderFiles.push_back(make_pair("deferred/attachmentAlphaShadowV.glsl", GL_VERTEX_SHADER));
 		gDeferredAttachmentAlphaMaskShadowProgram.mShaderFiles.push_back(make_pair("deferred/attachmentAlphaMaskShadowF.glsl", GL_FRAGMENT_SHADER));
-		gDeferredAttachmentAlphaMaskShadowProgram.addPermutation("DEPTH_CLAMP", gGLManager.mHasDepthClamp ? "1" : "0");
 		gDeferredAttachmentAlphaMaskShadowProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
 		success = gDeferredAttachmentAlphaMaskShadowProgram.createShader(NULL, NULL);
         llassert(success);
@@ -3976,95 +3905,6 @@ BOOL LLViewerShaderMgr::loadShadersWindLight()
 	return success;
 }
 
-BOOL LLViewerShaderMgr::loadTransformShaders()
-{
-	BOOL success = TRUE;
-	
-	if (mShaderLevel[SHADER_TRANSFORM] < 1)
-	{
-		gTransformPositionProgram.unload();
-		gTransformTexCoordProgram.unload();
-		gTransformNormalProgram.unload();
-		gTransformColorProgram.unload();
-		gTransformTangentProgram.unload();
-		return TRUE;
-	}
-
-	if (success)
-	{
-        gTransformPositionProgram.mName = "Position Transform Shader";
-		gTransformPositionProgram.mShaderFiles.clear();
-		gTransformPositionProgram.mShaderFiles.push_back(make_pair("transform/positionV.glsl", GL_VERTEX_SHADER));
-		gTransformPositionProgram.mShaderLevel = mShaderLevel[SHADER_TRANSFORM];
-
-		const char* varyings[] = {
-			"position_out",
-			"texture_index_out",
-		};
-	
-		success = gTransformPositionProgram.createShader(NULL, NULL, 2, varyings);
-	}
-
-	if (success)
-	{
-		gTransformTexCoordProgram.mName = "TexCoord Transform Shader";
-		gTransformTexCoordProgram.mShaderFiles.clear();
-		gTransformTexCoordProgram.mShaderFiles.push_back(make_pair("transform/texcoordV.glsl", GL_VERTEX_SHADER));
-		gTransformTexCoordProgram.mShaderLevel = mShaderLevel[SHADER_TRANSFORM];
-
-		const char* varyings[] = {
-			"texcoord_out",
-		};
-	
-		success = gTransformTexCoordProgram.createShader(NULL, NULL, 1, varyings);
-	}
-
-	if (success)
-	{
-		gTransformNormalProgram.mName = "Normal Transform Shader";
-		gTransformNormalProgram.mShaderFiles.clear();
-		gTransformNormalProgram.mShaderFiles.push_back(make_pair("transform/normalV.glsl", GL_VERTEX_SHADER));
-		gTransformNormalProgram.mShaderLevel = mShaderLevel[SHADER_TRANSFORM];
-
-		const char* varyings[] = {
-			"normal_out",
-		};
-	
-		success = gTransformNormalProgram.createShader(NULL, NULL, 1, varyings);
-	}
-
-	if (success)
-	{
-		gTransformColorProgram.mName = "Color Transform Shader";
-		gTransformColorProgram.mShaderFiles.clear();
-		gTransformColorProgram.mShaderFiles.push_back(make_pair("transform/colorV.glsl", GL_VERTEX_SHADER));
-		gTransformColorProgram.mShaderLevel = mShaderLevel[SHADER_TRANSFORM];
-
-		const char* varyings[] = {
-			"color_out",
-		};
-	
-		success = gTransformColorProgram.createShader(NULL, NULL, 1, varyings);
-	}
-
-	if (success)
-	{
-		gTransformTangentProgram.mName = "Binormal Transform Shader";
-		gTransformTangentProgram.mShaderFiles.clear();
-		gTransformTangentProgram.mShaderFiles.push_back(make_pair("transform/binormalV.glsl", GL_VERTEX_SHADER));
-        gTransformTangentProgram.mShaderLevel = mShaderLevel[SHADER_TRANSFORM];
-
-		const char* varyings[] = {
-			"tangent_out",
-		};
-	
-		success = gTransformTangentProgram.createShader(NULL, NULL, 1, varyings);
-	}
-
-	
-	return success;
-}
-
 std::string LLViewerShaderMgr::getShaderDirPrefix(void)
 {
 	return gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "shaders/class");
diff --git a/indra/newview/llviewershadermgr.h b/indra/newview/llviewershadermgr.h
index 19d8e87d6601b897e43ad7fd3254051db15f9395..464efd6e3fde6d3ac4f5555db6cdc00847b92a48 100644
--- a/indra/newview/llviewershadermgr.h
+++ b/indra/newview/llviewershadermgr.h
@@ -62,7 +62,6 @@ class LLViewerShaderMgr: public LLShaderMgr
 	BOOL loadShadersWater();
 	BOOL loadShadersInterface();
 	BOOL loadShadersWindLight();
-	BOOL loadTransformShaders();
 
 	std::vector<S32> mShaderLevel;
 	S32	mMaxAvatarShaderLevel;
@@ -78,7 +77,6 @@ class LLViewerShaderMgr: public LLShaderMgr
 		SHADER_WINDLIGHT,
 		SHADER_WATER,
 		SHADER_DEFERRED,
-		SHADER_TRANSFORM,
 		SHADER_COUNT
 	};
 
@@ -150,15 +148,6 @@ inline bool operator != (LLViewerShaderMgr::shader_iter const & a, LLViewerShade
 
 extern LLVector4			gShinyOrigin;
 
-//transform shaders
-extern LLGLSLShader			gTransformPositionProgram;
-extern LLGLSLShader			gTransformTexCoordProgram;
-extern LLGLSLShader			gTransformNormalProgram;
-extern LLGLSLShader			gTransformColorProgram;
-extern LLGLSLShader			gTransformTangentProgram;
-
-
-
 //utility shaders
 extern LLGLSLShader			gOcclusionProgram;
 extern LLGLSLShader			gOcclusionCubeProgram;
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index e9815a7872a18a1778a0a417b1d01d35a5781be0..5474098d168a9c0a7202f0011aa889a370e6f198 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -597,29 +597,6 @@ class LLDebugText
 		{
 			LLTrace::Recording& last_frame_recording = LLTrace::get_frame_recording().getLastRecording();
 
-			if (gGLManager.mHasATIMemInfo)
-			{
-				S32 meminfo[4];
-				glGetIntegerv(GL_TEXTURE_FREE_MEMORY_ATI, meminfo);
-
-				addText(xpos, ypos, llformat("%.2f MB Texture Memory Free", meminfo[0]/1024.f));
-				ypos += y_inc;
-
-				if (gGLManager.mHasVertexBufferObject)
-				{
-					glGetIntegerv(GL_VBO_FREE_MEMORY_ATI, meminfo);
-					addText(xpos, ypos, llformat("%.2f MB VBO Memory Free", meminfo[0]/1024.f));
-					ypos += y_inc;
-				}
-			}
-			else if (gGLManager.mHasNVXMemInfo)
-			{
-				S32 free_memory;
-				glGetIntegerv(GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX, &free_memory);
-				addText(xpos, ypos, llformat("%.2f MB Video Memory Free", free_memory/1024.f));
-				ypos += y_inc;
-			}
-
 			//show streaming cost/triangle count of known prims in current region OR selection
 			{
 				F32 cost = 0.f;
@@ -1979,11 +1956,6 @@ LLViewerWindow::LLViewerWindow(const Params& p)
 	LL_DEBUGS("Window") << "Loading feature tables." << LL_ENDL;
 
 	// Initialize OpenGL Renderer
-	if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderVBOEnable") ||
-		!gGLManager.mHasVertexBufferObject)
-	{
-		gSavedSettings.setBOOL("RenderVBOEnable", FALSE);
-	}
 	LLVertexBuffer::initClass(gSavedSettings.getBOOL("RenderVBOEnable"), gSavedSettings.getBOOL("RenderVBOMappingDisable"));
 	LL_INFOS("RenderInit") << "LLVertexBuffer initialization done." << LL_ENDL ;
 	gGL.init() ;
@@ -1997,11 +1969,6 @@ LLViewerWindow::LLViewerWindow(const Params& p)
 		gSavedSettings.setBOOL("ProbeHardwareOnStartup", FALSE);
 	}
 
-	if (!gGLManager.mHasDepthClamp)
-	{
-		LL_INFOS("RenderInit") << "Missing feature GL_ARB_depth_clamp. Void water might disappear in rare cases." << LL_ENDL;
-	}
-	
 	// If we crashed while initializng GL stuff last time, disable certain features
 	if (gSavedSettings.getBOOL("RenderInitError"))
 	{
diff --git a/indra/newview/llvosky.cpp b/indra/newview/llvosky.cpp
index b7a5a0667b228fea7026edecdb0d29c26ba20751..9f43fb9b8215f00fc06277952606fe08cb263e20 100644
--- a/indra/newview/llvosky.cpp
+++ b/indra/newview/llvosky.cpp
@@ -531,7 +531,7 @@ void LLVOSky::initCubeMap()
 		images.push_back(mShinyTex[side].getImageRaw());
 	}
 
-	if (!mCubeMap && gSavedSettings.getBOOL("RenderWater") && gGLManager.mHasCubeMap && LLCubeMap::sUseCubeMaps)
+	if (!mCubeMap && gSavedSettings.getBOOL("RenderWater") && LLCubeMap::sUseCubeMaps)
 	{
         mCubeMap = new LLCubeMap(false);
 	}
@@ -576,7 +576,7 @@ void LLVOSky::restoreGL()
 
 	updateDirections(psky);
 
-	if (gSavedSettings.getBOOL("RenderWater") && gGLManager.mHasCubeMap && LLCubeMap::sUseCubeMaps)
+	if (gSavedSettings.getBOOL("RenderWater") && LLCubeMap::sUseCubeMaps)
 	{
 		initCubeMap();
 	}
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index 61589640fef0a366b4f40a42544a791bba307e35..ad1711d3fb05c149e5b3fb2070fefdc6a6206589 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -1121,27 +1121,7 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams &params_in, const S32 detail, bo
 			}
 		}
 
-		static LLCachedControl<bool> use_transform_feedback(gSavedSettings, "RenderUseTransformFeedback", false);
-
-		bool cache_in_vram = use_transform_feedback && gTransformPositionProgram.mProgramObject &&
-			(!mVolumeImpl || !mVolumeImpl->isVolumeUnique());
-
-		if (cache_in_vram)
-		{ //this volume might be used as source data for a transform object, put it in vram
-			LLVolume* volume = getVolume();
-			for (S32 i = 0; i < volume->getNumFaces(); ++i)
-			{
-				const LLVolumeFace& face = volume->getVolumeFace(i);
-				if (face.mVertexBuffer.notNull())
-				{ //already cached
-					break;
-				}
-				volume->genTangents(i);
-				LLFace::cacheFaceInVRAM(face);
-			}
-		}
-
-		return TRUE;
+        return TRUE;
 	}
 	else if (NO_LOD == lod) 
 	{
@@ -6417,16 +6397,6 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace
 	U32 geometryBytes = 0;
 	U32 buffer_usage = group->mBufferUsage;
 	
-	static LLCachedControl<bool> use_transform_feedback(gSavedSettings, "RenderUseTransformFeedback", false);
-
-	if (use_transform_feedback &&
-		gTransformPositionProgram.mProgramObject && //transform shaders are loaded
-		buffer_usage == GL_DYNAMIC_DRAW && //target buffer is in VRAM
-		!(mask & LLVertexBuffer::MAP_WEIGHT4)) //TODO: add support for weights
-	{
-		buffer_usage = GL_DYNAMIC_COPY;
-	}
-
 #if LL_DARWIN
 	// HACK from Leslie:
 	// Disable VBO usage for alpha on Mac OS X because it kills the framerate
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index 858cc90d047df825d5028ce2d0988875d341c045..f8ab68e57d75e097b215e2cc1a3849a0b1b28353 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -892,16 +892,7 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples)
 		if (!mRT->occlusionDepth.allocate(resX/occlusion_divisor, resY/occlusion_divisor, 0, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE, samples)) return false;
 		if (!addDeferredAttachments(mRT->deferredScreen)) return false;
 	
-		GLuint screenFormat = GL_RGBA16;
-		if (gGLManager.mIsAMD)
-		{
-			screenFormat = GL_RGBA12;
-		}
-
-		if (gGLManager.mGLVersion < 4.f && gGLManager.mIsNVIDIA)
-		{
-			screenFormat = GL_RGBA16F_ARB;
-		}
+		GLuint screenFormat = GL_RGBA;
         
 		if (!mRT->screen.allocate(resX, resY, screenFormat, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE, samples)) return false;
 		if (samples > 0)
@@ -1065,8 +1056,7 @@ void LLPipeline::refreshCachedSettings()
 	LLPipeline::sUseOcclusion = 
 			(!gUseWireframe
 			&& LLFeatureManager::getInstance()->isFeatureAvailable("UseOcclusion") 
-			&& gSavedSettings.getBOOL("UseOcclusion") 
-			&& gGLManager.mHasOcclusionQuery) ? 2 : 0;
+			&& gSavedSettings.getBOOL("UseOcclusion")) ? 2 : 0;
 	
     WindLightUseAtmosShaders = TRUE; // DEPRECATED -- gSavedSettings.getBOOL("WindLightUseAtmosShaders");
     RenderDeferred = TRUE; // DEPRECATED -- gSavedSettings.getBOOL("RenderDeferred");
@@ -2355,8 +2345,7 @@ static LLTrace::BlockTimerStatHandle FTM_CULL("Object Culling");
 void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, LLPlane* planep)
 {
 	static LLCachedControl<bool> use_occlusion(gSavedSettings,"UseOcclusion");
-	static bool can_use_occlusion = LLFeatureManager::getInstance()->isFeatureAvailable("UseOcclusion") 
-									&& gGLManager.mHasOcclusionQuery;
+    static bool can_use_occlusion = LLFeatureManager::getInstance()->isFeatureAvailable("UseOcclusion");
 
     LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE; //LL_RECORD_BLOCK_TIME(FTM_CULL);
 
@@ -9759,7 +9748,7 @@ void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera
     LLGLEnable cull(GL_CULL_FACE);
 
     //enable depth clamping if available
-    LLGLEnable depth_clamp(gGLManager.mHasDepthClamp ? GL_DEPTH_CLAMP : 0);
+    //LLGLEnable depth_clamp(GL_DEPTH_CLAMP);
 
     if (use_shader)
     {
diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml
index eb4f9f16fa18d46d5f0e203681c8c1f894f1964c..825d1202a62384979e71494502c7206ffaff142c 100644
--- a/indra/newview/skins/default/xui/en/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/en/menu_viewer.xml
@@ -3099,8 +3099,6 @@ function="World.EnvPreset"
                 <menu_item_check.on_click
                  function="ToggleControl"
                  parameter="UseOcclusion" />
-                <menu_item_check.on_enable
-                 function="Advanced.EnableObjectObjectOcclusion" />
             </menu_item_check>
           <menu_item_separator />