forked from 1b-agent/opencadstudio-upstream
fix(paper): skip GPU for off-canvas inactive viewports
Zooming the paper view in PSPACE grows each floating viewport's screen rectangle until its edges run past the canvas. The per-viewport blit computes its surface offset via `(screen_rect.x * cw) as u32`, which saturates negative values to 0 — so a viewport hanging off the left edge was being painted at the canvas top-left instead of its actual position, producing a drifting ghost copy on top of the CPU projection that PaperCanvas was already drawing correctly clipped. `active_viewports` for paper now skips the GPU pass for any inactive content viewport whose screen rect would extend beyond the canvas. The CPU projection already handles those, so only one (correct) copy is visible. The active viewport keeps the GPU path so its per-viewport render mode (Hidden Line, Gouraud, …) still applies. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
1 parent
dac835fe33
commit
600717c1ec
1 file changed
+19
-1
+19
-1
@@ -4644,12 +4644,30 @@ impl Scene {
|
||||
) else {
|
||||
continue;
|
||||
};
|
||||
let is_active = self.active_viewport == Some(h);
|
||||
// Skip the GPU pass for inactive viewports whose screen rect
|
||||
// extends beyond the canvas — the per-viewport pipeline blits
|
||||
// the full MSAA at a u32-saturated (≥0) surface offset, so a
|
||||
// negative offset would paint the content at the canvas
|
||||
// corner instead of where the viewport actually sits. The CPU
|
||||
// projection in PaperCanvas already handles those correctly
|
||||
// clipped to the canvas, so the user simply sees that copy.
|
||||
// The active viewport always renders through the GPU so its
|
||||
// own render mode (Hidden Line, Gouraud, …) still applies.
|
||||
if !is_active
|
||||
&& (screen_rect.x < 0.0
|
||||
|| screen_rect.y < 0.0
|
||||
|| screen_rect.x + screen_rect.width > canvas_w
|
||||
|| screen_rect.y + screen_rect.height > canvas_h)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
out.push(ViewportInstance {
|
||||
handle: h,
|
||||
screen_rect,
|
||||
camera,
|
||||
render_mode: vp.render_mode,
|
||||
active: self.active_viewport == Some(h),
|
||||
active: is_active,
|
||||
});
|
||||
}
|
||||
out
|
||||
|
||||
Reference in new issue
Block a user