Commits

Alex Szpakowski committed a7567c5

improved GL texture binding api to take texture units into consideration

Comments (0)

Files changed (5)

src/modules/graphics/opengl/Graphics.cpp

 	, userMatrices(0)
 {
 	currentWindow = love::window::sdl::Window::getSingleton();
-
-	resetBoundTexture();
 }
 
 Graphics::~Graphics()
 	// Unload all volatile objects. These must be reloaded after
 	// the display mode change.
 	Volatile::unloadAll();
+	
+	uninitializeContext();
 
 	bool success = currentWindow->setWindow(width, height, fullscreen, vsync, fsaa);
 	// Regardless of failure, we'll have to set up OpenGL once again.
 	height = currentWindow->getHeight();
 
 	// Okay, setup OpenGL.
+	
+	initializeContext();
 
 	// Enable blending
 	glEnable(GL_BLEND);
 
 	// Enable textures
 	glEnable(GL_TEXTURE_2D);
+	setActiveTextureUnit(GL_TEXTURE0);
 
 	// Set the viewport to top-left corner
 	glViewport(0, 0, width, height);

src/modules/graphics/opengl/OpenGL.cpp

  * 3. This notice may not be removed or altered from any source distribution.
  **/
 
+#include <vector>
 #include "OpenGL.h"
+#include "common/Exception.h"
 
 namespace love
 {
 namespace opengl
 {
 
-static GLuint boundTexture = 0;
+static bool contextInitialized = false;
 
-void resetBoundTexture()
+static int curTextureUnitIndex = 0;
+static std::vector<GLuint> textureUnits;
+
+void initializeContext()
 {
-	// OpenGL might not be initialized yet, so we can't do a real reset
-	boundTexture = 0;
+	if (contextInitialized)
+		return;
+	
+	contextInitialized = true;
+	
+	if (GLEE_ARB_multitexture || GLEE_VERSION_1_3)
+	{
+		GLint maxtextureunits;
+		glGetIntegerv(GL_MAX_TEXTURE_UNITS, &maxtextureunits);
+		
+		if (GLEE_VERSION_2_0 || GLEE_ARB_vertex_shader)
+		{
+			GLint maxtextureimageunits;
+			glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &maxtextureimageunits);
+			
+			if (maxtextureimageunits > maxtextureunits)
+				maxtextureunits = maxtextureimageunits;
+		}
+		
+		textureUnits.resize(maxtextureunits, 0);
+		
+		GLenum activeTextureUnit;
+		glGetIntegerv(GL_ACTIVE_TEXTURE, (GLint *)&activeTextureUnit);
+		
+		curTextureUnitIndex = activeTextureUnit - GL_TEXTURE0;
+	}
+	else
+	{
+		// multitexturing not supported so we only have 1 texture unit
+		textureUnits.resize(1, 0);
+		curTextureUnitIndex = 0;
+	}
 }
 
-void bindTexture(GLuint texture, bool override)
+void uninitializeContext()
 {
-	if (texture != boundTexture || texture == 0 || override)
+	contextInitialized = false;
+}
+
+void setActiveTextureUnit(GLenum textureunit)
+{
+	initializeContext();
+	
+	int textureunitindex = textureunit - GL_TEXTURE0;
+	
+	if (textureunitindex < 0 || (size_t) textureunitindex >= textureUnits.size())
+		throw love::Exception("Invalid texture unit index.");
+	
+	if (textureunitindex != curTextureUnitIndex)
 	{
-		boundTexture = texture;
+		if (GLEE_VERSION_1_3)
+			glActiveTexture(textureunit);
+		else if (GLEE_ARB_multitexture)
+			glActiveTextureARB(textureunit);
+		else
+			throw love::Exception("Multitexturing not supported.");
+	}
+	
+	curTextureUnitIndex = textureunitindex;
+}
+
+void bindTexture(GLuint texture)
+{
+	initializeContext();
+	
+	if (texture != textureUnits[curTextureUnitIndex] || texture == 0)
+	{
+		textureUnits[curTextureUnitIndex] = texture;
 		glBindTexture(GL_TEXTURE_2D, texture);
 	}
 }
 
 void deleteTexture(GLuint texture)
 {
-	if (texture == boundTexture)
-		boundTexture = 0;
+	initializeContext();
+	
+	std::vector<GLuint>::iterator it;
+	for (it = textureUnits.begin(); it != textureUnits.end(); ++it)
+	{
+		if (*it == texture)
+			*it = 0;
+	}
 
 	glDeleteTextures(1, &texture);
 }

src/modules/graphics/opengl/OpenGL.h

 namespace opengl
 {
 
-// resets the stored bound texture id
-void resetBoundTexture();
+void initializeContext();
+
+void uninitializeContext();
+
+/**
+ * Helper for setting the active texture unit
+ * @param textureunit The GL texture unit to set
+ **/
+void setActiveTextureUnit(GLenum textureunit);
 
 /**
  * Helper for binding an OpenGL texture.
  * Makes sure we aren't redundantly binding textures.
  * @param texture The texture to bind.
- * @param override Overrides the checks to guarantee texture bind
  **/
-void bindTexture(GLuint texture, bool override = false);
+void bindTexture(GLuint texture);
 
 /**
  * Helper for deleting an OpenGL texture.

src/modules/graphics/opengl/ShaderEffect.cpp

 	
 	GLint texture_unit = getTextureUnit(name);
 	
-	glActiveTexture(GL_TEXTURE0 + texture_unit);
-	bindTexture(texture, true); // guarantee it gets bound
+	setActiveTextureUnit(GL_TEXTURE0 + texture_unit);
+	bindTexture(texture);
 	glUniform1i(location, texture_unit);
 	
 	// reset texture unit
-	glActiveTexture(GL_TEXTURE0);
+	setActiveTextureUnit(GL_TEXTURE0);
 	
 	// throw error if needed
 	checkSetUniformError();

src/modules/graphics/opengl/ShaderEffect.h

 
 	void attach();
 	static void detach();
+	
 	static std::string getGLSLVersion();
 	static bool isSupported();