365 Commits

Author SHA1 Message Date
Mitchell Hashimoto
fb9c52ecf4 Nuke GLFW from Orbit
This deletes the GLFW apprt from the Ghostty codebase.

The GLFW apprt was the original apprt used by Ghostty (well, before
Ghostty even had the concept of an "apprt" -- it was all just a single
application then). It let me iterate on the core terminal features,
rendering, etc. without bothering about the UI. It was a good way to get
started. But it has long since outlived its usefulness.

We've had a stable GTK apprt for Linux (and Windows via WSL) and a
native macOS app via libghostty for awhile now. The GLFW apprt only
remained within the tree for a few reasons:

  1. Primarily, it provided a faster feedback loop on macOS because
     building the macOS app historically required us to hop out of the
     zig build system and into Xcode, which is slow and cumbersome.

  2. It was a convenient way to narrow whether a bug was in the
     core Ghostty codebase or in the apprt itself. If a bug was in both
     the glfw and macOS app then it was likely in the core.

  3. It provided us a way on macOS to test OpenGL.

All of these reasons are no longer valid. Respectively:

  1. Our Zig build scripts now execute the `xcodebuild` CLI directly and
     can open the resulting app, stream logs, etc. This is the same
     experience we have on Linux. (Xcode has always been a dependency of
     building on macOS in general, so this is not cumbersome.)

  2. We have a healthy group of maintainers, many of which have access
     to both macOS and Linux, so we can quickly narrow down bugs
     regardless of the apprt.

  3. Our OpenGL renderer hasn't been compatible with macOS for some time
     now, so this is no longer a useful feature.

At this point, the GLFW apprt is just a burden. It adds complexity
across the board, and some people try to run Ghostty with it in the real
world and get confused when it doesn't work (it's always been lacking in
features and buggy compared to the other apprts).

So, it's time to say goodbye. Its bittersweet because it is a big part
of Ghostty's history, but we've grown up now and it's time to move on.
Thank you, goodbye.

(NOTE: If you are a user of the GLFW apprt, then please fork the project
prior to this commit or start a new project based on it. We've warned
against using it for a very, very long time now.)
2025-07-04 14:12:18 -07:00
Qwerasd
da46a47726 renderer: add support for background images
Adds support for background images via the `background-image` config.

Resolves #3645, supersedes PRs #4226 and #5233.

See docs of added config keys for usage details.
2025-06-25 16:27:23 -04:00
Qwerasd
41ae32814f 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.
2025-06-23 18:01:34 -06:00
Qwerasd
df8dc33ab6 renderer: unify image.zig
The code in metal/image.zig and opengl/image.zig was virtually identical
save for the texture options, so I've moved that to the GraphicsAPI and
unified them in to renderer/image.zig
2025-06-23 13:12:17 -06:00
Qwerasd
4b01cc1d88 renderer: unify cell.zig
The code in metal/cell.zig and opengl/cell.zig was virtually identical
aside from the types for the cell data, moved it to renderer/cell.zig
2025-06-23 12:21:30 -06:00
Qwerasd
bb576d1340 renderer: add custom shader cursor uniforms
Based on / supersedes PR #6912, implements discussion #6901

Co-authored-by: Krone Corylus <ahustinkrone@gmail.com>
2025-06-22 11:05:16 -06:00
Qwerasd
ddf1a5b23d renderer: move drawFrame AutoreleasePool handling to GraphicsAPI
Introduces `drawFrameStart`/`drawFrameEnd` for this purpose.
2025-06-20 16:21:44 -06:00
Qwerasd
ab926fc842 naming(GraphicsAPI): repeat -> presentLastTarget 2025-06-20 15:51:48 -06:00
Qwerasd
ea7a91e2ba style(renderer): explicit error sets 2025-06-20 15:18:41 -06:00
Qwerasd
6b7d751007 renderer: make GraphicsAPI.swap_chain_count required 2025-06-20 15:18:41 -06:00
Qwerasd
8b23e73d20 metal: retain IOSurfaceLayer ourselves instead of relying on the view
If this was Swift code, we'd be using a strong reference, which would
retain the layer for us and release it when the object is deallocated,
but this is Zig land so we have to do that manually.

NOTE: We don't *have* to do this, but it fits much better with Zig idiom
and hopefully avoids potential future footguns. We should do this to any
autoreleased objects that we persist a reference to in a Zig struct.
2025-06-20 15:18:41 -06:00
Qwerasd
371d62a82c renderer: big rework, graphics API abstraction layers, unified logic
This commit is very large, representing about a month of work with many
interdependent changes that don't separate cleanly in to atomic commits.

The main change here is unifying the renderer logic to a single generic
renderer, implemented on top of an abstraction layer over OpenGL/Metal.

I'll write a more complete summary of the changes in the description of
the PR.
2025-06-20 15:18:41 -06:00
Qwerasd
f40cd3cae3 chore: improve Metal API definitions a bit 2025-06-20 15:18:41 -06:00
Qwerasd
709b0214a0 fix(renderer): Don't force images to grid/cell sizes
This problem was introduced by f091a69 (PR #6675).

I've gone ahead and overhauled the placement positioning logic as well;
it was doing a lot of expensive calls before, I've significantly reduced
that.

Clipping partially off-screen images is now handled entirely by the
renderer, rather than while preparing the placement, and as such the
grid position passed to the image shader is now signed.
2025-05-15 11:41:12 -06:00
Jeffrey C. Ollie
e8c845b758 core: fixup callconv(.C) -> callconv(.c)
https://ziglang.org/download/0.14.0/release-notes.html#Calling-Convention-Enhancements-and-setAlignStack-Replaced
2025-05-07 08:41:09 -05:00
Mitchell Hashimoto
4d0bf303c6 ci: zig fmt check
This adds a CI test to ensure that all Zig files are properly formatted.
This avoids unrelated diff noise in future PRs.
2025-03-18 13:58:49 -07:00
Mitchell Hashimoto
1f6b1d75eb Fix aspect ratio when rendering images with kitty protocol (#6675)
Fixes https://github.com/ghostty-org/ghostty/issues/6673

<img width="914" alt="image"
src="https://github.com/user-attachments/assets/010a1304-0d46-46ec-9a82-87a8d8fbea1b"
/>
2025-03-13 09:50:19 -07:00
Mitchell Hashimoto
0f4d2bb237 Lots of 0.14 changes 2025-03-12 09:55:52 -07:00
Bryan Lee
f091a69790 Fix aspect ratio when rendering images with kitty protocol 2025-03-12 15:06:06 +08:00
Qwerasd
16a61c43dd fix(Metal): force a full rebuild in setFontGrid
This was causing garbled text due to a non-rebuilt rows referencing an
outdated atlas when the DPI changed but not the grid dimensions, which
could be caused by a variety of things such as the quick terminal
slide-in, dpi scaling changes on sleep/wake, moving windows between
displays because of closing/opening the laptop lid, etc.
2025-02-26 14:11:05 -05:00
Mitchell Hashimoto
d532a6e260 Update libxev to use dynamic backend, support Linux configurability
Related to #3224

Previously, Ghostty used a static API for async event handling: io_uring
on Linux, kqueue on macOS. This commit changes the backend to be dynamic
on Linux so that epoll will be used if io_uring isn't available, or if
the user explicitly chooses it.

This introduces a new config `async-backend` (default "auto") which can
be set by the user to change the async backend in use. This is a
best-effort setting: if the user requests io_uring but it isn't
available, Ghostty will fall back to something that is and that choice
is up to us.

Basic benchmarking both in libxev and Ghostty (vtebench) show no
noticeable performance differences introducing the dynamic API, nor
choosing epoll over io_uring.
2025-02-21 15:04:37 -08:00
Qwerasd
ea16890fd3 Metal: use "Managed" resource storage mode on discrete GPUs
Discrete GPUs cannot use the "shared" storage mode. This causes
undefined behavior right now, and I believe it's what's causing a
problem on Intel systems with discrete GPUs with "inverted" cells.

This commit also sets the CPU cache mode to "write combined" for our
resources since we don't read them back so Metal can optimize them
further with this hint.
2025-02-07 13:15:18 -05:00
Qwerasd
016a26cf98 cleanup: rename text-blending to alpha-blending
+ correct docs
2025-01-27 19:37:44 -05:00
Qwerasd
5c8f984ea1 renderer/Metal: improve linear blending correction
More mathematically sound approach, does a much better job of matching
the appearance of non-linear blending. Removed `experimental` from name
because it's not really an experiment anymore.
2025-01-27 19:15:18 -05:00
Qwerasd
78790f6ef7 fix(Metal): always render explicit background colors fully opaque
This fixes a regression introduced by the rework of this area before
during the color space changes. It seems like the original intent of
this code was the behavior it regressed to, but it turns out to be
better like this.
2025-01-23 20:06:53 -05:00
Qwerasd
3b8ab10776 fix(renderer): clip terminal contents to expected grid size (#4523)
This significantly improves the robustness of the renderers since it
prevents synchronization issues from causing memory corruption due to
out of bounds read/writes while building the cells.

TODO: when viewport is narrower than renderer grid size, fill blank
margin with bg color- currently appears as black, this only affects
DECCOLM right now, and possibly could create single-frame artefacts
during poorly managed resizes, but it's not ideal regardless.
2025-01-20 18:56:13 -05:00
Qwerasd
34abe2ceba fix(macos): prevent transparency leakage/flash in new/resized surfaces
By using the `CAMetalLayer`'s `backgroundColor` property instead of
drawing the background color in our shader, it is always stretched to
cover the full surface, even when live-resizing, and it doesn't require
us to draw a frame for it to be initialized so there's no transparent
flash when a new surface is created (as in a new split/tab).

This commit also allows for hot reload of `background-opacity`,
`window-vsync`, and `window-colorspace`.
2025-01-14 20:23:21 -05:00
Mitchell Hashimoto
a8b9c5bea5 config: remove experimental linear and merge into text-blending 2025-01-13 13:59:37 -08:00
Qwerasd
fca336c32d Metal: blend in Display P3 color space, add option for linear blending
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.
2025-01-13 13:50:29 -08:00
Mitchell Hashimoto
300884d50f refactor(font): move Metrics from Face to Collection (#4739)
This refactor enables two very significant improvements to our font
handling, which I will be implementing next:
1. Automatically adjust size of fallback faces to better align with the
primary face, a la CSS
[`font-size-adjust`](https://developer.mozilla.org/en-US/docs/Web/CSS/font-size-adjust).
[^1]
2. Move glyph resizing/positioning out of GPU-land and in to
`renderGlyph` and apply alignment/resizing rules from the nerd fonts
patcher[^2] to the glyphs at rasterization time, so that we can ensure
exact cell fits and swap out our embedded JB Mono with an unpatched
version with a separate dedicated symbols-only nerd font.

In addition to being necessary prep work for those two changes, this PR
is also a minor but real stand-alone improvement. By only computing the
cell metrics for our primary font, we avoid a *lot* of wasted work when
loading fallback fonts, and also avoid that being a source of load
errors, which we don't yet handle gracefully[^3].

To validate this PR I've run the full set of font backend tests locally
on my Mac with no failures, and did a sanity check of running Ghostty
with both renderers and with CoreText and FreeType font backends and
then `cat`ing a file that requires fallback fonts to render, and
everything looks correct.

[^1]: #3029

[^2]: The alignment and resizing rules for the nerd font symbols are
defined in the patcher
[here](6d0b8ba05a/font-patcher (L866-L1151))

[^3]: #2991
2025-01-07 20:43:48 -08:00
Gregory Anders
b2716375ac renderer: respect reverse with cursor-invert-fg-bg 2025-01-07 12:01:45 -06:00
Qwerasd
540fcc0b69 refactor(font): move Metrics out of face
in preparation to move ownership of metrics from faces to collections
2025-01-06 20:13:45 -05:00
yonihemi
63a47d0ba5 iOS: Fix crash on device 2025-01-06 22:01:41 +08:00
Qwerasd
25a112469c font(coretext): add config to adjust strength of font-thicken.
This is achieved by rendering to an alpha-only context rather than a
normal single-channel context, and adjusting the brightness at which
coretext thinks it's drawing the glyph, which affects how it applies
font smoothing (which is what `font-thicken` enables).
2025-01-03 14:19:19 -05:00
Mitchell Hashimoto
64ea3a1a29 renderer: track if fg/bg/cursor color is explicitly set by an OSC (#3228)
The renderer must track if the foreground, background, and cursor colors
are explicitly set by an OSC so that changes are not overridden when the
config file is reloaded.

Fixes: https://github.com/ghostty-org/ghostty/issues/2795
2024-12-29 09:05:37 -08:00
Xiaoyan Li
2993d12de7 Use premultiplied alpha for renderer clearColor
Fixes #3324
2024-12-28 19:37:24 -08:00
Gregory Anders
eef9664ef8 renderer: track if fg/bg/cursor color is explicitly set by an OSC
The renderer must track if the foreground, background, and cursor colors
are explicitly set by an OSC so that changes are not overridden when the
config file is reloaded.
2024-12-26 20:18:45 -06:00
Mitchell Hashimoto
bd90a6dd3b kittygfx: placement with rows (r) param scrolls properly out of viewport
Fixes #2332

Two bugs fixed to fix this behavior:

1. Our destination height didn't account for the top-left being
   offscreen.

2. We were using the wrong height for the source rectangle. When a rows
   param (r=) is specified, the image height and destination height are
   at different scales. We were using the viewport scale for the offset
   but it should be the image scale.
2024-12-23 14:11:14 -08:00
Mitchell Hashimoto
a908aca563 kittygfx: z-index handling fixes
Fixes #2921

Our z-index handling was pretty much completely broken, hence I can't
think of a better initial commit message. We were splitting the
placements at the wrong points and just generally putting images in the
wrong z-index. I'm shocked this didn't come up earlier.
2024-12-23 12:46:46 -08:00
Mitchell Hashimoto
f8a8b0464c renderer/opengl: fix memory leak when copying font features 2024-11-20 14:08:00 -08:00
Mitchell Hashimoto
1792ddfff1 remove some unused structs 2024-11-14 14:25:42 -08:00
Mitchell Hashimoto
b3b5e15e96 renderer/metal: use new size struct 2024-11-14 13:44:05 -08:00
Mitchell Hashimoto
aed51fd0b0 terminal: PageList rename "page" to "node" everywhere
This is more correct: a pagelist is a linked list of nodes, not pages.
The nodes themselves contain pages but we were previously calling the
nodes "pages" which was confusing, especially as I plan some future
changes to the way pages are stored.
2024-11-07 13:44:39 -08:00
Emily
20a77123d4 renderer/metal: prefer low‐power GPUs
Some Intel MacBook Pro laptops have both an integrated and discrete
GPU and support automatically switching between them. The system
uses the integrated GPU by default, but the default Metal device on
those systems is the discrete GPU. This means that Metal‐using
applications activate it by default, presumably as the intended
audience is high‐performance graphics applications.

This is unfortunate for productivity applications like terminals,
however, as the discrete GPU decreases battery life and worsens the
thermal throttling problems these machines have always had. Prefer
to use an integrated GPU when present and not using an external GPU.

The behaviour should be unchanged on Apple Silicon, as the platform
only supports one GPU. I have confirmed that the resulting app runs,
works, and doesn’t activate the AMD GPU on my MacBook Pro, but have
not done any measurements of the resulting performance impact. If
it is considered sufficiently noticeable, a GPU preference setting
could be added.

See <https://github.com/zed-industries/zed/issues/5124>,
<https://github.com/zed-industries/zed/pull/13685>,
<https://github.com/zed-industries/zed/pull/14738>, and
<https://github.com/zed-industries/zed/pull/14744> for discussion,
measurements, and changes relating to this issue in the Zed
project. The logic implemented here reflects what Zed ended up
settling on.

The [Metal documentation] recommends using
`MTLCopyAllDevicesWithObserver` to receive notifications of when
the list of available GPUs changes, such as when [external GPUs
are connected or disconnected]. I didn’t bother implementing that
because it seemed like a lot of fussy work to deal with migrating
everything to a new GPU on the fly just for a niche use case on a
legacy platform. Zed doesn’t implement it and I haven’t heard
about anyone complaining that their computer caught fire when they
unplugged an external GPU, so hopefully it’s fine.

[Metal documentation]: https://developer.apple.com/documentation/metal/gpu_devices_and_work_submission/multi-gpu_systems/finding_multiple_gpus_on_an_intel-based_mac
[external GPUs are connected or disconnected]: https://developer.apple.com/documentation/metal/gpu_devices_and_work_submission/multi-gpu_systems/handling_external_gpu_additions_and_removals

Closes: #2572
2024-11-04 00:35:21 +00:00
Emily
9c8b00f87d renderer/metal: release device on deinit() 2024-11-04 00:21:39 +00:00
Emily
e5f9f222b2 renderer/metal: use release() consistently
I’m not sure why this variation was here previously – maybe it
predated the introduction of `release()`?
2024-11-04 00:21:39 +00:00
Marijn Besseling
4496e7d314 implement overline decoration (SGR 53/55) 2024-10-21 08:36:08 -04:00
Qwerasd
0bb176d22c renderer: cleanup, reduce nesting, more comments 2024-10-09 15:53:02 -04:00
Qwerasd
7686cacde6 renderer, shaper: don't use null cells, handle bg and decorations separately
Significant rework that also removes a lot of unnecessarily duplicated
work while rebuilding cells in both renderers. Fixes multiple issues
with decorations and bg colors on wide chars and ligatures, while
reducing the amount of special case handling required.
2024-10-08 23:10:43 -04:00
Mitchell Hashimoto
89fadfc202 renderer: fg/bg/cursor change must mark the screen as dirty
Fixes #2372
2024-10-04 06:58:50 -10:00