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(