Allow a depth/stencil canvas to be active without a color canvas.

--HG--
branch : minor
This commit is contained in:
Alex Szpakowski
2017-12-03 19:33:48 -04:00
parent 0c1c78fe29
commit cbcb1a8606
4 changed files with 65 additions and 23 deletions
+16 -14
View File
@@ -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);
+10
View File
@@ -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
+34 -5
View File
@@ -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;
+5 -4
View File
@@ -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();