Browse Source

opengl: fix clearing integer format Canvases.

Sasha Szpakowski 1 year ago
parent
commit
2789e5eabf
2 changed files with 68 additions and 13 deletions
  1. 24 0
      src/modules/graphics/opengl/Graphics.cpp
  2. 44 13
      src/modules/graphics/opengl/Texture.cpp

+ 24 - 0
src/modules/graphics/opengl/Graphics.cpp

@@ -909,6 +909,30 @@ void Graphics::endPass(bool presenting)
 
 
 void Graphics::clear(OptionalColorD c, OptionalInt stencil, OptionalDouble depth)
 void Graphics::clear(OptionalColorD c, OptionalInt stencil, OptionalDouble depth)
 {
 {
+	if (c.hasValue)
+	{
+		bool hasintegerformat = false;
+
+		const auto &rts = states.back().renderTargets;
+		for (const auto &rt : rts.colors)
+		{
+			if (rt.texture.get() && isPixelFormatInteger(rt.texture->getPixelFormat()))
+				hasintegerformat = true;
+		}
+
+		// This variant of clear() uses glClear() which can't clear integer formats,
+		// so we switch to the MRT variant if needed.
+		if (hasintegerformat)
+		{
+			std::vector<OptionalColorD> colors(rts.colors.size());
+			for (size_t i = 0; i < colors.size(); i++)
+				colors[i] = c;
+
+			clear(colors, stencil, depth);
+			return;
+		}
+	}
+
 	if (c.hasValue || stencil.hasValue || depth.hasValue)
 	if (c.hasValue || stencil.hasValue || depth.hasValue)
 		flushBatchedDraws();
 		flushBatchedDraws();
 
 

+ 44 - 13
src/modules/graphics/opengl/Texture.cpp

@@ -78,7 +78,21 @@ static GLenum createFBO(GLuint &framebuffer, TextureType texType, PixelFormat fo
 						gl.framebufferTexture(attachment, texType, texture, mip, layer, face);
 						gl.framebufferTexture(attachment, texType, texture, mip, layer, face);
 					}
 					}
 
 
-					if (clear)
+					if (clear && isPixelFormatInteger(format))
+					{
+						PixelFormatType datatype = getPixelFormatInfo(format).dataType;
+						if (datatype == PIXELFORMATTYPE_SINT)
+						{
+							const GLint carray[] = { 0, 0, 0, 0 };
+							glClearBufferiv(GL_COLOR, 0, carray);
+						}
+						else
+						{
+							const GLuint carray[] = { 0, 0, 0, 0 };
+							glClearBufferuiv(GL_COLOR, 0, carray);
+						}
+					}
+					else if (clear)
 					{
 					{
 						bool ds = isPixelFormatDepthStencil(format);
 						bool ds = isPixelFormatDepthStencil(format);
 
 
@@ -158,23 +172,40 @@ static GLenum newRenderbuffer(int width, int height, int &samples, PixelFormat p
 
 
 	if (status == GL_FRAMEBUFFER_COMPLETE)
 	if (status == GL_FRAMEBUFFER_COMPLETE)
 	{
 	{
-		bool ds = isPixelFormatDepthStencil(pixelformat);
-
-		GLbitfield clearflags = ds ? GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT : GL_COLOR_BUFFER_BIT;
-		OpenGL::CleanClearState cleanClearState(clearflags);
-
-		if (ds)
+		if (isPixelFormatInteger(pixelformat))
 		{
 		{
-			gl.clearDepth(1.0);
-			glClearStencil(0);
+			PixelFormatType datatype = getPixelFormatInfo(pixelformat).dataType;
+			if (datatype == PIXELFORMATTYPE_SINT)
+			{
+				const GLint carray[] = { 0, 0, 0, 0 };
+				glClearBufferiv(GL_COLOR, 0, carray);
+			}
+			else
+			{
+				const GLuint carray[] = { 0, 0, 0, 0 };
+				glClearBufferuiv(GL_COLOR, 0, carray);
+			}
 		}
 		}
 		else
 		else
 		{
 		{
-			// Initialize the buffer to transparent black.
-			glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
-		}
+			bool ds = isPixelFormatDepthStencil(pixelformat);
 
 
-		glClear(clearflags);
+			GLbitfield clearflags = ds ? GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT : GL_COLOR_BUFFER_BIT;
+			OpenGL::CleanClearState cleanClearState(clearflags);
+
+			if (ds)
+			{
+				gl.clearDepth(1.0);
+				glClearStencil(0);
+			}
+			else
+			{
+				// Initialize the buffer to transparent black.
+				glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+			}
+
+			glClear(clearflags);
+		}
 	}
 	}
 	else
 	else
 	{
 	{