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.
|
//! 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();
|
pub const Metal = @This();
|
||||||
|
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
@ -64,7 +71,16 @@ const GPUCell = extern struct {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const GPUUniforms = 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,
|
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,
|
cell_size: [2]f32,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -292,11 +308,8 @@ pub fn render(
|
|||||||
@floatCast(f32, bounds.size.height),
|
@floatCast(f32, bounds.size.height),
|
||||||
0,
|
0,
|
||||||
),
|
),
|
||||||
|
.px_scale = .{ scaleX, scaleY },
|
||||||
.cell_size = .{
|
.cell_size = .{ self.cell_size.width, self.cell_size.height },
|
||||||
self.cell_size.width * scaleX,
|
|
||||||
self.cell_size.height * scaleY,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@ enum Mode : uint8_t {
|
|||||||
|
|
||||||
struct Uniforms {
|
struct Uniforms {
|
||||||
float4x4 projection_matrix;
|
float4x4 projection_matrix;
|
||||||
|
float2 px_scale;
|
||||||
float2 cell_size;
|
float2 cell_size;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -45,8 +46,11 @@ vertex VertexOut uber_vertex(
|
|||||||
VertexIn input [[ stage_in ]],
|
VertexIn input [[ stage_in ]],
|
||||||
constant Uniforms &uniforms [[ buffer(1) ]]
|
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
|
// 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
|
// Turn the cell position into a vertex point depending on the
|
||||||
// vertex ID. Since we use instanced drawing, we have 4 vertices
|
// 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.x = (vid == 0 || vid == 1) ? 1.0f : 0.0f;
|
||||||
position.y = (vid == 0 || vid == 3) ? 0.0f : 1.0f;
|
position.y = (vid == 0 || vid == 3) ? 0.0f : 1.0f;
|
||||||
|
|
||||||
// TODO: scale
|
|
||||||
float2 cell_size = uniforms.cell_size;
|
|
||||||
|
|
||||||
VertexOut out;
|
VertexOut out;
|
||||||
out.mode = input.mode;
|
out.mode = input.mode;
|
||||||
out.color = float4(input.color) / 255.0f;
|
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.
|
// Calculate the final position of our cell in world space.
|
||||||
// We have to add our cell size since our vertices are offset
|
// 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)
|
// 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);
|
out.position = uniforms.projection_matrix * float4(cell_pos.x, cell_pos.y, 0.0f, 1.0f);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MODE_FG:
|
case MODE_FG:
|
||||||
float2 glyph_size = float2(input.glyph_size);
|
float2 glyph_size = float2(input.glyph_size) * uniforms.px_scale;
|
||||||
float2 glyph_offset = float2(input.glyph_offset);
|
float2 glyph_offset = float2(input.glyph_offset) * uniforms.px_scale;
|
||||||
|
|
||||||
// TODO: downsampling
|
// TODO: downsampling
|
||||||
|
|
||||||
|
@ -147,7 +147,7 @@ void main() {
|
|||||||
glyph_offset_calc.y = cell_size_scaled.y - glyph_offset_calc.y;
|
glyph_offset_calc.y = cell_size_scaled.y - glyph_offset_calc.y;
|
||||||
|
|
||||||
// Calculate the final position of the cell.
|
// 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);
|
gl_Position = projection * vec4(cell_pos, cell_z, 1.0);
|
||||||
|
|
||||||
// We need to convert our texture position and size to normalized
|
// We need to convert our texture position and size to normalized
|
||||||
|
Reference in New Issue
Block a user