mirror of
https://github.com/love2d/love.git
synced 2026-08-14 01:20:56 +02:00
metal: use a fallback for fonts when luminance-alpha isn't supported.
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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])
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user