Commit Graph

51 Commits

Author SHA1 Message Date
Mitchell Hashimoto
62ed472d9e Revert "renderer: slightly optimize screen copy" (#8974)
This reverts commit fcea09e413 because it
appears to be causing memory leaks.
2025-10-08 09:57:14 -07:00
Mitchell Hashimoto
e974d58615 Inline All The Things (#8946)
I used the new CPU counter mode in Instruments.app to track down
functions that had instruction delivery bottlenecks (indicating i-cache
misses) and picked a bunch of trivial functions to mark as inline (plus
a couple that are only used once or twice and which benefit from
inlining).

The size of `macos-arm64/libghostty-fat.a` built with `zig build
-Doptimize=ReleaseFast -Dxcframework-target=native` goes from
`145,538,856` bytes on `main` to `145,595,952` on this branch, a
negligible increase.

These changes resulted in some pretty sizable improvements in vtebench
results on my machine (Apple M3 Max):
<img width="983" height="696" alt="image"
src="https://github.com/user-attachments/assets/cac595ca-7616-48ed-983c-208c2ca2023f"
/>

With this, the only vtebench test we're slower than Alacritty in (on my
machine, at 130x51 window size) is `dense_cells` (which, IMO, is so
artificial that optimizing for it might actually negatively impact real
world performance).

I also did a pretty simple improvement to how we copy the screen in the
renderer, gave it its own page pool for less memory churn. Further
optimization in that area should be explored since in some scenarios it
seems like as much as 35% of the time on the `io-reader` thread is spent
waiting for the lock.

> [!NOTE]
> Before this is merged, someone really ought to test this on an x86
processor to see how the performance compares there, since this *is*
tuning for my processor specifically, and I know that M chips have
pretty big i-cache compared to some x86 processors which could impact
the performance characteristics of these changes.
2025-10-06 08:59:22 -07:00
Mitchell Hashimoto
b34f3f7208 renderer: create explicit sampler state for custom shaders
The GLSL to MSL conversion process uses a passed-in sampler state for
the `iChannel0` parameter and we weren't providing it. This magically
worked on Apple Silicon for unknown reasons but failed on Intel GPUs.

In normal, hand-written MSL, we'd explicitly create the sampler state as
a normal variable (we do this in `shaders.metal` already!), but the
Shadertoy conversion stuff doesn't do this, probably because the exact
sampler parameters can't be safely known.

This fixes a Metal validation error when using custom shaders:

```
-[MTLDebugRenderCommandEncoder validateCommonDrawErrors:]:5970: failed 
assertion `Draw Errors Validation Fragment Function(main0): missing Sampler 
binding at index 0 for iChannel0Smplr[0].
```
2025-09-29 12:51:48 -07:00
Daniel Wennberg
812dc7cf2f Rewrite constraint code for improved icon scaling/alignment 2025-09-29 12:45:56 -07:00
Qwerasd
31e54ff44a comment + style changes 2025-09-08 10:40:56 -06:00
Jesse Miller
ecf3e2ad7d Position-independent font shaper caching
Use relative cluster positioning to allow identical texts runs in
different row positions to share the same cache entry.
2025-09-07 16:33:35 -06:00
Qwerasd
2464728851 font: constrain dingbats
This was a regression, we were giving dingbats an extra cell of
constraint width but not actually applying constraints to them.
2025-09-03 18:01:40 -06:00
Qwerasd
ef7857f9be fix(renderer): kitty images should all be processed
When processing kitty images in a loop in a few places we were returning
under certain conditions where we should instead have just continued the
loop. This caused serious problems for kitty images, especially for apps
that used multiple images on screen at once.

... I have no clue how I originally wrote this code and didn't see such
a trivial mistake, I think I was sleep deprived or something.
2025-09-02 12:42:34 -06:00
Mitchell Hashimoto
2009ea511d feat: added faint-opacity option (#8472)
This pull request adds the `--faint-opacity` option, as discussed in
#7637.

The default value of the option is also changed from `0.68` to `0.5` for
greater consistency with other popular terminal emulators.
2025-08-31 13:45:26 -07:00
Qwerasd
0d30f859bd renderer: clarify and correct custom shader cursor position math
This math was incorrect from the start, the previous fix helped OpenGL
but broke positioning under Metal; this commit fixes the math to be
correct under both backends and adds comments explaining exactly what's
going on.
2025-08-31 11:44:10 -06:00
Pavel Ivanov
6319464cfb refactor: move faint-opacity clamping to config finalization 2025-08-31 17:19:51 +02:00
Pavel Ivanov
fc6266133f feat: added faint-opacity option 2025-08-31 15:00:29 +02:00
ClearAspect
f7994e6412 fix: correct the cursor Y position value exposed to shader uniforms
Fix for discussion #8113

The cursor Y position value exposed to the shader uniforms was
incorrectly calculated. As per the doc in cell_text.v.glsl: In order to
get the top left of the glyph, we compute an offset based on the
bearings. The Y bearing is the distance from the bottom of the cell to
the top of the glyph, so we subtract it from the cell height to get the
y offset.

This calculation was mistakenly left out of the original code.

This will ensure that the custom shaders using
iCurrentCursor/iPreviousCursor get the correct Y coordinate representing
the top-left corner of the cursor rectangle, matching the documented
uniform behavior
2025-08-21 10:08:49 -07:00
Qwerasd
add7f762a6 fix(renderer/generic): deinit render targets with framestate
This was a memory leak under Metal, leaked 1 swapchain worth of targets
every time a surface was closed.

Under OpenGL I think it was all cleaned up when the GL context was
destroyed.
2025-08-14 11:47:05 -06:00
nferhat
991426e84e renderer: Allow the renderer to draw transparent cells
Co-authored-by: Kat <65649991+00-kat@users.noreply.github.com>
2025-07-11 06:59:01 -07:00
ClearAspect
88736a2ddb Fix custom shader cursor uniforms not set for non-block cursors (#7893)
Fixes #7893

Previously, custom shader cursor uniforms were only updated when the
cursor glyph was in the front (block) cursor list. This caused non-block
cursors (such as bar, underline, hollow block, and lock) to be missing
from custom shader effects.

This commit adds a helper to the cell contents struct to retrieve the
current cursor glyph from either the front or back cursor lists, and
updates the renderer to use this helper when setting custom shader
uniforms. As a result, custom shaders now receive correct cursor
information for all supported cursor styles.
2025-07-10 00:21:21 -04:00
Robert Ian Hawdon
52790fb92c Added bold-color option 2025-07-06 12:56:43 -07:00
Mitchell Hashimoto
b799462745 Better Glyph Constraint Logic (#7809)
This is a big'un.

- **Glyph constraint logic is now done fully on the CPU** at the
rasterization stage, so it only needs to be done once per glyph instead
of every frame. This also lets us eliminate padding between glyphs on
the atlas because we're doing nearest-neighbor sampling instead of
interpolating-- which ever so slightly increases our packing efficiency.
- **Special constraints for nerd font glyphs** are applied based roughly
on the constraints they use in their patcher. It's a simplification of
what they do, the largest difference being that they scale groups of
glyphs based on a shared bounding box so that they maintain relative
size to one another, but that would require loading all glyphs on the
group and I'd want to do that on font load TBH and at that point I'd
basically be re-implementing the nerd fonts patcher in Zig to patch
fonts at load time which is way beyond the scope I want to have. (Fixes
#7069)
- These constraints allow for **perfectly sized and centered emojis**,
this is very nice.
- **Changed the default embedded fonts** from 4 copies (regular, italic,
bold, bold italic) of a patched (and outdated) JetBrains Mono to a
single JetBrains Mono variable font and a single Nerd Fonts Symbols Only
font. This cuts the weight of those down from 9MB to 3MB!
- **FreeType's `renderGlyph` is significantly reworked**, and the new
code is, IMO, much cleaner- although there are probably some edge case
behavior differences I've introduced.

> [!NOTE]
> One breaking change I definitely introduced is changing the
`monochrome` freetype load flag config from its previous completely
backwards meaning to instead the correct one (I also changed the
default, so this won't affect any user who hasn't touched it, but users
who set the `monochrome` flag will find their fonts quite crispy after
this change because they will have no anti-aliasing anymore)

### Future work

Following this change I want to get to work on automatic font size
matching (a la CSS
[`font-size-adjust`](https://developer.mozilla.org/en-US/docs/Web/CSS/font-size-adjust)).
I set the stage for that quite some time ago so it shouldn't be too much
work and it will be a big benefit for users who regularly use multiple
writing systems and so have multiple fonts for them that aren't
necessarily size-compatible.
2025-07-05 14:37:46 -07:00
Mitchell Hashimoto
390812828a Nuke GLFW, make zig build run on macOS build the Xcode project (#7815)
This PR does two things.

1. Build system improvements to make developing on macOS more enjoyable 
2. Delete the GLFW apprt

## Build System Improvements (macOS)

On macOS, there are a few major improvements:

* `zig build` now produces a full macOS app bundle and copies it into
`zig-out`
* `zig build run` now builds the macOS app and runs it, streaming logs
directly into the terminal
* `-Demit-macos-app` can control whether app bundle is created
* `-Dxcframework-target` can be set to one of `native` or `universal` to
control whether the xcframework uses only your target machines arch or
creates a universal one with macOS and iOS. This defaults to `native`
for the `run` command and `universal` for all others.
* The general flow of the `build.zig` file was improved to be more
declarative

## Nuke GLFW

> 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-05 13:49:24 -07:00
Daniel
a9fc3b6fa0 enable drawing cursor on top or bottom based on style 2025-07-04 18:50:23 -04:00
Qwerasd
ec20c455c7 renderer: remove all gpu-side glyph constraint logic
Now that it's done at the rasterization stage, we don't need to handle
it on the GPU. This also means that we can switch to nearest neighbor
interpolation in the Metal shader since we're guaranteed to be pixel
perfect. Accidentally, we were already nearest neighbor in the OpenGL
shaders because I used the Rectangle texture mode in the big renderer
rework, which doesn't support interpolation- anyway, that's no longer
problematic since we won't be scaling glyphs on the GPU anymore.
2025-07-04 15:47:35 -06:00
Qwerasd
95c8747ab5 renderer: apply glyph constraints when rasterizing glyphs 2025-07-04 15:47:28 -06:00
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
Mitchell Hashimoto
465ac5b1b7 clean up some of the color usage, use exhaustive switches 2025-07-03 09:25:56 -07:00
Daniel
95de198761 Squash and rebase, updated refactored version with selection and cursor cell color changes 2025-07-03 07:14:37 -07:00
Qwerasd
2084d5f256 font/sprite+renderer: never constrain sprite glyphs
This was creating problems with the branch drawing glyphs at some sizes.

In the future the whole "foreground modes" thing needs to be reworked,
so this is just a stopgap until that gets turned in to something nicer.
2025-06-30 11:16:47 -06:00
Qwerasd
4f9d7c565a font/sprite: add explicit underline cursor
Resolves #7651 - uses cursor thickness rather than underline thickness.
2025-06-30 11:16:47 -06:00
Mitchell Hashimoto
73ff4b8f74 move runIterator options to dedicated struct 2025-06-30 09:05:09 -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
03bdb92292 renderer: clean up image.zig, reduce repetitive code 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
f5439c860a renderer: extract kitty image upload in drawFrame to fn
For cleanliness -- also updated some comments while I was at it.
2025-06-23 18:01:34 -06:00
Qwerasd
706a43138e renderer: keep post uniform buffer in frame state
This avoids creating a new buffer for this every frame.
2025-06-23 18:01:34 -06:00
Qwerasd
1da40ccbac fix(renderer): kitty image z-index accounting
The previous logic would consider all images fg if the only present
placements were bg, or consider mg images fg if there were no fg.
2025-06-23 18:01:34 -06:00
Qwerasd
4c3ab14571 renderer: make shader pipeline prep code DRYer
In this format it will be a lot easier to iterate on this since adding
and removing pipelines only has to be done in a single place.

This commit also separates out the main background color from individual
cell background color drawing, because sometimes kitty images need to be
between the main background and individual cell backgrounds (kitty image
z-index seems to be entirely broken at the moment, I intend to fix it in
future commits).
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
7ca9cd1994 docs: document uniforms available to custom shaders 2025-06-22 17:07:26 -06:00
Qwerasd
d0ff2452d5 renderer: add cursor color to custom shader uniforms 2025-06-22 11:05:16 -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
c7a7474be0 renderer: move custom shader uniforms out of frame state
These should not be independent per-frame, that makes the time
calculations all sorts of jank.

Also moves the uniforms struct layout in to `shadertoy.zig` and cleans
up the handling in general somewhat.
2025-06-21 23:07:18 -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
a802108558 renderer: remove unused surface parameter from updateFrame 2025-06-20 15:49:53 -06:00
Qwerasd
8b9e6641f2 style(renderer): explicit result type
In case of future breaking changes to `options`
2025-06-20 15:48:44 -06:00
Qwerasd
9d00018f8b renderer: minimize initial size of GPU resources
These will all be resized anyway on the first frame, so there's no point
in preallocating sizes that will be too small.
2025-06-20 15:18:41 -06:00
Qwerasd
2f10caec8f renderer: clarify why SwapChain.defunct is required 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
dccbec2283 style(renderer): capture generic consts as decls in returned struct
Out of an abundance of caution, since there have been issues in the past
relating to consts outside of the returned struct.
2025-06-20 15:18:41 -06:00
Qwerasd
ac2eef9aeb renderer: disable multi-buffering for OpenGL
Frames are sequential for OpenGL since the completion handler always
calls `glFinish`, so the extra buffers do nothing but waste memory.
2025-06-20 15:18:41 -06:00