diff --git a/runelite-client/src/main/java/net/runelite/client/callback/Hooks.java b/runelite-client/src/main/java/net/runelite/client/callback/Hooks.java index f1f3b1b319..ac08796bd9 100644 --- a/runelite-client/src/main/java/net/runelite/client/callback/Hooks.java +++ b/runelite-client/src/main/java/net/runelite/client/callback/Hooks.java @@ -30,12 +30,15 @@ import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Graphics2D; +import java.awt.GraphicsConfiguration; +import java.awt.Image; import java.awt.RenderingHints; import java.awt.event.FocusEvent; import java.awt.event.KeyEvent; import java.awt.event.MouseEvent; import java.awt.event.MouseWheelEvent; import java.awt.image.BufferedImage; +import java.awt.image.VolatileImage; import net.runelite.api.Actor; import net.runelite.api.ChatMessageType; import net.runelite.api.Client; @@ -72,6 +75,7 @@ import net.runelite.client.chat.ChatMessageManager; import net.runelite.client.input.KeyManager; import net.runelite.client.input.MouseManager; import net.runelite.client.task.Scheduler; +import net.runelite.client.ui.ClientUI; import net.runelite.client.ui.DrawManager; import net.runelite.client.ui.overlay.OverlayLayer; import net.runelite.client.ui.overlay.OverlayRenderer; @@ -102,9 +106,10 @@ public class Hooks private static final GameTick tick = new GameTick(); private static final DrawManager renderHooks = injector.getInstance(DrawManager.class); private static final Notifier notifier = injector.getInstance(Notifier.class); + private static final ClientUI clientUi = injector.getInstance(ClientUI.class); private static Dimension lastStretchedDimensions; - private static BufferedImage stretchedImage; + private static VolatileImage stretchedImage; private static Graphics2D stretchedGraphics; private static long lastCheck; @@ -264,7 +269,7 @@ public class Hooks return; } - BufferedImage image = (BufferedImage) mainBufferProvider.getImage(); + Image image = mainBufferProvider.getImage(); final Graphics2D graphics2d = (Graphics2D) image.getGraphics(); try @@ -281,14 +286,16 @@ public class Hooks // Stretch the game image if the user has that enabled if (!client.isResized() && client.isStretchedEnabled()) { + GraphicsConfiguration gc = clientUi.getGraphicsConfiguration(); Dimension stretchedDimensions = client.getStretchedDimensions(); - if (lastStretchedDimensions == null || !lastStretchedDimensions.equals(stretchedDimensions)) + if (lastStretchedDimensions == null || !lastStretchedDimensions.equals(stretchedDimensions) + || (stretchedImage != null && stretchedImage.validate(gc) == VolatileImage.IMAGE_INCOMPATIBLE)) { /* Reuse the resulting image instance to avoid creating an extreme amount of objects */ - stretchedImage = new BufferedImage(stretchedDimensions.width, stretchedDimensions.height, BufferedImage.TYPE_INT_RGB); + stretchedImage = gc.createCompatibleVolatileImage(stretchedDimensions.width, stretchedDimensions.height); if (stretchedGraphics != null) { diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/fps/FpsDrawListener.java b/runelite-client/src/main/java/net/runelite/client/plugins/fps/FpsDrawListener.java index 1deade0ea7..8c9957f739 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/fps/FpsDrawListener.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/fps/FpsDrawListener.java @@ -24,7 +24,7 @@ */ package net.runelite.client.plugins.fps; -import java.awt.image.BufferedImage; +import java.awt.Image; import java.util.function.Consumer; import javax.inject.Inject; import net.runelite.api.events.FocusChanged; @@ -42,7 +42,7 @@ import net.runelite.api.events.FocusChanged; * Enforcing FPS in the draw code does not impact the client engine's ability to run including its audio, * even when forced to 1 FPS with this plugin. */ -public class FpsDrawListener implements Consumer +public class FpsDrawListener implements Consumer { private static final int SAMPLE_SIZE = 4; @@ -90,7 +90,7 @@ public class FpsDrawListener implements Consumer } @Override - public void accept(BufferedImage bufferedImage) + public void accept(Image image) { if (!isEnforced()) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/screenshot/ScreenshotOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/screenshot/ScreenshotOverlay.java index ff08300e3c..69357d5bdb 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/screenshot/ScreenshotOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/screenshot/ScreenshotOverlay.java @@ -29,6 +29,7 @@ import java.awt.Color; import java.awt.Dimension; import java.awt.FontMetrics; import java.awt.Graphics2D; +import java.awt.Image; import java.awt.image.BufferedImage; import java.io.IOException; import java.text.DateFormat; @@ -74,7 +75,7 @@ public class ScreenshotOverlay extends Overlay private final Client client; private final DrawManager drawManager; - private final Queue> consumers = new ConcurrentLinkedQueue<>(); + private final Queue> consumers = new ConcurrentLinkedQueue<>(); @Inject public ScreenshotOverlay(Client client, DrawManager drawManager) @@ -118,7 +119,7 @@ public class ScreenshotOverlay extends Overlay // Request the queued screenshots to be taken, // now that the timestamp is visible. - Consumer consumer; + Consumer consumer; while ((consumer = consumers.poll()) != null) { drawManager.requestNextFrameListener(consumer); @@ -127,7 +128,7 @@ public class ScreenshotOverlay extends Overlay return null; } - public void queueForTimestamp(Consumer screenshotConsumer) + public void queueForTimestamp(Consumer screenshotConsumer) { if (REPORT_BUTTON == null) { diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/screenshot/ScreenshotPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/screenshot/ScreenshotPlugin.java index 3d9c3668a9..6034d6bc7b 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/screenshot/ScreenshotPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/screenshot/ScreenshotPlugin.java @@ -30,6 +30,7 @@ import com.google.common.eventbus.Subscribe; import com.google.inject.Provides; import java.awt.Desktop; import java.awt.Graphics; +import java.awt.Image; import java.awt.Toolkit; import java.awt.TrayIcon; import java.awt.datatransfer.Clipboard; @@ -409,11 +410,11 @@ public class ScreenshotPlugin extends Plugin return; } - Consumer screenshotConsumer = image -> + Consumer screenshotConsumer = image -> { BufferedImage screenshot = config.includeFrame() ? new BufferedImage(clientUi.getWidth(), clientUi.getHeight(), BufferedImage.TYPE_INT_ARGB) - : new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_INT_ARGB); + : new BufferedImage(image.getWidth(null), image.getHeight(null), BufferedImage.TYPE_INT_ARGB); Graphics graphics = screenshot.getGraphics(); diff --git a/runelite-client/src/main/java/net/runelite/client/ui/ClientUI.java b/runelite-client/src/main/java/net/runelite/client/ui/ClientUI.java index e67f79adc0..a572da7e5a 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/ClientUI.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/ClientUI.java @@ -34,6 +34,7 @@ import java.awt.Container; import java.awt.Cursor; import java.awt.Dimension; import java.awt.Graphics; +import java.awt.GraphicsConfiguration; import java.awt.LayoutManager; import java.awt.Rectangle; import java.awt.TrayIcon; @@ -582,6 +583,11 @@ public class ClientUI return new Point(0, 0); } + public GraphicsConfiguration getGraphicsConfiguration() + { + return frame.getGraphicsConfiguration(); + } + void toggleSidebar() { // Toggle sidebar open diff --git a/runelite-client/src/main/java/net/runelite/client/ui/DrawManager.java b/runelite-client/src/main/java/net/runelite/client/ui/DrawManager.java index 80dd22b8ea..fc31d90696 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/DrawManager.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/DrawManager.java @@ -24,7 +24,7 @@ */ package net.runelite.client.ui; -import java.awt.image.BufferedImage; +import java.awt.Image; import java.util.List; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; @@ -37,10 +37,10 @@ import lombok.extern.slf4j.Slf4j; @Slf4j public class DrawManager { - private final List> everyFrame = new CopyOnWriteArrayList<>(); - private final Queue> nextFrame = new ConcurrentLinkedQueue<>(); + private final List> everyFrame = new CopyOnWriteArrayList<>(); + private final Queue> nextFrame = new ConcurrentLinkedQueue<>(); - public void registerEveryFrameListener(Consumer everyFrameListener) + public void registerEveryFrameListener(Consumer everyFrameListener) { if (!everyFrame.contains(everyFrameListener)) { @@ -48,19 +48,19 @@ public class DrawManager } } - public void unregisterEveryFrameListener(Consumer everyFrameListener) + public void unregisterEveryFrameListener(Consumer everyFrameListener) { everyFrame.remove(everyFrameListener); } - public void requestNextFrameListener(Consumer nextFrameListener) + public void requestNextFrameListener(Consumer nextFrameListener) { nextFrame.add(nextFrameListener); } - public void processDrawComplete(BufferedImage image) + public void processDrawComplete(Image image) { - for (Consumer everyFrameListener : everyFrame) + for (Consumer everyFrameListener : everyFrame) { try { @@ -72,7 +72,7 @@ public class DrawManager } } - Consumer nextFrameListener = nextFrame.poll(); + Consumer nextFrameListener = nextFrame.poll(); while (nextFrameListener != null) { try