~bl4ckb0ne/kaiju-dev

kaiju: Replace custom render with wlr_scene v1 SUPERSEDED

This patchset introduces kaiju to the wlr_scene API. Let me know if you
want me to broke down into smaller hunks/commits.

Pedro Lucas Porcellis (4):
  render: replace manual render logic with wlr_scene
  server: build wlr_scene graph during initialization
  view: update view to use wlr_scene API
  server: find view from scene node graph

 render.c | 130 +++----------------------------------------------------
 server.c |  44 +++++++++++--------
 server.h |   2 +
 view.c   |  10 ++++-
 view.h   |   1 +
 5 files changed, 44 insertions(+), 143 deletions(-)

-- 
2.35.1
Export patchset (mbox)
How do I use this?

Copy & paste the following snippet into your terminal to import this patchset into git:

curl -s https://lists.sr.ht/~bl4ckb0ne/kaiju-dev/patches/31851/mbox | git am -3
Learn more about email & git

[PATCH kaiju 1/4] render: replace manual render logic with wlr_scene Export this patch

---
 render.c | 130 +++----------------------------------------------------
 1 file changed, 5 insertions(+), 125 deletions(-)

diff --git a/render.c b/render.c
index f868ca1..c6eaca7 100644
--- a/render.c
+++ b/render.c
@@ -20,137 +20,17 @@ struct render_data {
	struct timespec *when;
};

static void
render_surface(struct wlr_surface *surface, int x, int y, void *data)
{
	const struct render_data *rdata = data;
	struct wlr_output *output = rdata->output;

	struct wlr_texture *texture = wlr_surface_get_texture(surface);
	if (texture == NULL)
	{
		return;
	}

	double ox = 0.0, oy = 0.0;
	wlr_output_layout_output_coords(rdata->layout, output, &ox, &oy);

	ox += x + rdata->geometry->x;
	oy += y + rdata->geometry->y;

	struct wlr_box box = {
		.x = (int)(ox * (double)output->scale),
		.y = (int)(oy * (double)output->scale),
		.width = surface->current.width * (int)output->scale,
		.height = surface->current.height * (int)output->scale,
	};

	enum wl_output_transform transform = wlr_output_transform_invert(
			surface->current.transform);

	float matrix[9];
	wlr_matrix_project_box(matrix, &box, transform, 0,
			output->transform_matrix);

	wlr_render_texture_with_matrix(rdata->renderer, texture, matrix, 1);

	wlr_surface_send_frame_done(surface, rdata->when);
}

static void
render_view(struct kaiju_view *view, struct render_data *rdata)
{
	if (!view->mapped) {
		return;
	}

	wlr_xdg_surface_for_each_surface(view->wlr_xdg_surface, render_surface,
			rdata);
}

static void
render_views(struct wl_list *views, struct render_data *rdata)
{
	struct kaiju_view *view = NULL;
	wl_list_for_each_reverse(view, views, link) {
		struct wlr_box box = {
			.x = view->x,
			.y = view->y,
		};
		kaiju_view_get_geometry(view, &box.width, &box.height);
		rdata->geometry = &box;
		render_view(view, rdata);
	}
}

static void
render_layer(struct kaiju_layer *layer, struct render_data *rdata)
{
	if (!layer->mapped) {
		return;
	}

	wlr_layer_surface_v1_for_each_surface(layer->wlr_layer_surface,
			render_surface, rdata);
}

static void
render_layers(struct wl_list *layers, struct render_data *rdata)
{
	struct kaiju_layer *layer = NULL;
	wl_list_for_each(layer, layers, link) {
		rdata->geometry = &layer->geometry;
		render_layer(layer, rdata);
	}
}

void
kaiju_render_frame(struct kaiju_output *output)
{
	struct wlr_output *wlr_output = output->wlr_output;

	if (!wlr_output_attach_render(wlr_output, NULL)) {
		return;
	}
	struct wlr_scene *scene = output->server->scene;

	struct kaiju_server *server = output->server;
	struct wlr_renderer *renderer = server->wlr_renderer;
	struct wlr_scene_output *scene_output = wlr_scene_get_scene_output(
			scene, output->wlr_output);

	int width, height;
	wlr_output_effective_resolution(wlr_output, &width, &height);
	wlr_scene_output_commit(scene_output);

	struct timespec now;
	clock_gettime(CLOCK_MONOTONIC, &now);

	wlr_renderer_begin(renderer, width, height);
	{
		static const float color[4] = {0.22f, 0.24f, 0.33f, 1.0f};
		wlr_renderer_clear(renderer, color);

		struct render_data rdata = {
			.renderer = renderer,
			.output = wlr_output,
			.layout = output->server->wlr_output_layout,
			.when = &now,
		};

		render_layers(&server->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND],
				&rdata);

		render_views(&server->views, &rdata);

		render_layers(&server->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM],
				&rdata);

		render_layers(&server->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP],
				&rdata);

		render_layers(&server->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY],
				&rdata);

		wlr_output_render_software_cursors(wlr_output, NULL);
		wlr_renderer_scissor(renderer, NULL);
	}
	wlr_renderer_end(renderer);
	wlr_output_commit(wlr_output);
	wlr_scene_output_send_frame_done(scene_output, &now);
}
-- 
2.35.1

[PATCH kaiju 2/4] server: build wlr_scene graph during initialization Export this patch

---
 server.c | 15 ++++++++++++++-
 server.h |  2 ++
 2 files changed, 16 insertions(+), 1 deletion(-)

diff --git a/server.c b/server.c
index acaea16..235ff5d 100644
--- a/server.c
+++ b/server.c
@@ -105,10 +105,19 @@ new_xdg_surface_handler(struct wl_listener *listener, void *data)
			events.new_xdg_surface);
	struct wlr_xdg_surface *surface = data;

	if (surface->role != WLR_XDG_SURFACE_ROLE_TOPLEVEL) {
	if (surface->role == WLR_XDG_SURFACE_ROLE_POPUP) {
		struct wlr_xdg_surface *parent =
			wlr_xdg_surface_from_wlr_surface(surface->popup->parent);

		struct wlr_scene_node *parent_node = parent->data;
		surface->data = wlr_scene_xdg_surface_create(parent_node,
				surface);

		return;
	}

	assert(surface->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL);

	wlr_log(WLR_DEBUG, "New xdg surface %s", surface->toplevel->app_id);

	struct kaiju_view *view = kaiju_view_create(server, surface);
@@ -160,6 +169,10 @@ kaiju_server_init(struct kaiju_server *server)

	server->wlr_output_layout = wlr_output_layout_create();

	server->scene = wlr_scene_create();
	wlr_scene_attach_output_layout(server->scene,
			server->wlr_output_layout);

	server->wlr_input_method_manager = wlr_input_method_manager_v2_create(
			server->wl_display);

diff --git a/server.h b/server.h
index 91e20ee..f8e9a4d 100644
--- a/server.h
+++ b/server.h
@@ -9,6 +9,7 @@
#include <wlr/types/wlr_data_device.h>
#include <wlr/types/wlr_output_layout.h>
#include <wlr/types/wlr_xdg_shell.h>
#include <wlr/types/wlr_scene.h>
#include <wlr/types/wlr_layer_shell_v1.h>
#include <wlr/types/wlr_virtual_keyboard_v1.h>
#include <wlr/types/wlr_input_method_v2.h>
@@ -23,6 +24,7 @@ struct kaiju_server {
	struct wl_display *wl_display;
	const char *socket;

	struct wlr_scene *scene;
	struct wlr_backend *wlr_backend;
	struct wlr_renderer *wlr_renderer;
	struct wlr_allocator *wlr_allocator;
-- 
2.35.1

[PATCH kaiju 3/4] view: update view to use wlr_scene API Export this patch

---
 view.c | 10 +++++++++-
 view.h |  1 +
 2 files changed, 10 insertions(+), 1 deletion(-)

diff --git a/view.c b/view.c
index e12fc1f..ca4e074 100644
--- a/view.c
+++ b/view.c
@@ -32,6 +32,8 @@ kaiju_view_focus(struct kaiju_view *view)
	struct kaiju_server *server = view->server;
	struct wlr_keyboard *keyboard = wlr_seat_get_keyboard(seat);

	wlr_scene_node_raise_to_top(view->scene_node);

	/* Move the view to the front */
	wl_list_remove(&view->link);
	wl_list_insert(&server->views, &view->link);
@@ -62,7 +64,6 @@ kaiju_view_position(struct kaiju_view *view)
	struct wlr_box *layout = wlr_output_layout_get_box(
			view->server->wlr_output_layout, NULL);

	//if (view->wlr_xdg_surface->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL) {
	if (!view->wlr_xdg_surface->toplevel->parent) {
		/* The parent view should occupy all the screen space */
		view->x = layout->x;
@@ -78,6 +79,7 @@ kaiju_view_position(struct kaiju_view *view)
		kaiju_view_get_geometry(view, &width, &height);
		view->x = (layout->width - width) / 2;
		view->y = (layout->height - height) / 2;
		wlr_scene_node_set_position(view->scene_node, view->x, view->y);
	}
}

@@ -128,6 +130,12 @@ struct kaiju_view *kaiju_view_create(struct kaiju_server *server,

	view->server = server;
	view->wlr_xdg_surface = surface;
	view->scene_node = wlr_scene_xdg_surface_create(
			&view->server->scene->node,
			view->wlr_xdg_surface);

	view->scene_node->data = view;
	view->wlr_xdg_surface->data = view->scene_node;

	view->events.map.notify = view_map_handler;
	wl_signal_add(&surface->events.map, &view->events.map);
diff --git a/view.h b/view.h
index 5356b1c..b36a934 100644
--- a/view.h
+++ b/view.h
@@ -10,6 +10,7 @@ struct kaiju_server;

struct kaiju_view {
	struct wlr_xdg_surface *wlr_xdg_surface;
	struct wlr_scene_node *scene_node;

	bool mapped;
	int x, y;
-- 
2.35.1

[PATCH kaiju 4/4] server: find view from scene node graph Export this patch

---
 server.c | 29 +++++++++++++----------------
 1 file changed, 13 insertions(+), 16 deletions(-)

diff --git a/server.c b/server.c
index 235ff5d..f66d8b9 100644
--- a/server.c
+++ b/server.c
@@ -10,28 +10,25 @@
#include <wlr/util/log.h>

#include <stdlib.h>
#include <assert.h>

struct kaiju_view *kaiju_server_view_at(struct kaiju_server *server, double lx,
		double ly, struct wlr_surface **surface, double *sx, double *sy)
{
	struct kaiju_view *view = NULL;
	wl_list_for_each(view, &server->views, link) {
		double view_sx = lx - view->x;
		double view_sy = ly - view->y;
		double tmp_sx, tmp_sy;
		struct wlr_surface *tmp = wlr_xdg_surface_surface_at(
				view->wlr_xdg_surface, view_sx, view_sy,
				&tmp_sx, &tmp_sy);

		if (tmp != NULL) {
			*surface = tmp;
			*sx = tmp_sx;
			*sy = tmp_sy;
			return view;
		}
	struct wlr_scene_node *node = wlr_scene_node_at(&server->scene->node,
			lx, ly, sx, sy);

	if (node == NULL || node->type != WLR_SCENE_NODE_SURFACE) {
		return NULL;
	}

	*surface = wlr_scene_surface_from_node(node)->surface;

	while (node != NULL && node->data == NULL) {
		node = node->parent;
	}

	return NULL;
	return node->data;
}

bool
-- 
2.35.1