Separate rendering into its own module

This commit is contained in:
johni0702
2016-06-14 17:01:32 +02:00
parent 65cfdd13ec
commit 25582b6a51
68 changed files with 1822 additions and 2635 deletions

View File

@@ -0,0 +1,48 @@
package com.replaymod.render.utils;
import com.google.common.collect.Maps;
import org.lwjgl.BufferUtils;
import java.lang.ref.SoftReference;
import java.nio.ByteBuffer;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
public class ByteBufferPool {
private static Map<Integer, List<SoftReference<ByteBuffer>>> bufferPool = Maps.newHashMap();
public static synchronized ByteBuffer allocate(int size) {
List<SoftReference<ByteBuffer>> available = bufferPool.get(size);
if (available != null) {
Iterator<SoftReference<ByteBuffer>> iter = available.iterator();
try {
while (iter.hasNext()) {
SoftReference<ByteBuffer> reference = iter.next();
ByteBuffer buffer = reference.get();
iter.remove();
if (buffer != null) {
return buffer;
}
}
} finally {
if (!iter.hasNext()) {
bufferPool.remove(size);
}
}
}
return BufferUtils.createByteBuffer(size);
}
public static synchronized void release(ByteBuffer buffer) {
buffer.clear();
int size = buffer.capacity();
List<SoftReference<ByteBuffer>> available = bufferPool.get(size);
if (available == null) {
available = new LinkedList<>();
bufferPool.put(size, available);
}
available.add(new SoftReference<>(buffer));
}
}

View File

@@ -0,0 +1,176 @@
package com.replaymod.render.utils;
import com.google.common.base.Objects;
import lombok.RequiredArgsConstructor;
import net.minecraft.client.Minecraft;
import org.apache.logging.log4j.LogManager;
import org.lwjgl.opengl.ARBBufferObject;
import org.lwjgl.opengl.GLContext;
import org.lwjgl.opengl.Util;
import java.nio.ByteBuffer;
import static org.lwjgl.opengl.ARBPixelBufferObject.*;
import static org.lwjgl.opengl.GL15.*;
import static org.lwjgl.opengl.GL21.GL_PIXEL_PACK_BUFFER;
public class PixelBufferObject {
@RequiredArgsConstructor
public enum Usage {
COPY(GL_STREAM_COPY_ARB, GL_STREAM_COPY),
DRAW(GL_STREAM_DRAW_ARB, GL_STREAM_DRAW),
READ(GL_STREAM_READ_ARB, GL_STREAM_READ);
private final int arb, gl15;
}
public static final boolean SUPPORTED = GLContext.getCapabilities().GL_ARB_pixel_buffer_object || GLContext.getCapabilities().OpenGL15;
private static final boolean arb = !GLContext.getCapabilities().OpenGL15;
private static ThreadLocal<Integer> bound = new ThreadLocal<>();
private static ThreadLocal<Integer> mapped = new ThreadLocal<>();
private final long size;
private long handle;
public PixelBufferObject(long size, Usage usage) {
if (!SUPPORTED) {
throw new UnsupportedOperationException("PBOs not supported.");
}
this.size = size;
this.handle = arb ? ARBBufferObject.glGenBuffersARB() : glGenBuffers();
bind();
if (arb) {
ARBBufferObject.glBufferDataARB(GL_PIXEL_PACK_BUFFER_ARB, size, usage.arb);
} else {
glBufferData(GL_PIXEL_PACK_BUFFER, size, usage.gl15);
}
}
private int getHandle() {
if (handle == -1) {
throw new IllegalStateException("PBO not allocated.");
}
return (int) handle;
}
public void bind() {
if (arb) {
ARBBufferObject.glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, getHandle());
} else {
glBindBuffer(GL_PIXEL_PACK_BUFFER, getHandle());
}
bound.set(getHandle());
}
public void unbind() {
checkBound();
if (arb) {
ARBBufferObject.glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0);
} else {
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
}
bound.set(0);
}
private void checkBound() {
if (!Objects.equal(getHandle(), bound.get())) {
throw new IllegalStateException("Buffer not bound.");
}
}
private void checkNotMapped() {
if (Objects.equal(getHandle(), mapped.get())) {
throw new IllegalStateException("Buffer already mapped.");
}
}
public ByteBuffer mapReadOnly() {
checkBound();
checkNotMapped();
ByteBuffer buffer;
if (arb) {
buffer = ARBBufferObject.glMapBufferARB(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY_ARB, size, null);
} else {
buffer = glMapBuffer(GL_PIXEL_PACK_BUFFER, GL_READ_ONLY, size, null);
}
if (buffer == null) {
Util.checkGLError();
}
mapped.set(getHandle());
return buffer;
}
public ByteBuffer mapWriteOnly() {
checkBound();
checkNotMapped();
ByteBuffer buffer;
if (arb) {
buffer = ARBBufferObject.glMapBufferARB(GL_PIXEL_PACK_BUFFER_ARB, GL_WRITE_ONLY_ARB, size, null);
} else {
buffer = glMapBuffer(GL_PIXEL_PACK_BUFFER, GL_WRITE_ONLY, size, null);
}
if (buffer == null) {
Util.checkGLError();
}
mapped.set(getHandle());
return buffer;
}
public ByteBuffer mapReadWrite() {
checkBound();
checkNotMapped();
ByteBuffer buffer;
if (arb) {
buffer = ARBBufferObject.glMapBufferARB(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_WRITE_ARB, size, null);
} else {
buffer = glMapBuffer(GL_PIXEL_PACK_BUFFER, GL_READ_WRITE, size, null);
}
if (buffer == null) {
Util.checkGLError();
}
mapped.set(getHandle());
return buffer;
}
public void unmap() {
checkBound();
if (!Objects.equal(mapped.get(), getHandle())) {
throw new IllegalStateException("Buffer not mapped.");
}
if (arb) {
ARBBufferObject.glUnmapBufferARB(GL_PIXEL_PACK_BUFFER_ARB);
} else {
glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
}
mapped.set(0);
}
public void delete() {
if (handle != -1) {
if (arb) {
ARBBufferObject.glDeleteBuffersARB(getHandle());
} else {
glDeleteBuffers(getHandle());
}
handle = -1;
}
}
@Override
protected void finalize() throws Throwable {
super.finalize();
if (handle != -1) {
LogManager.getLogger().warn("PBO garbage collected before deleted!");
Minecraft.getMinecraft().addScheduledTask(new Runnable() {
@Override
public void run() {
delete();
}
});
}
}
}

View File

@@ -0,0 +1,26 @@
package com.replaymod.render.utils;
import java.nio.ByteBuffer;
public class Utils {
/**
* Copies the rgb image (flipped vertically) to the specified position in the target buffer
* @param buffer Source image
* @param bufferWidth Source image width
* @param xOffset X offset in target image
* @param yOffset Y offset in target image
* @param to Target image
* @param width Target image width
*/
public static void openGlBytesToRBG(ByteBuffer buffer, int bufferWidth, int xOffset, int yOffset, ByteBuffer to, int width) {
byte[] rowBuf = new byte[bufferWidth * 3];
// Copy image flipped vertically to target buffer
int rows = buffer.remaining() / 3 / bufferWidth;
for (int i = 0; i < rows; i++) {
buffer.get(rowBuf);
to.position(((yOffset + rows - i - 1) * width + xOffset) * 3);
to.put(rowBuf);
}
to.rewind();
}
}