mirror of
https://github.com/love2d/love.git
synced 2026-08-12 08:30:56 +02:00
Allow a depth/stencil canvas to be active without a color canvas.
--HG-- branch : minor
This commit is contained in:
@@ -317,7 +317,7 @@ double Graphics::getCurrentDPIScale() const
|
||||
{
|
||||
if (states.back().renderTargets.colors.size() > 0)
|
||||
{
|
||||
Canvas *c = states.back().renderTargets.colors[0].canvas;
|
||||
Canvas *c = states.back().renderTargets.getFirstTarget().canvas.get();
|
||||
return (double) c->getPixelHeight() / (double) c->getHeight();
|
||||
}
|
||||
|
||||
@@ -555,8 +555,6 @@ void Graphics::setCanvas(const RenderTargets &rts)
|
||||
|
||||
if (ncanvases == 0 && rts.depthStencil.canvas == nullptr)
|
||||
return setCanvas();
|
||||
else if (ncanvases == 0)
|
||||
throw love::Exception("At least one color render target is required when using a custom depth/stencil buffer.");
|
||||
|
||||
const auto &prevRTs = state.renderTargets;
|
||||
|
||||
@@ -592,20 +590,24 @@ void Graphics::setCanvas(const RenderTargets &rts)
|
||||
if (ncanvases > capabilities.limits[LIMIT_MULTI_CANVAS])
|
||||
throw love::Exception("This system can't simultaneously render to %d canvases.", ncanvases);
|
||||
|
||||
love::graphics::Canvas *firstcanvas = rts.colors[0].canvas;
|
||||
RenderTarget firsttarget = rts.getFirstTarget();
|
||||
love::graphics::Canvas *firstcanvas = firsttarget.canvas;
|
||||
|
||||
bool multiformatsupported = capabilities.features[FEATURE_MULTI_CANVAS_FORMATS];
|
||||
PixelFormat firstformat = firstcanvas->getPixelFormat();
|
||||
|
||||
if (isPixelFormatDepthStencil(firstformat))
|
||||
PixelFormat firstcolorformat = PIXELFORMAT_UNKNOWN;
|
||||
if (!rts.colors.empty())
|
||||
firstcolorformat = rts.colors[0].canvas->getPixelFormat();
|
||||
|
||||
if (isPixelFormatDepthStencil(firstcolorformat))
|
||||
throw love::Exception("Depth/stencil format Canvases must be used with the 'depthstencil' field of the table passed into setCanvas.");
|
||||
|
||||
if (rts.colors[0].mipmap < 0 || rts.colors[0].mipmap >= firstcanvas->getMipmapCount())
|
||||
throw love::Exception("Invalid mipmap level %d.", rts.colors[0].mipmap + 1);
|
||||
if (firsttarget.mipmap < 0 || firsttarget.mipmap >= firstcanvas->getMipmapCount())
|
||||
throw love::Exception("Invalid mipmap level %d.", firsttarget.mipmap + 1);
|
||||
|
||||
bool hasSRGBcanvas = firstformat == PIXELFORMAT_sRGBA8;
|
||||
int pixelw = firstcanvas->getPixelWidth(rts.colors[0].mipmap);
|
||||
int pixelh = firstcanvas->getPixelHeight(rts.colors[0].mipmap);
|
||||
bool hasSRGBcanvas = firstcolorformat == PIXELFORMAT_sRGBA8;
|
||||
int pixelw = firstcanvas->getPixelWidth(firsttarget.mipmap);
|
||||
int pixelh = firstcanvas->getPixelHeight(firsttarget.mipmap);
|
||||
|
||||
for (int i = 1; i < ncanvases; i++)
|
||||
{
|
||||
@@ -619,7 +621,7 @@ void Graphics::setCanvas(const RenderTargets &rts)
|
||||
if (c->getPixelWidth(mip) != pixelw || c->getPixelHeight(mip) != pixelh)
|
||||
throw love::Exception("All canvases must have the same pixel dimensions.");
|
||||
|
||||
if (!multiformatsupported && format != firstformat)
|
||||
if (!multiformatsupported && format != firstcolorformat)
|
||||
throw love::Exception("This system doesn't support multi-canvas rendering with different canvas formats.");
|
||||
|
||||
if (c->getRequestedMSAA() != firstcanvas->getRequestedMSAA())
|
||||
@@ -650,8 +652,8 @@ void Graphics::setCanvas(const RenderTargets &rts)
|
||||
throw love::Exception("Invalid mipmap level %d.", mip + 1);
|
||||
}
|
||||
|
||||
int w = firstcanvas->getWidth(rts.colors[0].mipmap);
|
||||
int h = firstcanvas->getHeight(rts.colors[0].mipmap);
|
||||
int w = firstcanvas->getWidth(firsttarget.mipmap);
|
||||
int h = firstcanvas->getHeight(firsttarget.mipmap);
|
||||
|
||||
flushStreamDraws();
|
||||
setCanvasInternal(rts, w, h, pixelw, pixelh, hasSRGBcanvas);
|
||||
|
||||
@@ -347,6 +347,11 @@ public:
|
||||
: depthStencil(nullptr)
|
||||
, temporaryRTFlags(0)
|
||||
{}
|
||||
|
||||
const RenderTarget &getFirstTarget() const
|
||||
{
|
||||
return colors.empty() ? depthStencil : colors[0];
|
||||
}
|
||||
};
|
||||
|
||||
struct RenderTargetsStrongRef
|
||||
@@ -359,6 +364,11 @@ public:
|
||||
: depthStencil(nullptr)
|
||||
, temporaryRTFlags(0)
|
||||
{}
|
||||
|
||||
const RenderTargetStrongRef &getFirstTarget() const
|
||||
{
|
||||
return colors.empty() ? depthStencil : colors[0];
|
||||
}
|
||||
};
|
||||
|
||||
struct DefaultShaderCode
|
||||
|
||||
@@ -405,6 +405,7 @@ void Graphics::setCanvasInternal(const RenderTargets &rts, int w, int h, int pix
|
||||
|
||||
OpenGL::TempDebugGroup debuggroup("setCanvas(...)");
|
||||
|
||||
flushStreamDraws();
|
||||
endPass();
|
||||
|
||||
bindCachedFBO(rts);
|
||||
@@ -501,6 +502,32 @@ void Graphics::endPass()
|
||||
}
|
||||
}
|
||||
|
||||
if (depthstencil != nullptr && depthstencil->getMSAA() > 1 && depthstencil->isReadable())
|
||||
{
|
||||
gl.bindFramebuffer(OpenGL::FRAMEBUFFER_DRAW, ((Canvas *) depthstencil)->getFBO());
|
||||
|
||||
if (GLAD_APPLE_framebuffer_multisample)
|
||||
glResolveMultisampleFramebufferAPPLE();
|
||||
else
|
||||
{
|
||||
int mip = rts.depthStencil.mipmap;
|
||||
int w = depthstencil->getPixelWidth(mip);
|
||||
int h = depthstencil->getPixelHeight(mip);
|
||||
PixelFormat format = depthstencil->getPixelFormat();
|
||||
|
||||
GLbitfield mask = 0;
|
||||
|
||||
if (isPixelFormatDepth(format))
|
||||
mask |= GL_DEPTH_BUFFER_BIT;
|
||||
if (isPixelFormatStencil(format))
|
||||
mask |= GL_STENCIL_BUFFER_BIT;
|
||||
|
||||
if (mask != 0)
|
||||
glBlitFramebuffer(0, 0, w, h, 0, 0, w, h, mask, GL_NEAREST);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
for (const auto &rt : rts.colors)
|
||||
{
|
||||
if (rt.canvas->getMipmapMode() == Canvas::MIPMAPS_AUTO && rt.mipmap == 0)
|
||||
@@ -709,11 +736,13 @@ void Graphics::bindCachedFBO(const RenderTargets &targets)
|
||||
}
|
||||
else
|
||||
{
|
||||
int mip = targets.colors[0].mipmap;
|
||||
int w = targets.colors[0].canvas->getPixelWidth(mip);
|
||||
int h = targets.colors[0].canvas->getPixelHeight(mip);
|
||||
int msaa = targets.colors[0].canvas->getMSAA();
|
||||
int reqmsaa = targets.colors[0].canvas->getRequestedMSAA();
|
||||
RenderTarget firstRT = targets.getFirstTarget();
|
||||
|
||||
int mip = firstRT.mipmap;
|
||||
int w = firstRT.canvas->getPixelWidth(mip);
|
||||
int h = firstRT.canvas->getPixelHeight(mip);
|
||||
int msaa = firstRT.canvas->getMSAA();
|
||||
int reqmsaa = firstRT.canvas->getRequestedMSAA();
|
||||
|
||||
RenderTarget depthstencil = targets.depthStencil;
|
||||
|
||||
|
||||
@@ -300,11 +300,12 @@ int w_setCanvas(lua_State *L)
|
||||
uint32 tempstencilflag = Graphics::TEMPORARY_RT_STENCIL;
|
||||
|
||||
lua_getfield(L, 1, "depthstencil");
|
||||
if (lua_istable(L, -1))
|
||||
int dstype = lua_type(L, -1);
|
||||
if (dstype == LUA_TTABLE)
|
||||
targets.depthStencil = checkRenderTarget(L, -1);
|
||||
else if (lua_isboolean(L, -1))
|
||||
else if (dstype == LUA_TBOOLEAN)
|
||||
targets.temporaryRTFlags |= luax_toboolean(L, -1) ? (tempdepthflag | tempstencilflag) : 0;
|
||||
else if (!lua_isnoneornil(L, -1))
|
||||
else if (dstype != LUA_TNONE && dstype != LUA_TNIL)
|
||||
targets.depthStencil.canvas = luax_checkcanvas(L, -1);
|
||||
lua_pop(L, 1);
|
||||
|
||||
@@ -342,7 +343,7 @@ int w_setCanvas(lua_State *L)
|
||||
}
|
||||
|
||||
luax_catchexcept(L, [&]() {
|
||||
if (targets.colors.size() > 0)
|
||||
if (targets.getFirstTarget().canvas != nullptr)
|
||||
instance()->setCanvas(targets);
|
||||
else
|
||||
instance()->setCanvas();
|
||||
|
||||
Reference in New Issue
Block a user