Browse Source

opengl: scissor and color mask no longer affects love.graphics.clear.

This makes it more consistent with other backends.
Sasha Szpakowski 1 year ago
parent
commit
b8cbb62bc3

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

@@ -922,36 +922,23 @@ void Graphics::clear(OptionalColorD c, OptionalInt stencil, OptionalDouble depth
 		flags |= GL_COLOR_BUFFER_BIT;
 		flags |= GL_COLOR_BUFFER_BIT;
 	}
 	}
 
 
-	uint32 stencilwrites = gl.getStencilWriteMask();
-
 	if (stencil.hasValue)
 	if (stencil.hasValue)
 	{
 	{
-		if (stencilwrites != LOVE_UINT32_MAX)
-			gl.setStencilWriteMask(LOVE_UINT32_MAX);
-
 		glClearStencil(stencil.value);
 		glClearStencil(stencil.value);
 		flags |= GL_STENCIL_BUFFER_BIT;
 		flags |= GL_STENCIL_BUFFER_BIT;
 	}
 	}
 
 
-	bool hadDepthWrites = gl.hasDepthWrites();
-
 	if (depth.hasValue)
 	if (depth.hasValue)
 	{
 	{
-		if (!hadDepthWrites) // glDepthMask also affects glClear.
-			gl.setDepthWrites(true);
-
 		gl.clearDepth(depth.value);
 		gl.clearDepth(depth.value);
 		flags |= GL_DEPTH_BUFFER_BIT;
 		flags |= GL_DEPTH_BUFFER_BIT;
 	}
 	}
 
 
 	if (flags != 0)
 	if (flags != 0)
+	{
+		OpenGL::CleanClearState cs(flags);
 		glClear(flags);
 		glClear(flags);
-
-	if (stencil.hasValue && stencilwrites != LOVE_UINT32_MAX)
-		gl.setStencilWriteMask(stencilwrites);
-
-	if (depth.hasValue && !hadDepthWrites)
-		gl.setDepthWrites(hadDepthWrites);
+	}
 
 
 	if (c.hasValue && gl.bugs.clearRequiresDriverTextureStateUpdate && Shader::current)
 	if (c.hasValue && gl.bugs.clearRequiresDriverTextureStateUpdate && Shader::current)
 	{
 	{
@@ -1041,36 +1028,23 @@ void Graphics::clear(const std::vector<OptionalColorD> &colors, OptionalInt sten
 
 
 	GLbitfield flags = 0;
 	GLbitfield flags = 0;
 
 
-	uint32 stencilwrites = gl.getStencilWriteMask();
-
 	if (stencil.hasValue)
 	if (stencil.hasValue)
 	{
 	{
-		if (stencilwrites != LOVE_UINT32_MAX)
-			gl.setStencilWriteMask(LOVE_UINT32_MAX);
-
 		glClearStencil(stencil.value);
 		glClearStencil(stencil.value);
 		flags |= GL_STENCIL_BUFFER_BIT;
 		flags |= GL_STENCIL_BUFFER_BIT;
 	}
 	}
 
 
-	bool hadDepthWrites = gl.hasDepthWrites();
-
 	if (depth.hasValue)
 	if (depth.hasValue)
 	{
 	{
-		if (!hadDepthWrites) // glDepthMask also affects glClear.
-			gl.setDepthWrites(true);
-
 		gl.clearDepth(depth.value);
 		gl.clearDepth(depth.value);
 		flags |= GL_DEPTH_BUFFER_BIT;
 		flags |= GL_DEPTH_BUFFER_BIT;
 	}
 	}
 
 
 	if (flags != 0)
 	if (flags != 0)
+	{
+		OpenGL::CleanClearState cs(flags);
 		glClear(flags);
 		glClear(flags);
-
-	if (stencil.hasValue && stencilwrites != LOVE_UINT32_MAX)
-		gl.setStencilWriteMask(stencilwrites);
-
-	if (depth.hasValue && !hadDepthWrites)
-		gl.setDepthWrites(hadDepthWrites);
+	}
 
 
 	if (gl.bugs.clearRequiresDriverTextureStateUpdate && Shader::current)
 	if (gl.bugs.clearRequiresDriverTextureStateUpdate && Shader::current)
 	{
 	{
@@ -1568,7 +1542,11 @@ void Graphics::setColorMask(ColorChannelMask mask)
 {
 {
 	flushBatchedDraws();
 	flushBatchedDraws();
 
 
-	glColorMask(mask.r, mask.g, mask.b, mask.a);
+	uint32 maskbits =
+		((mask.r ? 1 : 0) << 1) | ((mask.g ? 1 : 0) << 2) |
+		((mask.g ? 1 : 0) << 3) | ((mask.a ? 1 : 0) << 4);
+
+	gl.setColorWriteMask(maskbits);
 	states.back().colorMask = mask;
 	states.back().colorMask = mask;
 }
 }
 
 

+ 49 - 0
src/modules/graphics/opengl/OpenGL.cpp

@@ -91,12 +91,49 @@ OpenGL::TempDebugGroup::~TempDebugGroup()
 	}
 	}
 }
 }
 
 
+OpenGL::CleanClearState::CleanClearState(GLbitfield clearFlags)
+	: clearFlags(clearFlags)
+	, colorWriteMask(gl.getColorWriteMask())
+	, stencilWriteMask(gl.getStencilWriteMask())
+	, depthWrites(gl.hasDepthWrites())
+	, scissor(gl.isStateEnabled(ENABLE_SCISSOR_TEST))
+{
+	if (clearFlags & GL_COLOR_BUFFER_BIT)
+		gl.setColorWriteMask(LOVE_UINT32_MAX);
+
+	if (clearFlags & GL_DEPTH_BUFFER_BIT)
+		gl.setDepthWrites(false);
+
+	if (clearFlags & GL_STENCIL_BUFFER_BIT)
+		gl.setStencilWriteMask(LOVE_UINT32_MAX);
+
+	if (clearFlags != 0)
+		gl.setEnableState(ENABLE_SCISSOR_TEST, false);
+}
+
+OpenGL::CleanClearState::~CleanClearState()
+{
+	if (clearFlags & GL_COLOR_BUFFER_BIT)
+		gl.setColorWriteMask(colorWriteMask);
+
+	if (clearFlags & GL_DEPTH_BUFFER_BIT)
+		gl.setDepthWrites(depthWrites);
+
+	if (clearFlags & GL_STENCIL_BUFFER_BIT)
+		gl.setStencilWriteMask(stencilWriteMask);
+
+	if (clearFlags != 0)
+		gl.setEnableState(ENABLE_SCISSOR_TEST, scissor);
+}
+
 OpenGL::OpenGL()
 OpenGL::OpenGL()
 	: stats()
 	: stats()
+	, bugs()
 	, contextInitialized(false)
 	, contextInitialized(false)
 	, pixelShaderHighpSupported(false)
 	, pixelShaderHighpSupported(false)
 	, baseVertexSupported(false)
 	, baseVertexSupported(false)
 	, maxAnisotropy(1.0f)
 	, maxAnisotropy(1.0f)
+	, maxLODBias(0.0f)
 	, max2DTextureSize(0)
 	, max2DTextureSize(0)
 	, max3DTextureSize(0)
 	, max3DTextureSize(0)
 	, maxCubeTextureSize(0)
 	, maxCubeTextureSize(0)
@@ -284,6 +321,7 @@ void OpenGL::setupContext()
 
 
 	setDepthWrites(state.depthWritesEnabled);
 	setDepthWrites(state.depthWritesEnabled);
 	setStencilWriteMask(state.stencilWriteMask);
 	setStencilWriteMask(state.stencilWriteMask);
+	setColorWriteMask(state.colorWriteMask);
 
 
 	createDefaultTexture();
 	createDefaultTexture();
 
 
@@ -1125,6 +1163,17 @@ uint32 OpenGL::getStencilWriteMask() const
 	return state.stencilWriteMask;
 	return state.stencilWriteMask;
 }
 }
 
 
+void OpenGL::setColorWriteMask(uint32 mask)
+{
+	glColorMask(mask & (1 << 0), mask & (1 << 1), mask & (1 << 2), mask & (1 << 3));
+	state.colorWriteMask = mask;
+}
+
+uint32 OpenGL::getColorWriteMask() const
+{
+	return state.colorWriteMask;
+}
+
 void OpenGL::useProgram(GLuint program)
 void OpenGL::useProgram(GLuint program)
 {
 {
 	glUseProgram(program);
 	glUseProgram(program);

+ 19 - 0
src/modules/graphics/opengl/OpenGL.h

@@ -124,6 +124,21 @@ public:
 		~TempDebugGroup();
 		~TempDebugGroup();
 	};
 	};
 
 
+	// glClear() is affected by various OpenGL state...
+	class CleanClearState
+	{
+	public:
+		CleanClearState(GLbitfield clearFlags);
+		~CleanClearState();
+
+	private:
+		GLenum clearFlags;
+		uint32 colorWriteMask;
+		uint32 stencilWriteMask;
+		bool depthWrites;
+		bool scissor;
+	};
+
 	struct Stats
 	struct Stats
 	{
 	{
 		int shaderSwitches;
 		int shaderSwitches;
@@ -301,6 +316,9 @@ public:
 	void setStencilWriteMask(uint32 mask);
 	void setStencilWriteMask(uint32 mask);
 	uint32 getStencilWriteMask() const;
 	uint32 getStencilWriteMask() const;
 
 
+	void setColorWriteMask(uint32 mask);
+	uint32 getColorWriteMask() const;
+
 	/**
 	/**
 	 * Calls glUseProgram.
 	 * Calls glUseProgram.
 	 **/
 	 **/
@@ -528,6 +546,7 @@ private:
 
 
 		bool depthWritesEnabled = true;
 		bool depthWritesEnabled = true;
 		uint32 stencilWriteMask = LOVE_UINT32_MAX;
 		uint32 stencilWriteMask = LOVE_UINT32_MAX;
+		uint32 colorWriteMask = LOVE_UINT32_MAX;
 
 
 		GLuint boundFramebuffers[2];
 		GLuint boundFramebuffers[2];
 
 

+ 15 - 26
src/modules/graphics/opengl/Texture.cpp

@@ -80,31 +80,22 @@ static GLenum createFBO(GLuint &framebuffer, TextureType texType, PixelFormat fo
 
 
 					if (clear)
 					if (clear)
 					{
 					{
-						if (isPixelFormatDepthStencil(format))
-						{
-							bool hadDepthWrites = gl.hasDepthWrites();
-							if (!hadDepthWrites) // glDepthMask also affects glClear.
-								gl.setDepthWrites(true);
+						bool ds = isPixelFormatDepthStencil(format);
 
 
-							uint32 stencilwrite = gl.getStencilWriteMask();
-							if (stencilwrite != LOVE_UINT32_MAX)
-								gl.setStencilWriteMask(LOVE_UINT32_MAX);
+						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);
 							gl.clearDepth(1.0);
 							glClearStencil(0);
 							glClearStencil(0);
-							glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
-
-							if (!hadDepthWrites)
-								gl.setDepthWrites(hadDepthWrites);
-
-							if (stencilwrite != LOVE_UINT32_MAX)
-								gl.setStencilWriteMask(stencilwrite);
 						}
 						}
 						else
 						else
 						{
 						{
 							glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
 							glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
-							glClear(GL_COLOR_BUFFER_BIT);
 						}
 						}
+
+						glClear(clearflags);
 					}
 					}
 				}
 				}
 			}
 			}
@@ -167,25 +158,23 @@ static GLenum newRenderbuffer(int width, int height, int &samples, PixelFormat p
 
 
 	if (status == GL_FRAMEBUFFER_COMPLETE)
 	if (status == GL_FRAMEBUFFER_COMPLETE)
 	{
 	{
-		if (isPixelFormatDepthStencil(pixelformat))
-		{
-			bool hadDepthWrites = gl.hasDepthWrites();
-			if (!hadDepthWrites) // glDepthMask also affects glClear.
-				gl.setDepthWrites(true);
+		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)
+		{
 			gl.clearDepth(1.0);
 			gl.clearDepth(1.0);
 			glClearStencil(0);
 			glClearStencil(0);
-			glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
-
-			if (!hadDepthWrites)
-				gl.setDepthWrites(hadDepthWrites);
 		}
 		}
 		else
 		else
 		{
 		{
 			// Initialize the buffer to transparent black.
 			// Initialize the buffer to transparent black.
 			glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
 			glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
-			glClear(GL_COLOR_BUFFER_BIT);
 		}
 		}
+
+		glClear(clearflags);
 	}
 	}
 	else
 	else
 	{
 	{