Support BGR subpixel layout (#55174)
Release Notes: - Added text rendering support for BGR subpixel layouts.
This commit is contained in:
1 parent
348a9b815b
commit
f01d6816cb
9 files changed
+62
-11
No files matched your search
@@ -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 {
|
||||
@@ -195,6 +196,7 @@ impl InProgressOutput {
|
||||
name: self.name.clone(),
|
||||
scale,
|
||||
bounds: Bounds::new(position, size),
|
||||
subpixel: self.subpixel,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
@@ -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 {
|
||||
@@ -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)))
|
||||
|
||||
@@ -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();
|
||||
@@ -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 {
|
||||
@@ -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 {
|
||||
|
||||
@@ -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>,
|
||||
@@ -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,
|
||||
@@ -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)),
|
||||
@@ -1615,6 +1619,7 @@ impl LinuxClient for X11Client {
|
||||
appearance,
|
||||
parent_window,
|
||||
supports_xinput_gestures,
|
||||
is_bgr,
|
||||
)?;
|
||||
check_reply(
|
||||
|| "Failed to set XdndAware property",
|
||||
|
||||
@@ -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
|
||||
@@ -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,
|
||||
@@ -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();
|
||||
@@ -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(
|
||||
@@ -901,6 +905,7 @@ impl X11Window {
|
||||
appearance,
|
||||
parent_window,
|
||||
supports_xinput_gestures,
|
||||
is_bgr,
|
||||
)?)),
|
||||
callbacks: Rc::new(RefCell::new(Callbacks::default())),
|
||||
xcb: xcb.clone(),
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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)]
|
||||
@@ -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,
|
||||
@@ -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,
|
||||
@@ -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
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
@@ -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 {
|
||||
@@ -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,
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -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> {
|
||||
|
||||
@@ -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);
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
|
||||
Reference in new issue
Block a user