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

Improvements to surface and node handling #2275

Merged
merged 7 commits into from
Mar 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions metadata/workarounds.xml
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@
<option name="enable_input_method_v2" type="bool">
<_short>Enable support for the newer input-method-v2 protocol. Note that the input-method-v1 protocol works better in many cases.</_short>
<default>false</default>
</option>
<option name="enable_opaque_region_damage_optimizations" type="bool">
<_short>Enable certain damage optimizations which are based on a surfaces' opaque regions. In some cases, this optimization might give unexpected results (i.e background app stops updating) even though this is fine according to Wayland's protocol.</_short>
<default>false</default>
</option>
</plugin>
</wayfire>
2 changes: 2 additions & 0 deletions src/api/wayfire/debug.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ enum class logging_category : size_t
LSHELL = 9,
// Input-Method-related events
IM = 10,
// Rendering-related events
RENDER = 11,
TOTAL,
};

Expand Down
2 changes: 1 addition & 1 deletion src/api/wayfire/plugin.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ class plugin_interface_t
using wayfire_plugin_load_func = wf::plugin_interface_t * (*)();

/** The version of Wayfire's API/ABI */
constexpr uint32_t WAYFIRE_API_ABI_VERSION = 2024'03'24'2;
constexpr uint32_t WAYFIRE_API_ABI_VERSION = 2024'03'27;

/**
* Each plugin must also provide a function which returns the Wayfire API/ABI
Expand Down
86 changes: 51 additions & 35 deletions src/api/wayfire/scene.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,41 @@ enum class node_flags : int

using node_flags_bitmask_t = uint64_t;

/**
* A list of bitmask flags which indicate what parts of the node state have
* changed. The information is useful when updating the scenegraph's state
* with wf::scene::update().
*/
namespace update_flag
{
enum update_flag
{
/**
* The list of the node's children changed.
*/
CHILDREN_LIST = (1 << 0),
/**
* The node's enabled or disabled state changed.
*/
ENABLED = (1 << 1),
/**
* The node's input state changed, that is, the result of find_node_at()
* may have changed. Typically, this is triggered when a surface is mapped,
* unmapped or moved.
*/
INPUT_STATE = (1 << 2),
/**
* The node's geometry changed. Changes include not just the bounding box
* of the view, but also things like opaque regions.
*/
GEOMETRY = (1 << 3),
/**
* A keyboard refocus might be necessary (for example, node removed, keyboard input state changed, etc.).
*/
REFOCUS = (1 << 4),
};
}

/**
* Used as a result of an intersection of the scenegraph with the user input.
*/
Expand Down Expand Up @@ -298,6 +333,22 @@ class node_t : public std::enable_shared_from_this<node_t>,
return children;
}

/**
* When a scenegraph change happens, core or the plugin which modifies the scenegraph is supposed to call
* the @scene::update() function defined below, so that the scene graph can be updated properly, render
* instances regenerated, etc.
*
* However, in many cases a full update is not necessary. For example, when subsurfaces are being
* reordered, locally regenerating the render instances within the view render instances is enough.
* For such cases, nodes can override this function and change the information which is propagated for
* the update to their parent nodes. In the above example of subsurface reordering, the subsurface root
* will update all of its render instances manually and not propagate CHILDREN_LIST updates to its parent.
*/
virtual uint32_t optimize_update(uint32_t update_flags)
{
return update_flags;
}

public:
node_t(const node_t&) = delete;
node_t(node_t&&) = delete;
Expand Down Expand Up @@ -421,41 +472,6 @@ enum class layer : size_t
ALL_LAYERS,
};

/**
* A list of bitmask flags which indicate what parts of the node state have
* changed. The information is useful when updating the scenegraph's state
* with wf::scene::update().
*/
namespace update_flag
{
enum update_flag
{
/**
* The list of the node's children changed.
*/
CHILDREN_LIST = (1 << 0),
/**
* The node's enabled or disabled state changed.
*/
ENABLED = (1 << 1),
/**
* The node's input state changed, that is, the result of find_node_at()
* may have changed. Typically, this is triggered when a surface is mapped,
* unmapped or moved.
*/
INPUT_STATE = (1 << 2),
/**
* The node's geometry changed. Changes include not just the bounding box
* of the view, but also things like opaque regions.
*/
GEOMETRY = (1 << 3),
/**
* A keyboard refocus might be necessary (for example, node removed, keyboard input state changed, etc.).
*/
REFOCUS = (1 << 4),
};
}

/**
* A signal that the root node has been updated.
*
Expand Down
12 changes: 12 additions & 0 deletions src/api/wayfire/unstable/translation-node.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,14 @@ namespace wf
{
namespace scene
{
/**
* Emitted on: translation node
* The signal means that the translation node wishes to optimize a scenegraph update, and render instances
* should update their internal state to match.
*/
struct translation_node_regen_instances_signal
{};

/**
* A node which simply applies an offset to its children.
*/
Expand Down Expand Up @@ -34,6 +42,7 @@ class translation_node_t : public wf::scene::floating_inner_node_t
void gen_render_instances(std::vector<scene::render_instance_uptr>& instances,
scene::damage_callback damage, wf::output_t *output) override;
wf::geometry_t get_bounding_box() override;
uint32_t optimize_update(uint32_t flags) override;

protected:
wf::point_t offset = {0, 0};
Expand All @@ -46,6 +55,9 @@ class translation_node_instance_t : public render_instance_t
damage_callback push_damage;
translation_node_t *self;
wf::signal::connection_t<wf::scene::node_damage_signal> on_node_damage;
wf::signal::connection_t<wf::scene::translation_node_regen_instances_signal> on_regen_instances;
wf::output_t *shown_on;
void regen_instances();

public:
translation_node_instance_t(translation_node_t *self,
Expand Down
2 changes: 1 addition & 1 deletion src/api/wayfire/unstable/wlr-subsurface-controller.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ class wlr_subsurface_root_node_t : public wf::scene::translation_node_t
public:
wlr_subsurface_root_node_t(wlr_subsurface *subsurface);
std::string stringify() const override;
void update_offset();
bool update_offset(bool damage = true);

private:
wlr_subsurface *subsurface;
Expand Down
2 changes: 2 additions & 0 deletions src/api/wayfire/unstable/wlr-surface-controller.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ class wlr_surface_controller_t
wlr_surface_controller_t(wlr_surface *surface, scene::floating_inner_ptr root_node);
~wlr_surface_controller_t();

void update_subsurface_order_and_position();

scene::floating_inner_ptr root;
wlr_surface *surface;

Expand Down
10 changes: 10 additions & 0 deletions src/api/wayfire/unstable/wlr-surface-node.hpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#pragma once

#include "wayfire/geometry.hpp"
#include "wayfire/signal-definitions.hpp"
#include "wayfire/util.hpp"
#include "wayfire/view-transform.hpp"
#include <wayfire/scene.hpp>
Expand Down Expand Up @@ -72,8 +73,17 @@ class wlr_surface_node_t : public node_t, public zero_copy_texturable_node_t
std::unique_ptr<pointer_interaction_t> ptr_interaction;
std::unique_ptr<touch_interaction_t> tch_interaction;
wlr_surface *surface;

std::map<wf::output_t*, int> visibility;
std::map<wf::output_t*, int> pending_visibility_delta;
wf::signal::connection_t<wf::output_removed_signal> on_output_remove;

class wlr_surface_render_instance_t;
void handle_enter(wf::output_t *output);
void handle_leave(wf::output_t *output);
void update_pending_outputs();
wf::wl_idle_call idle_update_outputs;

wf::wl_listener_wrapper on_surface_destroyed;
wf::wl_listener_wrapper on_surface_commit;

Expand Down
4 changes: 1 addition & 3 deletions src/core/scene.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,15 @@
#include <wayfire/scene.hpp>
#include <wayfire/view.hpp>
#include <wayfire/output.hpp>
#include <set>
#include <algorithm>

#include "scene-priv.hpp"
#include "wayfire/debug.hpp"
#include "wayfire/geometry.hpp"
#include "wayfire/opengl.hpp"
#include "wayfire/region.hpp"
#include "wayfire/scene-input.hpp"
#include "wayfire/scene-render.hpp"
#include "wayfire/signal-provider.hpp"
#include "wayfire/util.hpp"
#include <wayfire/core.hpp>

namespace wf
Expand Down Expand Up @@ -503,6 +500,7 @@ void update(node_ptr changed_node, uint32_t flags)

if (changed_node->parent())
{
flags = changed_node->parent()->optimize_update(flags);
update(changed_node->parent()->shared_from_this(), flags);
}
}
Expand Down
4 changes: 4 additions & 0 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,10 @@ void parse_extended_debugging(const std::vector<std::string>& categories)
{
LOGD("Enabling extended debugging for input method events");
wf::log::enabled_categories.set((size_t)wf::log::logging_category::IM, 1);
} else if (cat == "render")
{
LOGD("Enabling extended debugging for render events");
wf::log::enabled_categories.set((size_t)wf::log::logging_category::RENDER, 1);
} else
{
LOGE("Unrecognized debugging category \"", cat, "\"");
Expand Down
14 changes: 10 additions & 4 deletions src/output/render-manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ struct swapchain_damage_manager_t
output_t *wo;

bool pending_gamma_lut = false;
wf::wl_idle_call idle_recompute_visibility;

void update_scenegraph(uint32_t update_mask)
{
Expand All @@ -51,6 +52,7 @@ struct swapchain_damage_manager_t

if (update_mask & recompute_instances_on)
{
LOGC(RENDER, "Output ", wo->to_string(), ": regenerating instances.");
auto root = wf::get_core().scene();
scene::damage_callback push_damage = [=] (wf::region_t region)
{
Expand All @@ -66,11 +68,15 @@ struct swapchain_damage_manager_t

if (update_mask & recompute_visibility_on)
{
wf::region_t region = this->wo->get_layout_geometry();
for (auto& inst : render_instances)
idle_recompute_visibility.run_once([=] ()
{
inst->compute_visibility(wo, region);
}
LOGC(RENDER, "Output ", wo->to_string(), ": recomputing visibility.");
wf::region_t region = this->wo->get_layout_geometry();
for (auto& inst : render_instances)
{
inst->compute_visibility(wo, region);
}
});
}
}

Expand Down
28 changes: 28 additions & 0 deletions src/view/translation-node.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,19 +46,47 @@ void wf::scene::translation_node_t::set_offset(wf::point_t offset)
this->offset = offset;
}

uint32_t wf::scene::translation_node_t::optimize_update(uint32_t flags)
{
if (flags & (update_flag::CHILDREN_LIST | update_flag::ENABLED))
{
// If we update the list of children, there is no need to notify the whole scenegraph.
// Instead, we can do a local update, and only update visibility.
flags &= ~update_flag::CHILDREN_LIST;
flags &= ~update_flag::ENABLED;
flags |= update_flag::GEOMETRY | update_flag::INPUT_STATE;
translation_node_regen_instances_signal data;
emit(&data);
}

return flags;
}

// ----------------------------------------- Render instance -------------------------------------------------
wf::scene::translation_node_instance_t::translation_node_instance_t(
translation_node_t *self, damage_callback push_damage, wf::output_t *shown_on)
{
this->self = self;
this->push_damage = push_damage;
this->shown_on = shown_on;

on_node_damage = [=] (wf::scene::node_damage_signal *data)
{
push_damage(data->region);
};
self->connect(&on_node_damage);

on_regen_instances = [=] (auto)
{
regen_instances();
};
self->connect(&on_regen_instances);
regen_instances();
}

void wf::scene::translation_node_instance_t::regen_instances()
{
children.clear();
auto push_damage_child = [=] (wf::region_t child_damage)
{
child_damage += self->get_offset();
Expand Down
4 changes: 0 additions & 4 deletions src/view/view-impl.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#include "wayfire/core.hpp"
#include "../core/core-impl.hpp"
#include "view-impl.hpp"
#include "wayfire/scene-input.hpp"
#include "wayfire/scene-render.hpp"
Expand All @@ -8,15 +7,12 @@
#include "wayfire/unstable/wlr-surface-controller.hpp"
#include "wayfire/unstable/wlr-surface-node.hpp"
#include "wayfire/view.hpp"
#include "wayfire/workspace-set.hpp"
#include "wayfire/output-layout.hpp"
#include <memory>
#include <wayfire/util/log.hpp>
#include <wayfire/view-helpers.hpp>
#include <wayfire/scene-operations.hpp>

#include "xdg-shell.hpp"

void wf::view_implementation::emit_view_map_signal(wayfire_view view, bool has_position)
{
wf::view_mapped_signal data;
Expand Down
15 changes: 9 additions & 6 deletions src/view/wlr-subsurface-controller.cpp
Original file line number Diff line number Diff line change
@@ -1,14 +1,10 @@
#include "view/view-impl.hpp"
#include "wayfire/geometry.hpp"
#include "wayfire/scene-operations.hpp"
#include "wayfire/scene.hpp"
#include "wayfire/signal-definitions.hpp"
#include "wayfire/unstable/translation-node.hpp"
#include "wayfire/unstable/wlr-subsurface-controller.hpp"
#include "wayfire/unstable/wlr-surface-node.hpp"
#include <memory>
#include <wayfire/debug.hpp>
#include <cassert>

wf::wlr_subsurface_controller_t::wlr_subsurface_controller_t(wlr_subsurface *sub)
{
Expand Down Expand Up @@ -81,13 +77,20 @@ std::string wf::wlr_subsurface_root_node_t::stringify() const
return "subsurface root node";
}

void wf::wlr_subsurface_root_node_t::update_offset()
bool wf::wlr_subsurface_root_node_t::update_offset(bool apply_damage)
{
wf::point_t offset = {subsurface->current.x, subsurface->current.y};
if (offset != get_offset())
const bool changed = offset != get_offset();

if (changed && apply_damage)
{
scene::damage_node(this, get_bounding_box());
set_offset(offset);
scene::damage_node(this, get_bounding_box());
} else if (changed)
{
set_offset(offset);
}

return changed;
}
Loading
Loading