Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Metal alpha blending fixes + color handling improvements #4913

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

qwerasd205
Copy link
Collaborator

This PR addresses #2125 for the Metal renderer. Both options are available: "Apple-style" blending where colors are blended in a wide gamut color space, which reduces but does not eliminate artifacts; and linear blending where colors are blended in linear RGB.

Because this doesn't add support for linear blending on Linux, I don't know whether the issue should be closed or not.

List of changes in no particular order

  • We now set the layer's color space in the renderer not in the apprt
  • We always set the layer to Display P3 color spaces
  • If the user hasn't configured their window-colorspace to display-p3 then terminal colors are automatically converted from sRGB to the corresponding Display P3 color in the shader
  • Background color is not set with the clear color anymore, instead we explicitly set all bg cell colors since this is needed for minimum contrast to not break with dark text on the default bg color (try it out, it forces it fully white right now), and we just draw the background as a part of the bg cells shader. Note: We may want to move the main background color to be the backgroundColor property on the CAMetalLayer, because this should fix the flash of transparency during startup (macOS: background bleeds/flicker when resizing splits, creating tabs #4516) and the weirdness at the edge of the window when resizing. I didn't make that a part of this PR because it requires further changes and my changes are already pretty significant, but I can make it a follow-up.
  • Added a config option for changing alpha blending between "native" blending, where colors are just blended directly in sRGB (or Display P3) and linear blending, where colors are blended in linear space.
  • Added a config option for an experimental technique that I think works pretty well which compensates for the perceptual thinning and thickening of dark and light text respectively when using linear blending.
  • Custom shaders can now be hot reloaded with config reloads.
  • Fixed a bug that was revealed when I changed how we handle backgrounds, page widths weren't being set while cloning the screen.

Main takeaways

Color blending now matches nearly identically to Apple apps like Terminal.app and TextEdit, not quite identical in worst case scenarios, off by the tiniest bit, because the default color space is slightly different than Display P3.

Linear alpha blending is now available for mac users who prefer more accurate color reproduction, and personally I think it looks very nice with the alpha correction turned on, I will be daily driving that configuration.

Future work

  • Handle primary background color with CALayer.backgroundColor instead of in shader, to avoid issues around edges when resizing.
  • Parse color space info directly from ICC profiles and compute the color conversion matrix dynamically, and pass it as a uniform to the shaders.
  • Port linear blending option to OpenGL.
  • Maybe support wide gamut images (right now all images are assumed to be sRGB).

Otherwise pages may have the wrong width if they were resized down with
a fast path that just chanes the size without adjusting capacity at all.
This commit is quite large because it's fairly interconnected and can't
be split up in a logical way. The main part of this commit is that alpha
blending is now always done in the Display P3 color space, and depending
on the configured `window-colorspace` colors will be converted from sRGB
or assumed to already be Display P3 colors. In addition, a config option
`text-blending` has been added which allows the user to configure linear
blending (AKA "gamma correction"). Linear alpha blending also applies to
images and makes custom shaders receive linear colors rather than sRGB.

In addition, an experimental option has been added which corrects linear
blending's tendency to make dark text look too thin and bright text look
too thick. Essentially it's a correction curve on the alpha channel that
depends on the luminance of the glyph being drawn.
/// text rendered with non-linear blending.
///
/// Has no effect if not using linear `text-blending`.
@"experimental-linear-correction": bool = false,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not ready to review the whole thing but knee jerk reaction: should this be an alternate enum value for text-blending, i.e. linear-experimental?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably. I set up the config options and then sorta just left them how I put them at first. It might also make sense to rename text-blending to alpha-blending. I'd also kinda like to rename window-colorspace to terminal-colorspace since what it does is define how terminal colors should be interpreted for rendering, but that felt out-of-scope for this PR.

} else .{
.color = true,
.depth = 4,
.space = try macos.graphics.ColorSpace.createDeviceRGB(),
.space = try macos.graphics.ColorSpace.createNamed(.displayP3),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@qwerasd205 suggestion: Should we make this ...ColorSpace.createFromName(.displayP3)?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why? I could understand changing it to createWithName if we wanted to match the name of the CoreGraphics function, but this really feels like splitting hairs either way. I'm not devoted to the name, but if I changed it I'd be more likely to change it to createWithName than createFromName unless there's particularly good reasoning...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants