diff --git a/crates/qbz-qt/qml/cards/PlaylistCollage.qml b/crates/qbz-qt/qml/cards/PlaylistCollage.qml index cb1436b69..f198028fe 100644 --- a/crates/qbz-qt/qml/cards/PlaylistCollage.qml +++ b/crates/qbz-qt/qml/cards/PlaylistCollage.qml @@ -135,7 +135,10 @@ Item { id: canvas anchors.fill: parent renderTarget: Canvas.Image - renderStrategy: Canvas.Cooperative + // See RoundedImage.qml: GUI-thread raster. This canvas repaints from + // libraryArtworkReady and from four async image probes, on a card the + // feed recycles. + renderStrategy: Canvas.Immediate // Dimension probes: Canvas cannot query a loaded image's intrinsic // size and the crop fit needs it (RoundedImage's pattern, one per diff --git a/crates/qbz-qt/qml/shell/AmbientField.qml b/crates/qbz-qt/qml/shell/AmbientField.qml index 5dff24c58..7391fbdc6 100644 --- a/crates/qbz-qt/qml/shell/AmbientField.qml +++ b/crates/qbz-qt/qml/shell/AmbientField.qml @@ -45,7 +45,10 @@ Canvas { : true renderTarget: Canvas.Image - renderStrategy: Canvas.Cooperative + // See RoundedImage.qml. This one repaints 30x/s for the whole window + // lifetime, so it is the canvas most likely to be mid-raster when another + // is torn down on the same render thread. + renderStrategy: Canvas.Immediate // The shader clock (t = time * 0.75). Accumulated at ~30fps. property real t: Math.random() * 40.0 diff --git a/crates/qbz-qt/qml/theme/RoundedImage.qml b/crates/qbz-qt/qml/theme/RoundedImage.qml index 429905ff4..bccc26eea 100644 --- a/crates/qbz-qt/qml/theme/RoundedImage.qml +++ b/crates/qbz-qt/qml/theme/RoundedImage.qml @@ -25,7 +25,13 @@ Canvas { property string fit: "crop" renderTarget: Canvas.Image - renderStrategy: Canvas.Cooperative + // GUI-thread raster. Cooperative/Threaded rasterize on the SCENE GRAPH + // RENDER THREAD, and this item is created and destroyed by list recycling + // while async artwork callbacks schedule repaints — the render thread can + // be mid-draw on a pixmap whose Canvas is already gone. Immediate keeps + // paint and destruction on one thread. renderTarget: Image already meant + // CPU raster, so this costs no visual change. + renderStrategy: Canvas.Immediate // Dimension probe: Canvas can't query the loaded image's intrinsic // size, and PreserveAspectCrop needs it. A hidden Image doubles as