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; 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
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() 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
View File
@@ -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];
+16 -27
View File
@@ -80,31 +80,22 @@ static GLenum createFBO(GLuint &framebuffer, TextureType texType, PixelFormat fo
if (clear) 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); 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 ds = isPixelFormatDepthStencil(pixelformat);
{
bool hadDepthWrites = gl.hasDepthWrites();
if (!hadDepthWrites) // glDepthMask also affects glClear.
gl.setDepthWrites(true);
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
{ {