Skip to content

Commit

Permalink
opengl: scissor and color mask no longer affects love.graphics.clear.
Browse files Browse the repository at this point in the history
This makes it more consistent with other backends.
  • Loading branch information
slime73 committed Oct 9, 2023
1 parent 27c4569 commit b8cbb62
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 59 deletions.
44 changes: 11 additions & 33 deletions src/modules/graphics/opengl/Graphics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -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;
}

Expand Down
49 changes: 49 additions & 0 deletions src/modules/graphics/opengl/OpenGL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -284,6 +321,7 @@ void OpenGL::setupContext()

setDepthWrites(state.depthWritesEnabled);
setStencilWriteMask(state.stencilWriteMask);
setColorWriteMask(state.colorWriteMask);

createDefaultTexture();

Expand Down Expand Up @@ -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);
Expand Down
19 changes: 19 additions & 0 deletions src/modules/graphics/opengl/OpenGL.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,21 @@ class OpenGL
~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;
Expand Down Expand Up @@ -301,6 +316,9 @@ class OpenGL
void setStencilWriteMask(uint32 mask);
uint32 getStencilWriteMask() const;

void setColorWriteMask(uint32 mask);
uint32 getColorWriteMask() const;

/**
* Calls glUseProgram.
**/
Expand Down Expand Up @@ -528,6 +546,7 @@ class OpenGL

bool depthWritesEnabled = true;
uint32 stencilWriteMask = LOVE_UINT32_MAX;
uint32 colorWriteMask = LOVE_UINT32_MAX;

GLuint boundFramebuffers[2];

Expand Down
41 changes: 15 additions & 26 deletions src/modules/graphics/opengl/Texture.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,31 +80,22 @@ static GLenum createFBO(GLuint &framebuffer, TextureType texType, PixelFormat fo

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);
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);
}
}
}
Expand Down Expand Up @@ -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
{
Expand Down

0 comments on commit b8cbb62

Please sign in to comment.