@@ -345,6 +345,12 @@ impl WaylandWindowState {
if let Some(title) = options.titlebar.and_then(|titlebar| titlebar.title) {
xdg_state.toplevel.set_title(title.to_string());
}
+ // Set max window size 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() as i32;
+ xdg_state
+ .toplevel
+ .set_max_size(max_texture_size, max_texture_size);
}
Ok(Self {
@@ -497,21 +497,6 @@ impl X11WindowState {
),
)?;
- if let Some(size) = params.window_min_size {
- let mut size_hints = WmSizeHints::new();
- let min_size = (f32::from(size.width) as i32, f32::from(size.height) as i32);
- size_hints.min_size = Some(min_size);
- check_reply(
- || {
- format!(
- "X11 change of WM_SIZE_HINTS failed. min_size: {:?}",
- min_size
- )
- },
- size_hints.set_normal_hints(xcb, x_window),
- )?;
- }
-
let reply = get_reply(|| "X11 GetGeometry failed.", xcb.get_geometry(x_window))?;
if reply.x == 0 && reply.y == 0 {
bounds.origin.x.0 += 2;
@@ -697,6 +682,25 @@ impl X11WindowState {
WgpuRenderer::new(gpu_context, &raw_window, config)?
};
+ // 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();
+ let mut size_hints = WmSizeHints::new();
+ if let Some(size) = params.window_min_size {
+ size_hints.min_size =
+ Some((f32::from(size.width) as i32, f32::from(size.height) as i32));
+ }
+ size_hints.max_size = Some((max_texture_size as i32, max_texture_size as i32));
+ check_reply(
+ || {
+ format!(
+ "X11 change of WM_SIZE_HINTS failed. max_size: {:?}",
+ max_texture_size
+ )
+ },
+ size_hints.set_normal_hints(xcb, x_window),
+ )?;
+
let display = Rc::new(X11Display::new(xcb, scale_factor, x_screen_index)?);
Ok(Self {
@@ -116,6 +116,7 @@ pub struct WgpuRenderer {
adapter_info: wgpu::AdapterInfo,
transparent_alpha_mode: wgpu::CompositeAlphaMode,
opaque_alpha_mode: wgpu::CompositeAlphaMode,
+ max_texture_size: u32,
}
impl WgpuRenderer {
@@ -215,11 +216,27 @@ impl WgpuRenderer {
opaque_alpha_mode
};
+ let device = Arc::clone(&context.device);
+ let max_texture_size = device.limits().max_texture_dimension_2d;
+
+ let requested_width = config.size.width.0 as u32;
+ let requested_height = config.size.height.0 as u32;
+ let clamped_width = requested_width.min(max_texture_size);
+ let clamped_height = requested_height.min(max_texture_size);
+
+ if clamped_width != requested_width || clamped_height != requested_height {
+ warn!(
+ "Requested surface size ({}, {}) exceeds maximum texture dimension {}. \
+ Clamping to ({}, {}). Window content may not fill the entire window.",
+ requested_width, requested_height, max_texture_size, clamped_width, clamped_height
+ );
+ }
+
let surface_config = wgpu::SurfaceConfiguration {
usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
format: surface_format,
- width: config.size.width.0 as u32,
- height: config.size.height.0 as u32,
+ width: clamped_width.max(1),
+ height: clamped_height.max(1),
present_mode: wgpu::PresentMode::Fifo,
desired_maximum_frame_latency: 2,
alpha_mode,
@@ -227,7 +244,6 @@ impl WgpuRenderer {
};
surface.configure(&context.device, &surface_config);
- let device = Arc::clone(&context.device);
let queue = Arc::clone(&context.queue);
let dual_source_blending = context.supports_dual_source_blending();
@@ -348,6 +364,7 @@ impl WgpuRenderer {
adapter_info,
transparent_alpha_mode,
opaque_alpha_mode,
+ max_texture_size,
})
}
@@ -762,6 +779,17 @@ impl WgpuRenderer {
let height = size.height.0 as u32;
if width != self.surface_config.width || height != self.surface_config.height {
+ let clamped_width = width.min(self.max_texture_size);
+ let clamped_height = height.min(self.max_texture_size);
+
+ if clamped_width != width || clamped_height != height {
+ warn!(
+ "Requested surface size ({}, {}) exceeds maximum texture dimension {}. \
+ Clamping to ({}, {}). Window content may not fill the entire window.",
+ width, height, self.max_texture_size, clamped_width, clamped_height
+ );
+ }
+
// Wait for any in-flight GPU work to complete before destroying textures
if let Err(e) = self.device.poll(wgpu::PollType::Wait {
submission_index: None,
@@ -778,8 +806,8 @@ impl WgpuRenderer {
texture.destroy();
}
- self.surface_config.width = width.max(1);
- self.surface_config.height = height.max(1);
+ self.surface_config.width = clamped_width.max(1);
+ self.surface_config.height = clamped_height.max(1);
self.surface.configure(&self.device, &self.surface_config);
// Invalidate intermediate textures - they will be lazily recreated
@@ -864,6 +892,10 @@ impl WgpuRenderer {
}
}
+ pub fn max_texture_size(&self) -> u32 {
+ self.max_texture_size
+ }
+
pub fn draw(&mut self, scene: &Scene) {
self.atlas.before_frame();