From 6e3d30e41be915193874455411a0866d26dc1aca Mon Sep 17 00:00:00 2001 From: Jonas Herzig Date: Sun, 17 Jul 2022 16:28:56 +0200 Subject: [PATCH] Fix thread unsafety in OpenGlToBitmapProcessor Sharing the temporary `row` and `rowSwap` buffers between different calls to the processor is not safe because it will be used by multiple threads. As a result some of the rows in the image could randomly get corrupted. This commit gets rid of the cached buffers (the value of which questionable anyway) and simply re-uses the same code which other processors use. --- .../processor/OpenGlToBitmapProcessor.java | 37 +++++-------------- 1 file changed, 10 insertions(+), 27 deletions(-) diff --git a/src/main/java/com/replaymod/render/processor/OpenGlToBitmapProcessor.java b/src/main/java/com/replaymod/render/processor/OpenGlToBitmapProcessor.java index 6cb60f5e..8740716d 100644 --- a/src/main/java/com/replaymod/render/processor/OpenGlToBitmapProcessor.java +++ b/src/main/java/com/replaymod/render/processor/OpenGlToBitmapProcessor.java @@ -2,42 +2,25 @@ package com.replaymod.render.processor; import com.replaymod.render.frame.OpenGlFrame; import com.replaymod.render.frame.BitmapFrame; +import com.replaymod.render.utils.ByteBufferPool; +import de.johni0702.minecraft.gui.utils.lwjgl.Dimension; import de.johni0702.minecraft.gui.utils.lwjgl.ReadableDimension; import java.nio.ByteBuffer; -public class OpenGlToBitmapProcessor extends AbstractFrameProcessor { +import static com.replaymod.render.utils.Utils.openGlBytesToBitmap; - private byte[] row, rowSwap; +public class OpenGlToBitmapProcessor extends AbstractFrameProcessor { @Override public BitmapFrame process(OpenGlFrame rawFrame) { - // Flip whole image in place - ReadableDimension size = rawFrame.getSize(); + int width = size.getWidth(); + int height = size.getHeight(); int bpp = rawFrame.getBytesPerPixel(); - int rowSize = size.getWidth() * bpp; - if (row == null || row.length < rowSize) { - row = new byte[rowSize]; - rowSwap = new byte[rowSize]; - } - ByteBuffer buffer = rawFrame.getByteBuffer(); - int rows = size.getHeight(); - byte[] row = this.row; - byte[] rowSwap = this.rowSwap; - for (int i = 0; i < rows / 2; i++) { - int from = rowSize * i; - int to = rowSize * (rows - i - 1); - buffer.position(from); - buffer.get(row); - buffer.position(to); - buffer.get(rowSwap); - buffer.position(to); - buffer.put(row); - buffer.position(from); - buffer.put(rowSwap); - } - buffer.rewind(); - return new BitmapFrame(rawFrame.getFrameId(), size, bpp, buffer); + ByteBuffer result = ByteBufferPool.allocate(width * height * bpp); + openGlBytesToBitmap(rawFrame, 0, 0, result, width); + ByteBufferPool.release(rawFrame.getByteBuffer()); + return new BitmapFrame(rawFrame.getFrameId(), new Dimension(width, height), bpp, result); } }