diff --git a/src/renderer/Metal.zig b/src/renderer/Metal.zig index 0dba464c5..8dc03e01a 100644 --- a/src/renderer/Metal.zig +++ b/src/renderer/Metal.zig @@ -625,8 +625,7 @@ pub fn init(alloc: Allocator, options: renderer.Options) !Metal { .cell_size = undefined, .grid_size = undefined, .grid_padding = undefined, - .padding_extend_top = true, - .padding_extend_bottom = true, + .padding_extend = .{}, .min_contrast = options.config.min_contrast, .cursor_pos = .{ std.math.maxInt(u16), std.math.maxInt(u16) }, .cursor_color = undefined, @@ -1950,16 +1949,20 @@ pub fn setScreenSize( const padded_dim = dim.subPadding(padding); // Blank space around the grid. - const blank: renderer.Padding = switch (self.config.padding_color) { - // We can use zero padding because the background color is our - // clear color. - .background => .{}, + const blank: renderer.Padding = dim.blankPadding(padding, grid_size, .{ + .width = self.grid_metrics.cell_width, + .height = self.grid_metrics.cell_height, + }).add(padding); - .extend => dim.blankPadding(padding, grid_size, .{ - .width = self.grid_metrics.cell_width, - .height = self.grid_metrics.cell_height, - }).add(padding), - }; + var padding_extend = self.uniforms.padding_extend; + if (self.config.padding_color == .extend) { + // If padding extension is enabled, we extend left and right always. + padding_extend.left = true; + padding_extend.right = true; + } else { + // Otherwise, disable all padding extension. + padding_extend = .{}; + } // Set the size of the drawable surface to the bounds self.layer.setProperty("drawableSize", macos.graphics.Size{ @@ -1990,8 +1993,7 @@ pub fn setScreenSize( @floatFromInt(blank.bottom), @floatFromInt(blank.left), }, - .padding_extend_top = old.padding_extend_top, - .padding_extend_bottom = old.padding_extend_bottom, + .padding_extend = padding_extend, .min_contrast = old.min_contrast, .cursor_pos = old.cursor_pos, .cursor_color = old.cursor_color, @@ -2136,8 +2138,10 @@ fn rebuildCells( self.cells.reset(); // We also reset our padding extension depending on the screen type - self.uniforms.padding_extend_top = screen_type == .alternate; - self.uniforms.padding_extend_bottom = screen_type == .alternate; + if (self.config.padding_color == .extend) { + self.uniforms.padding_extend.up = screen_type == .alternate; + self.uniforms.padding_extend.down = screen_type == .alternate; + } } // Go row-by-row to build the cells. We go row by row because we do @@ -2174,10 +2178,12 @@ fn rebuildCells( // under certain conditions we feel are safe. This helps make some // scenarios look better while avoiding scenarios we know do NOT look // good. - if (y == 0 and screen_type == .primary) { - self.uniforms.padding_extend_top = !row.neverExtendBg(); - } else if (y == self.cells.size.rows - 1 and screen_type == .primary) { - self.uniforms.padding_extend_bottom = !row.neverExtendBg(); + if (self.config.padding_color == .extend) { + if (y == 0 and screen_type == .primary) { + self.uniforms.padding_extend.up = !row.neverExtendBg(); + } else if (y == self.cells.size.rows - 1 and screen_type == .primary) { + self.uniforms.padding_extend.down = !row.neverExtendBg(); + } } // Split our row into runs and shape each one. diff --git a/src/renderer/metal/shaders.zig b/src/renderer/metal/shaders.zig index 9c9b44475..6708a8bec 100644 --- a/src/renderer/metal/shaders.zig +++ b/src/renderer/metal/shaders.zig @@ -124,9 +124,10 @@ pub const Uniforms = extern struct { /// top, right, bottom, left. grid_padding: [4]f32 align(16), - /// True if vertical padding gets the extended color of the nearest row. - padding_extend_top: bool align(1), - padding_extend_bottom: bool align(1), + /// Bit mask defining which directions to + /// extend cell colors in to the padding. + /// Order, LSB first: left, right, up, down + padding_extend: PaddingExtend align(1), /// The minimum contrast ratio for text. The contrast ratio is calculated /// according to the WCAG 2.0 spec. @@ -135,6 +136,14 @@ pub const Uniforms = extern struct { /// The cursor position and color. cursor_pos: [2]u16 align(4), cursor_color: [4]u8 align(4), + + const PaddingExtend = packed struct(u8) { + left: bool = false, + right: bool = false, + up: bool = false, + down: bool = false, + _padding: u4 = 0, + }; }; /// The uniforms used for custom postprocess shaders. diff --git a/src/renderer/shaders/cell.metal b/src/renderer/shaders/cell.metal index e34ea18b2..b58e6600e 100644 --- a/src/renderer/shaders/cell.metal +++ b/src/renderer/shaders/cell.metal @@ -2,13 +2,19 @@ using namespace metal; +enum Padding : uint8_t { + EXTEND_LEFT = 1u, + EXTEND_RIGHT = 2u, + EXTEND_UP = 4u, + EXTEND_DOWN = 8u, +}; + struct Uniforms { float4x4 projection_matrix; float2 cell_size; ushort2 grid_size; float4 grid_padding; - bool padding_extend_top; - bool padding_extend_bottom; + uint8_t padding_extend; float min_contrast; ushort2 cursor_pos; uchar4 cursor_color; @@ -110,21 +116,32 @@ fragment float4 cell_bg_fragment( constant uchar4 *cells [[buffer(0)]], constant Uniforms& uniforms [[buffer(1)]] ) { - int2 grid_pos = int2((in.position.xy - uniforms.grid_padding.wx) / uniforms.cell_size); + int2 grid_pos = int2(floor((in.position.xy - uniforms.grid_padding.wx) / uniforms.cell_size)); // Clamp x position, extends edge bg colors in to padding on sides. - grid_pos.x = clamp(grid_pos.x, 0, uniforms.grid_size.x - 1); - - // Clamp y position if we should extend, otherwise discard if out of bounds. - if (grid_pos.y < 0) { - if (uniforms.padding_extend_top) { - grid_pos.y = 0; + if (grid_pos.x < 0) { + if (uniforms.padding_extend & EXTEND_LEFT) { + grid_pos.x = 0; + } else { + return float4(0.0); + } + } else if (grid_pos.x > uniforms.grid_size.x - 1) { + if (uniforms.padding_extend & EXTEND_RIGHT) { + grid_pos.x = uniforms.grid_size.x - 1; } else { return float4(0.0); } } - if (grid_pos.y > uniforms.grid_size.y - 1) { - if (uniforms.padding_extend_bottom) { + + // Clamp y position if we should extend, otherwise discard if out of bounds. + if (grid_pos.y < 0) { + if (uniforms.padding_extend & EXTEND_UP) { + grid_pos.y = 0; + } else { + return float4(0.0); + } + } else if (grid_pos.y > uniforms.grid_size.y - 1) { + if (uniforms.padding_extend & EXTEND_DOWN) { grid_pos.y = uniforms.grid_size.y - 1; } else { return float4(0.0);