metal: use a fallback for fonts when luminance-alpha isn't supported.

This commit is contained in:
Alex Szpakowski
2022-01-22 14:41:42 -04:00
parent 62de8f62c7
commit 1cf0073cf4
6 changed files with 79 additions and 36 deletions
+50 -9
View File
@@ -82,6 +82,10 @@ Font::Font(love::font::Rasterizer *r, const SamplerState &s)
pixelFormat = gd->getFormat();
gd->release();
auto gfx = Module::getInstance<Graphics>(Module::M_GRAPHICS);
if (pixelFormat == PIXELFORMAT_LA8_UNORM && !gfx->isPixelFormatSupported(pixelFormat, PIXELFORMATUSAGEFLAGS_SAMPLE))
pixelFormat = PIXELFORMAT_RGBA8_UNORM;
if (!r->hasGlyph(9)) // No tab character in the Rasterizer.
useSpacesAsTab = true;
@@ -158,18 +162,30 @@ void Font::createTexture()
texture->setSamplerState(samplerState);
{
size_t bpp = getPixelFormatBlockSize(pixelFormat);
size_t datasize = getPixelFormatSliceSize(pixelFormat, size.width, size.height);
size_t pixelcount = size.width * size.height;
// Initialize the texture with transparent white for Luminance-Alpha
// formats (since we keep luminance constant and vary alpha in those
// glyphs), and transparent black otherwise.
std::vector<uint8> emptydata(pixelcount * bpp, 0);
// Initialize the texture with transparent white for truetype fonts
// (since we keep luminance constant and vary alpha in those glyphs),
// and transparent black otherwise.
std::vector<uint8> emptydata(datasize, 0);
if (pixelFormat == PIXELFORMAT_LA8_UNORM)
if (rasterizers[0]->getDataType() == font::Rasterizer::DATA_TRUETYPE)
{
for (size_t i = 0; i < pixelcount; i++)
emptydata[i * 2 + 0] = 255;
if (pixelFormat == PIXELFORMAT_LA8_UNORM)
{
for (size_t i = 0; i < pixelcount; i++)
emptydata[i * 2 + 0] = 255;
}
else if (pixelFormat == PIXELFORMAT_RGBA8_UNORM)
{
for (size_t i = 0; i < pixelcount; i++)
{
emptydata[i * 4 + 0] = 255;
emptydata[i * 4 + 1] = 255;
emptydata[i * 4 + 2] = 255;
}
}
}
Rect rect = {0, 0, size.width, size.height};
@@ -281,7 +297,32 @@ const Font::Glyph &Font::addGlyph(uint32 glyph)
g.texture = texture;
Rect rect = {textureX, textureY, gd->getWidth(), gd->getHeight()};
texture->replacePixels(gd->getData(), gd->getSize(), 0, 0, rect, false);
if (pixelFormat != gd->getFormat())
{
if (!(pixelFormat == PIXELFORMAT_RGBA8_UNORM && gd->getFormat() == PIXELFORMAT_LA8_UNORM))
throw love::Exception("Cannot upload font glyphs to texture atlas: unexpected format conversion.");
const uint8 *src = (const uint8 *) gd->getData();
size_t dstsize = getPixelFormatSliceSize(pixelFormat, w, h);
std::vector<uint8> dst(dstsize, 0);
uint8 *dstdata = dst.data();
for (int pixel = 0; pixel < w * h; pixel++)
{
dstdata[pixel * 4 + 0] = src[pixel * 2 + 0];
dstdata[pixel * 4 + 1] = src[pixel * 2 + 0];
dstdata[pixel * 4 + 2] = src[pixel * 2 + 0];
dstdata[pixel * 4 + 3] = src[pixel * 2 + 1];
}
texture->replacePixels(dstdata, dstsize, 0, 0, rect, false);
}
else
{
texture->replacePixels(gd->getData(), gd->getSize(), 0, 0, rect, false);
}
double tX = (double) textureX, tY = (double) textureY;
double tWidth = (double) textureWidth, tHeight = (double) textureHeight;
+6 -3
View File
@@ -1813,7 +1813,6 @@ bool Graphics::isPixelFormatSupported(PixelFormat format, PixelFormatUsageFlags
format = getSRGBPixelFormat(format);
const uint32 sample = PIXELFORMATUSAGEFLAGS_SAMPLE;
const uint32 linear = PIXELFORMATUSAGEFLAGS_LINEAR;
const uint32 rt = PIXELFORMATUSAGEFLAGS_RENDERTARGET;
const uint32 blend = PIXELFORMATUSAGEFLAGS_BLEND;
const uint32 msaa = PIXELFORMATUSAGEFLAGS_MSAA;
@@ -1858,8 +1857,12 @@ bool Graphics::isPixelFormatSupported(PixelFormat format, PixelFormatUsageFlags
flags |= all;
break;
case PIXELFORMAT_LA8_UNORM:
// TODO
flags |= commonsample;
// Requires texture swizzle support.
if (@available(macOS 10.15, iOS 13, *))
{
if (families.apple[1] || families.mac[2] || families.macCatalyst[2])
flags |= commonsample;
}
break;
case PIXELFORMAT_RG16_UNORM:
if (families.apple[1])
+2 -3
View File
@@ -36,14 +36,13 @@ class Metal
{
public:
struct API_AVAILABLE(macos(10.15), ios(13.0)) PixelFormatDesc
struct PixelFormatDesc
{
MTLPixelFormat format;
bool swizzled = false;
MTLTextureSwizzleChannels swizzle;
API_AVAILABLE(macos(10.15), ios(13.0)) MTLTextureSwizzleChannels swizzle;
};
API_AVAILABLE(macos(10.15), ios(13.0))
static PixelFormatDesc convertPixelFormat(id<MTLDevice> device, PixelFormat format, bool &isSRGB);
}; // Metal
+10 -5
View File
@@ -143,11 +143,16 @@ Metal::PixelFormatDesc Metal::convertPixelFormat(id<MTLDevice> device, PixelForm
break;
case PIXELFORMAT_LA8_UNORM:
// TODO: fall back to RGBA8 when swizzle isn't available. Pixel format
// size calculation will need to be adjusted as well
mtlformat = MTLPixelFormatRG8Unorm;
desc.swizzled = true;
desc.swizzle = MTLTextureSwizzleChannelsMake(MTLTextureSwizzleRed, MTLTextureSwizzleRed, MTLTextureSwizzleRed, MTLTextureSwizzleGreen);
// Only supported on some systems.
if (@available(macOS 10.15, iOS 13, *))
{
mtlformat = MTLPixelFormatRG8Unorm;
desc.swizzled = true;
desc.swizzle.red = MTLTextureSwizzleRed;
desc.swizzle.green = MTLTextureSwizzleRed;
desc.swizzle.blue = MTLTextureSwizzleRed;
desc.swizzle.alpha = MTLTextureSwizzleGreen;
}
break;
case PIXELFORMAT_RGBA4_UNORM:
+3 -8
View File
@@ -1064,14 +1064,9 @@ id<MTLRenderPipelineState> Shader::getCachedRenderPipeline(const RenderPipelineK
MTLRenderPipelineColorAttachmentDescriptor *attachment = desc.colorAttachments[i];
if (@available(macOS 10.15, iOS 13.0, *))
{
// We already don't really support metal on older systems, this just
// silences a compiler warning about it.
bool isSRGB = false;
auto formatdesc = Metal::convertPixelFormat(device, format, isSRGB);
attachment.pixelFormat = formatdesc.format;
}
bool isSRGB = false;
auto formatdesc = Metal::convertPixelFormat(device, format, isSRGB);
attachment.pixelFormat = formatdesc.format;
if (key.blend.enable)
{
+8 -8
View File
@@ -61,17 +61,17 @@ Texture::Texture(love::graphics::Graphics *gfxbase, id<MTLDevice> device, const
desc.arrayLength = layers;
desc.mipmapLevelCount = mipmapCount;
desc.textureType = getMTLTextureType(texType, 1);
if (@available(macOS 10.15, iOS 13, *))
auto formatdesc = Metal::convertPixelFormat(device, format, sRGB);
desc.pixelFormat = formatdesc.format;
if (formatdesc.swizzled)
{
// We already don't really support metal on older systems, this just
// silences a compiler warning about it.
auto formatdesc = Metal::convertPixelFormat(device, format, sRGB);
desc.pixelFormat = formatdesc.format;
if (formatdesc.swizzled)
// Swizzled formats are already only used on supported systems, this
// just silences a compiler warning about it.
if (@available(macOS 10.15, iOS 13, *))
desc.swizzle = formatdesc.swizzle;
}
else
throw love::Exception("Metal backend is only supported on macOS 10.15+ and iOS 13+.");
desc.storageMode = MTLStorageModePrivate;
if (readable)