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.
This commit is contained in:
Jonas Herzig
2022-07-17 16:28:56 +02:00
parent 633ac10d89
commit 6e3d30e41b

View File

@@ -2,42 +2,25 @@ package com.replaymod.render.processor;
import com.replaymod.render.frame.OpenGlFrame; import com.replaymod.render.frame.OpenGlFrame;
import com.replaymod.render.frame.BitmapFrame; 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 de.johni0702.minecraft.gui.utils.lwjgl.ReadableDimension;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
public class OpenGlToBitmapProcessor extends AbstractFrameProcessor<OpenGlFrame, BitmapFrame> { import static com.replaymod.render.utils.Utils.openGlBytesToBitmap;
private byte[] row, rowSwap; public class OpenGlToBitmapProcessor extends AbstractFrameProcessor<OpenGlFrame, BitmapFrame> {
@Override @Override
public BitmapFrame process(OpenGlFrame rawFrame) { public BitmapFrame process(OpenGlFrame rawFrame) {
// Flip whole image in place
ReadableDimension size = rawFrame.getSize(); ReadableDimension size = rawFrame.getSize();
int width = size.getWidth();
int height = size.getHeight();
int bpp = rawFrame.getBytesPerPixel(); int bpp = rawFrame.getBytesPerPixel();
int rowSize = size.getWidth() * bpp; ByteBuffer result = ByteBufferPool.allocate(width * height * bpp);
if (row == null || row.length < rowSize) { openGlBytesToBitmap(rawFrame, 0, 0, result, width);
row = new byte[rowSize]; ByteBufferPool.release(rawFrame.getByteBuffer());
rowSwap = new byte[rowSize]; return new BitmapFrame(rawFrame.getFrameId(), new Dimension(width, height), bpp, result);
}
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);
} }
} }