diff --git a/src/modules/graphics/Canvas.cpp b/src/modules/graphics/Canvas.cpp index e8179271b..682967c27 100644 --- a/src/modules/graphics/Canvas.cpp +++ b/src/modules/graphics/Canvas.cpp @@ -69,6 +69,9 @@ Canvas::Canvas(const Settings &settings) filter.mipmap = defaultMipmapFilter; } + if (settings.mipmaps == MIPMAPS_AUTO && isPixelFormatDepthStencil(format)) + throw love::Exception("Automatic mipmap generation cannot be used for depth/stencil Canvases."); + auto gfx = Module::getInstance(Module::M_GRAPHICS); const Graphics::Capabilities &caps = gfx->getCapabilities(); diff --git a/src/modules/graphics/opengl/Canvas.cpp b/src/modules/graphics/opengl/Canvas.cpp index 947c51d20..6d1a99745 100644 --- a/src/modules/graphics/opengl/Canvas.cpp +++ b/src/modules/graphics/opengl/Canvas.cpp @@ -67,19 +67,6 @@ static GLenum createFBO(GLuint &framebuffer, TextureType texType, PixelFormat fo if (texType == TEXTURE_VOLUME) nlayers = std::max(layers >> mip, 1); - GLuint tempframebuffer = 0; - if (mip > 0) - { - // Some Intel drivers on Windows don't like reusing the same - // FBO for different sized attachments, so use a temporary one - // to clear smaller mips. - // https://github.com/love2d/love/issues/1585 - glGenFramebuffers(1, &tempframebuffer); - gl.bindFramebuffer(OpenGL::FRAMEBUFFER_ALL, tempframebuffer); - } - else - gl.bindFramebuffer(OpenGL::FRAMEBUFFER_ALL, framebuffer); - for (int layer = nlayers - 1; layer >= 0; layer--) { for (int face = faces - 1; face >= 0; face--) @@ -112,9 +99,6 @@ static GLenum createFBO(GLuint &framebuffer, TextureType texType, PixelFormat fo } } } - - if (tempframebuffer != 0) - gl.deleteFramebuffer(tempframebuffer); } } @@ -278,8 +262,18 @@ bool Canvas::loadVolatile() return false; } + // All mipmap levels need to be initialized - for color formats we can + // clear the base mip and use glGenerateMipmap after that's done. Depth + // and stencil formats don't always support glGenerateMipmap so we need + // to individually clear each mip level in that case. We avoid doing that + // for color formats because of an Intel driver bug: + // https://github.com/love2d/love/issues/1585 + int clearmips = 1; + if (isPixelFormatDepthStencil(format)) + clearmips = mipmapCount; + // Create a canvas-local FBO used for glReadPixels as well as MSAA blitting. - status = createFBO(fbo, texType, format, texture, texType == TEXTURE_VOLUME ? depth : layers, mipmapCount); + status = createFBO(fbo, texType, format, texture, texType == TEXTURE_VOLUME ? depth : layers, clearmips); if (status != GL_FRAMEBUFFER_COMPLETE) { @@ -290,6 +284,9 @@ bool Canvas::loadVolatile() } return false; } + + if (clearmips < mipmapCount && getMipmapMode() != MIPMAPS_NONE) + generateMipmaps(); } if (!isReadable() || actualSamples > 0) @@ -488,6 +485,9 @@ void Canvas::generateMipmaps() if (getMipmapCount() == 1 || getMipmapMode() == MIPMAPS_NONE) throw love::Exception("generateMipmaps can only be called on a Canvas which was created with mipmaps enabled."); + if (isPixelFormatDepthStencil(format)) + throw love::Exception("generateMipmaps cannot be called on a depth/stencil Canvas."); + gl.bindTextureToUnit(this, 0, false); GLenum gltextype = OpenGL::getGLTextureType(texType); diff --git a/src/modules/graphics/opengl/Graphics.cpp b/src/modules/graphics/opengl/Graphics.cpp index d826479ee..5f11db41c 100644 --- a/src/modules/graphics/opengl/Graphics.cpp +++ b/src/modules/graphics/opengl/Graphics.cpp @@ -587,10 +587,6 @@ void Graphics::endPass() if (rt.canvas->getMipmapMode() == Canvas::MIPMAPS_AUTO && rt.mipmap == 0) rt.canvas->generateMipmaps(); } - - int dsmipmap = rts.depthStencil.mipmap; - if (depthstencil != nullptr && depthstencil->getMipmapMode() == Canvas::MIPMAPS_AUTO && dsmipmap == 0) - depthstencil->generateMipmaps(); } void Graphics::clear(OptionalColorf c, OptionalInt stencil, OptionalDouble depth)