mirror of
https://github.com/GTNewHorizons/Angelica.git
synced 2026-10-26 14:24:30 +00:00
Support glPixelStore in display lists (#1854)
This commit is contained in:
1 parent
805a266059
commit
bf08cd50d9
12 files changed
+554
-190
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;
|
||||
}
|
||||
@@ -1867,7 +1869,7 @@ public class GLStateManager {
|
||||
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;
|
||||
}
|
||||
@@ -1883,7 +1885,7 @@ public class GLStateManager {
|
||||
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;
|
||||
}
|
||||
@@ -1899,7 +1901,7 @@ public class GLStateManager {
|
||||
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;
|
||||
}
|
||||
@@ -1914,7 +1916,7 @@ public class GLStateManager {
|
||||
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);
|
||||
@@ -2202,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);
|
||||
@@ -2216,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);
|
||||
@@ -2234,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);
|
||||
@@ -2252,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);
|
||||
@@ -4439,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);
|
||||
@@ -4449,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);
|
||||
@@ -4459,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);
|
||||
@@ -4468,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);
|
||||
@@ -4557,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;
|
||||
}
|
||||
@@ -4571,7 +4573,7 @@ public class GLStateManager {
|
||||
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;
|
||||
}
|
||||
@@ -4584,7 +4586,7 @@ public class GLStateManager {
|
||||
|
||||
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);
|
||||
@@ -4592,7 +4594,7 @@ public class GLStateManager {
|
||||
|
||||
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);
|
||||
@@ -4601,14 +4603,14 @@ 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);
|
||||
@@ -4616,14 +4618,14 @@ public class GLStateManager {
|
||||
|
||||
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);
|
||||
@@ -4631,7 +4633,7 @@ public class GLStateManager {
|
||||
|
||||
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);
|
||||
}
|
||||
@@ -4766,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);
|
||||
}
|
||||
@@ -4835,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
|
||||
@@ -4941,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);
|
||||
}
|
||||
@@ -5091,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);
|
||||
}
|
||||
}
|
||||
+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);
|
||||
|
||||
Reference in new issue
Block a user