Viewer: reciprocal-space view does nothing while its window is closed

The window is a placeholder for future functionality and is closed almost all
of the time, but it extracted the frame's spots and rebuilt and uploaded its
vertex arrays on every image, whether or not anything was on screen.

Guard it in rebuildGL() rather than at each of the eight call sites, so any
future caller inherits the behaviour: while hidden it only records that a
rebuild is owed, and showEvent() pays it. imageLoaded() additionally skips
extracting the frame's spots, which is the other half of the per-frame work.

The OpenGL code path is untouched and still built and exercised the moment the
window is opened.

Note: I could not show a CPU saving for this on the headless test machine --
there, ~74% of the process CPU is Mesa llvmpipe software rasterisation that I
was unable to attribute to any per-frame code path, and it swamps the effect.
The work being skipped is nonetheless unambiguously unnecessary.

Verified in the GUI: after stepping frames with the window closed, opening it
shows the current frame's spots, and it keeps updating while open.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-26 21:05:21 +02:00
co-authored by Claude Opus 5
parent 6d1af4921f
commit 9aa19f021c
2 changed files with 34 additions and 0 deletions
@@ -472,6 +472,12 @@ void JFJochViewerReciprocalSpaceWindow::imageLoaded(std::shared_ptr<const JFJoch
if (full_dataset_mode_)
return;
// Closed: skip extracting this frame's spots as well, not just the GL rebuild.
if (!isVisible()) {
pending_rebuild_ = true;
return;
}
loadCurrentImageSpots(current_image_);
rebuildGL();
}
@@ -619,6 +625,29 @@ QColor JFJochViewerReciprocalSpaceWindow::spotColorFor(bool indexed,
}
void JFJochViewerReciprocalSpaceWindow::rebuildGL() {
// The reciprocal-space view is a gadget that is closed almost all of the time. Building the
// vertex arrays and pushing them to the GL view is real work on every frame, and nobody is
// looking at the result, so note that a rebuild is owed and do it when the window is shown.
if (!isVisible()) {
pending_rebuild_ = true;
return;
}
pending_rebuild_ = false;
rebuildGLNow();
}
void JFJochViewerReciprocalSpaceWindow::showEvent(QShowEvent *event) {
JFJochHelperWindow::showEvent(event);
if (!pending_rebuild_)
return;
pending_rebuild_ = false;
// Spots for the current frame were not extracted while the window was closed either.
if (!full_dataset_mode_)
loadCurrentImageSpots(current_image_);
rebuildGLNow();
}
void JFJochViewerReciprocalSpaceWindow::rebuildGLNow() {
const bool crystal_frame = crystalFrameCheck->isChecked() && has_rotation_;
std::optional<CrystalLattice> plot_lattice;
@@ -143,7 +143,12 @@ private:
};
QColor spotColorFor(bool indexed, bool ice_ring) const;
// rebuildGL() is a no-op while the window is closed - it only records that a rebuild is
// owed, and showEvent() pays it. rebuildGLNow() is the actual work.
void rebuildGL(); // rebuilds both spot and line vertex data
void rebuildGLNow();
void showEvent(QShowEvent *event) override;
bool pending_rebuild_ = false;
void loadCurrentImageSpots(std::shared_ptr<const JFJochReaderImage> image);
void addSpot(const SpotToSave &s,
const DiffractionGeometry &geom,