Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions crates/gpui_linux/src/linux/wayland/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,7 @@ pub struct InProgressOutput {
scale: Option<i32>,
position: Option<Point<DevicePixels>>,
size: Option<Size<DevicePixels>>,
subpixel: Option<wl_output::Subpixel>,
}

impl InProgressOutput {
Expand All @@ -195,6 +196,7 @@ impl InProgressOutput {
name: self.name.clone(),
scale,
bounds: Bounds::new(position, size),
subpixel: self.subpixel,
})
} else {
None
Expand All @@ -207,6 +209,7 @@ pub struct Output {
pub name: Option<String>,
pub scale: i32,
pub bounds: Bounds<DevicePixels>,
pub subpixel: Option<wl_output::Subpixel>,
}

pub(crate) struct WaylandClientState {
Expand Down Expand Up @@ -1166,8 +1169,11 @@ impl Dispatch<wl_output::WlOutput, ()> for WaylandClientStatePtr {
wl_output::Event::Scale { factor } => {
in_progress_output.scale = Some(factor);
}
wl_output::Event::Geometry { x, y, .. } => {
in_progress_output.position = Some(point(DevicePixels(x), DevicePixels(y)))
wl_output::Event::Geometry { x, y, subpixel, .. } => {
in_progress_output.position = Some(point(DevicePixels(x), DevicePixels(y)));
if let WEnum::Value(subpixel) = subpixel {
in_progress_output.subpixel = Some(subpixel);
}
}
wl_output::Event::Mode { width, height, .. } => {
in_progress_output.size = Some(size(DevicePixels(width), DevicePixels(height)))
Expand Down
12 changes: 12 additions & 0 deletions crates/gpui_linux/src/linux/wayland/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,16 @@ impl WaylandWindowState {
|| self.background_appearance != WindowBackgroundAppearance::Opaque
}

fn update_subpixel_layout(&mut self) {
use wayland_client::protocol::wl_output::Subpixel;
let is_bgr = self
.display
.as_ref()
.and_then(|(_, output)| output.subpixel)
.is_some_and(|s| s == Subpixel::HorizontalBgr);
self.renderer.set_subpixel_layout(is_bgr);
}

pub fn primary_output_scale(&mut self) -> i32 {
let mut scale = 1;
let mut current_output = self.display.take();
Expand Down Expand Up @@ -864,6 +874,7 @@ impl WaylandWindowStatePtr {
state.outputs.insert(id, output.clone());

let scale = state.primary_output_scale();
state.update_subpixel_layout();

// We use `PreferredBufferScale` instead to set the scale if it's available
if state.surface.version() < wl_surface::EVT_PREFERRED_BUFFER_SCALE_SINCE {
Expand All @@ -876,6 +887,7 @@ impl WaylandWindowStatePtr {
state.outputs.remove(&output.id());

let scale = state.primary_output_scale();
state.update_subpixel_layout();

// We use `PreferredBufferScale` instead to set the scale if it's available
if state.surface.version() < wl_surface::EVT_PREFERRED_BUFFER_SCALE_SINCE {
Expand Down
9 changes: 7 additions & 2 deletions crates/gpui_linux/src/linux/x11/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ pub struct X11ClientState {
xkb_device_id: i32,
client_side_decorations_supported: bool,
pub(crate) x_root_index: usize,
pub(crate) _resource_database: Database,
pub(crate) resource_database: Database,
pub(crate) atoms: XcbAtoms,
pub(crate) windows: HashMap<xproto::Window, WindowRef>,
pub(crate) mouse_focused_window: Option<xproto::Window>,
Expand Down Expand Up @@ -525,7 +525,7 @@ impl X11Client {
xkb_device_id,
client_side_decorations_supported,
x_root_index,
_resource_database: resource_database,
resource_database,
atoms,
windows: HashMap::default(),
mouse_focused_window: None,
Expand Down Expand Up @@ -1599,6 +1599,10 @@ impl LinuxClient for X11Client {
let appearance = state.common.appearance;
let compositor_gpu = state.compositor_gpu.take();
let supports_xinput_gestures = state.supports_xinput_gestures;
let is_bgr = state
.resource_database
.get_string("Xft.rgba", "Xft.Rgba")
.is_some_and(|v| v.eq_ignore_ascii_case("bgr"));
let window = X11Window::new(
handle,
X11ClientStatePtr(Rc::downgrade(&self.0)),
Expand All @@ -1615,6 +1619,7 @@ impl LinuxClient for X11Client {
appearance,
parent_window,
supports_xinput_gestures,
is_bgr,
)?;
check_reply(
|| "Failed to set XdndAware property",
Expand Down
7 changes: 6 additions & 1 deletion crates/gpui_linux/src/linux/x11/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -425,6 +425,7 @@ impl X11WindowState {
appearance: WindowAppearance,
parent_window: Option<X11WindowStatePtr>,
supports_xinput_gestures: bool,
is_bgr: bool,
) -> anyhow::Result<Self> {
let x_screen_index = params
.display_id
Expand Down Expand Up @@ -702,7 +703,7 @@ impl X11WindowState {

xcb_flush(xcb);

let renderer = {
let mut renderer = {
let raw_window = RawWindow {
connection: as_raw_xcb_connection::AsRawXcbConnection::as_raw_xcb_connection(
xcb,
Expand All @@ -725,6 +726,8 @@ impl X11WindowState {
WgpuRenderer::new(gpu_context, &raw_window, config, compositor_gpu)?
};

renderer.set_subpixel_layout(is_bgr);

// Set max window size hints based on the GPU's maximum texture dimension.
// This prevents the window from being resized larger than what the GPU can render.
let max_texture_size = renderer.max_texture_size();
Expand Down Expand Up @@ -883,6 +886,7 @@ impl X11Window {
appearance: WindowAppearance,
parent_window: Option<X11WindowStatePtr>,
supports_xinput_gestures: bool,
is_bgr: bool,
) -> anyhow::Result<Self> {
let ptr = X11WindowStatePtr {
state: Rc::new(RefCell::new(X11WindowState::new(
Expand All @@ -901,6 +905,7 @@ impl X11Window {
appearance,
parent_window,
supports_xinput_gestures,
is_bgr,
)?)),
callbacks: Rc::new(RefCell::new(Callbacks::default())),
xcb: xcb.clone(),
Expand Down
3 changes: 2 additions & 1 deletion crates/gpui_wgpu/src/shaders.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,8 @@ struct GammaParams {
gamma_ratios: vec4<f32>,
grayscale_enhanced_contrast: f32,
subpixel_enhanced_contrast: f32,
pad: vec2<f32>,
is_bgr: u32,
pad: u32,
}

@group(0) @binding(0) var<uniform> globals: GlobalParams;
Expand Down
5 changes: 4 additions & 1 deletion crates/gpui_wgpu/src/shaders_subpixel.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,10 @@ fn vs_subpixel_sprite(@builtin(vertex_index) vertex_id: u32, @builtin(instance_i

@fragment
fn fs_subpixel_sprite(input: SubpixelSpriteOutput) -> SubpixelSpriteFragmentOutput {
let sample = textureSample(t_sprite, s_sprite, input.tile_position).rgb;
var sample = textureSample(t_sprite, s_sprite, input.tile_position).rgb;
if (gamma_params.is_bgr != 0u) {
sample = sample.bgr;
}
let alpha_corrected = apply_contrast_and_gamma_correction3(sample, input.color.rgb, gamma_params.subpixel_enhanced_contrast, gamma_params.gamma_ratios);

// Alpha clip after using the derivatives.
Expand Down
12 changes: 10 additions & 2 deletions crates/gpui_wgpu/src/wgpu_renderer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,8 @@ struct GammaParams {
gamma_ratios: [f32; 4],
grayscale_enhanced_contrast: f32,
subpixel_enhanced_contrast: f32,
_pad: [f32; 2],
is_bgr: u32,
_pad: u32,
}

#[derive(Clone, Debug)]
Expand Down Expand Up @@ -146,6 +147,7 @@ pub struct WgpuRenderer {
max_buffer_size: u64,
storage_buffer_alignment: u64,
rendering_params: RenderingParameters,
is_bgr: bool,
dual_source_blending: bool,
adapter_info: wgpu::AdapterInfo,
transparent_alpha_mode: wgpu::CompositeAlphaMode,
Expand Down Expand Up @@ -475,6 +477,7 @@ impl WgpuRenderer {
max_buffer_size,
storage_buffer_alignment,
rendering_params,
is_bgr: false,
dual_source_blending,
adapter_info,
transparent_alpha_mode,
Expand Down Expand Up @@ -1016,6 +1019,10 @@ impl WgpuRenderer {
resources.path_msaa_view = path_msaa_view;
}

pub fn set_subpixel_layout(&mut self, is_bgr: bool) {
self.is_bgr = is_bgr;
}

pub fn update_transparency(&mut self, transparent: bool) {
let new_alpha_mode = if transparent {
self.transparent_alpha_mode
Expand Down Expand Up @@ -1147,7 +1154,8 @@ impl WgpuRenderer {
gamma_ratios: self.rendering_params.gamma_ratios,
grayscale_enhanced_contrast: self.rendering_params.grayscale_enhanced_contrast,
subpixel_enhanced_contrast: self.rendering_params.subpixel_enhanced_contrast,
_pad: [0.0; 2],
is_bgr: self.is_bgr as u32,
_pad: 0,
};

let globals = GlobalParams {
Expand Down
6 changes: 6 additions & 0 deletions crates/gpui_windows/src/directx_renderer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ pub(crate) struct FontInfo {
pub gamma_ratios: [f32; 4],
pub grayscale_enhanced_contrast: f32,
pub subpixel_enhanced_contrast: f32,
pub is_bgr: bool,
}

pub(crate) struct DirectXRenderer {
Expand Down Expand Up @@ -195,6 +196,8 @@ impl DirectXRenderer {
viewport_size: [resources.viewport.Width, resources.viewport.Height],
grayscale_enhanced_contrast: self.font_info.grayscale_enhanced_contrast,
subpixel_enhanced_contrast: self.font_info.subpixel_enhanced_contrast,
is_bgr: self.font_info.is_bgr as u32,
_pad: [0; 3],
}],
)?;
unsafe {
Expand Down Expand Up @@ -741,6 +744,7 @@ impl DirectXRenderer {
gamma_ratios: gpui::get_gamma_correction_ratios(render_params.GetGamma()),
grayscale_enhanced_contrast: render_params.GetGrayscaleEnhancedContrast(),
subpixel_enhanced_contrast: render_params.GetEnhancedContrast(),
is_bgr: render_params.GetPixelGeometry() == DWRITE_PIXEL_GEOMETRY_BGR,
}
})
}
Expand Down Expand Up @@ -961,6 +965,8 @@ struct GlobalParams {
viewport_size: [f32; 2],
grayscale_enhanced_contrast: f32,
subpixel_enhanced_contrast: f32,
is_bgr: u32,
_pad: [u32; 3],
}

struct PipelineState<T> {
Expand Down
9 changes: 7 additions & 2 deletions crates/gpui_windows/src/shaders.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ cbuffer GlobalParams: register(b0) {
float2 global_viewport_size;
float grayscale_enhanced_contrast;
float subpixel_enhanced_contrast;
uint is_bgr;
uint3 global_pad;
};

Texture2D<float4> t_sprite: register(t0);
Expand Down Expand Up @@ -420,11 +422,11 @@ float4 gradient_color(Background background,
// checkerboard
float size = background.gradient_angle_or_pattern_height;
float2 relative_position = position - bounds.origin;

float x_index = floor(relative_position.x / size);
float y_index = floor(relative_position.y / size);
float should_be_colored = (x_index + y_index) % 2.0;

color = solid_color;
color.a *= saturate(should_be_colored);
break;
Expand Down Expand Up @@ -1157,6 +1159,9 @@ MonochromeSpriteVertexOutput subpixel_sprite_vertex(uint vertex_id: SV_VertexID,

SubpixelSpriteFragmentOutput subpixel_sprite_fragment(MonochromeSpriteFragmentInput input) {
float3 sample = t_sprite.Sample(s_sprite, input.tile_position).rgb;
if (is_bgr) {
sample = sample.bgr;
}
float3 alpha_corrected = apply_contrast_and_gamma_correction3(sample, input.color.rgb, subpixel_enhanced_contrast, gamma_ratios);

SubpixelSpriteFragmentOutput output;
Expand Down
Loading