diff --git a/src/bitmap.cpp b/src/bitmap.cpp
index b0d6b94..7ebba37 100644
--- a/src/bitmap.cpp
+++ b/src/bitmap.cpp
@@ -873,7 +873,7 @@ void Bitmap::drawText(const IntRect &rect, const char *str, int align)
 				}
 
 				TEX::bind(p->gl.tex);
-				TEX::uploadSubImage(posRect.x, posRect.y, posRect.w, posRect.h, txtSurf->pixels, GL_BGRA_EXT);
+				TEX::uploadSubImage(posRect.x, posRect.y, posRect.w, posRect.h, txtSurf->pixels, GL_BGRA);
 
 				PixelStore::reset();
 			}
@@ -884,7 +884,7 @@ void Bitmap::drawText(const IntRect &rect, const char *str, int align)
 			TEXFBO &gpTF = shState->gpTexFBO(txtSurf->w, txtSurf->h);
 
 			TEX::bind(gpTF.tex);
-			TEX::uploadSubImage(0, 0, txtSurf->w, txtSurf->h, txtSurf->pixels, GL_BGRA_EXT);
+			TEX::uploadSubImage(0, 0, txtSurf->w, txtSurf->h, txtSurf->pixels, GL_BGRA);
 
 			FBO::bind(gpTF.fbo, FBO::Read);
 			p->bindFBO();
@@ -917,7 +917,7 @@ void Bitmap::drawText(const IntRect &rect, const char *str, int align)
 		shader.setOpacity(txtAlpha);
 
 		shState->bindTex();
-		TEX::uploadSubImage(0, 0, txtSurf->w, txtSurf->h, txtSurf->pixels, GL_BGRA_EXT);
+		TEX::uploadSubImage(0, 0, txtSurf->w, txtSurf->h, txtSurf->pixels, GL_BGRA);
 		TEX::setSmooth(true);
 
 		Quad &quad = shState->gpQuad();
diff --git a/src/gl-util.h b/src/gl-util.h
index 4383d49..d760672 100644
--- a/src/gl-util.h
+++ b/src/gl-util.h
@@ -109,19 +109,19 @@ namespace RBO
 	inline ID gen()
 	{
 		ID id;
-		glGenRenderbuffersEXT(1, &id.gl);
+		glGenRenderbuffers(1, &id.gl);
 
 		return id;
 	}
 
 	inline void del(ID id)
 	{
-		glDeleteRenderbuffersEXT(1, &id.gl);
+		glDeleteRenderbuffers(1, &id.gl);
 	}
 
 	inline void bind(ID id)
 	{
-		glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, id.gl);
+		glBindRenderbuffer(GL_RENDERBUFFER, id.gl);
 	}
 
 	inline void unbind()
@@ -131,7 +131,7 @@ namespace RBO
 
 	inline void allocEmpty(GLsizei width, GLsizei height)
 	{
-		glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGBA8, width, height);
+		glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, width, height);
 	}
 }
 
@@ -155,25 +155,25 @@ namespace FBO
 	inline ID gen()
 	{
 		ID id;
-		glGenFramebuffersEXT(1, &id.gl);
+		glGenFramebuffers(1, &id.gl);
 
 		return id;
 	}
 
 	inline void del(ID id)
 	{
-		glDeleteFramebuffersEXT(1, &id.gl);
+		glDeleteFramebuffers(1, &id.gl);
 	}
 
 	inline void bind(ID id, Mode mode)
 	{
 		static const GLenum modes[] =
 		{
-			GL_DRAW_FRAMEBUFFER_EXT,
-			GL_READ_FRAMEBUFFER_EXT
+			GL_DRAW_FRAMEBUFFER,
+			GL_READ_FRAMEBUFFER
 		};
 
-		glBindFramebufferEXT(modes[mode], id.gl);
+		glBindFramebuffer(modes[mode], id.gl);
 	}
 
 	inline void unbind(Mode mode)
@@ -183,12 +183,12 @@ namespace FBO
 
 	inline void setTarget(TEX::ID target, unsigned colorAttach = 0)
 	{
-		glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + colorAttach, GL_TEXTURE_2D, target.gl, 0);
+		glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + colorAttach, GL_TEXTURE_2D, target.gl, 0);
 	}
 
 	inline void setTarget(RBO::ID target, unsigned colorAttach = 0)
 	{
-		glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + colorAttach, GL_RENDERBUFFER, target.gl);
+		glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + colorAttach, GL_RENDERBUFFER, target.gl);
 	}
 
 	inline void blit(int srcX, int srcY,
@@ -203,9 +203,9 @@ namespace FBO
 			GL_LINEAR
 		};
 
-		glBlitFramebufferEXT(srcX, srcY, srcX+srcW, srcY+srcH,
-		                     dstX, dstY, dstX+dstW, dstY+dstH,
-		                     GL_COLOR_BUFFER_BIT, modes[mode]);
+		glBlitFramebuffer(srcX, srcY, srcX+srcW, srcY+srcH,
+						  dstX, dstY, dstX+dstW, dstY+dstH,
+						  GL_COLOR_BUFFER_BIT, modes[mode]);
 	}
 
 	inline void blit(int srcX, int srcY,
diff --git a/src/glstate.cpp b/src/glstate.cpp
index 677c9b7..f9c3557 100644
--- a/src/glstate.cpp
+++ b/src/glstate.cpp
@@ -71,21 +71,21 @@ void GLBlendMode::apply(const BlendType &value)
 
 	case BlendNormal :
 		glBlendEquation(GL_FUNC_ADD);
-		glBlendFuncSeparateEXT(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,
-		                       GL_ONE,       GL_ONE_MINUS_SRC_ALPHA);
+		glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,
+		                    GL_ONE,       GL_ONE_MINUS_SRC_ALPHA);
 		break;
 
 	case BlendAddition :
 		glBlendEquation(GL_FUNC_ADD);
-		glBlendFuncSeparateEXT(GL_SRC_ALPHA, GL_ONE,
-		                       GL_ONE,       GL_ONE);
+		glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE,
+		                    GL_ONE,       GL_ONE);
 		break;
 
 	case BlendSubstraction :
 		// FIXME Alpha calculation is untested
-		glBlendEquation(GL_FUNC_REVERSE_SUBTRACT_EXT);
-		glBlendFuncSeparateEXT(GL_SRC_ALPHA, GL_ONE,
-		                       GL_ONE,       GL_ONE);
+		glBlendEquation(GL_FUNC_REVERSE_SUBTRACT);
+		glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE,
+		                    GL_ONE,       GL_ONE);
 		break;
 	}
 }
diff --git a/src/main.cpp b/src/main.cpp
index 27b7533..3a251fe 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -39,21 +39,11 @@
 
 static const char *reqExt[] =
 {
-	"GL_ARB_fragment_shader",
-	"GL_ARB_shader_objects",
-	"GL_ARB_vertex_shader",
-	"GL_ARB_shading_language_100",
-	"GL_ARB_texture_non_power_of_two",
-	"GL_ARB_vertex_array_object",
-	"GL_ARB_vertex_buffer_object",
-	"GL_EXT_bgra",
-	"GL_EXT_blend_func_separate",
-	"GL_EXT_blend_subtract",
-	"GL_EXT_framebuffer_object",
-	"GL_EXT_framebuffer_blit",
+	// Everything we are using is CORE in OpenGL 2.0 except FBOs and VAOs which we'll handle in a special function
 	0
 };
 
+
 static void
 rgssThreadError(RGSSThreadData *rtData, const std::string &msg)
 {
@@ -77,6 +67,50 @@ printGLInfo()
 	Debug() << "GLSL Version :" << glGetStringInt(GL_SHADING_LANGUAGE_VERSION);
 }
 
+static bool
+setupOptionalGLExtensions(RGSSThreadData* threadData)
+{
+	if (!GLEW_ARB_framebuffer_object) {
+		if (!GLEW_EXT_framebuffer_object && !GLEW_EXT_framebuffer_blit) {
+			rgssThreadError(threadData, "GL extensions \"GL_ARB_framebuffer_object\" or compatible extensiosns GL_EXT_framebuffer_object and GL_EXT_framebuffer_blit are not present");
+			return false;
+		} else {
+			// setup compat
+			// From EXT_framebuffer_object
+			glGenRenderbuffers      = glGenRenderbuffersEXT;
+			glDeleteRenderbuffers   = glDeleteRenderbuffersEXT;
+			glBindRenderbuffer      = glBindRenderbufferEXT;
+			glRenderbufferStorage   = glRenderbufferStorageEXT;
+
+			glGenFramebuffers       = glGenFramebuffersEXT;
+			glDeleteFramebuffers    = glDeleteFramebuffersEXT;
+			glBindFramebuffer       = glBindFramebufferEXT;
+			glFramebufferTexture2D  = glFramebufferTexture2DEXT;
+			glFramebufferRenderbuffer = glFramebufferRenderbufferEXT;
+
+			// From EXT_framebuffer_blit
+			glBlitFramebuffer       = glBlitFramebufferEXT;
+		}
+	}
+	if (!GLEW_ARB_timer_query && GLEW_EXT_timer_query) {
+		glGetQueryObjecti64v = glGetQueryObjecti64vEXT;
+		glGetQueryObjectui64v = glGetQueryObjectui64vEXT;
+	}
+	if (!GLEW_ARB_vertex_array_object ) {
+		if (!GLEW_APPLE_vertex_array_object) {
+			rgssThreadError(threadData, "GL extensions \"GL_ARB_vertex_array_object\" or compatible extensiosn GL_APPLE_vertex_array_object are not present");
+			return false;
+		} else {
+			// setup compat
+			glBindVertexArray = glBindVertexArrayAPPLE;
+			// the cast is because apple's uses const GLuint* and ARB doesn't
+			glGenVertexArrays = (PFNGLGENVERTEXARRAYSPROC)glGenVertexArraysAPPLE;
+			glDeleteVertexArrays = glDeleteVertexArraysAPPLE;
+		}
+	}
+	return true;
+}
+
 int rgssThreadFun(void *userdata)
 {
 	RGSSThreadData *threadData = static_cast<RGSSThreadData*>(userdata);
@@ -132,6 +166,11 @@ int rgssThreadFun(void *userdata)
 			return 0;
 		}
 	}
+	/* Setup optional GL extensions */
+	if (!setupOptionalGLExtensions(threadData)) {
+		SDL_GL_DeleteContext(glCtx);
+		return 0;
+	}
 
 	SDL_GL_SetSwapInterval(threadData->config.vsync ? 1 : 0);
 
diff --git a/src/perftimer.cpp b/src/perftimer.cpp
index abe61a9..4fb450a 100644
--- a/src/perftimer.cpp
+++ b/src/perftimer.cpp
@@ -193,7 +193,7 @@ PerfTimer *createCPUTimer(int iter)
 
 PerfTimer *createGPUTimer(int iter)
 {
-	if (GLEW_EXT_timer_query)
+	if (GLEW_ARB_timer_query || GLEW_EXT_timer_query)
 	{
 		return new GPUTimerGLQuery(iter);
 	}