diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp
index f29ee0e57ec1e847c19929449241fa7b94853b40..a460912e70d080b98d97416f9ce308d3aebd2f61 100644
--- a/indra/llrender/llgl.cpp
+++ b/indra/llrender/llgl.cpp
@@ -328,6 +328,7 @@ LLGLManager::LLGLManager() :
 	mHasShaderObjects(FALSE),
 	mHasVertexShader(FALSE),
 	mHasFragmentShader(FALSE),
+	mNumTextureImageUnits(0),
 	mHasOcclusionQuery(FALSE),
 	mHasOcclusionQuery2(FALSE),
 	mHasPointParameters(FALSE),
@@ -534,6 +535,13 @@ bool LLGLManager::initGL()
 		return false;
 	}
 	
+	if (mHasFragmentShader)
+	{
+		GLint num_tex_image_units;
+		glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &num_tex_image_units);
+		mNumTextureImageUnits = num_tex_image_units;
+	}
+	
 	setToDebugGPU();
 
 	initGLStates();
@@ -878,11 +886,13 @@ void LLGLManager::initExtensions()
 		LL_INFOS("RenderInit") << "Disabling mip-map generation for Intel GPUs" << LL_ENDL;
 		mHasMipMapGeneration = FALSE;
 	}
+#if !LL_DARWIN
 	if (mIsATI && mHasMipMapGeneration)
 	{
 		LL_INFOS("RenderInit") << "Disabling mip-map generation for ATI GPUs (performance opt)" << LL_ENDL;
 		mHasMipMapGeneration = FALSE;
 	}
+#endif
 	
 	// Misc
 	glGetIntegerv(GL_MAX_ELEMENTS_VERTICES, (GLint*) &mGLMaxVertexRange);
diff --git a/indra/llrender/llgl.h b/indra/llrender/llgl.h
index 3d002fd8c459f735473cdce459a98afabced370c..1d7ab188fcef1991a22e8e38342cdd20041433d7 100644
--- a/indra/llrender/llgl.h
+++ b/indra/llrender/llgl.h
@@ -91,6 +91,7 @@ public:
 	BOOL mHasShaderObjects;
 	BOOL mHasVertexShader;
 	BOOL mHasFragmentShader;
+	S32  mNumTextureImageUnits;
 	BOOL mHasOcclusionQuery;
 	BOOL mHasOcclusionQuery2;
 	BOOL mHasPointParameters;
diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp
index 49e10c47902911dc082f79f96bbf16df966dbe63..c37139ac4c41a32da4ea4aaf364ac7a3bb40edfa 100644
--- a/indra/llrender/llrender.cpp
+++ b/indra/llrender/llrender.cpp
@@ -119,14 +119,29 @@ void LLTexUnit::refreshState(void)
 	gGL.flush();
 	
 	glActiveTextureARB(GL_TEXTURE0_ARB + mIndex);
+
+	//
+	// Per apple spec, don't call glEnable/glDisable when index exceeds max texture units
+	// http://www.mailinglistarchive.com/html/mac-opengl@lists.apple.com/2008-07/msg00653.html
+	//
+	bool enableDisable = (mIndex < gGLManager.mNumTextureUnits);
+		
 	if (mCurrTexType != TT_NONE)
 	{
-		glEnable(sGLTextureType[mCurrTexType]);
+		if (enableDisable)
+		{
+			glEnable(sGLTextureType[mCurrTexType]);
+		}
+		
 		glBindTexture(sGLTextureType[mCurrTexType], mCurrTexture);
 	}
 	else
 	{
-		glDisable(GL_TEXTURE_2D);
+		if (enableDisable)
+		{
+			glDisable(GL_TEXTURE_2D);
+		}
+		
 		glBindTexture(GL_TEXTURE_2D, 0);	
 	}
 
@@ -167,7 +182,11 @@ void LLTexUnit::enable(eTextureType type)
 		mCurrTexType = type;
 
 		gGL.flush();
-		glEnable(sGLTextureType[type]);
+		
+		if (mIndex < gGLManager.mNumTextureUnits)
+		{
+			glEnable(sGLTextureType[type]);
+		}
 	}
 }
 
@@ -180,7 +199,12 @@ void LLTexUnit::disable(void)
 		activate();
 		unbind(mCurrTexType);
 		gGL.flush();
-		glDisable(sGLTextureType[mCurrTexType]);
+		
+		if (mIndex < gGLManager.mNumTextureUnits)
+		{
+			glDisable(sGLTextureType[mCurrTexType]);
+		}
+		
 		mCurrTexType = TT_NONE;
 	}
 }
diff --git a/indra/llrender/llrendertarget.cpp b/indra/llrender/llrendertarget.cpp
index cd2556d435526757eb4a652244eefd7c53940f92..da1e94df64e5e0546a1f9fec67b8272bc67a1c5f 100644
--- a/indra/llrender/llrendertarget.cpp
+++ b/indra/llrender/llrendertarget.cpp
@@ -44,6 +44,7 @@ void check_framebuffer_status()
 		case GL_FRAMEBUFFER_COMPLETE:
 			break;
 		default:
+			llwarns << "check_framebuffer_status failed -- " << std::hex << status << llendl;
 			ll_fail("check_framebuffer_status failed");	
 			break;
 		}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl
index c5ddf31ac03b727b5e4370b0fd64e199ce2c52cd..609fc4f14ffa68aa634e0356d88891d022131ed7 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl
@@ -23,8 +23,9 @@ uniform float sun_wash;
 
 uniform int light_count;
 
-uniform vec4 light[16];
-uniform vec4 light_col[16];
+#define MAX_LIGHT_COUNT		16
+uniform vec4 light[MAX_LIGHT_COUNT];
+uniform vec4 light_col[MAX_LIGHT_COUNT];
 
 varying vec4 vary_fragcoord;
 uniform vec2 screen_res;
@@ -63,50 +64,56 @@ void main()
 	float noise = texture2D(noiseMap, frag.xy/128.0).b;
 	vec3 out_col = vec3(0,0,0);
 	vec3 npos = normalize(-pos);
-	
-	for (int i = 0; i < light_count; ++i)
+
+	// As of OSX 10.6.7 ATI Apple's crash when using a variable size loop
+	for (int i = 0; i < MAX_LIGHT_COUNT; ++i)
 	{
+		bool light_contrib = (i < light_count);
+		
 		vec3 lv = light[i].xyz-pos;
 		float dist2 = dot(lv,lv);
 		dist2 /= light[i].w;
 		if (dist2 > 1.0)
 		{
-			continue;
+			light_contrib = false;
 		}
 		
 		float da = dot(norm, lv);
 		if (da < 0.0)
 		{
-			continue;
+			light_contrib = false;
 		}
-				
-		lv = normalize(lv);
-		da = dot(norm, lv);
-				
-		float fa = light_col[i].a+1.0;
-		float dist_atten = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0);
-		dist_atten *= noise;
-
-		float lit = da * dist_atten;
 		
-		vec3 col = light_col[i].rgb*lit*diff;
-		//vec3 col = vec3(dist2, light_col[i].a, lit);
-		
-		if (spec.a > 0.0)
+		if (light_contrib)
 		{
-			//vec3 ref = dot(pos+lv, norm);
+			lv = normalize(lv);
+			da = dot(norm, lv);
+					
+			float fa = light_col[i].a+1.0;
+			float dist_atten = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0);
+			dist_atten *= noise;
+
+			float lit = da * dist_atten;
 			
-			float sa = dot(normalize(lv+npos),norm);
+			vec3 col = light_col[i].rgb*lit*diff;
+			//vec3 col = vec3(dist2, light_col[i].a, lit);
 			
-			if (sa > 0.0)
+			if (spec.a > 0.0)
 			{
-				sa = texture2D(lightFunc,vec2(sa, spec.a)).a * min(dist_atten*4.0, 1.0);
-				sa *= noise;
-				col += da*sa*light_col[i].rgb*spec.rgb;
+				//vec3 ref = dot(pos+lv, norm);
+				
+				float sa = dot(normalize(lv+npos),norm);
+				
+				if (sa > 0.0)
+				{
+					sa = texture2D(lightFunc,vec2(sa, spec.a)).a * min(dist_atten*4.0, 1.0);
+					sa *= noise;
+					col += da*sa*light_col[i].rgb*spec.rgb;
+				}
 			}
+			
+			out_col += col;
 		}
-		
-		out_col += col;	
 	}
 	
 	if (dot(out_col, out_col) <= 0.0)
diff --git a/indra/newview/featuretable_mac.txt b/indra/newview/featuretable_mac.txt
index c075c660f32a17de4ee5269414f831d4e8657aa5..e2b979d9e9c235e84bc3e14694e2a86c2eb5748f 100644
--- a/indra/newview/featuretable_mac.txt
+++ b/indra/newview/featuretable_mac.txt
@@ -281,6 +281,9 @@ RenderVBOEnable				1	0
 list TexUnit8orLess
 RenderDeferredSSAO			0	0
 
+list ATI
+RenderDeferredSSAO			0	0
+
 list Intel
 RenderAnisotropic			1	0
 RenderLocalLights			1	0
diff --git a/indra/newview/llfeaturemanager.cpp b/indra/newview/llfeaturemanager.cpp
index 524d2d74ef3aae894ea735cf57a6a3a41b6159d9..b7aabe2aebfbf04f9c364f4e446fcd4e01cd2436 100644
--- a/indra/newview/llfeaturemanager.cpp
+++ b/indra/newview/llfeaturemanager.cpp
@@ -753,7 +753,7 @@ void LLFeatureManager::applyBaseMasks()
 	{
 		maskFeatures("OpenGLPre30");
 	}
-	if (gGLManager.mNumTextureUnits <= 8)
+	if (gGLManager.mNumTextureImageUnits <= 8)
 	{
 		maskFeatures("TexUnit8orLess");
 	}
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index f64eb8986691799addb47364501ca5d81027bad3..845a87b8cff49fa020a6f7bcc00f14183c293b0d 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -625,8 +625,14 @@ void LLPipeline::allocateScreenBuffer(U32 resX, U32 resY)
 		mDeferredDepth.allocate(resX, resY, 0, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE);
 		addDeferredAttachments(mDeferredScreen);
 	
-		mScreen.allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE);		
+		mScreen.allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE);
+		
+#if LL_DARWIN
+		// As of OS X 10.6.7, Apple doesn't support multiple color formats in a single FBO
+		mEdgeMap.allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE);
+#else
 		mEdgeMap.allocate(resX, resY, GL_ALPHA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE);
+#endif
 
 		if (shadow_detail > 0 || ssao)
 		{ //only need mDeferredLight[0] for shadows OR ssao
@@ -651,7 +657,12 @@ void LLPipeline::allocateScreenBuffer(U32 resX, U32 resY)
 			mDeferredLight[2].allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE);
 			for (U32 i = 0; i < 2; i++)
 			{
+#if LL_DARWIN
+				// As of OS X 10.6.7, Apple doesn't support multiple color formats in a single FBO
+				mGIMapPost[i].allocate(resX,resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE);
+#else
 				mGIMapPost[i].allocate(resX,resY, GL_RGB, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE);
+#endif
 			}
 		}
 		else
@@ -666,8 +677,12 @@ void LLPipeline::allocateScreenBuffer(U32 resX, U32 resY)
 
 		F32 scale = gSavedSettings.getF32("RenderShadowResolutionScale");
 
+#if LL_DARWIN
+		U32 shadow_fmt = 0;
+#else
 		//HACK: make alpha masking work on ATI depth shadows (work around for ATI driver bug)
 		U32 shadow_fmt = gGLManager.mIsATI ? GL_ALPHA : 0;
+#endif
 
 		if (shadow_detail > 0)
 		{ //allocate 4 sun shadow maps