mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-15 00:06:09 +03:00
metal: handle HiDPI scaling
This commit is contained in:
@ -1,4 +1,11 @@
|
||||
//! Renderer implementation for Metal.
|
||||
//!
|
||||
//! Open questions:
|
||||
//!
|
||||
//! - This requires a "px_scale" uniform to account for pixel scaling
|
||||
//! issues with Retina. I'm not 100% sure why this is necessary and why
|
||||
//! this doesn't happen with OpenGL.
|
||||
//!
|
||||
pub const Metal = @This();
|
||||
|
||||
const std = @import("std");
|
||||
@ -64,7 +71,16 @@ const GPUCell = extern struct {
|
||||
};
|
||||
|
||||
const GPUUniforms = extern struct {
|
||||
/// The projection matrix for turning world coordinates to normalized.
|
||||
/// This is calculated based on the size of the screen.
|
||||
projection_matrix: math.Mat,
|
||||
|
||||
/// A scale factor to apply to all pixels given as input (including
|
||||
/// in this uniform i.e. cell_size). This is due to HiDPI screens (Retina)
|
||||
/// mismatch with the window.
|
||||
px_scale: [2]f32,
|
||||
|
||||
/// Size of a single cell in pixels, unscaled.
|
||||
cell_size: [2]f32,
|
||||
};
|
||||
|
||||
@ -292,11 +308,8 @@ pub fn render(
|
||||
@floatCast(f32, bounds.size.height),
|
||||
0,
|
||||
),
|
||||
|
||||
.cell_size = .{
|
||||
self.cell_size.width * scaleX,
|
||||
self.cell_size.height * scaleY,
|
||||
},
|
||||
.px_scale = .{ scaleX, scaleY },
|
||||
.cell_size = .{ self.cell_size.width, self.cell_size.height },
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -8,6 +8,7 @@ enum Mode : uint8_t {
|
||||
|
||||
struct Uniforms {
|
||||
float4x4 projection_matrix;
|
||||
float2 px_scale;
|
||||
float2 cell_size;
|
||||
};
|
||||
|
||||
@ -45,8 +46,11 @@ vertex VertexOut uber_vertex(
|
||||
VertexIn input [[ stage_in ]],
|
||||
constant Uniforms &uniforms [[ buffer(1) ]]
|
||||
) {
|
||||
// TODO: scale with cell width
|
||||
float2 cell_size = uniforms.cell_size * uniforms.px_scale;
|
||||
|
||||
// Convert the grid x,y into world space x, y by accounting for cell size
|
||||
float2 cell_pos = uniforms.cell_size * input.grid_pos;
|
||||
float2 cell_pos = cell_size * input.grid_pos;
|
||||
|
||||
// Turn the cell position into a vertex point depending on the
|
||||
// vertex ID. Since we use instanced drawing, we have 4 vertices
|
||||
@ -62,9 +66,6 @@ vertex VertexOut uber_vertex(
|
||||
position.x = (vid == 0 || vid == 1) ? 1.0f : 0.0f;
|
||||
position.y = (vid == 0 || vid == 3) ? 0.0f : 1.0f;
|
||||
|
||||
// TODO: scale
|
||||
float2 cell_size = uniforms.cell_size;
|
||||
|
||||
VertexOut out;
|
||||
out.mode = input.mode;
|
||||
out.color = float4(input.color) / 255.0f;
|
||||
@ -73,14 +74,14 @@ vertex VertexOut uber_vertex(
|
||||
// Calculate the final position of our cell in world space.
|
||||
// We have to add our cell size since our vertices are offset
|
||||
// one cell up and to the left. (Do the math to verify yourself)
|
||||
cell_pos = cell_pos + uniforms.cell_size * position;
|
||||
cell_pos = cell_pos + cell_size * position;
|
||||
|
||||
out.position = uniforms.projection_matrix * float4(cell_pos.x, cell_pos.y, 0.0f, 1.0f);
|
||||
break;
|
||||
|
||||
case MODE_FG:
|
||||
float2 glyph_size = float2(input.glyph_size);
|
||||
float2 glyph_offset = float2(input.glyph_offset);
|
||||
float2 glyph_size = float2(input.glyph_size) * uniforms.px_scale;
|
||||
float2 glyph_offset = float2(input.glyph_offset) * uniforms.px_scale;
|
||||
|
||||
// TODO: downsampling
|
||||
|
||||
|
@ -147,7 +147,7 @@ void main() {
|
||||
glyph_offset_calc.y = cell_size_scaled.y - glyph_offset_calc.y;
|
||||
|
||||
// Calculate the final position of the cell.
|
||||
cell_pos = cell_pos + glyph_size_downsampled * position + glyph_offset_calc;
|
||||
cell_pos = cell_pos + (glyph_size_downsampled * position) + glyph_offset_calc;
|
||||
gl_Position = projection * vec4(cell_pos, cell_z, 1.0);
|
||||
|
||||
// We need to convert our texture position and size to normalized
|
||||
|
Reference in New Issue
Block a user