Fix the stencil buffer in Canvases when the graphics driver uses a MSAA value for the Canvas' buffers that's greater than the number of requested MSAA samples.

Fixes https://love2d.org/forums/viewtopic.php?f=4&t=79701
This commit is contained in:
Alex Szpakowski
2015-02-21 01:56:17 -04:00
parent 672899f5c7
commit 813061c0e0
2 changed files with 31 additions and 29 deletions
+28 -27
View File
@@ -434,7 +434,8 @@ Canvas::Canvas(int width, int height, Format format, int msaa)
, msaa_buffer(0)
, depth_stencil(0)
, format(format)
, msaa_samples(msaa)
, requested_samples(msaa)
, actual_samples(0)
, msaa_dirty(false)
, texture_memory(0)
{
@@ -484,6 +485,14 @@ Canvas::~Canvas()
bool Canvas::createMSAAFBO(GLenum internalformat)
{
actual_samples = requested_samples;
if (actual_samples <= 1)
{
actual_samples = 0;
return false;
}
// Create our FBO without a texture.
status = strategy->createFBO(fbo, 0);
@@ -497,7 +506,7 @@ bool Canvas::createMSAAFBO(GLenum internalformat)
}
// Create and attach the MSAA buffer for our FBO.
if (strategy->createMSAABuffer(width, height, msaa_samples, internalformat, msaa_buffer))
if (strategy->createMSAABuffer(width, height, actual_samples, internalformat, msaa_buffer))
status = GL_FRAMEBUFFER_COMPLETE;
else
status = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
@@ -512,7 +521,7 @@ bool Canvas::createMSAAFBO(GLenum internalformat)
strategy->deleteFBO(fbo, 0, msaa_buffer);
strategy->deleteFBO(resolve_fbo, 0, 0);
fbo = msaa_buffer = resolve_fbo = 0;
msaa_samples = 0;
actual_samples = 0;
}
if (current != this)
@@ -534,6 +543,12 @@ bool Canvas::loadVolatile()
return false;
}
int max_samples = 0;
if (GLEE_VERSION_3_0 || GLEE_ARB_framebuffer_object || GLEE_EXT_framebuffer_multisample)
glGetIntegerv(GL_MAX_SAMPLES, &max_samples);
requested_samples = std::max(std::min(requested_samples, max_samples), 0);
glGenTextures(1, &texture);
gl.bindTexture(texture);
@@ -566,23 +581,9 @@ bool Canvas::loadVolatile()
return false;
}
int max_samples = 0;
if (GLEE_VERSION_3_0 || GLEE_ARB_framebuffer_object
|| GLEE_EXT_framebuffer_multisample)
{
glGetIntegerv(GL_MAX_SAMPLES, &max_samples);
}
if (msaa_samples > max_samples)
msaa_samples = max_samples;
// Try to create a MSAA FBO if requested.
bool msaasuccess = false;
if (msaa_samples > 1)
msaasuccess = createMSAAFBO(internalformat);
// On failure (or no requested MSAA), fall back to a regular FBO.
if (!msaasuccess)
// Try to create a MSAA FBO if requested. On failure (or no requested MSAA),
// fall back to a regular FBO.
if (!createMSAAFBO(internalformat))
status = strategy->createFBO(fbo, texture);
if (status != GL_FRAMEBUFFER_COMPLETE)
@@ -603,7 +604,7 @@ bool Canvas::loadVolatile()
texture_memory = (getFormatBitsPerPixel(format) * width * height) / 8;
if (msaa_buffer != 0)
texture_memory += (texture_memory * msaa_samples);
texture_memory += (texture_memory * actual_samples);
gl.updateTextureMemorySize(prevmemsize, texture_memory);
@@ -742,7 +743,7 @@ void Canvas::startGrab(const std::vector<Canvas *> &canvases)
if ((int) canvases.size() + 1 > gl.getMaxRenderTargets())
throw love::Exception("This system can't simultaniously render to %d canvases.", canvases.size()+1);
if (msaa_samples != 0)
if (actual_samples != 0)
throw love::Exception("Multi-canvas rendering is not supported with MSAA.");
}
@@ -880,7 +881,7 @@ bool Canvas::checkCreateStencil()
if (current != this)
strategy->bindFBO(fbo);
bool success = strategy->createStencil(width, height, msaa_samples, depth_stencil);
bool success = strategy->createStencil(width, height, requested_samples, depth_stencil);
if (current && current != this)
strategy->bindFBO(current->fbo);
@@ -899,9 +900,9 @@ love::image::ImageData *Canvas::getImageData(love::image::Image *image)
GLubyte *pixels = new GLubyte[size];
// Our texture is attached to 'resolve_fbo' when we use MSAA.
if (msaa_samples > 1 && (GLEE_VERSION_3_0 || GLEE_ARB_framebuffer_object))
if (resolve_fbo != 0 && (GLEE_VERSION_3_0 || GLEE_ARB_framebuffer_object))
glBindFramebuffer(GL_READ_FRAMEBUFFER, resolve_fbo);
else if (msaa_samples > 1 && GLEE_EXT_framebuffer_multisample)
else if (resolve_fbo != 0 && GLEE_EXT_framebuffer_multisample)
glBindFramebufferEXT(GL_READ_FRAMEBUFFER, resolve_fbo);
else
strategy->bindFBO(fbo);
@@ -926,9 +927,9 @@ void Canvas::getPixel(unsigned char* pixel_rgba, int x, int y)
resolveMSAA();
// Our texture is attached to 'resolve_fbo' when we use MSAA.
if (msaa_samples > 1 && (GLEE_VERSION_3_0 || GLEE_ARB_framebuffer_object))
if (resolve_fbo != 0 && (GLEE_VERSION_3_0 || GLEE_ARB_framebuffer_object))
glBindFramebuffer(GL_READ_FRAMEBUFFER, resolve_fbo);
else if (msaa_samples > 1 && GLEE_EXT_framebuffer_multisample)
else if (resolve_fbo != 0 && GLEE_EXT_framebuffer_multisample)
glBindFramebufferEXT(GL_READ_FRAMEBUFFER, resolve_fbo);
else if (current != this)
strategy->bindFBO(fbo);
+3 -2
View File
@@ -111,7 +111,7 @@ public:
inline int getMSAA() const
{
return msaa_samples;
return actual_samples;
}
bool resolveMSAA();
@@ -155,7 +155,8 @@ private:
std::vector<Canvas *> attachedCanvases;
int msaa_samples;
int requested_samples;
int actual_samples;
bool msaa_dirty;
size_t texture_memory;