minecraft-src/com/mojang/blaze3d/opengl/BufferStorage.java
2025-09-18 12:27:44 +00:00

115 lines
4.5 KiB
Java

package com.mojang.blaze3d.opengl;
import java.nio.ByteBuffer;
import java.util.Set;
import java.util.function.Supplier;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import org.jetbrains.annotations.Nullable;
import org.lwjgl.opengl.GLCapabilities;
import org.lwjgl.system.MemoryUtil;
@Environment(EnvType.CLIENT)
public abstract class BufferStorage {
public static BufferStorage create(GLCapabilities capabilities, Set<String> enabledExtensions) {
if (capabilities.GL_ARB_buffer_storage && GlDevice.USE_GL_ARB_buffer_storage) {
enabledExtensions.add("GL_ARB_buffer_storage");
return new BufferStorage.Immutable();
} else {
return new BufferStorage.Mutable();
}
}
public abstract GlBuffer createBuffer(DirectStateAccess directStateAccess, @Nullable Supplier<String> label, int usage, int size);
public abstract GlBuffer createBuffer(DirectStateAccess directStateAccess, @Nullable Supplier<String> label, int usage, ByteBuffer data);
public abstract GlBuffer.GlMappedView mapBuffer(DirectStateAccess directStateAccess, GlBuffer buffer, int offset, int size, int usage);
@Environment(EnvType.CLIENT)
static class Immutable extends BufferStorage {
@Override
public GlBuffer createBuffer(DirectStateAccess directStateAccess, @Nullable Supplier<String> label, int usage, int size) {
int i = directStateAccess.createBuffer();
directStateAccess.bufferStorage(i, size, GlConst.bufferUsageToGlFlag(usage));
ByteBuffer byteBuffer = this.tryMapBufferPersistent(directStateAccess, usage, i, size);
return new GlBuffer(label, directStateAccess, usage, size, i, byteBuffer);
}
@Override
public GlBuffer createBuffer(DirectStateAccess directStateAccess, @Nullable Supplier<String> label, int usage, ByteBuffer data) {
int i = directStateAccess.createBuffer();
int j = data.remaining();
directStateAccess.bufferStorage(i, data, GlConst.bufferUsageToGlFlag(usage));
ByteBuffer byteBuffer = this.tryMapBufferPersistent(directStateAccess, usage, i, j);
return new GlBuffer(label, directStateAccess, usage, j, i, byteBuffer);
}
@Nullable
private ByteBuffer tryMapBufferPersistent(DirectStateAccess directStateAccess, int usage, int handle, int size) {
int i = 0;
if ((usage & 1) != 0) {
i |= 1;
}
if ((usage & 2) != 0) {
i |= 18;
}
ByteBuffer byteBuffer;
if (i != 0) {
GlStateManager.clearGlErrors();
byteBuffer = directStateAccess.mapBufferRange(handle, 0, size, i | 64);
if (byteBuffer == null) {
throw new IllegalStateException("Can't persistently map buffer, opengl error " + GlStateManager._getError());
}
} else {
byteBuffer = null;
}
return byteBuffer;
}
@Override
public GlBuffer.GlMappedView mapBuffer(DirectStateAccess directStateAccess, GlBuffer buffer, int offset, int size, int usage) {
if (buffer.persistentBuffer == null) {
throw new IllegalStateException("Somehow trying to map an unmappable buffer");
} else {
return new GlBuffer.GlMappedView(() -> {
if ((usage & 2) != 0) {
directStateAccess.flushMappedBufferRange(buffer.handle, offset, size);
}
}, buffer, MemoryUtil.memSlice(buffer.persistentBuffer, offset, size));
}
}
}
@Environment(EnvType.CLIENT)
static class Mutable extends BufferStorage {
@Override
public GlBuffer createBuffer(DirectStateAccess directStateAccess, @Nullable Supplier<String> label, int usage, int size) {
int i = directStateAccess.createBuffer();
directStateAccess.bufferData(i, size, GlConst.bufferUsageToGlEnum(usage));
return new GlBuffer(label, directStateAccess, usage, size, i, null);
}
@Override
public GlBuffer createBuffer(DirectStateAccess directStateAccess, @Nullable Supplier<String> label, int usage, ByteBuffer data) {
int i = directStateAccess.createBuffer();
int j = data.remaining();
directStateAccess.bufferData(i, data, GlConst.bufferUsageToGlEnum(usage));
return new GlBuffer(label, directStateAccess, usage, j, i, null);
}
@Override
public GlBuffer.GlMappedView mapBuffer(DirectStateAccess directStateAccess, GlBuffer buffer, int offset, int size, int usage) {
GlStateManager.clearGlErrors();
ByteBuffer byteBuffer = directStateAccess.mapBufferRange(buffer.handle, offset, size, usage);
if (byteBuffer == null) {
throw new IllegalStateException("Can't map buffer, opengl error " + GlStateManager._getError());
} else {
return new GlBuffer.GlMappedView(() -> directStateAccess.unmapBuffer(buffer.handle), buffer, byteBuffer);
}
}
}
}