mirror of
https://github.com/kovidgoyal/kitty.git
synced 2026-10-21 04:32:05 +00:00
Custom shaders: Redraw static effects only on demand
This commit is contained in:
parent
cf33820973
commit
7b41e33399
5 changed files with 18 additions and 6 deletions
|
|
@ -205,7 +205,8 @@ Detailed list of changes
|
|||
- Support for :doc:`/custom-shaders` for adding various graphical effects (:iss:`10344`)
|
||||
|
||||
- Custom shaders: Allow tinting inactive windows toward a configurable color,
|
||||
preserving the tab bar and active window padding.
|
||||
preserving the tab bar and active window padding. Support static effects
|
||||
without periodic redraws.
|
||||
|
||||
- Various throughput performance improvements for a 15-35% real world improvement depending on workload
|
||||
|
||||
|
|
|
|||
|
|
@ -84,6 +84,7 @@ following as :file:`shaders/dim-gray.pipeline` in your kitty config directory an
|
|||
set ``custom_shaders dim-gray`` and ``inactive_text_alpha 1`` in :file:`kitty.conf`::
|
||||
|
||||
startgroup
|
||||
animation_step 0
|
||||
var float HIGHLIGHT_INTENSITY = 0
|
||||
var float BORDER_WIDTH = 0
|
||||
var float INACTIVE_DIM = 0.74
|
||||
|
|
@ -100,7 +101,8 @@ sRGB ``#808080``. The default target is black, preserving the existing dimming
|
|||
effect. The two optional flags preserve the tab bar and include the active
|
||||
window's padding in its unchanged area. Explicit cell backgrounds and images
|
||||
are blended together with text, while transparency and colors reported to
|
||||
terminal applications are preserved.
|
||||
terminal applications are preserved. ``animation_step 0`` makes this static
|
||||
effect redraw only when content or shader events change.
|
||||
|
||||
|
||||
Anatomy of a custom shader
|
||||
|
|
@ -269,7 +271,9 @@ Directives inside a group:
|
|||
How many milliseconds between animation frames. Lower values produce
|
||||
smoother animation at the cost of more GPU draws. Defaults to ``50`` ms
|
||||
(20 fps). The value is clamped to be no smaller than
|
||||
:opt:`repaint_delay`.
|
||||
:opt:`repaint_delay`. Set this to ``0`` for static effects that should
|
||||
redraw only when content or shader events change, without periodic frames.
|
||||
Animation stop events and duration limits still apply.
|
||||
|
||||
``attach``
|
||||
Mark this group as *attached* to the preceding group. An attached group
|
||||
|
|
|
|||
|
|
@ -957,13 +957,18 @@ prepare_to_render_os_window(
|
|||
events |= (1u << SHADER_ANIM_EVENT_TAB_CHANGE) | (1u << SHADER_ANIM_EVENT_WINDOW_FOCUS_IN) | (1u << SHADER_ANIM_EVENT_WINDOW_FOCUS_OUT);
|
||||
if (*active_window_id && *active_window_id != os_window->last_active_window_id)
|
||||
events |= (1u << SHADER_ANIM_EVENT_WINDOW_FOCUS_IN) | (1u << SHADER_ANIM_EVENT_WINDOW_FOCUS_OUT);
|
||||
const bool was_active = os_window->has_active_custom_shaders;
|
||||
const bool was_animating = os_window->shader_anim_min_step < MONOTONIC_T_MAX;
|
||||
const bool animation_ended = now >= os_window->shader_anim_next_end_at;
|
||||
monotonic_t min_step = update_custom_shader_animations(events, now, os_window);
|
||||
os_window->shader_anim_event_registry = 0;
|
||||
if (os_window->has_active_custom_shaders) {
|
||||
os_window->needs_layers = true;
|
||||
needs_render = true;
|
||||
if (events || min_step < MONOTONIC_T_MAX) needs_render = true;
|
||||
}
|
||||
if (was_active != os_window->has_active_custom_shaders || was_animating || animation_ended) needs_render = true;
|
||||
if (min_step < MONOTONIC_T_MAX) set_maximum_wait(min_step);
|
||||
if (os_window->shader_anim_next_end_at < MONOTONIC_T_MAX) set_maximum_wait(os_window->shader_anim_next_end_at - now);
|
||||
}
|
||||
return needs_render || was_previously_rendered_with_layers != os_window->needs_layers;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2998,7 +2998,7 @@ transfer_pipeline_to_struct(PyObject *pg, CustomShaderPipeline *p) {
|
|||
|
||||
PyObject *astep = PyDict_GetItemString(g, "animation_step");
|
||||
cg->animation_step = (astep && PyLong_Check(astep)) ? (monotonic_t)PyLong_AsLong(astep) : ANIMATION_SAMPLE_WAIT;
|
||||
cg->animation_step = MAX(cg->animation_step, OPT(repaint_delay));
|
||||
cg->animation_step = cg->animation_step == 0 ? MONOTONIC_T_MAX : MAX(cg->animation_step, OPT(repaint_delay));
|
||||
|
||||
PyObject *ae_events = PyDict_GetItemString(g, "animation_end_events");
|
||||
if (is_seq(ae_events)) cg->animation_end_events = parse_anim_event_sequence(ae_events);
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ class TestSlang(BaseTest):
|
|||
pipeline = parse_pipeline_definition(
|
||||
"""
|
||||
startgroup
|
||||
animation_step 0
|
||||
var float HIGHLIGHT_INTENSITY = 0
|
||||
var float BORDER_WIDTH = 0
|
||||
var float INACTIVE_DIM = 0.74
|
||||
|
|
@ -54,11 +55,12 @@ class TestSlang(BaseTest):
|
|||
with tempfile.TemporaryDirectory() as cache_dir:
|
||||
clear_caches()
|
||||
try:
|
||||
vertex, fragment, _ = build_custom_shader_pipeline_glsl(pipeline, cache_dir=cache_dir)
|
||||
vertex, fragment, metadata = build_custom_shader_pipeline_glsl(pipeline, cache_dir=cache_dir)
|
||||
finally:
|
||||
clear_caches()
|
||||
self.assertTrue(vertex)
|
||||
self.assertTrue(fragment)
|
||||
self.ae(metadata['pipeline']['groups'][0]['animation_step'], 0)
|
||||
|
||||
def test_slang_parser(self):
|
||||
def check(src: str, expected: SlangFile) -> None:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue