Commit 188ed0425658
tarball3 files changed+63-28
@@ -12,7 +12,7 @@ use smithay::backend::renderer::element::surface::render_elements_from_surface_t
1212
use smithay::backend::renderer::element::utils::{CropRenderElement, RescaleRenderElement};1313
use smithay::backend::renderer::element::{AsRenderElements, Element, Id, Kind, RenderElement};1414
use smithay::backend::renderer::utils::with_renderer_surface_state;15
-use smithay::backend::renderer::utils::{CommitCounter, DamageSet, OpaqueRegions};15
+use smithay::backend::renderer::utils::{CommitCounter, DamageSet, OpaqueRegions, SurfaceView};1616
use smithay::backend::renderer::{Frame, Renderer, Texture};1717
use smithay::desktop::Window;1818
use smithay::output::Output;@@ -280,17 +280,18 @@ fn window_elements(
280280
return;281281
};282282
let context = renderer.context_id();283
- let Some((tex, buffer_scale, transform)) = with_renderer_surface_state(&root, |s| {284
- s.texture::<VulkanTexture>(context.clone())285
- .cloned()286
- .map(|t| (t, s.buffer_scale(), s.buffer_transform()))283
+ let Some((tex, buffer_scale, transform, view)) = with_renderer_surface_state(&root, |s| {284
+ let texture = s.texture::<VulkanTexture>(context.clone())?.clone();285
+ Some((texture, s.buffer_scale(), s.buffer_transform(), s.view()?))287286
})288287
.flatten() else {289288
return;290289
};291290
let (gw, gh) = (drawn.w, drawn.h);292291
let (cw, ch) = (w.min(gw), h.min(gh));293
- let (gx, gy) = (f64::from(geo.loc.x), f64::from(geo.loc.y));292
+ let ratio = source_ratio(&view);293
+ let geo_src = to_source(&view, geo.to_f64());294
+ let (gx, gy) = (geo_src.loc.x, geo_src.loc.y);294295
let mut strip = |src: Rectangle<f64, Logical>, at: (i32, i32), size: (i32, i32)| {295296
if size.0 >= 1 && size.1 >= 1 {296297
let bounds = tex.size().to_logical(buffer_scale, transform).to_f64();@@ -301,15 +302,21 @@ fn window_elements(
301302
}302303
};303304
let pixel = 1.0 / f64::from(buffer_scale);304
- let right = gx + f64::from(geo.size.w) - pixel;305
- let bottom = gy + f64::from(geo.size.h) - pixel;305
+ let right = gx + geo_src.size.w - pixel;306
+ let bottom = gy + geo_src.size.h - pixel;306307
strip(307
- Rectangle::new((right, gy).into(), (pixel, f64::from(ch) / scale).into()),308
+ Rectangle::new(309
+ (right, gy).into(),310
+ (pixel, f64::from(ch) / scale * ratio.1).into(),311
+ ),308312
(x + gw, y),309313
(w - gw, ch),310314
);311315
strip(312
- Rectangle::new((gx, bottom).into(), (f64::from(cw) / scale, pixel).into()),316
+ Rectangle::new(317
+ (gx, bottom).into(),318
+ (f64::from(cw) / scale * ratio.0, pixel).into(),319
+ ),313320
(x, y + gh),314321
(cw, h - gh),315322
);@@ -367,6 +374,25 @@ fn pixels(r: Rect, scale: f64) -> Option<((i32, i32), (i32, i32))> {
367374
(w >= 1 && h >= 1).then_some(((x, y), (w, h)))368375
}369376
377
+/// How many logical units of the texture one logical unit of the surface378
+/// covers, which a viewport destination makes differ from 1.379
+fn source_ratio(view: &SurfaceView) -> (f64, f64) {380
+ (381
+ view.src.size.w / f64::from(view.dst.w.max(1)),382
+ view.src.size.h / f64::from(view.dst.h.max(1)),383
+ )384
+}385
+386
+/// Maps a rectangle in surface coordinates to the logical coordinates of the387
+/// texture behind them.388
+pub fn to_source(view: &SurfaceView, r: Rectangle<f64, Logical>) -> Rectangle<f64, Logical> {389
+ let (rx, ry) = source_ratio(view);390
+ Rectangle::new(391
+ (view.src.loc.x + r.loc.x * rx, view.src.loc.y + r.loc.y * ry).into(),392
+ (r.size.w * rx, r.size.h * ry).into(),393
+ )394
+}395
+370396
pub fn to_physical(p: (f64, f64), scale: f64) -> Point<i32, Physical> {371397
((p.0 * scale).round() as i32, (p.1 * scale).round() as i32).into()372398
}@@ -397,9 +423,8 @@ fn effect_elements(
397423
let crop = Rectangle::new(at.into(), size.into());398424
let context = renderer.context_id();399425
let root_tex = with_renderer_surface_state(&root, |s| {400
- s.texture::<VulkanTexture>(context.clone())401
- .cloned()402
- .map(|t| (t, s.buffer_scale(), s.buffer_transform()))426
+ let texture = s.texture::<VulkanTexture>(context.clone())?.clone();427
+ Some((texture, s.buffer_scale(), s.buffer_transform(), s.view()?))403428
})404429
.flatten();405430
out.extend(@@ -409,11 +434,14 @@ fn effect_elements(
409434
.filter_map(|e| CropRenderElement::from_element(e, scale, crop))410435
.map(Draw::Cropped),411436
);412
- if let Some((tex, buffer_scale, transform)) = root_tex {437
+ if let Some((tex, buffer_scale, transform, view)) = root_tex {413438
let geo = window.geometry();414
- let src = Rectangle::new(415
- geo.loc.to_f64(),416
- (f64::from(size.0) / scale, f64::from(size.1) / scale).into(),439
+ let src = to_source(440
+ &view,441
+ Rectangle::new(442
+ geo.loc.to_f64(),443
+ (f64::from(size.0) / scale, f64::from(size.1) / scale).into(),444
+ ),417445
);418446
let bounds = tex.size().to_logical(buffer_scale, transform).to_f64();419447
let src = src.to_buffer(f64::from(buffer_scale), transform, &bounds);@@ -516,9 +544,12 @@ fn ghost_element(
516544
scale: f64,517545
) -> Option<Draw> {518546
let (at, size) = pixels(r, scale)?;519
- let src = Rectangle::new(520
- frame.geometry.loc.to_f64(),521
- (f64::from(size.0) / scale, f64::from(size.1) / scale).into(),547
+ let src = to_source(548
+ &frame.view,549
+ Rectangle::new(550
+ frame.geometry.loc.to_f64(),551
+ (f64::from(size.0) / scale, f64::from(size.1) / scale).into(),552
+ ),522553
);523554
let bounds = frame524555
.texture@@ -434,14 +434,14 @@ impl State {
434434
// below already holds.435435
let geometry = window.geometry();436436
with_renderer_surface_state(&surface, |s| {437
- s.texture::<VulkanTexture>(context.clone())438
- .cloned()439
- .map(|texture| LastFrame {440
- texture,441
- scale: s.buffer_scale(),442
- transform: s.buffer_transform(),443
- geometry,444
- })437
+ let texture = s.texture::<VulkanTexture>(context.clone())?.clone();438
+ Some(LastFrame {439
+ texture,440
+ scale: s.buffer_scale(),441
+ transform: s.buffer_transform(),442
+ geometry,443
+ view: s.view()?,444
+ })445445
})446446
.flatten()447447
}@@ -7,6 +7,7 @@ use monolith_layout::{Layout, OutputId, Rect, WindowId};
77
use monolith_render_vk::VulkanTexture;88
use slotmap::SecondaryMap;99
use smithay::backend::renderer::element::solid::SolidColorBuffer;10
+use smithay::backend::renderer::utils::SurfaceView;1011
use smithay::desktop::{PopupManager, Space, Window};1112
use smithay::reexports::wayland_protocols::xdg::shell::server::xdg_toplevel::State as XdgState;1213
use smithay::reexports::wayland_server::protocol::wl_surface::WlSurface;@@ -39,6 +40,9 @@ pub struct LastFrame {
3940
pub transform: Transform,4041
/// Window geometry inside the buffer.4142
pub geometry: Rectangle<i32, Logical>,43
+ /// Where the surface's own coordinates sit in the texture, which a44
+ /// viewport makes more than a scale.45
+ pub view: SurfaceView,4246
}4347
4448
pub struct Parts<'a> {