115 lines
		
	
	
	
		
			4.5 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
			
		
		
	
	
			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);
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| }
 |