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

This makes it more consistent with other backends.
This commit is contained in:
Sasha Szpakowski
2023-10-08 21:08:59 -03:00
parent 27c4569697
commit b8cbb62bc3
4 changed files with 95 additions and 60 deletions
+11 -33
View File
@@ -922,36 +922,23 @@ void Graphics::clear(OptionalColorD c, OptionalInt stencil, OptionalDouble depth
flags |= GL_COLOR_BUFFER_BIT;
}
uint32 stencilwrites = gl.getStencilWriteMask();
if (stencil.hasValue)
{
if (stencilwrites != LOVE_UINT32_MAX)
gl.setStencilWriteMask(LOVE_UINT32_MAX);
glClearStencil(stencil.value);
flags |= GL_STENCIL_BUFFER_BIT;
}
bool hadDepthWrites = gl.hasDepthWrites();
if (depth.hasValue)
{
if (!hadDepthWrites) // glDepthMask also affects glClear.
gl.setDepthWrites(true);
gl.clearDepth(depth.value);
flags |= GL_DEPTH_BUFFER_BIT;
}
if (flags != 0)
{
OpenGL::CleanClearState cs(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)
{
@@ -1041,36 +1028,23 @@ void Graphics::clear(const std::vector<OptionalColorD> &colors, OptionalInt sten
GLbitfield flags = 0;
uint32 stencilwrites = gl.getStencilWriteMask();
if (stencil.hasValue)
{
if (stencilwrites != LOVE_UINT32_MAX)
gl.setStencilWriteMask(LOVE_UINT32_MAX);
glClearStencil(stencil.value);
flags |= GL_STENCIL_BUFFER_BIT;
}
bool hadDepthWrites = gl.hasDepthWrites();
if (depth.hasValue)
{
if (!hadDepthWrites) // glDepthMask also affects glClear.
gl.setDepthWrites(true);
gl.clearDepth(depth.value);
flags |= GL_DEPTH_BUFFER_BIT;
}
if (flags != 0)
{
OpenGL::CleanClearState cs(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)
{
@@ -1568,7 +1542,11 @@ void Graphics::setColorMask(ColorChannelMask mask)
{
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;
}
+49
View File
@@ -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()
: stats()
, bugs()
, contextInitialized(false)
, pixelShaderHighpSupported(false)
, baseVertexSupported(false)
, maxAnisotropy(1.0f)
, maxLODBias(0.0f)
, max2DTextureSize(0)
, max3DTextureSize(0)
, maxCubeTextureSize(0)
@@ -284,6 +321,7 @@ void OpenGL::setupContext()
setDepthWrites(state.depthWritesEnabled);
setStencilWriteMask(state.stencilWriteMask);
setColorWriteMask(state.colorWriteMask);
createDefaultTexture();
@@ -1125,6 +1163,17 @@ uint32 OpenGL::getStencilWriteMask() const
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)
{
glUseProgram(program);
+19
View File
@@ -124,6 +124,21 @@ public:
~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
{
int shaderSwitches;
@@ -301,6 +316,9 @@ public:
void setStencilWriteMask(uint32 mask);
uint32 getStencilWriteMask() const;
void setColorWriteMask(uint32 mask);
uint32 getColorWriteMask() const;
/**
* Calls glUseProgram.
**/
@@ -528,6 +546,7 @@ private:
bool depthWritesEnabled = true;
uint32 stencilWriteMask = LOVE_UINT32_MAX;
uint32 colorWriteMask = LOVE_UINT32_MAX;
GLuint boundFramebuffers[2];
+16 -27
View File
@@ -80,31 +80,22 @@ static GLenum createFBO(GLuint &framebuffer, TextureType texType, PixelFormat fo
if (clear)
{
if (isPixelFormatDepthStencil(format))
bool ds = isPixelFormatDepthStencil(format);
GLbitfield clearflags = ds ? GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT : GL_COLOR_BUFFER_BIT;
OpenGL::CleanClearState cleanClearState(clearflags);
if (ds)
{
bool hadDepthWrites = gl.hasDepthWrites();
if (!hadDepthWrites) // glDepthMask also affects glClear.
gl.setDepthWrites(true);
uint32 stencilwrite = gl.getStencilWriteMask();
if (stencilwrite != LOVE_UINT32_MAX)
gl.setStencilWriteMask(LOVE_UINT32_MAX);
gl.clearDepth(1.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
{
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 (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);
glClearStencil(0);
glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
if (!hadDepthWrites)
gl.setDepthWrites(hadDepthWrites);
}
else
{
// Initialize the buffer to transparent black.
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT);
}
glClear(clearflags);
}
else
{