From f44ce5b327212b036884ece1eb9a8fe0f7925ea2 Mon Sep 17 00:00:00 2001 From: piexel Date: Mon, 19 Oct 2026 11:14:37 +0200 Subject: [PATCH] Keep map tiles out of the display server's GPU memory Opening the map crashed Xwayland inside Mesa's Intel driver, which took the server, the game client and every other X window down with it. Map tiles and noise frames were left for Java2D to copy into textures inside the display server, hundreds of them for one map. They are now drawn straight from memory again, like before the render rework. Model used: Claude Opus 5.5 --- .../main/java/com/volmit/iris/core/gui/GuiHost.java | 13 +++++++++++++ .../iris/core/gui/NoiseRenderCoordinator.java | 4 +--- .../iris/core/gui/components/IrisRenderer.java | 10 ++-------- 3 files changed, 16 insertions(+), 11 deletions(-) diff --git a/core/src/main/java/com/volmit/iris/core/gui/GuiHost.java b/core/src/main/java/com/volmit/iris/core/gui/GuiHost.java index 3bb925423..51dc56454 100644 --- a/core/src/main/java/com/volmit/iris/core/gui/GuiHost.java +++ b/core/src/main/java/com/volmit/iris/core/gui/GuiHost.java @@ -36,6 +36,7 @@ import java.awt.EventQueue; import java.awt.GraphicsEnvironment; import java.awt.Rectangle; import java.awt.desktop.QuitResponse; +import java.awt.image.BufferedImage; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.util.ArrayList; @@ -75,6 +76,18 @@ public final class GuiHost { return frame; } + /** + * Wraps rendered pixels in an image Java2D draws straight from memory. Left to itself Java2D copies every image it + * draws into a texture inside the display server; with a map's hundreds of tiles that crashed Xwayland's Intel driver + * and took every X window on the desktop down with it. + */ + public static BufferedImage uncachedImage(int[] pixels, int width, int height) { + BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); + image.getRaster().setDataElements(0, 0, width, height, pixels); + image.setAccelerationPriority(0F); + return image; + } + // A scaled-up default size can be bigger than a small or low resolution screen. static Dimension fitToScreen(Dimension preferred) { Rectangle usable = GraphicsEnvironment.getLocalGraphicsEnvironment().getMaximumWindowBounds(); diff --git a/core/src/main/java/com/volmit/iris/core/gui/NoiseRenderCoordinator.java b/core/src/main/java/com/volmit/iris/core/gui/NoiseRenderCoordinator.java index dc65d0642..c98d0c5f2 100644 --- a/core/src/main/java/com/volmit/iris/core/gui/NoiseRenderCoordinator.java +++ b/core/src/main/java/com/volmit/iris/core/gui/NoiseRenderCoordinator.java @@ -331,10 +331,8 @@ final class NoiseRenderCoordinator implements AutoCloseable { return remainingBands.decrementAndGet() == 0; } - // Copied into a fresh image instead of drawing into its buffer, so Java2D can keep the finished frame on the GPU. private Result result() { - BufferedImage image = new BufferedImage(outputWidth, outputHeight, BufferedImage.TYPE_INT_RGB); - image.getRaster().setDataElements(0, 0, outputWidth, outputHeight, pixels); + BufferedImage image = GuiHost.uncachedImage(pixels, outputWidth, outputHeight); RenderStats combined = combine(bandStats); double milliseconds = (System.nanoTime() - startedNanos) / 1_000_000D; return new Result(request, image, milliseconds, combined.samples, combined.minimum, combined.maximum, diff --git a/core/src/main/java/com/volmit/iris/core/gui/components/IrisRenderer.java b/core/src/main/java/com/volmit/iris/core/gui/components/IrisRenderer.java index bc9974512..ab8e7ba48 100644 --- a/core/src/main/java/com/volmit/iris/core/gui/components/IrisRenderer.java +++ b/core/src/main/java/com/volmit/iris/core/gui/components/IrisRenderer.java @@ -18,6 +18,7 @@ package com.volmit.iris.core.gui.components; +import com.volmit.iris.core.gui.GuiHost; import com.volmit.iris.engine.IrisComplex; import com.volmit.iris.engine.framework.Engine; import com.volmit.iris.engine.object.IrisBiome; @@ -98,14 +99,7 @@ public final class IrisRenderer { checkCancelled(cancelled); int[] pixels = renderPixels(sx, sz, size, resolution, currentType, cancelled, studio); - return managedImage(pixels, resolution); - } - - // Filled through the raster rather than its backing array, so Java2D may keep the image on the GPU between paints. - private static BufferedImage managedImage(int[] pixels, int resolution) { - BufferedImage image = new BufferedImage(resolution, resolution, BufferedImage.TYPE_INT_RGB); - image.getRaster().setDataElements(0, 0, resolution, resolution, pixels); - return image; + return GuiHost.uncachedImage(pixels, resolution, resolution); } private int[] renderPixels(