Make the layer allocation more dynamic, which makes it
possible for the box model stuff to allocate a layer based
on the zindex for an element.
Adjust the box model code to cascade the base zindex via
the layer context so that the render stage can select
the correct layer.
This fixes up rendering tabs over the top of the right status
area.
Each layer has the same 3-pass draw that we use for the main terminal
display.
These layers allow for potentially compositing between the layers.
That is untested at the moment as the upper layers use the box model
stuff which hard-codes its work to the vb index 1 which doesn't
use regular alpha blending.
This comes from a time where our quads were always locked to grid
positions. We don't need it any more: we can simply add the adjustments
to the quad positions that we set.
Removing it makes the vertex a bit smaller and reduces the amount
of GPU accessible memory we need to use.
On Windows, both EGL and MESA render modes were too dark.
After a bit of hunting around what I found made EGL and MESA
consistent with my default nVidia GPL rendering was:
* Tell glium that our shader outputs srgb
* Add explicit gamma conversion from linear to srgb in the shader
AFAICT, that shouldn't be required, but it seems as though something
deep in glium really wants to apply some kind of gamma conversion,
and it seems to select the wrong kind unless we set things explicitly
to SRGB.
There are some people complaining about this in
https://github.com/glium/glium/issues/1615.
I actually tried to move entirely aware from the glium srgbtexture2d
type in the hope of having explicit control over the gamma, but the
issue is in what happens to the outputs rather than the inputs.
It appears to me as though the text now looks slightly less
intense, so I think this may be what we need for the gamma issue
in https://github.com/wez/wezterm/issues/544 and potentially
also https://github.com/wez/wezterm/issues/1025
refs: https://github.com/wez/wezterm/issues/1373
Since we may have two different sizes/namespaces of fonts between
the title font and the main terminal font, we need to be a bit more
careful to pass down distinguishing font information when caching
glyphs.
In addition, I noticed that the advance for custom block glyphs
(eg: powerline!) weren't right in the tab bar. To resolve this,
when shaping, we skip using the glyph from the font and synthesize
a placeholder with the appropriate advance.
This splits rendering into 3 passes:
* background pass for z-index < 0. This is for solid background colors,
background images, and image attachments with z-index < 0.
Rendered with regular alpha blending.
* glyph pass: for glyphs at z-index==0. This is rendered with dual
source blending enabled to facilitate subpixel aa appearance.
* top layer pass for z-index >= 0 graphics. This is rendered with
regular alpha blending.
This avoids weird effects, like images with alpha shining through
the back of the window when the window itself isn't transparent.
refs: #544
This makes the comparison in https://github.com/wez/wezterm/issues/544
work for me on mac, linux (x11, wayland) and also on Windows but
only using WGL.
It looks like we can use the proper colorspace on all targets
except for ANGLE EGL. For whatever reason, the combination of
glium and ANGLE EGL on windows over-gamma corrects.
AFAICT, the framebuffer and perhaps the surfaces it creates
don't indicate srgb support, and whatever combination of status
they return tickles glium's srgb stuff the wrong way.
I think the "solution" is just to directly use WGL by default.
EGL was on by default because it tended to be more survivable
when graphics card drivers were updated, but the last couple
of times I updated mine it still killed wezterm anyway.
refs: #544
This replaces the slightly gnarly subpixel enabled blending in the
shader with Dual Source Blending, which is a technique where the
fragment shader can specify both the primary color (RGBA) as well
as an additional per-channel mask that can be used to alpha blend
with the destination.
This enables artifact-free alpha blending when used together
with a transparent window background.
refs: https://github.com/wez/wezterm/issues/932
I noticed when running the notcurses demo that we're spending a
decent amount of time decoding png data whenever we need to
re-do the texture atlas.
Let's avoid that by allowing for ImageData at the termwiz layer
to represent both the image file format and decoded rgba8 data.
This commit is a bit muddy and also includes some stuff to try
to delete placements from the model. It's not perfect by any
means--more expensive than I want, and there's something funky
that causes a large number of images to build up during some
phases of the demo.
refs: #986
Taking further advantage of dynamic quad allocation, we can now
remove the multiple render passes in favor of allocating the quads
and painting them from back to front.
In turn, this means that we can reduce the amount of data that we
store in the vertex, which simplifies the shaders a bit, at the
expense of making the render code in rust a bit more complex.
However, we can take advantage of stretching runs of cells with
background colors in to a single quad.
refs: #986
This was added in 365a68dfb8 to free the
orca from its cage. With the recent dynamic quad allocation changes, we
don't need a distinct 4th pass any more and can simply layer a separate
quad on top of the glyph quad.
refs: #986
This removes the pre-allocated (at resize) number of quads
and replaces it with a dynamic mechanism that tracks how many
quads are needed for a frame and then will re-allocate and
re-render when there weren't enough.
We start with 1024 quads and try to allocate in multiples
of 1024 quads.
refs: #986
This commit removes the `Quads` struct which maintained pre-defined quad
indices for each of the cells, the background image and scrollbar thumb.
In its place, we now "dynamically" hand out quads to meet the needs of
what is being rendered. There are some efficiency gains here with
things like the selection (which can now be a single stretched quad,
rather than `n` quads in width).
This isn't a fully dynamic allocation scheme, as we still allocate the
current worst case number of quads when resizing.
A following commit will adjust that so that we allocate a ballpark and
then employ a mechanism similar to OutOfTextureSpace to grow and retry a
render pass when we need more quads.
Futhermore, this dynamic approach may allow reducing the amount of stuff
we have in the Vertex and "simply" render some quads before others so
that we don't have to have so many draw() passes to build up the
complete scene.
refs: #986
This commit introduces a 4th draw pass for rendering sixel and
iterm images that are attached to cells.
Previously, a cell could container either text or an image from
the perspective of the renderer. If it had an image then the glyph
bitmap would be ignored in favor of the image.
However, that causes sixel behavior to diverge from other terminals
(https://github.com/wez/wezterm/issues/942) so we need to be render
both of these.
The simplest way to achieve this is to add a distinct set of texture
coordinates for the attached image and then add a draw pass to alpha
blend it over the glyph content.
The sixel/iterm image processing stage is also adjusted to preserve
the prior cell information and "simply" attach the image info to
the cell. Previously, the cell would be replaced with a blank cell
with the image attached.
The result of this is that the notcurses-demo intro section can
now render the orca "enveloped in the soft glow of glyphs" rather
than caged in a black box.
Note that there are some cases where the render turns blocky but
I suspect that that is due to some other misunderstanding between
wezterm and notcurses and that we'll root cause it as a follow up.
Switches from using a dynamic vertex buffer to an immutable
vertex buffer. This feels counter-intuitive to me; the purpose
of dynamic is to sustain frequent updates, but mapping the buffer
needs to synchronize with the GPU, and if we are rapidly invalidating
the window that can stall painting by tens of milliseconds.
Switching to an immutable buffer avoids the stall and makes
quad mapping more consistently < 10ms, but its still not
ideal.
refs: https://github.com/wez/wezterm/issues/546
A casualty of b8dcfba9a4 was that
the decoded gif would get reset each time the texture filled up.
Take care to move that cached into the newly minted glyphcache.
Two issues highlighted by profiling:
* Clearing the texture takes a non-trivial percentage of the profile.
The docs suggest that it is better to create a new texture than
to update large portions of a texture, so add some plumbing so
that we can do that in the first texture-full case.
* Next on the list is the code that translates from linear BGRA to
SRGBA. This is present for reasons that I believe are now legacy,
but for the moment: those two primitives now have faster and
easier implementations, so simplify to those.
This improves the timg video playback performance by ~10% for me.
refs: #537
This is to support <https://github.com/wez/wezterm/issues/291>.
The window resized event happens asynchronously wrt. processing
a window resize, triggering at the end of the normal window
resize handling.
This commit introduces the notion of whether we are in full screen
mode or not in the underlying event callback, which is useful to
gate the desired feature, which is: when in full screen mode,
increase the padding for the window to center its content.
While poking around at this, I noticed that we weren't passing
the per-window config down to the code that computes the quad
locations for the window.
This commit also changes the font size increase/decrease behavior
so that in full screen mode it doesn't try to resize the window.
```lua
local wezterm = require 'wezterm';
wezterm.on("window-resized", function(window, pane)
local window_dims = window:get_dimensions();
local pane_dims = pane:get_dimensions();
local overrides = window:get_config_overrides() or {}
if not window_dims.is_full_screen then
if not overrides.window_padding then
-- not changing anything
return;
end
overrides.window_padding = nil;
else
-- Use only the middle 33%
local third = math.floor(window_dims.pixel_width / 3)
local new_padding = {
left = third,
right = third,
top = 0,
bottom = 0
};
if overrides.window_padding and new_padding.left == overrides.window_padding.left then
-- padding is same, avoid triggering further changes
return
end
overrides.window_padding = new_padding
end
window:set_config_overrides(overrides)
end);
return {
}
```