From bc1c38d361209d701146b25e6c8ae991cedc1899 Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Sat, 19 Feb 2022 16:34:52 -0400 Subject: [PATCH] improve logic for detecting when Texture:generateMipmaps is supported --- src/modules/graphics/Texture.cpp | 51 ++++++++++++++++++++++----- src/modules/graphics/Texture.h | 1 + src/modules/graphics/metal/Texture.mm | 2 -- 3 files changed, 44 insertions(+), 10 deletions(-) diff --git a/src/modules/graphics/Texture.cpp b/src/modules/graphics/Texture.cpp index b0c1c0924..7da786e4d 100644 --- a/src/modules/graphics/Texture.cpp +++ b/src/modules/graphics/Texture.cpp @@ -232,8 +232,13 @@ Texture::Texture(Graphics *gfx, const Settings &settings, const Slices *slices) if (mipmapsMode != MIPMAPS_NONE) mipmapCount = getTotalMipmapCount(pixelWidth, pixelHeight, depth); - if (mipmapsMode == MIPMAPS_AUTO && isPixelFormatDepthStencil(format)) - throw love::Exception("Automatic mipmap generation cannot be used for depth/stencil textures."); + const char *miperr = nullptr; + if (mipmapsMode == MIPMAPS_AUTO && !supportsGenerateMipmaps(miperr)) + { + const char *fstr = "unknown"; + love::getConstant(format, fstr); + throw love::Exception("Automatic mipmap generation is not supported for textures with the %s pixel format.", fstr); + } if (pixelWidth <= 0 || pixelHeight <= 0 || layers <= 0 || depth <= 0) throw love::Exception("Texture dimensions must be greater than 0."); @@ -511,19 +516,49 @@ void Texture::replacePixels(const void *data, size_t size, int slice, int mipmap generateMipmaps(); } -void Texture::generateMipmaps() +bool Texture::supportsGenerateMipmaps(const char *&outReason) const { - if (getMipmapCount() == 1 || getMipmapsMode() == MIPMAPS_NONE) - throw love::Exception("generateMipmaps can only be called on a Texture which was created with mipmaps enabled."); + if (getMipmapsMode() == MIPMAPS_NONE) + { + outReason = "generateMipmaps can only be called on a Texture which was created with mipmaps enabled."; + return false; + } if (isPixelFormatCompressed(format)) - throw love::Exception("generateMipmaps cannot be called on a compressed Texture."); + { + outReason = "generateMipmaps cannot be called on a compressed Texture."; + return false; + } if (isPixelFormatDepthStencil(format)) - throw love::Exception("generateMipmaps cannot be called on a depth/stencil Texture."); + { + outReason = "generateMipmaps cannot be called on a depth/stencil Texture."; + return false; + } if (isPixelFormatInteger(format)) - throw love::Exception("generateMipmaps cannot be called on an integer Texture."); + { + outReason = "generateMipmaps cannot be called on an integer Texture."; + return false; + } + + // This should be linear | rt because that's what metal needs, but the above + // code handles textures can't be used as RTs in metal. + auto gfx = Module::getInstance(Module::M_GRAPHICS); + if (gfx != nullptr && !gfx->isPixelFormatSupported(format, PIXELFORMATUSAGEFLAGS_LINEAR)) + { + outReason = "generateMipmaps cannot be called on textures with formats that don't support linear filtering on this system."; + return false; + } + + return true; +} + +void Texture::generateMipmaps() +{ + const char *err = nullptr; + if (!supportsGenerateMipmaps(err)) + throw love::Exception("%s", err); generateMipmapsInternal(); } diff --git a/src/modules/graphics/Texture.h b/src/modules/graphics/Texture.h index e79ad0528..415e4ace7 100644 --- a/src/modules/graphics/Texture.h +++ b/src/modules/graphics/Texture.h @@ -311,6 +311,7 @@ protected: void uploadImageData(love::image::ImageDataBase *d, int level, int slice, int x, int y); virtual void uploadByteData(PixelFormat pixelformat, const void *data, size_t size, int level, int slice, const Rect &r) = 0; + bool supportsGenerateMipmaps(const char *&outReason) const; virtual void generateMipmapsInternal() = 0; virtual void readbackImageData(love::image::ImageData *imagedata, int slice, int mipmap, const Rect &rect) = 0; diff --git a/src/modules/graphics/metal/Texture.mm b/src/modules/graphics/metal/Texture.mm index fcd01885c..0c2adf944 100644 --- a/src/modules/graphics/metal/Texture.mm +++ b/src/modules/graphics/metal/Texture.mm @@ -269,8 +269,6 @@ void Texture::uploadByteData(PixelFormat pixelformat, const void *data, size_t s void Texture::generateMipmapsInternal() { @autoreleasepool { - // TODO: alternate method for non-color-renderable and non-filterable - // pixel formats. id encoder = Graphics::getInstance()->useBlitEncoder(); [encoder generateMipmapsForTexture:texture]; }}