Browse Source

Improved clarity/readability of internal OpenGL state shadowing functions

Alex Szpakowski 12 years ago
parent
commit
6fd3038405

+ 20 - 20
src/modules/graphics/opengl/Canvas.cpp

@@ -107,13 +107,13 @@ struct FramebufferStrategyGL3 : public FramebufferStrategy
 		}
 		}
 
 
 		glGenTextures(1, &img);
 		glGenTextures(1, &img);
-		bindTexture(img);
+		gl.bindTexture(img);
 
 
-		setTextureFilter(Image::getDefaultFilter());
+		gl.setTextureFilter(Image::getDefaultFilter());
 
 
 		glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, width, height,
 		glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, width, height,
 			0, GL_RGBA, format, NULL);
 			0, GL_RGBA, format, NULL);
-		bindTexture(0);
+		gl.bindTexture(0);
 		glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
 		glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
 			GL_TEXTURE_2D, img, 0);
 			GL_TEXTURE_2D, img, 0);
 
 
@@ -127,7 +127,7 @@ struct FramebufferStrategyGL3 : public FramebufferStrategy
 	}
 	}
 	virtual void deleteFBO(GLuint framebuffer, GLuint depth_stencil,  GLuint img)
 	virtual void deleteFBO(GLuint framebuffer, GLuint depth_stencil,  GLuint img)
 	{
 	{
-		deleteTexture(img);
+		gl.deleteTexture(img);
 		glDeleteRenderbuffers(1, &depth_stencil);
 		glDeleteRenderbuffers(1, &depth_stencil);
 		glDeleteFramebuffers(1, &framebuffer);
 		glDeleteFramebuffers(1, &framebuffer);
 	}
 	}
@@ -209,13 +209,13 @@ struct FramebufferStrategyPackedEXT : public FramebufferStrategy
 		}
 		}
 
 
 		glGenTextures(1, &img);
 		glGenTextures(1, &img);
-		bindTexture(img);
+		gl.bindTexture(img);
 
 
-		setTextureFilter(Image::getDefaultFilter());
+		gl.setTextureFilter(Image::getDefaultFilter());
 
 
 		glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, width, height,
 		glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, width, height,
 			0, GL_RGBA, format, NULL);
 			0, GL_RGBA, format, NULL);
-		bindTexture(0);
+		gl.bindTexture(0);
 		glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
 		glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
 			GL_TEXTURE_2D, img, 0);
 			GL_TEXTURE_2D, img, 0);
 
 
@@ -230,7 +230,7 @@ struct FramebufferStrategyPackedEXT : public FramebufferStrategy
 
 
 	virtual void deleteFBO(GLuint framebuffer, GLuint depth_stencil, GLuint img)
 	virtual void deleteFBO(GLuint framebuffer, GLuint depth_stencil, GLuint img)
 	{
 	{
-		deleteTexture(img);
+		gl.deleteTexture(img);
 		glDeleteRenderbuffersEXT(1, &depth_stencil);
 		glDeleteRenderbuffersEXT(1, &depth_stencil);
 		glDeleteFramebuffersEXT(1, &framebuffer);
 		glDeleteFramebuffersEXT(1, &framebuffer);
 	}
 	}
@@ -310,13 +310,13 @@ struct FramebufferStrategyEXT : public FramebufferStrategyPackedEXT
 		}
 		}
 
 
 		glGenTextures(1, &img);
 		glGenTextures(1, &img);
-		bindTexture(img);
+		gl.bindTexture(img);
 
 
-		setTextureFilter(Image::getDefaultFilter());
+		gl.setTextureFilter(Image::getDefaultFilter());
 
 
 		glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, width, height,
 		glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, width, height,
 			0, GL_RGBA, format, NULL);
 			0, GL_RGBA, format, NULL);
-		bindTexture(0);
+		gl.bindTexture(0);
 		glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
 		glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
 			GL_TEXTURE_2D, img, 0);
 			GL_TEXTURE_2D, img, 0);
 
 
@@ -644,26 +644,26 @@ const std::vector<Canvas *> &Canvas::getAttachedCanvases() const
 
 
 void Canvas::setFilter(const Image::Filter &f)
 void Canvas::setFilter(const Image::Filter &f)
 {
 {
-	bindTexture(img);
-	setTextureFilter(f);
+	gl.bindTexture(img);
+	gl.setTextureFilter(f);
 }
 }
 
 
 Image::Filter Canvas::getFilter() const
 Image::Filter Canvas::getFilter() const
 {
 {
-	bindTexture(img);
-	return getTextureFilter();
+	gl.bindTexture(img);
+	return gl.getTextureFilter();
 }
 }
 
 
 void Canvas::setWrap(const Image::Wrap &w)
 void Canvas::setWrap(const Image::Wrap &w)
 {
 {
-	bindTexture(img);
-	setTextureWrap(w);
+	gl.bindTexture(img);
+	gl.setTextureWrap(w);
 }
 }
 
 
 Image::Wrap Canvas::getWrap() const
 Image::Wrap Canvas::getWrap() const
 {
 {
-	bindTexture(img);
-	return getTextureWrap();
+	gl.bindTexture(img);
+	return gl.getTextureWrap();
 }
 }
 
 
 bool Canvas::loadVolatile()
 bool Canvas::loadVolatile()
@@ -708,7 +708,7 @@ void Canvas::drawv(const Matrix &t, const vertex *v) const
 
 
 	glMultMatrixf((const GLfloat *)t.getElements());
 	glMultMatrixf((const GLfloat *)t.getElements());
 
 
-	bindTexture(img);
+	gl.bindTexture(img);
 
 
 	glEnableClientState(GL_VERTEX_ARRAY);
 	glEnableClientState(GL_VERTEX_ARRAY);
 	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
 	glEnableClientState(GL_TEXTURE_COORD_ARRAY);

+ 8 - 8
src/modules/graphics/opengl/Font.cpp

@@ -120,7 +120,7 @@ void Font::createTexture()
 	glGenTextures(1, &t);
 	glGenTextures(1, &t);
 	textures.push_back(t);
 	textures.push_back(t);
 
 
-	bindTexture(t);
+	gl.bindTexture(t);
 
 
 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
@@ -148,8 +148,8 @@ void Font::createTexture()
 	if (!initialized)
 	if (!initialized)
 	{
 	{
 		// cleanup before throwing
 		// cleanup before throwing
-		deleteTexture(t);
-		bindTexture(0);
+		gl.deleteTexture(t);
+		gl.bindTexture(0);
 		textures.pop_back();
 		textures.pop_back();
 
 
 		throw love::Exception("Could not create font texture!");
 		throw love::Exception("Could not create font texture!");
@@ -200,7 +200,7 @@ Font::Glyph *Font::addGlyph(unsigned int glyph)
 	{
 	{
 		const GLuint t = textures.back();
 		const GLuint t = textures.back();
 
 
-		bindTexture(t);
+		gl.bindTexture(t);
 		glTexSubImage2D(GL_TEXTURE_2D,
 		glTexSubImage2D(GL_TEXTURE_2D,
 						0,
 						0,
 						textureX,
 						textureX,
@@ -356,7 +356,7 @@ void Font::print(const std::string &text, float x, float y, float letter_spacing
 		std::vector<GlyphArrayDrawInfo>::const_iterator it;
 		std::vector<GlyphArrayDrawInfo>::const_iterator it;
 		for (it = glyphinfolist.begin(); it != glyphinfolist.end(); ++it)
 		for (it = glyphinfolist.begin(); it != glyphinfolist.end(); ++it)
 		{
 		{
-			bindTexture(it->texture);
+			gl.bindTexture(it->texture);
 
 
 			int startvertex = it->startquad * 4;
 			int startvertex = it->startquad * 4;
 			int numvertices = it->numquads * 4;
 			int numvertices = it->numquads * 4;
@@ -504,8 +504,8 @@ void Font::setFilter(const Image::Filter &f)
 	std::vector<GLuint>::const_iterator it;
 	std::vector<GLuint>::const_iterator it;
 	for (it = textures.begin(); it != textures.end(); ++it)
 	for (it = textures.begin(); it != textures.end(); ++it)
 	{
 	{
-		bindTexture(*it);
-		filter.anisotropy = setTextureFilter(f);
+		gl.bindTexture(*it);
+		filter.anisotropy = gl.setTextureFilter(f);
 	}
 	}
 }
 }
 
 
@@ -534,7 +534,7 @@ void Font::unloadVolatile()
 	std::vector<GLuint>::iterator iter = textures.begin();
 	std::vector<GLuint>::iterator iter = textures.begin();
 	while (iter != textures.end())
 	while (iter != textures.end())
 	{
 	{
-		deleteTexture(*iter);
+		gl.deleteTexture(*iter);
 		iter++;
 		iter++;
 	}
 	}
 	textures.clear();
 	textures.clear();

+ 11 - 11
src/modules/graphics/opengl/Graphics.cpp

@@ -131,7 +131,7 @@ bool Graphics::setMode(int width, int height, WindowFlags *flags)
 	// the display mode change.
 	// the display mode change.
 	Volatile::unloadAll();
 	Volatile::unloadAll();
 
 
-	uninitializeContext();
+	gl.deInitContext();
 
 
 	bool success = currentWindow->setWindow(width, height, flags);
 	bool success = currentWindow->setWindow(width, height, flags);
 
 
@@ -140,7 +140,7 @@ bool Graphics::setMode(int width, int height, WindowFlags *flags)
 	height = currentWindow->getHeight();
 	height = currentWindow->getHeight();
 
 
 	// Okay, setup OpenGL.
 	// Okay, setup OpenGL.
-	initializeContext();
+	gl.initContext();
 
 
 	// Make sure antialiasing works when set elsewhere
 	// Make sure antialiasing works when set elsewhere
 	if (GLEE_VERSION_1_3 || GLEE_ARB_multisample)
 	if (GLEE_VERSION_1_3 || GLEE_ARB_multisample)
@@ -170,7 +170,7 @@ bool Graphics::setMode(int width, int height, WindowFlags *flags)
 
 
 	// Enable textures
 	// Enable textures
 	glEnable(GL_TEXTURE_2D);
 	glEnable(GL_TEXTURE_2D);
-	setActiveTextureUnit(0);
+	gl.setActiveTextureUnit(0);
 
 
 	// Set the viewport to top-left corner
 	// Set the viewport to top-left corner
 	glViewport(0, 0, width, height);
 	glViewport(0, 0, width, height);
@@ -576,12 +576,12 @@ Shader *Graphics::newShader(const Shader::ShaderSources &sources)
 
 
 void Graphics::setColor(const Color &c)
 void Graphics::setColor(const Color &c)
 {
 {
-	opengl::setCurrentColor(c);
+	gl.setColor(c);
 }
 }
 
 
 Color Graphics::getColor() const
 Color Graphics::getColor() const
 {
 {
-	return opengl::getCurrentColor();
+	return gl.getColor();
 }
 }
 
 
 void Graphics::setBackgroundColor(const Color &c)
 void Graphics::setBackgroundColor(const Color &c)
@@ -924,7 +924,7 @@ void Graphics::printf(const char *str, float x, float y, float wrap, AlignMode a
 
 
 void Graphics::point(float x, float y)
 void Graphics::point(float x, float y)
 {
 {
-	bindTexture(0);
+	gl.bindTexture(0);
 	glBegin(GL_POINTS);
 	glBegin(GL_POINTS);
 	glVertex2f(x, y);
 	glVertex2f(x, y);
 	glEnd();
 	glEnd();
@@ -1042,7 +1042,7 @@ static void draw_overdraw(Vector *overdraw, size_t count, float pixel_size, bool
 	// prepare colors:
 	// prepare colors:
 	// even indices in overdraw* point to inner vertices => alpha = current-alpha,
 	// even indices in overdraw* point to inner vertices => alpha = current-alpha,
 	// odd indices point to outer vertices => alpha = 0.
 	// odd indices point to outer vertices => alpha = 0.
-	Color c = opengl::getCurrentColor();
+	Color c = gl.getColor();
 
 
 	Color *colors = new Color[2*count+2];
 	Color *colors = new Color[2*count+2];
 	for (size_t i = 0; i < 2*count+2; ++i)
 	for (size_t i = 0; i < 2*count+2; ++i)
@@ -1061,7 +1061,7 @@ static void draw_overdraw(Vector *overdraw, size_t count, float pixel_size, bool
 	// "if GL_COLOR_ARRAY is enabled, the value of the current color is
 	// "if GL_COLOR_ARRAY is enabled, the value of the current color is
 	// undefined after glDrawArrays executes"
 	// undefined after glDrawArrays executes"
 	
 	
-	opengl::setCurrentColor(c);
+	gl.setColor(c);
 
 
 	delete[] colors;
 	delete[] colors;
 }
 }
@@ -1119,7 +1119,7 @@ void Graphics::polyline(const float *coords, size_t count)
 	// end get line vertex boundaries
 	// end get line vertex boundaries
 
 
 	// draw the core line
 	// draw the core line
-	bindTexture(0);
+	gl.bindTexture(0);
 	glEnableClientState(GL_VERTEX_ARRAY);
 	glEnableClientState(GL_VERTEX_ARRAY);
 	glVertexPointer(2, GL_FLOAT, 0, (const GLvoid *)vertices);
 	glVertexPointer(2, GL_FLOAT, 0, (const GLvoid *)vertices);
 	glDrawArrays(GL_TRIANGLE_STRIP, 0, count);
 	glDrawArrays(GL_TRIANGLE_STRIP, 0, count);
@@ -1201,7 +1201,7 @@ void Graphics::arc(DrawMode mode, float x, float y, float radius, float angle1,
 	}
 	}
 	else
 	else
 	{
 	{
-		bindTexture(0);
+		gl.bindTexture(0);
 		glEnableClientState(GL_VERTEX_ARRAY);
 		glEnableClientState(GL_VERTEX_ARRAY);
 		glVertexPointer(2, GL_FLOAT, 0, (const GLvoid *) coords);
 		glVertexPointer(2, GL_FLOAT, 0, (const GLvoid *) coords);
 		glDrawArrays(GL_TRIANGLE_FAN, 0, points + 2);
 		glDrawArrays(GL_TRIANGLE_FAN, 0, points + 2);
@@ -1224,7 +1224,7 @@ void Graphics::polygon(DrawMode mode, const float *coords, size_t count)
 	}
 	}
 	else
 	else
 	{
 	{
-		bindTexture(0);
+		gl.bindTexture(0);
 		glEnableClientState(GL_VERTEX_ARRAY);
 		glEnableClientState(GL_VERTEX_ARRAY);
 		glVertexPointer(2, GL_FLOAT, 0, (const GLvoid *)coords);
 		glVertexPointer(2, GL_FLOAT, 0, (const GLvoid *)coords);
 		glDrawArrays(GL_POLYGON, 0, count/2-1); // opengl will close the polygon for us
 		glDrawArrays(GL_POLYGON, 0, count/2-1); // opengl will close the polygon for us

+ 10 - 10
src/modules/graphics/opengl/Image.cpp

@@ -217,7 +217,7 @@ void Image::setFilter(const Image::Filter &f)
 	filter = f;
 	filter = f;
 
 
 	bind();
 	bind();
-	filter.anisotropy = setTextureFilter(f);
+	filter.anisotropy = gl.setTextureFilter(f);
 	checkMipmapsCreated();
 	checkMipmapsCreated();
 }
 }
 
 
@@ -231,7 +231,7 @@ void Image::setWrap(const Image::Wrap &w)
 	wrap = w;
 	wrap = w;
 
 
 	bind();
 	bind();
-	setTextureWrap(w);
+	gl.setTextureWrap(w);
 }
 }
 
 
 const Image::Wrap &Image::getWrap() const
 const Image::Wrap &Image::getWrap() const
@@ -265,7 +265,7 @@ void Image::bind() const
 	if (texture == 0)
 	if (texture == 0)
 		return;
 		return;
 
 
-	bindTexture(texture);
+	gl.bindTexture(texture);
 }
 }
 
 
 void Image::preload()
 void Image::preload()
@@ -330,10 +330,10 @@ bool Image::loadVolatile()
 bool Image::loadVolatilePOT()
 bool Image::loadVolatilePOT()
 {
 {
 	glGenTextures(1,(GLuint *)&texture);
 	glGenTextures(1,(GLuint *)&texture);
-	bindTexture(texture);
+	gl.bindTexture(texture);
 
 
-	filter.anisotropy = setTextureFilter(filter);
-	setTextureWrap(wrap);
+	filter.anisotropy = gl.setTextureFilter(filter);
+	gl.setTextureWrap(wrap);
 
 
 	float p2width = next_p2(width);
 	float p2width = next_p2(width);
 	float p2height = next_p2(height);
 	float p2height = next_p2(height);
@@ -400,10 +400,10 @@ bool Image::loadVolatilePOT()
 bool Image::loadVolatileNPOT()
 bool Image::loadVolatileNPOT()
 {
 {
 	glGenTextures(1,(GLuint *)&texture);
 	glGenTextures(1,(GLuint *)&texture);
-	bindTexture(texture);
+	gl.bindTexture(texture);
 
 
-	filter.anisotropy = setTextureFilter(filter);
-	setTextureWrap(wrap);
+	filter.anisotropy = gl.setTextureFilter(filter);
+	gl.setTextureWrap(wrap);
 
 
 	while (glGetError() != GL_NO_ERROR); // clear errors
 	while (glGetError() != GL_NO_ERROR); // clear errors
 
 
@@ -448,7 +448,7 @@ void Image::unloadVolatile()
 	// Delete the hardware texture.
 	// Delete the hardware texture.
 	if (texture != 0)
 	if (texture != 0)
 	{
 	{
-		deleteTexture(texture);
+		gl.deleteTexture(texture);
 		texture = 0;
 		texture = 0;
 	}
 	}
 }
 }

+ 87 - 69
src/modules/graphics/opengl/OpenGL.cpp

@@ -18,13 +18,14 @@
  * 3. This notice may not be removed or altered from any source distribution.
  * 3. This notice may not be removed or altered from any source distribution.
  **/
  **/
 
 
+#include "OpenGL.h"
+
+// LOVE
 #include "common/config.h"
 #include "common/config.h"
 #include "common/Exception.h"
 #include "common/Exception.h"
-
-#include "OpenGL.h"
 #include "Shader.h"
 #include "Shader.h"
 
 
-#include <vector>
+// STL
 #include <algorithm>
 #include <algorithm>
 
 
 namespace love
 namespace love
@@ -34,61 +35,83 @@ namespace graphics
 namespace opengl
 namespace opengl
 {
 {
 
 
-static bool contextInitialized = false;
+// OpenGL class instance singleton.
+OpenGL gl;
 
 
-static Color curColor;
-
-static int curTextureUnit = 0;
-static std::vector<GLuint> textureUnits;
-
-static float maxAnisotropy = 1.0f;
+OpenGL::OpenGL()
+	: contexInitialized(false)
+	, maxAnisotropy(1.0f)
+	, state()
+{
+}
 
 
-void initializeContext()
+void OpenGL::initContext()
 {
 {
-	if (contextInitialized)
+	if (contexInitialized)
 		return;
 		return;
 
 
-	contextInitialized = true;
+	initOpenGLFunctions();
 
 
-	// Store the current color so we don't have to get it through GL later
+	// Store the current color so we don't have to get it through GL later.
 	GLfloat glcolor[4];
 	GLfloat glcolor[4];
 	glGetFloatv(GL_CURRENT_COLOR, glcolor);
 	glGetFloatv(GL_CURRENT_COLOR, glcolor);
-	curColor.r = glcolor[0];
-	curColor.g = glcolor[1];
-	curColor.b = glcolor[2];
-	curColor.a = glcolor[3];
+	state.color.r = glcolor[0];
+	state.color.g = glcolor[1];
+	state.color.b = glcolor[2];
+	state.color.a = glcolor[3];
 
 
-	// initialize multiple texture unit support for shaders, if available
-	textureUnits.clear();
+	// Initialize multiple texture unit support for shaders, if available.
+	state.textureUnits.clear();
 	if (Shader::isSupported())
 	if (Shader::isSupported())
 	{
 	{
 		GLint maxtextureunits;
 		GLint maxtextureunits;
 		glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &maxtextureunits);
 		glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &maxtextureunits);
 
 
-		textureUnits.resize(maxtextureunits, 0);
+		state.textureUnits.resize(maxtextureunits, 0);
 
 
 		GLenum curgltextureunit;
 		GLenum curgltextureunit;
 		glGetIntegerv(GL_ACTIVE_TEXTURE, (GLint *) &curgltextureunit);
 		glGetIntegerv(GL_ACTIVE_TEXTURE, (GLint *) &curgltextureunit);
 
 
-		curTextureUnit = curgltextureunit - GL_TEXTURE0;
+		state.curTextureUnit = curgltextureunit - GL_TEXTURE0;
 
 
-		// Retrieve currently bound textures for each texture unit
-		for (size_t i = 0; i < textureUnits.size(); i++)
+		// Retrieve currently bound textures for each texture unit.
+		for (size_t i = 0; i < state.textureUnits.size(); i++)
 		{
 		{
 			glActiveTexture(GL_TEXTURE0 + i);
 			glActiveTexture(GL_TEXTURE0 + i);
-			glGetIntegerv(GL_TEXTURE_BINDING_2D, (GLint *) &textureUnits[i]);
+			glGetIntegerv(GL_TEXTURE_BINDING_2D, (GLint *) &state.textureUnits[i]);
 		}
 		}
 
 
 		glActiveTexture(curgltextureunit);
 		glActiveTexture(curgltextureunit);
 	}
 	}
 	else
 	else
 	{
 	{
-		// multitexturing not supported, so we only have 1 texture unit
-		textureUnits.resize(1, 0);
-		curTextureUnit = 0;
-		glGetIntegerv(GL_TEXTURE_BINDING_2D, (GLint *) &textureUnits[0]);
+		// Multitexturing not supported, so we only have 1 texture unit.
+		state.textureUnits.resize(1, 0);
+		state.curTextureUnit = 0;
+		glGetIntegerv(GL_TEXTURE_BINDING_2D, (GLint *) &state.textureUnits[0]);
 	}
 	}
 
 
+	// We'll need this value to clamp anisotropy.
+	if (GLEE_EXT_texture_filter_anisotropic)
+		glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &maxAnisotropy);
+	else
+		maxAnisotropy = 1.0f;
+
+	createDefaultTexture();
+
+	contexInitialized = true;
+}
+
+void OpenGL::deInitContext()
+{
+	if (!contexInitialized)
+		return;
+
+	contexInitialized = false;
+}
+
+void OpenGL::initOpenGLFunctions()
+{
 	// The functionality of the core and ARB VBOs are identical, so we can
 	// The functionality of the core and ARB VBOs are identical, so we can
 	// assign the pointers of the core functions to the names of the ARB
 	// assign the pointers of the core functions to the names of the ARB
 	// functions, if the latter isn't supported but the former is.
 	// functions, if the latter isn't supported but the former is.
@@ -114,17 +137,16 @@ void initializeContext()
 		glCompressedTexSubImage2DARB = (GLEEPFNGLCOMPRESSEDTEXSUBIMAGE2DARBPROC) glCompressedTexSubImage2D;
 		glCompressedTexSubImage2DARB = (GLEEPFNGLCOMPRESSEDTEXSUBIMAGE2DARBPROC) glCompressedTexSubImage2D;
 		glGetCompressedTexImageARB = (GLEEPFNGLGETCOMPRESSEDTEXIMAGEARBPROC) glGetCompressedTexImage;
 		glGetCompressedTexImageARB = (GLEEPFNGLGETCOMPRESSEDTEXIMAGEARBPROC) glGetCompressedTexImage;
 	}
 	}
+}
 
 
-	if (GLEE_EXT_texture_filter_anisotropic)
-		glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &maxAnisotropy);
-	else
-		maxAnisotropy = 1.0f;
-
-	// Set the 'default' texture (id 0) as a repeating white pixel.
-	// Otherwise, texture2D inside a shader would return black when drawing graphics primitives,
-	// which would create the need to use different "passthrough" shaders for untextured primitives vs images.
+void OpenGL::createDefaultTexture()
+{
+	// Set the 'default' texture (id 0) as a repeating white pixel. Otherwise,
+	// texture2D calls inside a shader would return black when drawing graphics
+	// primitives, which would create the need to use different "passthrough"
+	// shaders for untextured primitives vs images.
 
 
-	GLuint curtexture = textureUnits[curTextureUnit];
+	GLuint curtexture = state.textureUnits[state.curTextureUnit];
 	bindTexture(0);
 	bindTexture(0);
 
 
 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
@@ -133,64 +155,59 @@ void initializeContext()
 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
 
 
-	GLubyte pixel = 255;
-	glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE8, 1, 1, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, &pixel);
+	GLubyte pix = 255;
+	glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE8, 1, 1, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, &pix);
 
 
 	bindTexture(curtexture);
 	bindTexture(curtexture);
 }
 }
 
 
-void uninitializeContext()
-{
-	contextInitialized = false;
-}
-
-void setCurrentColor(const Color &c)
+void OpenGL::setColor(const Color &c)
 {
 {
 	glColor4ubv(&c.r);
 	glColor4ubv(&c.r);
-	curColor = c;
+	state.color = c;
 }
 }
 
 
-Color getCurrentColor()
+Color OpenGL::getColor()
 {
 {
-	return curColor;
+	return state.color;
 }
 }
 
 
-void setActiveTextureUnit(int textureunit)
+void OpenGL::setActiveTextureUnit(int textureunit)
 {
 {
-	if (textureunit < 0 || (size_t) textureunit >= textureUnits.size())
+	if (textureunit < 0 || (size_t) textureunit >= state.textureUnits.size())
 		throw love::Exception("Invalid texture unit index (%d).", textureunit);
 		throw love::Exception("Invalid texture unit index (%d).", textureunit);
 
 
-	if (textureunit != curTextureUnit)
+	if (textureunit != state.curTextureUnit)
 	{
 	{
-		if (textureUnits.size() > 1)
+		if (state.textureUnits.size() > 1)
 			glActiveTexture(GL_TEXTURE0 + textureunit);
 			glActiveTexture(GL_TEXTURE0 + textureunit);
 		else
 		else
 			throw love::Exception("Multitexturing not supported.");
 			throw love::Exception("Multitexturing not supported.");
 	}
 	}
 
 
-	curTextureUnit = textureunit;
+	state.curTextureUnit = textureunit;
 }
 }
 
 
-void bindTexture(GLuint texture)
+void OpenGL::bindTexture(GLuint texture)
 {
 {
-	if (texture != textureUnits[curTextureUnit])
+	if (texture != state.textureUnits[state.curTextureUnit])
 	{
 	{
-		textureUnits[curTextureUnit] = texture;
+		state.textureUnits[state.curTextureUnit] = texture;
 		glBindTexture(GL_TEXTURE_2D, texture);
 		glBindTexture(GL_TEXTURE_2D, texture);
 	}
 	}
 }
 }
 
 
-void bindTextureToUnit(GLuint texture, int textureunit, bool restoreprev)
+void OpenGL::bindTextureToUnit(GLuint texture, int textureunit, bool restoreprev)
 {
 {
-	if (textureunit < 0 || (size_t) textureunit >= textureUnits.size())
+	if (textureunit < 0 || (size_t) textureunit >= state.textureUnits.size())
 		throw love::Exception("Invalid texture unit index.");
 		throw love::Exception("Invalid texture unit index.");
 
 
-	if (texture != textureUnits[textureunit])
+	if (texture != state.textureUnits[textureunit])
 	{
 	{
-		int oldtextureunit = curTextureUnit;
+		int oldtextureunit = state.curTextureUnit;
 		setActiveTextureUnit(textureunit);
 		setActiveTextureUnit(textureunit);
 
 
-		textureUnits[textureunit] = texture;
+		state.textureUnits[textureunit] = texture;
 		glBindTexture(GL_TEXTURE_2D, texture);
 		glBindTexture(GL_TEXTURE_2D, texture);
 
 
 		if (restoreprev)
 		if (restoreprev)
@@ -198,11 +215,12 @@ void bindTextureToUnit(GLuint texture, int textureunit, bool restoreprev)
 	}
 	}
 }
 }
 
 
-void deleteTexture(GLuint texture)
+void OpenGL::deleteTexture(GLuint texture)
 {
 {
-	// glDeleteTextures binds texture 0 to all texture units the deleted texture was bound to
+	// glDeleteTextures binds texture 0 to all texture units the deleted texture
+	// was bound to before deletion.
 	std::vector<GLuint>::iterator it;
 	std::vector<GLuint>::iterator it;
-	for (it = textureUnits.begin(); it != textureUnits.end(); ++it)
+	for (it = state.textureUnits.begin(); it != state.textureUnits.end(); ++it)
 	{
 	{
 		if (*it == texture)
 		if (*it == texture)
 			*it = 0;
 			*it = 0;
@@ -211,7 +229,7 @@ void deleteTexture(GLuint texture)
 	glDeleteTextures(1, &texture);
 	glDeleteTextures(1, &texture);
 }
 }
 
 
-float setTextureFilter(const graphics::Image::Filter &f)
+float OpenGL::setTextureFilter(const graphics::Image::Filter &f)
 {
 {
 	GLint gmin, gmag;
 	GLint gmin, gmag;
 
 
@@ -262,7 +280,7 @@ float setTextureFilter(const graphics::Image::Filter &f)
 	return anisotropy;
 	return anisotropy;
 }
 }
 
 
-graphics::Image::Filter getTextureFilter()
+graphics::Image::Filter OpenGL::getTextureFilter()
 {
 {
 	GLint gmin, gmag;
 	GLint gmin, gmag;
 	glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, &gmin);
 	glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, &gmin);
@@ -314,7 +332,7 @@ graphics::Image::Filter getTextureFilter()
 	return f;
 	return f;
 }
 }
 
 
-void setTextureWrap(const graphics::Image::Wrap &w)
+void OpenGL::setTextureWrap(const graphics::Image::Wrap &w)
 {
 {
 	GLint gs, gt;
 	GLint gs, gt;
 
 
@@ -344,7 +362,7 @@ void setTextureWrap(const graphics::Image::Wrap &w)
 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, gt);
 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, gt);
 }
 }
 
 
-graphics::Image::Wrap getTextureWrap()
+graphics::Image::Wrap OpenGL::getTextureWrap()
 {
 {
 	GLint gs, gt;
 	GLint gs, gt;
 
 

+ 113 - 67
src/modules/graphics/opengl/OpenGL.h

@@ -23,9 +23,13 @@
 
 
 #include "GLee.h"
 #include "GLee.h"
 
 
+// LOVE
 #include "graphics/Color.h"
 #include "graphics/Color.h"
 #include "graphics/Image.h"
 #include "graphics/Image.h"
 
 
+// STL
+#include <vector>
+
 namespace love
 namespace love
 {
 {
 namespace graphics
 namespace graphics
@@ -34,76 +38,118 @@ namespace opengl
 {
 {
 
 
 /**
 /**
- * Initializes some required context state,
- * based on current and default OpenGL state.
- **/
-void initializeContext();
-
-/**
- * Marks current context state as invalid.
- **/
-void uninitializeContext();
-
-/**
- * Sets the current constant color.
- **/
-void setCurrentColor(const Color &c);
-
-/**
- * Gets the current constant color.
- **/
-Color getCurrentColor();
-
-/**
- * Helper for setting the active texture unit.
- *
- * @param textureunit Index in the range of [0, maxtextureunits-1]
- **/
-void setActiveTextureUnit(int textureunit);
-
-/**
- * Helper for binding an OpenGL texture.
- * Makes sure we aren't redundantly binding textures.
+ * Thin layer between OpenGL and the rest of the program.
+ * Internally shadows some OpenGL context state for improved efficiency and
+ * accuracy (compared to glGet etc.)
+ * A class is more convenient and readable than plain namespaced functions, but
+ * typically only one OpenGL object should be used (singleton.)
  **/
  **/
-void bindTexture(GLuint texture);
-
-/**
- * Helper for binding a texture to a specific texture unit.
- *
- * @param textureunit Index in the range of [0, maxtextureunits-1]
- * @param resoreprev Restore previously bound texture unit when done.
- **/
-void bindTextureToUnit(GLuint texture, int textureunit, bool restoreprev);
-
-/**
- * Helper for deleting an OpenGL texture.
- * Cleans up if the texture is currently bound.
- **/
-void deleteTexture(GLuint texture);
-
-/**
- * Sets the image filter mode for the currently bound texture.
- * Returns the actual amount of anisotropic filtering set.
- */
-float setTextureFilter(const graphics::Image::Filter &f);
-
-/**
- * Returns the image filter mode for the currently bound texture.
- */
-graphics::Image::Filter getTextureFilter();
-
-/**
- * Sets the image wrap mode for the currently bound texture.
- */
-void setTextureWrap(const graphics::Image::Wrap &w);
-
-/**
- * Returns the image wrap mode for the currently bound texture.
- */
-graphics::Image::Wrap getTextureWrap();
+class OpenGL
+{
+public:
+
+	OpenGL();
+
+	/**
+	 * Initializes some required context state based on current and default
+	 * OpenGL state. Call this directly after creating an OpenGL context!
+	 **/
+	void initContext();
+
+	/**
+	 * Marks current context state as invalid and deletes OpenGL objects owned
+	 * by this class instance. Call this directly before potentially deleting
+	 * an OpenGL context!
+	 **/
+	void deInitContext();
+
+	/**
+	 * Sets the current constant color.
+	 **/
+	void setColor(const Color &c);
+
+	/**
+	 * Gets the current constant color.
+	 **/
+	Color getColor();
+
+	/**
+	 * Helper for setting the active texture unit.
+	 *
+	 * @param textureunit Index in the range of [0, maxtextureunits-1]
+	 **/
+	void setActiveTextureUnit(int textureunit);
+
+	/**
+	 * Helper for binding an OpenGL texture.
+	 * Makes sure we aren't redundantly binding textures.
+	 **/
+	void bindTexture(GLuint texture);
+
+	/**
+	 * Helper for binding a texture to a specific texture unit.
+	 *
+	 * @param textureunit Index in the range of [0, maxtextureunits-1]
+	 * @param resoreprev Restore previously bound texture unit when done.
+	 **/
+	void bindTextureToUnit(GLuint texture, int textureunit, bool restoreprev);
+
+	/**
+	 * Helper for deleting an OpenGL texture.
+	 * Cleans up if the texture is currently bound.
+	 **/
+	void deleteTexture(GLuint texture);
+
+	/**
+	 * Sets the image filter mode for the currently bound texture.
+	 * Returns the actual amount of anisotropic filtering set.
+	 */
+	float setTextureFilter(const graphics::Image::Filter &f);
+
+	/**
+	 * Returns the image filter mode for the currently bound texture.
+	 */
+	graphics::Image::Filter getTextureFilter();
+
+	/**
+	 * Sets the image wrap mode for the currently bound texture.
+	 */
+	void setTextureWrap(const graphics::Image::Wrap &w);
+
+	/**
+	 * Returns the image wrap mode for the currently bound texture.
+	 */
+	graphics::Image::Wrap getTextureWrap();
+
+private:
+
+	void initOpenGLFunctions();
+	void createDefaultTexture();
+
+	bool contexInitialized;
+	float maxAnisotropy;
+
+	// Tracked OpenGL state.
+	struct
+	{
+		// Current constant color.
+		Color color;
+
+		// Texture unit state (currently bound texture for each texture unit.)
+		std::vector<GLuint> textureUnits;
+
+		// Currently active texture unit.
+		int curTextureUnit;
+
+	} state;
+
+}; // OpenGL
+
+// OpenGL class instance singleton.
+extern OpenGL gl;
 
 
 } // opengl
 } // opengl
 } // graphics
 } // graphics
 } // love
 } // love
 
 
-#endif
+#endif // LOVE_GRAPHICS_OPENGL_OPENGL_H

+ 2 - 2
src/modules/graphics/opengl/ParticleSystem.cpp

@@ -516,7 +516,7 @@ void ParticleSystem::draw(float x, float y, float angle, float sx, float sy, flo
 	int numParticles = count();
 	int numParticles = count();
 	if (numParticles == 0) return; // don't bother if there's nothing to do
 	if (numParticles == 0) return; // don't bother if there's nothing to do
 
 
-	Color curcolor = opengl::getCurrentColor();
+	Color curcolor = gl.getColor();
 
 
 	glPushMatrix();
 	glPushMatrix();
 
 
@@ -581,7 +581,7 @@ void ParticleSystem::draw(float x, float y, float angle, float sx, float sy, flo
 
 
 	glPopMatrix();
 	glPopMatrix();
 
 
-	opengl::setCurrentColor(curcolor);
+	gl.setColor(curcolor);
 }
 }
 
 
 void ParticleSystem::update(float dt)
 void ParticleSystem::update(float dt)

+ 4 - 4
src/modules/graphics/opengl/Shader.cpp

@@ -293,9 +293,9 @@ void Shader::attach(bool temporary)
 		for (size_t i = 0; i < activeTextureUnits.size(); ++i)
 		for (size_t i = 0; i < activeTextureUnits.size(); ++i)
 		{
 		{
 			if (activeTextureUnits[i] > 0)
 			if (activeTextureUnits[i] > 0)
-				bindTextureToUnit(activeTextureUnits[i], i + 1, false);
+				gl.bindTextureToUnit(activeTextureUnits[i], i + 1, false);
 		}
 		}
-		setActiveTextureUnit(0);
+		gl.setActiveTextureUnit(0);
 	}
 	}
 }
 }
 
 
@@ -372,11 +372,11 @@ void Shader::sendTexture(const std::string &name, GLuint texture)
 	int textureunit = getTextureUnit(name);
 	int textureunit = getTextureUnit(name);
 
 
 	// bind texture to assigned texture unit and send uniform to shader program
 	// bind texture to assigned texture unit and send uniform to shader program
-	bindTextureToUnit(texture, textureunit, false);
+	gl.bindTextureToUnit(texture, textureunit, false);
 	glUniform1i(location, textureunit);
 	glUniform1i(location, textureunit);
 
 
 	// reset texture unit
 	// reset texture unit
-	setActiveTextureUnit(0);
+	gl.setActiveTextureUnit(0);
 
 
 	// throw error if needed
 	// throw error if needed
 	checkSetUniformError();
 	checkSetUniformError();

+ 2 - 2
src/modules/graphics/opengl/SpriteBatch.cpp

@@ -218,7 +218,7 @@ void SpriteBatch::draw(float x, float y, float angle, float sx, float sy, float
 	VertexBuffer::Bind array_bind(*array_buf);
 	VertexBuffer::Bind array_bind(*array_buf);
 	VertexBuffer::Bind element_bind(*element_buf->getVertexBuffer());
 	VertexBuffer::Bind element_bind(*element_buf->getVertexBuffer());
 
 
-	Color curcolor = opengl::getCurrentColor();
+	Color curcolor = gl.getColor();
 
 
 	// Apply per-sprite color, if a color is set.
 	// Apply per-sprite color, if a color is set.
 	if (color)
 	if (color)
@@ -241,7 +241,7 @@ void SpriteBatch::draw(float x, float y, float angle, float sx, float sy, float
 	if (color)
 	if (color)
 	{
 	{
 		glDisableClientState(GL_COLOR_ARRAY);
 		glDisableClientState(GL_COLOR_ARRAY);
-		opengl::setCurrentColor(curcolor);
+		gl.setColor(curcolor);
 	}
 	}
 
 
 	glPopMatrix();
 	glPopMatrix();