mirror of
https://github.com/love2d/love.git
synced 2026-08-16 00:02:12 +02:00
Require stencil=true to be specified in setCanvas if stenciling is used while a Canvas is active and there is no custom stencil buffer.
--HG-- branch : minor
This commit is contained in:
@@ -314,6 +314,9 @@ void Graphics::restoreStateChecked(const DisplayState &s)
|
||||
{
|
||||
canvaseschanged = true;
|
||||
}
|
||||
|
||||
if (sRTs.useTemporaryStencil != curRTs.useTemporaryStencil)
|
||||
canvaseschanged = true;
|
||||
}
|
||||
|
||||
if (canvaseschanged)
|
||||
@@ -406,13 +409,14 @@ love::graphics::Shader *Graphics::getShader() const
|
||||
return states.back().shader.get();
|
||||
}
|
||||
|
||||
void Graphics::setCanvas(RenderTarget rt)
|
||||
void Graphics::setCanvas(RenderTarget rt, bool useStencil)
|
||||
{
|
||||
if (rt.canvas == nullptr)
|
||||
return setCanvas();
|
||||
|
||||
RenderTargets rts;
|
||||
rts.colors.push_back(rt);
|
||||
rts.useTemporaryStencil = useStencil;
|
||||
|
||||
setCanvas(rts);
|
||||
}
|
||||
@@ -426,6 +430,7 @@ void Graphics::setCanvas(const RenderTargetsStrongRef &rts)
|
||||
targets.colors.emplace_back(rt.canvas.get(), rt.slice, rt.mipmap);
|
||||
|
||||
targets.depthStencil = RenderTarget(rts.depthStencil.canvas, rts.depthStencil.slice, rts.depthStencil.mipmap);
|
||||
targets.useTemporaryStencil = rts.useTemporaryStencil;
|
||||
|
||||
return setCanvas(targets);
|
||||
}
|
||||
@@ -441,13 +446,15 @@ Graphics::RenderTargets Graphics::getCanvas() const
|
||||
rts.colors.emplace_back(rt.canvas.get(), rt.slice, rt.mipmap);
|
||||
|
||||
rts.depthStencil = RenderTarget(curRTs.depthStencil.canvas, curRTs.depthStencil.slice, curRTs.depthStencil.mipmap);
|
||||
rts.useTemporaryStencil = curRTs.useTemporaryStencil;
|
||||
|
||||
return rts;
|
||||
}
|
||||
|
||||
bool Graphics::isCanvasActive() const
|
||||
{
|
||||
return !states.back().renderTargets.colors.empty();
|
||||
const auto &rts = states.back().renderTargets;
|
||||
return !rts.colors.empty() || rts.depthStencil.canvas != nullptr;
|
||||
}
|
||||
|
||||
bool Graphics::isCanvasActive(love::graphics::Canvas *canvas) const
|
||||
|
||||
@@ -323,9 +323,11 @@ public:
|
||||
{
|
||||
std::vector<RenderTarget> colors;
|
||||
RenderTarget depthStencil;
|
||||
bool useTemporaryStencil;
|
||||
|
||||
RenderTargets()
|
||||
: depthStencil(nullptr)
|
||||
, useTemporaryStencil(false)
|
||||
{}
|
||||
};
|
||||
|
||||
@@ -333,9 +335,11 @@ public:
|
||||
{
|
||||
std::vector<RenderTargetStrongRef> colors;
|
||||
RenderTargetStrongRef depthStencil;
|
||||
bool useTemporaryStencil;
|
||||
|
||||
RenderTargetsStrongRef()
|
||||
: depthStencil(nullptr)
|
||||
, useTemporaryStencil(false)
|
||||
{}
|
||||
};
|
||||
|
||||
@@ -459,7 +463,7 @@ public:
|
||||
|
||||
Shader *getShader() const;
|
||||
|
||||
void setCanvas(RenderTarget rt);
|
||||
void setCanvas(RenderTarget rt, bool useStencil);
|
||||
virtual void setCanvas(const RenderTargets &rts) = 0;
|
||||
void setCanvas(const RenderTargetsStrongRef &rts);
|
||||
virtual void setCanvas() = 0;
|
||||
|
||||
@@ -533,6 +533,9 @@ void Graphics::setCanvas(const RenderTargets &rts)
|
||||
modified = true;
|
||||
}
|
||||
|
||||
if (rts.useTemporaryStencil != prevRTs.useTemporaryStencil)
|
||||
modified = true;
|
||||
|
||||
if (!modified)
|
||||
return;
|
||||
}
|
||||
@@ -631,6 +634,7 @@ void Graphics::setCanvas(const RenderTargets &rts)
|
||||
refs.colors.emplace_back(c.canvas, c.slice);
|
||||
|
||||
refs.depthStencil = RenderTargetStrongRef(rts.depthStencil.canvas, rts.depthStencil.slice);
|
||||
refs.useTemporaryStencil = rts.useTemporaryStencil;
|
||||
|
||||
std::swap(state.renderTargets, refs);
|
||||
|
||||
@@ -682,7 +686,7 @@ void Graphics::endPass()
|
||||
love::graphics::Canvas *depthstencil = rts.depthStencil.canvas.get();
|
||||
|
||||
// Discard the stencil buffer if we're using an internal cached one.
|
||||
if (depthstencil == nullptr)
|
||||
if (depthstencil == nullptr && rts.useTemporaryStencil)
|
||||
discard({}, true);
|
||||
|
||||
// Resolve MSAA buffers. MSAA is only supported for 2D render targets so we
|
||||
@@ -907,6 +911,8 @@ void Graphics::bindCachedFBO(const RenderTargets &targets)
|
||||
|
||||
if (targets.depthStencil.canvas != nullptr)
|
||||
hashtargets[hashcount++] = targets.depthStencil;
|
||||
else if (targets.useTemporaryStencil)
|
||||
hashtargets[hashcount++] = RenderTarget(nullptr, -1, 0);
|
||||
|
||||
uint32 hash = XXH32(hashtargets, sizeof(RenderTarget) * hashcount, 0);
|
||||
GLuint fbo = framebufferObjects[hash];
|
||||
@@ -925,7 +931,7 @@ void Graphics::bindCachedFBO(const RenderTargets &targets)
|
||||
|
||||
RenderTarget depthstencil = targets.depthStencil;
|
||||
|
||||
if (depthstencil.canvas == nullptr)
|
||||
if (depthstencil.canvas == nullptr && targets.useTemporaryStencil)
|
||||
{
|
||||
depthstencil.canvas = getCachedStencilBuffer(w, h, reqmsaa);
|
||||
depthstencil.slice = 0;
|
||||
@@ -1176,8 +1182,13 @@ void Graphics::setScissor()
|
||||
|
||||
void Graphics::drawToStencilBuffer(StencilAction action, int value)
|
||||
{
|
||||
const auto &rts = states.back().renderTargets;
|
||||
love::graphics::Canvas *dscanvas = rts.depthStencil.canvas.get();
|
||||
|
||||
if (!isCanvasActive() && !windowHasStencil)
|
||||
throw love::Exception("The window must have stenciling enabled to draw to the main screen's stencil buffer.");
|
||||
else if (isCanvasActive() && !rts.useTemporaryStencil && (dscanvas == nullptr || !isPixelFormatStencil(dscanvas->getPixelFormat())))
|
||||
throw love::Exception("Drawing to the stencil buffer with a Canvas active requires either stencil=true or a custom stencil-type Canvas to be used, in setCanvas.");
|
||||
|
||||
flushStreamDraws();
|
||||
|
||||
@@ -1237,9 +1248,6 @@ void Graphics::stopDrawToStencilBuffer()
|
||||
|
||||
void Graphics::setStencilTest(CompareMode compare, int value)
|
||||
{
|
||||
if (compare != COMPARE_ALWAYS && !isCanvasActive() && !windowHasStencil)
|
||||
throw love::Exception("The window must have stenciling enabled to use setStencilTest on the main screen.");
|
||||
|
||||
DisplayState &state = states.back();
|
||||
|
||||
if (state.stencilCompare != compare || state.stencilTestValue != value)
|
||||
|
||||
@@ -346,7 +346,7 @@ void Image::unloadVolatile()
|
||||
void Image::replacePixels(love::image::ImageDataBase *d, int slice, int mipmap, bool reloadmipmaps)
|
||||
{
|
||||
// No effect if the texture hasn't been created yet.
|
||||
if (texture == 0 || usingDefaultTexture)
|
||||
if (getHandle() == 0 || usingDefaultTexture)
|
||||
return;
|
||||
|
||||
if (d->getFormat() != getPixelFormat())
|
||||
|
||||
@@ -65,7 +65,7 @@ int w_Canvas_renderTo(lua_State *L)
|
||||
if (oldtargets.depthStencil.canvas != nullptr)
|
||||
oldtargets.depthStencil.canvas->retain();
|
||||
|
||||
luax_catchexcept(L, [&](){ graphics->setCanvas(rt); });
|
||||
luax_catchexcept(L, [&](){ graphics->setCanvas(rt, false); });
|
||||
|
||||
lua_settop(L, 2); // make sure the function is on top of the stack
|
||||
int status = lua_pcall(L, 0, 0, 0);
|
||||
|
||||
@@ -300,6 +300,9 @@ int w_setCanvas(lua_State *L)
|
||||
else if (!lua_isnoneornil(L, -1))
|
||||
targets.depthStencil.canvas = luax_checkcanvas(L, -1);
|
||||
lua_pop(L, 1);
|
||||
|
||||
if (targets.depthStencil.canvas == nullptr)
|
||||
targets.useTemporaryStencil = luax_boolflag(L, 1, "stencil", false);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user