mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-10-15 14:26:09 +00:00
renderer: fix color glyph rendering under OpenGL
Also changes color atlas to always use an sRGB internal format so that the texture reads automatically linearize the colors. Renames the misleading `rgba` atlas format to `bgra`, since both FreeType and CoreText are set up to draw color glyphs in bgra.
This commit is contained in:
@@ -50,15 +50,18 @@ modified: std.atomic.Value(usize) = .{ .raw = 0 },
|
||||
resized: std.atomic.Value(usize) = .{ .raw = 0 },
|
||||
|
||||
pub const Format = enum(u8) {
|
||||
/// 1 byte per pixel grayscale.
|
||||
grayscale = 0,
|
||||
rgb = 1,
|
||||
rgba = 2,
|
||||
/// 3 bytes per pixel BGR.
|
||||
bgr = 1,
|
||||
/// 4 bytes per pixel BGRA.
|
||||
bgra = 2,
|
||||
|
||||
pub fn depth(self: Format) u8 {
|
||||
return switch (self) {
|
||||
.grayscale => 1,
|
||||
.rgb => 3,
|
||||
.rgba => 4,
|
||||
.bgr => 3,
|
||||
.bgra => 4,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
@@ -79,7 +79,7 @@ pub fn init(
|
||||
|
||||
var atlas_grayscale = try Atlas.init(alloc, 512, .grayscale);
|
||||
errdefer atlas_grayscale.deinit(alloc);
|
||||
var atlas_color = try Atlas.init(alloc, 512, .rgba);
|
||||
var atlas_color = try Atlas.init(alloc, 512, .bgra);
|
||||
errdefer atlas_color.deinit(alloc);
|
||||
|
||||
var result: SharedGrid = .{
|
||||
|
@@ -391,7 +391,7 @@ pub const Face = struct {
|
||||
const format: ?font.Atlas.Format = switch (bitmap_ft.pixel_mode) {
|
||||
freetype.c.FT_PIXEL_MODE_MONO => null,
|
||||
freetype.c.FT_PIXEL_MODE_GRAY => .grayscale,
|
||||
freetype.c.FT_PIXEL_MODE_BGRA => .rgba,
|
||||
freetype.c.FT_PIXEL_MODE_BGRA => .bgra,
|
||||
else => {
|
||||
log.warn("glyph={} pixel mode={}", .{ glyph_index, bitmap_ft.pixel_mode });
|
||||
@panic("unsupported pixel mode");
|
||||
|
@@ -347,7 +347,7 @@ pub fn initAtlasTexture(
|
||||
) Texture.Error!Texture {
|
||||
const pixel_format: mtl.MTLPixelFormat = switch (atlas.format) {
|
||||
.grayscale => .r8unorm,
|
||||
.rgba => .bgra8unorm,
|
||||
.bgra => .bgra8unorm_srgb,
|
||||
else => @panic("unsupported atlas format for Metal texture"),
|
||||
};
|
||||
|
||||
|
@@ -440,7 +440,7 @@ pub fn initAtlasTexture(
|
||||
const format: gl.Texture.Format, const internal_format: gl.Texture.InternalFormat =
|
||||
switch (atlas.format) {
|
||||
.grayscale => .{ .red, .red },
|
||||
.rgba => .{ .rgba, .srgba },
|
||||
.bgra => .{ .bgra, .srgba },
|
||||
else => @panic("unsupported atlas format for OpenGL texture"),
|
||||
};
|
||||
|
||||
|
@@ -336,7 +336,7 @@ pub fn Renderer(comptime GraphicsAPI: type) type {
|
||||
const color = try api.initAtlasTexture(&.{
|
||||
.data = undefined,
|
||||
.size = 1,
|
||||
.format = .rgba,
|
||||
.format = .bgra,
|
||||
});
|
||||
errdefer color.deinit();
|
||||
|
||||
|
@@ -87,19 +87,19 @@ void main() {
|
||||
case MODE_TEXT_COLOR:
|
||||
{
|
||||
// For now, we assume that color glyphs
|
||||
// are already premultiplied sRGB colors.
|
||||
// are already premultiplied linear colors.
|
||||
vec4 color = texture(atlas_color, in_data.tex_coord);
|
||||
|
||||
// If we aren't doing linear blending, we can return this right away.
|
||||
if (!use_linear_blending) {
|
||||
// If we are doing linear blending, we can return this right away.
|
||||
if (use_linear_blending) {
|
||||
out_FragColor = color;
|
||||
return;
|
||||
}
|
||||
|
||||
// Otherwise we need to linearize the color. Since the alpha is
|
||||
// premultiplied, we need to divide it out before linearizing.
|
||||
// Otherwise we need to unlinearize the color. Since the alpha is
|
||||
// premultiplied, we need to divide it out before unlinearizing.
|
||||
color.rgb /= vec3(color.a);
|
||||
color = linearize(color);
|
||||
color = unlinearize(color);
|
||||
color.rgb *= vec3(color.a);
|
||||
|
||||
out_FragColor = color;
|
||||
|
@@ -553,19 +553,19 @@ fragment float4 cell_text_fragment(
|
||||
}
|
||||
|
||||
case MODE_TEXT_COLOR: {
|
||||
// For now, we assume that color glyphs are
|
||||
// already premultiplied Display P3 colors.
|
||||
// For now, we assume that color glyphs
|
||||
// are already premultiplied linear colors.
|
||||
float4 color = textureColor.sample(textureSampler, in.tex_coord);
|
||||
|
||||
// If we aren't doing linear blending, we can return this right away.
|
||||
if (!uniforms.use_linear_blending) {
|
||||
// If we're doing linear blending, we can return this right away.
|
||||
if (uniforms.use_linear_blending) {
|
||||
return color;
|
||||
}
|
||||
|
||||
// Otherwise we need to linearize the color. Since the alpha is
|
||||
// premultiplied, we need to divide it out before linearizing.
|
||||
// Otherwise we need to unlinearize the color. Since the alpha is
|
||||
// premultiplied, we need to divide it out before unlinearizing.
|
||||
color.rgb /= color.a;
|
||||
color = linearize(color);
|
||||
color = unlinearize(color);
|
||||
color.rgb *= color.a;
|
||||
|
||||
return color;
|
||||
|
Reference in New Issue
Block a user