Verified Commit f2ef2ff0 authored by Tudor Roman's avatar Tudor Roman 👾
Browse files

output: implemented the most basic damage tracking

either renders everything or none at all
parent 7b15613e
Pipeline #245098238 passed with stage
in 2 minutes and 21 seconds
......@@ -316,6 +316,7 @@ void LayerSurface::commit_handler(struct wl_listener* listener, void*)
}
layer_surface->layer = layer_surface->surface->current.layer;
}
server->output_manager->set_dirty();
}
void LayerSurface::destroy_handler(struct wl_listener* listener, void*)
......
......@@ -46,11 +46,12 @@ void register_output(Server& server, Output&& output_)
server.output_manager->outputs.emplace_back(output_);
auto& output = server.output_manager->outputs.back();
output.wlr_output->data = &output;
output.wlr_output_damage = wlr_output_damage_create(output.wlr_output);
register_handlers(server,
&output,
{
{ &output.wlr_output->events.frame, Output::frame_handler },
{ &output.wlr_output_damage->events.frame, Output::frame_handler },
{ &output.wlr_output->events.present, Output::present_handler },
{ &output.wlr_output->events.commit, Output::commit_handler },
{ &output.wlr_output->events.mode, Output::mode_handler },
......@@ -260,37 +261,50 @@ void Output::frame_handler(struct wl_listener* listener, void*)
auto* wlr_output = output->wlr_output;
struct wlr_renderer* renderer = server->renderer;
server->seat.update_swipe(*server);
struct timespec now;
clock_gettime(CLOCK_MONOTONIC, &now);
server->seat.update_swipe(*server);
// make the OpenGL context current
if (!wlr_output_attach_render(wlr_output, nullptr)) {
bool needs_frame;
pixman_region32_t damage;
pixman_region32_init(&damage);
if (!wlr_output_damage_attach_render(output->wlr_output_damage, &needs_frame, &damage)) {
wlr_log(WLR_ERROR, "cannot make damage output current");
return;
}
if (!needs_frame) {
wlr_output_rollback(output->wlr_output);
goto damage_finish;
}
int width, height;
// the effective resolution takes the rotation of outputs in account
wlr_output_effective_resolution(wlr_output, &width, &height);
wlr_renderer_begin(renderer, width, height);
std::array<float, 4> color = { .3, .3, .3, 1. };
wlr_renderer_clear(renderer, color.data());
{
std::array<float, 4> color = { .3, .3, .3, 1. };
wlr_renderer_clear(renderer, color.data());
}
int workspaces_number = 0;
int fullscreen_workspaces_number = 0;
{
int workspaces_number = 0;
int fullscreen_workspaces_number = 0;
for (auto& ws : server->output_manager->workspaces) {
if (ws.output.raw_pointer() == output) {
workspaces_number++;
fullscreen_workspaces_number += static_cast<bool>(ws.fullscreen_view);
for (auto& ws : server->output_manager->workspaces) {
if (ws.output.raw_pointer() == output) {
workspaces_number++;
fullscreen_workspaces_number += static_cast<bool>(ws.fullscreen_view);
}
}
}
if (fullscreen_workspaces_number != workspaces_number - fullscreen_workspaces_number) {
render_layer(*server, server->surface_manager.layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND], *output, renderer, &now);
render_layer(*server, server->surface_manager.layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM], *output, renderer, &now);
if (fullscreen_workspaces_number != workspaces_number - fullscreen_workspaces_number) {
render_layer(*server, server->surface_manager.layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND], *output, renderer, &now);
render_layer(*server, server->surface_manager.layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM], *output, renderer, &now);
}
}
for (auto& ws : server->output_manager->workspaces) {
......@@ -355,6 +369,9 @@ void Output::frame_handler(struct wl_listener* listener, void*)
// swap buffers and show frame
wlr_renderer_end(renderer);
wlr_output_commit(wlr_output);
damage_finish:
pixman_region32_fini(&damage);
}
void Output::present_handler(struct wl_listener* listener, void* data)
......
......@@ -14,6 +14,7 @@ You should have received a copy of the GNU General Public License along with thi
extern "C" {
#include <wayland-server.h>
#include <wlr/types/wlr_output_layout.h>
#include <wlr/types/wlr_output_damage.h>
}
#include <array>
......@@ -30,6 +31,7 @@ extern "C" {
struct Output {
struct wlr_output* wlr_output;
struct wlr_output_damage* wlr_output_damage;
struct wlr_box usable_area;
/// Time of last presentation. Use it to calculate the delta time.
......
......@@ -10,6 +10,7 @@ You should have received a copy of the GNU General Public License along with thi
*/
extern "C" {
#include <wlr/types/wlr_output_layout.h>
#include <wlr/types/wlr_output_damage.h>
#include <wlr/util/log.h>
}
......@@ -124,6 +125,13 @@ Workspace& OutputManager::get_view_workspace(View& view)
return workspaces[view.workspace_id];
}
void OutputManager::set_dirty()
{
for (auto& output : outputs) {
wlr_output_damage_add_whole(output.wlr_output_damage);
}
}
void OutputManager::output_manager_apply_handler([[maybe_unused]] wl_listener* listener, [[maybe_unused]] void* data)
{
}
......
......@@ -54,11 +54,14 @@ struct OutputManager {
Workspace& create_workspace(Server* server);
Workspace& get_view_workspace(View&);
void set_dirty();
static void output_manager_apply_handler(wl_listener* listener, void* data);
static void output_manager_test_handler(wl_listener* listener, void* data);
private:
/**
* \brief Executed when a new output (monitor) is attached.
*
......
......@@ -661,7 +661,7 @@ void Seat::focus(Server& server, Workspace& workspace)
for (auto& column : workspace.columns) {
for (auto& tile : column.mapped_and_normal_tiles()) {
tile.view->move(tile.view->x, tile.view->y + height_offset);
tile.view->move(*server.output_manager, tile.view->x, tile.view->y + height_offset);
animation_tasks.push_back({ tile.view,
tile.view->x,
......
......@@ -82,10 +82,11 @@ void View::cycle_width(int screen_width)
resize(static_cast<int>(screen_width * ratios[i]), geometry.height);
}
void View::move(int x_, int y_)
void View::move(OutputManager& output_manager, int x_, int y_)
{
x = x_;
y = y_;
output_manager.set_dirty();
}
bool View::is_mapped_and_normal()
......
......@@ -132,7 +132,7 @@ public:
virtual void resize(int width, int height);
/// Requests the move to the client. Do not assume that the client is resized afterwards.
virtual void move(int x, int y);
virtual void move(OutputManager& server, int x, int y);
/// Prepares the view before registering to the server by attaching some handlers and doing shell-specific stuff.
virtual void prepare(Server& server) = 0;
......
......@@ -12,8 +12,9 @@ You should have received a copy of the GNU General Public License along with thi
#include "Server.h"
ViewAnimation::ViewAnimation(AnimationSettings settings)
ViewAnimation::ViewAnimation(AnimationSettings settings, OutputManager& output_manager)
: settings { settings }
, output_manager { &output_manager }
{
}
......@@ -66,6 +67,7 @@ int ViewAnimation::timer_callback(void* data)
float multiplier = beziere_blend(completeness);
task.view->move(
*view_animation->output_manager,
task.startx - multiplier * (task.startx - task.targetx),
task.starty - multiplier * (task.starty - task.targety));
......@@ -84,7 +86,7 @@ int ViewAnimation::timer_callback(void* data)
ViewAnimationInstance create_view_animation(Server* server, AnimationSettings settings)
{
auto view_animation = std::make_unique<ViewAnimation>(ViewAnimation { settings });
auto view_animation = std::make_unique<ViewAnimation>(ViewAnimation { settings, *server->output_manager });
view_animation->event_source = wl_event_loop_add_timer(server->event_loop, ViewAnimation::timer_callback, view_animation.get());
wl_event_source_timer_update(view_animation->event_source, settings.ms_per_frame);
......
......@@ -39,7 +39,7 @@ struct AnimationSettings {
};
class ViewAnimation {
ViewAnimation(AnimationSettings);
ViewAnimation(AnimationSettings, OutputManager&);
public:
void enqueue_task(const AnimationTask&);
......@@ -73,6 +73,7 @@ private:
wl_event_source* event_source;
AnimationSettings settings;
NotNullPointer<OutputManager> output_manager;
static int timer_callback(void* data);
friend ViewAnimationInstance create_view_animation(Server* server, AnimationSettings);
};
......
......@@ -33,6 +33,7 @@ void change_view_workspace(Server& server, View& view, Workspace& new_workspace)
if (view.x < output_area.x || view.x >= output_area.x + output_area.width || view.y < output_area.y || view.y >= output_area.y + output_area.height) {
view.move(
*server.output_manager,
output_area.x + output_area.width / 2,
output_area.y + output_area.height / 2);
}
......@@ -76,7 +77,7 @@ void reconfigure_view_position(Server& server, View& view, int x, int y, bool an
scroll_workspace(*(server.output_manager), workspace, RelativeScroll { dx }, animate);
} else {
view.move(x, y);
view.move(*server.output_manager, x, y);
update_view_workspace(server, view);
}
}
......
......@@ -191,8 +191,8 @@ void Workspace::arrange_workspace(OutputManager& output_manager, bool animate)
const struct wlr_box* output_box = output_manager.get_output_box(output.unwrap());
const struct wlr_box& usable_area = output.unwrap().usable_area;
fullscreen_view.and_then([output_box](auto& view) {
view.move(output_box->x - view.geometry.x, output_box->y - view.geometry.y);
fullscreen_view.and_then([output_box, &output_manager](auto& view) {
view.move(output_manager, output_box->x - view.geometry.x, output_box->y - view.geometry.y);
view.resize(output_box->width, output_box->height);
});
......@@ -374,10 +374,10 @@ int Workspace::get_view_wx(View& view)
void Workspace::set_fullscreen_view(OutputManager& output_manager, OptionalRef<View> view)
{
fullscreen_view.and_then([](auto& fview) {
fullscreen_view.and_then([&output_manager](auto& fview) {
fview.set_fullscreen(false);
fview.expansion_state = View::ExpansionState::RECOVERING;
fview.move(fview.saved_state->x, fview.saved_state->y);
fview.move(output_manager, fview.saved_state->x, fview.saved_state->y);
fview.resize(fview.saved_state->width, fview.saved_state->height);
fview.saved_state = std::nullopt;
});
......
......@@ -244,6 +244,7 @@ void XDGView::surface_commit_handler(struct wl_listener* listener, void*)
ws.arrange_workspace(*(server->output_manager));
}
server->output_manager->set_dirty();
}
void XDGView::surface_new_popup_handler(struct wl_listener* listener, void* data)
......
......@@ -74,9 +74,9 @@ void XwaylandView::resize(int width, int height)
xwayland_surface, x, y, width, height);
}
void XwaylandView::move(int x_, int y_)
void XwaylandView::move(OutputManager& output_manager, int x_, int y_)
{
View::move(x_, y_);
View::move(output_manager, x_, y_);
wlr_xwayland_surface_configure(
xwayland_surface, x, y, geometry.width, geometry.height);
......@@ -225,6 +225,7 @@ void XwaylandView::surface_commit_handler(struct wl_listener* listener, void*)
ws.arrange_workspace(*(server->output_manager));
}
server->output_manager->set_dirty();
}
void XwaylandView::surface_request_fullscreen_handler(struct wl_listener* listener, void*)
......@@ -328,8 +329,11 @@ void XwaylandORSurface::surface_request_configure_handler(struct wl_listener* li
void XwaylandORSurface::surface_commit_handler(struct wl_listener* listener, void*)
{
auto* server = get_server(listener);
auto* xwayland_or_surface = get_listener_data<XwaylandORSurface*>(listener);
xwayland_or_surface->lx = xwayland_or_surface->xwayland_surface->x;
xwayland_or_surface->ly = xwayland_or_surface->xwayland_surface->y;
server->output_manager->set_dirty();
}
......@@ -35,7 +35,7 @@ public:
struct wlr_surface* get_surface() final;
bool get_surface_under_coords(double lx, double ly, struct wlr_surface*& surface, double& sx, double& sy) final;
void resize(int width, int height) final;
void move(int x, int y) final;
void move(OutputManager&, int x, int y) final;
void prepare(Server& server) final;
void set_activated(bool activated) final;
void set_fullscreen(bool fullscreen) final;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment