Commits

vrld committed 0a0b2c3

Fix #756: Sending an Image to a shader does not retain it

Each shader contains a map of uniform name -> bound retainable Object. After
setting the uniform, sendImage() and sendCanvas() release() the Object with
the requested name (if present) and record the new Image/Canvas.

Related bugfix: Shader::attach() calls retain()/release() on the shader.

  • Participants
  • Parent commits e2c1520

Comments (0)

Files changed (2)

src/modules/graphics/opengl/Shader.cpp

 	if (current == this)
 		detach();
 
+	for (auto it = boundRetainables.begin(); it != boundRetainables.end(); ++it)
+	{
+		it->second->release();
+		boundRetainables.erase(it);
+	}
+
 	unloadVolatile();
 }
 
 {
 	if (current != this)
 	{
+		if (current != NULL)
+			current->release();
+
 		glUseProgram(program);
 		current = this;
+
+		current->retain();
 	}
 
 	if (!temporary)
 	activeTextureUnits[textureunit-1] = texture;
 }
 
-void Shader::sendImage(const std::string &name, const Image &image)
+void Shader::retainTexture(const std::string &name, Object *texture)
+{
+	auto it = boundRetainables.find(name);
+	if (it != boundRetainables.end())
+		it->second->release();
+
+	texture->retain();
+	boundRetainables[name] = texture;
+}
+
+void Shader::sendImage(const std::string &name, Image &image)
 {
 	sendTexture(name, image.getTextureName());
+	retainTexture(name, &image);
 }
 
-void Shader::sendCanvas(const std::string &name, const Canvas &canvas)
+void Shader::sendCanvas(const std::string &name, Canvas &canvas)
 {
 	sendTexture(name, canvas.getTextureName());
+	retainTexture(name, &canvas);
 }
 
 int Shader::getTextureUnit(const std::string &name)

src/modules/graphics/opengl/Shader.h

 	 *
 	 * @param name The name of the uniform variable in the source code.
 	 **/
-	void sendImage(const std::string &name, const Image &image);
+	void sendImage(const std::string &name, Image &image);
 
 	/**
 	 * Send a canvas to this Shader as a uniform.
 	 *
 	 * @param name The name of the uniform variable in the source code.
 	 **/
-	void sendCanvas(const std::string &name, const Canvas &canvas);
+	void sendCanvas(const std::string &name, Canvas &canvas);
 
 	static std::string getGLSLVersion();
 	static bool isSupported();
 	int getTextureUnit(const std::string &name);
 
 	void sendTexture(const std::string &name, GLuint texture);
+	void retainTexture(const std::string &name, Object *texture);
 
 	// Get any warnings or errors generated only by the shader program object.
 	std::string getProgramWarnings() const;
 	std::map<std::string, GLint> textureUnitPool; // textureUnitPool[name] = textureunit
 	std::vector<GLuint> activeTextureUnits; // activeTextureUnits[textureunit-1] = textureid
 
+	// Uniform name to retainable objects
+	std::map<std::string, Object*> boundRetainables;
+
 	// Max GPU texture units available for sent images
 	static GLint maxTextureUnits;