From 247b92ce0751927336384ef241f72f74849dc9b9 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Tue, 21 Nov 2023 16:56:02 -0800 Subject: [PATCH] renderer/opengl: convert Kitty images from RGB to RGBA Fixes #932 We have to do this for Metal as well (this code is copied from Metal) since Metal doesnt even allow RGB textures. I couldn't figure out a way to get the A value to be "255" (byte), it seems to always be set to 1 which gets normalized to 1/255, so lets just manually convert. --- src/renderer/opengl/image.zig | 40 +++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/src/renderer/opengl/image.zig b/src/renderer/opengl/image.zig index a10fe9600..d9ad118b8 100644 --- a/src/renderer/opengl/image.zig +++ b/src/renderer/opengl/image.zig @@ -114,12 +114,52 @@ pub const Image = union(enum) { }; } + /// Converts the image data to a format that can be uploaded to the GPU. + /// If the data is already in a format that can be uploaded, this is a + /// no-op. + fn convert(self: *Image, alloc: Allocator) !void { + switch (self.*) { + .ready, + .unload_pending, + .unload_ready, + => unreachable, // invalid + + .pending_rgba => {}, // ready + + // RGB needs to be converted to RGBA because Metal textures + // don't support RGB. + .pending_rgb => |*p| { + // Note: this is the slowest possible way to do this... + const data = p.dataSlice(3); + const pixels = data.len / 3; + var rgba = try alloc.alloc(u8, pixels * 4); + errdefer alloc.free(rgba); + var i: usize = 0; + while (i < pixels) : (i += 1) { + const data_i = i * 3; + const rgba_i = i * 4; + rgba[rgba_i] = data[data_i]; + rgba[rgba_i + 1] = data[data_i + 1]; + rgba[rgba_i + 2] = data[data_i + 2]; + rgba[rgba_i + 3] = 255; + } + + alloc.free(data); + p.data = rgba.ptr; + self.* = .{ .pending_rgba = p.* }; + }, + } + } + /// Upload the pending image to the GPU and change the state of this /// image to ready. pub fn upload( self: *Image, alloc: Allocator, ) !void { + // Convert our data if we have to + try self.convert(alloc); + // Get our pending info const p = self.pending().?;