aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--river/Root.zig11
-rw-r--r--river/View.zig60
-rw-r--r--river/render.zig59
3 files changed, 78 insertions, 52 deletions
diff --git a/river/Root.zig b/river/Root.zig
index f032665..601b415 100644
--- a/river/Root.zig
+++ b/river/Root.zig
@@ -132,6 +132,7 @@ fn startTransaction(self: *Self) void {
var view_it = ViewStack(View).iterator(output.views.first, std.math.maxInt(u32));
while (view_it.next()) |view_node| {
const view = &view_node.view;
+
// Clear the serial in case this transaction is interrupting a prior one.
view.pending_serial = null;
@@ -145,10 +146,10 @@ fn startTransaction(self: *Self) void {
view.sendFrameDone();
}
- // If there is a saved buffer present, then this transaction is interrupting
- // a previous transaction and we should keep the old buffer.
- if (view.stashed_buffer == null) {
- view.stashBuffer();
+ // If there are saved buffers present, then this transaction is interrupting
+ // a previous transaction and we should keep the old buffers.
+ if (view.saved_buffers.items.len == 0) {
+ view.saveBuffers();
}
}
}
@@ -239,7 +240,7 @@ fn commitTransaction(self: *Self) void {
view_tags_changed = true;
}
- view.dropStashedBuffer();
+ view.dropSavedBuffers();
}
if (view_tags_changed) output.sendViewTags();
diff --git a/river/View.zig b/river/View.zig
index cc07252..608a7fb 100644
--- a/river/View.zig
+++ b/river/View.zig
@@ -38,6 +38,11 @@ const Impl = union(enum) {
xwayland_view: XwaylandView,
};
+const SavedBuffer = struct {
+ wlr_buffer: *c.wlr_buffer,
+ box: Box,
+};
+
/// The implementation of this view
impl: Impl,
@@ -66,8 +71,8 @@ pending_tags: ?u32,
pending_serial: ?u32,
-// This is what we render while a transaction is in progress
-stashed_buffer: ?*c.wlr_buffer,
+/// These are what we render while a transaction is in progress
+saved_buffers: std.ArrayList(SavedBuffer),
pub fn init(
self: *Self,
@@ -94,7 +99,7 @@ pub fn init(
self.pending_serial = null;
- self.stashed_buffer = null;
+ self.saved_buffers = std.ArrayList(SavedBuffer).init(output.root.server.allocator);
if (@TypeOf(surface) == *c.wlr_xdg_surface) {
self.impl = .{ .xdg_toplevel = undefined };
@@ -106,9 +111,8 @@ pub fn init(
}
pub fn deinit(self: Self) void {
- if (self.stashed_buffer) |buffer| {
- c.wlr_buffer_unref(buffer);
- }
+ for (self.saved_buffers.items) |buffer| c.wlr_buffer_unref(buffer.wlr_buffer);
+ self.saved_buffers.deinit();
}
pub fn needsConfigure(self: Self) bool {
@@ -135,20 +139,42 @@ pub fn sendFrameDone(self: Self) void {
c.wlr_surface_send_frame_done(self.wlr_surface.?, &now);
}
-pub fn dropStashedBuffer(self: *Self) void {
- // TODO: log debug error
- if (self.stashed_buffer) |buffer| {
- c.wlr_buffer_unref(buffer);
- self.stashed_buffer = null;
+pub fn dropSavedBuffers(self: *Self) void {
+ for (self.saved_buffers.items) |buffer| c.wlr_buffer_unref(buffer.wlr_buffer);
+ self.saved_buffers.items.len = 0;
+}
+
+pub fn saveBuffers(self: *Self) void {
+ if (self.saved_buffers.items.len > 0) {
+ Log.Error.log("view already has buffers saved, overwriting", .{});
+ self.saved_buffers.items.len = 0;
}
+
+ self.forEachSurface(saveBuffersIterator, &self.saved_buffers);
}
-pub fn stashBuffer(self: *Self) void {
- // TODO: log debug error if there is already a saved buffer
- if (self.wlr_surface) |wlr_surface| {
- if (c.wlr_surface_has_buffer(wlr_surface)) {
- _ = c.wlr_buffer_ref(wlr_surface.buffer);
- self.stashed_buffer = wlr_surface.buffer;
+fn saveBuffersIterator(
+ wlr_surface: ?*c.wlr_surface,
+ surface_x: c_int,
+ surface_y: c_int,
+ data: ?*c_void,
+) callconv(.C) void {
+ const saved_buffers = @ptrCast(
+ *std.ArrayList(SavedBuffer),
+ @alignCast(@alignOf(*std.ArrayList(SavedBuffer)), data),
+ );
+ if (wlr_surface) |surface| {
+ if (c.wlr_surface_has_buffer(surface)) {
+ saved_buffers.append(.{
+ .wlr_buffer = surface.buffer,
+ .box = Box{
+ .x = surface_x,
+ .y = surface_y,
+ .width = @intCast(u32, surface.current.width),
+ .height = @intCast(u32, surface.current.height),
+ },
+ }) catch return;
+ _ = c.wlr_buffer_ref(surface.buffer);
}
}
}
diff --git a/river/render.zig b/river/render.zig
index a7055ef..9ba3631 100644
--- a/river/render.zig
+++ b/river/render.zig
@@ -136,36 +136,35 @@ fn renderLayer(output: Output, layer: std.TailQueue(LayerSurface), now: *c.times
}
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.
- if (view.stashed_buffer) |buffer| {
- var box = c.wlr_box{
- .x = view.current_box.x,
- .y = view.current_box.y,
- .width = @intCast(c_int, view.current_box.width),
- .height = @intCast(c_int, view.current_box.height),
- };
-
- // Scale the box to the output's current scaling factor
- scaleBox(&box, output.wlr_output.scale);
-
- var matrix: [9]f32 = undefined;
- c.wlr_matrix_project_box(
- &matrix,
- &box,
- .WL_OUTPUT_TRANSFORM_NORMAL,
- 0.0,
- &output.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(
- output.getRenderer(),
- buffer.texture,
- &matrix,
- 1.0,
- );
+ // If we have saved buffers, we are in the middle of a transaction
+ // and need to render those buffers until the transaction is complete.
+ if (view.saved_buffers.items.len != 0) {
+ for (view.saved_buffers.items) |saved_buffer| {
+ var box = saved_buffer.box.toWlrBox();
+ box.x += view.current_box.x;
+ box.y += view.current_box.y;
+
+ // Scale the box to the output's current scaling factor
+ scaleBox(&box, output.wlr_output.scale);
+
+ var matrix: [9]f32 = undefined;
+ c.wlr_matrix_project_box(
+ &matrix,
+ &box,
+ .WL_OUTPUT_TRANSFORM_NORMAL,
+ 0.0,
+ &output.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(
+ output.getRenderer(),
+ saved_buffer.wlr_buffer.texture,
+ &matrix,
+ 1.0,
+ );
+ }
} else {
// Since there is no stashed buffer, we are not in the middle of
// a transaction and may simply render each toplevel surface.