Commits

Alex Szpakowski  committed e9c6084

Separated canvas texture creation code from FBO creation code

  • Participants
  • Parent commits be602a7

Comments (0)

Files changed (2)

File src/modules/graphics/opengl/Canvas.cpp

 
 	/// create a new framebuffer and texture
 	/**
-	 * @param[out] framebuffer   Framebuffer name
-	 * @param[out] img           Texture name
-	 * @param[in]  width         Width of framebuffer
-	 * @param[in]  height        Height of framebuffer
-	 * @param[in]  texture_type  Type of the canvas texture.
+	 * @param[out] framebuffer Framebuffer name
+	 * @param[in]  texture     Texture name
 	 * @return Creation status
 	 */
-	virtual GLenum createFBO(GLuint &, GLuint &, int, int, Canvas::TextureType)
+	virtual GLenum createFBO(GLuint &, GLuint)
 	{
 		return GL_FRAMEBUFFER_UNSUPPORTED;
 	}
 	/**
 	 * @param[in] framebuffer   Framebuffer name
 	 * @param[in] depth_stencil Name for packed depth and stencil buffer
-	 * @param[in] img           Texture name
 	 */
-	virtual void deleteFBO(GLuint, GLuint, GLuint) {}
+	virtual void deleteFBO(GLuint, GLuint) {}
 	virtual void bindFBO(GLuint) {}
 
 	/// attach additional canvases to the active framebuffer for rendering
 
 struct FramebufferStrategyGL3 : public FramebufferStrategy
 {
-	virtual GLenum createFBO(GLuint &framebuffer, GLuint &img, int width, int height, Canvas::TextureType texture_type)
+	virtual GLenum createFBO(GLuint &framebuffer, GLuint texture)
 	{
 		// get currently bound fbo to reset to it later
 		GLint current_fbo;
 		glGenFramebuffers(1, &framebuffer);
 		glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
 
-		// generate texture save target
-		GLint internalFormat;
-		GLenum format;
-		switch (texture_type)
-		{
-		case Canvas::TYPE_HDR:
-			internalFormat = GL_RGBA16F;
-			format = GL_FLOAT;
-			break;
-		case Canvas::TYPE_NORMAL:
-		default:
-			internalFormat = GL_RGBA8;
-			format = GL_UNSIGNED_BYTE;
-		}
-
-		glGenTextures(1, &img);
-		gl.bindTexture(img);
-
-		Texture::Filter filter = Texture::getDefaultFilter();
-		gl.setTextureFilter(filter);
-
-		glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, width, height,
-			0, GL_RGBA, format, NULL);
-		gl.bindTexture(0);
 		glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
-			GL_TEXTURE_2D, img, 0);
+			GL_TEXTURE_2D, texture, 0);
 
 		// check status
 		GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
 		return glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE;
 	}
 
-	virtual void deleteFBO(GLuint framebuffer, GLuint depth_stencil,  GLuint img)
+	virtual void deleteFBO(GLuint framebuffer, GLuint depth_stencil)
 	{
-		gl.deleteTexture(img);
 		if (depth_stencil != 0)
 			glDeleteRenderbuffers(1, &depth_stencil);
 		if (framebuffer != 0)
 
 struct FramebufferStrategyPackedEXT : public FramebufferStrategy
 {
-	virtual GLenum createFBO(GLuint &framebuffer, GLuint &img, int width, int height, Canvas::TextureType texture_type)
+	virtual GLenum createFBO(GLuint &framebuffer, GLuint texture)
 	{
 		GLint current_fbo;
 		glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING_EXT, &current_fbo);
 		glGenFramebuffersEXT(1, &framebuffer);
 		glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, framebuffer);
 
-		// generate texture save target
-		GLint internalFormat;
-		GLenum format;
-		switch (texture_type)
-		{
-		case Canvas::TYPE_HDR:
-			internalFormat = GL_RGBA16F;
-			format = GL_FLOAT;
-			break;
-		case Canvas::TYPE_NORMAL:
-		default:
-			internalFormat = GL_RGBA8;
-			format = GL_UNSIGNED_BYTE;
-		}
-
-		glGenTextures(1, &img);
-		gl.bindTexture(img);
-
-		Texture::Filter filter = Texture::getDefaultFilter();
-		gl.setTextureFilter(filter);
-
-		glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, width, height,
-			0, GL_RGBA, format, NULL);
-		gl.bindTexture(0);
 		glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
-			GL_TEXTURE_2D, img, 0);
+			GL_TEXTURE_2D, texture, 0);
 
 		// check status
 		GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
 		return glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) == GL_FRAMEBUFFER_COMPLETE_EXT;
 	}
 
-	virtual void deleteFBO(GLuint framebuffer, GLuint depth_stencil, GLuint img)
+	virtual void deleteFBO(GLuint framebuffer, GLuint depth_stencil)
 	{
-		gl.deleteTexture(img);
 		if (depth_stencil != 0)
 			glDeleteRenderbuffersEXT(1, &depth_stencil);
 		if (framebuffer != 0)
 
 	bool isSupported()
 	{
-		GLuint fb = 0, stencil = 0, img = 0;
-		GLenum status = createFBO(fb, img, 2, 2, Canvas::TYPE_NORMAL);
-		deleteFBO(fb, stencil, img);
+		GLuint fb = 0, stencil = 0;
+		GLenum status = createFBO(fb, 0);
+		deleteFBO(fb, stencil);
 		return status == GL_FRAMEBUFFER_COMPLETE;
 	}
 };
 
 Canvas::Canvas(int width, int height, TextureType texture_type)
 	: fbo(0)
+	, texture(0)
 	, depth_stencil(0)
-	, img(0)
 	, texture_type(texture_type)
 {
 	this->width = width;
 
 bool Canvas::loadVolatile()
 {
-	fbo = depth_stencil = img = 0;
+	fbo = depth_stencil = texture = 0;
 
 	// glTexImage2D is guaranteed to error in this case.
 	if (width > gl.getMaxTextureSize() || height > gl.getMaxTextureSize())
 		return false;
 	}
 
-	status = strategy->createFBO(fbo, img, width, height, texture_type);
+	glGenTextures(1, &texture);
+	gl.bindTexture(texture);
+
+	setFilter(filter);
+	setWrap(wrap);
+
+	GLint internalformat;
+	GLenum textype;
+	switch (texture_type)
+	{
+	case TYPE_HDR:
+		internalformat = GL_RGBA16F;
+		textype = GL_FLOAT;
+		break;
+	case TYPE_NORMAL:
+	default:
+		internalformat = GL_RGBA8;
+		textype = GL_UNSIGNED_BYTE;
+	}
+
+	while (glGetError() != GL_NO_ERROR)
+		/* Clear the error buffer. */;
+
+	glTexImage2D(GL_TEXTURE_2D,
+	             0,
+	             internalformat,
+	             width, height,
+	             0,
+	             GL_RGBA,
+	             textype,
+	             nullptr);
+
+	if (glGetError() != GL_NO_ERROR)
+	{
+		status = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+		return false;
+	}
+
+	status = strategy->createFBO(fbo, texture);
 	if (status != GL_FRAMEBUFFER_COMPLETE)
 		return false;
 
-	setFilter(filter);
-	setWrap(wrap);
 	clear(Color(0, 0, 0, 0));
 	return true;
 }
 
 void Canvas::unloadVolatile()
 {
-	strategy->deleteFBO(fbo, depth_stencil, img);
-	fbo = depth_stencil = img = 0;
+	strategy->deleteFBO(fbo, depth_stencil);
+
+	gl.deleteTexture(texture);
+
+	fbo = depth_stencil = texture = 0;
 
 	for (size_t i = 0; i < attachedCanvases.size(); i++)
 		attachedCanvases[i]->release();
 
 	glMultMatrixf((const GLfloat *)t.getElements());
 
-	gl.bindTexture(img);
+	gl.bindTexture(texture);
 
 	glEnableClientState(GL_VERTEX_ARRAY);
 	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
 void Canvas::setFilter(const Texture::Filter &f)
 {
 	filter = f;
-	gl.bindTexture(img);
+	gl.bindTexture(texture);
 	gl.setTextureFilter(filter);
 }
 
 void Canvas::setWrap(const Texture::Wrap &w)
 {
 	wrap = w;
-	gl.bindTexture(img);
+	gl.bindTexture(texture);
 	gl.setTextureWrap(wrap);
 }
 
 GLuint Canvas::getGLTexture() const
 {
-	return img;
+	return texture;
 }
 
 void Canvas::predraw() const
 {
-	gl.bindTexture(img);
+	gl.bindTexture(texture);
 }
 
 void Canvas::setupGrab()

File src/modules/graphics/opengl/Canvas.h

 private:
 
 	GLuint fbo;
+	GLuint texture;
 	GLuint depth_stencil;
-	GLuint img;
 
 	TextureType texture_type;