mirror of
https://github.com/SquidDev-CC/CC-Tweaked
synced 2025-01-20 22:16:57 +00:00
Move the rendering monitor code to the client side
It's kinda funny looking at all the pre-CC:T proxy code, how much this has come full circle. I think this design is nicer than what 1.12 did, but it's still slighly embarassing.
This commit is contained in:
parent
b36b96e0bc
commit
48285404b9
@ -13,12 +13,12 @@ import dan200.computercraft.client.render.CableHighlightRenderer;
|
|||||||
import dan200.computercraft.client.render.ItemPocketRenderer;
|
import dan200.computercraft.client.render.ItemPocketRenderer;
|
||||||
import dan200.computercraft.client.render.ItemPrintoutRenderer;
|
import dan200.computercraft.client.render.ItemPrintoutRenderer;
|
||||||
import dan200.computercraft.client.render.MonitorHighlightRenderer;
|
import dan200.computercraft.client.render.MonitorHighlightRenderer;
|
||||||
|
import dan200.computercraft.client.render.monitor.MonitorRenderState;
|
||||||
import dan200.computercraft.client.sound.SpeakerManager;
|
import dan200.computercraft.client.sound.SpeakerManager;
|
||||||
import dan200.computercraft.shared.CommonHooks;
|
import dan200.computercraft.shared.CommonHooks;
|
||||||
import dan200.computercraft.shared.command.CommandComputerCraft;
|
import dan200.computercraft.shared.command.CommandComputerCraft;
|
||||||
import dan200.computercraft.shared.computer.core.ServerContext;
|
import dan200.computercraft.shared.computer.core.ServerContext;
|
||||||
import dan200.computercraft.shared.media.items.ItemPrintout;
|
import dan200.computercraft.shared.media.items.ItemPrintout;
|
||||||
import dan200.computercraft.shared.peripheral.monitor.ClientMonitor;
|
|
||||||
import dan200.computercraft.shared.peripheral.monitor.TileMonitor;
|
import dan200.computercraft.shared.peripheral.monitor.TileMonitor;
|
||||||
import dan200.computercraft.shared.pocket.items.ItemPocketComputer;
|
import dan200.computercraft.shared.pocket.items.ItemPocketComputer;
|
||||||
import dan200.computercraft.shared.turtle.blocks.TileTurtle;
|
import dan200.computercraft.shared.turtle.blocks.TileTurtle;
|
||||||
@ -58,7 +58,7 @@ public final class ClientHooks {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void onWorldUnload() {
|
public static void onWorldUnload() {
|
||||||
ClientMonitor.destroyAll();
|
MonitorRenderState.destroyAll();
|
||||||
SpeakerManager.reset();
|
SpeakerManager.reset();
|
||||||
ClientPocketComputers.reset();
|
ClientPocketComputers.reset();
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@ import com.mojang.math.Matrix4f;
|
|||||||
import com.mojang.math.Vector3f;
|
import com.mojang.math.Vector3f;
|
||||||
import dan200.computercraft.ComputerCraft;
|
import dan200.computercraft.ComputerCraft;
|
||||||
import dan200.computercraft.client.FrameInfo;
|
import dan200.computercraft.client.FrameInfo;
|
||||||
|
import dan200.computercraft.client.render.monitor.MonitorRenderState;
|
||||||
import dan200.computercraft.client.render.text.DirectFixedWidthFontRenderer;
|
import dan200.computercraft.client.render.text.DirectFixedWidthFontRenderer;
|
||||||
import dan200.computercraft.client.render.text.FixedWidthFontRenderer;
|
import dan200.computercraft.client.render.text.FixedWidthFontRenderer;
|
||||||
import dan200.computercraft.client.util.DirectBuffers;
|
import dan200.computercraft.client.util.DirectBuffers;
|
||||||
@ -31,6 +32,7 @@ import net.minecraft.Util;
|
|||||||
import net.minecraft.client.renderer.MultiBufferSource;
|
import net.minecraft.client.renderer.MultiBufferSource;
|
||||||
import net.minecraft.client.renderer.blockentity.BlockEntityRenderer;
|
import net.minecraft.client.renderer.blockentity.BlockEntityRenderer;
|
||||||
import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider;
|
import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider;
|
||||||
|
import org.lwjgl.opengl.GL;
|
||||||
import org.lwjgl.opengl.GL11;
|
import org.lwjgl.opengl.GL11;
|
||||||
import org.lwjgl.opengl.GL20;
|
import org.lwjgl.opengl.GL20;
|
||||||
import org.lwjgl.opengl.GL31;
|
import org.lwjgl.opengl.GL31;
|
||||||
@ -64,18 +66,19 @@ public class TileEntityMonitorRenderer implements BlockEntityRenderer<TileMonito
|
|||||||
|
|
||||||
if (originTerminal == null) return;
|
if (originTerminal == null) return;
|
||||||
var origin = originTerminal.getOrigin();
|
var origin = originTerminal.getOrigin();
|
||||||
|
var renderState = originTerminal.getRenderState(MonitorRenderState::new);
|
||||||
var monitorPos = monitor.getBlockPos();
|
var monitorPos = monitor.getBlockPos();
|
||||||
|
|
||||||
// Ensure each monitor terminal is rendered only once. We allow rendering a specific tile
|
// Ensure each monitor terminal is rendered only once. We allow rendering a specific tile
|
||||||
// multiple times in a single frame to ensure compatibility with shaders which may run a
|
// multiple times in a single frame to ensure compatibility with shaders which may run a
|
||||||
// pass multiple times.
|
// pass multiple times.
|
||||||
var renderFrame = FrameInfo.getRenderFrame();
|
var renderFrame = FrameInfo.getRenderFrame();
|
||||||
if (originTerminal.lastRenderFrame == renderFrame && !monitorPos.equals(originTerminal.lastRenderPos)) {
|
if (renderState.lastRenderFrame == renderFrame && !monitorPos.equals(renderState.lastRenderPos)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
originTerminal.lastRenderFrame = renderFrame;
|
renderState.lastRenderFrame = renderFrame;
|
||||||
originTerminal.lastRenderPos = monitorPos;
|
renderState.lastRenderPos = monitorPos;
|
||||||
|
|
||||||
var originPos = origin.getBlockPos();
|
var originPos = origin.getBlockPos();
|
||||||
|
|
||||||
@ -116,7 +119,7 @@ public class TileEntityMonitorRenderer implements BlockEntityRenderer<TileMonito
|
|||||||
|
|
||||||
var matrix = transform.last().pose();
|
var matrix = transform.last().pose();
|
||||||
|
|
||||||
renderTerminal(matrix, originTerminal, terminal, (float) (MARGIN / xScale), (float) (MARGIN / yScale));
|
renderTerminal(matrix, originTerminal, renderState, terminal, (float) (MARGIN / xScale), (float) (MARGIN / yScale));
|
||||||
|
|
||||||
transform.popPose();
|
transform.popPose();
|
||||||
} else {
|
} else {
|
||||||
@ -130,34 +133,36 @@ public class TileEntityMonitorRenderer implements BlockEntityRenderer<TileMonito
|
|||||||
transform.popPose();
|
transform.popPose();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void renderTerminal(Matrix4f matrix, ClientMonitor monitor, Terminal terminal, float xMargin, float yMargin) {
|
private static void renderTerminal(
|
||||||
|
Matrix4f matrix, ClientMonitor monitor, MonitorRenderState renderState, Terminal terminal, float xMargin, float yMargin
|
||||||
|
) {
|
||||||
int width = terminal.getWidth(), height = terminal.getHeight();
|
int width = terminal.getWidth(), height = terminal.getHeight();
|
||||||
int pixelWidth = width * FONT_WIDTH, pixelHeight = height * FONT_HEIGHT;
|
int pixelWidth = width * FONT_WIDTH, pixelHeight = height * FONT_HEIGHT;
|
||||||
|
|
||||||
var renderType = MonitorRenderer.current();
|
var renderType = currentRenderer();
|
||||||
var redraw = monitor.pollTerminalChanged();
|
var redraw = monitor.pollTerminalChanged();
|
||||||
if (monitor.createBuffer(renderType)) redraw = true;
|
if (renderState.createBuffer(renderType)) redraw = true;
|
||||||
|
|
||||||
switch (renderType) {
|
switch (renderType) {
|
||||||
case TBO -> {
|
case TBO -> {
|
||||||
if (redraw) {
|
if (redraw) {
|
||||||
var terminalBuffer = getBuffer(width * height * 3);
|
var terminalBuffer = getBuffer(width * height * 3);
|
||||||
MonitorTextureBufferShader.setTerminalData(terminalBuffer, terminal);
|
MonitorTextureBufferShader.setTerminalData(terminalBuffer, terminal);
|
||||||
DirectBuffers.setBufferData(GL31.GL_TEXTURE_BUFFER, monitor.tboBuffer, terminalBuffer, GL20.GL_STATIC_DRAW);
|
DirectBuffers.setBufferData(GL31.GL_TEXTURE_BUFFER, renderState.tboBuffer, terminalBuffer, GL20.GL_STATIC_DRAW);
|
||||||
|
|
||||||
var uniformBuffer = getBuffer(MonitorTextureBufferShader.UNIFORM_SIZE);
|
var uniformBuffer = getBuffer(MonitorTextureBufferShader.UNIFORM_SIZE);
|
||||||
MonitorTextureBufferShader.setUniformData(uniformBuffer, terminal);
|
MonitorTextureBufferShader.setUniformData(uniformBuffer, terminal);
|
||||||
DirectBuffers.setBufferData(GL31.GL_UNIFORM_BUFFER, monitor.tboUniform, uniformBuffer, GL20.GL_STATIC_DRAW);
|
DirectBuffers.setBufferData(GL31.GL_UNIFORM_BUFFER, renderState.tboUniform, uniformBuffer, GL20.GL_STATIC_DRAW);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Nobody knows what they're doing!
|
// Nobody knows what they're doing!
|
||||||
var active = GlStateManager._getActiveTexture();
|
var active = GlStateManager._getActiveTexture();
|
||||||
RenderSystem.activeTexture(MonitorTextureBufferShader.TEXTURE_INDEX);
|
RenderSystem.activeTexture(MonitorTextureBufferShader.TEXTURE_INDEX);
|
||||||
GL11.glBindTexture(GL31.GL_TEXTURE_BUFFER, monitor.tboTexture);
|
GL11.glBindTexture(GL31.GL_TEXTURE_BUFFER, renderState.tboTexture);
|
||||||
RenderSystem.activeTexture(active);
|
RenderSystem.activeTexture(active);
|
||||||
|
|
||||||
var shader = RenderTypes.getMonitorTextureBufferShader();
|
var shader = RenderTypes.getMonitorTextureBufferShader();
|
||||||
shader.setupUniform(monitor.tboUniform);
|
shader.setupUniform(renderState.tboUniform);
|
||||||
|
|
||||||
var buffer = Tesselator.getInstance().getBuilder();
|
var buffer = Tesselator.getInstance().getBuilder();
|
||||||
buffer.begin(RenderTypes.MONITOR_TBO.mode(), RenderTypes.MONITOR_TBO.format());
|
buffer.begin(RenderTypes.MONITOR_TBO.mode(), RenderTypes.MONITOR_TBO.format());
|
||||||
@ -168,8 +173,8 @@ public class TileEntityMonitorRenderer implements BlockEntityRenderer<TileMonito
|
|||||||
RenderTypes.MONITOR_TBO.end(buffer, 0, 0, 0);
|
RenderTypes.MONITOR_TBO.end(buffer, 0, 0, 0);
|
||||||
}
|
}
|
||||||
case VBO -> {
|
case VBO -> {
|
||||||
var backgroundBuffer = assertNonNull(monitor.backgroundBuffer);
|
var backgroundBuffer = assertNonNull(renderState.backgroundBuffer);
|
||||||
var foregroundBuffer = assertNonNull(monitor.foregroundBuffer);
|
var foregroundBuffer = assertNonNull(renderState.foregroundBuffer);
|
||||||
if (redraw) {
|
if (redraw) {
|
||||||
var size = DirectFixedWidthFontRenderer.getVertexCount(terminal);
|
var size = DirectFixedWidthFontRenderer.getVertexCount(terminal);
|
||||||
|
|
||||||
@ -238,7 +243,6 @@ public class TileEntityMonitorRenderer implements BlockEntityRenderer<TileMonito
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static ByteBuffer getBuffer(int capacity) {
|
private static ByteBuffer getBuffer(int capacity) {
|
||||||
|
|
||||||
var buffer = backingBuffer;
|
var buffer = backingBuffer;
|
||||||
if (buffer == null || buffer.capacity() < capacity) {
|
if (buffer == null || buffer.capacity() < capacity) {
|
||||||
buffer = backingBuffer = buffer == null ? MemoryTracker.create(capacity) : MemoryTracker.resize(buffer, capacity);
|
buffer = backingBuffer = buffer == null ? MemoryTracker.create(capacity) : MemoryTracker.resize(buffer, capacity);
|
||||||
@ -252,4 +256,30 @@ public class TileEntityMonitorRenderer implements BlockEntityRenderer<TileMonito
|
|||||||
public int getViewDistance() {
|
public int getViewDistance() {
|
||||||
return ComputerCraft.monitorDistance;
|
return ComputerCraft.monitorDistance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the current renderer to use.
|
||||||
|
*
|
||||||
|
* @return The current renderer. Will not return {@link MonitorRenderer#BEST}.
|
||||||
|
*/
|
||||||
|
public static MonitorRenderer currentRenderer() {
|
||||||
|
var current = ComputerCraft.monitorRenderer;
|
||||||
|
if (current == MonitorRenderer.BEST) current = ComputerCraft.monitorRenderer = bestRenderer();
|
||||||
|
return current;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static MonitorRenderer bestRenderer() {
|
||||||
|
if (!GL.getCapabilities().OpenGL31) {
|
||||||
|
ComputerCraft.log.warn("Texture buffers are not supported on your graphics card. Falling back to VBO monitor renderer.");
|
||||||
|
return MonitorRenderer.VBO;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ShaderMod.INSTANCE.isShaderMod()) {
|
||||||
|
ComputerCraft.log.warn("Optifine is loaded, assuming shaders are being used. Falling back to VBO monitor renderer.");
|
||||||
|
return MonitorRenderer.VBO;
|
||||||
|
}
|
||||||
|
|
||||||
|
return MonitorRenderer.TBO;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,132 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of ComputerCraft - http://www.computercraft.info
|
||||||
|
* Copyright Daniel Ratcliffe, 2011-2022. Do not distribute without permission.
|
||||||
|
* Send enquiries to dratcliffe@gmail.com
|
||||||
|
*/
|
||||||
|
package dan200.computercraft.client.render.monitor;
|
||||||
|
|
||||||
|
import com.google.errorprone.annotations.concurrent.GuardedBy;
|
||||||
|
import com.mojang.blaze3d.platform.GlStateManager;
|
||||||
|
import dan200.computercraft.client.util.DirectBuffers;
|
||||||
|
import dan200.computercraft.client.util.DirectVertexBuffer;
|
||||||
|
import dan200.computercraft.shared.peripheral.monitor.ClientMonitor;
|
||||||
|
import dan200.computercraft.shared.peripheral.monitor.MonitorRenderer;
|
||||||
|
import net.minecraft.core.BlockPos;
|
||||||
|
import org.lwjgl.opengl.GL11;
|
||||||
|
import org.lwjgl.opengl.GL15;
|
||||||
|
import org.lwjgl.opengl.GL30;
|
||||||
|
import org.lwjgl.opengl.GL31;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
public class MonitorRenderState implements ClientMonitor.RenderState {
|
||||||
|
@GuardedBy("allMonitors")
|
||||||
|
private static final Set<MonitorRenderState> allMonitors = new HashSet<>();
|
||||||
|
|
||||||
|
public long lastRenderFrame = -1;
|
||||||
|
public @Nullable BlockPos lastRenderPos = null;
|
||||||
|
|
||||||
|
public int tboBuffer;
|
||||||
|
public int tboTexture;
|
||||||
|
public int tboUniform;
|
||||||
|
public @Nullable DirectVertexBuffer backgroundBuffer;
|
||||||
|
public @Nullable DirectVertexBuffer foregroundBuffer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create the appropriate buffer if needed.
|
||||||
|
*
|
||||||
|
* @param renderer The renderer to use.
|
||||||
|
* @return If a buffer was created. This will return {@code false} if we already have an appropriate buffer,
|
||||||
|
* or this mode does not require one.
|
||||||
|
*/
|
||||||
|
public boolean createBuffer(MonitorRenderer renderer) {
|
||||||
|
switch (renderer) {
|
||||||
|
case TBO: {
|
||||||
|
if (tboBuffer != 0) return false;
|
||||||
|
|
||||||
|
deleteBuffers();
|
||||||
|
|
||||||
|
tboBuffer = DirectBuffers.createBuffer();
|
||||||
|
DirectBuffers.setEmptyBufferData(GL31.GL_TEXTURE_BUFFER, tboBuffer, GL15.GL_STATIC_DRAW);
|
||||||
|
tboTexture = GlStateManager._genTexture();
|
||||||
|
GL11.glBindTexture(GL31.GL_TEXTURE_BUFFER, tboTexture);
|
||||||
|
GL31.glTexBuffer(GL31.GL_TEXTURE_BUFFER, GL30.GL_R8UI, tboBuffer);
|
||||||
|
GL11.glBindTexture(GL31.GL_TEXTURE_BUFFER, 0);
|
||||||
|
|
||||||
|
tboUniform = DirectBuffers.createBuffer();
|
||||||
|
DirectBuffers.setEmptyBufferData(GL31.GL_UNIFORM_BUFFER, tboUniform, GL15.GL_STATIC_DRAW);
|
||||||
|
|
||||||
|
addMonitor();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
case VBO:
|
||||||
|
if (backgroundBuffer != null) return false;
|
||||||
|
|
||||||
|
deleteBuffers();
|
||||||
|
backgroundBuffer = new DirectVertexBuffer();
|
||||||
|
foregroundBuffer = new DirectVertexBuffer();
|
||||||
|
addMonitor();
|
||||||
|
return true;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addMonitor() {
|
||||||
|
synchronized (allMonitors) {
|
||||||
|
allMonitors.add(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void deleteBuffers() {
|
||||||
|
if (tboBuffer != 0) {
|
||||||
|
DirectBuffers.deleteBuffer(GL31.GL_TEXTURE_BUFFER, tboBuffer);
|
||||||
|
tboBuffer = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tboTexture != 0) {
|
||||||
|
GlStateManager._deleteTexture(tboTexture);
|
||||||
|
tboTexture = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tboUniform != 0) {
|
||||||
|
DirectBuffers.deleteBuffer(GL31.GL_UNIFORM_BUFFER, tboUniform);
|
||||||
|
tboUniform = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (backgroundBuffer != null) {
|
||||||
|
backgroundBuffer.close();
|
||||||
|
backgroundBuffer = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (foregroundBuffer != null) {
|
||||||
|
foregroundBuffer.close();
|
||||||
|
foregroundBuffer = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() {
|
||||||
|
if (tboBuffer != 0 || backgroundBuffer != null) {
|
||||||
|
synchronized (allMonitors) {
|
||||||
|
allMonitors.remove(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteBuffers();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void destroyAll() {
|
||||||
|
synchronized (allMonitors) {
|
||||||
|
for (var iterator = allMonitors.iterator(); iterator.hasNext(); ) {
|
||||||
|
var monitor = iterator.next();
|
||||||
|
monitor.deleteBuffers();
|
||||||
|
iterator.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -5,39 +5,19 @@
|
|||||||
*/
|
*/
|
||||||
package dan200.computercraft.shared.peripheral.monitor;
|
package dan200.computercraft.shared.peripheral.monitor;
|
||||||
|
|
||||||
import com.mojang.blaze3d.platform.GlStateManager;
|
|
||||||
import dan200.computercraft.client.util.DirectBuffers;
|
|
||||||
import dan200.computercraft.client.util.DirectVertexBuffer;
|
|
||||||
import dan200.computercraft.core.terminal.Terminal;
|
import dan200.computercraft.core.terminal.Terminal;
|
||||||
import dan200.computercraft.shared.computer.terminal.NetworkedTerminal;
|
import dan200.computercraft.shared.computer.terminal.NetworkedTerminal;
|
||||||
import dan200.computercraft.shared.computer.terminal.TerminalState;
|
import dan200.computercraft.shared.computer.terminal.TerminalState;
|
||||||
import net.minecraft.core.BlockPos;
|
|
||||||
import net.minecraftforge.api.distmarker.Dist;
|
|
||||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
|
||||||
import org.lwjgl.opengl.GL11;
|
|
||||||
import org.lwjgl.opengl.GL15;
|
|
||||||
import org.lwjgl.opengl.GL30;
|
|
||||||
import org.lwjgl.opengl.GL31;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import java.util.HashSet;
|
import java.util.function.Supplier;
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
public final class ClientMonitor {
|
public final class ClientMonitor {
|
||||||
private static final Set<ClientMonitor> allMonitors = new HashSet<>();
|
|
||||||
|
|
||||||
private final TileMonitor origin;
|
private final TileMonitor origin;
|
||||||
|
|
||||||
public long lastRenderFrame = -1;
|
|
||||||
public @Nullable BlockPos lastRenderPos = null;
|
|
||||||
|
|
||||||
public int tboBuffer;
|
|
||||||
public int tboTexture;
|
|
||||||
public int tboUniform;
|
|
||||||
public @Nullable DirectVertexBuffer backgroundBuffer;
|
|
||||||
public @Nullable DirectVertexBuffer foregroundBuffer;
|
|
||||||
private @Nullable NetworkedTerminal terminal;
|
private @Nullable NetworkedTerminal terminal;
|
||||||
private boolean terminalChanged;
|
private boolean terminalChanged;
|
||||||
|
private @Nullable RenderState state;
|
||||||
|
|
||||||
public ClientMonitor(TileMonitor origin) {
|
public ClientMonitor(TileMonitor origin) {
|
||||||
this.origin = origin;
|
this.origin = origin;
|
||||||
@ -48,103 +28,21 @@ public final class ClientMonitor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create the appropriate buffer if needed.
|
* Get or create the current render state.
|
||||||
*
|
*
|
||||||
* @param renderer The renderer to use. This can be fetched from {@link MonitorRenderer#current()}.
|
* @param create A factory to create the render state.
|
||||||
* @return If a buffer was created. This will return {@code false} if we already have an appropriate buffer,
|
* @param <T> The current render state. This type parameter should only be inhabited by a single class.
|
||||||
* or this mode does not require one.
|
* @return This monitor's render state.
|
||||||
*/
|
*/
|
||||||
@OnlyIn(Dist.CLIENT)
|
@SuppressWarnings("unchecked")
|
||||||
public boolean createBuffer(MonitorRenderer renderer) {
|
public <T extends RenderState> T getRenderState(Supplier<T> create) {
|
||||||
switch (renderer) {
|
var state = this.state;
|
||||||
case TBO: {
|
return (T) (state != null ? state : (this.state = create.get()));
|
||||||
if (tboBuffer != 0) return false;
|
|
||||||
|
|
||||||
deleteBuffers();
|
|
||||||
|
|
||||||
tboBuffer = DirectBuffers.createBuffer();
|
|
||||||
DirectBuffers.setEmptyBufferData(GL31.GL_TEXTURE_BUFFER, tboBuffer, GL15.GL_STATIC_DRAW);
|
|
||||||
tboTexture = GlStateManager._genTexture();
|
|
||||||
GL11.glBindTexture(GL31.GL_TEXTURE_BUFFER, tboTexture);
|
|
||||||
GL31.glTexBuffer(GL31.GL_TEXTURE_BUFFER, GL30.GL_R8UI, tboBuffer);
|
|
||||||
GL11.glBindTexture(GL31.GL_TEXTURE_BUFFER, 0);
|
|
||||||
|
|
||||||
tboUniform = DirectBuffers.createBuffer();
|
|
||||||
DirectBuffers.setEmptyBufferData(GL31.GL_UNIFORM_BUFFER, tboUniform, GL15.GL_STATIC_DRAW);
|
|
||||||
|
|
||||||
addMonitor();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
case VBO:
|
|
||||||
if (backgroundBuffer != null) return false;
|
|
||||||
|
|
||||||
deleteBuffers();
|
|
||||||
backgroundBuffer = new DirectVertexBuffer();
|
|
||||||
foregroundBuffer = new DirectVertexBuffer();
|
|
||||||
addMonitor();
|
|
||||||
return true;
|
|
||||||
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addMonitor() {
|
void destroy() {
|
||||||
synchronized (allMonitors) {
|
if (state != null) state.close();
|
||||||
allMonitors.add(this);
|
state = null;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void deleteBuffers() {
|
|
||||||
|
|
||||||
if (tboBuffer != 0) {
|
|
||||||
DirectBuffers.deleteBuffer(GL31.GL_TEXTURE_BUFFER, tboBuffer);
|
|
||||||
tboBuffer = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tboTexture != 0) {
|
|
||||||
GlStateManager._deleteTexture(tboTexture);
|
|
||||||
tboTexture = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tboUniform != 0) {
|
|
||||||
DirectBuffers.deleteBuffer(GL31.GL_UNIFORM_BUFFER, tboUniform);
|
|
||||||
tboUniform = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (backgroundBuffer != null) {
|
|
||||||
backgroundBuffer.close();
|
|
||||||
backgroundBuffer = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (foregroundBuffer != null) {
|
|
||||||
foregroundBuffer.close();
|
|
||||||
foregroundBuffer = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@OnlyIn(Dist.CLIENT)
|
|
||||||
public void destroy() {
|
|
||||||
if (tboBuffer != 0 || backgroundBuffer != null) {
|
|
||||||
synchronized (allMonitors) {
|
|
||||||
allMonitors.remove(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
deleteBuffers();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@OnlyIn(Dist.CLIENT)
|
|
||||||
public static void destroyAll() {
|
|
||||||
synchronized (allMonitors) {
|
|
||||||
for (var iterator = allMonitors.iterator(); iterator.hasNext(); ) {
|
|
||||||
var monitor = iterator.next();
|
|
||||||
monitor.deleteBuffers();
|
|
||||||
|
|
||||||
iterator.remove();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean pollTerminalChanged() {
|
public boolean pollTerminalChanged() {
|
||||||
@ -169,4 +67,15 @@ public final class ClientMonitor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An interface representing the current state of the monitor renderer.
|
||||||
|
* <p>
|
||||||
|
* This interface should only be inhabited by {@link dan200.computercraft.client.render.monitor.MonitorRenderState}:
|
||||||
|
* it exists solely to avoid referencing client-side classes in common code.
|
||||||
|
*/
|
||||||
|
public interface RenderState extends AutoCloseable {
|
||||||
|
@Override
|
||||||
|
void close();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,15 +5,10 @@
|
|||||||
*/
|
*/
|
||||||
package dan200.computercraft.shared.peripheral.monitor;
|
package dan200.computercraft.shared.peripheral.monitor;
|
||||||
|
|
||||||
import dan200.computercraft.ComputerCraft;
|
|
||||||
import dan200.computercraft.client.render.TileEntityMonitorRenderer;
|
|
||||||
import dan200.computercraft.shared.integration.ShaderMod;
|
|
||||||
import org.lwjgl.opengl.GL;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The render type to use for monitors.
|
* The render type to use for monitors.
|
||||||
*
|
*
|
||||||
* @see TileEntityMonitorRenderer
|
* @see dan200.computercraft.client.render.TileEntityMonitorRenderer
|
||||||
* @see ClientMonitor
|
* @see ClientMonitor
|
||||||
*/
|
*/
|
||||||
public enum MonitorRenderer {
|
public enum MonitorRenderer {
|
||||||
@ -34,30 +29,5 @@ public enum MonitorRenderer {
|
|||||||
*
|
*
|
||||||
* @see com.mojang.blaze3d.vertex.VertexBuffer
|
* @see com.mojang.blaze3d.vertex.VertexBuffer
|
||||||
*/
|
*/
|
||||||
VBO;
|
VBO,
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the current renderer to use.
|
|
||||||
*
|
|
||||||
* @return The current renderer. Will not return {@link MonitorRenderer#BEST}.
|
|
||||||
*/
|
|
||||||
public static MonitorRenderer current() {
|
|
||||||
var current = ComputerCraft.monitorRenderer;
|
|
||||||
if (current == BEST) current = ComputerCraft.monitorRenderer = best();
|
|
||||||
return current;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static MonitorRenderer best() {
|
|
||||||
if (!GL.getCapabilities().OpenGL31) {
|
|
||||||
ComputerCraft.log.warn("Texture buffers are not supported on your graphics card. Falling back to VBO monitor renderer.");
|
|
||||||
return VBO;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ShaderMod.INSTANCE.isShaderMod()) {
|
|
||||||
ComputerCraft.log.warn("Optifine is loaded, assuming shaders are being used. Falling back to VBO monitor renderer.");
|
|
||||||
return VBO;
|
|
||||||
}
|
|
||||||
|
|
||||||
return TBO;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user