mirror of
https://github.com/GTNewHorizons/Angelica.git
synced 2026-11-15 09:44:52 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bf08cd50d9 | ||
|
|
805a266059 | ||
|
|
d3c9963280 | ||
|
|
4630bc4fd8 | ||
|
|
ce32a3d3df |
No files matched your search
@@ -111,6 +111,7 @@ public class DisplayListManager {
|
||||
int listMode,
|
||||
CommandRecorder recorder,
|
||||
List<AccumulatedDraw> draws,
|
||||
DisplayListCallback callback,
|
||||
StackTraceElement[] stackTrace,
|
||||
|
||||
// Debug logging fields (only used when LOG_DISPLAY_LIST_COMPILATION)
|
||||
@@ -131,6 +132,19 @@ public class DisplayListManager {
|
||||
return currentRecorder != null && Thread.currentThread() == recordingThread;
|
||||
}
|
||||
|
||||
public static UnsupportedOperationException unsupportedInList(String what) {
|
||||
return new UnsupportedOperationException(what + " in display lists not yet implemented - if you see this, please report! " + describeCurrentCompilation());
|
||||
}
|
||||
|
||||
public static String describeCurrentCompilation() {
|
||||
if (currentRecorder == null) {
|
||||
return "(not compiling)";
|
||||
}
|
||||
final String mode = glListMode == GL11.GL_COMPILE_AND_EXECUTE ? "GL_COMPILE_AND_EXECUTE" : "GL_COMPILE";
|
||||
final int depth = compilationStack.size() + 1;
|
||||
return "while compiling display list " + glListId + " (" + mode + (depth > 1 ? ", nesting depth " + depth : "") + ")";
|
||||
}
|
||||
|
||||
public static boolean isCompileAndExecute() {
|
||||
return glListMode == GL11.GL_COMPILE_AND_EXECUTE;
|
||||
}
|
||||
@@ -159,7 +173,9 @@ public class DisplayListManager {
|
||||
* Only use this if you are 100% that the transforms will not be of any use after the display list draw call.
|
||||
*/
|
||||
public static void discardMatrixTransforms() {
|
||||
resetRelativeTransform();
|
||||
if (isRecording()) {
|
||||
resetRelativeTransform();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -748,7 +764,7 @@ public class DisplayListManager {
|
||||
// Nested display list compilation violates OpenGL spec, but some of our optimizations require it
|
||||
// Save current compilation context and start fresh for nested list
|
||||
final CompilationContext parentContext = new CompilationContext(
|
||||
glListId, glListMode, currentRecorder, accumulatedDraws,
|
||||
glListId, glListMode, currentRecorder, accumulatedDraws, transformCallback,
|
||||
compilationStackTrace, pendingTransformOps, multMatrixSources, drawRangeSources
|
||||
);
|
||||
compilationStack.push(parentContext);
|
||||
@@ -784,9 +800,21 @@ public class DisplayListManager {
|
||||
if (glListMode == 0) {
|
||||
throw new RuntimeException("glEndList called outside of a display list!");
|
||||
}
|
||||
try {
|
||||
finishCurrentList();
|
||||
} finally {
|
||||
// Non-null here means finishCurrentList threw before transferring or releasing
|
||||
// ownership of the recorder.
|
||||
if (currentRecorder != null) {
|
||||
currentRecorder.delete();
|
||||
}
|
||||
// Must always run, even when compilation fails - a leaked context leaves
|
||||
// isRecording() true forever and every guarded GL call throws afterward.
|
||||
popCompilationContext();
|
||||
}
|
||||
}
|
||||
|
||||
final boolean isNested = !compilationStack.isEmpty();
|
||||
|
||||
private static void finishCurrentList() {
|
||||
// Stop compiling mode (works for both root and nested lists now)
|
||||
TessellatorManager.stopCapturingDirect();
|
||||
|
||||
@@ -803,8 +831,9 @@ public class DisplayListManager {
|
||||
final boolean hasCommands = !commandBuffer.isEmpty();
|
||||
|
||||
if (hasCommands) {
|
||||
final DisplayListVBO compiledBuffers = new DisplayListVBOBuilder().addDraws(accumulatedDraws).build();
|
||||
DisplayListVBO compiledBuffers = null;
|
||||
try {
|
||||
compiledBuffers = new DisplayListVBOBuilder().addDraws(accumulatedDraws).build();
|
||||
final IndexedDrawBatchBuilder indexedBuilder = commandBuffer.getIndexedDraws();
|
||||
final List<IndexedDrawBatch> indexedBatches;
|
||||
if (indexedBuilder.isEmpty()) {
|
||||
@@ -824,16 +853,23 @@ public class DisplayListManager {
|
||||
}
|
||||
}
|
||||
|
||||
compiled = new CompiledDisplayList(commandBuffer.finish(), commandBuffer.getComplexObjects(), compiledBuffers, indexedBatches);
|
||||
final DisplayListCommand[] complexObjects = commandBuffer.getComplexObjects();
|
||||
compiled = new CompiledDisplayList(commandBuffer.finish(), complexObjects, compiledBuffers, indexedBatches);
|
||||
currentRecorder = null;
|
||||
} catch (Exception e) {
|
||||
GLStateManager.LOGGER.error("Encountered a fatal issue while trying to compile a display list.");
|
||||
e.printStackTrace();
|
||||
commandBuffer.delete();
|
||||
currentRecorder = null;
|
||||
if (compiledBuffers != null) {
|
||||
compiledBuffers.delete();
|
||||
}
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// Free the recorder even if empty
|
||||
commandBuffer.delete();
|
||||
currentRecorder = null;
|
||||
// Empty display list - per OpenGL spec, still valid after glNewList/glEndList
|
||||
compiled = CompiledDisplayList.EMPTY;
|
||||
}
|
||||
@@ -846,6 +882,10 @@ public class DisplayListManager {
|
||||
if (LOG_DISPLAY_LIST_COMPILATION) {
|
||||
logCompiledDisplayList(glListId, compiled, compilationStackTrace);
|
||||
}
|
||||
}
|
||||
|
||||
private static void popCompilationContext() {
|
||||
final boolean isNested = !compilationStack.isEmpty();
|
||||
|
||||
// Handle nested compilation - restore parent context
|
||||
if (isNested) {
|
||||
@@ -856,6 +896,7 @@ public class DisplayListManager {
|
||||
glListMode = parentContext.listMode;
|
||||
currentRecorder = parentContext.recorder;
|
||||
accumulatedDraws = parentContext.draws;
|
||||
transformCallback = parentContext.callback;
|
||||
compilationStackTrace = parentContext.stackTrace;
|
||||
pendingTransformOps = parentContext.pendingOps;
|
||||
multMatrixSources = parentContext.matrixSources;
|
||||
@@ -869,6 +910,7 @@ public class DisplayListManager {
|
||||
recordingThread = null;
|
||||
accumulatedDraws = null;
|
||||
pendingDraw = null;
|
||||
transformCallback = null;
|
||||
compilationStackTrace = null;
|
||||
pendingTransformOps = null;
|
||||
multMatrixSources = null;
|
||||
|
||||
@@ -38,6 +38,7 @@ import com.gtnewhorizons.angelica.glsm.stacks.PolygonStateStack;
|
||||
import com.gtnewhorizons.angelica.glsm.stacks.StencilStateStack;
|
||||
import com.gtnewhorizons.angelica.glsm.stacks.ViewPortStateStack;
|
||||
import com.gtnewhorizons.angelica.glsm.states.ClipPlaneState;
|
||||
import com.gtnewhorizons.angelica.glsm.states.PixelUnpackState;
|
||||
import com.gtnewhorizons.angelica.glsm.states.Color4;
|
||||
import com.gtnewhorizons.angelica.glsm.states.TextureBinding;
|
||||
import com.gtnewhorizons.angelica.glsm.states.TextureUnitArray;
|
||||
@@ -463,6 +464,7 @@ public class GLStateManager {
|
||||
private static final int[] clientArraysVBOOffsets = new int[VertexAttribState.MAX_ATTRIBS];
|
||||
private static int boundPixelUnpackBuffer;
|
||||
private static int boundPixelPackBuffer;
|
||||
private static PixelUnpackState pixelUnpackState = PixelUnpackState.DEFAULT;
|
||||
private static final Int2IntOpenHashMap vaoEboMap = new Int2IntOpenHashMap();
|
||||
|
||||
static {
|
||||
@@ -1316,7 +1318,7 @@ public class GLStateManager {
|
||||
|
||||
public static void glBlendEquation(int mode) {
|
||||
if (DisplayListManager.isRecording()) {
|
||||
throw new UnsupportedOperationException("glBlendEquation in display lists not yet implemented - if you see this, please report!");
|
||||
throw DisplayListManager.unsupportedInList("glBlendEquation");
|
||||
}
|
||||
final boolean caching = isCachingEnabled();
|
||||
final boolean bypass = BYPASS_CACHE || !caching;
|
||||
@@ -1331,7 +1333,7 @@ public class GLStateManager {
|
||||
|
||||
public static void glBlendEquationSeparate(int modeRGB, int modeAlpha) {
|
||||
if (DisplayListManager.isRecording()) {
|
||||
throw new UnsupportedOperationException("glBlendEquationSeparate in display lists not yet implemented - if you see this, please report!");
|
||||
throw DisplayListManager.unsupportedInList("glBlendEquationSeparate");
|
||||
}
|
||||
final boolean caching = isCachingEnabled();
|
||||
final boolean bypass = BYPASS_CACHE || !caching;
|
||||
@@ -1851,7 +1853,7 @@ public class GLStateManager {
|
||||
internalformat = changeFormatIfDeprecated(internalformat);
|
||||
final RecordMode mode = DisplayListManager.getRecordMode();
|
||||
if (mode != RecordMode.NONE) {
|
||||
DisplayListManager.recordComplexCommand(TexImage2DCmd.fromIntBuffer(target, level, internalformat, width, height, border, format, type, pixels));
|
||||
DisplayListManager.recordComplexCommand(TexImage2DCmd.fromIntBuffer(target, level, internalformat, width, height, border, format, type, pixels, pixelUnpackState));
|
||||
if (mode == RecordMode.COMPILE) {
|
||||
return;
|
||||
}
|
||||
@@ -1860,13 +1862,14 @@ public class GLStateManager {
|
||||
suspendPixelUnpackBuffer();
|
||||
RENDER_BACKEND.texImage2D(target, level, internalformat, width, height, border, format, type, pixels);
|
||||
restorePixelUnpackBuffer();
|
||||
maybeGenerateMipmap(target, level);
|
||||
}
|
||||
|
||||
public static void glTexImage2D(int target, int level, int internalformat, int width, int height, int border, int format, int type, FloatBuffer pixels) {
|
||||
internalformat = changeFormatIfDeprecated(internalformat);
|
||||
final RecordMode mode = DisplayListManager.getRecordMode();
|
||||
if (mode != RecordMode.NONE) {
|
||||
DisplayListManager.recordComplexCommand(TexImage2DCmd.fromFloatBuffer(target, level, internalformat, width, height, border, format, type, pixels));
|
||||
DisplayListManager.recordComplexCommand(TexImage2DCmd.fromFloatBuffer(target, level, internalformat, width, height, border, format, type, pixels, pixelUnpackState));
|
||||
if (mode == RecordMode.COMPILE) {
|
||||
return;
|
||||
}
|
||||
@@ -1875,13 +1878,14 @@ public class GLStateManager {
|
||||
suspendPixelUnpackBuffer();
|
||||
RENDER_BACKEND.texImage2D(target, level, internalformat, width, height, border, format, type, pixels);
|
||||
restorePixelUnpackBuffer();
|
||||
maybeGenerateMipmap(target, level);
|
||||
}
|
||||
|
||||
public static void glTexImage2D(int target, int level, int internalformat, int width, int height, int border, int format, int type, DoubleBuffer pixels) {
|
||||
internalformat = changeFormatIfDeprecated(internalformat);
|
||||
final RecordMode mode = DisplayListManager.getRecordMode();
|
||||
if (mode != RecordMode.NONE) {
|
||||
DisplayListManager.recordComplexCommand(TexImage2DCmd.fromDoubleBuffer(target, level, internalformat, width, height, border, format, type, pixels));
|
||||
DisplayListManager.recordComplexCommand(TexImage2DCmd.fromDoubleBuffer(target, level, internalformat, width, height, border, format, type, pixels, pixelUnpackState));
|
||||
if (mode == RecordMode.COMPILE) {
|
||||
return;
|
||||
}
|
||||
@@ -1890,13 +1894,14 @@ public class GLStateManager {
|
||||
suspendPixelUnpackBuffer();
|
||||
RENDER_BACKEND.texImage2D(target, level, internalformat, width, height, border, format, type, pixels);
|
||||
restorePixelUnpackBuffer();
|
||||
maybeGenerateMipmap(target, level);
|
||||
}
|
||||
|
||||
public static void glTexImage2D(int target, int level, int internalformat, int width, int height, int border, int format, int type, ByteBuffer pixels) {
|
||||
internalformat = changeFormatIfDeprecated(internalformat);
|
||||
final RecordMode mode = DisplayListManager.getRecordMode();
|
||||
if (mode != RecordMode.NONE) {
|
||||
DisplayListManager.recordComplexCommand(TexImage2DCmd.fromByteBuffer(target, level, internalformat, width, height, border, format, type, pixels));
|
||||
DisplayListManager.recordComplexCommand(TexImage2DCmd.fromByteBuffer(target, level, internalformat, width, height, border, format, type, pixels, pixelUnpackState));
|
||||
if (mode == RecordMode.COMPILE) {
|
||||
return;
|
||||
}
|
||||
@@ -1905,15 +1910,17 @@ public class GLStateManager {
|
||||
suspendPixelUnpackBuffer();
|
||||
RENDER_BACKEND.texImage2D(target, level, internalformat, width, height, border, format, type, pixels);
|
||||
restorePixelUnpackBuffer();
|
||||
maybeGenerateMipmap(target, level);
|
||||
}
|
||||
|
||||
public static void glTexImage2D(int target, int level, int internalformat, int width, int height, int border, int format, int type, long pixels_buffer_offset) {
|
||||
internalformat = changeFormatIfDeprecated(internalformat);
|
||||
if (DisplayListManager.isRecording()) {
|
||||
throw new UnsupportedOperationException("glTexImage2D with buffer offset in display lists not yet supported");
|
||||
throw DisplayListManager.unsupportedInList("glTexImage2D with buffer offset");
|
||||
}
|
||||
TextureInfoCache.INSTANCE.onTexImage2D(target, level, internalformat, width, height, border, format, type, pixels_buffer_offset);
|
||||
RENDER_BACKEND.texImage2D(target, level, internalformat, width, height, border, format, type, pixels_buffer_offset);
|
||||
maybeGenerateMipmap(target, level);
|
||||
}
|
||||
|
||||
public static void glTexCoord1f(float s) {
|
||||
@@ -2197,7 +2204,7 @@ public class GLStateManager {
|
||||
|
||||
public static void glDrawElements(int mode, ByteBuffer indices) {
|
||||
if (DisplayListManager.isRecording()) {
|
||||
throw new UnsupportedOperationException("glDrawElements in display lists not yet implemented - if you see this, please report!");
|
||||
throw DisplayListManager.unsupportedInList("glDrawElements");
|
||||
}
|
||||
if (FeedbackManager.isFeedbackMode()) {
|
||||
FeedbackManager.processDrawElements(mode, indices);
|
||||
@@ -2211,7 +2218,7 @@ public class GLStateManager {
|
||||
|
||||
public static void glDrawElements(int mode, IntBuffer indices) {
|
||||
if (DisplayListManager.isRecording()) {
|
||||
throw new UnsupportedOperationException("glDrawElements in display lists not yet implemented - if you see this, please report!");
|
||||
throw DisplayListManager.unsupportedInList("glDrawElements");
|
||||
}
|
||||
if (FeedbackManager.isFeedbackMode()) {
|
||||
FeedbackManager.processDrawElements(mode, indices);
|
||||
@@ -2229,7 +2236,7 @@ public class GLStateManager {
|
||||
|
||||
public static void glDrawElements(int mode, ShortBuffer indices) {
|
||||
if (DisplayListManager.isRecording()) {
|
||||
throw new UnsupportedOperationException("glDrawElements in display lists not yet implemented - if you see this, please report!");
|
||||
throw DisplayListManager.unsupportedInList("glDrawElements");
|
||||
}
|
||||
if (FeedbackManager.isFeedbackMode()) {
|
||||
FeedbackManager.processDrawElements(mode, indices);
|
||||
@@ -2247,7 +2254,7 @@ public class GLStateManager {
|
||||
|
||||
public static void glDrawElements(int mode, int count, int type, ByteBuffer indices) {
|
||||
if (DisplayListManager.isRecording()) {
|
||||
throw new UnsupportedOperationException("glDrawElements in display lists not yet implemented - if you see this, please report!");
|
||||
throw DisplayListManager.unsupportedInList("glDrawElements");
|
||||
}
|
||||
if (FeedbackManager.isFeedbackMode()) {
|
||||
FeedbackManager.processDrawElements(mode, count, type, indices);
|
||||
@@ -3734,6 +3741,25 @@ public class GLStateManager {
|
||||
return DisplayListManager.getListMode();
|
||||
}
|
||||
|
||||
private static boolean handleRemovedTexParam(int target, int pname, int value) {
|
||||
if (pname == GL14.GL_GENERATE_MIPMAP) {
|
||||
if (target == GL11.GL_TEXTURE_2D) {
|
||||
final TextureInfo info = TextureInfoCache.INSTANCE.getInfo(getBoundTextureForServerState());
|
||||
if (info != null) info.setGenerateMipmap(value != 0);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static void maybeGenerateMipmap(int target, int level) {
|
||||
if (target != GL11.GL_TEXTURE_2D) return;
|
||||
final TextureInfo info = TextureInfoCache.INSTANCE.getInfo(getBoundTextureForServerState());
|
||||
if (info != null && info.isGenerateMipmap() && level == info.getBaseLevel() && level < info.getMaxLevel()) {
|
||||
RENDER_BACKEND.generateMipmap(target);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean updateTexParameteriCache(int target, int texture, int pname, int param) {
|
||||
if (target != GL11.GL_TEXTURE_2D) {
|
||||
return true;
|
||||
@@ -3759,6 +3785,10 @@ public class GLStateManager {
|
||||
if (info.getWrapT() == param && !shouldBypassCache()) return false;
|
||||
info.setWrapT(param);
|
||||
}
|
||||
case GL12.GL_TEXTURE_BASE_LEVEL -> {
|
||||
if (info.getBaseLevel() == param && !shouldBypassCache()) return false;
|
||||
info.setBaseLevel(param);
|
||||
}
|
||||
case GL12.GL_TEXTURE_MAX_LEVEL -> {
|
||||
if (info.getMaxLevel() == param && !shouldBypassCache()) return false;
|
||||
info.setMaxLevel(param);
|
||||
@@ -3776,6 +3806,7 @@ public class GLStateManager {
|
||||
}
|
||||
|
||||
public static void glTexParameter(int target, int pname, IntBuffer params) {
|
||||
if (handleRemovedTexParam(target, pname, params.remaining() >= 1 ? params.get(params.position()) : 0)) return;
|
||||
if (params.remaining() >= 1) {
|
||||
final int val = params.get(params.position());
|
||||
final int remapped = remapTexClamp(pname, val);
|
||||
@@ -3786,6 +3817,7 @@ public class GLStateManager {
|
||||
}
|
||||
|
||||
public static void glTexParameter(int target, int pname, FloatBuffer params) {
|
||||
if (handleRemovedTexParam(target, pname, params.remaining() >= 1 ? (int) params.get(params.position()) : 0)) return;
|
||||
if (params.remaining() >= 1) {
|
||||
final float val = params.get(params.position());
|
||||
final float remapped = remapTexClamp(pname, val);
|
||||
@@ -3796,6 +3828,7 @@ public class GLStateManager {
|
||||
}
|
||||
|
||||
public static void glTexParameteri(int target, int pname, int param) {
|
||||
if (handleRemovedTexParam(target, pname, param)) return;
|
||||
param = remapTexClamp(pname, param);
|
||||
final RecordMode mode = DisplayListManager.getRecordMode();
|
||||
if (mode != RecordMode.NONE) {
|
||||
@@ -3835,6 +3868,7 @@ public class GLStateManager {
|
||||
}
|
||||
|
||||
public static void glTexParameterf(int target, int pname, float param) {
|
||||
if (handleRemovedTexParam(target, pname, param > 0 ? (int) (param + 0.5f) : (int) (param - 0.5f))) return;
|
||||
param = remapTexClamp(pname, param);
|
||||
final RecordMode mode = DisplayListManager.getRecordMode();
|
||||
if (mode != RecordMode.NONE) {
|
||||
@@ -3867,9 +3901,11 @@ public class GLStateManager {
|
||||
case GL11.GL_TEXTURE_MAG_FILTER -> info.getMagFilter();
|
||||
case GL11.GL_TEXTURE_WRAP_S -> info.getWrapS();
|
||||
case GL11.GL_TEXTURE_WRAP_T -> info.getWrapT();
|
||||
case GL12.GL_TEXTURE_BASE_LEVEL -> info.getBaseLevel();
|
||||
case GL12.GL_TEXTURE_MAX_LEVEL -> info.getMaxLevel();
|
||||
case GL12.GL_TEXTURE_MIN_LOD -> info.getMinLod();
|
||||
case GL12.GL_TEXTURE_MAX_LOD -> info.getMaxLod();
|
||||
case GL14.GL_GENERATE_MIPMAP -> info.isGenerateMipmap() ? GL11.GL_TRUE : GL11.GL_FALSE;
|
||||
default -> {
|
||||
if (isRecordingDisplayList()) {
|
||||
throw new IllegalStateException(String.format(
|
||||
@@ -4405,7 +4441,7 @@ public class GLStateManager {
|
||||
public static void glTexImage1D(int target, int level, int internalformat, int width, int border, int format, int type, ByteBuffer pixels) {
|
||||
internalformat = changeFormatIfDeprecated(internalformat);
|
||||
if (DisplayListManager.isRecording()) {
|
||||
throw new UnsupportedOperationException("glTexImage1D in display lists not yet implemented");
|
||||
throw DisplayListManager.unsupportedInList("glTexImage1D");
|
||||
}
|
||||
suspendPixelUnpackBuffer();
|
||||
RENDER_BACKEND.texImage1D(target, level, internalformat, width, border, format, type, pixels);
|
||||
@@ -4415,7 +4451,7 @@ public class GLStateManager {
|
||||
public static void glTexImage3D(int target, int level, int internalformat, int width, int height, int depth, int border, int format, int type, ByteBuffer pixels) {
|
||||
internalformat = changeFormatIfDeprecated(internalformat);
|
||||
if (DisplayListManager.isRecording()) {
|
||||
throw new UnsupportedOperationException("glTexImage3D in display lists not yet implemented");
|
||||
throw DisplayListManager.unsupportedInList("glTexImage3D");
|
||||
}
|
||||
suspendPixelUnpackBuffer();
|
||||
RENDER_BACKEND.texImage3D(target, level, internalformat, width, height, depth, border, format, type, pixels);
|
||||
@@ -4425,7 +4461,7 @@ public class GLStateManager {
|
||||
public static void glTexImage3D(int target, int level, int internalformat, int width, int height, int depth, int border, int format, int type, IntBuffer pixels) {
|
||||
internalformat = changeFormatIfDeprecated(internalformat);
|
||||
if (DisplayListManager.isRecording()) {
|
||||
throw new UnsupportedOperationException("glTexImage3D in display lists not yet implemented");
|
||||
throw DisplayListManager.unsupportedInList("glTexImage3D");
|
||||
}
|
||||
suspendPixelUnpackBuffer();
|
||||
RENDER_BACKEND.texImage3D(target, level, internalformat, width, height, depth, border, format, type, pixels);
|
||||
@@ -4434,7 +4470,7 @@ public class GLStateManager {
|
||||
|
||||
public static void glTexSubImage1D(int target, int level, int xoffset, int width, int format, int type, ByteBuffer pixels) {
|
||||
if (DisplayListManager.isRecording()) {
|
||||
throw new UnsupportedOperationException("glTexSubImage1D in display lists not yet implemented");
|
||||
throw DisplayListManager.unsupportedInList("glTexSubImage1D");
|
||||
}
|
||||
suspendPixelUnpackBuffer();
|
||||
RENDER_BACKEND.texSubImage1D(target, level, xoffset, width, format, type, pixels);
|
||||
@@ -4523,7 +4559,7 @@ public class GLStateManager {
|
||||
public static void glTexSubImage2D(int target, int level, int xoffset, int yoffset, int width, int height, int format, int type, ByteBuffer pixels) {
|
||||
final RecordMode mode = DisplayListManager.getRecordMode();
|
||||
if (mode != RecordMode.NONE) {
|
||||
DisplayListManager.recordComplexCommand(TexSubImage2DCmd.fromByteBuffer(target, level, xoffset, yoffset, width, height, format, type, pixels));
|
||||
DisplayListManager.recordComplexCommand(TexSubImage2DCmd.fromByteBuffer(target, level, xoffset, yoffset, width, height, format, type, pixels, pixelUnpackState));
|
||||
if (mode == RecordMode.COMPILE) {
|
||||
return;
|
||||
}
|
||||
@@ -4531,12 +4567,13 @@ public class GLStateManager {
|
||||
suspendPixelUnpackBuffer();
|
||||
RENDER_BACKEND.texSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels);
|
||||
restorePixelUnpackBuffer();
|
||||
maybeGenerateMipmap(target, level);
|
||||
}
|
||||
|
||||
public static void glTexSubImage2D(int target, int level, int xoffset, int yoffset, int width, int height, int format, int type, IntBuffer pixels) {
|
||||
final RecordMode mode = DisplayListManager.getRecordMode();
|
||||
if (mode != RecordMode.NONE) {
|
||||
DisplayListManager.recordComplexCommand(TexSubImage2DCmd.fromIntBuffer(target, level, xoffset, yoffset, width, height, format, type, pixels));
|
||||
DisplayListManager.recordComplexCommand(TexSubImage2DCmd.fromIntBuffer(target, level, xoffset, yoffset, width, height, format, type, pixels, pixelUnpackState));
|
||||
if (mode == RecordMode.COMPILE) {
|
||||
return;
|
||||
}
|
||||
@@ -4544,18 +4581,20 @@ public class GLStateManager {
|
||||
suspendPixelUnpackBuffer();
|
||||
RENDER_BACKEND.texSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels);
|
||||
restorePixelUnpackBuffer();
|
||||
maybeGenerateMipmap(target, level);
|
||||
}
|
||||
|
||||
public static void glTexSubImage2D(int target, int level, int xoffset, int yoffset, int width, int height, int format, int type, long pixels_buffer_offset) {
|
||||
if (DisplayListManager.isRecording()) {
|
||||
throw new UnsupportedOperationException("glTexSubImage2D with buffer offset in display lists not yet supported");
|
||||
throw DisplayListManager.unsupportedInList("glTexSubImage2D with buffer offset");
|
||||
}
|
||||
RENDER_BACKEND.texSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels_buffer_offset);
|
||||
maybeGenerateMipmap(target, level);
|
||||
}
|
||||
|
||||
public static void glTexSubImage3D(int target, int level, int xoffset, int yoffset, int zoffset, int width, int height, int depth, int format, int type, ByteBuffer pixels) {
|
||||
if (DisplayListManager.isRecording()) {
|
||||
throw new UnsupportedOperationException("glTexSubImage3D in display lists not yet implemented - if you see this, please report!");
|
||||
throw DisplayListManager.unsupportedInList("glTexSubImage3D");
|
||||
}
|
||||
suspendPixelUnpackBuffer();
|
||||
RENDER_BACKEND.texSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels);
|
||||
@@ -4564,35 +4603,37 @@ public class GLStateManager {
|
||||
|
||||
public static void glCopyTexImage1D(int target, int level, int internalFormat, int x, int y, int width, int border) {
|
||||
if (DisplayListManager.isRecording()) {
|
||||
throw new UnsupportedOperationException("glCopyTexImage1D in display lists not yet implemented - if you see this, please report!");
|
||||
throw DisplayListManager.unsupportedInList("glCopyTexImage1D");
|
||||
}
|
||||
RENDER_BACKEND.copyTexImage1D(target, level, internalFormat, x, y, width, border);
|
||||
}
|
||||
|
||||
public static void glCopyTexImage2D(int target, int level, int internalFormat, int x, int y, int width, int height, int border) {
|
||||
if (DisplayListManager.isRecording()) {
|
||||
throw new UnsupportedOperationException("glCopyTexImage2D in display lists not yet implemented - if you see this, please report!");
|
||||
throw DisplayListManager.unsupportedInList("glCopyTexImage2D");
|
||||
}
|
||||
RENDER_BACKEND.copyTexImage2D(target, level, internalFormat, x, y, width, height, border);
|
||||
maybeGenerateMipmap(target, level);
|
||||
}
|
||||
|
||||
public static void glCopyTexSubImage1D(int target, int level, int xoffset, int x, int y, int width) {
|
||||
if (DisplayListManager.isRecording()) {
|
||||
throw new UnsupportedOperationException("glCopyTexSubImage1D in display lists not yet implemented - if you see this, please report!");
|
||||
throw DisplayListManager.unsupportedInList("glCopyTexSubImage1D");
|
||||
}
|
||||
RENDER_BACKEND.copyTexSubImage1D(target, level, xoffset, x, y, width);
|
||||
}
|
||||
|
||||
public static void glCopyTexSubImage2D(int target, int level, int xoffset, int yoffset, int x, int y, int width, int height) {
|
||||
if (DisplayListManager.isRecording()) {
|
||||
throw new UnsupportedOperationException("glCopyTexSubImage2D in display lists not yet implemented - if you see this, please report!");
|
||||
throw DisplayListManager.unsupportedInList("glCopyTexSubImage2D");
|
||||
}
|
||||
RENDER_BACKEND.copyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height);
|
||||
maybeGenerateMipmap(target, level);
|
||||
}
|
||||
|
||||
public static void glCopyTexSubImage3D(int target, int level, int xoffset, int yoffset, int zoffset, int x, int y, int width, int height) {
|
||||
if (DisplayListManager.isRecording()) {
|
||||
throw new UnsupportedOperationException("glCopyTexSubImage3D in display lists not yet implemented - if you see this, please report!");
|
||||
throw DisplayListManager.unsupportedInList("glCopyTexSubImage3D");
|
||||
}
|
||||
RENDER_BACKEND.copyTexSubImage3D(target, level, xoffset, yoffset, zoffset, x, y, width, height);
|
||||
}
|
||||
@@ -4633,6 +4674,12 @@ public class GLStateManager {
|
||||
}
|
||||
|
||||
public static void glHint(int target, int hint) {
|
||||
// These hint targets are removed in core profile, ignore them
|
||||
switch (target) {
|
||||
case GL11.GL_PERSPECTIVE_CORRECTION_HINT, GL11.GL_POINT_SMOOTH_HINT, GL11.GL_FOG_HINT, GL14.GL_GENERATE_MIPMAP_HINT -> {
|
||||
return;
|
||||
}
|
||||
}
|
||||
final RecordMode mode = DisplayListManager.getRecordMode();
|
||||
if (mode != RecordMode.NONE) {
|
||||
DisplayListManager.recordHint(target, hint);
|
||||
@@ -4721,7 +4768,7 @@ public class GLStateManager {
|
||||
|
||||
public static void glReadBuffer(int mode) {
|
||||
if (DisplayListManager.isRecording()) {
|
||||
throw new UnsupportedOperationException("glReadBuffer in display lists not yet implemented - if you see this, please report!");
|
||||
throw DisplayListManager.unsupportedInList("glReadBuffer");
|
||||
}
|
||||
RENDER_BACKEND.readBuffer(mode);
|
||||
}
|
||||
@@ -4790,18 +4837,16 @@ public class GLStateManager {
|
||||
}
|
||||
}
|
||||
|
||||
// glPixelStore* isn'tcompiled into display lists, it executes immediately
|
||||
public static void glPixelStorei(int pname, int param) {
|
||||
if (DisplayListManager.isRecording()) {
|
||||
throw new UnsupportedOperationException("glPixelStorei in display lists not yet implemented - if you see this, please report!");
|
||||
if (isCachingEnabled()) {
|
||||
pixelUnpackState = pixelUnpackState.with(pname, param);
|
||||
}
|
||||
RENDER_BACKEND.pixelStorei(pname, param);
|
||||
}
|
||||
|
||||
public static void glPixelStoref(int pname, float param) {
|
||||
if (DisplayListManager.isRecording()) {
|
||||
throw new UnsupportedOperationException("glPixelStoref in display lists not yet implemented - if you see this, please report!");
|
||||
}
|
||||
RENDER_BACKEND.pixelStoref(pname, param);
|
||||
glPixelStorei(pname, param < 0 ? -Math.round(-param) : Math.round(param));
|
||||
}
|
||||
|
||||
// Display List Commands
|
||||
@@ -4896,7 +4941,7 @@ public class GLStateManager {
|
||||
// Multisample Commands
|
||||
public static void glSampleCoverage(float value, boolean invert) {
|
||||
if (DisplayListManager.isRecording()) {
|
||||
throw new UnsupportedOperationException("glSampleCoverage in display lists not yet implemented - if you see this, please report!");
|
||||
throw DisplayListManager.unsupportedInList("glSampleCoverage");
|
||||
}
|
||||
RENDER_BACKEND.sampleCoverage(value, invert);
|
||||
}
|
||||
@@ -5046,6 +5091,14 @@ public class GLStateManager {
|
||||
RENDER_BACKEND.bindBuffer(target, buffer);
|
||||
}
|
||||
|
||||
public static void forcePixelUnpackState(PixelUnpackState target) {
|
||||
PixelUnpackState.applyDiff(pixelUnpackState, target);
|
||||
}
|
||||
|
||||
public static void restorePixelUnpackState(PixelUnpackState applied) {
|
||||
PixelUnpackState.applyDiff(applied, pixelUnpackState);
|
||||
}
|
||||
|
||||
static void suspendPixelUnpackBuffer() {
|
||||
if (boundPixelUnpackBuffer != 0) {
|
||||
RENDER_BACKEND.bindBuffer(GL21.GL_PIXEL_UNPACK_BUFFER, 0);
|
||||
|
||||
@@ -507,11 +507,6 @@ public final class Lwjgl2GLRenderBackend extends RenderBackend {
|
||||
GL11.glPixelStorei(pname, param);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pixelStoref(int pname, float param) {
|
||||
GL11.glPixelStoref(pname, param);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sampleCoverage(float value, boolean invert) {
|
||||
GL13.glSampleCoverage(value, invert);
|
||||
|
||||
@@ -125,7 +125,6 @@ public abstract class RenderBackend {
|
||||
public abstract int getTexLevelParameteri(int target, int level, int pname);
|
||||
public abstract void generateMipmap(int target);
|
||||
public abstract void pixelStorei(int pname, int param);
|
||||
public void pixelStoref(int pname, float param) {}
|
||||
public void sampleCoverage(float value, boolean invert) {}
|
||||
|
||||
|
||||
|
||||
@@ -653,12 +653,19 @@ public final class CommandRecorder {
|
||||
for (IndexedDrawCapture c : indexedDraws.getCaptures()) {
|
||||
c.freeBuffers();
|
||||
}
|
||||
memFree(buffer);
|
||||
for (DisplayListCommand cmd : complexObjects) {
|
||||
cmd.delete();
|
||||
}
|
||||
complexObjects.clear();
|
||||
if (buffer != null) {
|
||||
memFree(buffer);
|
||||
buffer = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes every allocated object & returns a ByteBuffer with the capacity equal to its limit.
|
||||
* This CommandRecorder object cannot be used after calling this anymore.
|
||||
* This CommandRecorder object cannot be used after calling this anymore
|
||||
*/
|
||||
public ByteBuffer finish() {
|
||||
for (IndexedDrawCapture c : indexedDraws.getCaptures()) {
|
||||
@@ -666,7 +673,10 @@ public final class CommandRecorder {
|
||||
}
|
||||
final int size = size();
|
||||
buffer.limit(size);
|
||||
return memRealloc(buffer, size);
|
||||
final ByteBuffer out = memRealloc(buffer, size);
|
||||
buffer = null;
|
||||
complexObjects.clear();
|
||||
return out;
|
||||
}
|
||||
|
||||
public DisplayListCommand[] getComplexObjects() {
|
||||
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
package com.gtnewhorizons.angelica.glsm.recording.commands;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.DoubleBuffer;
|
||||
import java.nio.FloatBuffer;
|
||||
import java.nio.IntBuffer;
|
||||
|
||||
import static com.gtnewhorizon.gtnhlib.bytebuf.MemoryUtilities.memAlloc;
|
||||
|
||||
final class PixelDataSnapshot {
|
||||
private PixelDataSnapshot() {}
|
||||
|
||||
static @Nullable ByteBuffer copy(@Nullable ByteBuffer pixels) {
|
||||
if (pixels == null) return null;
|
||||
final int pos = pixels.position();
|
||||
final ByteBuffer out = memAlloc(pixels.remaining()).order(ByteOrder.nativeOrder());
|
||||
out.put(pixels);
|
||||
out.flip();
|
||||
pixels.position(pos);
|
||||
return out;
|
||||
}
|
||||
|
||||
static @Nullable ByteBuffer copy(@Nullable IntBuffer pixels) {
|
||||
if (pixels == null) return null;
|
||||
final int pos = pixels.position();
|
||||
final ByteBuffer out = memAlloc(pixels.remaining() * 4).order(ByteOrder.nativeOrder());
|
||||
out.asIntBuffer().put(pixels);
|
||||
pixels.position(pos);
|
||||
return out;
|
||||
}
|
||||
|
||||
static @Nullable ByteBuffer copy(@Nullable FloatBuffer pixels) {
|
||||
if (pixels == null) return null;
|
||||
final int pos = pixels.position();
|
||||
final ByteBuffer out = memAlloc(pixels.remaining() * 4).order(ByteOrder.nativeOrder());
|
||||
out.asFloatBuffer().put(pixels);
|
||||
pixels.position(pos);
|
||||
return out;
|
||||
}
|
||||
|
||||
static @Nullable ByteBuffer copy(@Nullable DoubleBuffer pixels) {
|
||||
if (pixels == null) return null;
|
||||
final int pos = pixels.position();
|
||||
final ByteBuffer out = memAlloc(pixels.remaining() * 8).order(ByteOrder.nativeOrder());
|
||||
out.asDoubleBuffer().put(pixels);
|
||||
pixels.position(pos);
|
||||
return out;
|
||||
}
|
||||
}
|
||||
+37
-69
@@ -2,15 +2,17 @@ package com.gtnewhorizons.angelica.glsm.recording.commands;
|
||||
|
||||
import com.gtnewhorizons.angelica.glsm.GLDebug;
|
||||
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||
import com.gtnewhorizons.angelica.glsm.states.PixelUnpackState;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.DoubleBuffer;
|
||||
import java.nio.FloatBuffer;
|
||||
import java.nio.IntBuffer;
|
||||
|
||||
import static com.gtnewhorizon.gtnhlib.bytebuf.MemoryUtilities.memFree;
|
||||
|
||||
/**
|
||||
* Command: glTexImage2D(target, level, internalformat, width, height, border, format, type, pixels)
|
||||
* Specifies a two-dimensional texture image during display list playback.
|
||||
@@ -24,92 +26,58 @@ public record TexImage2DCmd(
|
||||
int border,
|
||||
int format,
|
||||
int type,
|
||||
@Nullable byte[] pixelData
|
||||
@Nullable ByteBuffer pixels,
|
||||
@Nullable PixelUnpackState unpack
|
||||
) implements DisplayListCommand {
|
||||
|
||||
/**
|
||||
* Create command from IntBuffer
|
||||
*/
|
||||
public static TexImage2DCmd fromIntBuffer(int target, int level, int internalformat, int width, int height, int border, int format, int type, @Nullable IntBuffer pixels) {
|
||||
byte[] data = null;
|
||||
if (pixels != null) {
|
||||
int pos = pixels.position();
|
||||
int limit = pixels.limit();
|
||||
int size = (limit - pos) * 4; // 4 bytes per int
|
||||
data = new byte[size];
|
||||
ByteBuffer bb = ByteBuffer.wrap(data).order(ByteOrder.nativeOrder());
|
||||
bb.asIntBuffer().put(pixels);
|
||||
pixels.position(pos); // Restore position
|
||||
public TexImage2DCmd {
|
||||
if (pixels == null) {
|
||||
unpack = null;
|
||||
}
|
||||
return new TexImage2DCmd(target, level, internalformat, width, height, border, format, type, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create command from FloatBuffer
|
||||
*/
|
||||
public static TexImage2DCmd fromFloatBuffer(int target, int level, int internalformat, int width, int height, int border, int format, int type, @Nullable FloatBuffer pixels) {
|
||||
byte[] data = null;
|
||||
if (pixels != null) {
|
||||
int pos = pixels.position();
|
||||
int limit = pixels.limit();
|
||||
int size = (limit - pos) * 4; // 4 bytes per float
|
||||
data = new byte[size];
|
||||
ByteBuffer bb = ByteBuffer.wrap(data).order(ByteOrder.nativeOrder());
|
||||
bb.asFloatBuffer().put(pixels);
|
||||
pixels.position(pos); // Restore position
|
||||
}
|
||||
return new TexImage2DCmd(target, level, internalformat, width, height, border, format, type, data);
|
||||
public static TexImage2DCmd fromIntBuffer(int target, int level, int internalformat, int width, int height, int border, int format, int type, @Nullable IntBuffer pixels, PixelUnpackState unpack) {
|
||||
return new TexImage2DCmd(target, level, internalformat, width, height, border, format, type, PixelDataSnapshot.copy(pixels), unpack);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create command from DoubleBuffer
|
||||
*/
|
||||
public static TexImage2DCmd fromDoubleBuffer(int target, int level, int internalformat, int width, int height, int border, int format, int type, @Nullable DoubleBuffer pixels) {
|
||||
byte[] data = null;
|
||||
if (pixels != null) {
|
||||
int pos = pixels.position();
|
||||
int limit = pixels.limit();
|
||||
int size = (limit - pos) * 8; // 8 bytes per double
|
||||
data = new byte[size];
|
||||
ByteBuffer bb = ByteBuffer.wrap(data).order(ByteOrder.nativeOrder());
|
||||
bb.asDoubleBuffer().put(pixels);
|
||||
pixels.position(pos); // Restore position
|
||||
}
|
||||
return new TexImage2DCmd(target, level, internalformat, width, height, border, format, type, data);
|
||||
public static TexImage2DCmd fromFloatBuffer(int target, int level, int internalformat, int width, int height, int border, int format, int type, @Nullable FloatBuffer pixels, PixelUnpackState unpack) {
|
||||
return new TexImage2DCmd(target, level, internalformat, width, height, border, format, type, PixelDataSnapshot.copy(pixels), unpack);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create command from ByteBuffer
|
||||
*/
|
||||
public static TexImage2DCmd fromByteBuffer(int target, int level, int internalformat, int width, int height, int border, int format, int type, @Nullable ByteBuffer pixels) {
|
||||
byte[] data = null;
|
||||
if (pixels != null) {
|
||||
int pos = pixels.position();
|
||||
int limit = pixels.limit();
|
||||
int size = limit - pos;
|
||||
data = new byte[size];
|
||||
pixels.get(data);
|
||||
pixels.position(pos); // Restore position
|
||||
}
|
||||
return new TexImage2DCmd(target, level, internalformat, width, height, border, format, type, data);
|
||||
public static TexImage2DCmd fromDoubleBuffer(int target, int level, int internalformat, int width, int height, int border, int format, int type, @Nullable DoubleBuffer pixels, PixelUnpackState unpack) {
|
||||
return new TexImage2DCmd(target, level, internalformat, width, height, border, format, type, PixelDataSnapshot.copy(pixels), unpack);
|
||||
}
|
||||
|
||||
public static TexImage2DCmd fromByteBuffer(int target, int level, int internalformat, int width, int height, int border, int format, int type, @Nullable ByteBuffer pixels, PixelUnpackState unpack) {
|
||||
return new TexImage2DCmd(target, level, internalformat, width, height, border, format, type, PixelDataSnapshot.copy(pixels), unpack);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
ByteBuffer buffer = null;
|
||||
if (pixelData != null) {
|
||||
buffer = ByteBuffer.allocateDirect(pixelData.length).order(ByteOrder.nativeOrder());
|
||||
buffer.put(pixelData);
|
||||
buffer.flip();
|
||||
if (pixels == null) {
|
||||
GLStateManager.glTexImage2D(target, level, internalformat, width, height, border, format, type, (ByteBuffer) null);
|
||||
return;
|
||||
}
|
||||
GLStateManager.forcePixelUnpackState(unpack);
|
||||
try {
|
||||
GLStateManager.glTexImage2D(target, level, internalformat, width, height, border, format, type, pixels);
|
||||
} finally {
|
||||
GLStateManager.restorePixelUnpackState(unpack);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete() {
|
||||
if (pixels != null) {
|
||||
memFree(pixels);
|
||||
}
|
||||
GLStateManager.glTexImage2D(target, level, internalformat, width, height, border, format, type, buffer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String toString() {
|
||||
String dataStr = pixelData != null ? (pixelData.length + " bytes") : "null";
|
||||
return String.format("TexImage2D(target=%s, level=%d, internalformat=%s, %dx%d, border=%d, format=%s, type=%s, data=%s)",
|
||||
String dataStr = pixels != null ? (pixels.remaining() + " bytes") : "null";
|
||||
return String.format("TexImage2D(target=%s, level=%d, internalformat=%s, %dx%d, border=%d, format=%s, type=%s, data=%s, unpack=%s)",
|
||||
GLDebug.getTextureTargetName(target), level, GLDebug.getTextureFormatName(internalformat),
|
||||
width, height, border, GLDebug.getTextureFormatName(format), GLDebug.getDataTypeName(type), dataStr);
|
||||
width, height, border, GLDebug.getTextureFormatName(format), GLDebug.getDataTypeName(type), dataStr, unpack);
|
||||
}
|
||||
}
|
||||
+37
-69
@@ -2,15 +2,17 @@ package com.gtnewhorizons.angelica.glsm.recording.commands;
|
||||
|
||||
import com.gtnewhorizons.angelica.glsm.GLDebug;
|
||||
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||
import com.gtnewhorizons.angelica.glsm.states.PixelUnpackState;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.DoubleBuffer;
|
||||
import java.nio.FloatBuffer;
|
||||
import java.nio.IntBuffer;
|
||||
|
||||
import static com.gtnewhorizon.gtnhlib.bytebuf.MemoryUtilities.memFree;
|
||||
|
||||
/**
|
||||
* Command: glTexSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels)
|
||||
* Updates a portion of an existing two-dimensional texture image during display list playback.
|
||||
@@ -24,92 +26,58 @@ public record TexSubImage2DCmd(
|
||||
int height,
|
||||
int format,
|
||||
int type,
|
||||
@Nullable byte[] pixelData
|
||||
@Nullable ByteBuffer pixels,
|
||||
@Nullable PixelUnpackState unpack
|
||||
) implements DisplayListCommand {
|
||||
|
||||
/**
|
||||
* Create command from IntBuffer
|
||||
*/
|
||||
public static TexSubImage2DCmd fromIntBuffer(int target, int level, int xoffset, int yoffset, int width, int height, int format, int type, @Nullable IntBuffer pixels) {
|
||||
byte[] data = null;
|
||||
if (pixels != null) {
|
||||
int pos = pixels.position();
|
||||
int limit = pixels.limit();
|
||||
int size = (limit - pos) * 4; // 4 bytes per int
|
||||
data = new byte[size];
|
||||
ByteBuffer bb = ByteBuffer.wrap(data).order(ByteOrder.nativeOrder());
|
||||
bb.asIntBuffer().put(pixels);
|
||||
pixels.position(pos); // Restore position
|
||||
public TexSubImage2DCmd {
|
||||
if (pixels == null) {
|
||||
unpack = null;
|
||||
}
|
||||
return new TexSubImage2DCmd(target, level, xoffset, yoffset, width, height, format, type, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create command from FloatBuffer
|
||||
*/
|
||||
public static TexSubImage2DCmd fromFloatBuffer(int target, int level, int xoffset, int yoffset, int width, int height, int format, int type, @Nullable FloatBuffer pixels) {
|
||||
byte[] data = null;
|
||||
if (pixels != null) {
|
||||
int pos = pixels.position();
|
||||
int limit = pixels.limit();
|
||||
int size = (limit - pos) * 4; // 4 bytes per float
|
||||
data = new byte[size];
|
||||
ByteBuffer bb = ByteBuffer.wrap(data).order(ByteOrder.nativeOrder());
|
||||
bb.asFloatBuffer().put(pixels);
|
||||
pixels.position(pos); // Restore position
|
||||
}
|
||||
return new TexSubImage2DCmd(target, level, xoffset, yoffset, width, height, format, type, data);
|
||||
public static TexSubImage2DCmd fromIntBuffer(int target, int level, int xoffset, int yoffset, int width, int height, int format, int type, @Nullable IntBuffer pixels, PixelUnpackState unpack) {
|
||||
return new TexSubImage2DCmd(target, level, xoffset, yoffset, width, height, format, type, PixelDataSnapshot.copy(pixels), unpack);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create command from DoubleBuffer
|
||||
*/
|
||||
public static TexSubImage2DCmd fromDoubleBuffer(int target, int level, int xoffset, int yoffset, int width, int height, int format, int type, @Nullable DoubleBuffer pixels) {
|
||||
byte[] data = null;
|
||||
if (pixels != null) {
|
||||
int pos = pixels.position();
|
||||
int limit = pixels.limit();
|
||||
int size = (limit - pos) * 8; // 8 bytes per double
|
||||
data = new byte[size];
|
||||
ByteBuffer bb = ByteBuffer.wrap(data).order(ByteOrder.nativeOrder());
|
||||
bb.asDoubleBuffer().put(pixels);
|
||||
pixels.position(pos); // Restore position
|
||||
}
|
||||
return new TexSubImage2DCmd(target, level, xoffset, yoffset, width, height, format, type, data);
|
||||
public static TexSubImage2DCmd fromFloatBuffer(int target, int level, int xoffset, int yoffset, int width, int height, int format, int type, @Nullable FloatBuffer pixels, PixelUnpackState unpack) {
|
||||
return new TexSubImage2DCmd(target, level, xoffset, yoffset, width, height, format, type, PixelDataSnapshot.copy(pixels), unpack);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create command from ByteBuffer
|
||||
*/
|
||||
public static TexSubImage2DCmd fromByteBuffer(int target, int level, int xoffset, int yoffset, int width, int height, int format, int type, @Nullable ByteBuffer pixels) {
|
||||
byte[] data = null;
|
||||
if (pixels != null) {
|
||||
int pos = pixels.position();
|
||||
int limit = pixels.limit();
|
||||
int size = limit - pos;
|
||||
data = new byte[size];
|
||||
pixels.get(data);
|
||||
pixels.position(pos); // Restore position
|
||||
}
|
||||
return new TexSubImage2DCmd(target, level, xoffset, yoffset, width, height, format, type, data);
|
||||
public static TexSubImage2DCmd fromDoubleBuffer(int target, int level, int xoffset, int yoffset, int width, int height, int format, int type, @Nullable DoubleBuffer pixels, PixelUnpackState unpack) {
|
||||
return new TexSubImage2DCmd(target, level, xoffset, yoffset, width, height, format, type, PixelDataSnapshot.copy(pixels), unpack);
|
||||
}
|
||||
|
||||
public static TexSubImage2DCmd fromByteBuffer(int target, int level, int xoffset, int yoffset, int width, int height, int format, int type, @Nullable ByteBuffer pixels, PixelUnpackState unpack) {
|
||||
return new TexSubImage2DCmd(target, level, xoffset, yoffset, width, height, format, type, PixelDataSnapshot.copy(pixels), unpack);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
ByteBuffer buffer = null;
|
||||
if (pixelData != null) {
|
||||
buffer = ByteBuffer.allocateDirect(pixelData.length).order(ByteOrder.nativeOrder());
|
||||
buffer.put(pixelData);
|
||||
buffer.flip();
|
||||
if (pixels == null) {
|
||||
GLStateManager.glTexSubImage2D(target, level, xoffset, yoffset, width, height, format, type, (ByteBuffer) null);
|
||||
return;
|
||||
}
|
||||
GLStateManager.forcePixelUnpackState(unpack);
|
||||
try {
|
||||
GLStateManager.glTexSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels);
|
||||
} finally {
|
||||
GLStateManager.restorePixelUnpackState(unpack);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete() {
|
||||
if (pixels != null) {
|
||||
memFree(pixels);
|
||||
}
|
||||
GLStateManager.glTexSubImage2D(target, level, xoffset, yoffset, width, height, format, type, buffer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String toString() {
|
||||
String dataStr = pixelData != null ? (pixelData.length + " bytes") : "null";
|
||||
return String.format("TexSubImage2D(target=%s, level=%d, offset=(%d,%d), %dx%d, format=%s, type=%s, data=%s)",
|
||||
String dataStr = pixels != null ? (pixels.remaining() + " bytes") : "null";
|
||||
return String.format("TexSubImage2D(target=%s, level=%d, offset=(%d,%d), %dx%d, format=%s, type=%s, data=%s, unpack=%s)",
|
||||
GLDebug.getTextureTargetName(target), level, xoffset, yoffset, width, height,
|
||||
GLDebug.getTextureFormatName(format), GLDebug.getDataTypeName(type), dataStr);
|
||||
GLDebug.getTextureFormatName(format), GLDebug.getDataTypeName(type), dataStr, unpack);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package com.gtnewhorizons.angelica.glsm.states;
|
||||
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL12;
|
||||
|
||||
import static com.gtnewhorizons.angelica.glsm.backend.BackendManager.RENDER_BACKEND;
|
||||
|
||||
/**
|
||||
* Immutable client-side pixel unpack state (glPixelStore UNPACK_* params)
|
||||
*/
|
||||
public record PixelUnpackState(
|
||||
int alignment,
|
||||
int rowLength,
|
||||
int skipRows,
|
||||
int skipPixels,
|
||||
int imageHeight,
|
||||
int skipImages,
|
||||
boolean swapBytes,
|
||||
boolean lsbFirst
|
||||
) {
|
||||
public static final PixelUnpackState DEFAULT = new PixelUnpackState(4, 0, 0, 0, 0, 0, false, false);
|
||||
|
||||
public boolean isDefault() {
|
||||
return this.equals(DEFAULT);
|
||||
}
|
||||
|
||||
public PixelUnpackState with(int pname, int param) {
|
||||
return switch (pname) {
|
||||
case GL11.GL_UNPACK_ALIGNMENT -> (param == 1 || param == 2 || param == 4 || param == 8) ? new PixelUnpackState(param, rowLength, skipRows, skipPixels, imageHeight, skipImages, swapBytes, lsbFirst) : this;
|
||||
case GL11.GL_UNPACK_ROW_LENGTH -> param >= 0 ? new PixelUnpackState(alignment, param, skipRows, skipPixels, imageHeight, skipImages, swapBytes, lsbFirst) : this;
|
||||
case GL11.GL_UNPACK_SKIP_ROWS -> param >= 0 ? new PixelUnpackState(alignment, rowLength, param, skipPixels, imageHeight, skipImages, swapBytes, lsbFirst) : this;
|
||||
case GL11.GL_UNPACK_SKIP_PIXELS -> param >= 0 ? new PixelUnpackState(alignment, rowLength, skipRows, param, imageHeight, skipImages, swapBytes, lsbFirst) : this;
|
||||
case GL12.GL_UNPACK_IMAGE_HEIGHT -> param >= 0 ? new PixelUnpackState(alignment, rowLength, skipRows, skipPixels, param, skipImages, swapBytes, lsbFirst) : this;
|
||||
case GL12.GL_UNPACK_SKIP_IMAGES -> param >= 0 ? new PixelUnpackState(alignment, rowLength, skipRows, skipPixels, imageHeight, param, swapBytes, lsbFirst) : this;
|
||||
case GL11.GL_UNPACK_SWAP_BYTES -> new PixelUnpackState(alignment, rowLength, skipRows, skipPixels, imageHeight, skipImages, param != 0, lsbFirst);
|
||||
case GL11.GL_UNPACK_LSB_FIRST -> new PixelUnpackState(alignment, rowLength, skipRows, skipPixels, imageHeight, skipImages, swapBytes, param != 0);
|
||||
default -> this;
|
||||
};
|
||||
}
|
||||
|
||||
public static void applyDiff(PixelUnpackState from, PixelUnpackState to) {
|
||||
if (from.alignment != to.alignment) RENDER_BACKEND.pixelStorei(GL11.GL_UNPACK_ALIGNMENT, to.alignment);
|
||||
if (from.rowLength != to.rowLength) RENDER_BACKEND.pixelStorei(GL11.GL_UNPACK_ROW_LENGTH, to.rowLength);
|
||||
if (from.skipRows != to.skipRows) RENDER_BACKEND.pixelStorei(GL11.GL_UNPACK_SKIP_ROWS, to.skipRows);
|
||||
if (from.skipPixels != to.skipPixels) RENDER_BACKEND.pixelStorei(GL11.GL_UNPACK_SKIP_PIXELS, to.skipPixels);
|
||||
if (from.imageHeight != to.imageHeight) RENDER_BACKEND.pixelStorei(GL12.GL_UNPACK_IMAGE_HEIGHT, to.imageHeight);
|
||||
if (from.skipImages != to.skipImages) RENDER_BACKEND.pixelStorei(GL12.GL_UNPACK_SKIP_IMAGES, to.skipImages);
|
||||
if (from.swapBytes != to.swapBytes) RENDER_BACKEND.pixelStorei(GL11.GL_UNPACK_SWAP_BYTES, to.swapBytes ? 1 : 0);
|
||||
if (from.lsbFirst != to.lsbFirst) RENDER_BACKEND.pixelStorei(GL11.GL_UNPACK_LSB_FIRST, to.lsbFirst ? 1 : 0);
|
||||
}
|
||||
}
|
||||
@@ -17,6 +17,7 @@ public class TextureInfo {
|
||||
@Getter @Setter protected int magFilter = GL11.GL_LINEAR;
|
||||
@Getter @Setter protected int wrapS = GL11.GL_REPEAT;
|
||||
@Getter @Setter protected int wrapT = GL11.GL_REPEAT;
|
||||
@Getter @Setter protected int baseLevel = 0;
|
||||
@Getter @Setter protected int maxLevel = 1000;
|
||||
@Getter @Setter protected int minLod = -1000;
|
||||
@Getter @Setter protected int maxLod = 1000;
|
||||
@@ -24,6 +25,8 @@ public class TextureInfo {
|
||||
|
||||
@Getter @Setter protected float maxAnisotropy = 1.0f;
|
||||
|
||||
@Getter @Setter protected boolean generateMipmap = false;
|
||||
|
||||
protected TextureInfo(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
+215
@@ -0,0 +1,215 @@
|
||||
package com.gtnewhorizons.angelica.glsm;
|
||||
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
@ExtendWith(GLSMCoreExtension.class)
|
||||
public class GLSM_DisplayList_PixelStore_Test {
|
||||
|
||||
private static final int SRC = 8;
|
||||
private static final int SUB = 4;
|
||||
|
||||
@AfterEach
|
||||
void resetUnpackState() {
|
||||
GLStateManager.glPixelStorei(GL11.GL_UNPACK_ALIGNMENT, 4);
|
||||
setUnpack(0, 0, 0);
|
||||
}
|
||||
|
||||
private static void setUnpack(int rowLength, int skipRows, int skipPixels) {
|
||||
GLStateManager.glPixelStorei(GL11.GL_UNPACK_ROW_LENGTH, rowLength);
|
||||
GLStateManager.glPixelStorei(GL11.GL_UNPACK_SKIP_ROWS, skipRows);
|
||||
GLStateManager.glPixelStorei(GL11.GL_UNPACK_SKIP_PIXELS, skipPixels);
|
||||
}
|
||||
|
||||
private static void setStridedUnpack() {
|
||||
setUnpack(SRC, 1, 2);
|
||||
}
|
||||
|
||||
/** RGBA source; red channel = y*size+x, alpha = 255. */
|
||||
private static ByteBuffer makeSource(int size) {
|
||||
final ByteBuffer buf = ByteBuffer.allocateDirect(size * size * 4).order(ByteOrder.nativeOrder());
|
||||
for (int i = 0; i < size * size; i++) {
|
||||
buf.put((byte) i).put((byte) 0).put((byte) 0).put((byte) 255);
|
||||
}
|
||||
buf.flip();
|
||||
return buf;
|
||||
}
|
||||
|
||||
private static int makeTexture(int size, ByteBuffer pixels) {
|
||||
final int tex = GLStateManager.glGenTextures();
|
||||
GLStateManager.glBindTexture(GL11.GL_TEXTURE_2D, tex);
|
||||
GLStateManager.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA8, size, size, 0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, pixels);
|
||||
return tex;
|
||||
}
|
||||
|
||||
private static ByteBuffer readback(int size) {
|
||||
final ByteBuffer out = ByteBuffer.allocateDirect(size * size * 4).order(ByteOrder.nativeOrder());
|
||||
GLStateManager.glGetTexImage(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, out);
|
||||
return out;
|
||||
}
|
||||
|
||||
private static int red(ByteBuffer pixels, int size, int x, int y) {
|
||||
return pixels.get((y * size + x) * 4) & 0xFF;
|
||||
}
|
||||
|
||||
private static void assertStridedSubImage(ByteBuffer pixels) {
|
||||
for (int y = 0; y < SUB; y++) {
|
||||
for (int x = 0; x < SUB; x++) {
|
||||
assertEquals((y + 1) * SRC + (x + 2), red(pixels, SUB, x, y), "pixel (" + x + "," + y + ")");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void assertTightSubImage(ByteBuffer pixels) {
|
||||
for (int y = 0; y < SUB; y++) {
|
||||
for (int x = 0; x < SUB; x++) {
|
||||
assertEquals(y * SUB + x, red(pixels, SUB, x, y), "pixel (" + x + "," + y + ")");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void assertUnpack(int rowLength, int skipRows, int skipPixels) {
|
||||
assertEquals(rowLength, GL11.glGetInteger(GL11.GL_UNPACK_ROW_LENGTH));
|
||||
assertEquals(skipRows, GL11.glGetInteger(GL11.GL_UNPACK_SKIP_ROWS));
|
||||
assertEquals(skipPixels, GL11.glGetInteger(GL11.GL_UNPACK_SKIP_PIXELS));
|
||||
}
|
||||
|
||||
@Test
|
||||
void pixelStoreExecutesImmediatelyAndIsNotRecorded() {
|
||||
final int list = GLStateManager.glGenLists(1);
|
||||
GLStateManager.glNewList(list, GL11.GL_COMPILE);
|
||||
GLStateManager.glPixelStorei(GL11.GL_UNPACK_ROW_LENGTH, 7);
|
||||
assertEquals(7, GL11.glGetInteger(GL11.GL_UNPACK_ROW_LENGTH), "must execute immediately during recording");
|
||||
GLStateManager.glEndList();
|
||||
assertEquals(7, GL11.glGetInteger(GL11.GL_UNPACK_ROW_LENGTH), "must persist after glEndList");
|
||||
|
||||
GLStateManager.glPixelStorei(GL11.GL_UNPACK_ROW_LENGTH, 0);
|
||||
GLStateManager.glCallList(list);
|
||||
assertEquals(0, GL11.glGetInteger(GL11.GL_UNPACK_ROW_LENGTH), "must not have been recorded into the list");
|
||||
|
||||
GLStateManager.glDeleteLists(list, 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
void stridedTexSubImage2DCompile() {
|
||||
final int tex = makeTexture(SUB, ByteBuffer.allocateDirect(SUB * SUB * 4).order(ByteOrder.nativeOrder()));
|
||||
final ByteBuffer src = makeSource(SRC);
|
||||
|
||||
setStridedUnpack();
|
||||
|
||||
final int list = GLStateManager.glGenLists(1);
|
||||
GLStateManager.glNewList(list, GL11.GL_COMPILE);
|
||||
GLStateManager.glTexSubImage2D(GL11.GL_TEXTURE_2D, 0, 0, 0, SUB, SUB, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, src);
|
||||
GLStateManager.glEndList();
|
||||
|
||||
assertEquals(0, red(readback(SUB), SUB, 0, 0), "GL_COMPILE must not execute the upload");
|
||||
|
||||
setUnpack(0, 0, 0);
|
||||
|
||||
GLStateManager.glCallList(list);
|
||||
assertStridedSubImage(readback(SUB));
|
||||
assertUnpack(0, 0, 0);
|
||||
|
||||
GLStateManager.glDeleteLists(list, 1);
|
||||
GLStateManager.glDeleteTextures(tex);
|
||||
}
|
||||
|
||||
@Test
|
||||
void stridedTexSubImage2DCompileAndExecute() {
|
||||
final ByteBuffer zeros = ByteBuffer.allocateDirect(SUB * SUB * 4).order(ByteOrder.nativeOrder());
|
||||
final int tex = makeTexture(SUB, zeros);
|
||||
final ByteBuffer src = makeSource(SRC);
|
||||
|
||||
setStridedUnpack();
|
||||
|
||||
final int list = GLStateManager.glGenLists(1);
|
||||
GLStateManager.glNewList(list, GL11.GL_COMPILE_AND_EXECUTE);
|
||||
GLStateManager.glTexSubImage2D(GL11.GL_TEXTURE_2D, 0, 0, 0, SUB, SUB, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, src);
|
||||
GLStateManager.glEndList();
|
||||
|
||||
assertStridedSubImage(readback(SUB));
|
||||
|
||||
setUnpack(0, 0, 0);
|
||||
GLStateManager.glTexSubImage2D(GL11.GL_TEXTURE_2D, 0, 0, 0, SUB, SUB, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, zeros);
|
||||
|
||||
GLStateManager.glCallList(list);
|
||||
assertStridedSubImage(readback(SUB));
|
||||
assertUnpack(0, 0, 0);
|
||||
|
||||
GLStateManager.glDeleteLists(list, 1);
|
||||
GLStateManager.glDeleteTextures(tex);
|
||||
}
|
||||
|
||||
@Test
|
||||
void stridedTexImage2DCompile() {
|
||||
final int tex = makeTexture(SUB, ByteBuffer.allocateDirect(SUB * SUB * 4).order(ByteOrder.nativeOrder()));
|
||||
final ByteBuffer src = makeSource(SRC);
|
||||
|
||||
setStridedUnpack();
|
||||
|
||||
final int list = GLStateManager.glGenLists(1);
|
||||
GLStateManager.glNewList(list, GL11.GL_COMPILE);
|
||||
GLStateManager.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA8, SUB, SUB, 0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, src);
|
||||
GLStateManager.glEndList();
|
||||
|
||||
setUnpack(0, 0, 0);
|
||||
|
||||
GLStateManager.glCallList(list);
|
||||
assertStridedSubImage(readback(SUB));
|
||||
assertUnpack(0, 0, 0);
|
||||
|
||||
GLStateManager.glDeleteLists(list, 1);
|
||||
GLStateManager.glDeleteTextures(tex);
|
||||
}
|
||||
|
||||
@Test
|
||||
void defaultRecordedTexSubImage2DReplaysWithDefaults() {
|
||||
final int tex = makeTexture(SUB, ByteBuffer.allocateDirect(SUB * SUB * 4).order(ByteOrder.nativeOrder()));
|
||||
final ByteBuffer src = makeSource(SUB);
|
||||
|
||||
final int list = GLStateManager.glGenLists(1);
|
||||
GLStateManager.glNewList(list, GL11.GL_COMPILE);
|
||||
GLStateManager.glTexSubImage2D(GL11.GL_TEXTURE_2D, 0, 0, 0, SUB, SUB, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, src);
|
||||
GLStateManager.glEndList();
|
||||
|
||||
GLStateManager.glPixelStorei(GL11.GL_UNPACK_ALIGNMENT, 1);
|
||||
setStridedUnpack();
|
||||
|
||||
GLStateManager.glCallList(list);
|
||||
assertTightSubImage(readback(SUB));
|
||||
assertEquals(1, GL11.glGetInteger(GL11.GL_UNPACK_ALIGNMENT), "live state must survive replay");
|
||||
assertUnpack(SRC, 1, 2);
|
||||
|
||||
GLStateManager.glDeleteLists(list, 1);
|
||||
GLStateManager.glDeleteTextures(tex);
|
||||
}
|
||||
|
||||
@Test
|
||||
void defaultRecordedTexImage2DReplaysWithDefaults() {
|
||||
final int tex = makeTexture(SUB, ByteBuffer.allocateDirect(SUB * SUB * 4).order(ByteOrder.nativeOrder()));
|
||||
final ByteBuffer src = makeSource(SUB);
|
||||
|
||||
final int list = GLStateManager.glGenLists(1);
|
||||
GLStateManager.glNewList(list, GL11.GL_COMPILE);
|
||||
GLStateManager.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA8, SUB, SUB, 0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, src);
|
||||
GLStateManager.glEndList();
|
||||
|
||||
GLStateManager.glPixelStorei(GL11.GL_UNPACK_ALIGNMENT, 1);
|
||||
setStridedUnpack();
|
||||
|
||||
GLStateManager.glCallList(list);
|
||||
assertTightSubImage(readback(SUB));
|
||||
assertEquals(1, GL11.glGetInteger(GL11.GL_UNPACK_ALIGNMENT), "live state must survive replay");
|
||||
assertUnpack(SRC, 1, 2);
|
||||
|
||||
GLStateManager.glDeleteLists(list, 1);
|
||||
GLStateManager.glDeleteTextures(tex);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package com.gtnewhorizons.angelica.glsm.states;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL12;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertSame;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
class PixelUnpackStateTest {
|
||||
|
||||
@Test
|
||||
void defaults() {
|
||||
assertTrue(PixelUnpackState.DEFAULT.isDefault());
|
||||
assertEquals(4, PixelUnpackState.DEFAULT.alignment());
|
||||
assertEquals(0, PixelUnpackState.DEFAULT.rowLength());
|
||||
assertFalse(PixelUnpackState.DEFAULT.swapBytes());
|
||||
assertFalse(PixelUnpackState.DEFAULT.lsbFirst());
|
||||
}
|
||||
|
||||
@Test
|
||||
void withUpdatesUnpackParams() {
|
||||
PixelUnpackState s = PixelUnpackState.DEFAULT
|
||||
.with(GL11.GL_UNPACK_ALIGNMENT, 1)
|
||||
.with(GL11.GL_UNPACK_ROW_LENGTH, 64)
|
||||
.with(GL11.GL_UNPACK_SKIP_ROWS, 2)
|
||||
.with(GL11.GL_UNPACK_SKIP_PIXELS, 3)
|
||||
.with(GL12.GL_UNPACK_IMAGE_HEIGHT, 32)
|
||||
.with(GL12.GL_UNPACK_SKIP_IMAGES, 1)
|
||||
.with(GL11.GL_UNPACK_SWAP_BYTES, 1)
|
||||
.with(GL11.GL_UNPACK_LSB_FIRST, 1);
|
||||
assertEquals(new PixelUnpackState(1, 64, 2, 3, 32, 1, true, true), s);
|
||||
assertFalse(s.isDefault());
|
||||
}
|
||||
|
||||
@Test
|
||||
void invalidValuesIgnored() {
|
||||
assertSame(PixelUnpackState.DEFAULT, PixelUnpackState.DEFAULT.with(GL11.GL_UNPACK_ALIGNMENT, 3));
|
||||
assertSame(PixelUnpackState.DEFAULT, PixelUnpackState.DEFAULT.with(GL11.GL_UNPACK_ALIGNMENT, 0));
|
||||
assertSame(PixelUnpackState.DEFAULT, PixelUnpackState.DEFAULT.with(GL11.GL_UNPACK_ROW_LENGTH, -1));
|
||||
assertSame(PixelUnpackState.DEFAULT, PixelUnpackState.DEFAULT.with(GL11.GL_UNPACK_SKIP_ROWS, -5));
|
||||
assertSame(PixelUnpackState.DEFAULT, PixelUnpackState.DEFAULT.with(GL12.GL_UNPACK_IMAGE_HEIGHT, -1));
|
||||
}
|
||||
|
||||
@Test
|
||||
void booleansAcceptAnyNonzero() {
|
||||
assertTrue(PixelUnpackState.DEFAULT.with(GL11.GL_UNPACK_SWAP_BYTES, 2).swapBytes());
|
||||
assertTrue(PixelUnpackState.DEFAULT.with(GL11.GL_UNPACK_LSB_FIRST, -1).lsbFirst());
|
||||
PixelUnpackState on = PixelUnpackState.DEFAULT.with(GL11.GL_UNPACK_SWAP_BYTES, 1);
|
||||
assertFalse(on.with(GL11.GL_UNPACK_SWAP_BYTES, 0).swapBytes());
|
||||
}
|
||||
|
||||
@Test
|
||||
void packAndUnknownPnamesIgnored() {
|
||||
assertSame(PixelUnpackState.DEFAULT, PixelUnpackState.DEFAULT.with(GL11.GL_PACK_ALIGNMENT, 1));
|
||||
assertSame(PixelUnpackState.DEFAULT, PixelUnpackState.DEFAULT.with(GL11.GL_PACK_ROW_LENGTH, 16));
|
||||
assertSame(PixelUnpackState.DEFAULT, PixelUnpackState.DEFAULT.with(0x1234, 1));
|
||||
}
|
||||
}
|
||||
-5
@@ -544,11 +544,6 @@ public final class Lwjgl3GLRenderBackend extends RenderBackend {
|
||||
GL11C.glPixelStorei(pname, param);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pixelStoref(int pname, float param) {
|
||||
GL11C.glPixelStoref(pname, param);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sampleCoverage(float value, boolean invert) {
|
||||
GL13C.glSampleCoverage(value, invert);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.gtnewhorizons.angelica.compat;
|
||||
|
||||
import com.falsepattern.endlessids.config.GeneralConfig;
|
||||
import com.gtnewhorizons.angelica.compat.backhand.BackhandReflectionCompat;
|
||||
import com.gtnewhorizons.angelica.helpers.LoadControllerHelper;
|
||||
import cpw.mods.fml.common.Loader;
|
||||
@@ -14,6 +15,8 @@ public class ModStatus {
|
||||
public static boolean isBetterCrashesLoaded;
|
||||
public static boolean isNEIDLoaded;
|
||||
public static boolean isNEIDMetadataExtended;
|
||||
public static boolean isEIDLoaded;
|
||||
public static boolean isMetadataExtended;
|
||||
public static boolean isLotrLoaded;
|
||||
public static boolean isChunkAPILoaded;
|
||||
public static boolean isEIDBiomeLoaded;
|
||||
@@ -35,9 +38,9 @@ public class ModStatus {
|
||||
|
||||
isBetterCrashesLoaded = Loader.isModLoaded("bettercrashes");
|
||||
isNEIDLoaded = Loader.isModLoaded("neid");
|
||||
isEIDLoaded = Loader.isModLoaded("endlessids");
|
||||
isLotrLoaded = Loader.isModLoaded("lotr");
|
||||
isChunkAPILoaded = Loader.isModLoaded("chunkapi");
|
||||
isEIDBiomeLoaded = Loader.isModLoaded("endlessids_biome");
|
||||
isXaerosMinimapLoaded = Loader.isModLoaded("XaeroMinimap");
|
||||
isHoloInventoryLoaded = Loader.isModLoaded("holoinventory");
|
||||
isBattlegearLoaded = Loader.isModLoaded("battlegear2");
|
||||
@@ -65,5 +68,15 @@ public class ModStatus {
|
||||
isNEIDMetadataExtended = true;
|
||||
}
|
||||
}
|
||||
|
||||
boolean eidBlockItemExtended = false;
|
||||
boolean eidBiomeExtended = false;
|
||||
if (isEIDLoaded) {
|
||||
eidBlockItemExtended = GeneralConfig.extendBlockItem;
|
||||
eidBiomeExtended = GeneralConfig.extendBiome;
|
||||
}
|
||||
|
||||
isEIDBiomeLoaded = eidBiomeExtended || Loader.isModLoaded("endlessids_biome");
|
||||
isMetadataExtended = isNEIDMetadataExtended || eidBlockItemExtended;
|
||||
}
|
||||
}
|
||||
+3
-2
@@ -7,6 +7,7 @@ import static com.gtnewhorizons.angelica.rendering.celeritas.iris.IrisExtendedCh
|
||||
import it.unimi.dsi.fastutil.ints.Int2IntMap;
|
||||
import it.unimi.dsi.fastutil.objects.Reference2ObjectMap;
|
||||
import lombok.Setter;
|
||||
import net.coderbot.iris.block_rendering.BlockMaterialMapping;
|
||||
import net.coderbot.iris.block_rendering.BlockRenderingSettings;
|
||||
import net.coderbot.iris.vertices.ExtendedDataHelper;
|
||||
import net.coderbot.iris.vertices.NormalHelper;
|
||||
@@ -55,7 +56,7 @@ public class IrisExtendedChunkVertexEncoder implements ContextAwareChunkVertexEn
|
||||
public void prepareToRenderBlock(BlockRenderContext ctx, Block block, int metadata, short renderType, byte lightValue) {
|
||||
this.context = ctx;
|
||||
Int2IntMap metaMap = blockMetaMatches != null ? blockMetaMatches.get(block) : null;
|
||||
ctx.blockId = (short) (metaMap != null ? metaMap.get(metadata) : -1);
|
||||
ctx.blockId = (short) (metaMap != null ? BlockMaterialMapping.resolveId(metaMap, metadata) : -1);
|
||||
ctx.renderType = renderType;
|
||||
ctx.lightValue = lightValue;
|
||||
}
|
||||
@@ -84,7 +85,7 @@ public class IrisExtendedChunkVertexEncoder implements ContextAwareChunkVertexEn
|
||||
|
||||
private int lookupFluidMeta(Block block, int metadata) {
|
||||
final Int2IntMap metaMap = blockMetaMatches.get(block);
|
||||
return metaMap != null ? metaMap.get(metadata) : -1;
|
||||
return metaMap != null ? BlockMaterialMapping.resolveId(metaMap, metadata) : -1;
|
||||
}
|
||||
|
||||
private static Block liquidCounterpart(Block block) {
|
||||
|
||||
@@ -13,6 +13,7 @@ import cpw.mods.fml.common.gameevent.InputEvent;
|
||||
import it.unimi.dsi.fastutil.ints.Int2IntMap;
|
||||
import it.unimi.dsi.fastutil.objects.Reference2ObjectMap;
|
||||
import lombok.Getter;
|
||||
import net.coderbot.iris.block_rendering.BlockMaterialMapping;
|
||||
import net.coderbot.iris.block_rendering.BlockRenderingSettings;
|
||||
import net.coderbot.iris.celeritas.IrisCeleritasShaderProvider;
|
||||
import net.coderbot.iris.compat.dh.DHCompat;
|
||||
@@ -948,7 +949,7 @@ public class Iris {
|
||||
return;
|
||||
|
||||
final Int2IntMap metaMap = blockMetaMatches.get(block);
|
||||
final int blockId = metaMap != null ? metaMap.get(meta) : -1;
|
||||
final int blockId = metaMap != null ? BlockMaterialMapping.resolveId(metaMap, meta) : -1;
|
||||
|
||||
if (TessellatorManager.get() instanceof StateAwareTessellator tess)
|
||||
tess.angelica$setShaderOverrideBlockId((short) blockId);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package net.coderbot.iris.block_rendering;
|
||||
|
||||
import com.gtnewhorizons.angelica.compat.ModStatus;
|
||||
import com.gtnewhorizons.angelica.rendering.celeritas.BlockRenderLayer;
|
||||
import it.unimi.dsi.fastutil.ints.Int2IntMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap;
|
||||
@@ -27,10 +28,12 @@ public class BlockMaterialMapping {
|
||||
public record BlockIdMaps(Reference2ObjectMap<Block, Int2IntMap> blockMetaMap, NbtConditionalIdMap<Block> tileEntityMap) {}
|
||||
|
||||
// Meta-key bits OR'd in at runtime
|
||||
public static final int SNOWY_META_BIT = 0x10;
|
||||
public static final int SNOWY_META_BIT = 1 << 16;
|
||||
|
||||
public static final int DOUBLE_PLANT_TOP_BIT = 0x8;
|
||||
|
||||
public static final int WILDCARD_META_KEY = 1 << 30;
|
||||
|
||||
/**
|
||||
* Creates the standard block meta ID map, the TileEntity NBT-conditional map, and registers
|
||||
* snowy blocks on {@link BlockRenderingSettings}.
|
||||
@@ -168,11 +171,17 @@ public class BlockMaterialMapping {
|
||||
|
||||
if (metas.isEmpty()) {
|
||||
for (int meta = 0; meta < 16; meta++) metaMap.putIfAbsent(meta | extraBits, intId);
|
||||
if (ModStatus.isMetadataExtended) metaMap.putIfAbsent(WILDCARD_META_KEY | extraBits, intId);
|
||||
} else {
|
||||
for (int meta : metas) metaMap.putIfAbsent(meta | extraBits, intId);
|
||||
}
|
||||
}
|
||||
|
||||
public static int resolveId(Int2IntMap metaMap, int metaKey) {
|
||||
final int id = metaMap.get(metaKey);
|
||||
return id != -1 ? id : metaMap.get(WILDCARD_META_KEY | (metaKey & SNOWY_META_BIT));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the registered Block for an id, or null if unknown.
|
||||
* The registry returns Blocks.air (its default) for missing keys, which we coerce to null.
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
package net.coderbot.iris.shaderpack;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class DimensionFlatteningMap {
|
||||
private static final Map<String, String> MODERN_TO_LEGACY = new HashMap<>();
|
||||
|
||||
static {
|
||||
MODERN_TO_LEGACY.put("minecraft:overworld", "Overworld");
|
||||
MODERN_TO_LEGACY.put("minecraft:the_nether", "Nether");
|
||||
MODERN_TO_LEGACY.put("minecraft:the_end", "The End");
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps a modern dimension ID to its 1.7.10 string name.
|
||||
*/
|
||||
public static String toLegacyName(String dimensionName) {
|
||||
return MODERN_TO_LEGACY.getOrDefault(dimensionName, dimensionName);
|
||||
}
|
||||
}
|
||||
@@ -25,13 +25,10 @@ import net.coderbot.iris.shaderpack.option.values.MutableOptionValues;
|
||||
import net.coderbot.iris.shaderpack.option.values.OptionValues;
|
||||
import net.coderbot.iris.shaderpack.parsing.BooleanParser;
|
||||
import net.coderbot.iris.shaderpack.preprocessor.JcppProcessor;
|
||||
import net.coderbot.iris.shaderpack.preprocessor.PropertiesPreprocessor;
|
||||
import net.coderbot.iris.shaderpack.texture.CustomTextureData;
|
||||
import net.coderbot.iris.shaderpack.texture.TextureFilteringData;
|
||||
import net.coderbot.iris.shaderpack.texture.TextureStage;
|
||||
import net.coderbot.iris.uniforms.custom.CustomUniforms;
|
||||
import net.irisshaders.iris.api.v0.IrisApi;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
@@ -243,12 +240,8 @@ public class ShaderPack {
|
||||
List<String> invalidFeatureFlags = invalidFlagList.stream().map(FeatureFlags::getHumanReadableName).collect(Collectors.toList());
|
||||
|
||||
if (!invalidFeatureFlags.isEmpty()) {
|
||||
// TODO: GUI
|
||||
// if (Minecraft.getMinecraft().screen instanceof ShaderPackScreen) {
|
||||
// Minecraft.getMinecraft().setScreen(new FeatureMissingErrorScreen(Minecraft.getMinecraft().screen, I18n.format("iris.unsupported.pack"), I18n.format("iris.unsupported.pack.description", FeatureFlags.getInvalidStatus(invalidFlagList), invalidFeatureFlags.stream()
|
||||
// .collect(Collectors.joining(", ", ": ", ".")))));
|
||||
// }
|
||||
IrisApi.getInstance().getConfig().setShadersEnabledAndApply(false);
|
||||
// TODO: GUI?
|
||||
Iris.logger.warn("Shader pack requires unsupported feature flags, loading anyway: {}", String.join(", ", invalidFeatureFlags));
|
||||
}
|
||||
|
||||
ProfileSet profiles = ProfileSet.fromTree(shaderProperties.getProfiles(), this.shaderPackOptions.getOptionSet());
|
||||
@@ -437,7 +430,8 @@ public class ShaderPack {
|
||||
folderNames.add(folderName);
|
||||
|
||||
for (String dimensionName : dimensionNames) {
|
||||
dimensionMap.put(dimensionName, folderName);
|
||||
// Convert modern dimension IDs to 1.7.10 names
|
||||
dimensionMap.put(DimensionFlatteningMap.toLegacyName(dimensionName), folderName);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -667,6 +661,7 @@ public class ShaderPack {
|
||||
*/
|
||||
public ProgramSet getProgramSet(String dimensionName) {
|
||||
int dimensionId = Iris.getCurrentDimensionId();
|
||||
dimensionName = DimensionFlatteningMap.toLegacyName(dimensionName);
|
||||
|
||||
// First, try to find an exact match in the dimension map
|
||||
String folderName = dimensionMap.get(dimensionName);
|
||||
|
||||
@@ -5,6 +5,7 @@ import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap;
|
||||
import it.unimi.dsi.fastutil.objects.Object2IntFunction;
|
||||
import it.unimi.dsi.fastutil.objects.Reference2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap;
|
||||
import net.coderbot.iris.block_rendering.BlockMaterialMapping;
|
||||
import net.coderbot.iris.block_rendering.BlockRenderingSettings;
|
||||
import net.coderbot.iris.block_rendering.NbtConditionalIdMap;
|
||||
import net.coderbot.iris.shaderpack.materialmap.NamespacedId;
|
||||
@@ -96,7 +97,7 @@ public class ItemMaterialHelper {
|
||||
if (blockMetaMatches != null) {
|
||||
Int2IntMap metaMap = blockMetaMatches.get(block);
|
||||
if (metaMap != null) {
|
||||
int id = metaMap.get(itemBlock.getMetadata(metadata));
|
||||
int id = BlockMaterialMapping.resolveId(metaMap, itemBlock.getMetadata(metadata));
|
||||
if (id != -1) {
|
||||
return id;
|
||||
}
|
||||
|
||||
@@ -72,6 +72,11 @@ public class VanillaBiomeList {
|
||||
biomes.add(new BiomeEntry(BiomeGenBase.sky, "END_HIGHLANDS"));
|
||||
biomes.add(new BiomeEntry(BiomeGenBase.sky, "END_BARRENS"));
|
||||
|
||||
// Modern biome variants (1.20+)
|
||||
biomes.add(new BiomeEntry(BiomeGenBase.jungle, "BIOME_SPARSE_JUNGLE"));
|
||||
biomes.add(new BiomeEntry(BiomeGenBase.mushroomIsland, "BIOME_MUSHROOM_FIELDS"));
|
||||
biomes.add(new BiomeEntry(BiomeGenBase.swampland, "BIOME_MANGROVE_SWAMP"));
|
||||
|
||||
return Collections.unmodifiableList(biomes);
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -193,7 +193,7 @@ public abstract class MixinRenderBlocks {
|
||||
CompactCtmQuadProcessor processor = ctx.compact().getProcessor();
|
||||
RenderBlockState renderBlockState = ctx.renderBlockState();
|
||||
CTMUtils.clearCurrentCompact();
|
||||
if (this.blockAccess == null) {
|
||||
if (this.blockAccess == null || renderBlockState.getBlockAccess() == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user