transactions: save transform, refactor rendering
This commit is contained in:
parent
48ea771310
commit
ddc7da0f16
2 changed files with 44 additions and 55 deletions
|
@ -41,6 +41,7 @@ const Impl = union(enum) {
|
||||||
const SavedBuffer = struct {
|
const SavedBuffer = struct {
|
||||||
wlr_buffer: *c.wlr_buffer,
|
wlr_buffer: *c.wlr_buffer,
|
||||||
box: Box,
|
box: Box,
|
||||||
|
transform: c.wl_output_transform,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// The implementation of this view
|
/// The implementation of this view
|
||||||
|
@ -173,6 +174,7 @@ fn saveBuffersIterator(
|
||||||
.width = @intCast(u32, surface.current.width),
|
.width = @intCast(u32, surface.current.width),
|
||||||
.height = @intCast(u32, surface.current.height),
|
.height = @intCast(u32, surface.current.height),
|
||||||
},
|
},
|
||||||
|
.transform = surface.current.transform,
|
||||||
}) catch return;
|
}) catch return;
|
||||||
_ = c.wlr_buffer_ref(surface.buffer);
|
_ = c.wlr_buffer_ref(surface.buffer);
|
||||||
}
|
}
|
||||||
|
|
|
@ -129,7 +129,7 @@ fn renderLayer(output: Output, layer: std.TailQueue(LayerSurface), now: *c.times
|
||||||
};
|
};
|
||||||
c.wlr_layer_surface_v1_for_each_surface(
|
c.wlr_layer_surface_v1_for_each_surface(
|
||||||
layer_surface.wlr_layer_surface,
|
layer_surface.wlr_layer_surface,
|
||||||
renderSurface,
|
renderSurfaceIterator,
|
||||||
&rdata,
|
&rdata,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -139,32 +139,18 @@ fn renderView(output: Output, view: *View, now: *c.timespec) void {
|
||||||
// If we have saved buffers, 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 those buffers until the transaction is complete.
|
// and need to render those buffers until the transaction is complete.
|
||||||
if (view.saved_buffers.items.len != 0) {
|
if (view.saved_buffers.items.len != 0) {
|
||||||
for (view.saved_buffers.items) |saved_buffer| {
|
for (view.saved_buffers.items) |saved_buffer|
|
||||||
var box = saved_buffer.box.toWlrBox();
|
renderTexture(
|
||||||
box.x += view.current_box.x;
|
output,
|
||||||
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,
|
saved_buffer.wlr_buffer.texture,
|
||||||
&matrix,
|
.{
|
||||||
1.0,
|
.x = saved_buffer.box.x + view.current_box.x,
|
||||||
|
.y = saved_buffer.box.y + view.current_box.y,
|
||||||
|
.width = @intCast(c_int, saved_buffer.box.width),
|
||||||
|
.height = @intCast(c_int, saved_buffer.box.height),
|
||||||
|
},
|
||||||
|
saved_buffer.transform,
|
||||||
);
|
);
|
||||||
}
|
|
||||||
} 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.
|
||||||
|
@ -175,7 +161,7 @@ fn renderView(output: Output, view: *View, now: *c.timespec) void {
|
||||||
.when = now,
|
.when = now,
|
||||||
};
|
};
|
||||||
|
|
||||||
view.forEachSurface(renderSurface, &rdata);
|
view.forEachSurface(renderSurfaceIterator, &rdata);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -197,58 +183,59 @@ fn renderXwaylandUnmanaged(output: Output, now: *c.timespec) void {
|
||||||
.output_y = wlr_xwayland_surface.y - output_box.y,
|
.output_y = wlr_xwayland_surface.y - output_box.y,
|
||||||
.when = now,
|
.when = now,
|
||||||
};
|
};
|
||||||
c.wlr_surface_for_each_surface(wlr_xwayland_surface.surface, renderSurface, &rdata);
|
c.wlr_surface_for_each_surface(wlr_xwayland_surface.surface, renderSurfaceIterator, &rdata);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This function is passed to wlroots to render each surface during iteration
|
/// This function is passed to wlroots to render each surface during iteration
|
||||||
fn renderSurface(
|
fn renderSurfaceIterator(
|
||||||
_surface: ?*c.wlr_surface,
|
surface: ?*c.wlr_surface,
|
||||||
surface_x: c_int,
|
surface_x: c_int,
|
||||||
surface_y: c_int,
|
surface_y: c_int,
|
||||||
data: ?*c_void,
|
data: ?*c_void,
|
||||||
) callconv(.C) void {
|
) callconv(.C) void {
|
||||||
// wlroots says this will never be null
|
|
||||||
const surface = _surface.?;
|
|
||||||
const rdata = @ptrCast(*SurfaceRenderData, @alignCast(@alignOf(SurfaceRenderData), data));
|
const rdata = @ptrCast(*SurfaceRenderData, @alignCast(@alignOf(SurfaceRenderData), data));
|
||||||
const output = rdata.output;
|
|
||||||
const wlr_output = output.wlr_output;
|
|
||||||
|
|
||||||
// We first obtain a wlr_texture, which is a GPU resource. wlroots
|
renderTexture(
|
||||||
// automatically handles negotiating these with the client. The underlying
|
rdata.output.*,
|
||||||
// resource could be an opaque handle passed from the client, or the client
|
c.wlr_surface_get_texture(surface),
|
||||||
// could have sent a pixel buffer which we copied to the GPU, or a few other
|
.{
|
||||||
// means. You don't have to worry about this, wlroots takes care of it.
|
.x = rdata.output_x + surface_x,
|
||||||
const texture = c.wlr_surface_get_texture(surface);
|
.y = rdata.output_y + surface_y,
|
||||||
if (texture == null) {
|
.width = surface.?.current.width,
|
||||||
return;
|
.height = surface.?.current.height,
|
||||||
}
|
},
|
||||||
|
surface.?.current.transform,
|
||||||
|
);
|
||||||
|
|
||||||
var box = c.wlr_box{
|
c.wlr_surface_send_frame_done(surface, rdata.when);
|
||||||
.x = rdata.output_x + surface_x,
|
}
|
||||||
.y = rdata.output_y + surface_y,
|
|
||||||
.width = surface.current.width,
|
/// Render the given texture at the given box, taking the scale and transform
|
||||||
.height = surface.current.height,
|
/// of the output into account.
|
||||||
};
|
fn renderTexture(
|
||||||
|
output: Output,
|
||||||
|
wlr_texture: ?*c.wlr_texture,
|
||||||
|
wlr_box: c.wlr_box,
|
||||||
|
transform: c.wl_output_transform,
|
||||||
|
) void {
|
||||||
|
const texture = wlr_texture orelse return;
|
||||||
|
var box = wlr_box;
|
||||||
|
|
||||||
// Scale the box to the output's current scaling factor
|
// Scale the box to the output's current scaling factor
|
||||||
scaleBox(&box, wlr_output.scale);
|
scaleBox(&box, output.wlr_output.scale);
|
||||||
|
|
||||||
// wlr_matrix_project_box is a helper which takes a box with a desired
|
// 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
|
// x, y coordinates, width and height, and an output geometry, then
|
||||||
// prepares an orthographic projection and multiplies the necessary
|
// prepares an orthographic projection and multiplies the necessary
|
||||||
// transforms to produce a model-view-projection matrix.
|
// transforms to produce a model-view-projection matrix.
|
||||||
var matrix: [9]f32 = undefined;
|
var matrix: [9]f32 = undefined;
|
||||||
const transform = c.wlr_output_transform_invert(surface.current.transform);
|
const inverted = c.wlr_output_transform_invert(transform);
|
||||||
c.wlr_matrix_project_box(&matrix, &box, transform, 0.0, &wlr_output.transform_matrix);
|
c.wlr_matrix_project_box(&matrix, &box, inverted, 0.0, &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(output.getRenderer(), 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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn renderBorders(output: Output, view: *View, now: *c.timespec) void {
|
fn renderBorders(output: Output, view: *View, now: *c.timespec) void {
|
||||||
|
|
Loading…
Reference in a new issue