transactions: save and render subsurface buffers
This commit is contained in:
parent
052c8e1dcb
commit
48ea771310
@ -132,6 +132,7 @@ fn startTransaction(self: *Self) void {
|
|||||||
var view_it = ViewStack(View).iterator(output.views.first, std.math.maxInt(u32));
|
var view_it = ViewStack(View).iterator(output.views.first, std.math.maxInt(u32));
|
||||||
while (view_it.next()) |view_node| {
|
while (view_it.next()) |view_node| {
|
||||||
const view = &view_node.view;
|
const view = &view_node.view;
|
||||||
|
|
||||||
// Clear the serial in case this transaction is interrupting a prior one.
|
// Clear the serial in case this transaction is interrupting a prior one.
|
||||||
view.pending_serial = null;
|
view.pending_serial = null;
|
||||||
|
|
||||||
@ -145,10 +146,10 @@ fn startTransaction(self: *Self) void {
|
|||||||
view.sendFrameDone();
|
view.sendFrameDone();
|
||||||
}
|
}
|
||||||
|
|
||||||
// If there is a saved buffer present, then this transaction is interrupting
|
// If there are saved buffers present, then this transaction is interrupting
|
||||||
// a previous transaction and we should keep the old buffer.
|
// a previous transaction and we should keep the old buffers.
|
||||||
if (view.stashed_buffer == null) {
|
if (view.saved_buffers.items.len == 0) {
|
||||||
view.stashBuffer();
|
view.saveBuffers();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -239,7 +240,7 @@ fn commitTransaction(self: *Self) void {
|
|||||||
view_tags_changed = true;
|
view_tags_changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
view.dropStashedBuffer();
|
view.dropSavedBuffers();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (view_tags_changed) output.sendViewTags();
|
if (view_tags_changed) output.sendViewTags();
|
||||||
|
@ -38,6 +38,11 @@ const Impl = union(enum) {
|
|||||||
xwayland_view: XwaylandView,
|
xwayland_view: XwaylandView,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const SavedBuffer = struct {
|
||||||
|
wlr_buffer: *c.wlr_buffer,
|
||||||
|
box: Box,
|
||||||
|
};
|
||||||
|
|
||||||
/// The implementation of this view
|
/// The implementation of this view
|
||||||
impl: Impl,
|
impl: Impl,
|
||||||
|
|
||||||
@ -66,8 +71,8 @@ pending_tags: ?u32,
|
|||||||
|
|
||||||
pending_serial: ?u32,
|
pending_serial: ?u32,
|
||||||
|
|
||||||
// This is what we render while a transaction is in progress
|
/// These are what we render while a transaction is in progress
|
||||||
stashed_buffer: ?*c.wlr_buffer,
|
saved_buffers: std.ArrayList(SavedBuffer),
|
||||||
|
|
||||||
pub fn init(
|
pub fn init(
|
||||||
self: *Self,
|
self: *Self,
|
||||||
@ -94,7 +99,7 @@ pub fn init(
|
|||||||
|
|
||||||
self.pending_serial = null;
|
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) {
|
if (@TypeOf(surface) == *c.wlr_xdg_surface) {
|
||||||
self.impl = .{ .xdg_toplevel = undefined };
|
self.impl = .{ .xdg_toplevel = undefined };
|
||||||
@ -106,9 +111,8 @@ pub fn init(
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn deinit(self: Self) void {
|
pub fn deinit(self: Self) void {
|
||||||
if (self.stashed_buffer) |buffer| {
|
for (self.saved_buffers.items) |buffer| c.wlr_buffer_unref(buffer.wlr_buffer);
|
||||||
c.wlr_buffer_unref(buffer);
|
self.saved_buffers.deinit();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn needsConfigure(self: Self) bool {
|
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);
|
c.wlr_surface_send_frame_done(self.wlr_surface.?, &now);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn dropStashedBuffer(self: *Self) void {
|
pub fn dropSavedBuffers(self: *Self) void {
|
||||||
// TODO: log debug error
|
for (self.saved_buffers.items) |buffer| c.wlr_buffer_unref(buffer.wlr_buffer);
|
||||||
if (self.stashed_buffer) |buffer| {
|
self.saved_buffers.items.len = 0;
|
||||||
c.wlr_buffer_unref(buffer);
|
|
||||||
self.stashed_buffer = null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn stashBuffer(self: *Self) void {
|
pub fn saveBuffers(self: *Self) void {
|
||||||
// TODO: log debug error if there is already a saved buffer
|
if (self.saved_buffers.items.len > 0) {
|
||||||
if (self.wlr_surface) |wlr_surface| {
|
Log.Error.log("view already has buffers saved, overwriting", .{});
|
||||||
if (c.wlr_surface_has_buffer(wlr_surface)) {
|
self.saved_buffers.items.len = 0;
|
||||||
_ = c.wlr_buffer_ref(wlr_surface.buffer);
|
}
|
||||||
self.stashed_buffer = wlr_surface.buffer;
|
|
||||||
|
self.forEachSurface(saveBuffersIterator, &self.saved_buffers);
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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 {
|
fn renderView(output: Output, view: *View, now: *c.timespec) void {
|
||||||
// If we have a stashed buffer, we are in the middle of a transaction
|
// If we have saved buffers, we are in the middle of a transaction
|
||||||
// and need to render that buffer until the transaction is complete.
|
// and need to render those buffers until the transaction is complete.
|
||||||
if (view.stashed_buffer) |buffer| {
|
if (view.saved_buffers.items.len != 0) {
|
||||||
var box = c.wlr_box{
|
for (view.saved_buffers.items) |saved_buffer| {
|
||||||
.x = view.current_box.x,
|
var box = saved_buffer.box.toWlrBox();
|
||||||
.y = view.current_box.y,
|
box.x += view.current_box.x;
|
||||||
.width = @intCast(c_int, view.current_box.width),
|
box.y += view.current_box.y;
|
||||||
.height = @intCast(c_int, view.current_box.height),
|
|
||||||
};
|
|
||||||
|
|
||||||
// Scale the box to the output's current scaling factor
|
// Scale the box to the output's current scaling factor
|
||||||
scaleBox(&box, output.wlr_output.scale);
|
scaleBox(&box, output.wlr_output.scale);
|
||||||
|
|
||||||
var matrix: [9]f32 = undefined;
|
var matrix: [9]f32 = undefined;
|
||||||
c.wlr_matrix_project_box(
|
c.wlr_matrix_project_box(
|
||||||
&matrix,
|
&matrix,
|
||||||
&box,
|
&box,
|
||||||
.WL_OUTPUT_TRANSFORM_NORMAL,
|
.WL_OUTPUT_TRANSFORM_NORMAL,
|
||||||
0.0,
|
0.0,
|
||||||
&output.wlr_output.transform_matrix,
|
&output.wlr_output.transform_matrix,
|
||||||
);
|
);
|
||||||
|
|
||||||
// This takes our matrix, the texture, and an alpha, and performs the actual
|
// This takes our matrix, the texture, and an alpha, and performs the actual
|
||||||
// rendering on the GPU.
|
// rendering on the GPU.
|
||||||
_ = c.wlr_render_texture_with_matrix(
|
_ = c.wlr_render_texture_with_matrix(
|
||||||
output.getRenderer(),
|
output.getRenderer(),
|
||||||
buffer.texture,
|
saved_buffer.wlr_buffer.texture,
|
||||||
&matrix,
|
&matrix,
|
||||||
1.0,
|
1.0,
|
||||||
);
|
);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// Since there is no stashed buffer, we are not in the middle of
|
// Since there is no stashed buffer, we are not in the middle of
|
||||||
// a transaction and may simply render each toplevel surface.
|
// a transaction and may simply render each toplevel surface.
|
||||||
|
Loading…
Reference in New Issue
Block a user