From 83fe4805acd2e70ef27abd958b29640bb4787ed4 Mon Sep 17 00:00:00 2001 From: downthecrop Date: Sat, 26 Oct 2024 09:59:25 -0700 Subject: [PATCH] GC issues + some late invokes --- client/src/main/java/rt4/GlRenderer.java | 35 ++++- .../src/main/kotlin/KondoKit/plugin.kt | 144 +++++++++--------- 2 files changed, 99 insertions(+), 80 deletions(-) diff --git a/client/src/main/java/rt4/GlRenderer.java b/client/src/main/java/rt4/GlRenderer.java index 3ad7392..3f564b3 100644 --- a/client/src/main/java/rt4/GlRenderer.java +++ b/client/src/main/java/rt4/GlRenderer.java @@ -9,6 +9,7 @@ import org.openrs2.deob.annotation.OriginalMember; import org.openrs2.deob.annotation.Pc; import java.awt.*; +import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.IntBuffer; import java.nio.charset.StandardCharsets; @@ -24,7 +25,10 @@ public final class GlRenderer { public static float hFOV = 0; - public static int[] pixelData = null; + + private static ByteBuffer pixelByteBuffer; + private static IntBuffer pixelIntBuffer; + public static int[] pixelData; @OriginalMember(owner = "client!tf", name = "c", descriptor = "F") private static float aFloat30; @@ -201,18 +205,33 @@ public final class GlRenderer { @OriginalMember(owner = "client!tf", name = "d", descriptor = "()V") public static void swapBuffers() { try { - pixelData = readPixels(); + readPixels(); drawable.swapBuffers(); } catch (@Pc(3) Exception local3) { } } - @OriginalMember(owner = "client!tf", name = "readPixels", descriptor = "()int[]") - public static int[] readPixels() { - int[] pixels = new int[canvasWidth * canvasHeight]; - IntBuffer buffer = IntBuffer.wrap(pixels); - gl.glReadPixels(0, 0, canvasWidth, canvasHeight, GL2.GL_BGRA, GlRenderer.bigEndian ? GL2.GL_UNSIGNED_INT_8_8_8_8_REV : GL2.GL_UNSIGNED_BYTE, buffer); - return pixels; + public static void initializePixelBuffer(int width, int height) { + // Allocate ByteBuffer for BGRA pixels (4 bytes per pixel) + pixelByteBuffer = ByteBuffer.allocateDirect(width * height * 4).order(ByteOrder.nativeOrder()); + pixelIntBuffer = pixelByteBuffer.asIntBuffer(); + pixelData = new int[width * height]; + } + + public static void readPixels() { + // Ensure the pixel buffer is initialized with the correct size + if (pixelByteBuffer == null || pixelIntBuffer.capacity() != canvasWidth * canvasHeight) { + initializePixelBuffer(canvasWidth, canvasHeight); + } + + // Read pixels into the direct ByteBuffer + gl.glReadPixels(0, 0, canvasWidth, canvasHeight, GL2.GL_BGRA, + GlRenderer.bigEndian ? GL2.GL_UNSIGNED_INT_8_8_8_8_REV : GL2.GL_UNSIGNED_BYTE, + pixelByteBuffer); + + // Convert to int array if needed + pixelIntBuffer.rewind(); // Prepare the IntBuffer for reading + pixelIntBuffer.get(pixelData, 0, pixelData.length); // Transfer to pixelData array if necessary } @OriginalMember(owner = "client!tf", name = "a", descriptor = "(Z)V") diff --git a/plugin-playground/src/main/kotlin/KondoKit/plugin.kt b/plugin-playground/src/main/kotlin/KondoKit/plugin.kt index fe6f249..ea53905 100644 --- a/plugin-playground/src/main/kotlin/KondoKit/plugin.kt +++ b/plugin-playground/src/main/kotlin/KondoKit/plugin.kt @@ -150,6 +150,8 @@ class plugin : Plugin() { class AltCanvas : Canvas() { private var gameImage: VolatileImage? = null + private var flippedPixels: IntArray? = null + private var bufferImage: BufferedImage? = null private var scaleX = 1.0 private var scaleY = 1.0 private var offsetX = 0 @@ -158,6 +160,8 @@ class plugin : Plugin() { init { validateGameImage() + isFocusable = true + requestFocusInWindow() addMouseListener(object : MouseAdapter() { override fun mousePressed(e: MouseEvent) { @@ -212,6 +216,11 @@ class plugin : Plugin() { paint(g) } + override fun addNotify() { + super.addNotify() + //createBufferStrategy(2) // Double buffering for V-Sync, called only after the peer is created + } + private fun validateGameImage() { val gc = GraphicsEnvironment.getLocalGraphicsEnvironment().defaultScreenDevice.defaultConfiguration if (gameImage == null) { @@ -294,6 +303,9 @@ class plugin : Plugin() { val x = offsetX val y = offsetY g2d.drawImage(image, x, y, drawWidth, drawHeight, null) + g2d.dispose() + //bufferStrategy.show() // Shows the buffer with V-Sync enabled + Toolkit.getDefaultToolkit().sync() // Ensures V-Sync on some systems } } @@ -322,30 +334,27 @@ class plugin : Plugin() { repaint() } private fun renderGlRaster() { - val pixels = GlRenderer.pixelData // Assuming this holds the int[] BGRA pixel data from GlRenderer.readPixels() - val width = gameImage!!.width - val height = gameImage!!.height - - // Create a BufferedImage with the same dimensions as the gameImage - val bufferedImage = BufferedImage(width, height, BufferedImage.TYPE_INT_BGR) - - // Flip the image vertically by reversing the rows - val flippedPixels = IntArray(width * height) - for (y in 0 until height) { - // Calculate the source row (bottom to top) - val srcY = height - 1 - y - System.arraycopy(pixels, srcY * width, flippedPixels, y * width, width) + if (flippedPixels == null || flippedPixels!!.size != gameImage!!.width * gameImage!!.height) { + flippedPixels = IntArray(gameImage!!.width * gameImage!!.height) } - // Set the flipped pixel data into the BufferedImage - bufferedImage.setRGB(0, 0, width, height, flippedPixels, 0, width) + // Initialize bufferImage only once and reuse it + if (bufferImage == null || bufferImage!!.width != gameImage!!.width || bufferImage!!.height != gameImage!!.height) { + bufferImage = BufferedImage(gameImage!!.width, gameImage!!.height, BufferedImage.TYPE_INT_BGR) + } - // Draw the BufferedImage onto the VolatileImage - val g = gameImage!!.createGraphics() - try { - g.drawImage(bufferedImage, 0, 0, null) - } finally { - g.dispose() + val width = gameImage!!.width + val height = gameImage!!.height + val pixels = GlRenderer.pixelData // Retrieve BGRA pixel data + for (y in 0 until height) { + System.arraycopy(pixels, (height - 1 - y) * width, flippedPixels, y * width, width) + } + + bufferImage!!.setRGB(0, 0, width, height, flippedPixels, 0, width) + + gameImage?.createGraphics()?.apply { + drawImage(bufferImage, 0, 0, null) + dispose() } } @@ -404,9 +413,7 @@ class plugin : Plugin() { rightPanelWrapper?.preferredSize = Dimension(currentScrollPaneWidth, frame.height) rightPanelWrapper?.let { it.isDoubleBuffered = true } rightPanelWrapper?.revalidate() - SwingUtilities.invokeLater { - rightPanelWrapper?.repaint() - } + rightPanelWrapper?.repaint() } fun OnKondoValueUpdated(){ @@ -462,9 +469,7 @@ class plugin : Plugin() { override fun OnPluginsReloaded(): Boolean { if (!initialized) return true - UpdateDisplaySettings() - frame.remove(rightPanelWrapper) frame.layout = BorderLayout() frame.add(rightPanelWrapper, BorderLayout.EAST) @@ -475,32 +480,31 @@ class plugin : Plugin() { } override fun OnXPUpdate(skillId: Int, xp: Int) { - if (!initialXP.containsKey(skillId)) { - initialXP[skillId] = xp - return - } + SwingUtilities.invokeLater{ + if (!initialXP.containsKey(skillId)) { + initialXP[skillId] = xp + return@invokeLater + } + var xpWidget = xpWidgets[skillId] + if (xpWidget != null) { + updateWidget(xpWidget, xp) + } else { + val previousXp = initialXP[skillId] ?: xp + if (xp == initialXP[skillId]) return@invokeLater - var xpWidget = xpWidgets[skillId] + xpWidget = createXPWidget(skillId, previousXp) + xpWidgets[skillId] = xpWidget - if (xpWidget != null) { - updateWidget(xpWidget, xp) - } else { - val previousXp = initialXP[skillId] ?: xp - if (xp == initialXP[skillId]) return + xpTrackerView?.add(wrappedWidget(xpWidget.container)) + xpTrackerView?.add(Box.createVerticalStrut(5)) - xpWidget = createXPWidget(skillId, previousXp) - xpWidgets[skillId] = xpWidget - - xpTrackerView?.add(wrappedWidget(xpWidget.container)) - xpTrackerView?.add(Box.createVerticalStrut(5)) - - xpTrackerView?.revalidate() - if(focusedView == XPTrackerView.VIEW_NAME) - SwingUtilities.invokeLater { + if(focusedView == XPTrackerView.VIEW_NAME) { + xpTrackerView?.revalidate() xpTrackerView?.repaint() } - updateWidget(xpWidget, xp) + updateWidget(xpWidget, xp) + } } } @@ -545,16 +549,19 @@ class plugin : Plugin() { override fun LateDraw(timeDelta: Long){ if(!initialized) return - SwingUtilities.invokeLater { - if (GetWindowMode() == WindowMode.FIXED) { - if (canvas.parent !== hiddenFrame?.contentPane) { - println("Moving canvas to hidden frame") - initializeHiddenFrame() - frame.remove(canvas) // Remove from main frame if necessary - hiddenFrame?.contentPane?.add(canvas) - hiddenFrame?.pack() + if (GetWindowMode() == WindowMode.FIXED) { + if (canvas.parent !== hiddenFrame?.contentPane) { + if(altCanvas?.parent != frame) { + frame.add(altCanvas) } + println("Moving canvas to hidden frame") + initializeHiddenFrame() + frame.remove(canvas) // Remove from main frame if necessary + hiddenFrame?.contentPane?.add(canvas) + hiddenFrame?.pack() } + } else { + frame.remove(altCanvas) } altCanvas?.updateGameImage() // Update the game image as needed } @@ -716,9 +723,9 @@ class plugin : Plugin() { val elapsedTime = (System.currentTimeMillis() - xpWidget.startTime) / 1000.0 / 60.0 / 60.0 val xpPerHour = if (elapsedTime > 0) (xpWidget.totalXpGained / elapsedTime).toInt() else 0 val formattedXpPerHour = formatNumber(xpPerHour) - xpWidget.xpPerHourLabel.text = - formatHtmlLabelText("XP /hr: ", primaryColor, formattedXpPerHour, secondaryColor) SwingUtilities.invokeLater{ + xpWidget.xpPerHourLabel.text = + formatHtmlLabelText("XP /hr: ", primaryColor, formattedXpPerHour, secondaryColor) xpWidget.container.repaint() } } @@ -727,9 +734,9 @@ class plugin : Plugin() { val elapsedTime = (System.currentTimeMillis() - totalXPWidget.startTime) / 1000.0 / 60.0 / 60.0 val totalXPPerHour = if (elapsedTime > 0) (totalXPWidget.totalXpGained / elapsedTime).toInt() else 0 val formattedTotalXpPerHour = formatNumber(totalXPPerHour) - totalXPWidget.xpPerHourLabel.text = - formatHtmlLabelText("XP /hr: ", primaryColor, formattedTotalXpPerHour, secondaryColor) SwingUtilities.invokeLater{ + totalXPWidget.xpPerHourLabel.text = + formatHtmlLabelText("XP /hr: ", primaryColor, formattedTotalXpPerHour, secondaryColor) totalXPWidget.container.repaint() } } @@ -759,11 +766,9 @@ class plugin : Plugin() { rightPanelWrapper?.revalidate() frame?.revalidate() - SwingUtilities.invokeLater{ - mainContentPanel.repaint() - rightPanelWrapper?.repaint() - frame?.repaint() - } + mainContentPanel.repaint() + rightPanelWrapper?.repaint() + frame?.repaint() focusedView = viewName } @@ -826,20 +831,15 @@ class plugin : Plugin() { override fun mouseEntered(e: MouseEvent?) { background = WIDGET_COLOR.darker() imageCanvas.fillColor = WIDGET_COLOR.darker() - SwingUtilities.invokeLater{ - imageCanvas.repaint() - repaint() - } + imageCanvas.repaint() + repaint() } override fun mouseExited(e: MouseEvent?) { background = WIDGET_COLOR imageCanvas.fillColor = WIDGET_COLOR - SwingUtilities.invokeLater{ - imageCanvas.repaint() - repaint() - } - + imageCanvas.repaint() + repaint() } override fun mouseClicked(e: MouseEvent?) {