From 0902e048bed7cfd4a63729051db811b6c889a440 Mon Sep 17 00:00:00 2001 From: Isaac Freund Date: Fri, 8 May 2020 15:23:02 +0200 Subject: [PATCH] Refactor server setup and renderer access --- src/Output.zig | 4 ++++ src/Server.zig | 45 ++++++++++++++++++--------------------- src/render.zig | 58 ++++++++++++++++++++++++-------------------------- 3 files changed, 53 insertions(+), 54 deletions(-) diff --git a/src/Output.zig b/src/Output.zig index a0ee749..cb5cba4 100644 --- a/src/Output.zig +++ b/src/Output.zig @@ -143,6 +143,10 @@ pub fn deinit(self: *Self) void { } } +pub fn getRenderer(self: Self) *c.wlr_renderer { + return c.river_wlr_backend_get_renderer(self.wlr_output.backend); +} + /// Add a new view to the output. arrangeViews() will be called by the view /// when it is mapped. The surface argument must be a c.wlr_xdg_surface or /// c.wlr_xwayland_surface (if xwayland is enabled) diff --git a/src/Server.zig b/src/Server.zig index da980dd..b617b04 100644 --- a/src/Server.zig +++ b/src/Server.zig @@ -35,24 +35,25 @@ allocator: *std.mem.Allocator, wl_display: *c.wl_display, wl_event_loop: *c.wl_event_loop, + wlr_backend: *c.wlr_backend, noop_backend: *c.wlr_backend, -wlr_renderer: *c.wlr_renderer, +listen_new_output: c.wl_listener, wlr_xdg_shell: *c.wlr_xdg_shell, +listen_new_xdg_surface: c.wl_listener, + wlr_layer_shell: *c.wlr_layer_shell_v1, +listen_new_layer_surface: c.wl_listener, + wlr_xwayland: if (build_options.xwayland) *c.wlr_xwayland else void, +listen_new_xwayland_surface: if (build_options.xwayland) c.wl_listener else void, decoration_manager: DecorationManager, input_manager: InputManager, root: Root, config: Config, -listen_new_output: c.wl_listener, -listen_new_xdg_surface: c.wl_listener, -listen_new_layer_surface: c.wl_listener, -listen_new_xwayland_surface: c.wl_listener, - pub fn init(self: *Self, allocator: *std.mem.Allocator) !void { self.allocator = allocator; @@ -81,24 +82,35 @@ pub fn init(self: *Self, allocator: *std.mem.Allocator) !void { // If we don't provide a renderer, autocreate makes a GLES2 renderer for us. // The renderer is responsible for defining the various pixel formats it // supports for shared memory, this configures that for clients. - self.wlr_renderer = c.river_wlr_backend_get_renderer(self.wlr_backend) orelse + const wlr_renderer = c.river_wlr_backend_get_renderer(self.wlr_backend) orelse return error.CantGetWlrRenderer; // TODO: Handle failure after https://github.com/swaywm/wlroots/pull/2080 - c.wlr_renderer_init_wl_display(self.wlr_renderer, self.wl_display); // orelse + c.wlr_renderer_init_wl_display(wlr_renderer, self.wl_display); // orelse // return error.CantInitWlDisplay; + self.listen_new_output.notify = handleNewOutput; + c.wl_signal_add(&self.wlr_backend.events.new_output, &self.listen_new_output); - const wlr_compositor = c.wlr_compositor_create(self.wl_display, self.wlr_renderer) orelse + const wlr_compositor = c.wlr_compositor_create(self.wl_display, wlr_renderer) orelse return error.CantCreateWlrCompositor; + // Set up xdg shell self.wlr_xdg_shell = c.wlr_xdg_shell_create(self.wl_display) orelse return error.CantCreateWlrXdgShell; + self.listen_new_xdg_surface.notify = handleNewXdgSurface; + c.wl_signal_add(&self.wlr_xdg_shell.events.new_surface, &self.listen_new_xdg_surface); + // Set up layer shell self.wlr_layer_shell = c.wlr_layer_shell_v1_create(self.wl_display) orelse return error.CantCreateWlrLayerShell; + self.listen_new_layer_surface.notify = handleNewLayerSurface; + c.wl_signal_add(&self.wlr_layer_shell.events.new_surface, &self.listen_new_layer_surface); + // Set up xwayland if built with suport if (build_options.xwayland) { self.wlr_xwayland = c.wlr_xwayland_create(self.wl_display, wlr_compositor, false) orelse return error.CantCreateWlrXwayland; + self.listen_new_xwayland_surface.notify = handleNewXwaylandSurface; + c.wl_signal_add(&self.wlr_xwayland.events.new_surface, &self.listen_new_xwayland_surface); } try self.decoration_manager.init(self); @@ -114,21 +126,6 @@ pub fn init(self: *Self, allocator: *std.mem.Allocator) !void { return error.CantCreateWlrScreencopyManager; _ = c.wlr_xdg_output_manager_v1_create(self.wl_display, self.root.wlr_output_layout) orelse return error.CantCreateWlrOutputManager; - - // Register listeners for events on our globals - self.listen_new_output.notify = handleNewOutput; - c.wl_signal_add(&self.wlr_backend.events.new_output, &self.listen_new_output); - - self.listen_new_xdg_surface.notify = handleNewXdgSurface; - c.wl_signal_add(&self.wlr_xdg_shell.events.new_surface, &self.listen_new_xdg_surface); - - self.listen_new_layer_surface.notify = handleNewLayerSurface; - c.wl_signal_add(&self.wlr_layer_shell.events.new_surface, &self.listen_new_layer_surface); - - if (build_options.xwayland) { - self.listen_new_xwayland_surface.notify = handleNewXwaylandSurface; - c.wl_signal_add(&self.wlr_xwayland.events.new_surface, &self.listen_new_xwayland_surface); - } } /// Free allocated memory and clean up diff --git a/src/render.zig b/src/render.zig index ac37e42..9f1dc39 100644 --- a/src/render.zig +++ b/src/render.zig @@ -26,8 +26,20 @@ const Server = @import("Server.zig"); const View = @import("View.zig"); const ViewStack = @import("view_stack.zig").ViewStack; +const ViewRenderData = struct { + output: *const Output, + view: *View, + when: *c.timespec, +}; + +const LayerSurfaceRenderData = struct { + output: *const Output, + layer_surface: *LayerSurface, + when: *c.timespec, +}; + pub fn renderOutput(output: *Output) void { - const renderer = output.root.server.wlr_renderer; + const wlr_renderer = output.getRenderer(); var now: c.timespec = undefined; _ = c.clock_gettime(c.CLOCK_MONOTONIC, &now); @@ -41,10 +53,10 @@ pub fn renderOutput(output: *Output) void { var height: c_int = undefined; c.wlr_output_effective_resolution(output.wlr_output, &width, &height); // Begin the renderer (calls glViewport and some other GL sanity checks) - c.wlr_renderer_begin(renderer, width, height); + c.wlr_renderer_begin(wlr_renderer, width, height); const color = [_]f32{ 0.0, 0.16862745, 0.21176471, 1.0 }; - c.wlr_renderer_clear(renderer, &color); + c.wlr_renderer_clear(wlr_renderer, &color); renderLayer(output.*, output.layers[c.ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND], &now); renderLayer(output.*, output.layers[c.ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM], &now); @@ -95,18 +107,11 @@ pub fn renderOutput(output: *Output) void { // Conclude rendering and swap the buffers, showing the final frame // on-screen. - c.wlr_renderer_end(renderer); + c.wlr_renderer_end(wlr_renderer); // TODO: handle failure _ = c.wlr_output_commit(output.wlr_output); } -const LayerSurfaceRenderData = struct { - output: *c.wlr_output, - renderer: *c.wlr_renderer, - layer_surface: *LayerSurface, - when: *c.timespec, -}; - /// Render all surfaces on the passed layer fn renderLayer(output: Output, layer: std.TailQueue(LayerSurface), now: *c.timespec) void { var it = layer.first; @@ -116,8 +121,7 @@ fn renderLayer(output: Output, layer: std.TailQueue(LayerSurface), now: *c.times continue; } var rdata = LayerSurfaceRenderData{ - .output = output.wlr_output, - .renderer = output.root.server.wlr_renderer, + .output = &output, .layer_surface = layer_surface, .when = now, }; @@ -138,6 +142,7 @@ fn renderLayerSurface(_surface: ?*c.wlr_surface, sx: c_int, sy: c_int, data: ?*c const rdata = @ptrCast(*LayerSurfaceRenderData, @alignCast(@alignOf(LayerSurfaceRenderData), data)); const layer_surface = rdata.layer_surface; const output = rdata.output; + const wlr_output = output.wlr_output; // We first obtain a wlr_texture, which is a GPU resource. wlroots // automatically handles negotiating these with the client. The underlying @@ -157,7 +162,7 @@ fn renderLayerSurface(_surface: ?*c.wlr_surface, sx: c_int, sy: c_int, data: ?*c }; // Scale the box to the output's current scaling factor - scaleBox(&box, output.scale); + scaleBox(&box, wlr_output.scale); // wlr_matrix_project_box is a helper which takes a box with a desired // x, y coordinates, width and height, and an output geometry, then @@ -165,24 +170,17 @@ fn renderLayerSurface(_surface: ?*c.wlr_surface, sx: c_int, sy: c_int, data: ?*c // transforms to produce a model-view-projection matrix. var matrix: [9]f32 = undefined; const transform = c.wlr_output_transform_invert(surface.current.transform); - c.wlr_matrix_project_box(&matrix, &box, transform, 0.0, &output.transform_matrix); + c.wlr_matrix_project_box(&matrix, &box, transform, 0.0, &wlr_output.transform_matrix); // This takes our matrix, the texture, and an alpha, and performs the actual // rendering on the GPU. - _ = c.wlr_render_texture_with_matrix(rdata.renderer, texture, &matrix, 1.0); + _ = c.wlr_render_texture_with_matrix(output.getRenderer(), texture, &matrix, 1.0); // This lets the client know that we've displayed that frame and it can // prepare another one now if it likes. c.wlr_surface_send_frame_done(surface, rdata.when); } -const ViewRenderData = struct { - output: *c.wlr_output, - renderer: *c.wlr_renderer, - view: *View, - when: *c.timespec, -}; - fn renderView(output: Output, view: *View, now: *c.timespec) void { // If we have a stashed buffer, we are in the middle of a transaction // and need to render that buffer until the transaction is complete. @@ -209,7 +207,7 @@ fn renderView(output: Output, view: *View, now: *c.timespec) void { // This takes our matrix, the texture, and an alpha, and performs the actual // rendering on the GPU. _ = c.wlr_render_texture_with_matrix( - output.root.server.wlr_renderer, + output.getRenderer(), buffer.texture, &matrix, 1.0, @@ -218,9 +216,8 @@ fn renderView(output: Output, view: *View, now: *c.timespec) void { // Since there is no stashed buffer, we are not in the middle of // a transaction and may simply render each toplevel surface. var rdata = ViewRenderData{ - .output = output.wlr_output, + .output = &output, .view = view, - .renderer = output.root.server.wlr_renderer, .when = now, }; @@ -235,6 +232,7 @@ fn renderSurface(_surface: ?*c.wlr_surface, sx: c_int, sy: c_int, data: ?*c_void const rdata = @ptrCast(*ViewRenderData, @alignCast(@alignOf(ViewRenderData), data)); const view = rdata.view; const output = rdata.output; + const wlr_output = output.wlr_output; // We first obtain a wlr_texture, which is a GPU resource. wlroots // automatically handles negotiating these with the client. The underlying @@ -254,7 +252,7 @@ fn renderSurface(_surface: ?*c.wlr_surface, sx: c_int, sy: c_int, data: ?*c_void }; // Scale the box to the output's current scaling factor - scaleBox(&box, output.scale); + scaleBox(&box, wlr_output.scale); // wlr_matrix_project_box is a helper which takes a box with a desired // x, y coordinates, width and height, and an output geometry, then @@ -262,11 +260,11 @@ fn renderSurface(_surface: ?*c.wlr_surface, sx: c_int, sy: c_int, data: ?*c_void // transforms to produce a model-view-projection matrix. var matrix: [9]f32 = undefined; const transform = c.wlr_output_transform_invert(surface.current.transform); - c.wlr_matrix_project_box(&matrix, &box, transform, 0.0, &output.transform_matrix); + c.wlr_matrix_project_box(&matrix, &box, transform, 0.0, &wlr_output.transform_matrix); // This takes our matrix, the texture, and an alpha, and performs the actual // rendering on the GPU. - _ = c.wlr_render_texture_with_matrix(rdata.renderer, texture, &matrix, 1.0); + _ = c.wlr_render_texture_with_matrix(output.getRenderer(), texture, &matrix, 1.0); // This lets the client know that we've displayed that frame and it can // prepare another one now if it likes. @@ -312,7 +310,7 @@ fn renderRect(output: Output, box: Box, color: [4]f32) void { var wlr_box = box.toWlrBox(); scaleBox(&wlr_box, output.wlr_output.scale); c.wlr_render_rect( - output.root.server.wlr_renderer, + output.getRenderer(), &wlr_box, &color, &output.wlr_output.transform_matrix,