Mark reused buffers as busy before returning from nextBuffer (before, they only got marked busy on init). Re-attach wl_buffer listener after re-initializing a buffer. This lets the re-inited buffer still get a released event. Combine scale and translate matrices with multiply instead of overwriting Use appendAssumeCapacity for pixel conversion loop (since we already initialized the list with the correct size).
60 lines
2.3 KiB
Zig
60 lines
2.3 KiB
Zig
// SPDX-FileCopyrightText: 2026 Ben Buhse <me@benbuhse.email>
|
|
//
|
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
const WallpaperImage = @This();
|
|
|
|
image: *pixman.Image,
|
|
pixels: std.ArrayList(u32),
|
|
|
|
// TODO: Make image_path nullable, if null, do a single color with a single_pixel_buffer instead(?)
|
|
pub fn create(image_path: []const u8) !*WallpaperImage {
|
|
var wallpaper_image = try utils.allocator.create(WallpaperImage);
|
|
errdefer utils.allocator.destroy(wallpaper_image);
|
|
|
|
var read_buf: [zigimg.io.DEFAULT_BUFFER_SIZE]u8 = undefined;
|
|
var image = try zigimg.Image.fromFilePath(utils.allocator, image_path, &read_buf);
|
|
defer image.deinit(utils.allocator);
|
|
|
|
// We don't want to deal with all the possible formats,
|
|
// so let's just convert to one we can use with pixman.
|
|
if (image.pixelFormat() != .rgba32) {
|
|
try image.convert(utils.allocator, .rgba32);
|
|
}
|
|
|
|
log.debug("image loaded ({}x{})", .{ image.width, image.height });
|
|
|
|
const pixels = image.pixels.rgba32;
|
|
// We have to manually convert to argb --
|
|
// It's only guaranteed that Wayland compositors will have xrgb and argb support but zigimg doesn't have either of those.
|
|
wallpaper_image.pixels = try std.ArrayList(u32).initCapacity(utils.allocator, pixels.len);
|
|
errdefer wallpaper_image.pixels.deinit(utils.allocator);
|
|
for (0..pixels.len) |i| {
|
|
const a: u32 = @intCast(pixels[i].a);
|
|
const r: u32 = @intCast(pixels[i].r);
|
|
const g: u32 = @intCast(pixels[i].g);
|
|
const b: u32 = @intCast(pixels[i].b);
|
|
const new_val: u32 = (a << 24) + (r << 16) + (g << 8) + b;
|
|
wallpaper_image.pixels.appendAssumeCapacity(new_val);
|
|
}
|
|
|
|
wallpaper_image.image = pixman.Image.createBits(.a8r8g8b8, @intCast(image.width), @intCast(image.height), @ptrCast(@alignCast(wallpaper_image.pixels.items.ptr)), @intCast(image.width * image.pixelFormat().pixelStride())) orelse return error.FailedToCreatePixmanImage;
|
|
|
|
return wallpaper_image;
|
|
}
|
|
|
|
pub fn destroy(wallpaper_image: *WallpaperImage) void {
|
|
_ = wallpaper_image.image.unref();
|
|
wallpaper_image.pixels.deinit(utils.allocator);
|
|
|
|
utils.allocator.destroy(wallpaper_image);
|
|
}
|
|
|
|
const std = @import("std");
|
|
|
|
const pixman = @import("pixman");
|
|
const zigimg = @import("zigimg");
|
|
|
|
const utils = @import("utils.zig");
|
|
|
|
const log = std.log.scoped(.WallpaperImage);
|