mirror of
https://github.com/GTNewHorizons/Angelica.git
synced 2026-10-25 20:22:22 +00:00
Answer legacy GL queries from tracked state (#2247)
This commit is contained in:
1 parent
2ed838acf1
commit
3978be161d
264 files changed
+7276
-9375
No files matched your search
@@ -10,4 +10,6 @@ on:
|
||||
jobs:
|
||||
build-and-test:
|
||||
uses: GTNewHorizons/GTNH-Actions-Workflows/.github/workflows/build-and-test.yml@master
|
||||
with:
|
||||
disable-spotless-pr: true
|
||||
secrets: inherit
|
||||
@@ -96,6 +96,7 @@ public class Feature {
|
||||
, GLStateManager.getSecondaryColor() // Current secondary color
|
||||
, ShaderManager.getNormalStack() // Current normal vector
|
||||
, ShaderManager.getTexCoordStack() // Current texture coordinates
|
||||
, GLStateManager.getEdgeFlagState()
|
||||
// Current color index
|
||||
// Current raster position
|
||||
// GL_CURRENT_RASTER_POSITION_VALID flag
|
||||
@@ -158,6 +159,8 @@ public class Feature {
|
||||
, GLStateManager.getPolygonOffsetPointState()
|
||||
, GLStateManager.getPolygonOffsetLineState()
|
||||
, GLStateManager.getPolygonOffsetFillState()
|
||||
, GLStateManager.getPointSpriteState()
|
||||
, GLStateManager.getVertexProgramTwoSideState()
|
||||
, GLStateManager.getPolygonSmoothState()
|
||||
, GLStateManager.getPolygonStippleState()
|
||||
, GLStateManager.getRescaleNormalState()
|
||||
@@ -178,6 +181,7 @@ public class Feature {
|
||||
enableBits.add(GLStateManager.getTextures().getTexture1DStates(i));
|
||||
enableBits.add(GLStateManager.getTextures().getTextureUnitStates(i));
|
||||
enableBits.add(GLStateManager.getTextures().getTexture3DStates(i));
|
||||
enableBits.add(GLStateManager.getTextures().getTextureCubeMapStates(i));
|
||||
}
|
||||
|
||||
// Flags GL_TEXTURE_GEN_x where x is S, T, R, or Q
|
||||
@@ -216,13 +220,7 @@ public class Feature {
|
||||
// ^^ GL_FOG_MODE value
|
||||
));
|
||||
attribToFeatures.put(GL11.GL_HINT_BIT, ImmutableSet.of(
|
||||
// GL_PERSPECTIVE_CORRECTION_HINT setting
|
||||
// GL_POINT_SMOOTH_HINT setting
|
||||
// GL_LINE_SMOOTH_HINT setting
|
||||
// GL_POLYGON_SMOOTH_HINT setting
|
||||
// GL_FOG_HINT setting
|
||||
// GL_GENERATE_MIPMAP_HINT setting
|
||||
// GL_TEXTURE_COMPRESSION_HINT setting
|
||||
GLStateManager.getHintState()
|
||||
));
|
||||
attribToFeatures.put(GL11.GL_LIGHTING_BIT, ImmutableSet.of(
|
||||
GLStateManager.getColorMaterial()
|
||||
@@ -286,6 +284,7 @@ public class Feature {
|
||||
));
|
||||
attribToFeatures.put(GL11.GL_POINT_BIT, ImmutableSet.of(
|
||||
GLStateManager.getPointSmoothState()
|
||||
, GLStateManager.getPointSpriteState()
|
||||
, GLStateManager.getPointState()
|
||||
));
|
||||
attribToFeatures.put(GL11.GL_POLYGON_BIT, ImmutableSet.of(
|
||||
@@ -328,6 +327,10 @@ public class Feature {
|
||||
for(int i = 0 ; i < GLStateManager.MAX_TEXTURE_UNITS; i++) {
|
||||
textureAttribs.add(GLStateManager.getTextures().getTextureUnitBindings(i));
|
||||
textureAttribs.add(GLStateManager.getTextures().getTexEnvState(i));
|
||||
textureAttribs.add(GLStateManager.getTextures().getTexture1DStates(i));
|
||||
textureAttribs.add(GLStateManager.getTextures().getTextureUnitStates(i));
|
||||
textureAttribs.add(GLStateManager.getTextures().getTexture3DStates(i));
|
||||
textureAttribs.add(GLStateManager.getTextures().getTextureCubeMapStates(i));
|
||||
}
|
||||
|
||||
// Enable bits GL_TEXTURE_GEN_x where x is S, T, R, or Q
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.gtnewhorizons.angelica.glsm;
|
||||
|
||||
import com.gtnewhorizons.angelica.glsm.ffp.VAOManager;
|
||||
import com.gtnewhorizons.angelica.glsm.recording.ImmediateModeRecorder;
|
||||
import com.gtnewhorizons.angelica.glsm.states.ViewportState;
|
||||
import org.joml.Matrix4f;
|
||||
@@ -141,6 +142,7 @@ public class FeedbackManager {
|
||||
public static void processDrawArrays(int mode, int first, int count) {
|
||||
computeMVP();
|
||||
final GLContextState glCtx = GLStateManager.ctx();
|
||||
if (!glCtx.vaos.isAttribEnabled(0)) return;
|
||||
final int stride = positionStride(glCtx);
|
||||
final long posOffset = positionOffset(glCtx);
|
||||
final int byteCount = count * stride;
|
||||
@@ -154,6 +156,7 @@ public class FeedbackManager {
|
||||
public static void processDrawElements(int mode, int indexCount, int type, long eboOffset) {
|
||||
computeMVP();
|
||||
final GLContextState glCtx = GLStateManager.ctx();
|
||||
if (!glCtx.vaos.isAttribEnabled(0)) return;
|
||||
final int stride = positionStride(glCtx);
|
||||
|
||||
final int elementSize = GLTypes.sizeBytes(type);
|
||||
@@ -210,6 +213,7 @@ public class FeedbackManager {
|
||||
private static void processDrawElementsImpl(int mode, int count, IndexReader reader) {
|
||||
computeMVP();
|
||||
final GLContextState glCtx = GLStateManager.ctx();
|
||||
if (!glCtx.vaos.isAttribEnabled(0)) return;
|
||||
final int stride = positionStride(glCtx);
|
||||
|
||||
int minIdx = Integer.MAX_VALUE, maxIdx = Integer.MIN_VALUE;
|
||||
@@ -261,6 +265,14 @@ public class FeedbackManager {
|
||||
}
|
||||
|
||||
private static void readPositionBuffer(long offset, ByteBuffer destination, GLContextState glCtx) {
|
||||
final VAOManager.Attrib position = glCtx.vaos.attrib(0);
|
||||
if (position != null && position.clientPointer != null) {
|
||||
final ByteBuffer source = position.clientPointer.duplicate();
|
||||
source.position(source.position() + (int) offset);
|
||||
if (source.remaining() > destination.remaining()) source.limit(source.position() + destination.remaining());
|
||||
destination.duplicate().put(source);
|
||||
return;
|
||||
}
|
||||
final int positionVbo = glCtx.vaos.attribVBO(0);
|
||||
final int previousVbo = glCtx.boundVBO;
|
||||
|
||||
|
||||
@@ -47,6 +47,7 @@ import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL12;
|
||||
import org.lwjgl.opengl.GL13;
|
||||
import org.lwjgl.opengl.GL14;
|
||||
import org.lwjgl.opengl.GL20;
|
||||
import org.lwjgl.opengl.GL30;
|
||||
|
||||
import java.nio.DoubleBuffer;
|
||||
@@ -169,6 +170,9 @@ public class GLContextState {
|
||||
public final BooleanStateStack lineSmoothState = track(new BooleanStateStack(GL11.GL_LINE_SMOOTH));
|
||||
public final BooleanStateStack lineStippleState = track(new BooleanStateStack(GL11.GL_LINE_STIPPLE, false, true));
|
||||
public final BooleanStateStack pointSmoothState = track(new BooleanStateStack(GL11.GL_POINT_SMOOTH, false, true));
|
||||
public final BooleanStateStack pointSpriteState = track(new BooleanStateStack(GL20.GL_POINT_SPRITE, false, true));
|
||||
public final BooleanStateStack vertexProgramTwoSideState = track(new BooleanStateStack(GL20.GL_VERTEX_PROGRAM_TWO_SIDE, false, true));
|
||||
public final BooleanStateStack edgeFlagState = track(new BooleanStateStack(GL11.GL_EDGE_FLAG, true, true));
|
||||
public final BooleanStateStack polygonSmoothState = track(new BooleanStateStack(GL11.GL_POLYGON_SMOOTH));
|
||||
public final BooleanStateStack polygonStippleState = track(new BooleanStateStack(GL11.GL_POLYGON_STIPPLE, false, true));
|
||||
public final BooleanStateStack multisampleState = track(new BooleanStateStack(GL13.GL_MULTISAMPLE, true));
|
||||
@@ -182,6 +186,7 @@ public class GLContextState {
|
||||
public final BooleanStateStack polygonOffsetFillState = track(new BooleanStateStack(GL11.GL_POLYGON_OFFSET_FILL));
|
||||
public final LineStateStack lineState = member(new LineStateStack(StackIdAllocator.nextId()));
|
||||
public final PointStateStack pointState = member(new PointStateStack(StackIdAllocator.nextId()));
|
||||
public final IntegerStateStack hintState = member(new IntegerStateStack(0, StackIdAllocator.nextId()).restoreBit(StateSet.R_HINT));
|
||||
public final PolygonStateStack polygonState = member(new PolygonStateStack(StackIdAllocator.nextId()));
|
||||
public final StencilStateStack stencilState = member(new StencilStateStack(StackIdAllocator.nextId()));
|
||||
public int stencilBitMask = 0xFFFFFFFF;
|
||||
@@ -238,10 +243,9 @@ public class GLContextState {
|
||||
public final PixelStoreState[] clientAttribSavedPixelPack = new PixelStoreState[GLStateManager.CLIENT_ATTRIB_STACK_DEPTH];
|
||||
public final int[] clientAttribSavedUnpackBuffer = new int[GLStateManager.CLIENT_ATTRIB_STACK_DEPTH];
|
||||
public final int[] clientAttribSavedPackBuffer = new int[GLStateManager.CLIENT_ATTRIB_STACK_DEPTH];
|
||||
public final int[] clientAttribSavedTextureUnit = new int[GLStateManager.CLIENT_ATTRIB_STACK_DEPTH];
|
||||
public final int[] clientAttribSavedVertexFlags = new int[GLStateManager.CLIENT_ATTRIB_STACK_DEPTH];
|
||||
public final boolean[] clientAttribSavedVertexArray = new boolean[GLStateManager.CLIENT_ATTRIB_STACK_DEPTH];
|
||||
public final VAOManager.ClientArrays[] clientAttribSavedArrays = new VAOManager.ClientArrays[GLStateManager.CLIENT_ATTRIB_STACK_DEPTH];
|
||||
public int clientAttribStackPointer = 0;
|
||||
public float maxPointSize = Float.NaN;
|
||||
public int restoreChangedMask;
|
||||
public long restoreUnitChangedMask;
|
||||
public final BlendState vanillaBlendBefore = new BlendState();
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,167 @@
|
||||
package com.gtnewhorizons.angelica.glsm;
|
||||
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL12;
|
||||
import org.lwjgl.opengl.GL13;
|
||||
import org.lwjgl.opengl.GL14;
|
||||
import org.lwjgl.opengl.GL15;
|
||||
import org.lwjgl.opengl.GL20;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.FloatBuffer;
|
||||
import java.nio.IntBuffer;
|
||||
|
||||
final class LegacyQueries {
|
||||
|
||||
static final int BOOL = 1;
|
||||
static final int INT = 2;
|
||||
static final int FLOAT = 3;
|
||||
static final int FLOATN = 4;
|
||||
|
||||
private static final int COUNT_SHIFT = 3;
|
||||
|
||||
private LegacyQueries() {}
|
||||
|
||||
static int desc(int pname) {
|
||||
return switch (pname) {
|
||||
case GL11.GL_ALPHA_TEST, GL11.GL_AUTO_NORMAL, GL11.GL_COLOR_MATERIAL, GL14.GL_COLOR_SUM, GL11.GL_FOG,
|
||||
GL11.GL_INDEX_LOGIC_OP, GL11.GL_LIGHTING, GL11.GL_LIGHT0, GL11.GL_LIGHT1, GL11.GL_LIGHT2, GL11.GL_LIGHT3,
|
||||
GL11.GL_LIGHT4, GL11.GL_LIGHT5, GL11.GL_LIGHT6, GL11.GL_LIGHT7, GL11.GL_LINE_STIPPLE, GL11.GL_MAP1_COLOR_4,
|
||||
GL11.GL_MAP1_INDEX, GL11.GL_MAP1_NORMAL, GL11.GL_MAP1_TEXTURE_COORD_1, GL11.GL_MAP1_TEXTURE_COORD_2,
|
||||
GL11.GL_MAP1_TEXTURE_COORD_3, GL11.GL_MAP1_TEXTURE_COORD_4, GL11.GL_MAP1_VERTEX_3, GL11.GL_MAP1_VERTEX_4,
|
||||
GL11.GL_MAP2_COLOR_4, GL11.GL_MAP2_INDEX, GL11.GL_MAP2_NORMAL, GL11.GL_MAP2_TEXTURE_COORD_1,
|
||||
GL11.GL_MAP2_TEXTURE_COORD_2, GL11.GL_MAP2_TEXTURE_COORD_3, GL11.GL_MAP2_TEXTURE_COORD_4,
|
||||
GL11.GL_MAP2_VERTEX_3, GL11.GL_MAP2_VERTEX_4, GL11.GL_NORMALIZE, GL11.GL_POINT_SMOOTH,
|
||||
GL11.GL_POLYGON_STIPPLE, GL12.GL_RESCALE_NORMAL, GL11.GL_TEXTURE_1D, GL12.GL_TEXTURE_3D,
|
||||
GL13.GL_TEXTURE_CUBE_MAP, GL11.GL_TEXTURE_GEN_S, GL11.GL_TEXTURE_GEN_T, GL11.GL_TEXTURE_GEN_R,
|
||||
GL11.GL_TEXTURE_GEN_Q, GL11.GL_LIGHT_MODEL_LOCAL_VIEWER, GL11.GL_LIGHT_MODEL_TWO_SIDE,
|
||||
GL11.GL_VERTEX_ARRAY, GL11.GL_NORMAL_ARRAY, GL11.GL_COLOR_ARRAY, GL11.GL_TEXTURE_COORD_ARRAY,
|
||||
GL11.GL_INDEX_ARRAY, GL11.GL_EDGE_FLAG_ARRAY, GL14.GL_SECONDARY_COLOR_ARRAY, GL14.GL_FOG_COORDINATE_ARRAY,
|
||||
GL11.GL_EDGE_FLAG, GL20.GL_POINT_SPRITE, GL20.GL_VERTEX_PROGRAM_TWO_SIDE -> BOOL;
|
||||
case GL11.GL_ALPHA_TEST_FUNC, GL11.GL_LIST_BASE, GL11.GL_MATRIX_MODE, GL11.GL_SHADE_MODEL,
|
||||
GL11.GL_COLOR_MATERIAL_FACE, GL11.GL_COLOR_MATERIAL_PARAMETER, GL12.GL_LIGHT_MODEL_COLOR_CONTROL,
|
||||
GL11.GL_FOG_MODE, GL11.GL_LINE_STIPPLE_PATTERN, GL11.GL_LINE_STIPPLE_REPEAT, GL13.GL_CLIENT_ACTIVE_TEXTURE,
|
||||
GL20.GL_MAX_TEXTURE_COORDS, GL11.GL_RENDER_MODE, GL11.GL_FOG_HINT, GL11.GL_PERSPECTIVE_CORRECTION_HINT,
|
||||
GL11.GL_POINT_SMOOTH_HINT, GL14.GL_GENERATE_MIPMAP_HINT, GL11.GL_LINE_SMOOTH_HINT, GL11.GL_POLYGON_SMOOTH_HINT,
|
||||
GL13.GL_TEXTURE_COMPRESSION_HINT, GL20.GL_FRAGMENT_SHADER_DERIVATIVE_HINT, GL20.GL_POINT_SPRITE_COORD_ORIGIN,
|
||||
GL11.GL_VERTEX_ARRAY_SIZE, GL11.GL_VERTEX_ARRAY_TYPE, GL11.GL_VERTEX_ARRAY_STRIDE, GL15.GL_VERTEX_ARRAY_BUFFER_BINDING,
|
||||
GL11.GL_NORMAL_ARRAY_TYPE, GL11.GL_NORMAL_ARRAY_STRIDE, GL15.GL_NORMAL_ARRAY_BUFFER_BINDING,
|
||||
GL11.GL_COLOR_ARRAY_SIZE, GL11.GL_COLOR_ARRAY_TYPE, GL11.GL_COLOR_ARRAY_STRIDE, GL15.GL_COLOR_ARRAY_BUFFER_BINDING,
|
||||
GL11.GL_INDEX_ARRAY_TYPE, GL11.GL_INDEX_ARRAY_STRIDE, GL15.GL_INDEX_ARRAY_BUFFER_BINDING,
|
||||
GL11.GL_TEXTURE_COORD_ARRAY_SIZE, GL11.GL_TEXTURE_COORD_ARRAY_TYPE, GL11.GL_TEXTURE_COORD_ARRAY_STRIDE,
|
||||
GL15.GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING, GL11.GL_EDGE_FLAG_ARRAY_STRIDE, GL15.GL_EDGE_FLAG_ARRAY_BUFFER_BINDING,
|
||||
GL14.GL_SECONDARY_COLOR_ARRAY_SIZE, GL14.GL_SECONDARY_COLOR_ARRAY_TYPE, GL14.GL_SECONDARY_COLOR_ARRAY_STRIDE,
|
||||
GL15.GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING, GL14.GL_FOG_COORDINATE_ARRAY_TYPE, GL14.GL_FOG_COORDINATE_ARRAY_STRIDE,
|
||||
GL15.GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING -> INT;
|
||||
case GL11.GL_FOG_DENSITY, GL11.GL_FOG_START, GL11.GL_FOG_END, GL14.GL_POINT_SIZE_MIN, GL14.GL_POINT_SIZE_MAX,
|
||||
GL14.GL_POINT_FADE_THRESHOLD_SIZE -> FLOAT;
|
||||
case GL11.GL_ALPHA_TEST_REF -> FLOATN;
|
||||
case GL14.GL_POINT_DISTANCE_ATTENUATION -> FLOAT | 2 << COUNT_SHIFT;
|
||||
case GL11.GL_CURRENT_TEXTURE_COORDS -> FLOAT | 3 << COUNT_SHIFT;
|
||||
case GL11.GL_MODELVIEW_MATRIX, GL11.GL_PROJECTION_MATRIX, GL11.GL_TEXTURE_MATRIX -> FLOATN | 15 << COUNT_SHIFT;
|
||||
case GL11.GL_CURRENT_NORMAL -> FLOATN | 2 << COUNT_SHIFT;
|
||||
case GL11.GL_CURRENT_COLOR, GL14.GL_CURRENT_SECONDARY_COLOR, GL11.GL_FOG_COLOR, GL11.GL_LIGHT_MODEL_AMBIENT -> FLOATN | 3 << COUNT_SHIFT;
|
||||
default -> 0;
|
||||
};
|
||||
}
|
||||
|
||||
static int type(int desc) {
|
||||
return desc & 7;
|
||||
}
|
||||
|
||||
static int count(int desc) {
|
||||
return (desc >> COUNT_SHIFT) + 1;
|
||||
}
|
||||
|
||||
static int floatToInt(float value) {
|
||||
return (int) (2147483647.0 * value);
|
||||
}
|
||||
|
||||
static int lround(float value) {
|
||||
return value < 0 ? -Math.round(-value) : Math.round(value);
|
||||
}
|
||||
|
||||
static int toInt(int type, float value) {
|
||||
return type == FLOATN ? floatToInt(value) : lround(value);
|
||||
}
|
||||
|
||||
private static FloatBuffer fillScratch(GLContextState glCtx, int pname) {
|
||||
final FloatBuffer scratch = glCtx.queryScratch;
|
||||
scratch.clear();
|
||||
GLStateManager.glGetFloat(pname, scratch);
|
||||
return scratch;
|
||||
}
|
||||
|
||||
private static IllegalStateException uncached(int pname) {
|
||||
return new IllegalStateException("Legacy pname 0x" + Integer.toHexString(pname) + " has no cached answer for its declared type");
|
||||
}
|
||||
|
||||
static int getInteger(GLContextState glCtx, int pname, int desc) {
|
||||
final int type = type(desc);
|
||||
if (count(desc) > 1) {
|
||||
return toInt(type, fillScratch(glCtx, pname).get(0));
|
||||
}
|
||||
return switch (type) {
|
||||
case BOOL -> GLStateManager.glGetBoolean(glCtx, pname) ? GL11.GL_TRUE : GL11.GL_FALSE;
|
||||
case FLOAT -> lround(GLStateManager.glGetFloat(glCtx, pname));
|
||||
case FLOATN -> floatToInt(GLStateManager.glGetFloat(glCtx, pname));
|
||||
default -> throw uncached(pname);
|
||||
};
|
||||
}
|
||||
|
||||
static float getFloat(GLContextState glCtx, int pname, int desc) {
|
||||
if (count(desc) > 1) {
|
||||
return fillScratch(glCtx, pname).get(0);
|
||||
}
|
||||
return switch (type(desc)) {
|
||||
case BOOL -> GLStateManager.glGetBoolean(glCtx, pname) ? 1.0f : 0.0f;
|
||||
case INT -> (float) GLStateManager.glGetInteger(glCtx, pname);
|
||||
default -> throw uncached(pname);
|
||||
};
|
||||
}
|
||||
|
||||
static boolean getBoolean(GLContextState glCtx, int pname, int desc) {
|
||||
if (count(desc) > 1) {
|
||||
return fillScratch(glCtx, pname).get(0) != 0.0f;
|
||||
}
|
||||
return switch (type(desc)) {
|
||||
case INT -> GLStateManager.glGetInteger(glCtx, pname) != 0;
|
||||
case FLOAT, FLOATN -> GLStateManager.glGetFloat(glCtx, pname) != 0.0f;
|
||||
default -> throw uncached(pname);
|
||||
};
|
||||
}
|
||||
|
||||
static boolean getIntegerv(GLContextState glCtx, int pname, IntBuffer params) {
|
||||
final int desc = desc(pname);
|
||||
if (desc == 0) return false;
|
||||
final int pos = params.position();
|
||||
final int type = type(desc);
|
||||
final FloatBuffer scratch = fillScratch(glCtx, pname);
|
||||
for (int i = 0, count = count(desc); i < count; i++) {
|
||||
params.put(pos + i, toInt(type, scratch.get(i)));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static boolean getIntegerv(GLContextState glCtx, int pname, int[] params) {
|
||||
final int desc = desc(pname);
|
||||
if (desc == 0) return false;
|
||||
final int type = type(desc);
|
||||
final FloatBuffer scratch = fillScratch(glCtx, pname);
|
||||
for (int i = 0, count = Math.min(count(desc), params.length); i < count; i++) {
|
||||
params[i] = toInt(type, scratch.get(i));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static boolean getBooleanv(GLContextState glCtx, int pname, ByteBuffer params) {
|
||||
final int desc = desc(pname);
|
||||
if (desc == 0) return false;
|
||||
final int pos = params.position();
|
||||
final FloatBuffer scratch = fillScratch(glCtx, pname);
|
||||
for (int i = 0, count = count(desc); i < count; i++) {
|
||||
params.put(pos + i, (byte) (scratch.get(i) != 0.0f ? GL11.GL_TRUE : GL11.GL_FALSE));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -24,6 +24,7 @@ public final class StateSet {
|
||||
public static final int R_ACTIVE_UNIT = 1 << 13;
|
||||
public static final int R_PROGRAM = 1 << 14;
|
||||
public static final int R_SCISSOR = 1 << 15;
|
||||
public static final int R_HINT = 1 << 16;
|
||||
|
||||
public static final int B_FRAG_COLORBUF = 1;
|
||||
public static final int B_FRAG_TEXTURE = 1 << 1;
|
||||
@@ -224,6 +225,9 @@ public final class StateSet {
|
||||
if ((mask & GL11.GL_POINT_BIT) != 0) {
|
||||
restore |= R_POINT;
|
||||
}
|
||||
if ((mask & GL11.GL_HINT_BIT) != 0) {
|
||||
restore |= R_HINT;
|
||||
}
|
||||
if ((mask & GL11.GL_POLYGON_BIT) != 0) {
|
||||
restore |= R_POLYGON;
|
||||
}
|
||||
|
||||
@@ -1,13 +1,20 @@
|
||||
package com.gtnewhorizons.angelica.glsm.ffp;
|
||||
|
||||
import com.gtnewhorizon.gtnhlib.client.renderer.vertex.VertexFormatElement.Usage;
|
||||
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||
import com.gtnewhorizons.angelica.glsm.GLTypes;
|
||||
import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL12;
|
||||
import org.lwjgl.opengl.GL15;
|
||||
import org.lwjgl.opengl.GL30;
|
||||
import org.lwjgl.opengl.GL33;
|
||||
import org.lwjgl.opengl.GL41;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Arrays;
|
||||
|
||||
import static com.gtnewhorizons.angelica.glsm.backend.BackendManager.RENDER_BACKEND;
|
||||
|
||||
@@ -19,12 +26,116 @@ public final class VAOManager {
|
||||
final Int2ObjectOpenHashMap<VAOData> eboOwners = new Int2ObjectOpenHashMap<>();
|
||||
|
||||
private VAOData current = null;
|
||||
public static final int CONV_POSITION = 0;
|
||||
public static final int CONV_NORMAL = 1;
|
||||
public static final int CONV_COLOR = 2;
|
||||
public static final int CONV_SECONDARY_COLOR = 3;
|
||||
public static final int CONV_FOG_COORD = 4;
|
||||
public static final int CONV_INDEX = 5;
|
||||
public static final int CONV_EDGE_FLAG = 6;
|
||||
public static final int CONV_TEX0 = 7;
|
||||
public static final int TEX_COORD_UNITS = 8;
|
||||
public static final int CONV_COUNT = CONV_TEX0 + TEX_COORD_UNITS;
|
||||
|
||||
private static final int[] CONV_LOCATION = new int[CONV_COUNT];
|
||||
private static final int[] LOCATION_CONV = new int[MAX_ATTRIBS];
|
||||
static {
|
||||
Arrays.fill(CONV_LOCATION, -1);
|
||||
Arrays.fill(LOCATION_CONV, -1);
|
||||
mapConventional(CONV_POSITION, Usage.POSITION);
|
||||
mapConventional(CONV_NORMAL, Usage.NORMAL);
|
||||
mapConventional(CONV_COLOR, Usage.COLOR);
|
||||
mapConventional(CONV_TEX0, Usage.PRIMARY_UV);
|
||||
mapConventional(CONV_TEX0 + 1, Usage.SECONDARY_UV);
|
||||
}
|
||||
|
||||
private static void mapConventional(int conv, Usage usage) {
|
||||
final int location = usage.getAttributeLocation();
|
||||
CONV_LOCATION[conv] = location;
|
||||
LOCATION_CONV[location] = conv;
|
||||
}
|
||||
|
||||
public static int conventionalLocation(int conv) {
|
||||
return CONV_LOCATION[conv];
|
||||
}
|
||||
|
||||
private static final int T_BYTE = 1, T_UBYTE = 1 << 1, T_SHORT = 1 << 2, T_USHORT = 1 << 3, T_INT = 1 << 4, T_UINT = 1 << 5, T_FLOAT = 1 << 6;
|
||||
private static final int T_DOUBLE = 1 << 10, T_HALF = 1 << 11, T_FIXED = 1 << 12, T_PACKED = 1 << 13, T_PACKED_FLOAT = 1 << 14;
|
||||
private static final int T_INTEGER = T_BYTE | T_UBYTE | T_SHORT | T_USHORT | T_INT | T_UINT;
|
||||
private static final int T_COLOR = T_INTEGER | T_HALF | T_FLOAT | T_DOUBLE | T_PACKED;
|
||||
private static final int T_GENERIC = T_COLOR | T_FIXED | T_PACKED_FLOAT;
|
||||
private static final int[] LEGAL_TYPES = new int[CONV_COUNT];
|
||||
private static final int[] MIN_SIZE = new int[CONV_COUNT];
|
||||
private static final int[] MAX_SIZE = new int[CONV_COUNT];
|
||||
static {
|
||||
legal(CONV_POSITION, T_SHORT | T_INT | T_FLOAT | T_DOUBLE | T_HALF | T_PACKED, 2, 4);
|
||||
legal(CONV_NORMAL, T_BYTE | T_SHORT | T_INT | T_HALF | T_FLOAT | T_DOUBLE | T_PACKED, 3, 3);
|
||||
legal(CONV_COLOR, T_COLOR, 3, 4);
|
||||
legal(CONV_SECONDARY_COLOR, T_COLOR, 3, 4);
|
||||
legal(CONV_FOG_COORD, T_HALF | T_FLOAT | T_DOUBLE, 1, 1);
|
||||
legal(CONV_INDEX, T_UBYTE | T_SHORT | T_INT | T_FLOAT | T_DOUBLE, 1, 1);
|
||||
legal(CONV_EDGE_FLAG, T_UBYTE, 1, 1);
|
||||
for (int unit = 0; unit < TEX_COORD_UNITS; unit++) {
|
||||
legal(CONV_TEX0 + unit, T_SHORT | T_INT | T_HALF | T_FLOAT | T_DOUBLE | T_PACKED, 1, 4);
|
||||
}
|
||||
}
|
||||
|
||||
private static void legal(int conv, int types, int minSize, int maxSize) {
|
||||
LEGAL_TYPES[conv] = types;
|
||||
MIN_SIZE[conv] = minSize;
|
||||
MAX_SIZE[conv] = maxSize;
|
||||
}
|
||||
|
||||
private static int typeBit(int type) {
|
||||
if (type >= GL11.GL_BYTE && type <= GL30.GL_HALF_FLOAT) return 1 << type - GL11.GL_BYTE;
|
||||
return switch (type) {
|
||||
case GL41.GL_FIXED -> T_FIXED;
|
||||
case GL12.GL_UNSIGNED_INT_2_10_10_10_REV, GL33.GL_INT_2_10_10_10_REV -> T_PACKED;
|
||||
case GL30.GL_UNSIGNED_INT_10F_11F_11F_REV -> T_PACKED_FLOAT;
|
||||
default -> 0;
|
||||
};
|
||||
}
|
||||
|
||||
private static boolean isLegal(int types, int minSize, int maxSize, boolean bgra, int size, int type) {
|
||||
final int bit = typeBit(type);
|
||||
if ((types & bit) == 0) return false;
|
||||
if (size == GL12.GL_BGRA) return bgra && (bit & (T_UBYTE | T_PACKED)) != 0;
|
||||
return size >= minSize && size <= maxSize;
|
||||
}
|
||||
|
||||
public static boolean isLegalConventional(int conv, int size, int type) {
|
||||
return isLegal(LEGAL_TYPES[conv], MIN_SIZE[conv], MAX_SIZE[conv], conv == CONV_COLOR || conv == CONV_SECONDARY_COLOR, size, type);
|
||||
}
|
||||
|
||||
public static boolean isLegalGeneric(int index, int size, int type, boolean integer) {
|
||||
return index >= 0 && index < MAX_ATTRIBS && isLegal(integer ? T_INTEGER : T_GENERIC, 1, 4, !integer, size, type);
|
||||
}
|
||||
|
||||
private int currentVertexFlags = 0;
|
||||
private int genericEnabled = 0;
|
||||
private int conventionalEnabled = 0;
|
||||
private Attrib[] currentAttribs = null;
|
||||
private Attrib[] currentGeneric = null;
|
||||
private Attrib[] currentConventional = null;
|
||||
public int boundEBO = 0;
|
||||
|
||||
private int clientSideEnabledCount = 0;
|
||||
private int arrayVersion = 0;
|
||||
private int versionClock = 0;
|
||||
private int bufferEpoch = 0;
|
||||
private final Int2IntOpenHashMap bufferDeletedAt = new Int2IntOpenHashMap();
|
||||
|
||||
private void touch() {
|
||||
arrayVersion = ++versionClock;
|
||||
}
|
||||
|
||||
private boolean isBufferLive(int buffer, int sinceEpoch) {
|
||||
return bufferDeletedAt.get(buffer) <= sinceEpoch;
|
||||
}
|
||||
|
||||
public boolean isBufferLive(Attrib a) {
|
||||
return isBufferLive(a.vboId, a.epoch);
|
||||
}
|
||||
|
||||
public void init(int defaultVAO) {
|
||||
final VAOData data = new VAOData();
|
||||
@@ -45,6 +156,10 @@ public final class VAOManager {
|
||||
// Save old VAO data
|
||||
if (current != null) {
|
||||
current.vertexFlags = currentVertexFlags;
|
||||
current.genericEnabled = genericEnabled;
|
||||
current.conventionalEnabled = conventionalEnabled;
|
||||
current.generic = currentGeneric;
|
||||
current.conventional = currentConventional;
|
||||
if (current.ebo != boundEBO) {
|
||||
removeEboOwner(current.ebo, current);
|
||||
current.ebo = boundEBO;
|
||||
@@ -52,6 +167,7 @@ public final class VAOManager {
|
||||
}
|
||||
current.attribs = currentAttribs;
|
||||
current.clientSideEnabledCount = clientSideEnabledCount;
|
||||
current.arrayVersion = arrayVersion;
|
||||
}
|
||||
|
||||
VAOData data = vaoMap.get(vaoId);
|
||||
@@ -61,9 +177,14 @@ public final class VAOManager {
|
||||
}
|
||||
current = data;
|
||||
currentVertexFlags = data.vertexFlags;
|
||||
genericEnabled = data.genericEnabled;
|
||||
conventionalEnabled = data.conventionalEnabled;
|
||||
currentAttribs = data.attribs;
|
||||
currentGeneric = data.generic;
|
||||
currentConventional = data.conventional;
|
||||
boundEBO = data.ebo;
|
||||
clientSideEnabledCount = data.clientSideEnabledCount;
|
||||
arrayVersion = data.arrayVersion;
|
||||
}
|
||||
|
||||
public void onDeleteVertexArray(int vaoId) {
|
||||
@@ -73,8 +194,25 @@ public final class VAOManager {
|
||||
if (data == current) current = null;
|
||||
}
|
||||
|
||||
private static boolean detach(Attrib[] slots, int buffer) {
|
||||
boolean detached = false;
|
||||
for (final Attrib a : slots) {
|
||||
if (a != null && a.vboId == buffer) {
|
||||
a.vboId = 0;
|
||||
detached = true;
|
||||
}
|
||||
}
|
||||
return detached;
|
||||
}
|
||||
|
||||
public void onDeleteBuffer(int buffer) {
|
||||
if (buffer == 0) return;
|
||||
bufferDeletedAt.put(buffer, ++bufferEpoch);
|
||||
if (currentAttribs != null) {
|
||||
boolean detached = detach(currentGeneric != null ? currentGeneric : currentAttribs, buffer);
|
||||
if (currentConventional != null) detached |= detach(currentConventional, buffer);
|
||||
if (detached) touch();
|
||||
}
|
||||
VAOData owner = eboOwners.remove(buffer);
|
||||
while (owner != null) {
|
||||
final VAOData next = owner.nextEboOwner;
|
||||
@@ -112,14 +250,19 @@ public final class VAOManager {
|
||||
public void enableClientVertexFlag(int flag) { currentVertexFlags |= flag; }
|
||||
public void disableClientVertexFlag(int flag) { currentVertexFlags &= ~flag; }
|
||||
public int getVertexFlags() { return currentVertexFlags; }
|
||||
public void setVertexFlags(int flags) { currentVertexFlags = flags; }
|
||||
public boolean isConventionalEnabled(int conv) { return (conventionalEnabled >> conv & 1) != 0; }
|
||||
public static void setCurrentVertexFlags(int flags) { GLStateManager.ctx().vaos.currentVertexFlags = flags; }
|
||||
|
||||
public static final class VAOData {
|
||||
public Attrib[] attribs;
|
||||
public int vertexFlags;
|
||||
public int genericEnabled;
|
||||
public int conventionalEnabled;
|
||||
public Attrib[] generic;
|
||||
public Attrib[] conventional;
|
||||
public int ebo;
|
||||
public int clientSideEnabledCount;
|
||||
int arrayVersion;
|
||||
private VAOData nextEboOwner;
|
||||
|
||||
public VAOData() {
|
||||
@@ -127,92 +270,307 @@ public final class VAOManager {
|
||||
}
|
||||
}
|
||||
|
||||
public void setAttribute(int index, int size, int type, boolean normalized, int stride, long offset, int vboId) {
|
||||
if (index < 0 || index >= MAX_ATTRIBS) return;
|
||||
final Attrib a = getAttrib(index);
|
||||
final boolean wasClient = a.clientPointer != null;
|
||||
public boolean setAttribute(int index, int size, int type, boolean normalized, int stride, long offset, int vboId) {
|
||||
return setGeneric(index, size, type, normalized, false, stride, offset, vboId, null);
|
||||
}
|
||||
|
||||
public boolean setAttribute(int index, int size, int type, boolean normalized, int stride, ByteBuffer pointer) {
|
||||
return setGeneric(index, size, type, normalized, false, stride, 0, 0, pointer);
|
||||
}
|
||||
|
||||
public boolean setIntegerAttribute(int index, int size, int type, int stride, long offset, int vboId) {
|
||||
return setGeneric(index, size, type, false, true, stride, offset, vboId, null);
|
||||
}
|
||||
|
||||
public boolean setIntegerAttribute(int index, int size, int type, int stride, ByteBuffer pointer) {
|
||||
return setGeneric(index, size, type, false, true, stride, 0, 0, pointer);
|
||||
}
|
||||
|
||||
public boolean setConventional(int conv, int size, int type, boolean normalized, int stride, long offset, int vboId) {
|
||||
return setConventional(conv, size, type, normalized, stride, offset, vboId, null);
|
||||
}
|
||||
|
||||
public boolean setConventional(int conv, int size, int type, boolean normalized, int stride, ByteBuffer pointer) {
|
||||
return setConventional(conv, size, type, normalized, stride, 0, 0, pointer);
|
||||
}
|
||||
|
||||
private boolean setGeneric(int index, int size, int type, boolean normalized, boolean integer, int stride, long offset, int vboId, ByteBuffer pointer) {
|
||||
if (index < 0 || index >= MAX_ATTRIBS) return false;
|
||||
final Attrib g = genericSlot(index);
|
||||
store(g, size, type, normalized, integer, stride, offset, vboId, pointer);
|
||||
if (currentAttribs[index] == g) return true;
|
||||
if (!isGenericEnabled(index) && isLocationConventionalEnabled(index)) return false;
|
||||
apply(index, g);
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean setConventional(int conv, int size, int type, boolean normalized, int stride, long offset, int vboId, ByteBuffer pointer) {
|
||||
if (conv < 0 || conv >= CONV_COUNT) return false;
|
||||
final Attrib c = conventionalSlot(conv);
|
||||
store(c, size, type, normalized, false, stride, offset, vboId, pointer);
|
||||
final int index = CONV_LOCATION[conv];
|
||||
if (index < 0) return false;
|
||||
if (currentAttribs[index] == c) return true;
|
||||
if (isGenericEnabled(index)) return false;
|
||||
apply(index, c);
|
||||
return true;
|
||||
}
|
||||
|
||||
private void store(Attrib a, int size, int type, boolean normalized, boolean integer, int stride, long offset, int vboId, ByteBuffer pointer) {
|
||||
final boolean wasClient = a.isClientSide();
|
||||
a.size = size;
|
||||
a.type = type;
|
||||
a.normalized = normalized;
|
||||
a.integer = integer;
|
||||
a.stride = stride;
|
||||
a.offset = offset;
|
||||
a.vboId = vboId;
|
||||
a.clientPointer = null;
|
||||
a.genericPointer = true;
|
||||
if (wasClient && a.enabled) {
|
||||
clientSideEnabledCount--;
|
||||
}
|
||||
}
|
||||
|
||||
public void setAttribute(int index, int size, int type, boolean normalized, int stride, ByteBuffer pointer) {
|
||||
if (index < 0 || index >= MAX_ATTRIBS) return;
|
||||
final Attrib a = getAttrib(index);
|
||||
final boolean wasClient = a.clientPointer != null;
|
||||
a.size = size;
|
||||
a.type = type;
|
||||
a.normalized = normalized;
|
||||
a.stride = stride;
|
||||
a.offset = 0;
|
||||
a.vboId = 0;
|
||||
a.epoch = bufferEpoch;
|
||||
a.clientPointer = pointer;
|
||||
a.genericPointer = true;
|
||||
if (!wasClient && a.enabled) {
|
||||
clientSideEnabledCount++;
|
||||
if (wasClient != a.isClientSide()) clientSideEnabledCount += wasClient ? -1 : 1;
|
||||
touch();
|
||||
}
|
||||
|
||||
private void apply(int index, Attrib source) {
|
||||
final Attrib old = currentAttribs[index];
|
||||
if (old != null) {
|
||||
if (old.isClientSide()) clientSideEnabledCount--;
|
||||
source.enabled = old.enabled;
|
||||
old.enabled = false;
|
||||
if (source.isClientSide()) clientSideEnabledCount++;
|
||||
}
|
||||
currentAttribs[index] = source;
|
||||
}
|
||||
|
||||
private boolean isGenericEnabled(int index) {
|
||||
return (genericEnabled >> index & 1) != 0;
|
||||
}
|
||||
|
||||
private boolean isLocationConventionalEnabled(int index) {
|
||||
final int conv = LOCATION_CONV[index];
|
||||
return conv >= 0 && isConventionalEnabled(conv);
|
||||
}
|
||||
|
||||
private Attrib generic(int index) {
|
||||
return (currentGeneric != null ? currentGeneric : currentAttribs)[index];
|
||||
}
|
||||
|
||||
private Attrib genericSlot(int index) {
|
||||
final Attrib[] slots = currentGeneric != null ? currentGeneric : currentAttribs;
|
||||
Attrib g = slots[index];
|
||||
if (g == null) {
|
||||
g = new Attrib();
|
||||
g.genericPointer = true;
|
||||
slots[index] = g;
|
||||
if (currentAttribs[index] == null) currentAttribs[index] = g;
|
||||
}
|
||||
return g;
|
||||
}
|
||||
|
||||
private Attrib conventionalSlot(int conv) {
|
||||
if (currentConventional == null) {
|
||||
currentConventional = new Attrib[CONV_COUNT];
|
||||
currentGeneric = currentAttribs.clone();
|
||||
}
|
||||
Attrib c = currentConventional[conv];
|
||||
if (c == null) {
|
||||
c = new Attrib();
|
||||
currentConventional[conv] = c;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
private boolean refresh(int index) {
|
||||
touch();
|
||||
boolean repoint = false;
|
||||
final boolean conventional = isLocationConventionalEnabled(index);
|
||||
final Attrib winner = isGenericEnabled(index) ? genericSlot(index) : conventional ? currentConventional[LOCATION_CONV[index]] : null;
|
||||
if (winner != null && winner != currentAttribs[index]) {
|
||||
apply(index, winner);
|
||||
repoint = true;
|
||||
}
|
||||
final boolean enabled = winner != null;
|
||||
Attrib e = currentAttribs[index];
|
||||
if (e == null) {
|
||||
if (!enabled) return repoint;
|
||||
e = genericSlot(index);
|
||||
}
|
||||
if (e.enabled != enabled) {
|
||||
if (e.clientPointer != null) clientSideEnabledCount += enabled ? 1 : -1;
|
||||
e.enabled = enabled;
|
||||
}
|
||||
return repoint;
|
||||
}
|
||||
|
||||
public boolean enableAttribute(int index) {
|
||||
if (index < 0 || index >= MAX_ATTRIBS) return false;
|
||||
genericEnabled |= 1 << index;
|
||||
return refresh(index);
|
||||
}
|
||||
|
||||
public boolean disableAttribute(int index) {
|
||||
if (index < 0 || index >= MAX_ATTRIBS) return false;
|
||||
genericEnabled &= ~(1 << index);
|
||||
return refresh(index);
|
||||
}
|
||||
|
||||
public boolean setConventionalEnabled(int conv, boolean enabled) {
|
||||
if (conv < 0 || conv >= CONV_COUNT) return false;
|
||||
conventionalSlot(conv);
|
||||
if (enabled) {
|
||||
conventionalEnabled |= 1 << conv;
|
||||
} else {
|
||||
conventionalEnabled &= ~(1 << conv);
|
||||
}
|
||||
final int index = CONV_LOCATION[conv];
|
||||
if (index >= 0) return refresh(index);
|
||||
touch();
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean setDivisor(int index, int divisor) {
|
||||
if (index < 0 || index >= MAX_ATTRIBS) return true;
|
||||
final Attrib g = genericSlot(index);
|
||||
g.divisor = divisor;
|
||||
touch();
|
||||
return currentAttribs[index] == g;
|
||||
}
|
||||
|
||||
public @Nullable Attrib conventional(int conv) {
|
||||
return conv >= 0 && currentConventional != null ? currentConventional[conv] : null;
|
||||
}
|
||||
|
||||
public static final class ClientArrays {
|
||||
public int boundVAO;
|
||||
public int boundVBO;
|
||||
public int boundEBO;
|
||||
public int clientActiveTextureUnit;
|
||||
int arrayVersion;
|
||||
int bufferEpoch;
|
||||
int vertexFlags;
|
||||
int genericEnabled;
|
||||
int conventionalEnabled;
|
||||
int genericPresent;
|
||||
int conventionalPresent;
|
||||
int effectiveGeneric;
|
||||
final Attrib[] generic = new Attrib[MAX_ATTRIBS];
|
||||
final Attrib[] conventional = new Attrib[CONV_COUNT];
|
||||
}
|
||||
|
||||
private static void saveSlot(Attrib[] saved, int i, Attrib source) {
|
||||
if (saved[i] == null) saved[i] = new Attrib();
|
||||
saved[i].copyPointer(source);
|
||||
}
|
||||
|
||||
public boolean isBufferLive(int buffer, ClientArrays saved) {
|
||||
return isBufferLive(buffer, saved.bufferEpoch);
|
||||
}
|
||||
|
||||
public void saveClientArrays(ClientArrays out) {
|
||||
out.arrayVersion = arrayVersion;
|
||||
out.bufferEpoch = bufferEpoch;
|
||||
out.vertexFlags = currentVertexFlags;
|
||||
out.genericEnabled = genericEnabled;
|
||||
out.conventionalEnabled = conventionalEnabled;
|
||||
out.genericPresent = 0;
|
||||
out.conventionalPresent = 0;
|
||||
out.effectiveGeneric = 0;
|
||||
for (int i = 0; i < MAX_ATTRIBS; i++) {
|
||||
final Attrib g = generic(i);
|
||||
if (g != null) {
|
||||
out.genericPresent |= 1 << i;
|
||||
saveSlot(out.generic, i, g);
|
||||
}
|
||||
final Attrib e = currentAttribs[i];
|
||||
if (e != null && e.genericPointer) out.effectiveGeneric |= 1 << i;
|
||||
}
|
||||
if (currentConventional == null) return;
|
||||
for (int i = 0; i < CONV_COUNT; i++) {
|
||||
final Attrib c = currentConventional[i];
|
||||
if (c != null) {
|
||||
out.conventionalPresent |= 1 << i;
|
||||
saveSlot(out.conventional, i, c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isGenericPointerEnabled(int index) {
|
||||
private final Attrib[] restoreBefore = new Attrib[MAX_ATTRIBS];
|
||||
|
||||
public int restoreClientArrays(ClientArrays in) {
|
||||
currentVertexFlags = in.vertexFlags;
|
||||
if (arrayVersion == in.arrayVersion) return 0;
|
||||
for (int i = 0; i < MAX_ATTRIBS; i++) {
|
||||
if (restoreBefore[i] == null) restoreBefore[i] = new Attrib();
|
||||
final Attrib e = currentAttribs[i];
|
||||
if (e == null) {
|
||||
restoreBefore[i].clearPointer();
|
||||
restoreBefore[i].enabled = false;
|
||||
} else {
|
||||
restoreBefore[i].copyPointer(e);
|
||||
restoreBefore[i].enabled = e.enabled;
|
||||
}
|
||||
}
|
||||
genericEnabled = in.genericEnabled;
|
||||
conventionalEnabled = in.conventionalEnabled;
|
||||
for (int i = 0; i < MAX_ATTRIBS; i++) {
|
||||
if ((in.genericPresent >> i & 1) != 0) {
|
||||
genericSlot(i).copyPointer(in.generic[i]);
|
||||
} else {
|
||||
final Attrib g = generic(i);
|
||||
if (g != null) g.clearPointer();
|
||||
}
|
||||
}
|
||||
if (currentConventional != null || in.conventionalPresent != 0) {
|
||||
for (int i = 0; i < CONV_COUNT; i++) {
|
||||
if ((in.conventionalPresent >> i & 1) != 0) {
|
||||
conventionalSlot(i).copyPointer(in.conventional[i]);
|
||||
} else if (currentConventional != null && currentConventional[i] != null) {
|
||||
currentConventional[i].clearPointer();
|
||||
}
|
||||
}
|
||||
}
|
||||
clientSideEnabledCount = 0;
|
||||
for (int i = 0; i < MAX_ATTRIBS; i++) {
|
||||
final int conv = LOCATION_CONV[i];
|
||||
final Attrib g = generic(i);
|
||||
final Attrib c = conventional(conv);
|
||||
final boolean conventional = isLocationConventionalEnabled(i);
|
||||
Attrib e;
|
||||
if (isGenericEnabled(i)) {
|
||||
e = genericSlot(i);
|
||||
} else if (conventional) {
|
||||
e = conventionalSlot(conv);
|
||||
} else {
|
||||
e = c == null || (in.effectiveGeneric >> i & 1) != 0 ? g : c;
|
||||
}
|
||||
if (g != null) g.enabled = false;
|
||||
if (c != null) c.enabled = false;
|
||||
currentAttribs[i] = e;
|
||||
if (e != null) {
|
||||
e.enabled = isGenericEnabled(i) || conventional;
|
||||
if (e.isClientSide()) clientSideEnabledCount++;
|
||||
}
|
||||
}
|
||||
int changed = 0;
|
||||
for (int i = 0; i < MAX_ATTRIBS; i++) {
|
||||
final Attrib e = currentAttribs[i];
|
||||
final Attrib before = restoreBefore[i];
|
||||
if (e == null) {
|
||||
if (before.enabled) changed |= 0x10000 << i;
|
||||
} else {
|
||||
if (e.enabled != before.enabled) changed |= 0x10000 << i;
|
||||
if (!e.samePointer(before)) changed |= 1 << i;
|
||||
}
|
||||
before.clientPointer = null;
|
||||
}
|
||||
arrayVersion = in.arrayVersion;
|
||||
return changed;
|
||||
}
|
||||
|
||||
public boolean isAttribEnabled(int index) {
|
||||
if (index < 0 || index >= MAX_ATTRIBS) return false;
|
||||
final Attrib a = currentAttribs[index];
|
||||
return a != null && a.genericPointer && a.enabled;
|
||||
}
|
||||
|
||||
public void markConventional(int index) {
|
||||
if (index < 0 || index >= MAX_ATTRIBS) return;
|
||||
final Attrib a = currentAttribs[index];
|
||||
if (a != null) a.genericPointer = false;
|
||||
}
|
||||
|
||||
public void setEnabled(int index, boolean enabled) {
|
||||
if (index < 0 || index >= MAX_ATTRIBS) return;
|
||||
final Attrib a = getAttrib(index);
|
||||
if (a.clientPointer != null && a.enabled != enabled) {
|
||||
clientSideEnabledCount += enabled ? 1 : -1;
|
||||
}
|
||||
a.enabled = enabled;
|
||||
}
|
||||
|
||||
public void enableAttribute(int index) {
|
||||
if (index < 0 || index >= MAX_ATTRIBS) return;
|
||||
final Attrib a = getAttrib(index);
|
||||
if (a.clientPointer != null && !a.enabled) {
|
||||
clientSideEnabledCount++;
|
||||
}
|
||||
a.enabled = true;
|
||||
}
|
||||
|
||||
public void disableAttribute(int index) {
|
||||
if (index < 0 || index >= MAX_ATTRIBS) return;
|
||||
final Attrib a = getAttrib(index);
|
||||
if (a.clientPointer != null && a.enabled) {
|
||||
clientSideEnabledCount--;
|
||||
}
|
||||
a.enabled = false;
|
||||
}
|
||||
|
||||
// Lazily allocate each attrib. Most VAOs don't even have 4 attribs, let alone 16.
|
||||
private Attrib getAttrib(int index) {
|
||||
Attrib a = currentAttribs[index];
|
||||
if (a == null) {
|
||||
a = new Attrib();
|
||||
currentAttribs[index] = a;
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
public boolean isClientSideAttrib(int index) {
|
||||
final Attrib attrib = currentAttribs[index];
|
||||
return attrib != null && attrib.isClientSide();
|
||||
return a != null && a.enabled;
|
||||
}
|
||||
|
||||
public Attrib attrib(int index) {
|
||||
@@ -286,7 +644,11 @@ public final class VAOManager {
|
||||
if (clientArraysVBOOffsets[i] < 0) continue;
|
||||
final VAOManager.Attrib a = currentAttribs[i];
|
||||
RENDER_BACKEND.bufferSubData(GL15.GL_ARRAY_BUFFER, clientArraysVBOOffsets[i], a.clientPointer.duplicate());
|
||||
RENDER_BACKEND.vertexAttribPointer(i, a.size, a.type, a.normalized, a.stride, (long) clientArraysVBOOffsets[i]);
|
||||
if (a.integer) {
|
||||
RENDER_BACKEND.vertexAttribIPointer(i, a.size, a.type, a.stride, (long) clientArraysVBOOffsets[i]);
|
||||
} else {
|
||||
RENDER_BACKEND.vertexAttribPointer(i, a.size, a.type, a.normalized, a.stride, (long) clientArraysVBOOffsets[i]);
|
||||
}
|
||||
}
|
||||
|
||||
GLStateManager.glBindBuffer(GL15.GL_ARRAY_BUFFER, savedVBO);
|
||||
@@ -298,9 +660,12 @@ public final class VAOManager {
|
||||
public int size;
|
||||
public int type;
|
||||
public boolean normalized;
|
||||
public boolean integer;
|
||||
public int stride;
|
||||
public long offset;
|
||||
public int vboId;
|
||||
public int divisor;
|
||||
int epoch;
|
||||
public ByteBuffer clientPointer;
|
||||
public boolean genericPointer;
|
||||
|
||||
@@ -308,16 +673,35 @@ public final class VAOManager {
|
||||
return enabled && clientPointer != null;
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
enabled = false;
|
||||
void copyPointer(Attrib source) {
|
||||
size = source.size;
|
||||
type = source.type;
|
||||
normalized = source.normalized;
|
||||
integer = source.integer;
|
||||
stride = source.stride;
|
||||
offset = source.offset;
|
||||
vboId = source.vboId;
|
||||
divisor = source.divisor;
|
||||
epoch = source.epoch;
|
||||
clientPointer = source.clientPointer;
|
||||
}
|
||||
|
||||
boolean samePointer(Attrib other) {
|
||||
return size == other.size && type == other.type && normalized == other.normalized && integer == other.integer
|
||||
&& stride == other.stride && offset == other.offset && vboId == other.vboId && divisor == other.divisor
|
||||
&& clientPointer == other.clientPointer;
|
||||
}
|
||||
|
||||
void clearPointer() {
|
||||
size = 0;
|
||||
type = 0;
|
||||
normalized = false;
|
||||
integer = false;
|
||||
stride = 0;
|
||||
offset = 0;
|
||||
vboId = 0;
|
||||
divisor = 0;
|
||||
clientPointer = null;
|
||||
genericPointer = false;
|
||||
}
|
||||
|
||||
public int effectiveStride() {
|
||||
|
||||
@@ -143,6 +143,7 @@ public class GLSMRedirector {
|
||||
private static final String OpenGlHelper = "net/minecraft/client/renderer/OpenGlHelper";
|
||||
private static final String EXTBlendFunc = "org/lwjgl/opengl/EXTBlendFuncSeparate";
|
||||
private static final String EXTSecondaryColor = "org/lwjgl/opengl/EXTSecondaryColor";
|
||||
private static final String EXTFogCoord = "org/lwjgl/opengl/EXTFogCoord";
|
||||
private static final String ARBMultiTexture = "org/lwjgl/opengl/ARBMultitexture";
|
||||
private static final String ARBShaderObjects = "org/lwjgl/opengl/ARBShaderObjects";
|
||||
private static final String ARBInstancedArrays = "org/lwjgl/opengl/ARBInstancedArrays";
|
||||
@@ -378,6 +379,8 @@ public class GLSMRedirector {
|
||||
.add("glEnableClientState")
|
||||
.add("glDisableClientState")
|
||||
.add("glInterleavedArrays")
|
||||
.add("glEdgeFlagPointer")
|
||||
.add("glGetPointer")
|
||||
.add("glPushClientAttrib")
|
||||
.add("glPopClientAttrib")
|
||||
.add("glViewport")
|
||||
@@ -408,11 +411,16 @@ public class GLSMRedirector {
|
||||
.add("glMultiDrawArrays")
|
||||
.add("glPointParameterf")
|
||||
.add("glPointParameteri")
|
||||
.add("glPointParameter")
|
||||
.add("glPointParameterfv", "glPointParameter")
|
||||
.add("glPointParameteriv", "glPointParameter")
|
||||
// Removed in core profile - emulated by the FFP shaders, calling through would abort the JVM
|
||||
.add("glSecondaryColor3f")
|
||||
.add("glSecondaryColor3d")
|
||||
.add("glSecondaryColor3b")
|
||||
.add("glSecondaryColor3ub");
|
||||
.add("glSecondaryColor3ub")
|
||||
.add("glSecondaryColorPointer")
|
||||
.add("glFogCoordPointer");
|
||||
final var gl15 = RedirectMap.newMap()
|
||||
.add("glGenBuffers")
|
||||
.add("glBindBuffer")
|
||||
@@ -604,7 +612,9 @@ public class GLSMRedirector {
|
||||
.add("glSecondaryColor3bEXT", "glSecondaryColor3b")
|
||||
.add("glSecondaryColor3fEXT", "glSecondaryColor3f")
|
||||
.add("glSecondaryColor3dEXT", "glSecondaryColor3d")
|
||||
.add("glSecondaryColor3ubEXT", "glSecondaryColor3ub"));
|
||||
.add("glSecondaryColor3ubEXT", "glSecondaryColor3ub")
|
||||
.add("glSecondaryColorPointerEXT", "glSecondaryColorPointer"));
|
||||
methodRedirects.put(EXTFogCoord, RedirectMap.newMap().add("glFogCoordPointerEXT", "glFogCoordPointer"));
|
||||
|
||||
// ARB
|
||||
methodRedirects.put(ARBMultiTexture, RedirectMap.newMap()
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.gtnewhorizons.angelica.glsm.states;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.lwjgl.opengl.GL20;
|
||||
|
||||
/**
|
||||
* Tracks GL point state: size.
|
||||
@@ -10,10 +11,24 @@ import lombok.Setter;
|
||||
@Getter @Setter
|
||||
public class PointState implements ISettableState<PointState> {
|
||||
private float size = 1.0f;
|
||||
private float minSize = 0.0f;
|
||||
private float maxSize = Float.NaN;
|
||||
private float fadeThreshold = 1.0f;
|
||||
private float attenuationConstant = 1.0f;
|
||||
private float attenuationLinear = 0.0f;
|
||||
private float attenuationQuadratic = 0.0f;
|
||||
private int spriteCoordOrigin = GL20.GL_UPPER_LEFT;
|
||||
|
||||
@Override
|
||||
public PointState set(PointState state) {
|
||||
this.size = state.size;
|
||||
this.minSize = state.minSize;
|
||||
this.maxSize = state.maxSize;
|
||||
this.fadeThreshold = state.fadeThreshold;
|
||||
this.attenuationConstant = state.attenuationConstant;
|
||||
this.attenuationLinear = state.attenuationLinear;
|
||||
this.attenuationQuadratic = state.attenuationQuadratic;
|
||||
this.spriteCoordOrigin = state.spriteCoordOrigin;
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -21,7 +36,14 @@ public class PointState implements ISettableState<PointState> {
|
||||
public boolean sameAs(Object state) {
|
||||
if (this == state) return true;
|
||||
if (!(state instanceof PointState pointState)) return false;
|
||||
return Float.compare(size, pointState.size) == 0;
|
||||
return Float.compare(size, pointState.size) == 0
|
||||
&& Float.compare(minSize, pointState.minSize) == 0
|
||||
&& Float.compare(maxSize, pointState.maxSize) == 0
|
||||
&& Float.compare(fadeThreshold, pointState.fadeThreshold) == 0
|
||||
&& Float.compare(attenuationConstant, pointState.attenuationConstant) == 0
|
||||
&& Float.compare(attenuationLinear, pointState.attenuationLinear) == 0
|
||||
&& Float.compare(attenuationQuadratic, pointState.attenuationQuadratic) == 0
|
||||
&& spriteCoordOrigin == pointState.spriteCoordOrigin;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -9,6 +9,7 @@ import lombok.Getter;
|
||||
import org.joml.Matrix4fStack;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL12;
|
||||
import org.lwjgl.opengl.GL13;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -19,6 +20,7 @@ public class TextureUnitArray {
|
||||
private final TextureUnitBooleanStateStack[] states;
|
||||
private final TextureUnitBooleanStateStack[] texture1DStates;
|
||||
private final TextureUnitBooleanStateStack[] texture3DStates;
|
||||
private final TextureUnitBooleanStateStack[] textureCubeMapStates;
|
||||
private final TextureUnitBooleanStateStack[] texGenSStates;
|
||||
private final TextureUnitBooleanStateStack[] texGenTStates;
|
||||
private final TextureUnitBooleanStateStack[] texGenRStates;
|
||||
@@ -36,6 +38,7 @@ public class TextureUnitArray {
|
||||
states = new TextureUnitBooleanStateStack[GLStateManager.MAX_TEXTURE_UNITS];
|
||||
texture1DStates = new TextureUnitBooleanStateStack[GLStateManager.MAX_TEXTURE_UNITS];
|
||||
texture3DStates = new TextureUnitBooleanStateStack[GLStateManager.MAX_TEXTURE_UNITS];
|
||||
textureCubeMapStates = new TextureUnitBooleanStateStack[GLStateManager.MAX_TEXTURE_UNITS];
|
||||
texGenSStates = new TextureUnitBooleanStateStack[GLStateManager.MAX_TEXTURE_UNITS];
|
||||
texGenTStates = new TextureUnitBooleanStateStack[GLStateManager.MAX_TEXTURE_UNITS];
|
||||
texGenRStates = new TextureUnitBooleanStateStack[GLStateManager.MAX_TEXTURE_UNITS];
|
||||
@@ -49,6 +52,7 @@ public class TextureUnitArray {
|
||||
states[i] = track(new TextureUnitBooleanStateStack(GL11.GL_TEXTURE_2D, i));
|
||||
texture1DStates[i] = track(new TextureUnitBooleanStateStack(GL11.GL_TEXTURE_1D, i));
|
||||
texture3DStates[i] = track(new TextureUnitBooleanStateStack(GL12.GL_TEXTURE_3D, i));
|
||||
textureCubeMapStates[i] = track(new TextureUnitBooleanStateStack(GL13.GL_TEXTURE_CUBE_MAP, i));
|
||||
texGenSStates[i] = track(new TextureUnitBooleanStateStack(GL11.GL_TEXTURE_GEN_S, i));
|
||||
texGenTStates[i] = track(new TextureUnitBooleanStateStack(GL11.GL_TEXTURE_GEN_T, i));
|
||||
texGenRStates[i] = track(new TextureUnitBooleanStateStack(GL11.GL_TEXTURE_GEN_R, i));
|
||||
@@ -90,6 +94,10 @@ public class TextureUnitArray {
|
||||
return texture3DStates[index];
|
||||
}
|
||||
|
||||
public TextureUnitBooleanStateStack getTextureCubeMapStates(int index) {
|
||||
return textureCubeMapStates[index];
|
||||
}
|
||||
|
||||
public TextureUnitBooleanStateStack getTexGenSStates(int index) {
|
||||
return texGenSStates[index];
|
||||
}
|
||||
@@ -127,6 +135,7 @@ public class TextureUnitArray {
|
||||
if (!states[i].sameAs(textureUnitArray.states[i])) return false;
|
||||
if (!texture1DStates[i].sameAs(textureUnitArray.texture1DStates[i])) return false;
|
||||
if (!texture3DStates[i].sameAs(textureUnitArray.texture3DStates[i])) return false;
|
||||
if (!textureCubeMapStates[i].sameAs(textureUnitArray.textureCubeMapStates[i])) return false;
|
||||
if (!texGenSStates[i].sameAs(textureUnitArray.texGenSStates[i])) return false;
|
||||
if (!texGenTStates[i].sameAs(textureUnitArray.texGenTStates[i])) return false;
|
||||
if (!texGenRStates[i].sameAs(textureUnitArray.texGenRStates[i])) return false;
|
||||
|
||||
@@ -2,7 +2,6 @@ package com.gtnewhorizons.angelica.glsm;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.lwjgl.BufferUtils;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL20;
|
||||
|
||||
import java.nio.FloatBuffer;
|
||||
@@ -14,29 +13,6 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
@GLCoreTest
|
||||
class ArrayUniformUploadGLTest {
|
||||
|
||||
private static int compile(int type, String src) {
|
||||
final int s = GL20.glCreateShader(type);
|
||||
GL20.glShaderSource(s, src);
|
||||
GL20.glCompileShader(s);
|
||||
assertEquals(GL11.GL_TRUE, GL20.glGetShaderi(s, GL20.GL_COMPILE_STATUS), () -> "shader compile failed: " + GL20.glGetShaderInfoLog(s, 4096));
|
||||
return s;
|
||||
}
|
||||
|
||||
private static int link(String vs, String fs) {
|
||||
final int v = compile(GL20.GL_VERTEX_SHADER, vs);
|
||||
final int f = compile(GL20.GL_FRAGMENT_SHADER, fs);
|
||||
final int p = GL20.glCreateProgram();
|
||||
GL20.glAttachShader(p, v);
|
||||
GL20.glAttachShader(p, f);
|
||||
GL20.glLinkProgram(p);
|
||||
assertEquals(GL11.GL_TRUE, GL20.glGetProgrami(p, GL20.GL_LINK_STATUS), () -> "link failed: " + GL20.glGetProgramInfoLog(p, 4096));
|
||||
GL20.glDeleteShader(v);
|
||||
GL20.glDeleteShader(f);
|
||||
return p;
|
||||
}
|
||||
|
||||
private static final String VS = "#version 330 core\nvoid main(){ gl_Position = vec4(0.0); }\n";
|
||||
|
||||
@Test
|
||||
void glUniform2FloatBufferUploadsWholeArray() {
|
||||
// Runtime index keeps the whole array active so element locations stay queryable.
|
||||
@@ -45,7 +21,7 @@ class ArrayUniformUploadGLTest {
|
||||
+ "uniform int idx;\n"
|
||||
+ "out vec4 o;\n"
|
||||
+ "void main(){ o = vec4(cosmicuvs[idx], cosmicuvs[(idx+1)%10]); }\n";
|
||||
final int p = link(VS, fs);
|
||||
final int p = GlTestSupport.program(GlTestSupport.TRIVIAL_VS, fs);
|
||||
try {
|
||||
GL20.glUseProgram(p);
|
||||
|
||||
@@ -66,7 +42,7 @@ class ArrayUniformUploadGLTest {
|
||||
}
|
||||
} finally {
|
||||
GL20.glUseProgram(0);
|
||||
GL20.glDeleteProgram(p);
|
||||
GLStateManager.glDeleteProgram(p);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,7 +53,7 @@ class ArrayUniformUploadGLTest {
|
||||
+ "uniform int idx;\n"
|
||||
+ "out vec4 o;\n"
|
||||
+ "void main(){ o = vec4(float(vals[idx])); }\n";
|
||||
final int p = link(VS, fs);
|
||||
final int p = GlTestSupport.program(GlTestSupport.TRIVIAL_VS, fs);
|
||||
try {
|
||||
GL20.glUseProgram(p);
|
||||
|
||||
@@ -96,7 +72,7 @@ class ArrayUniformUploadGLTest {
|
||||
}
|
||||
} finally {
|
||||
GL20.glUseProgram(0);
|
||||
GL20.glDeleteProgram(p);
|
||||
GLStateManager.glDeleteProgram(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,30 +5,24 @@ import org.junit.jupiter.api.Test;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.CsvSource;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
class CaptureGateTest {
|
||||
|
||||
@Test
|
||||
void gateOffWhenNothingAttached() {
|
||||
assertFalse(CaptureGate.gateValue(false, false, false));
|
||||
}
|
||||
|
||||
@Test
|
||||
void gateOnWhenForced() {
|
||||
assertTrue(CaptureGate.gateValue(true, false, false));
|
||||
}
|
||||
|
||||
@Test
|
||||
void gateOnWhenToolAttached() {
|
||||
assertTrue(CaptureGate.gateValue(false, true, false));
|
||||
}
|
||||
|
||||
@Test
|
||||
void gateOnWhenTracyConnected() {
|
||||
assertTrue(CaptureGate.gateValue(false, false, true));
|
||||
@ParameterizedTest(name = "{0}")
|
||||
@CsvSource({
|
||||
"nothing attached, false, false, false, false",
|
||||
"forced, true, false, false, true",
|
||||
"tool attached, false, true, false, true",
|
||||
"tracy connected, false, false, true, true"
|
||||
})
|
||||
void gateIsOnWhenAnySourceIs(String name, boolean forced, boolean toolAttached, boolean tracyConnected, boolean expected) {
|
||||
assertEquals(expected, CaptureGate.gateValue(forced, toolAttached, tracyConnected));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
+200
-318
@@ -5,9 +5,12 @@ import com.gtnewhorizons.angelica.glsm.testutil.Reflect;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.io.TempDir;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
import org.junit.jupiter.params.provider.ValueSource;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
@@ -17,66 +20,104 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
class CompatShaderTransformerTest {
|
||||
|
||||
@Test
|
||||
void testModelViewMatrixReplacement() {
|
||||
String src = """
|
||||
#version 120
|
||||
void main() {
|
||||
vec4 pos = gl_ModelViewMatrix * gl_Vertex;
|
||||
gl_Position = gl_ProjectionMatrix * pos;
|
||||
}
|
||||
""";
|
||||
|
||||
String result = CompatShaderTransformer.transform(src, false);
|
||||
assertTrue(result.contains("angelica_ModelViewMatrix"));
|
||||
assertTrue(result.contains("angelica_ProjectionMatrix"));
|
||||
assertFalse(result.contains("gl_ModelViewMatrix"));
|
||||
assertFalse(result.contains("gl_ProjectionMatrix"));
|
||||
assertTrue(result.contains("#version 330 core"));
|
||||
private static String[] strings(String... values) {
|
||||
return values;
|
||||
}
|
||||
|
||||
@Test
|
||||
void testNormalMatrixReplacement() {
|
||||
String src = """
|
||||
#version 120
|
||||
void main() {
|
||||
vec3 n = gl_NormalMatrix * gl_Normal;
|
||||
}
|
||||
""";
|
||||
|
||||
String result = CompatShaderTransformer.transform(src, false);
|
||||
assertTrue(result.contains("uniform mat3 angelica_NormalMatrix"));
|
||||
assertFalse(result.contains("gl_NormalMatrix"));
|
||||
private static void assertRewrite(boolean fragment, String src, String[] present, String[] absent) {
|
||||
final String result = CompatShaderTransformer.transform(src, fragment);
|
||||
for (final String s : present) {
|
||||
assertTrue(result.contains(s), () -> "expected '" + s + "' in\n\n" + result);
|
||||
}
|
||||
for (final String s : absent) {
|
||||
assertFalse(result.contains(s), () -> "'" + s + "' must not remain in\n\n" + result);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testModelViewProjectionMatrixExpression() {
|
||||
String src = """
|
||||
#version 120
|
||||
void main() {
|
||||
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
|
||||
}
|
||||
""";
|
||||
|
||||
String result = CompatShaderTransformer.transform(src, false);
|
||||
assertFalse(result.contains("gl_ModelViewProjectionMatrix"));
|
||||
assertTrue(result.contains("angelica_ProjectionMatrix"));
|
||||
static Stream<Arguments> matrixBuiltins() {
|
||||
return Stream.of(
|
||||
Arguments.of("modelview and projection matrices", false, """
|
||||
#version 120
|
||||
void main() {
|
||||
vec4 pos = gl_ModelViewMatrix * gl_Vertex;
|
||||
gl_Position = gl_ProjectionMatrix * pos;
|
||||
}
|
||||
""", strings("angelica_ModelViewMatrix", "angelica_ProjectionMatrix", "#version 330 core"), strings("gl_ModelViewMatrix", "gl_ProjectionMatrix")),
|
||||
Arguments.of("normal matrix", false, """
|
||||
#version 120
|
||||
void main() {
|
||||
vec3 n = gl_NormalMatrix * gl_Normal;
|
||||
}
|
||||
""", strings("uniform mat3 angelica_NormalMatrix"), strings("gl_NormalMatrix")),
|
||||
Arguments.of("modelview-projection matrix", false, """
|
||||
#version 120
|
||||
void main() {
|
||||
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
|
||||
}
|
||||
""", strings("angelica_ProjectionMatrix"), strings("gl_ModelViewProjectionMatrix")),
|
||||
Arguments.of("inverse matrices", false, """
|
||||
#version 120
|
||||
void main() {
|
||||
vec4 pos = gl_ModelViewMatrixInverse * vec4(0.0, 0.0, 0.0, 1.0);
|
||||
vec4 proj = gl_ProjectionMatrixInverse * vec4(0.0, 0.0, -1.0, 1.0);
|
||||
}
|
||||
""", strings(), strings("gl_ModelViewMatrixInverse", "gl_ProjectionMatrixInverse")),
|
||||
Arguments.of("texture matrix", false, """
|
||||
#version 120
|
||||
void main() {
|
||||
vec4 lmCoord = gl_TextureMatrix[1] * gl_MultiTexCoord1;
|
||||
}
|
||||
""", strings(), strings("gl_TextureMatrix")),
|
||||
Arguments.of("several builtins in one fragment shader", true, """
|
||||
#version 120
|
||||
uniform sampler2D tex;
|
||||
void main() {
|
||||
vec3 n = gl_NormalMatrix * gl_Normal;
|
||||
vec4 pos = gl_ModelViewMatrix * gl_Vertex;
|
||||
gl_Position = gl_ProjectionMatrix * pos;
|
||||
vec4 color = texture2D(tex, vec2(0.0));
|
||||
gl_FragColor = color;
|
||||
}
|
||||
""", strings("angelica_ModelViewMatrix", "angelica_ProjectionMatrix", "angelica_NormalMatrix", "#version 330 core"), strings("gl_ModelViewMatrix", "gl_ProjectionMatrix", "gl_NormalMatrix", "texture2D", "gl_FragColor")));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testTextureFunctionRenames() {
|
||||
String src = """
|
||||
#version 120
|
||||
uniform sampler2D tex;
|
||||
void main() {
|
||||
vec4 color = texture2D(tex, vec2(0.0));
|
||||
}
|
||||
""";
|
||||
@ParameterizedTest(name = "{0}")
|
||||
@MethodSource("matrixBuiltins")
|
||||
void matrixBuiltinsAreRewritten(String name, boolean fragment, String src, String[] present, String[] absent) {
|
||||
assertRewrite(fragment, src, present, absent);
|
||||
}
|
||||
|
||||
String result = CompatShaderTransformer.transform(src, false);
|
||||
// texture2D -> texture
|
||||
assertFalse(result.contains("texture2D"));
|
||||
assertTrue(result.contains("texture"));
|
||||
static Stream<Arguments> textureFunctions() {
|
||||
return Stream.of(
|
||||
Arguments.of("texture2D", false, """
|
||||
#version 120
|
||||
uniform sampler2D tex;
|
||||
void main() {
|
||||
vec4 color = texture2D(tex, vec2(0.0));
|
||||
}
|
||||
""", strings("texture"), strings("texture2D")),
|
||||
Arguments.of("shadow2D", true, """
|
||||
#version 120
|
||||
uniform sampler2DShadow shadowMap;
|
||||
void main() {
|
||||
float s = shadow2D(shadowMap, vec3(0.0)).r;
|
||||
gl_FragColor = vec4(s);
|
||||
}
|
||||
""", strings("texture"), strings("shadow2D(")),
|
||||
Arguments.of("texelFetch3D", true, """
|
||||
#version 120
|
||||
uniform sampler3D vol;
|
||||
void main() {
|
||||
vec4 v = texelFetch3D(vol, ivec3(0), 0);
|
||||
gl_FragColor = v;
|
||||
}
|
||||
""", strings("texelFetch"), strings("texelFetch3D")));
|
||||
}
|
||||
|
||||
@ParameterizedTest(name = "{0}")
|
||||
@MethodSource("textureFunctions")
|
||||
void legacyTextureFunctionsAreRenamed(String name, boolean fragment, String src, String[] present, String[] absent) {
|
||||
assertRewrite(fragment, src, present, absent);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -95,32 +136,26 @@ class CompatShaderTransformerTest {
|
||||
assertTrue(result.contains("layout"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testVersionUpgradeTo330() {
|
||||
String src = """
|
||||
#version 110
|
||||
void main() {
|
||||
gl_FragColor = vec4(1.0);
|
||||
}
|
||||
""";
|
||||
|
||||
String result = CompatShaderTransformer.transform(src, true);
|
||||
assertTrue(result.contains("#version 330 core"));
|
||||
assertFalse(result.contains("#version 110"));
|
||||
static Stream<Arguments> versionDirectives() {
|
||||
return Stream.of(
|
||||
Arguments.of("110 becomes 330 core", true, """
|
||||
#version 110
|
||||
void main() {
|
||||
gl_FragColor = vec4(1.0);
|
||||
}
|
||||
""", strings("#version 330 core"), strings("#version 110")),
|
||||
Arguments.of("compatibility profile is stripped", false, """
|
||||
#version 330 compatibility
|
||||
void main() {
|
||||
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
|
||||
}
|
||||
""", strings("#version 330 core"), strings("compatibility")));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCompatibilityProfileStripped() {
|
||||
String src = """
|
||||
#version 330 compatibility
|
||||
void main() {
|
||||
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
|
||||
}
|
||||
""";
|
||||
|
||||
String result = CompatShaderTransformer.transform(src, false);
|
||||
assertTrue(result.contains("#version 330 core"));
|
||||
assertFalse(result.contains("compatibility"));
|
||||
@ParameterizedTest(name = "{0}")
|
||||
@MethodSource("versionDirectives")
|
||||
void versionIsUpgradedToCore(String name, boolean fragment, String src, String[] present, String[] absent) {
|
||||
assertRewrite(fragment, src, present, absent);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -139,60 +174,6 @@ class CompatShaderTransformerTest {
|
||||
assertEquals(src, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCombinedBuiltinsInSingleShader() {
|
||||
String src = """
|
||||
#version 120
|
||||
uniform sampler2D tex;
|
||||
void main() {
|
||||
vec3 n = gl_NormalMatrix * gl_Normal;
|
||||
vec4 pos = gl_ModelViewMatrix * gl_Vertex;
|
||||
gl_Position = gl_ProjectionMatrix * pos;
|
||||
vec4 color = texture2D(tex, vec2(0.0));
|
||||
gl_FragColor = color;
|
||||
}
|
||||
""";
|
||||
|
||||
String result = CompatShaderTransformer.transform(src, true);
|
||||
assertTrue(result.contains("angelica_ModelViewMatrix"));
|
||||
assertTrue(result.contains("angelica_ProjectionMatrix"));
|
||||
assertTrue(result.contains("angelica_NormalMatrix"));
|
||||
assertFalse(result.contains("gl_ModelViewMatrix"));
|
||||
assertFalse(result.contains("gl_ProjectionMatrix"));
|
||||
assertFalse(result.contains("gl_NormalMatrix"));
|
||||
assertFalse(result.contains("texture2D"));
|
||||
assertFalse(result.contains("gl_FragColor"));
|
||||
assertTrue(result.contains("#version 330 core"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testInverseMatrixReplacement() {
|
||||
String src = """
|
||||
#version 120
|
||||
void main() {
|
||||
vec4 pos = gl_ModelViewMatrixInverse * vec4(0.0, 0.0, 0.0, 1.0);
|
||||
vec4 proj = gl_ProjectionMatrixInverse * vec4(0.0, 0.0, -1.0, 1.0);
|
||||
}
|
||||
""";
|
||||
|
||||
String result = CompatShaderTransformer.transform(src, false);
|
||||
assertFalse(result.contains("gl_ModelViewMatrixInverse"));
|
||||
assertFalse(result.contains("gl_ProjectionMatrixInverse"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testTextureMatrixReplacement() {
|
||||
String src = """
|
||||
#version 120
|
||||
void main() {
|
||||
vec4 lmCoord = gl_TextureMatrix[1] * gl_MultiTexCoord1;
|
||||
}
|
||||
""";
|
||||
|
||||
String result = CompatShaderTransformer.transform(src, false);
|
||||
assertFalse(result.contains("gl_TextureMatrix"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFogStructAccess() {
|
||||
String src = """
|
||||
@@ -211,34 +192,27 @@ class CompatShaderTransformerTest {
|
||||
assertTrue(result.contains("uniform vec4 angelica_FogColor"), "Fog color uniform should be injected");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFogFragCoordVertex() {
|
||||
String src = """
|
||||
#version 120
|
||||
void main() {
|
||||
gl_FogFragCoord = length(gl_ModelViewMatrix * gl_Vertex);
|
||||
}
|
||||
""";
|
||||
|
||||
String result = CompatShaderTransformer.transform(src, false);
|
||||
assertTrue(result.contains("out float angelica_FogFragCoord"), "Vertex shader should get 'out' declaration");
|
||||
assertTrue(result.contains("angelica_FogFragCoord"), "gl_FogFragCoord should be renamed");
|
||||
assertFalse(result.contains("gl_FogFragCoord"), "gl_FogFragCoord should not remain");
|
||||
static Stream<Arguments> fogFragCoord() {
|
||||
return Stream.of(
|
||||
Arguments.of("vertex shader declares an out", false, """
|
||||
#version 120
|
||||
void main() {
|
||||
gl_FogFragCoord = length(gl_ModelViewMatrix * gl_Vertex);
|
||||
}
|
||||
""", strings("out float angelica_FogFragCoord"), strings("gl_FogFragCoord")),
|
||||
Arguments.of("fragment shader declares an in", true, """
|
||||
#version 120
|
||||
void main() {
|
||||
float f = gl_FogFragCoord;
|
||||
gl_FragColor = vec4(f);
|
||||
}
|
||||
""", strings("in float angelica_FogFragCoord"), strings("gl_FogFragCoord")));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFogFragCoordFragment() {
|
||||
String src = """
|
||||
#version 120
|
||||
void main() {
|
||||
float f = gl_FogFragCoord;
|
||||
gl_FragColor = vec4(f);
|
||||
}
|
||||
""";
|
||||
|
||||
String result = CompatShaderTransformer.transform(src, true);
|
||||
assertTrue(result.contains("in float angelica_FogFragCoord"), "Fragment shader should get 'in' declaration");
|
||||
assertFalse(result.contains("gl_FogFragCoord"), "gl_FogFragCoord should not remain");
|
||||
@ParameterizedTest(name = "{0}")
|
||||
@MethodSource("fogFragCoord")
|
||||
void fogFragCoordBecomesAVarying(String name, boolean fragment, String src, String[] present, String[] absent) {
|
||||
assertRewrite(fragment, src, present, absent);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -255,23 +229,6 @@ class CompatShaderTransformerTest {
|
||||
assertFalse(result.contains("gl_FrontColor"), "gl_FrontColor should not remain");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testShadow2DRename() {
|
||||
String src = """
|
||||
#version 120
|
||||
uniform sampler2DShadow shadowMap;
|
||||
void main() {
|
||||
float s = shadow2D(shadowMap, vec3(0.0)).r;
|
||||
gl_FragColor = vec4(s);
|
||||
}
|
||||
""";
|
||||
|
||||
String result = CompatShaderTransformer.transform(src, true);
|
||||
assertFalse(result.contains("shadow2D("), "shadow2D should be renamed");
|
||||
// shadow2D -> texture with vec4 wrapping
|
||||
assertTrue(result.contains("texture"), "shadow2D should be renamed to texture");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testReservedWordTextureAsVariable() {
|
||||
// Shader declares 'texture' as a sampler variable - this is valid in GLSL 120
|
||||
@@ -321,155 +278,81 @@ class CompatShaderTransformerTest {
|
||||
"Alpha test discard should be appended to main()");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testTexelFetch3DTriggersTransformation() {
|
||||
String src = """
|
||||
#version 120
|
||||
uniform sampler3D vol;
|
||||
void main() {
|
||||
vec4 v = texelFetch3D(vol, ivec3(0), 0);
|
||||
gl_FragColor = v;
|
||||
}
|
||||
""";
|
||||
|
||||
String result = CompatShaderTransformer.transform(src, true);
|
||||
// texelFetch3D should be renamed to texelFetch
|
||||
assertFalse(result.contains("texelFetch3D"), "texelFetch3D should be renamed");
|
||||
assertTrue(result.contains("texelFetch"), "texelFetch3D should become texelFetch");
|
||||
static Stream<Arguments> vertexAttributes() {
|
||||
return Stream.of(
|
||||
Arguments.of("gl_Vertex at location 0", false, """
|
||||
#version 120
|
||||
void main() {
|
||||
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
|
||||
}
|
||||
""", strings("in vec4 angelica_Vertex", "location = 0"), strings("gl_Vertex")),
|
||||
Arguments.of("gl_Color at location 1", false, """
|
||||
#version 120
|
||||
varying vec4 v_Color;
|
||||
void main() {
|
||||
v_Color = gl_Color;
|
||||
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
|
||||
}
|
||||
""", strings("in vec4 angelica_Color", "location = 1"), strings("gl_Color")),
|
||||
Arguments.of("gl_MultiTexCoord0 at location 2", false, """
|
||||
#version 120
|
||||
void main() {
|
||||
gl_TexCoord[0] = gl_MultiTexCoord0;
|
||||
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
|
||||
}
|
||||
""", strings("in vec4 angelica_MultiTexCoord0", "location = 2"), strings("gl_MultiTexCoord0")),
|
||||
Arguments.of("gl_MultiTexCoord1 at location 3", false, """
|
||||
#version 120
|
||||
void main() {
|
||||
vec4 lm = gl_TextureMatrix[1] * gl_MultiTexCoord1;
|
||||
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
|
||||
}
|
||||
""", strings("angelica_MultiTexCoord1", "location = 3"), strings("gl_MultiTexCoord1")),
|
||||
Arguments.of("gl_Normal at location 4", false, """
|
||||
#version 120
|
||||
void main() {
|
||||
vec3 n = gl_NormalMatrix * gl_Normal;
|
||||
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
|
||||
}
|
||||
""", strings("in vec3 angelica_Normal", "location = 4"), strings("gl_Normal")));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testVertexAttributeGlVertex() {
|
||||
String src = """
|
||||
#version 120
|
||||
void main() {
|
||||
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
|
||||
}
|
||||
""";
|
||||
|
||||
String result = CompatShaderTransformer.transform(src, false);
|
||||
assertFalse(result.contains("gl_Vertex"), "gl_Vertex should be replaced");
|
||||
assertTrue(result.contains("angelica_Vertex"), "should become angelica_Vertex");
|
||||
assertTrue(result.contains("in vec4 angelica_Vertex"), "should have in declaration");
|
||||
assertTrue(result.contains("location = 0"), "should use attribute location 0");
|
||||
@ParameterizedTest(name = "{0}")
|
||||
@MethodSource("vertexAttributes")
|
||||
void vertexAttributeBuiltinsGetFixedLocations(String name, boolean fragment, String src, String[] present, String[] absent) {
|
||||
assertRewrite(fragment, src, present, absent);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testVertexAttributeGlColorInVertexShader() {
|
||||
// gl_Color in a vertex shader is the per-vertex color attribute, not the fragment varying
|
||||
String src = """
|
||||
#version 120
|
||||
varying vec4 v_Color;
|
||||
void main() {
|
||||
v_Color = gl_Color;
|
||||
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
|
||||
}
|
||||
""";
|
||||
|
||||
String result = CompatShaderTransformer.transform(src, false);
|
||||
assertTrue(result.contains("angelica_Color"), "gl_Color -> angelica_Color (vertex attribute)");
|
||||
assertTrue(result.contains("in vec4 angelica_Color"), "should have in declaration");
|
||||
assertTrue(result.contains("location = 1"), "should use attribute location 1");
|
||||
assertFalse(result.contains("gl_Color"), "gl_Color should not remain");
|
||||
static Stream<Arguments> texCoordVaryings() {
|
||||
return Stream.of(
|
||||
Arguments.of("vertex shader declares an out", false, """
|
||||
#version 120
|
||||
void main() {
|
||||
gl_TexCoord[0] = gl_MultiTexCoord0;
|
||||
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
|
||||
}
|
||||
""", strings("out vec4 angelica_TexCoord0"), strings("gl_TexCoord")),
|
||||
Arguments.of("fragment shader declares an in", true, """
|
||||
#version 120
|
||||
void main() {
|
||||
vec2 uv = gl_TexCoord[0].xy;
|
||||
gl_FragColor = vec4(uv, 0.0, 1.0);
|
||||
}
|
||||
""", strings("in vec4 angelica_TexCoord0"), strings("gl_TexCoord")),
|
||||
Arguments.of("one varying per index", false, """
|
||||
#version 120
|
||||
void main() {
|
||||
gl_TexCoord[0] = gl_MultiTexCoord0;
|
||||
gl_TexCoord[1] = gl_MultiTexCoord1;
|
||||
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
|
||||
}
|
||||
""", strings("out vec4 angelica_TexCoord0", "out vec4 angelica_TexCoord1"), strings("gl_TexCoord")));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testVertexAttributeMultiTexCoord0() {
|
||||
String src = """
|
||||
#version 120
|
||||
void main() {
|
||||
gl_TexCoord[0] = gl_MultiTexCoord0;
|
||||
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
|
||||
}
|
||||
""";
|
||||
|
||||
String result = CompatShaderTransformer.transform(src, false);
|
||||
assertFalse(result.contains("gl_MultiTexCoord0"), "gl_MultiTexCoord0 should be replaced");
|
||||
assertTrue(result.contains("angelica_MultiTexCoord0"), "should become angelica_MultiTexCoord0");
|
||||
assertTrue(result.contains("in vec4 angelica_MultiTexCoord0"), "should have in declaration");
|
||||
assertTrue(result.contains("location = 2"), "should use attribute location 2");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testVertexAttributeMultiTexCoord1() {
|
||||
String src = """
|
||||
#version 120
|
||||
void main() {
|
||||
vec4 lm = gl_TextureMatrix[1] * gl_MultiTexCoord1;
|
||||
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
|
||||
}
|
||||
""";
|
||||
|
||||
String result = CompatShaderTransformer.transform(src, false);
|
||||
assertFalse(result.contains("gl_MultiTexCoord1"), "gl_MultiTexCoord1 should be replaced");
|
||||
assertTrue(result.contains("angelica_MultiTexCoord1"), "should become angelica_MultiTexCoord1");
|
||||
assertTrue(result.contains("location = 3"), "should use attribute location 3");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testVertexAttributeGlNormal() {
|
||||
String src = """
|
||||
#version 120
|
||||
void main() {
|
||||
vec3 n = gl_NormalMatrix * gl_Normal;
|
||||
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
|
||||
}
|
||||
""";
|
||||
|
||||
String result = CompatShaderTransformer.transform(src, false);
|
||||
assertFalse(result.contains("gl_Normal"), "gl_Normal should be replaced");
|
||||
assertTrue(result.contains("angelica_Normal"), "should become angelica_Normal");
|
||||
assertTrue(result.contains("in vec3 angelica_Normal"), "should have in vec3 declaration");
|
||||
assertTrue(result.contains("location = 4"), "should use attribute location 4");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testTexCoordVaryingVertexShader() {
|
||||
String src = """
|
||||
#version 120
|
||||
void main() {
|
||||
gl_TexCoord[0] = gl_MultiTexCoord0;
|
||||
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
|
||||
}
|
||||
""";
|
||||
|
||||
String result = CompatShaderTransformer.transform(src, false);
|
||||
assertFalse(result.contains("gl_TexCoord"), "gl_TexCoord should be replaced");
|
||||
assertTrue(result.contains("angelica_TexCoord0"), "should become angelica_TexCoord0");
|
||||
assertTrue(result.contains("out vec4 angelica_TexCoord0"), "vertex shader should have 'out' declaration");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testTexCoordVaryingFragmentShader() {
|
||||
String src = """
|
||||
#version 120
|
||||
void main() {
|
||||
vec2 uv = gl_TexCoord[0].xy;
|
||||
gl_FragColor = vec4(uv, 0.0, 1.0);
|
||||
}
|
||||
""";
|
||||
|
||||
String result = CompatShaderTransformer.transform(src, true);
|
||||
assertFalse(result.contains("gl_TexCoord"), "gl_TexCoord should be replaced");
|
||||
assertTrue(result.contains("angelica_TexCoord0"), "should become angelica_TexCoord0");
|
||||
assertTrue(result.contains("in vec4 angelica_TexCoord0"), "fragment shader should have 'in' declaration");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testTexCoordMultipleIndices() {
|
||||
String src = """
|
||||
#version 120
|
||||
void main() {
|
||||
gl_TexCoord[0] = gl_MultiTexCoord0;
|
||||
gl_TexCoord[1] = gl_MultiTexCoord1;
|
||||
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
|
||||
}
|
||||
""";
|
||||
|
||||
String result = CompatShaderTransformer.transform(src, false);
|
||||
assertTrue(result.contains("out vec4 angelica_TexCoord0"), "should have TexCoord0 out");
|
||||
assertTrue(result.contains("out vec4 angelica_TexCoord1"), "should have TexCoord1 out");
|
||||
assertFalse(result.contains("gl_TexCoord"), "no gl_TexCoord should remain");
|
||||
@ParameterizedTest(name = "{0}")
|
||||
@MethodSource("texCoordVaryings")
|
||||
void texCoordBecomesPerIndexVaryings(String name, boolean fragment, String src, String[] present, String[] absent) {
|
||||
assertRewrite(fragment, src, present, absent);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -533,7 +416,6 @@ class CompatShaderTransformerTest {
|
||||
String result = CompatShaderTransformer.transform(src, false);
|
||||
assertFalse(result.contains("gl_FrontLightModelProduct"), "gl_FrontLightModelProduct should be replaced");
|
||||
assertTrue(result.contains("uniform vec4 angelica_SceneColor"), "angelica_SceneColor uniform should be injected");
|
||||
assertTrue(result.contains("angelica_SceneColor"), "should reference angelica_SceneColor");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
+1
-6
@@ -9,6 +9,7 @@ import org.lwjgl.opengl.GL11;
|
||||
|
||||
import java.nio.FloatBuffer;
|
||||
|
||||
import static com.gtnewhorizons.angelica.glsm.GlTestSupport.assertMatrixEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
@@ -64,12 +65,6 @@ class DisplayListCompilationParityTest {
|
||||
return buf;
|
||||
}
|
||||
|
||||
private static void assertMatrixEquals(FloatBuffer expected, FloatBuffer actual, String message) {
|
||||
for (int i = 0; i < 16; i++) {
|
||||
assertEquals(expected.get(i), actual.get(i), 0.001f, message + " (element " + i + ")");
|
||||
}
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
void setup() {
|
||||
if (DisplayListManager.isRecording()) {
|
||||
|
||||
@@ -3,11 +3,9 @@ package com.gtnewhorizons.angelica.glsm;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.lwjgl.BufferUtils;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import java.nio.FloatBuffer;
|
||||
|
||||
import static com.gtnewhorizons.angelica.glsm.GlTestSupport.matrix;
|
||||
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
@@ -48,12 +46,6 @@ class DisplayListCompilationTest {
|
||||
GLStateManager.glLoadIdentity();
|
||||
}
|
||||
|
||||
private static FloatBuffer matrix(int pname) {
|
||||
final FloatBuffer buf = BufferUtils.createFloatBuffer(16);
|
||||
GLStateManager.glGetFloat(pname, buf);
|
||||
return buf;
|
||||
}
|
||||
|
||||
@Test
|
||||
void glsm_compileAndExecute_matrixModeWithTransforms() {
|
||||
GLStateManager.glMatrixMode(GL11.GL_PROJECTION);
|
||||
@@ -102,69 +94,4 @@ class DisplayListCompilationTest {
|
||||
|
||||
assertFalse(DisplayListManager.isRecording(), "frame-begin backstop must clear a leaked open list");
|
||||
}
|
||||
|
||||
@Test
|
||||
void rawGL_compile_immediateModeWithTransforms() {
|
||||
GL11.glLoadIdentity();
|
||||
GL11.glTranslatef(100.0f, 0.0f, 0.0f);
|
||||
|
||||
testList = GL11.glGenLists(1);
|
||||
GL11.glNewList(testList, GL11.GL_COMPILE);
|
||||
|
||||
GL11.glPushMatrix();
|
||||
GL11.glTranslatef(50.0f, 25.0f, 0.0f);
|
||||
GL11.glScalef(0.5f, 0.5f, 1.0f);
|
||||
|
||||
GL11.glBegin(GL11.GL_QUADS);
|
||||
GL11.glVertex3f(0.0f, 0.0f, 0.0f);
|
||||
GL11.glVertex3f(16.0f, 0.0f, 0.0f);
|
||||
GL11.glVertex3f(16.0f, 16.0f, 0.0f);
|
||||
GL11.glVertex3f(0.0f, 16.0f, 0.0f);
|
||||
GL11.glEnd();
|
||||
|
||||
GL11.glPopMatrix();
|
||||
GL11.glEndList();
|
||||
|
||||
final FloatBuffer afterCompile = BufferUtils.createFloatBuffer(16);
|
||||
GL11.glGetFloat(GL11.GL_MODELVIEW_MATRIX, afterCompile);
|
||||
assertEquals(100.0f, afterCompile.get(12), 0.001f, "After GL_COMPILE: matrix unchanged");
|
||||
|
||||
GL11.glCallList(testList);
|
||||
|
||||
final FloatBuffer afterPlayback = BufferUtils.createFloatBuffer(16);
|
||||
GL11.glGetFloat(GL11.GL_MODELVIEW_MATRIX, afterPlayback);
|
||||
assertEquals(100.0f, afterPlayback.get(12), 0.001f, "After playback: base position preserved");
|
||||
assertEquals(1.0f, afterPlayback.get(0), 0.001f, "After playback: no scale (popped)");
|
||||
|
||||
GL11.glLoadIdentity();
|
||||
}
|
||||
|
||||
@Test
|
||||
void rawGL_compileAndExecute_immediateModeExecutesImmediately() {
|
||||
GL11.glLoadIdentity();
|
||||
|
||||
testList = GL11.glGenLists(1);
|
||||
GL11.glNewList(testList, GL11.GL_COMPILE_AND_EXECUTE);
|
||||
|
||||
GL11.glScalef(0.5f, 0.5f, 0.5f);
|
||||
|
||||
final FloatBuffer during = BufferUtils.createFloatBuffer(16);
|
||||
GL11.glGetFloat(GL11.GL_MODELVIEW_MATRIX, during);
|
||||
assertEquals(0.5f, during.get(0), 0.001f, "During COMPILE_AND_EXECUTE: scale applied");
|
||||
|
||||
GL11.glBegin(GL11.GL_QUADS);
|
||||
GL11.glVertex3f(0.0f, 0.0f, 0.0f);
|
||||
GL11.glVertex3f(1.0f, 0.0f, 0.0f);
|
||||
GL11.glVertex3f(1.0f, 1.0f, 0.0f);
|
||||
GL11.glVertex3f(0.0f, 1.0f, 0.0f);
|
||||
GL11.glEnd();
|
||||
|
||||
GL11.glEndList();
|
||||
|
||||
final FloatBuffer after = BufferUtils.createFloatBuffer(16);
|
||||
GL11.glGetFloat(GL11.GL_MODELVIEW_MATRIX, after);
|
||||
assertEquals(0.5f, after.get(0), 0.001f, "After COMPILE_AND_EXECUTE: scale remains");
|
||||
|
||||
GL11.glLoadIdentity();
|
||||
}
|
||||
}
|
||||
@@ -1,16 +1,15 @@
|
||||
package com.gtnewhorizons.angelica.glsm;
|
||||
|
||||
import com.gtnewhorizons.angelica.glsm.testutil.TestThreads;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
@@ -39,25 +38,14 @@ class DisplayListIdAllocatorTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void zeroNeverReturned() {
|
||||
DisplayListIDAllocator alloc = new DisplayListIDAllocator(1);
|
||||
// Allocate enough IDs to fill the first word (32 IDs). None should be 0.
|
||||
for (int i = 0; i < 31; i++) {
|
||||
int id = alloc.allocRange(1);
|
||||
assertNotEquals(0, id, "ID 0 must never be returned");
|
||||
assertTrue(id > 0, "All returned IDs must be positive");
|
||||
void singleAllocsAreSequentialFromOne() {
|
||||
// Sequential from 1 across several words: 0 is never handed out and no id repeats
|
||||
final DisplayListIDAllocator alloc = new DisplayListIDAllocator(1);
|
||||
for (int expected = 1; expected <= 500; expected++) {
|
||||
assertEquals(expected, alloc.allocRange(1));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void singleAllocReturnsSequential() {
|
||||
DisplayListIDAllocator alloc = new DisplayListIDAllocator();
|
||||
// First alloc should be 1 (0 is reserved)
|
||||
assertEquals(1, alloc.allocRange(1));
|
||||
assertEquals(2, alloc.allocRange(1));
|
||||
assertEquals(3, alloc.allocRange(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
void isAllocatedTracksState() {
|
||||
DisplayListIDAllocator alloc = new DisplayListIDAllocator();
|
||||
@@ -159,9 +147,9 @@ class DisplayListIdAllocatorTest {
|
||||
@Test
|
||||
void freeZeroIsNoOp() {
|
||||
DisplayListIDAllocator alloc = new DisplayListIDAllocator();
|
||||
// Should not throw
|
||||
alloc.free(0);
|
||||
alloc.free(-1);
|
||||
assertEquals(1, alloc.allocRange(1), "freeing the reserved id 0 must not make it allocatable");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -205,17 +193,6 @@ class DisplayListIdAllocatorTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void noDoubleAllocation() {
|
||||
DisplayListIDAllocator alloc = new DisplayListIDAllocator();
|
||||
// Allocate many IDs and verify uniqueness
|
||||
Set<Integer> seen = new HashSet<>();
|
||||
for (int i = 0; i < 500; i++) {
|
||||
int id = alloc.allocRange(1);
|
||||
assertTrue(seen.add(id), "Duplicate ID returned: " + id);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void rangeAfterSingleAllocs() {
|
||||
DisplayListIDAllocator alloc = new DisplayListIDAllocator();
|
||||
|
||||
+1
-3
@@ -54,9 +54,7 @@ class DisplayListMatrixRestorationTest extends DisplayListTestFixture {
|
||||
}
|
||||
|
||||
private static float translation(int target) {
|
||||
FloatBuffer b = BufferUtils.createFloatBuffer(16);
|
||||
GLStateManager.glGetFloat(target, b);
|
||||
return b.get(12);
|
||||
return GlTestSupport.matrix(target).get(12);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -1,10 +1,17 @@
|
||||
package com.gtnewhorizons.angelica.glsm;
|
||||
|
||||
import com.gtnewhorizon.gtnhlib.client.renderer.DirectTessellator;
|
||||
import com.gtnewhorizon.gtnhlib.client.renderer.TessellatorManager;
|
||||
import com.gtnewhorizons.angelica.glsm.recording.CompiledDisplayList;
|
||||
import com.gtnewhorizons.angelica.glsm.recording.ImmediateModeRecorder;
|
||||
import net.minecraft.client.renderer.Tessellator;
|
||||
import org.joml.Matrix4f;
|
||||
import org.lwjgl.BufferUtils;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import java.nio.FloatBuffer;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
|
||||
/**
|
||||
@@ -62,4 +69,58 @@ public final class DisplayListTestHelper {
|
||||
assertNotNull(compiled, "Display list should be compiled");
|
||||
return compiled;
|
||||
}
|
||||
|
||||
/** Calls {@code list} on an identity modelview and returns the resulting matrix. The caller's matrix is restored. */
|
||||
public static FloatBuffer modelviewAfterCall(int list) {
|
||||
GLStateManager.glPushMatrix();
|
||||
try {
|
||||
GLStateManager.glLoadIdentity();
|
||||
GLStateManager.glCallList(list);
|
||||
return GlTestSupport.modelview();
|
||||
} finally {
|
||||
GLStateManager.glPopMatrix();
|
||||
}
|
||||
}
|
||||
|
||||
public static void assertMatrixEquals(Matrix4f expected, FloatBuffer actual, String message) {
|
||||
final FloatBuffer expectedBuf = BufferUtils.createFloatBuffer(16);
|
||||
expected.get(expectedBuf);
|
||||
for (int i = 0; i < 16; i++) {
|
||||
assertEquals(expectedBuf.get(i), actual.get(i), 0.0001f, message + " (element " + i + ")");
|
||||
}
|
||||
}
|
||||
|
||||
public static void assertModelviewAfterCall(int list, Matrix4f expected, String message) {
|
||||
assertMatrixEquals(expected, modelviewAfterCall(list), message);
|
||||
}
|
||||
|
||||
/** Immediate-mode quad from the origin to (size, size) at z = 0. */
|
||||
public static void immediateQuad(float size) {
|
||||
GLStateManager.glBegin(GL11.GL_QUADS);
|
||||
GLStateManager.glVertex3f(0.0f, 0.0f, 0.0f);
|
||||
GLStateManager.glVertex3f(size, 0.0f, 0.0f);
|
||||
GLStateManager.glVertex3f(size, size, 0.0f);
|
||||
GLStateManager.glVertex3f(0.0f, size, 0.0f);
|
||||
GLStateManager.glEnd();
|
||||
}
|
||||
|
||||
/** Textured quad written straight into the vanilla Tessellator's raw buffer and handed to the draw interceptor. */
|
||||
public static void rawQuad(float size) {
|
||||
final Tessellator tess = Tessellator.instance;
|
||||
final float[][] corners = { { 0.0f, 0.0f }, { size, 0.0f }, { size, size }, { 0.0f, size } };
|
||||
tess.rawBuffer = new int[4 * 8];
|
||||
for (int i = 0; i < 4; i++) {
|
||||
final int base = i * 8;
|
||||
tess.rawBuffer[base] = Float.floatToRawIntBits(corners[i][0]);
|
||||
tess.rawBuffer[base + 1] = Float.floatToRawIntBits(corners[i][1]);
|
||||
tess.rawBuffer[base + 3] = Float.floatToRawIntBits(i == 1 || i == 2 ? 1.0f : 0.0f);
|
||||
tess.rawBuffer[base + 4] = Float.floatToRawIntBits(i >= 2 ? 1.0f : 0.0f);
|
||||
}
|
||||
tess.isDrawing = true;
|
||||
tess.drawMode = GL11.GL_QUADS;
|
||||
tess.hasTexture = true;
|
||||
tess.rawBufferIndex = 4 * 8;
|
||||
tess.vertexCount = 4;
|
||||
TessellatorManager.interceptDraw(tess);
|
||||
}
|
||||
}
|
||||
@@ -3,12 +3,16 @@ package com.gtnewhorizons.angelica.glsm;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
import org.lwjgl.BufferUtils;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL15;
|
||||
import org.lwjgl.opengl.GL30;
|
||||
|
||||
import java.nio.FloatBuffer;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
@@ -97,68 +101,23 @@ class FeedbackManagerTest {
|
||||
assertEquals(42.0f, buf.get(1), "Second token should be the pass-through value");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testTriangleFeedback_GL2D() {
|
||||
final FloatBuffer buf = BufferUtils.createFloatBuffer(128);
|
||||
FeedbackManager.glFeedbackBuffer(GL11.GL_2D, buf);
|
||||
FeedbackManager.glRenderMode(GL11.GL_FEEDBACK);
|
||||
|
||||
// Identity MV/proj, viewport (0,0,800,600)
|
||||
GLStateManager.getModelViewMatrix().identity();
|
||||
GLStateManager.getProjectionMatrix().identity();
|
||||
GLStateManager.getViewportState().setViewPort(0, 0, 800, 600);
|
||||
GLStateManager.getViewportState().setDepthRange(0.0, 1.0);
|
||||
|
||||
// Upload 3 vertices forming a triangle
|
||||
final int vao = GL30.glGenVertexArrays();
|
||||
GLStateManager.glBindVertexArray(vao);
|
||||
|
||||
// NDC vertices: (0,0,0), (1,0,0), (0,1,0)
|
||||
// With identity MVP and viewport 800x600:
|
||||
// NDC(0,0) → window(400, 300)
|
||||
// NDC(1,0) → window(800, 300)
|
||||
// NDC(0,1) → window(400, 600)
|
||||
final float[] verts = { 0f, 0f, 0f, 1f, 0f, 0f, 0f, 1f, 0f };
|
||||
final FloatBuffer vertBuf = BufferUtils.createFloatBuffer(9);
|
||||
vertBuf.put(verts).flip();
|
||||
|
||||
final int vbo = GL15.glGenBuffers();
|
||||
GLStateManager.glBindBuffer(GL15.GL_ARRAY_BUFFER, vbo);
|
||||
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, vertBuf, GL15.GL_STATIC_DRAW);
|
||||
GLStateManager.glVertexAttribPointer(0, 3, GL11.GL_FLOAT, false, 12, 0);
|
||||
GLStateManager.glEnableVertexAttribArray(0);
|
||||
|
||||
FeedbackManager.processDrawArrays(GL11.GL_TRIANGLES, 0, 3);
|
||||
|
||||
final int count = FeedbackManager.glRenderMode(GL11.GL_RENDER);
|
||||
|
||||
// GL_2D: POLYGON_TOKEN, 3, x0, y0, x1, y1, x2, y2 = 8 floats
|
||||
assertEquals(8, count, "Triangle in GL_2D should produce 8 floats");
|
||||
|
||||
assertEquals(GL11.GL_POLYGON_TOKEN, buf.get(0), 0.001f);
|
||||
assertEquals(3.0f, buf.get(1), 0.001f);
|
||||
|
||||
// Vertex 0: NDC(0,0) → window(400, 300)
|
||||
assertEquals(400.0f, buf.get(2), 0.01f);
|
||||
assertEquals(300.0f, buf.get(3), 0.01f);
|
||||
|
||||
// Vertex 1: NDC(1,0) → window(800, 300)
|
||||
assertEquals(800.0f, buf.get(4), 0.01f);
|
||||
assertEquals(300.0f, buf.get(5), 0.01f);
|
||||
|
||||
// Vertex 2: NDC(0,1) → window(400, 600)
|
||||
assertEquals(400.0f, buf.get(6), 0.01f);
|
||||
assertEquals(600.0f, buf.get(7), 0.01f);
|
||||
|
||||
// Cleanup
|
||||
GLStateManager.glDisableVertexAttribArray(0);
|
||||
GLStateManager.glBindVertexArray(0);
|
||||
GL15.glDeleteBuffers(vbo);
|
||||
GLStateManager.glDeleteVertexArrays(vao);
|
||||
// Identity MVP on an 800x600 viewport: NDC (0,0) -> window (400,300), (1,0) -> (800,300), (0,1) -> (400,600)
|
||||
static Stream<Arguments> primitives() {
|
||||
return Stream.of(
|
||||
Arguments.of("triangle", GL11.GL_TRIANGLES,
|
||||
new float[] { 0f, 0f, 0f, 1f, 0f, 0f, 0f, 1f, 0f },
|
||||
new float[] { GL11.GL_POLYGON_TOKEN, 3f, 400f, 300f, 800f, 300f, 400f, 600f }),
|
||||
Arguments.of("polygon", GL11.GL_POLYGON,
|
||||
new float[] { 0f, 0f, 0f, 1f, 0f, 0f, 1f, 1f, 0f, 0f, 1f, 0f },
|
||||
new float[] { GL11.GL_POLYGON_TOKEN, 4f, 400f, 300f, 800f, 300f, 800f, 600f, 400f, 600f }),
|
||||
Arguments.of("quad strip", GL11.GL_QUAD_STRIP,
|
||||
new float[] { 0f, 0f, 0f, 0f, 1f, 0f, 1f, 0f, 0f, 1f, 1f, 0f },
|
||||
new float[] { GL11.GL_POLYGON_TOKEN, 4f, 400f, 300f, 400f, 600f, 800f, 600f, 800f, 300f }));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testPolygonFeedback_GL2D() {
|
||||
@ParameterizedTest(name = "{0}")
|
||||
@MethodSource("primitives")
|
||||
void testPrimitiveFeedback_GL2D(String name, int mode, float[] verts, float[] expected) {
|
||||
final FloatBuffer buf = BufferUtils.createFloatBuffer(128);
|
||||
FeedbackManager.glFeedbackBuffer(GL11.GL_2D, buf);
|
||||
FeedbackManager.glRenderMode(GL11.GL_FEEDBACK);
|
||||
@@ -171,12 +130,6 @@ class FeedbackManagerTest {
|
||||
final int vao = GL30.glGenVertexArrays();
|
||||
GLStateManager.glBindVertexArray(vao);
|
||||
|
||||
final float[] verts = {
|
||||
0f, 0f, 0f,
|
||||
1f, 0f, 0f,
|
||||
1f, 1f, 0f,
|
||||
0f, 1f, 0f
|
||||
};
|
||||
final FloatBuffer vertBuf = BufferUtils.createFloatBuffer(verts.length);
|
||||
vertBuf.put(verts).flip();
|
||||
|
||||
@@ -186,72 +139,15 @@ class FeedbackManagerTest {
|
||||
GLStateManager.glVertexAttribPointer(0, 3, GL11.GL_FLOAT, false, 12, 0);
|
||||
GLStateManager.glEnableVertexAttribArray(0);
|
||||
|
||||
FeedbackManager.processDrawArrays(GL11.GL_POLYGON, 0, 4);
|
||||
FeedbackManager.processDrawArrays(mode, 0, verts.length / 3);
|
||||
|
||||
final int count = FeedbackManager.glRenderMode(GL11.GL_RENDER);
|
||||
|
||||
assertEquals(10, count, "Polygon in GL_2D should produce 10 floats");
|
||||
assertEquals(GL11.GL_POLYGON_TOKEN, buf.get(0), 0.001f);
|
||||
assertEquals(4.0f, buf.get(1), 0.001f);
|
||||
assertEquals(400.0f, buf.get(2), 0.01f);
|
||||
assertEquals(300.0f, buf.get(3), 0.01f);
|
||||
assertEquals(800.0f, buf.get(4), 0.01f);
|
||||
assertEquals(300.0f, buf.get(5), 0.01f);
|
||||
assertEquals(800.0f, buf.get(6), 0.01f);
|
||||
assertEquals(600.0f, buf.get(7), 0.01f);
|
||||
assertEquals(400.0f, buf.get(8), 0.01f);
|
||||
assertEquals(600.0f, buf.get(9), 0.01f);
|
||||
|
||||
GLStateManager.glDisableVertexAttribArray(0);
|
||||
GLStateManager.glBindVertexArray(0);
|
||||
GL15.glDeleteBuffers(vbo);
|
||||
GLStateManager.glDeleteVertexArrays(vao);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testQuadStripFeedback_GL2D() {
|
||||
final FloatBuffer buf = BufferUtils.createFloatBuffer(128);
|
||||
FeedbackManager.glFeedbackBuffer(GL11.GL_2D, buf);
|
||||
FeedbackManager.glRenderMode(GL11.GL_FEEDBACK);
|
||||
|
||||
GLStateManager.getModelViewMatrix().identity();
|
||||
GLStateManager.getProjectionMatrix().identity();
|
||||
GLStateManager.getViewportState().setViewPort(0, 0, 800, 600);
|
||||
GLStateManager.getViewportState().setDepthRange(0.0, 1.0);
|
||||
|
||||
final int vao = GL30.glGenVertexArrays();
|
||||
GLStateManager.glBindVertexArray(vao);
|
||||
|
||||
final float[] verts = {
|
||||
0f, 0f, 0f,
|
||||
0f, 1f, 0f,
|
||||
1f, 0f, 0f,
|
||||
1f, 1f, 0f
|
||||
};
|
||||
final FloatBuffer vertBuf = BufferUtils.createFloatBuffer(verts.length);
|
||||
vertBuf.put(verts).flip();
|
||||
|
||||
final int vbo = GL15.glGenBuffers();
|
||||
GLStateManager.glBindBuffer(GL15.GL_ARRAY_BUFFER, vbo);
|
||||
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, vertBuf, GL15.GL_STATIC_DRAW);
|
||||
GLStateManager.glVertexAttribPointer(0, 3, GL11.GL_FLOAT, false, 12, 0);
|
||||
GLStateManager.glEnableVertexAttribArray(0);
|
||||
|
||||
FeedbackManager.processDrawArrays(GL11.GL_QUAD_STRIP, 0, 4);
|
||||
|
||||
final int count = FeedbackManager.glRenderMode(GL11.GL_RENDER);
|
||||
|
||||
assertEquals(10, count, "Quad strip in GL_2D should produce 10 floats");
|
||||
assertEquals(GL11.GL_POLYGON_TOKEN, buf.get(0), 0.001f);
|
||||
assertEquals(4.0f, buf.get(1), 0.001f);
|
||||
assertEquals(400.0f, buf.get(2), 0.01f);
|
||||
assertEquals(300.0f, buf.get(3), 0.01f);
|
||||
assertEquals(400.0f, buf.get(4), 0.01f);
|
||||
assertEquals(600.0f, buf.get(5), 0.01f);
|
||||
assertEquals(800.0f, buf.get(6), 0.01f);
|
||||
assertEquals(600.0f, buf.get(7), 0.01f);
|
||||
assertEquals(800.0f, buf.get(8), 0.01f);
|
||||
assertEquals(300.0f, buf.get(9), 0.01f);
|
||||
// GL_2D: POLYGON_TOKEN, vertex count, then x, y per vertex
|
||||
assertEquals(expected.length, count, name + " float count");
|
||||
for (int i = 0; i < expected.length; i++) {
|
||||
assertEquals(expected[i], buf.get(i), 0.01f, name + " feedback value " + i);
|
||||
}
|
||||
|
||||
GLStateManager.glDisableVertexAttribArray(0);
|
||||
GLStateManager.glBindVertexArray(0);
|
||||
|
||||
-7
@@ -22,7 +22,6 @@ class GLSM_BlendFuncUnknownState_GLTest {
|
||||
@BeforeEach
|
||||
void requireBufferBlending() {
|
||||
assumeTrue(RenderSystem.supportsBufferBlending());
|
||||
drainGlErrors();
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
@@ -30,11 +29,6 @@ class GLSM_BlendFuncUnknownState_GLTest {
|
||||
if (!RenderSystem.supportsBufferBlending()) return;
|
||||
GLStateManager.tryBlendFuncSeparate(GL11.GL_ZERO, GL11.GL_ZERO, GL11.GL_ZERO, GL11.GL_ZERO);
|
||||
GLStateManager.tryBlendFuncSeparate(GL11.GL_ONE, GL11.GL_ZERO, GL11.GL_ONE, GL11.GL_ZERO);
|
||||
drainGlErrors();
|
||||
}
|
||||
|
||||
private static void drainGlErrors() {
|
||||
while (GL11.glGetError() != GL11.GL_NO_ERROR) {}
|
||||
}
|
||||
|
||||
private static void seedVanillaSeparate() {
|
||||
@@ -59,7 +53,6 @@ class GLSM_BlendFuncUnknownState_GLTest {
|
||||
assertBufferBlend(buffer, VANILLA_SRC_RGB, VANILLA_DST_RGB, VANILLA_SRC_ALPHA, VANILLA_DST_ALPHA);
|
||||
}
|
||||
assertFalse(GLStateManager.getBlendState().isFuncUnknown(), "forward must clear the unknown flag");
|
||||
assertEquals(GL11.GL_NO_ERROR, GL11.glGetError());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
+22
-38
@@ -3,11 +3,13 @@ package com.gtnewhorizons.angelica.glsm;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.ValueSource;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL30;
|
||||
|
||||
import static com.gtnewhorizons.angelica.util.GLSMUtil.resetGLState;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
/**
|
||||
@@ -51,46 +53,28 @@ class GLSM_BlendUnknownState_UnitTest {
|
||||
assertTrue(GL11.glIsEnabled(GL11.GL_BLEND), "GL blend should be re-enabled after setUnknownState");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testDisableBufferBlendInvalidatesCache() {
|
||||
GLStateManager.enableBlend();
|
||||
assertTrue(GL11.glIsEnabled(GL11.GL_BLEND));
|
||||
@ParameterizedTest(name = "global blend enabled={0}")
|
||||
@ValueSource(booleans = {true, false})
|
||||
void perBufferBlendToggleInvalidatesCache(boolean enabled) {
|
||||
setBlend(enabled);
|
||||
assertEquals(enabled, GL11.glIsEnabled(GL11.GL_BLEND));
|
||||
|
||||
// Use RenderSystem which should call setUnknownState internally
|
||||
RenderSystem.disableBufferBlend(0);
|
||||
// Flips buffer 0 behind the cache and marks it unknown, so the repeated global call must reach the driver
|
||||
if (enabled) {
|
||||
RenderSystem.disableBufferBlend(0);
|
||||
} else {
|
||||
RenderSystem.enableBufferBlend(0);
|
||||
}
|
||||
|
||||
// Now re-enable via GLSM — should issue the GL call
|
||||
GLStateManager.enableBlend();
|
||||
assertTrue(GL11.glIsEnabled(GL11.GL_BLEND), "Blend should be re-enabled after disableBufferBlend");
|
||||
setBlend(enabled);
|
||||
assertEquals(enabled, GL11.glIsEnabled(GL11.GL_BLEND), "global blend state must be re-issued after a per-buffer toggle");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testEnableBufferBlendInvalidatesCache() {
|
||||
// Start with blend disabled
|
||||
GLStateManager.disableBlend();
|
||||
assertFalse(GL11.glIsEnabled(GL11.GL_BLEND));
|
||||
|
||||
// Per-buffer enable bypasses cache
|
||||
RenderSystem.enableBufferBlend(0);
|
||||
|
||||
// Disable via GLSM — should issue the GL call despite cache saying disabled
|
||||
GLStateManager.disableBlend();
|
||||
assertFalse(GL11.glIsEnabled(GL11.GL_BLEND), "Blend should be disabled after enableBufferBlend + disableBlend");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testUnknownStateClearedAfterSetEnabled() {
|
||||
GLStateManager.enableBlend();
|
||||
|
||||
// Mark unknown
|
||||
GLStateManager.getBlendMode().setUnknownState();
|
||||
|
||||
// First setEnabled clears the unknown flag
|
||||
GLStateManager.enableBlend();
|
||||
|
||||
// Second setEnabled should use normal caching (no redundant GL call)
|
||||
// Verify state is consistent
|
||||
assertTrue(GL11.glIsEnabled(GL11.GL_BLEND));
|
||||
assertTrue(GLStateManager.getBlendMode().isEnabled());
|
||||
private static void setBlend(boolean enabled) {
|
||||
if (enabled) {
|
||||
GLStateManager.enableBlend();
|
||||
} else {
|
||||
GLStateManager.disableBlend();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,672 @@
|
||||
package com.gtnewhorizons.angelica.glsm;
|
||||
|
||||
import com.gtnewhorizon.gtnhlib.bytebuf.MemoryUtilities;
|
||||
import com.gtnewhorizon.gtnhlib.client.renderer.vertex.VertexFlags;
|
||||
import com.gtnewhorizon.gtnhlib.client.renderer.vertex.VertexFormatElement.Usage;
|
||||
import com.gtnewhorizons.angelica.glsm.ffp.VAOManager;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.lwjgl.BufferUtils;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL12;
|
||||
import org.lwjgl.opengl.GL13;
|
||||
import org.lwjgl.opengl.GL14;
|
||||
import org.lwjgl.opengl.GL15;
|
||||
import org.lwjgl.opengl.GL20;
|
||||
import org.lwjgl.opengl.GL33;
|
||||
|
||||
import java.nio.FloatBuffer;
|
||||
import java.nio.IntBuffer;
|
||||
|
||||
import static com.gtnewhorizons.angelica.glsm.LegacyQueryFixture.CLIENT_ARRAY_CAPS;
|
||||
import static com.gtnewhorizons.angelica.glsm.LegacyQueryFixture.assertEnableRoundTrip;
|
||||
import static com.gtnewhorizons.angelica.glsm.LegacyQueryFixture.drainClientAttribStack;
|
||||
import static com.gtnewhorizons.angelica.glsm.LegacyQueryFixture.hex;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.junit.jupiter.api.Assumptions.assumeFalse;
|
||||
import static org.junit.jupiter.api.Assumptions.assumeTrue;
|
||||
|
||||
/** Conventional client arrays and the client attrib stack, emulated on a core-profile vertex array object. */
|
||||
@GLCoreTest
|
||||
public class GLSM_ClientArrays_GLTest {
|
||||
|
||||
private int savedVao;
|
||||
private int vao;
|
||||
private int vbo;
|
||||
|
||||
@BeforeEach
|
||||
void bindFreshVertexArray() {
|
||||
savedVao = GLStateManager.getBoundVAO();
|
||||
vao = GLStateManager.glGenVertexArrays();
|
||||
vbo = GLStateManager.glGenBuffers();
|
||||
GLStateManager.glBindVertexArray(vao);
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void deleteVertexArray() {
|
||||
GLStateManager.glBindVertexArray(savedVao);
|
||||
GLStateManager.glDeleteVertexArrays(vao);
|
||||
GLStateManager.glDeleteBuffers(vbo);
|
||||
}
|
||||
|
||||
private static boolean attribHasSize3(Usage usage) {
|
||||
final VAOManager.Attrib attrib = GLStateManager.ctx().vaos.attrib(usage.getAttributeLocation());
|
||||
return attrib != null && attrib.size == 3;
|
||||
}
|
||||
|
||||
private static boolean positionArrayEnabled() {
|
||||
final VAOManager.Attrib position = GLStateManager.ctx().vaos.attrib(Usage.POSITION.getAttributeLocation());
|
||||
return position != null && position.enabled;
|
||||
}
|
||||
|
||||
private static boolean colorArrayEnabled() {
|
||||
return (GLStateManager.ctx().vaos.getVertexFlags() & VertexFlags.COLOR_BIT) != 0;
|
||||
}
|
||||
|
||||
private static int driverAttrib(int index, int pname) {
|
||||
final IntBuffer out = BufferUtils.createIntBuffer(16);
|
||||
GL20.glGetVertexAttrib(index, pname, out);
|
||||
return out.get(0);
|
||||
}
|
||||
|
||||
private static void assertClientArray(String name, int sizePname, int size, int typePname, int type, int stridePname, int stride, int bindingPname, int binding) {
|
||||
if (sizePname != 0) assertEquals(size, GLStateManager.glGetInteger(sizePname), name + " size");
|
||||
if (typePname != 0) assertEquals(type, GLStateManager.glGetInteger(typePname), name + " type");
|
||||
assertEquals(stride, GLStateManager.glGetInteger(stridePname), name + " stride");
|
||||
assertEquals(binding, GLStateManager.glGetInteger(bindingPname), name + " buffer binding");
|
||||
}
|
||||
|
||||
private static void assertVertexArray(String name, int size, int type, int stride, int binding) {
|
||||
assertClientArray(name, GL11.GL_VERTEX_ARRAY_SIZE, size, GL11.GL_VERTEX_ARRAY_TYPE, type, GL11.GL_VERTEX_ARRAY_STRIDE, stride, GL15.GL_VERTEX_ARRAY_BUFFER_BINDING, binding);
|
||||
}
|
||||
|
||||
private static void assertTexCoordArray(String name, int size, int type, int stride, int binding) {
|
||||
assertClientArray(name, GL11.GL_TEXTURE_COORD_ARRAY_SIZE, size, GL11.GL_TEXTURE_COORD_ARRAY_TYPE, type, GL11.GL_TEXTURE_COORD_ARRAY_STRIDE, stride,
|
||||
GL15.GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING, binding);
|
||||
}
|
||||
|
||||
@Test
|
||||
void vertexArrayStateRestoredOnlyWithVertexArrayBit() {
|
||||
final int position = Usage.POSITION.getAttributeLocation();
|
||||
try {
|
||||
GLStateManager.glClientActiveTexture(GL13.GL_TEXTURE0);
|
||||
final int flagsBefore = GLStateManager.ctx().vaos.getVertexFlags();
|
||||
assertFalse(positionArrayEnabled());
|
||||
assertFalse(colorArrayEnabled());
|
||||
|
||||
GLStateManager.glPushClientAttrib(GL11.GL_CLIENT_VERTEX_ARRAY_BIT);
|
||||
GLStateManager.glEnableClientState(GL11.GL_VERTEX_ARRAY);
|
||||
GLStateManager.glEnableClientState(GL11.GL_COLOR_ARRAY);
|
||||
GLStateManager.glClientActiveTexture(GL13.GL_TEXTURE1);
|
||||
assertTrue(positionArrayEnabled());
|
||||
assertTrue(colorArrayEnabled());
|
||||
GLStateManager.glPopClientAttrib();
|
||||
assertFalse(positionArrayEnabled(), "pop disables an array enabled inside the push");
|
||||
assertEquals(GL11.GL_FALSE, driverAttrib(position, GL20.GL_VERTEX_ATTRIB_ARRAY_ENABLED));
|
||||
assertFalse(colorArrayEnabled());
|
||||
assertEquals(flagsBefore, GLStateManager.ctx().vaos.getVertexFlags());
|
||||
assertEquals(0, GLStateManager.getClientActiveTextureUnit());
|
||||
|
||||
GLStateManager.glEnableClientState(GL11.GL_VERTEX_ARRAY);
|
||||
GLStateManager.glPushClientAttrib(GL11.GL_CLIENT_VERTEX_ARRAY_BIT);
|
||||
GLStateManager.glDisableClientState(GL11.GL_VERTEX_ARRAY);
|
||||
GLStateManager.glPopClientAttrib();
|
||||
assertTrue(positionArrayEnabled(), "pop re-enables an array disabled inside the push");
|
||||
assertEquals(GL11.GL_TRUE, driverAttrib(position, GL20.GL_VERTEX_ATTRIB_ARRAY_ENABLED));
|
||||
GLStateManager.glDisableClientState(GL11.GL_VERTEX_ARRAY);
|
||||
|
||||
GLStateManager.glPushClientAttrib(GL11.GL_CLIENT_PIXEL_STORE_BIT);
|
||||
GLStateManager.glEnableClientState(GL11.GL_VERTEX_ARRAY);
|
||||
GLStateManager.glEnableClientState(GL11.GL_COLOR_ARRAY);
|
||||
GLStateManager.glClientActiveTexture(GL13.GL_TEXTURE1);
|
||||
GLStateManager.glPopClientAttrib();
|
||||
assertTrue(positionArrayEnabled(), "a pixel-store push must not restore array enables");
|
||||
assertTrue(colorArrayEnabled());
|
||||
assertEquals(1, GLStateManager.getClientActiveTextureUnit());
|
||||
} finally {
|
||||
drainClientAttribStack();
|
||||
GLStateManager.glClientActiveTexture(GL13.GL_TEXTURE0);
|
||||
GLStateManager.glDisableClientState(GL11.GL_VERTEX_ARRAY);
|
||||
GLStateManager.glDisableClientState(GL11.GL_COLOR_ARRAY);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void clientActiveTextureRoundTrips() {
|
||||
try {
|
||||
GLStateManager.glBindBuffer(GL15.GL_ARRAY_BUFFER, vbo);
|
||||
assertEquals(GLStateManager.MAX_TEXTURE_COORDS, GLStateManager.glGetInteger(GL20.GL_MAX_TEXTURE_COORDS));
|
||||
|
||||
GLStateManager.glClientActiveTexture(GL13.GL_TEXTURE1);
|
||||
assertEquals(GL13.GL_TEXTURE1, GLStateManager.glGetInteger(GL13.GL_CLIENT_ACTIVE_TEXTURE));
|
||||
GLStateManager.glClientActiveTexture(0);
|
||||
assertEquals(GL13.GL_TEXTURE1, GLStateManager.glGetInteger(GL13.GL_CLIENT_ACTIVE_TEXTURE));
|
||||
GLStateManager.glClientActiveTexture(GL13.GL_TEXTURE0 + GLStateManager.MAX_TEXTURE_UNITS);
|
||||
assertEquals(GL13.GL_TEXTURE1, GLStateManager.glGetInteger(GL13.GL_CLIENT_ACTIVE_TEXTURE));
|
||||
GLStateManager.glClientActiveTexture(GL13.GL_TEXTURE0 + GLStateManager.MAX_TEXTURE_COORDS);
|
||||
assertEquals(GL13.GL_TEXTURE1, GLStateManager.glGetInteger(GL13.GL_CLIENT_ACTIVE_TEXTURE), "units past GL_MAX_TEXTURE_COORDS are rejected");
|
||||
assertEquals(1, GLStateManager.getClientActiveTextureUnit());
|
||||
|
||||
GLStateManager.glTexCoordPointer(2, GL11.GL_FLOAT, 0, 0L);
|
||||
final VAOManager.Attrib attrib = GLStateManager.ctx().vaos.attrib(Usage.SECONDARY_UV.getAttributeLocation());
|
||||
assertNotNull(attrib);
|
||||
assertEquals(2, attrib.size);
|
||||
|
||||
assumeTrue(GLStateManager.MAX_TEXTURE_COORDS > 5);
|
||||
GLStateManager.glClientActiveTexture(GL13.GL_TEXTURE5);
|
||||
assertEquals(GL13.GL_TEXTURE5, GLStateManager.glGetInteger(GL13.GL_CLIENT_ACTIVE_TEXTURE));
|
||||
GLStateManager.glTexCoordPointer(3, GL11.GL_FLOAT, 0, 0L);
|
||||
assertEquals(3, GLStateManager.glGetInteger(GL11.GL_TEXTURE_COORD_ARRAY_SIZE));
|
||||
assertFalse(attribHasSize3(Usage.PRIMARY_UV));
|
||||
assertFalse(attribHasSize3(Usage.SECONDARY_UV));
|
||||
} finally {
|
||||
GLStateManager.glClientActiveTexture(GL13.GL_TEXTURE0);
|
||||
GLStateManager.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void conventionalPointerSurvivesGenericOverride() {
|
||||
final int position = Usage.POSITION.getAttributeLocation();
|
||||
try {
|
||||
GLStateManager.glBindBuffer(GL15.GL_ARRAY_BUFFER, vbo);
|
||||
|
||||
GLStateManager.glVertexPointer(3, GL11.GL_FLOAT, 12, 0L);
|
||||
GLStateManager.glEnableClientState(GL11.GL_VERTEX_ARRAY);
|
||||
GLStateManager.glVertexAttribPointer(position, 2, GL11.GL_FLOAT, false, 8, 4L);
|
||||
assertEquals(3, VAOManager.get(position).size, "disabled generic pointer must not displace an enabled conventional array");
|
||||
assertEquals(3, driverAttrib(position, GL20.GL_VERTEX_ATTRIB_ARRAY_SIZE));
|
||||
|
||||
GLStateManager.glEnableVertexAttribArray(position);
|
||||
assertEquals(2, VAOManager.get(position).size, "enabled generic attribute wins");
|
||||
assertTrue(VAOManager.get(position).genericPointer);
|
||||
assertEquals(2, driverAttrib(position, GL20.GL_VERTEX_ATTRIB_ARRAY_SIZE));
|
||||
assertEquals(8, driverAttrib(position, GL20.GL_VERTEX_ATTRIB_ARRAY_STRIDE));
|
||||
|
||||
GLStateManager.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
|
||||
GLStateManager.glDisableVertexAttribArray(position);
|
||||
assertEquals(3, VAOManager.get(position).size, "conventional pointer must come back when the generic attribute is disabled");
|
||||
assertEquals(12, VAOManager.get(position).stride);
|
||||
assertFalse(VAOManager.get(position).genericPointer);
|
||||
assertEquals(3, driverAttrib(position, GL20.GL_VERTEX_ATTRIB_ARRAY_SIZE));
|
||||
assertEquals(12, driverAttrib(position, GL20.GL_VERTEX_ATTRIB_ARRAY_STRIDE));
|
||||
assertEquals(vbo, driverAttrib(position, GL15.GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING));
|
||||
assertEquals(GL11.GL_TRUE, driverAttrib(position, GL20.GL_VERTEX_ATTRIB_ARRAY_ENABLED), "conventional array stays enabled at draw level");
|
||||
assertTrue(GLStateManager.glIsEnabled(GL11.GL_VERTEX_ARRAY));
|
||||
assertEquals(0, GLStateManager.glGetInteger(GL15.GL_ARRAY_BUFFER_BINDING), "repoint must restore the array buffer binding");
|
||||
} finally {
|
||||
GLStateManager.glDisableVertexAttribArray(position);
|
||||
GLStateManager.glDisableClientState(GL11.GL_VERTEX_ARRAY);
|
||||
GLStateManager.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void conventionalPointerSetUnderEnabledGenericAppliesOnceGenericIsDisabled() {
|
||||
final int position = Usage.POSITION.getAttributeLocation();
|
||||
try {
|
||||
GLStateManager.glBindBuffer(GL15.GL_ARRAY_BUFFER, vbo);
|
||||
|
||||
GLStateManager.glVertexAttribPointer(position, 2, GL11.GL_FLOAT, false, 8, 0L);
|
||||
GLStateManager.glEnableVertexAttribArray(position);
|
||||
GLStateManager.glVertexPointer(3, GL11.GL_FLOAT, 12, 0L);
|
||||
GLStateManager.glEnableClientState(GL11.GL_VERTEX_ARRAY);
|
||||
assertEquals(2, VAOManager.get(position).size);
|
||||
assertEquals(2, driverAttrib(position, GL20.GL_VERTEX_ATTRIB_ARRAY_SIZE));
|
||||
|
||||
GLStateManager.glDisableVertexAttribArray(position);
|
||||
assertEquals(3, VAOManager.get(position).size);
|
||||
assertEquals(3, driverAttrib(position, GL20.GL_VERTEX_ATTRIB_ARRAY_SIZE));
|
||||
assertEquals(GL11.GL_TRUE, driverAttrib(position, GL20.GL_VERTEX_ATTRIB_ARRAY_ENABLED));
|
||||
|
||||
GLStateManager.glDisableClientState(GL11.GL_VERTEX_ARRAY);
|
||||
assertEquals(GL11.GL_FALSE, driverAttrib(position, GL20.GL_VERTEX_ATTRIB_ARRAY_ENABLED));
|
||||
assertFalse(positionArrayEnabled());
|
||||
} finally {
|
||||
GLStateManager.glDisableVertexAttribArray(position);
|
||||
GLStateManager.glDisableClientState(GL11.GL_VERTEX_ARRAY);
|
||||
GLStateManager.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void drawVertexFlagsDoNotAnswerClientArrayEnables() {
|
||||
try {
|
||||
GLStateManager.glClientActiveTexture(GL13.GL_TEXTURE0);
|
||||
VAOManager.setCurrentVertexFlags(VertexFlags.COLOR_BIT | VertexFlags.NORMAL_BIT | VertexFlags.TEXTURE_BIT);
|
||||
assertFalse(GLStateManager.glIsEnabled(GL11.GL_COLOR_ARRAY));
|
||||
assertFalse(GLStateManager.glIsEnabled(GL11.GL_NORMAL_ARRAY));
|
||||
assertFalse(GLStateManager.glIsEnabled(GL11.GL_TEXTURE_COORD_ARRAY));
|
||||
|
||||
GLStateManager.glEnableClientState(GL11.GL_COLOR_ARRAY);
|
||||
VAOManager.setCurrentVertexFlags(0);
|
||||
assertTrue(GLStateManager.glIsEnabled(GL11.GL_COLOR_ARRAY));
|
||||
} finally {
|
||||
GLStateManager.glDisableClientState(GL11.GL_COLOR_ARRAY);
|
||||
VAOManager.setCurrentVertexFlags(0);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void clientArrayPointerQueriesAreAnsweredFromCache() {
|
||||
final int vaoB = GLStateManager.glGenVertexArrays();
|
||||
final IntBuffer ints = BufferUtils.createIntBuffer(16);
|
||||
try {
|
||||
GLStateManager.glBindBuffer(GL15.GL_ARRAY_BUFFER, vbo);
|
||||
GLStateManager.glClientActiveTexture(GL13.GL_TEXTURE0);
|
||||
|
||||
assertVertexArray("default vertex", 4, GL11.GL_FLOAT, 0, 0);
|
||||
assertClientArray("default normal", 0, 0, GL11.GL_NORMAL_ARRAY_TYPE, GL11.GL_FLOAT, GL11.GL_NORMAL_ARRAY_STRIDE, 0, GL15.GL_NORMAL_ARRAY_BUFFER_BINDING, 0);
|
||||
assertClientArray("default color", GL11.GL_COLOR_ARRAY_SIZE, 4, GL11.GL_COLOR_ARRAY_TYPE, GL11.GL_FLOAT, GL11.GL_COLOR_ARRAY_STRIDE, 0, GL15.GL_COLOR_ARRAY_BUFFER_BINDING, 0);
|
||||
assertClientArray("default secondary color", GL14.GL_SECONDARY_COLOR_ARRAY_SIZE, 3, GL14.GL_SECONDARY_COLOR_ARRAY_TYPE, GL11.GL_FLOAT,
|
||||
GL14.GL_SECONDARY_COLOR_ARRAY_STRIDE, 0, GL15.GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING, 0);
|
||||
assertClientArray("default fog coord", 0, 0, GL14.GL_FOG_COORDINATE_ARRAY_TYPE, GL11.GL_FLOAT, GL14.GL_FOG_COORDINATE_ARRAY_STRIDE, 0,
|
||||
GL15.GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING, 0);
|
||||
assertClientArray("default index", 0, 0, GL11.GL_INDEX_ARRAY_TYPE, GL11.GL_FLOAT, GL11.GL_INDEX_ARRAY_STRIDE, 0, GL15.GL_INDEX_ARRAY_BUFFER_BINDING, 0);
|
||||
assertClientArray("default edge flag", 0, 0, 0, 0, GL11.GL_EDGE_FLAG_ARRAY_STRIDE, 0, GL15.GL_EDGE_FLAG_ARRAY_BUFFER_BINDING, 0);
|
||||
assertTexCoordArray("default texcoord", 4, GL11.GL_FLOAT, 0, 0);
|
||||
assertNull(GLStateManager.glGetPointer(GL11.GL_VERTEX_ARRAY_POINTER, 4));
|
||||
|
||||
GLStateManager.glVertexPointer(3, GL11.GL_SHORT, 20, 8L);
|
||||
GLStateManager.glNormalPointer(GL11.GL_BYTE, 16, 4L);
|
||||
GLStateManager.glColorPointer(4, GL11.GL_UNSIGNED_BYTE, 16, 12L);
|
||||
GLStateManager.glSecondaryColorPointer(3, GL11.GL_FLOAT, 12, 0L);
|
||||
GLStateManager.glFogCoordPointer(GL11.GL_FLOAT, 4, 0L);
|
||||
GLStateManager.glEdgeFlagPointer(7, 0L);
|
||||
GLStateManager.glTexCoordPointer(2, GL11.GL_FLOAT, 8, 0L);
|
||||
|
||||
assertVertexArray("vertex", 3, GL11.GL_SHORT, 20, vbo);
|
||||
assertClientArray("normal", 0, 0, GL11.GL_NORMAL_ARRAY_TYPE, GL11.GL_BYTE, GL11.GL_NORMAL_ARRAY_STRIDE, 16, GL15.GL_NORMAL_ARRAY_BUFFER_BINDING, vbo);
|
||||
assertClientArray("color", GL11.GL_COLOR_ARRAY_SIZE, 4, GL11.GL_COLOR_ARRAY_TYPE, GL11.GL_UNSIGNED_BYTE, GL11.GL_COLOR_ARRAY_STRIDE, 16,
|
||||
GL15.GL_COLOR_ARRAY_BUFFER_BINDING, vbo);
|
||||
assertClientArray("secondary color", GL14.GL_SECONDARY_COLOR_ARRAY_SIZE, 3, GL14.GL_SECONDARY_COLOR_ARRAY_TYPE, GL11.GL_FLOAT,
|
||||
GL14.GL_SECONDARY_COLOR_ARRAY_STRIDE, 12, GL15.GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING, vbo);
|
||||
assertClientArray("fog coord", 0, 0, GL14.GL_FOG_COORDINATE_ARRAY_TYPE, GL11.GL_FLOAT, GL14.GL_FOG_COORDINATE_ARRAY_STRIDE, 4,
|
||||
GL15.GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING, vbo);
|
||||
assertClientArray("edge flag", 0, 0, 0, 0, GL11.GL_EDGE_FLAG_ARRAY_STRIDE, 7, GL15.GL_EDGE_FLAG_ARRAY_BUFFER_BINDING, vbo);
|
||||
assertTexCoordArray("texcoord unit 0", 2, GL11.GL_FLOAT, 8, vbo);
|
||||
|
||||
assertEquals(3.0f, GLStateManager.glGetFloat(GL11.GL_VERTEX_ARRAY_SIZE));
|
||||
GLStateManager.glGetInteger(GL11.GL_VERTEX_ARRAY_STRIDE, ints);
|
||||
assertEquals(20, ints.get(0));
|
||||
assertEquals(8L, MemoryUtilities.memAddress(GLStateManager.glGetPointer(GL11.GL_VERTEX_ARRAY_POINTER, 4)));
|
||||
assertEquals(12L, MemoryUtilities.memAddress(GLStateManager.glGetPointer(GL11.GL_COLOR_ARRAY_POINTER, 4)));
|
||||
|
||||
GLStateManager.glClientActiveTexture(GL13.GL_TEXTURE0 + GLStateManager.MAX_TEXTURE_COORDS - 1);
|
||||
assertTexCoordArray("unset texcoord unit", 4, GL11.GL_FLOAT, 0, 0);
|
||||
GLStateManager.glTexCoordPointer(3, GL11.GL_SHORT, 6, 0L);
|
||||
assertTexCoordArray("last texcoord unit", 3, GL11.GL_SHORT, 6, vbo);
|
||||
assertFalse(attribHasSize3(Usage.PRIMARY_UV));
|
||||
assertFalse(attribHasSize3(Usage.SECONDARY_UV));
|
||||
GLStateManager.glClientActiveTexture(GL13.GL_TEXTURE0);
|
||||
assertTexCoordArray("texcoord unit 0 again", 2, GL11.GL_FLOAT, 8, vbo);
|
||||
|
||||
GLStateManager.glBindVertexArray(vaoB);
|
||||
assertVertexArray("other vao", 4, GL11.GL_FLOAT, 0, 0);
|
||||
final FloatBuffer client = BufferUtils.createFloatBuffer(12);
|
||||
GLStateManager.glVertexPointer(2, 0, client);
|
||||
assertVertexArray("client pointer", 2, GL11.GL_FLOAT, 0, 0);
|
||||
assertEquals(MemoryUtilities.memAddress(client), MemoryUtilities.memAddress(GLStateManager.glGetPointer(GL11.GL_VERTEX_ARRAY_POINTER, 4)));
|
||||
GLStateManager.glBindVertexArray(vao);
|
||||
assertVertexArray("first vao again", 3, GL11.GL_SHORT, 20, vbo);
|
||||
} finally {
|
||||
GLStateManager.glClientActiveTexture(GL13.GL_TEXTURE0);
|
||||
GLStateManager.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
|
||||
GLStateManager.glDeleteVertexArrays(vaoB);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void interleavedArraysSetClientStateWithoutAnActiveFfpProgram() {
|
||||
try {
|
||||
GLStateManager.glBindBuffer(GL15.GL_ARRAY_BUFFER, vbo);
|
||||
GLStateManager.glClientActiveTexture(GL13.GL_TEXTURE0);
|
||||
assumeFalse(GLStateManager.ctx().ffp.isActive());
|
||||
|
||||
GLStateManager.glInterleavedArrays(GL11.GL_C4UB_V3F, 0, 0L);
|
||||
assertTrue(GLStateManager.glIsEnabled(GL11.GL_VERTEX_ARRAY));
|
||||
assertTrue(GLStateManager.glIsEnabled(GL11.GL_COLOR_ARRAY));
|
||||
assertFalse(GLStateManager.glIsEnabled(GL11.GL_NORMAL_ARRAY));
|
||||
assertVertexArray("interleaved vertex", 3, GL11.GL_FLOAT, 16, vbo);
|
||||
assertEquals(GL11.GL_UNSIGNED_BYTE, GLStateManager.glGetInteger(GL11.GL_COLOR_ARRAY_TYPE));
|
||||
} finally {
|
||||
for (final int cap : CLIENT_ARRAY_CAPS) {
|
||||
GLStateManager.glDisableClientState(cap);
|
||||
}
|
||||
GLStateManager.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void clientVertexArrayBitRestoresPointersEnablesAndBindings() {
|
||||
final int vaoB = GLStateManager.glGenVertexArrays();
|
||||
final int vbo2 = GLStateManager.glGenBuffers();
|
||||
final int ebo = GLStateManager.glGenBuffers();
|
||||
final int position = Usage.POSITION.getAttributeLocation();
|
||||
final int color = Usage.COLOR.getAttributeLocation();
|
||||
final int normal = Usage.NORMAL.getAttributeLocation();
|
||||
try {
|
||||
GLStateManager.glBindBuffer(GL15.GL_ARRAY_BUFFER, vbo);
|
||||
GLStateManager.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, ebo);
|
||||
GLStateManager.glClientActiveTexture(GL13.GL_TEXTURE0);
|
||||
GLStateManager.glVertexPointer(3, GL11.GL_FLOAT, 12, 0L);
|
||||
GLStateManager.glColorPointer(4, GL11.GL_UNSIGNED_BYTE, 16, 12L);
|
||||
GLStateManager.glFogCoordPointer(GL11.GL_FLOAT, 4, 0L);
|
||||
GLStateManager.glEnableClientState(GL11.GL_VERTEX_ARRAY);
|
||||
GLStateManager.glEnableClientState(GL11.GL_COLOR_ARRAY);
|
||||
|
||||
GLStateManager.glPushClientAttrib(GL11.GL_CLIENT_VERTEX_ARRAY_BIT);
|
||||
GLStateManager.glBindBuffer(GL15.GL_ARRAY_BUFFER, vbo2);
|
||||
GLStateManager.glVertexPointer(2, GL11.GL_SHORT, 4, 4L);
|
||||
GLStateManager.glFogCoordPointer(GL11.GL_FLOAT, 8, 0L);
|
||||
GLStateManager.glDisableClientState(GL11.GL_COLOR_ARRAY);
|
||||
GLStateManager.glEnableClientState(GL11.GL_NORMAL_ARRAY);
|
||||
GLStateManager.glVertexAttribPointer(5, 1, GL11.GL_FLOAT, false, 4, 0L);
|
||||
GLStateManager.glEnableVertexAttribArray(5);
|
||||
GLStateManager.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
GLStateManager.glClientActiveTexture(GL13.GL_TEXTURE1);
|
||||
GLStateManager.glBindVertexArray(vaoB);
|
||||
GLStateManager.glPopClientAttrib();
|
||||
|
||||
assertEquals(vao, GLStateManager.getBoundVAO());
|
||||
assertEquals(vbo, GLStateManager.glGetInteger(GL15.GL_ARRAY_BUFFER_BINDING));
|
||||
assertEquals(ebo, GLStateManager.glGetInteger(GL15.GL_ELEMENT_ARRAY_BUFFER_BINDING));
|
||||
assertEquals(ebo, GL11.glGetInteger(GL15.GL_ELEMENT_ARRAY_BUFFER_BINDING));
|
||||
assertEquals(GL13.GL_TEXTURE0, GLStateManager.glGetInteger(GL13.GL_CLIENT_ACTIVE_TEXTURE));
|
||||
assertVertexArray("restored vertex", 3, GL11.GL_FLOAT, 12, vbo);
|
||||
assertEquals(4, GLStateManager.glGetInteger(GL14.GL_FOG_COORDINATE_ARRAY_STRIDE));
|
||||
assertEquals(vbo, GLStateManager.glGetInteger(GL15.GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING));
|
||||
assertTrue(GLStateManager.glIsEnabled(GL11.GL_COLOR_ARRAY));
|
||||
assertFalse(GLStateManager.glIsEnabled(GL11.GL_NORMAL_ARRAY));
|
||||
assertTrue(colorArrayEnabled());
|
||||
|
||||
assertEquals(3, driverAttrib(position, GL20.GL_VERTEX_ATTRIB_ARRAY_SIZE));
|
||||
assertEquals(GL11.GL_FLOAT, driverAttrib(position, GL20.GL_VERTEX_ATTRIB_ARRAY_TYPE));
|
||||
assertEquals(12, driverAttrib(position, GL20.GL_VERTEX_ATTRIB_ARRAY_STRIDE));
|
||||
assertEquals(vbo, driverAttrib(position, GL15.GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING));
|
||||
assertEquals(GL11.GL_TRUE, driverAttrib(position, GL20.GL_VERTEX_ATTRIB_ARRAY_ENABLED));
|
||||
assertEquals(GL11.GL_TRUE, driverAttrib(color, GL20.GL_VERTEX_ATTRIB_ARRAY_ENABLED));
|
||||
assertEquals(GL11.GL_FALSE, driverAttrib(normal, GL20.GL_VERTEX_ATTRIB_ARRAY_ENABLED));
|
||||
assertEquals(GL11.GL_FALSE, driverAttrib(5, GL20.GL_VERTEX_ATTRIB_ARRAY_ENABLED));
|
||||
|
||||
GLStateManager.glBindVertexArray(vaoB);
|
||||
GLStateManager.glPushClientAttrib(GL11.GL_CLIENT_VERTEX_ARRAY_BIT);
|
||||
GLStateManager.glBindVertexArray(vao);
|
||||
GLStateManager.glDeleteVertexArrays(vaoB);
|
||||
GLStateManager.glPopClientAttrib();
|
||||
assertEquals(vao, GLStateManager.getBoundVAO(), "a deleted VAO must not be restored");
|
||||
assertVertexArray("after dead-vao pop", 3, GL11.GL_FLOAT, 12, vbo);
|
||||
} finally {
|
||||
drainClientAttribStack();
|
||||
GLStateManager.glBindVertexArray(vao);
|
||||
GLStateManager.glClientActiveTexture(GL13.GL_TEXTURE0);
|
||||
for (final int cap : CLIENT_ARRAY_CAPS) {
|
||||
GLStateManager.glDisableClientState(cap);
|
||||
}
|
||||
GLStateManager.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
|
||||
GLStateManager.glDeleteVertexArrays(vaoB);
|
||||
GLStateManager.glDeleteBuffers(vbo2);
|
||||
GLStateManager.glDeleteBuffers(ebo);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void enabledGenericAttributeWinsWithoutAPointer() {
|
||||
final int position = Usage.POSITION.getAttributeLocation();
|
||||
try {
|
||||
GLStateManager.glBindBuffer(GL15.GL_ARRAY_BUFFER, vbo);
|
||||
GLStateManager.glVertexPointer(3, GL11.GL_FLOAT, 12, 0L);
|
||||
GLStateManager.glEnableClientState(GL11.GL_VERTEX_ARRAY);
|
||||
assertFalse(VAOManager.get(position).genericPointer);
|
||||
|
||||
GLStateManager.glEnableVertexAttribArray(position);
|
||||
assertTrue(VAOManager.get(position).genericPointer, "generic 0 supersedes position on its enable bit alone");
|
||||
GLStateManager.glDisableVertexAttribArray(position);
|
||||
assertFalse(VAOManager.get(position).genericPointer);
|
||||
assertEquals(3, VAOManager.get(position).size);
|
||||
} finally {
|
||||
GLStateManager.glDisableVertexAttribArray(position);
|
||||
GLStateManager.glDisableClientState(GL11.GL_VERTEX_ARRAY);
|
||||
GLStateManager.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void deletedBufferIsDetachedFromTheBoundVertexArray() {
|
||||
GLStateManager.glBindBuffer(GL15.GL_ARRAY_BUFFER, vbo);
|
||||
GLStateManager.glVertexPointer(3, GL11.GL_FLOAT, 12, 4L);
|
||||
GLStateManager.glFogCoordPointer(GL11.GL_FLOAT, 4, 0L);
|
||||
assertEquals(vbo, GLStateManager.glGetInteger(GL15.GL_VERTEX_ARRAY_BUFFER_BINDING));
|
||||
|
||||
GLStateManager.glDeleteBuffers(vbo);
|
||||
assertEquals(0, GLStateManager.glGetInteger(GL15.GL_VERTEX_ARRAY_BUFFER_BINDING));
|
||||
assertEquals(0, GLStateManager.glGetInteger(GL15.GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING));
|
||||
assertEquals(12, GLStateManager.glGetInteger(GL11.GL_VERTEX_ARRAY_STRIDE), "offset and stride survive the detach");
|
||||
assertEquals(3, GLStateManager.glGetInteger(GL11.GL_VERTEX_ARRAY_SIZE));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shadowedPointerIsNotRepointedAtAReusedBufferName() {
|
||||
final int other = GLStateManager.glGenVertexArrays();
|
||||
final int conventional = GLStateManager.glGenBuffers();
|
||||
final int generic = GLStateManager.glGenBuffers();
|
||||
final int position = Usage.POSITION.getAttributeLocation();
|
||||
int reused = 0;
|
||||
try {
|
||||
GLStateManager.glBindBuffer(GL15.GL_ARRAY_BUFFER, conventional);
|
||||
GLStateManager.glVertexPointer(3, GL11.GL_FLOAT, 12, 0L);
|
||||
GLStateManager.glEnableClientState(GL11.GL_VERTEX_ARRAY);
|
||||
GLStateManager.glBindBuffer(GL15.GL_ARRAY_BUFFER, generic);
|
||||
GLStateManager.glVertexAttribPointer(position, 2, GL11.GL_FLOAT, false, 8, 0L);
|
||||
GLStateManager.glEnableVertexAttribArray(position);
|
||||
|
||||
GLStateManager.glBindVertexArray(other);
|
||||
GLStateManager.glDeleteBuffers(conventional);
|
||||
reused = GLStateManager.glGenBuffers();
|
||||
GLStateManager.glBindBuffer(GL15.GL_ARRAY_BUFFER, reused);
|
||||
assumeTrue(reused == conventional, "driver did not reuse the buffer name");
|
||||
|
||||
GLStateManager.glBindVertexArray(vao);
|
||||
GLStateManager.glDisableVertexAttribArray(position);
|
||||
assertEquals(generic, driverAttrib(position, GL15.GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING), "a pointer set before the delete must not attach to the new buffer");
|
||||
} finally {
|
||||
GLStateManager.glBindVertexArray(vao);
|
||||
GLStateManager.glDisableVertexAttribArray(position);
|
||||
GLStateManager.glDisableClientState(GL11.GL_VERTEX_ARRAY);
|
||||
GLStateManager.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
|
||||
GLStateManager.glDeleteVertexArrays(other);
|
||||
GLStateManager.glDeleteBuffers(generic);
|
||||
if (reused != 0) GLStateManager.glDeleteBuffers(reused);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void popKeepsCurrentArraysWhenTheSavedArrayBufferWasDeleted() {
|
||||
final int vbo2 = GLStateManager.glGenBuffers();
|
||||
try {
|
||||
GLStateManager.glBindBuffer(GL15.GL_ARRAY_BUFFER, vbo);
|
||||
GLStateManager.glClientActiveTexture(GL13.GL_TEXTURE0);
|
||||
GLStateManager.glVertexPointer(3, GL11.GL_FLOAT, 12, 0L);
|
||||
|
||||
GLStateManager.glPushClientAttrib(GL11.GL_CLIENT_VERTEX_ARRAY_BIT);
|
||||
GLStateManager.glBindBuffer(GL15.GL_ARRAY_BUFFER, vbo2);
|
||||
GLStateManager.glVertexPointer(2, GL11.GL_SHORT, 4, 0L);
|
||||
GLStateManager.glClientActiveTexture(GL13.GL_TEXTURE1);
|
||||
GLStateManager.glDeleteBuffers(vbo);
|
||||
GLStateManager.glPopClientAttrib();
|
||||
|
||||
assertEquals(2, GLStateManager.glGetInteger(GL11.GL_VERTEX_ARRAY_SIZE), "array state is not restored once its array buffer is gone");
|
||||
assertEquals(vbo2, GLStateManager.glGetInteger(GL15.GL_ARRAY_BUFFER_BINDING));
|
||||
assertEquals(GL13.GL_TEXTURE0, GLStateManager.glGetInteger(GL13.GL_CLIENT_ACTIVE_TEXTURE));
|
||||
} finally {
|
||||
drainClientAttribStack();
|
||||
GLStateManager.glClientActiveTexture(GL13.GL_TEXTURE0);
|
||||
GLStateManager.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
|
||||
GLStateManager.glDeleteBuffers(vbo2);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void clientAttribStackIsNotCompiledIntoDisplayLists() {
|
||||
final int other = GLStateManager.glGenVertexArrays();
|
||||
final int list = GLStateManager.glGenLists(1);
|
||||
try {
|
||||
GLStateManager.glNewList(list, GL11.GL_COMPILE);
|
||||
GLStateManager.glPushClientAttrib(GL11.GL_CLIENT_VERTEX_ARRAY_BIT);
|
||||
GLStateManager.glPopClientAttrib();
|
||||
GLStateManager.glEndList();
|
||||
|
||||
GLStateManager.glBindVertexArray(other);
|
||||
GLStateManager.glCallList(list);
|
||||
assertEquals(other, GLStateManager.getBoundVAO(), "replaying the list must not rebind the vertex array that was bound while compiling");
|
||||
} finally {
|
||||
drainClientAttribStack();
|
||||
GLStateManager.glDeleteLists(list, 1);
|
||||
GLStateManager.glDeleteVertexArrays(other);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void popRestoresDivisorAndStateWithoutAnAttributeLocation() {
|
||||
try {
|
||||
GLStateManager.glBindBuffer(GL15.GL_ARRAY_BUFFER, vbo);
|
||||
GLStateManager.glVertexAttribPointer(5, 1, GL11.GL_FLOAT, false, 4, 0L);
|
||||
|
||||
GLStateManager.glPushClientAttrib(GL11.GL_CLIENT_VERTEX_ARRAY_BIT);
|
||||
GLStateManager.glPopClientAttrib();
|
||||
assertEquals(0, driverAttrib(5, GL33.GL_VERTEX_ATTRIB_ARRAY_DIVISOR));
|
||||
|
||||
GLStateManager.glPushClientAttrib(GL11.GL_CLIENT_VERTEX_ARRAY_BIT);
|
||||
GLStateManager.glVertexAttribDivisor(5, 3);
|
||||
assertEquals(3, driverAttrib(5, GL33.GL_VERTEX_ATTRIB_ARRAY_DIVISOR));
|
||||
GLStateManager.glPopClientAttrib();
|
||||
assertEquals(0, driverAttrib(5, GL33.GL_VERTEX_ATTRIB_ARRAY_DIVISOR));
|
||||
|
||||
GLStateManager.glPushClientAttrib(GL11.GL_CLIENT_VERTEX_ARRAY_BIT);
|
||||
GLStateManager.glEnableClientState(GL14.GL_FOG_COORDINATE_ARRAY);
|
||||
GLStateManager.glPopClientAttrib();
|
||||
assertFalse(GLStateManager.glIsEnabled(GL14.GL_FOG_COORDINATE_ARRAY));
|
||||
|
||||
GLStateManager.glPushClientAttrib(GL11.GL_CLIENT_VERTEX_ARRAY_BIT);
|
||||
GLStateManager.glEnableVertexAttribArray(5);
|
||||
GLStateManager.glPopClientAttrib();
|
||||
assertEquals(GL11.GL_FALSE, driverAttrib(5, GL20.GL_VERTEX_ATTRIB_ARRAY_ENABLED));
|
||||
} finally {
|
||||
drainClientAttribStack();
|
||||
GLStateManager.glDisableVertexAttribArray(5);
|
||||
GLStateManager.glDisableClientState(GL14.GL_FOG_COORDINATE_ARRAY);
|
||||
GLStateManager.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void interleavedArraysFromAClientBufferRegisterClientPointers() {
|
||||
final FloatBuffer data = BufferUtils.createFloatBuffer(64);
|
||||
final int position = Usage.POSITION.getAttributeLocation();
|
||||
try {
|
||||
GLStateManager.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
|
||||
data.position(2);
|
||||
|
||||
GLStateManager.glInterleavedArrays(GL11.GL_C4UB_V3F, 0, data);
|
||||
final long base = MemoryUtilities.memAddress(data);
|
||||
assertNotNull(VAOManager.get(position).clientPointer);
|
||||
assertEquals(base + 4, MemoryUtilities.memAddress(VAOManager.get(position).clientPointer));
|
||||
assertEquals(base + 4, MemoryUtilities.memAddress(GLStateManager.glGetPointer(GL11.GL_VERTEX_ARRAY_POINTER, 4)));
|
||||
assertEquals(base, MemoryUtilities.memAddress(GLStateManager.glGetPointer(GL11.GL_COLOR_ARRAY_POINTER, 4)));
|
||||
assertEquals(0, GLStateManager.glGetInteger(GL15.GL_VERTEX_ARRAY_BUFFER_BINDING));
|
||||
assertEquals(16, GLStateManager.glGetInteger(GL11.GL_VERTEX_ARRAY_STRIDE));
|
||||
assertTrue(GLStateManager.ctx().vaos.hasAnyClientSideEnabledAttrib());
|
||||
} finally {
|
||||
for (final int cap : CLIENT_ARRAY_CAPS) {
|
||||
GLStateManager.glDisableClientState(cap);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void enableAndDisableRouteClientArrayCapsToClientState() {
|
||||
for (final int cap : CLIENT_ARRAY_CAPS) {
|
||||
GLStateManager.glEnable(cap);
|
||||
assertTrue(GLStateManager.glIsEnabled(cap), hex(cap));
|
||||
GLStateManager.glDisable(cap);
|
||||
assertFalse(GLStateManager.glIsEnabled(cap), hex(cap));
|
||||
}
|
||||
GLStateManager.glEnable(GL11.GL_VERTEX_ARRAY);
|
||||
assertTrue(positionArrayEnabled());
|
||||
GLStateManager.glDisable(GL11.GL_VERTEX_ARRAY);
|
||||
}
|
||||
|
||||
@Test
|
||||
void illegalPointerArgumentsAreIgnored() {
|
||||
try {
|
||||
GLStateManager.glBindBuffer(GL15.GL_ARRAY_BUFFER, vbo);
|
||||
GLStateManager.glVertexPointer(3, GL11.GL_FLOAT, 12, 0L);
|
||||
GLStateManager.glNormalPointer(GL11.GL_FLOAT, 12, 0L);
|
||||
|
||||
GLStateManager.glVertexPointer(1, GL11.GL_FLOAT, 4, 0L);
|
||||
GLStateManager.glVertexPointer(3, GL11.GL_UNSIGNED_BYTE, 3, 0L);
|
||||
GLStateManager.glNormalPointer(GL11.GL_UNSIGNED_BYTE, 3, 0L);
|
||||
assertVertexArray("vertex after illegal calls", 3, GL11.GL_FLOAT, 12, vbo);
|
||||
assertEquals(GL11.GL_FLOAT, GLStateManager.glGetInteger(GL11.GL_NORMAL_ARRAY_TYPE));
|
||||
|
||||
GLStateManager.glColorPointer(GL12.GL_BGRA, GL11.GL_UNSIGNED_BYTE, 4, 0L);
|
||||
assertEquals(GL12.GL_BGRA, GLStateManager.glGetInteger(GL11.GL_COLOR_ARRAY_SIZE));
|
||||
GLStateManager.glColorPointer(GL12.GL_BGRA, GL11.GL_FLOAT, 16, 0L);
|
||||
assertEquals(GL11.GL_UNSIGNED_BYTE, GLStateManager.glGetInteger(GL11.GL_COLOR_ARRAY_TYPE));
|
||||
|
||||
GLStateManager.glVertexAttribPointer(VAOManager.MAX_ATTRIBS, 3, GL11.GL_FLOAT, false, 0, 0L);
|
||||
GLStateManager.glEnableVertexAttribArray(VAOManager.MAX_ATTRIBS);
|
||||
GLStateManager.glDisableVertexAttribArray(VAOManager.MAX_ATTRIBS);
|
||||
GLStateManager.glVertexAttribPointer(5, 5, GL11.GL_FLOAT, false, 0, 0L);
|
||||
assertNull(VAOManager.get(5));
|
||||
} finally {
|
||||
GLStateManager.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void clientArrayEnablesAreAnsweredFromCache() {
|
||||
final int vaoB = GLStateManager.glGenVertexArrays();
|
||||
try {
|
||||
GLStateManager.glClientActiveTexture(GL13.GL_TEXTURE0);
|
||||
for (final int cap : CLIENT_ARRAY_CAPS) {
|
||||
assertFalse(GLStateManager.glIsEnabled(cap), "default isEnabled " + hex(cap));
|
||||
assertEnableRoundTrip(cap, true);
|
||||
}
|
||||
|
||||
GLStateManager.glEnableClientState(GL11.GL_TEXTURE_COORD_ARRAY);
|
||||
GLStateManager.glClientActiveTexture(GL13.GL_TEXTURE1);
|
||||
assertFalse(GLStateManager.glIsEnabled(GL11.GL_TEXTURE_COORD_ARRAY), "texcoord array enable is per client texture unit");
|
||||
GLStateManager.glClientActiveTexture(GL13.GL_TEXTURE0);
|
||||
assertTrue(GLStateManager.glIsEnabled(GL11.GL_TEXTURE_COORD_ARRAY));
|
||||
GLStateManager.glDisableClientState(GL11.GL_TEXTURE_COORD_ARRAY);
|
||||
|
||||
GLStateManager.glEnableClientState(GL11.GL_INDEX_ARRAY);
|
||||
GLStateManager.glBindVertexArray(vaoB);
|
||||
assertFalse(GLStateManager.glIsEnabled(GL11.GL_INDEX_ARRAY), "array enables are per vertex array object");
|
||||
GLStateManager.glBindVertexArray(vao);
|
||||
assertTrue(GLStateManager.glIsEnabled(GL11.GL_INDEX_ARRAY));
|
||||
GLStateManager.glDisableClientState(GL11.GL_INDEX_ARRAY);
|
||||
|
||||
GLStateManager.glBindVertexArray(vaoB);
|
||||
GLStateManager.glEnableVertexAttribArray(0);
|
||||
assertFalse(GLStateManager.glIsEnabled(GL11.GL_VERTEX_ARRAY), "an enabled generic attribute 0 is not GL_VERTEX_ARRAY");
|
||||
GLStateManager.glDisableVertexAttribArray(0);
|
||||
GLStateManager.glBindVertexArray(vao);
|
||||
} finally {
|
||||
GLStateManager.glBindVertexArray(vaoB);
|
||||
GLStateManager.glDisableVertexAttribArray(0);
|
||||
GLStateManager.glBindVertexArray(vao);
|
||||
GLStateManager.glClientActiveTexture(GL13.GL_TEXTURE0);
|
||||
for (final int cap : CLIENT_ARRAY_CAPS) {
|
||||
GLStateManager.glDisableClientState(cap);
|
||||
}
|
||||
GLStateManager.glDeleteVertexArrays(vaoB);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -76,7 +76,6 @@ public class GLSM_CoreRemovedCaps_GLTest {
|
||||
assertFalse(GLStateManager.glIsEnabled(cap));
|
||||
} finally {
|
||||
GLStateManager.glDisable(cap);
|
||||
while (GL11.glGetError() != GL11.GL_NO_ERROR) {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,7 +90,6 @@ public class GLSM_CoreRemovedCaps_GLTest {
|
||||
assertFalse(GLStateManager.glIsEnabled(cap));
|
||||
} finally {
|
||||
GLStateManager.glDisable(cap);
|
||||
while (GL11.glGetError() != GL11.GL_NO_ERROR) {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,7 +103,6 @@ public class GLSM_CoreRemovedCaps_GLTest {
|
||||
assertSecondaryColor(0.25F, 0.5F, 0.75F);
|
||||
} finally {
|
||||
GLStateManager.glSecondaryColor3f(0.0F, 0.0F, 0.0F);
|
||||
while (GL11.glGetError() != GL11.GL_NO_ERROR) {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -121,7 +118,6 @@ public class GLSM_CoreRemovedCaps_GLTest {
|
||||
assertSecondaryColor(0.125F, 0.25F, 0.375F);
|
||||
} finally {
|
||||
GLStateManager.glSecondaryColor3f(0.0F, 0.0F, 0.0F);
|
||||
while (GL11.glGetError() != GL11.GL_NO_ERROR) {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -135,7 +131,6 @@ public class GLSM_CoreRemovedCaps_GLTest {
|
||||
assertFalse(GLStateManager.glIsEnabled(GL14.GL_COLOR_SUM));
|
||||
} finally {
|
||||
GLStateManager.glDisable(GL14.GL_COLOR_SUM);
|
||||
while (GL11.glGetError() != GL11.GL_NO_ERROR) {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -156,7 +151,6 @@ public class GLSM_CoreRemovedCaps_GLTest {
|
||||
} finally {
|
||||
GLStateManager.glDeleteLists(list, 1);
|
||||
GLStateManager.glSecondaryColor3f(0.0F, 0.0F, 0.0F);
|
||||
while (GL11.glGetError() != GL11.GL_NO_ERROR) {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -176,7 +170,6 @@ public class GLSM_CoreRemovedCaps_GLTest {
|
||||
} finally {
|
||||
GLStateManager.glDeleteLists(list, 1);
|
||||
GLStateManager.glDisable(GL11.GL_LINE_STIPPLE);
|
||||
while (GL11.glGetError() != GL11.GL_NO_ERROR) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
package com.gtnewhorizons.angelica.glsm;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL12;
|
||||
import org.lwjgl.opengl.GL30;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assumptions.assumeTrue;
|
||||
|
||||
@GLCoreTest
|
||||
public class GLSM_DeferredTextureDelete_GLTest {
|
||||
|
||||
private static int immutableTexture() {
|
||||
assumeTrue(GLStateManager.capabilities.OpenGL42, "no glTexStorage2D on this context");
|
||||
final int tex = GLStateManager.glGenTextures();
|
||||
GLStateManager.glBindTexture(GL11.GL_TEXTURE_2D, tex);
|
||||
GLStateManager.glTexStorage2D(GL11.GL_TEXTURE_2D, 1, GL30.GL_R8, 4, 4);
|
||||
GLStateManager.glBindTexture(GL11.GL_TEXTURE_2D, 0);
|
||||
return tex;
|
||||
}
|
||||
|
||||
@Test
|
||||
void deletingAnImmutableTextureRaisesNoError() {
|
||||
final int tex = immutableTexture();
|
||||
|
||||
GLStateManager.glDeleteTextures(tex);
|
||||
|
||||
assertEquals(GL11.GL_NO_ERROR, GL11.glGetError());
|
||||
}
|
||||
|
||||
@Test
|
||||
void deletingARescuedImmutableTextureRaisesNoError() {
|
||||
final int tex = immutableTexture();
|
||||
GLStateManager.glDeleteTextures(tex);
|
||||
GLStateManager.glBindTexture(GL11.GL_TEXTURE_2D, tex);
|
||||
|
||||
GLStateManager.glDeleteTextures(tex);
|
||||
|
||||
assertEquals(GL11.GL_NO_ERROR, GL11.glGetError());
|
||||
}
|
||||
|
||||
@Test
|
||||
void deletingA2DTextureWhileA3DTextureIsBoundLeavesNothingBoundTo2D() {
|
||||
final int t2d = GLStateManager.glGenTextures();
|
||||
final int t3d = GLStateManager.glGenTextures();
|
||||
try {
|
||||
GLStateManager.glBindTexture(GL11.GL_TEXTURE_2D, t2d);
|
||||
GLStateManager.glBindTexture(GL12.GL_TEXTURE_3D, t3d);
|
||||
|
||||
GLStateManager.glDeleteTextures(t2d);
|
||||
|
||||
assertEquals(GL11.GL_NO_ERROR, GL11.glGetError());
|
||||
assertEquals(0, GL11.glGetInteger(GL11.GL_TEXTURE_BINDING_2D), "the deleted texture must not stay bound");
|
||||
assertEquals(t3d, GL11.glGetInteger(GL12.GL_TEXTURE_BINDING_3D));
|
||||
} finally {
|
||||
GLStateManager.glBindTexture(GL12.GL_TEXTURE_3D, 0);
|
||||
GLStateManager.glBindTexture(GL11.GL_TEXTURE_2D, 0);
|
||||
GLStateManager.glDeleteTextures(t3d);
|
||||
}
|
||||
}
|
||||
}
|
||||
+14
-45
@@ -6,18 +6,12 @@ import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.FloatBuffer;
|
||||
|
||||
import static com.gtnewhorizons.angelica.glsm.GlTestSupport.floats;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
@GLCoreTest
|
||||
public class GLSM_DirtyTracking_UnitTest {
|
||||
|
||||
static final FloatBuffer f4b = ByteBuffer.allocateDirect(4 << 2).order(ByteOrder.nativeOrder()).asFloatBuffer();
|
||||
static final FloatBuffer f3b = ByteBuffer.allocateDirect(3 << 2).order(ByteOrder.nativeOrder()).asFloatBuffer();
|
||||
|
||||
@BeforeEach
|
||||
void pushTrackedState() {
|
||||
GLStateManager.glPushAttrib(GL11.GL_LIGHTING_BIT | GL11.GL_FOG_BIT | GL11.GL_CURRENT_BIT);
|
||||
@@ -30,38 +24,31 @@ public class GLSM_DirtyTracking_UnitTest {
|
||||
|
||||
@Test
|
||||
void materialBumpsOnlyOnChange() {
|
||||
newf4b(0.1F, 0.2F, 0.3F, 0.4F);
|
||||
GLStateManager.glMaterial(GL11.GL_FRONT, GL11.GL_AMBIENT, f4b);
|
||||
GLStateManager.glMaterial(GL11.GL_FRONT, GL11.GL_AMBIENT, floats(0.1F, 0.2F, 0.3F, 0.4F));
|
||||
final int gen = GLStateManager.getLightingGeneration();
|
||||
|
||||
newf4b(0.1F, 0.2F, 0.3F, 0.4F);
|
||||
GLStateManager.glMaterial(GL11.GL_FRONT, GL11.GL_AMBIENT, f4b);
|
||||
GLStateManager.glMaterial(GL11.GL_FRONT, GL11.GL_AMBIENT, floats(0.1F, 0.2F, 0.3F, 0.4F));
|
||||
assertEquals(gen, GLStateManager.getLightingGeneration(), "identical material must not bump lightingGeneration");
|
||||
|
||||
newf4b(0.9F, 0.2F, 0.3F, 0.4F);
|
||||
GLStateManager.glMaterial(GL11.GL_FRONT, GL11.GL_AMBIENT, f4b);
|
||||
GLStateManager.glMaterial(GL11.GL_FRONT, GL11.GL_AMBIENT, floats(0.9F, 0.2F, 0.3F, 0.4F));
|
||||
assertEquals(gen + 1, GLStateManager.getLightingGeneration(), "changed material must bump lightingGeneration once");
|
||||
}
|
||||
|
||||
@Test
|
||||
void lightModelBumpsOnlyOnChange() {
|
||||
newf4b(0.5F, 0.5F, 0.5F, 1.0F);
|
||||
GLStateManager.glLightModel(GL11.GL_LIGHT_MODEL_AMBIENT, f4b);
|
||||
GLStateManager.glLightModel(GL11.GL_LIGHT_MODEL_AMBIENT, floats(0.5F, 0.5F, 0.5F, 1.0F));
|
||||
final int gen = GLStateManager.getLightingGeneration();
|
||||
|
||||
newf4b(0.5F, 0.5F, 0.5F, 1.0F);
|
||||
GLStateManager.glLightModel(GL11.GL_LIGHT_MODEL_AMBIENT, f4b);
|
||||
GLStateManager.glLightModel(GL11.GL_LIGHT_MODEL_AMBIENT, floats(0.5F, 0.5F, 0.5F, 1.0F));
|
||||
assertEquals(gen, GLStateManager.getLightingGeneration(), "identical light model ambient must not bump");
|
||||
}
|
||||
|
||||
@Test
|
||||
void lightColorBumpsOnlyOnChange() {
|
||||
newf4b(0.25F, 0.5F, 0.75F, 1.0F);
|
||||
GLStateManager.glLight(GL11.GL_LIGHT0, GL11.GL_DIFFUSE, f4b);
|
||||
GLStateManager.glLight(GL11.GL_LIGHT0, GL11.GL_DIFFUSE, floats(0.25F, 0.5F, 0.75F, 1.0F));
|
||||
final int gen = GLStateManager.getLightingGeneration();
|
||||
|
||||
newf4b(0.25F, 0.5F, 0.75F, 1.0F);
|
||||
GLStateManager.glLight(GL11.GL_LIGHT0, GL11.GL_DIFFUSE, f4b);
|
||||
GLStateManager.glLight(GL11.GL_LIGHT0, GL11.GL_DIFFUSE, floats(0.25F, 0.5F, 0.75F, 1.0F));
|
||||
assertEquals(gen, GLStateManager.getLightingGeneration(), "identical light diffuse must not bump");
|
||||
}
|
||||
|
||||
@@ -72,17 +59,14 @@ public class GLSM_DirtyTracking_UnitTest {
|
||||
GLStateManager.glLoadIdentity();
|
||||
GLStateManager.glTranslatef(1.0F, 2.0F, 3.0F);
|
||||
|
||||
newf4b(0.1F, 0.2F, 0.3F, 1.0F);
|
||||
GLStateManager.glLight(GL11.GL_LIGHT0, GL11.GL_POSITION, f4b);
|
||||
GLStateManager.glLight(GL11.GL_LIGHT0, GL11.GL_POSITION, floats(0.1F, 0.2F, 0.3F, 1.0F));
|
||||
final int gen = GLStateManager.getLightingGeneration();
|
||||
|
||||
newf4b(0.1F, 0.2F, 0.3F, 1.0F);
|
||||
GLStateManager.glLight(GL11.GL_LIGHT0, GL11.GL_POSITION, f4b);
|
||||
GLStateManager.glLight(GL11.GL_LIGHT0, GL11.GL_POSITION, floats(0.1F, 0.2F, 0.3F, 1.0F));
|
||||
assertEquals(gen, GLStateManager.getLightingGeneration(), "same position under same modelview must not bump");
|
||||
|
||||
GLStateManager.glTranslatef(5.0F, 0.0F, 0.0F);
|
||||
newf4b(0.1F, 0.2F, 0.3F, 1.0F);
|
||||
GLStateManager.glLight(GL11.GL_LIGHT0, GL11.GL_POSITION, f4b);
|
||||
GLStateManager.glLight(GL11.GL_LIGHT0, GL11.GL_POSITION, floats(0.1F, 0.2F, 0.3F, 1.0F));
|
||||
assertEquals(gen + 1, GLStateManager.getLightingGeneration(), "same raw position under changed modelview must bump");
|
||||
|
||||
GLStateManager.glPopMatrix();
|
||||
@@ -128,18 +112,15 @@ public class GLSM_DirtyTracking_UnitTest {
|
||||
GLStateManager.glPushMatrix();
|
||||
GLStateManager.glLoadIdentity();
|
||||
|
||||
newf3b(0.0F, 0.0F, -1.0F);
|
||||
GLStateManager.glLight(GL11.GL_LIGHT0, GL11.GL_SPOT_DIRECTION, f3b);
|
||||
GLStateManager.glLight(GL11.GL_LIGHT0, GL11.GL_SPOT_DIRECTION, floats(0.0F, 0.0F, -1.0F));
|
||||
final int gen = GLStateManager.getLightingGeneration();
|
||||
|
||||
GLStateManager.glTranslatef(5.0F, 0.0F, 0.0F);
|
||||
newf3b(0.0F, 0.0F, -1.0F);
|
||||
GLStateManager.glLight(GL11.GL_LIGHT0, GL11.GL_SPOT_DIRECTION, f3b);
|
||||
GLStateManager.glLight(GL11.GL_LIGHT0, GL11.GL_SPOT_DIRECTION, floats(0.0F, 0.0F, -1.0F));
|
||||
assertEquals(gen, GLStateManager.getLightingGeneration(), "spot direction under translation-only must not bump");
|
||||
|
||||
GLStateManager.glRotatef(90.0F, 0.0F, 1.0F, 0.0F);
|
||||
newf3b(0.0F, 0.0F, -1.0F);
|
||||
GLStateManager.glLight(GL11.GL_LIGHT0, GL11.GL_SPOT_DIRECTION, f3b);
|
||||
GLStateManager.glLight(GL11.GL_LIGHT0, GL11.GL_SPOT_DIRECTION, floats(0.0F, 0.0F, -1.0F));
|
||||
assertEquals(gen + 1, GLStateManager.getLightingGeneration(), "same raw spot direction under changed 3x3 must bump");
|
||||
|
||||
GLStateManager.glPopMatrix();
|
||||
@@ -158,16 +139,4 @@ public class GLSM_DirtyTracking_UnitTest {
|
||||
assertEquals(0.0F, diffuse.y, "green channel must be 0");
|
||||
assertEquals(1.0F, diffuse.z, "blue channel must be 1");
|
||||
}
|
||||
|
||||
static void newf4b(float x, float y, float z, float w) {
|
||||
f4b.clear();
|
||||
f4b.put(x).put(y).put(z).put(w);
|
||||
f4b.flip();
|
||||
}
|
||||
|
||||
static void newf3b(float x, float y, float z) {
|
||||
f3b.clear();
|
||||
f3b.put(x).put(y).put(z);
|
||||
f3b.flip();
|
||||
}
|
||||
}
|
||||
+14
-92
@@ -2,6 +2,8 @@ package com.gtnewhorizons.angelica.glsm;
|
||||
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.ValueSource;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import static com.gtnewhorizons.angelica.util.GLSMUtil.verifyState;
|
||||
@@ -28,106 +30,26 @@ class GLSM_DisplayList_FormatOptimization_Test {
|
||||
GLStateManager.glNormal3f(0.0f, 0.0f, 1.0f);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testPositionOnlyFormat() {
|
||||
// Create a display list with only position data (no color, texture, brightness, or normals)
|
||||
// Use GLStateManager for all calls to ensure they go through GLSM (test env doesn't redirect GL11)
|
||||
private static final float[][] CORNERS = {{0, 0}, {1, 0}, {1, 1}, {0, 1}};
|
||||
private static final float[][] COLORS = {{1, 1, 1, 1}, {1, 0, 0, 1}, {0, 1, 0, 1}, {0, 0, 1, 1}};
|
||||
|
||||
@ParameterizedTest(name = "normals={0}")
|
||||
@ValueSource(booleans = {false, true})
|
||||
void colorTextureFormatLeavesLastColorCurrent(boolean normals) {
|
||||
displayList = GL11.glGenLists(1);
|
||||
GLStateManager.glNewList(displayList, GL11.GL_COMPILE);
|
||||
|
||||
GLStateManager.glBegin(GL11.GL_QUADS);
|
||||
GLStateManager.glVertex3f(0, 0, 0);
|
||||
GLStateManager.glVertex3f(1, 0, 0);
|
||||
GLStateManager.glVertex3f(1, 1, 0);
|
||||
GLStateManager.glVertex3f(0, 1, 0);
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (normals) GLStateManager.glNormal3f(0, 0, 1);
|
||||
GLStateManager.glColor4f(COLORS[i][0], COLORS[i][1], COLORS[i][2], COLORS[i][3]);
|
||||
GLStateManager.glTexCoord2f(CORNERS[i][0], CORNERS[i][1]);
|
||||
GLStateManager.glVertex3f(CORNERS[i][0], CORNERS[i][1], 0);
|
||||
}
|
||||
GLStateManager.glEnd();
|
||||
|
||||
GLStateManager.glEndList();
|
||||
|
||||
// Call the list to ensure it doesn't crash (verifies compilation succeeded)
|
||||
GLStateManager.glCallList(displayList);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testPositionTextureFormat() {
|
||||
// Create a display list with position and texture coordinates
|
||||
displayList = GL11.glGenLists(1);
|
||||
GLStateManager.glNewList(displayList, GL11.GL_COMPILE);
|
||||
|
||||
GLStateManager.glBegin(GL11.GL_QUADS);
|
||||
GLStateManager.glTexCoord2f(0, 0);
|
||||
GLStateManager.glVertex3f(0, 0, 0);
|
||||
GLStateManager.glTexCoord2f(1, 0);
|
||||
GLStateManager.glVertex3f(1, 0, 0);
|
||||
GLStateManager.glTexCoord2f(1, 1);
|
||||
GLStateManager.glVertex3f(1, 1, 0);
|
||||
GLStateManager.glTexCoord2f(0, 1);
|
||||
GLStateManager.glVertex3f(0, 1, 0);
|
||||
GLStateManager.glEnd();
|
||||
|
||||
GLStateManager.glEndList();
|
||||
|
||||
// Call the list to ensure it doesn't crash (verifies compilation succeeded)
|
||||
GLStateManager.glCallList(displayList);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testPositionColorTextureFormat() {
|
||||
// Create a display list with position, color, and texture
|
||||
displayList = GL11.glGenLists(1);
|
||||
GLStateManager.glNewList(displayList, GL11.GL_COMPILE);
|
||||
|
||||
GLStateManager.glBegin(GL11.GL_QUADS);
|
||||
GLStateManager.glColor4f(1, 1, 1, 1);
|
||||
GLStateManager.glTexCoord2f(0, 0);
|
||||
GLStateManager.glVertex3f(0, 0, 0);
|
||||
GLStateManager.glColor4f(1, 0, 0, 1);
|
||||
GLStateManager.glTexCoord2f(1, 0);
|
||||
GLStateManager.glVertex3f(1, 0, 0);
|
||||
GLStateManager.glColor4f(0, 1, 0, 1);
|
||||
GLStateManager.glTexCoord2f(1, 1);
|
||||
GLStateManager.glVertex3f(1, 1, 0);
|
||||
GLStateManager.glColor4f(0, 0, 1, 1);
|
||||
GLStateManager.glTexCoord2f(0, 1);
|
||||
GLStateManager.glVertex3f(0, 1, 0);
|
||||
GLStateManager.glEnd();
|
||||
|
||||
GLStateManager.glEndList();
|
||||
|
||||
// Call the list and verify color is restored to last value (blue)
|
||||
GLStateManager.glCallList(displayList);
|
||||
verifyState(GL11.GL_CURRENT_COLOR, new float[]{0f, 0f, 1f, 1f},
|
||||
"After playback, color should be blue (last color in immediate mode block)");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFullFormat() {
|
||||
// Create a display list with all attributes: position, color, texture, and normal
|
||||
displayList = GL11.glGenLists(1);
|
||||
GLStateManager.glNewList(displayList, GL11.GL_COMPILE);
|
||||
|
||||
GLStateManager.glBegin(GL11.GL_QUADS);
|
||||
GLStateManager.glNormal3f(0, 0, 1);
|
||||
GLStateManager.glColor4f(1, 1, 1, 1);
|
||||
GLStateManager.glTexCoord2f(0, 0);
|
||||
GLStateManager.glVertex3f(0, 0, 0);
|
||||
GLStateManager.glNormal3f(0, 0, 1);
|
||||
GLStateManager.glColor4f(1, 0, 0, 1);
|
||||
GLStateManager.glTexCoord2f(1, 0);
|
||||
GLStateManager.glVertex3f(1, 0, 0);
|
||||
GLStateManager.glNormal3f(0, 0, 1);
|
||||
GLStateManager.glColor4f(0, 1, 0, 1);
|
||||
GLStateManager.glTexCoord2f(1, 1);
|
||||
GLStateManager.glVertex3f(1, 1, 0);
|
||||
GLStateManager.glNormal3f(0, 0, 1);
|
||||
GLStateManager.glColor4f(0, 0, 1, 1);
|
||||
GLStateManager.glTexCoord2f(0, 1);
|
||||
GLStateManager.glVertex3f(0, 1, 0);
|
||||
GLStateManager.glEnd();
|
||||
|
||||
GLStateManager.glEndList();
|
||||
|
||||
// Call the list and verify color is restored to last value (blue)
|
||||
GLStateManager.glCallList(displayList);
|
||||
verifyState(GL11.GL_CURRENT_COLOR, new float[]{0f, 0f, 1f, 1f},
|
||||
"After playback, color should be blue (last color in immediate mode block)");
|
||||
|
||||
+27
-50
@@ -2,6 +2,8 @@ package com.gtnewhorizons.angelica.glsm;
|
||||
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.EnumSource;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
@@ -15,6 +17,23 @@ public class GLSM_DisplayList_PixelStore_Test {
|
||||
private static final int SRC = 8;
|
||||
private static final int SUB = 4;
|
||||
|
||||
enum Upload {
|
||||
TEX_SUB_IMAGE_2D {
|
||||
@Override
|
||||
void run(ByteBuffer src) {
|
||||
GLStateManager.glTexSubImage2D(GL11.GL_TEXTURE_2D, 0, 0, 0, SUB, SUB, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, src);
|
||||
}
|
||||
},
|
||||
TEX_IMAGE_2D {
|
||||
@Override
|
||||
void run(ByteBuffer src) {
|
||||
GLStateManager.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA8, SUB, SUB, 0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, src);
|
||||
}
|
||||
};
|
||||
|
||||
abstract void run(ByteBuffer src);
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void resetUnpackState() {
|
||||
GLStateManager.glPixelStorei(GL11.GL_UNPACK_ALIGNMENT, 4);
|
||||
@@ -96,8 +115,9 @@ public class GLSM_DisplayList_PixelStore_Test {
|
||||
GLStateManager.glDeleteLists(list, 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
void stridedTexSubImage2DCompile() {
|
||||
@ParameterizedTest
|
||||
@EnumSource(Upload.class)
|
||||
void stridedUploadCompile(Upload upload) {
|
||||
final int tex = makeTexture(SUB, ByteBuffer.allocateDirect(SUB * SUB * 4).order(ByteOrder.nativeOrder()));
|
||||
final ByteBuffer src = makeSource(SRC);
|
||||
|
||||
@@ -105,7 +125,7 @@ public class GLSM_DisplayList_PixelStore_Test {
|
||||
|
||||
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);
|
||||
upload.run(src);
|
||||
GLStateManager.glEndList();
|
||||
|
||||
assertEquals(0, red(readback(SUB), SUB, 0, 0), "GL_COMPILE must not execute the upload");
|
||||
@@ -146,58 +166,15 @@ public class GLSM_DisplayList_PixelStore_Test {
|
||||
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() {
|
||||
@ParameterizedTest
|
||||
@EnumSource(Upload.class)
|
||||
void defaultRecordedUploadReplaysWithDefaults(Upload upload) {
|
||||
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);
|
||||
upload.run(src);
|
||||
GLStateManager.glEndList();
|
||||
|
||||
GLStateManager.glPixelStorei(GL11.GL_UNPACK_ALIGNMENT, 1);
|
||||
|
||||
+2
-30
@@ -1,14 +1,14 @@
|
||||
package com.gtnewhorizons.angelica.glsm;
|
||||
|
||||
import com.gtnewhorizon.gtnhlib.client.renderer.TessellatorManager;
|
||||
import com.gtnewhorizons.angelica.glsm.recording.CompiledDisplayList;
|
||||
import com.gtnewhorizons.angelica.glsm.recording.GLCommand;
|
||||
import it.unimi.dsi.fastutil.ints.IntList;
|
||||
import net.minecraft.client.renderer.Tessellator;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import static com.gtnewhorizons.angelica.glsm.DisplayListTestHelper.immediateQuad;
|
||||
import static com.gtnewhorizons.angelica.glsm.DisplayListTestHelper.rawQuad;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
@@ -27,34 +27,6 @@ class GLSM_DisplayList_RawTessellatorTransform_Test {
|
||||
GLStateManager.glLoadIdentity();
|
||||
}
|
||||
|
||||
private static void rawQuad(float size) {
|
||||
final Tessellator tess = Tessellator.instance;
|
||||
final float[][] corners = { { 0.0f, 0.0f }, { size, 0.0f }, { size, size }, { 0.0f, size } };
|
||||
tess.rawBuffer = new int[4 * 8];
|
||||
for (int i = 0; i < 4; i++) {
|
||||
final int base = i * 8;
|
||||
tess.rawBuffer[base] = Float.floatToRawIntBits(corners[i][0]);
|
||||
tess.rawBuffer[base + 1] = Float.floatToRawIntBits(corners[i][1]);
|
||||
tess.rawBuffer[base + 3] = Float.floatToRawIntBits(i == 1 || i == 2 ? 1.0f : 0.0f);
|
||||
tess.rawBuffer[base + 4] = Float.floatToRawIntBits(i >= 2 ? 1.0f : 0.0f);
|
||||
}
|
||||
tess.isDrawing = true;
|
||||
tess.drawMode = GL11.GL_QUADS;
|
||||
tess.hasTexture = true;
|
||||
tess.rawBufferIndex = 4 * 8;
|
||||
tess.vertexCount = 4;
|
||||
TessellatorManager.interceptDraw(tess);
|
||||
}
|
||||
|
||||
private static void immediateQuad(float size) {
|
||||
GLStateManager.glBegin(GL11.GL_QUADS);
|
||||
GLStateManager.glVertex3f(0.0f, 0.0f, 0.0f);
|
||||
GLStateManager.glVertex3f(size, 0.0f, 0.0f);
|
||||
GLStateManager.glVertex3f(size, size, 0.0f);
|
||||
GLStateManager.glVertex3f(0.0f, size, 0.0f);
|
||||
GLStateManager.glEnd();
|
||||
}
|
||||
|
||||
@Test
|
||||
void pendingTransformIsEmittedBeforeARawDraw() {
|
||||
testList = GLStateManager.glGenLists(1);
|
||||
|
||||
+46
-357
@@ -1,19 +1,25 @@
|
||||
package com.gtnewhorizons.angelica.glsm;
|
||||
|
||||
import com.gtnewhorizon.gtnhlib.client.renderer.TessellatorManager;
|
||||
import com.gtnewhorizons.angelica.glsm.recording.CompiledDisplayList;
|
||||
import com.gtnewhorizons.angelica.glsm.recording.GLCommand;
|
||||
import net.minecraft.client.renderer.Tessellator;
|
||||
import it.unimi.dsi.fastutil.ints.Int2IntMap;
|
||||
import it.unimi.dsi.fastutil.ints.IntList;
|
||||
import org.joml.Matrix4f;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
import org.lwjgl.BufferUtils;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import java.nio.FloatBuffer;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static com.gtnewhorizons.angelica.glsm.DisplayListTestHelper.assertMatrixEquals;
|
||||
import static com.gtnewhorizons.angelica.glsm.DisplayListTestHelper.immediateQuad;
|
||||
import static com.gtnewhorizons.angelica.glsm.DisplayListTestHelper.modelviewAfterCall;
|
||||
import static com.gtnewhorizons.angelica.glsm.DisplayListTestHelper.rawQuad;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
@@ -70,12 +76,7 @@ class GLSM_DisplayList_TransformCollapsing_Test {
|
||||
"No individual transform commands should remain in optimized list");
|
||||
|
||||
// Verify behavioral correctness: matrix state should match expected
|
||||
GLStateManager.glPushMatrix();
|
||||
GLStateManager.glLoadIdentity();
|
||||
GLStateManager.glCallList(testList);
|
||||
|
||||
FloatBuffer actualBuf = BufferUtils.createFloatBuffer(16);
|
||||
GLStateManager.glGetFloat(GL11.GL_MODELVIEW_MATRIX, actualBuf);
|
||||
final FloatBuffer actualBuf = modelviewAfterCall(testList);
|
||||
|
||||
Matrix4f expected = new Matrix4f()
|
||||
.translate(1.0f, 2.0f, 3.0f)
|
||||
@@ -84,15 +85,7 @@ class GLSM_DisplayList_TransformCollapsing_Test {
|
||||
.translate(-0.5f, -0.5f, -0.5f)
|
||||
.rotate((float) Math.toRadians(30.0f), 1.0f, 0.0f, 0.0f);
|
||||
|
||||
FloatBuffer expectedBuf = BufferUtils.createFloatBuffer(16);
|
||||
expected.get(expectedBuf);
|
||||
|
||||
for (int i = 0; i < 16; i++) {
|
||||
assertEquals(expectedBuf.get(i), actualBuf.get(i), 0.0001f,
|
||||
String.format("Matrix[%d] mismatch after collapsed transforms", i));
|
||||
}
|
||||
|
||||
GLStateManager.glPopMatrix();
|
||||
assertMatrixEquals(expected, actualBuf, "mismatch after collapsed transforms");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -121,12 +114,7 @@ class GLSM_DisplayList_TransformCollapsing_Test {
|
||||
assertEquals(1, popCount, "Should have exactly 1 PopMatrix");
|
||||
|
||||
// Verify behavioral correctness
|
||||
GLStateManager.glPushMatrix();
|
||||
GLStateManager.glLoadIdentity();
|
||||
GLStateManager.glCallList(testList);
|
||||
|
||||
FloatBuffer actualBuf = BufferUtils.createFloatBuffer(16);
|
||||
GLStateManager.glGetFloat(GL11.GL_MODELVIEW_MATRIX, actualBuf);
|
||||
final FloatBuffer actualBuf = modelviewAfterCall(testList);
|
||||
|
||||
// Expected: translate(10,0,0) then translate(0,3,0) = translate(10,3,0)
|
||||
// The inner push/pop isolates the (5,0,0) translate and rotation
|
||||
@@ -134,15 +122,7 @@ class GLSM_DisplayList_TransformCollapsing_Test {
|
||||
.translate(10.0f, 0.0f, 0.0f)
|
||||
.translate(0.0f, 3.0f, 0.0f);
|
||||
|
||||
FloatBuffer expectedBuf = BufferUtils.createFloatBuffer(16);
|
||||
expected.get(expectedBuf);
|
||||
|
||||
for (int i = 0; i < 16; i++) {
|
||||
assertEquals(expectedBuf.get(i), actualBuf.get(i), 0.0001f,
|
||||
String.format("Matrix[%d] mismatch - push/pop should isolate inner transforms", i));
|
||||
}
|
||||
|
||||
GLStateManager.glPopMatrix();
|
||||
assertMatrixEquals(expected, actualBuf, "mismatch - push/pop should isolate inner transforms");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -164,12 +144,7 @@ class GLSM_DisplayList_TransformCollapsing_Test {
|
||||
GLStateManager.glEndList();
|
||||
|
||||
// Verify behavioral correctness
|
||||
GLStateManager.glPushMatrix();
|
||||
GLStateManager.glLoadIdentity();
|
||||
GLStateManager.glCallList(testList);
|
||||
|
||||
FloatBuffer actualBuf = BufferUtils.createFloatBuffer(16);
|
||||
GLStateManager.glGetFloat(GL11.GL_MODELVIEW_MATRIX, actualBuf);
|
||||
final FloatBuffer actualBuf = modelviewAfterCall(testList);
|
||||
|
||||
// Final state: translate(1,0,0) + translate(5,0,0) = translate(6,0,0)
|
||||
// Level 1 and 2 transforms are isolated by push/pop
|
||||
@@ -182,8 +157,6 @@ class GLSM_DisplayList_TransformCollapsing_Test {
|
||||
|
||||
assertEquals(expectedBuf.get(12), actualBuf.get(12), 0.0001f,
|
||||
"X translation should be 6.0 (1+5, inner transforms isolated)");
|
||||
|
||||
GLStateManager.glPopMatrix(); // Balance the push from line 185
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -219,12 +192,7 @@ class GLSM_DisplayList_TransformCollapsing_Test {
|
||||
"MultMatrix should be emitted BEFORE CallList (transform flush at barrier)");
|
||||
|
||||
// Verify behavioral correctness
|
||||
GLStateManager.glPushMatrix();
|
||||
GLStateManager.glLoadIdentity();
|
||||
GLStateManager.glCallList(testList);
|
||||
|
||||
FloatBuffer actualBuf = BufferUtils.createFloatBuffer(16);
|
||||
GLStateManager.glGetFloat(GL11.GL_MODELVIEW_MATRIX, actualBuf);
|
||||
final FloatBuffer actualBuf = modelviewAfterCall(testList);
|
||||
|
||||
// Build expected: translate(10,0,0) * rotate(90,Y) * translate(100,0,0) * translate(1,0,0)
|
||||
// After 90-degree Y rotation, X axis points into -Z, so nested translate goes along -Z
|
||||
@@ -234,15 +202,7 @@ class GLSM_DisplayList_TransformCollapsing_Test {
|
||||
.translate(100.0f, 0.0f, 0.0f)
|
||||
.translate(1.0f, 0.0f, 0.0f);
|
||||
|
||||
FloatBuffer expectedBuf = BufferUtils.createFloatBuffer(16);
|
||||
expected.get(expectedBuf);
|
||||
|
||||
for (int i = 0; i < 16; i++) {
|
||||
assertEquals(expectedBuf.get(i), actualBuf.get(i), 0.0001f,
|
||||
String.format("Matrix[%d] mismatch - nested list should see parent's transformed state", i));
|
||||
}
|
||||
|
||||
GLStateManager.glPopMatrix();
|
||||
assertMatrixEquals(expected, actualBuf, "mismatch - nested list should see parent's transformed state");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -271,63 +231,33 @@ class GLSM_DisplayList_TransformCollapsing_Test {
|
||||
"Identity-equivalent transforms should not emit MultMatrix");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testTransformBetweenDrawsCreatesSeparateBatches() {
|
||||
// This test verifies that draws with different transforms are not batched together
|
||||
// Note: Without actual Tessellator integration, we can only verify command structure
|
||||
|
||||
testList = GL11.glGenLists(1);
|
||||
GLStateManager.glNewList(testList, GL11.GL_COMPILE);
|
||||
|
||||
// Simulate: Transform A, Draw, Transform B, Draw
|
||||
// The draws should NOT be in the same batch
|
||||
GLStateManager.glTranslatef(1.0f, 0.0f, 0.0f);
|
||||
// (Would have a draw here in real usage)
|
||||
GLStateManager.glTranslatef(2.0f, 0.0f, 0.0f);
|
||||
// (Would have another draw here)
|
||||
|
||||
GLStateManager.glEndList();
|
||||
|
||||
// Verify the transforms are accumulated correctly
|
||||
GLStateManager.glPushMatrix();
|
||||
GLStateManager.glLoadIdentity();
|
||||
GLStateManager.glCallList(testList);
|
||||
|
||||
FloatBuffer actualBuf = BufferUtils.createFloatBuffer(16);
|
||||
GLStateManager.glGetFloat(GL11.GL_MODELVIEW_MATRIX, actualBuf);
|
||||
|
||||
// Total translation should be 3.0 (1+2)
|
||||
assertEquals(3.0f, actualBuf.get(12), 0.0001f,
|
||||
"Consecutive translates should accumulate");
|
||||
|
||||
GLStateManager.glPopMatrix();
|
||||
static Stream<Arguments> discardedByLoadIdentity() {
|
||||
return Stream.of(
|
||||
Arguments.of("accumulated translate", (Runnable) () -> GLStateManager.glTranslatef(100.0f, 100.0f, 100.0f)),
|
||||
Arguments.of("loaded matrix", (Runnable) () -> {
|
||||
final FloatBuffer loadBuf = BufferUtils.createFloatBuffer(16);
|
||||
new Matrix4f().translate(50.0f, 60.0f, 70.0f).rotate((float) Math.toRadians(45.0f), 1.0f, 1.0f, 0.0f).get(loadBuf);
|
||||
GLStateManager.glLoadMatrix(loadBuf);
|
||||
}));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testLoadIdentityResetsAccumulation() {
|
||||
// LoadIdentity should reset accumulated transforms
|
||||
@ParameterizedTest(name = "{0}")
|
||||
@MethodSource("discardedByLoadIdentity")
|
||||
void testLoadIdentityDiscardsEarlierTransforms(String name, Runnable earlier) {
|
||||
testList = GL11.glGenLists(1);
|
||||
GLStateManager.glNewList(testList, GL11.GL_COMPILE);
|
||||
|
||||
GLStateManager.glTranslatef(100.0f, 100.0f, 100.0f); // Big translate
|
||||
GLStateManager.glLoadIdentity(); // Reset
|
||||
GLStateManager.glTranslatef(1.0f, 2.0f, 3.0f); // New translate
|
||||
earlier.run();
|
||||
GLStateManager.glLoadIdentity();
|
||||
GLStateManager.glTranslatef(1.0f, 2.0f, 3.0f);
|
||||
|
||||
GLStateManager.glEndList();
|
||||
|
||||
// Verify: final state should only have the second translate
|
||||
GLStateManager.glPushMatrix();
|
||||
GLStateManager.glLoadIdentity();
|
||||
GLStateManager.glCallList(testList);
|
||||
|
||||
FloatBuffer actualBuf = BufferUtils.createFloatBuffer(16);
|
||||
GLStateManager.glGetFloat(GL11.GL_MODELVIEW_MATRIX, actualBuf);
|
||||
final FloatBuffer actualBuf = modelviewAfterCall(testList);
|
||||
|
||||
assertEquals(1.0f, actualBuf.get(12), 0.0001f, "X should be 1.0 (LoadIdentity reset)");
|
||||
assertEquals(2.0f, actualBuf.get(13), 0.0001f, "Y should be 2.0 (LoadIdentity reset)");
|
||||
assertEquals(3.0f, actualBuf.get(14), 0.0001f, "Z should be 3.0 (LoadIdentity reset)");
|
||||
|
||||
GLStateManager.glPopMatrix();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -359,121 +289,14 @@ class GLSM_DisplayList_TransformCollapsing_Test {
|
||||
"Translate + MultMatrix + Translate should collapse to 1 MultMatrix");
|
||||
|
||||
// Verify behavioral correctness
|
||||
GLStateManager.glPushMatrix();
|
||||
GLStateManager.glLoadIdentity();
|
||||
GLStateManager.glCallList(testList);
|
||||
|
||||
FloatBuffer actualBuf = BufferUtils.createFloatBuffer(16);
|
||||
GLStateManager.glGetFloat(GL11.GL_MODELVIEW_MATRIX, actualBuf);
|
||||
final FloatBuffer actualBuf = modelviewAfterCall(testList);
|
||||
|
||||
Matrix4f expected = new Matrix4f()
|
||||
.translate(1.0f, 0.0f, 0.0f)
|
||||
.rotate((float) Math.toRadians(90.0f), 0.0f, 1.0f, 0.0f)
|
||||
.translate(2.0f, 0.0f, 0.0f);
|
||||
|
||||
FloatBuffer expectedBuf = BufferUtils.createFloatBuffer(16);
|
||||
expected.get(expectedBuf);
|
||||
|
||||
for (int i = 0; i < 16; i++) {
|
||||
assertEquals(expectedBuf.get(i), actualBuf.get(i), 0.0001f,
|
||||
String.format("Matrix[%d] mismatch for MultMatrix accumulation", i));
|
||||
}
|
||||
|
||||
GLStateManager.glPopMatrix();
|
||||
}
|
||||
|
||||
// ==================== Batcher Flush Ordering Tests ====================
|
||||
|
||||
@Test
|
||||
void testDrawsBeforePushMatrixAreEmittedBeforePush() {
|
||||
// This test verifies that draws occurring before a PushMatrix are flushed
|
||||
// before the PushMatrix command, not delayed until later.
|
||||
// This was a bug where the batcher wasn't flushed at PushMatrix.
|
||||
|
||||
// Create a list with: Transform, (implicit draw would go here), PushMatrix, Transform, PopMatrix
|
||||
testList = GL11.glGenLists(1);
|
||||
GLStateManager.glNewList(testList, GL11.GL_COMPILE);
|
||||
|
||||
// Outer transform
|
||||
GLStateManager.glTranslatef(1.0f, 0.0f, 0.0f);
|
||||
// Note: If there was a draw here, it should be emitted BEFORE PushMatrix
|
||||
|
||||
GLStateManager.glPushMatrix();
|
||||
GLStateManager.glTranslatef(5.0f, 0.0f, 0.0f); // Inner transform
|
||||
GLStateManager.glPopMatrix();
|
||||
|
||||
// Final transform after pop
|
||||
GLStateManager.glTranslatef(2.0f, 0.0f, 0.0f);
|
||||
|
||||
GLStateManager.glEndList();
|
||||
|
||||
// Verify the command structure
|
||||
CompiledDisplayList compiled = DisplayListManager.getDisplayList(testList);
|
||||
assertNotNull(compiled, "Display list should be compiled");
|
||||
|
||||
IntList opcodes = compiled.getCommandOpcodes();
|
||||
|
||||
// Find indices of key commands
|
||||
int pushIndex = opcodes.indexOf(GLCommand.PUSH_MATRIX);
|
||||
int popIndex = opcodes.indexOf(GLCommand.POP_MATRIX);
|
||||
|
||||
// Count MultMatrix commands before first PushMatrix
|
||||
int multMatrixBeforePushCount = 0;
|
||||
for (int i = 0; i < opcodes.size() && i < pushIndex; i++) {
|
||||
if (opcodes.get(i) == GLCommand.TRANSLATE) {
|
||||
multMatrixBeforePushCount++;
|
||||
}
|
||||
}
|
||||
|
||||
assertTrue(pushIndex >= 0, "Should have PushMatrix command");
|
||||
assertTrue(popIndex >= 0, "Should have PopMatrix command");
|
||||
assertTrue(pushIndex < popIndex, "PushMatrix should come before PopMatrix");
|
||||
|
||||
// The outer translate(1,0,0) should be emitted as MultMatrix before PushMatrix
|
||||
assertTrue(multMatrixBeforePushCount >= 1,
|
||||
"Transform before PushMatrix should be emitted before the Push");
|
||||
|
||||
// Verify behavioral correctness: final state should be translate(1,0,0) + translate(2,0,0) = translate(3,0,0)
|
||||
// The inner translate(5,0,0) is isolated by push/pop
|
||||
GLStateManager.glPushMatrix();
|
||||
GLStateManager.glLoadIdentity();
|
||||
GLStateManager.glCallList(testList);
|
||||
|
||||
FloatBuffer actualBuf = BufferUtils.createFloatBuffer(16);
|
||||
GLStateManager.glGetFloat(GL11.GL_MODELVIEW_MATRIX, actualBuf);
|
||||
|
||||
assertEquals(3.0f, actualBuf.get(12), 0.0001f,
|
||||
"X translation should be 3.0 (1+2, inner transform isolated by push/pop)");
|
||||
|
||||
GLStateManager.glPopMatrix();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testDrawsBeforePopMatrixAreEmittedBeforePop() {
|
||||
// Verify draws inside a push/pop block are emitted before the pop
|
||||
testList = GL11.glGenLists(1);
|
||||
GLStateManager.glNewList(testList, GL11.GL_COMPILE);
|
||||
|
||||
GLStateManager.glPushMatrix();
|
||||
GLStateManager.glTranslatef(10.0f, 0.0f, 0.0f);
|
||||
// Draws here should be emitted before PopMatrix
|
||||
GLStateManager.glPopMatrix();
|
||||
|
||||
GLStateManager.glEndList();
|
||||
|
||||
CompiledDisplayList compiled = DisplayListManager.getDisplayList(testList);
|
||||
IntList opcodes = compiled.getCommandOpcodes();
|
||||
|
||||
int pushIndex = opcodes.indexOf(GLCommand.PUSH_MATRIX);
|
||||
int popIndex = opcodes.indexOf(GLCommand.POP_MATRIX);
|
||||
|
||||
assertTrue(pushIndex >= 0, "Should have PushMatrix");
|
||||
assertTrue(popIndex >= 0, "Should have PopMatrix");
|
||||
assertTrue(pushIndex < popIndex, "Push should come before Pop");
|
||||
|
||||
// The inner translate should be emitted between push and pop (or collapsed to residual)
|
||||
// At minimum, the structure should be valid
|
||||
assertTrue(popIndex > pushIndex, "PopMatrix should follow PushMatrix");
|
||||
assertMatrixEquals(expected, actualBuf, "mismatch for MultMatrix accumulation");
|
||||
}
|
||||
|
||||
// ==================== LoadMatrix Tests ====================
|
||||
@@ -509,22 +332,9 @@ class GLSM_DisplayList_TransformCollapsing_Test {
|
||||
"Should have exactly 1 LoadMatrix command (can't be absorbed)");
|
||||
|
||||
// Verify behavioral correctness: matrix should equal the loaded matrix
|
||||
GLStateManager.glPushMatrix();
|
||||
GLStateManager.glLoadIdentity();
|
||||
GLStateManager.glCallList(testList);
|
||||
final FloatBuffer actualBuf = modelviewAfterCall(testList);
|
||||
|
||||
FloatBuffer actualBuf = BufferUtils.createFloatBuffer(16);
|
||||
GLStateManager.glGetFloat(GL11.GL_MODELVIEW_MATRIX, actualBuf);
|
||||
|
||||
FloatBuffer expectedBuf = BufferUtils.createFloatBuffer(16);
|
||||
loadedMatrix.get(expectedBuf);
|
||||
|
||||
for (int i = 0; i < 16; i++) {
|
||||
assertEquals(expectedBuf.get(i), actualBuf.get(i), 0.0001f,
|
||||
String.format("Matrix[%d] should match loaded matrix (not multiplied)", i));
|
||||
}
|
||||
|
||||
GLStateManager.glPopMatrix();
|
||||
assertMatrixEquals(loadedMatrix, actualBuf, "should match loaded matrix (not multiplied)");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -547,62 +357,11 @@ class GLSM_DisplayList_TransformCollapsing_Test {
|
||||
GLStateManager.glEndList();
|
||||
|
||||
// Verify behavioral correctness
|
||||
GLStateManager.glPushMatrix();
|
||||
GLStateManager.glLoadIdentity();
|
||||
GLStateManager.glCallList(testList);
|
||||
|
||||
FloatBuffer actualBuf = BufferUtils.createFloatBuffer(16);
|
||||
GLStateManager.glGetFloat(GL11.GL_MODELVIEW_MATRIX, actualBuf);
|
||||
final FloatBuffer actualBuf = modelviewAfterCall(testList);
|
||||
|
||||
// Expected: loadedMatrix * translate(10,0,0)
|
||||
Matrix4f expected = new Matrix4f(loadedMatrix).translate(10.0f, 0.0f, 0.0f);
|
||||
FloatBuffer expectedBuf = BufferUtils.createFloatBuffer(16);
|
||||
expected.get(expectedBuf);
|
||||
|
||||
for (int i = 0; i < 16; i++) {
|
||||
assertEquals(expectedBuf.get(i), actualBuf.get(i), 0.0001f,
|
||||
String.format("Matrix[%d] - transform after LoadMatrix should be relative to loaded matrix", i));
|
||||
}
|
||||
|
||||
GLStateManager.glPopMatrix();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testLoadMatrixThenLoadIdentity() {
|
||||
// LoadMatrix followed by LoadIdentity should result in identity
|
||||
testList = GL11.glGenLists(1);
|
||||
GLStateManager.glNewList(testList, GL11.GL_COMPILE);
|
||||
|
||||
// Load a complex matrix
|
||||
Matrix4f loadedMatrix = new Matrix4f()
|
||||
.translate(50.0f, 60.0f, 70.0f)
|
||||
.rotate((float) Math.toRadians(45.0f), 1.0f, 1.0f, 0.0f);
|
||||
FloatBuffer loadBuf = BufferUtils.createFloatBuffer(16);
|
||||
loadedMatrix.get(loadBuf);
|
||||
loadBuf.rewind();
|
||||
GLStateManager.glLoadMatrix(loadBuf);
|
||||
|
||||
// Then reset to identity
|
||||
GLStateManager.glLoadIdentity();
|
||||
|
||||
// Then apply a simple translate
|
||||
GLStateManager.glTranslatef(1.0f, 2.0f, 3.0f);
|
||||
|
||||
GLStateManager.glEndList();
|
||||
|
||||
// Verify: final state should just be translate(1,2,3)
|
||||
GLStateManager.glPushMatrix();
|
||||
GLStateManager.glLoadIdentity();
|
||||
GLStateManager.glCallList(testList);
|
||||
|
||||
FloatBuffer actualBuf = BufferUtils.createFloatBuffer(16);
|
||||
GLStateManager.glGetFloat(GL11.GL_MODELVIEW_MATRIX, actualBuf);
|
||||
|
||||
assertEquals(1.0f, actualBuf.get(12), 0.0001f, "X should be 1.0");
|
||||
assertEquals(2.0f, actualBuf.get(13), 0.0001f, "Y should be 2.0");
|
||||
assertEquals(3.0f, actualBuf.get(14), 0.0001f, "Z should be 3.0");
|
||||
|
||||
GLStateManager.glPopMatrix();
|
||||
assertMatrixEquals(expected, actualBuf, "transform after LoadMatrix should be relative to loaded matrix");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -628,17 +387,10 @@ class GLSM_DisplayList_TransformCollapsing_Test {
|
||||
GLStateManager.glEndList();
|
||||
|
||||
// Verify: final state should be matrix2
|
||||
GLStateManager.glPushMatrix();
|
||||
GLStateManager.glLoadIdentity();
|
||||
GLStateManager.glCallList(testList);
|
||||
|
||||
FloatBuffer actualBuf = BufferUtils.createFloatBuffer(16);
|
||||
GLStateManager.glGetFloat(GL11.GL_MODELVIEW_MATRIX, actualBuf);
|
||||
final FloatBuffer actualBuf = modelviewAfterCall(testList);
|
||||
|
||||
assertEquals(0.0f, actualBuf.get(12), 0.0001f, "X should be 0.0 (from second LoadMatrix)");
|
||||
assertEquals(20.0f, actualBuf.get(13), 0.0001f, "Y should be 20.0 (from second LoadMatrix)");
|
||||
|
||||
GLStateManager.glPopMatrix();
|
||||
}
|
||||
|
||||
// ==================== Immediate Mode with Transforms Tests ====================
|
||||
@@ -652,12 +404,7 @@ class GLSM_DisplayList_TransformCollapsing_Test {
|
||||
GLStateManager.glPushMatrix();
|
||||
GLStateManager.glScalef(0.25f, 0.25f, 0.25f);
|
||||
|
||||
GLStateManager.glBegin(GL11.GL_QUADS);
|
||||
GLStateManager.glVertex3f(0.0f, 0.0f, 0.0f);
|
||||
GLStateManager.glVertex3f(2.0f, 0.0f, 0.0f);
|
||||
GLStateManager.glVertex3f(2.0f, 2.0f, 0.0f);
|
||||
GLStateManager.glVertex3f(0.0f, 2.0f, 0.0f);
|
||||
GLStateManager.glEnd();
|
||||
immediateQuad(2.0f);
|
||||
|
||||
GLStateManager.glPopMatrix();
|
||||
GLStateManager.glEndList();
|
||||
@@ -683,12 +430,7 @@ class GLSM_DisplayList_TransformCollapsing_Test {
|
||||
GLStateManager.glTranslatef(100.0f, 50.0f, 0.0f);
|
||||
GLStateManager.glScalef(0.5f, 0.5f, 1.0f);
|
||||
|
||||
GLStateManager.glBegin(GL11.GL_QUADS);
|
||||
GLStateManager.glVertex3f(0.0f, 0.0f, 0.0f);
|
||||
GLStateManager.glVertex3f(16.0f, 0.0f, 0.0f);
|
||||
GLStateManager.glVertex3f(16.0f, 16.0f, 0.0f);
|
||||
GLStateManager.glVertex3f(0.0f, 16.0f, 0.0f);
|
||||
GLStateManager.glEnd();
|
||||
immediateQuad(16.0f);
|
||||
|
||||
GLStateManager.glEndList();
|
||||
|
||||
@@ -700,20 +442,13 @@ class GLSM_DisplayList_TransformCollapsing_Test {
|
||||
assertEquals(0, counts.getOrDefault(GLCommand.SCALE, 0), "No individual Scale");
|
||||
|
||||
// Verify matrix values after playback
|
||||
GLStateManager.glPushMatrix();
|
||||
GLStateManager.glLoadIdentity();
|
||||
GLStateManager.glCallList(testList);
|
||||
|
||||
FloatBuffer matrixBuf = BufferUtils.createFloatBuffer(16);
|
||||
GLStateManager.glGetFloat(GL11.GL_MODELVIEW_MATRIX, matrixBuf);
|
||||
final FloatBuffer matrixBuf = modelviewAfterCall(testList);
|
||||
|
||||
assertEquals(0.5f, matrixBuf.get(0), 0.0001f, "Scale X");
|
||||
assertEquals(0.5f, matrixBuf.get(5), 0.0001f, "Scale Y");
|
||||
assertEquals(1.0f, matrixBuf.get(10), 0.0001f, "Scale Z");
|
||||
assertEquals(100.0f, matrixBuf.get(12), 0.0001f, "Translate X");
|
||||
assertEquals(50.0f, matrixBuf.get(13), 0.0001f, "Translate Y");
|
||||
|
||||
GLStateManager.glPopMatrix();
|
||||
}
|
||||
|
||||
// ==================== Cross-Mode Transform Collapsing Tests ====================
|
||||
@@ -806,12 +541,7 @@ class GLSM_DisplayList_TransformCollapsing_Test {
|
||||
GLStateManager.glBindTexture(GL11.GL_TEXTURE_2D, 0);
|
||||
GLStateManager.glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
|
||||
GLStateManager.glBegin(GL11.GL_QUADS);
|
||||
GLStateManager.glVertex3f(0.0f, 0.0f, 0.0f);
|
||||
GLStateManager.glVertex3f(1.0f, 0.0f, 0.0f);
|
||||
GLStateManager.glVertex3f(1.0f, 1.0f, 0.0f);
|
||||
GLStateManager.glVertex3f(0.0f, 1.0f, 0.0f);
|
||||
GLStateManager.glEnd();
|
||||
immediateQuad(1.0f);
|
||||
|
||||
GLStateManager.glEndList();
|
||||
|
||||
@@ -826,16 +556,9 @@ class GLSM_DisplayList_TransformCollapsing_Test {
|
||||
assertTrue(opcodes.indexOf(GLCommand.MULT_MATRIX) > opcodes.indexOf(GLCommand.DRAW_RANGE),
|
||||
"MultMatrix after DrawRange for mode " + mode);
|
||||
|
||||
GLStateManager.glPushMatrix();
|
||||
GLStateManager.glLoadIdentity();
|
||||
GLStateManager.glCallList(testList);
|
||||
|
||||
FloatBuffer matrixBuf = BufferUtils.createFloatBuffer(16);
|
||||
GLStateManager.glGetFloat(GL11.GL_MODELVIEW_MATRIX, matrixBuf);
|
||||
final FloatBuffer matrixBuf = modelviewAfterCall(testList);
|
||||
assertEquals(0.5f, matrixBuf.get(0), 0.0001f, "Scale X for mode " + mode);
|
||||
assertEquals(0.5f, matrixBuf.get(5), 0.0001f, "Scale Y for mode " + mode);
|
||||
|
||||
GLStateManager.glPopMatrix();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -846,38 +569,16 @@ class GLSM_DisplayList_TransformCollapsing_Test {
|
||||
|
||||
GLStateManager.glScalef(0.5f, 0.5f, 0.5f);
|
||||
|
||||
final Tessellator tess = Tessellator.instance;
|
||||
final float[][] corners = { { 0.0f, 0.0f }, { 1.0f, 0.0f }, { 1.0f, 1.0f }, { 0.0f, 1.0f } };
|
||||
tess.rawBuffer = new int[4 * 8];
|
||||
for (int i = 0; i < 4; i++) {
|
||||
final int base = i * 8;
|
||||
tess.rawBuffer[base] = Float.floatToRawIntBits(corners[i][0]);
|
||||
tess.rawBuffer[base + 1] = Float.floatToRawIntBits(corners[i][1]);
|
||||
tess.rawBuffer[base + 3] = Float.floatToRawIntBits(i == 1 || i == 2 ? 1.0f : 0.0f);
|
||||
tess.rawBuffer[base + 4] = Float.floatToRawIntBits(i >= 2 ? 1.0f : 0.0f);
|
||||
}
|
||||
tess.isDrawing = true;
|
||||
tess.drawMode = GL11.GL_QUADS;
|
||||
tess.hasTexture = true;
|
||||
tess.rawBufferIndex = 4 * 8;
|
||||
tess.vertexCount = 4;
|
||||
TessellatorManager.interceptDraw(tess);
|
||||
rawQuad(1.0f);
|
||||
|
||||
GLStateManager.glEndList();
|
||||
|
||||
CompiledDisplayList compiled = DisplayListManager.getDisplayList(testList);
|
||||
assertNotNull(compiled);
|
||||
|
||||
GLStateManager.glPushMatrix();
|
||||
GLStateManager.glLoadIdentity();
|
||||
GLStateManager.glCallList(testList);
|
||||
|
||||
FloatBuffer matrixBuf = BufferUtils.createFloatBuffer(16);
|
||||
GLStateManager.glGetFloat(GL11.GL_MODELVIEW_MATRIX, matrixBuf);
|
||||
final FloatBuffer matrixBuf = modelviewAfterCall(testList);
|
||||
assertEquals(0.5f, matrixBuf.get(0), 0.0001f, "Scale X after playback");
|
||||
assertEquals(0.5f, matrixBuf.get(5), 0.0001f, "Scale Y after playback");
|
||||
|
||||
GLStateManager.glPopMatrix();
|
||||
}
|
||||
|
||||
// ==================== Optimizer Push/Pop Reset Tests ====================
|
||||
@@ -898,12 +599,7 @@ class GLSM_DisplayList_TransformCollapsing_Test {
|
||||
GLStateManager.glTranslatef(10.0f, 0.0f, 0.0f);
|
||||
GLStateManager.glRotatef(45.0f, 0.0f, 1.0f, 0.0f);
|
||||
|
||||
GLStateManager.glBegin(GL11.GL_QUADS);
|
||||
GLStateManager.glVertex3f(0.0f, 0.0f, 0.0f);
|
||||
GLStateManager.glVertex3f(1.0f, 0.0f, 0.0f);
|
||||
GLStateManager.glVertex3f(1.0f, 1.0f, 0.0f);
|
||||
GLStateManager.glVertex3f(0.0f, 1.0f, 0.0f);
|
||||
GLStateManager.glEnd();
|
||||
immediateQuad(1.0f);
|
||||
|
||||
GLStateManager.glPopMatrix();
|
||||
GLStateManager.glEndList();
|
||||
@@ -930,18 +626,11 @@ class GLSM_DisplayList_TransformCollapsing_Test {
|
||||
assertTrue(drawIndex < popIndex, "DRAW before POP");
|
||||
|
||||
// Verify final matrix after pop = T1
|
||||
GLStateManager.glPushMatrix();
|
||||
GLStateManager.glLoadIdentity();
|
||||
GLStateManager.glCallList(testList);
|
||||
|
||||
FloatBuffer matrixBuf = BufferUtils.createFloatBuffer(16);
|
||||
GLStateManager.glGetFloat(GL11.GL_MODELVIEW_MATRIX, matrixBuf);
|
||||
final FloatBuffer matrixBuf = modelviewAfterCall(testList);
|
||||
|
||||
assertEquals(2.0f, matrixBuf.get(0), 0.0001f, "Scale X after pop");
|
||||
assertEquals(2.0f, matrixBuf.get(5), 0.0001f, "Scale Y after pop");
|
||||
assertEquals(5.0f, matrixBuf.get(12), 0.0001f, "Translate X after pop");
|
||||
|
||||
GLStateManager.glPopMatrix();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
+65
-265
@@ -1,7 +1,16 @@
|
||||
package com.gtnewhorizons.angelica.glsm;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
import org.lwjgl.BufferUtils;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL14;
|
||||
|
||||
import java.nio.FloatBuffer;
|
||||
import java.util.function.DoubleSupplier;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static com.gtnewhorizons.angelica.util.GLSMUtil.verifyState;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
@@ -9,128 +18,77 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
@GLCompatTest
|
||||
class GLSM_DisplayList_UnitTest {
|
||||
|
||||
@Test
|
||||
void testDisplayListCompileCall() {
|
||||
verifyState(GL11.GL_LIGHTING, false, "GL_LIGHTING Initial State");
|
||||
|
||||
int list = GL11.glGenLists(1);
|
||||
GLStateManager.glNewList(list, GL11.GL_COMPILE);
|
||||
GLStateManager.glEnable(GL11.GL_LIGHTING);
|
||||
GLStateManager.glEndList();
|
||||
|
||||
verifyState(GL11.GL_LIGHTING, false, "GL_LIGHTING Post Display List Compile");
|
||||
|
||||
GLStateManager.glCallList(list);
|
||||
|
||||
verifyState(GL11.GL_LIGHTING, true, "GL_LIGHTING Post Display List Call");
|
||||
|
||||
// Reset state that we changed during test
|
||||
GLStateManager.glDisable(GL11.GL_LIGHTING);
|
||||
/** One recordable state command: {@code apply} moves the driver value read by {@code driver} to {@code applied}. */
|
||||
private static Arguments state(String name, Runnable apply, Runnable reset, DoubleSupplier driver, double applied) {
|
||||
return Arguments.of(name, apply, reset, driver, applied);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testDisplayListCompileExecute() {
|
||||
verifyState(GL11.GL_LIGHTING, false, "GL_LIGHTING Initial State");
|
||||
|
||||
int list = GL11.glGenLists(1);
|
||||
GLStateManager.glNewList(list, GL11.GL_COMPILE_AND_EXECUTE);
|
||||
GLStateManager.glEnable(GL11.GL_LIGHTING);
|
||||
GLStateManager.glEndList();
|
||||
|
||||
verifyState(GL11.GL_LIGHTING, true, "GL_LIGHTING Post Display List Compile and Execute");
|
||||
|
||||
// Reset state that we changed during test
|
||||
GLStateManager.glDisable(GL11.GL_LIGHTING);
|
||||
private static double lighting() {
|
||||
final boolean enabled = GLStateManager.glIsEnabled(GL11.GL_LIGHTING);
|
||||
verifyState(GL11.GL_LIGHTING, enabled, "driver must agree with the GLSM cache");
|
||||
return enabled ? 1.0 : 0.0;
|
||||
}
|
||||
|
||||
// ==================== CullFace Tests ====================
|
||||
|
||||
@Test
|
||||
void testCullFaceInDisplayList() {
|
||||
// Get initial cull face mode
|
||||
int initialMode = GL11.glGetInteger(GL11.GL_CULL_FACE_MODE);
|
||||
|
||||
int list = GL11.glGenLists(1);
|
||||
GLStateManager.glNewList(list, GL11.GL_COMPILE);
|
||||
GLStateManager.glCullFace(GL11.GL_FRONT);
|
||||
GLStateManager.glEndList();
|
||||
|
||||
// After compile, mode should be unchanged
|
||||
assertEquals(initialMode, GL11.glGetInteger(GL11.GL_CULL_FACE_MODE), "CullFace mode should be unchanged after GL_COMPILE");
|
||||
|
||||
// Call the display list
|
||||
GLStateManager.glCallList(list);
|
||||
|
||||
// Now mode should be GL_FRONT
|
||||
assertEquals(GL11.GL_FRONT, GL11.glGetInteger(GL11.GL_CULL_FACE_MODE), "CullFace mode should be GL_FRONT after calling display list");
|
||||
|
||||
// Cleanup
|
||||
GLStateManager.glCullFace(GL11.GL_BACK); // Reset to default
|
||||
GLStateManager.glDeleteLists(list, 1);
|
||||
private static double blendColorRed() {
|
||||
final FloatBuffer color = BufferUtils.createFloatBuffer(16);
|
||||
GL11.glGetFloat(GL14.GL_BLEND_COLOR, color);
|
||||
return color.get(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCullFaceCompileAndExecute() {
|
||||
// Get initial cull face mode
|
||||
int initialMode = GL11.glGetInteger(GL11.GL_CULL_FACE_MODE);
|
||||
|
||||
int list = GL11.glGenLists(1);
|
||||
GLStateManager.glNewList(list, GL11.GL_COMPILE_AND_EXECUTE);
|
||||
GLStateManager.glCullFace(GL11.GL_FRONT_AND_BACK);
|
||||
GLStateManager.glEndList();
|
||||
|
||||
// After compile and execute, mode should be changed
|
||||
assertEquals(GL11.GL_FRONT_AND_BACK, GL11.glGetInteger(GL11.GL_CULL_FACE_MODE), "CullFace mode should be GL_FRONT_AND_BACK after GL_COMPILE_AND_EXECUTE");
|
||||
|
||||
// Cleanup
|
||||
GLStateManager.glCullFace(GL11.GL_BACK);
|
||||
GLStateManager.glDeleteLists(list, 1);
|
||||
static Stream<Arguments> states() {
|
||||
return Stream.of(
|
||||
state("glEnable(GL_LIGHTING)", () -> GLStateManager.glEnable(GL11.GL_LIGHTING), () -> GLStateManager.glDisable(GL11.GL_LIGHTING),
|
||||
GLSM_DisplayList_UnitTest::lighting, 1.0),
|
||||
state("glCullFace", () -> GLStateManager.glCullFace(GL11.GL_FRONT), () -> GLStateManager.glCullFace(GL11.GL_BACK),
|
||||
() -> GL11.glGetInteger(GL11.GL_CULL_FACE_MODE), GL11.GL_FRONT),
|
||||
state("glLogicOp", () -> GLStateManager.glLogicOp(GL11.GL_XOR), () -> GLStateManager.glLogicOp(GL11.GL_COPY),
|
||||
() -> GL11.glGetInteger(GL11.GL_LOGIC_OP_MODE), GL11.GL_XOR),
|
||||
state("glClearDepth", () -> GLStateManager.glClearDepth(0.5), () -> GLStateManager.glClearDepth(1.0),
|
||||
() -> GL11.glGetDouble(GL11.GL_DEPTH_CLEAR_VALUE), 0.5),
|
||||
state("glBlendColor", () -> GLStateManager.glBlendColor(0.5f, 0.4f, 0.6f, 0.8f), () -> GLStateManager.glBlendColor(0f, 0f, 0f, 0f),
|
||||
GLSM_DisplayList_UnitTest::blendColorRed, 0.5),
|
||||
state("glFrontFace", () -> GLStateManager.glFrontFace(GL11.GL_CW), () -> GLStateManager.glFrontFace(GL11.GL_CCW),
|
||||
() -> GL11.glGetInteger(GL11.GL_FRONT_FACE), GL11.GL_CW),
|
||||
state("glHint", () -> GLStateManager.glHint(GL11.GL_LINE_SMOOTH_HINT, GL11.GL_NICEST), () -> GLStateManager.glHint(GL11.GL_LINE_SMOOTH_HINT, GL11.GL_DONT_CARE),
|
||||
() -> GL11.glGetInteger(GL11.GL_LINE_SMOOTH_HINT), GL11.GL_NICEST));
|
||||
}
|
||||
|
||||
// ==================== LogicOp Tests ====================
|
||||
@ParameterizedTest(name = "{0}")
|
||||
@MethodSource("states")
|
||||
void compiledStateChangeAppliesOnlyWhenTheListIsCalled(String name, Runnable apply, Runnable reset, DoubleSupplier driver, double applied) {
|
||||
final double initial = driver.getAsDouble();
|
||||
final int list = GL11.glGenLists(1);
|
||||
try {
|
||||
GLStateManager.glNewList(list, GL11.GL_COMPILE);
|
||||
apply.run();
|
||||
GLStateManager.glEndList();
|
||||
assertEquals(initial, driver.getAsDouble(), 0.0001, name + " must not execute under GL_COMPILE");
|
||||
|
||||
@Test
|
||||
void testLogicOpInDisplayList() {
|
||||
// Get initial logic op
|
||||
int initialOp = GL11.glGetInteger(GL11.GL_LOGIC_OP_MODE);
|
||||
|
||||
int list = GL11.glGenLists(1);
|
||||
GLStateManager.glNewList(list, GL11.GL_COMPILE);
|
||||
GLStateManager.glLogicOp(GL11.GL_XOR);
|
||||
GLStateManager.glEndList();
|
||||
|
||||
// After compile, op should be unchanged
|
||||
assertEquals(initialOp, GL11.glGetInteger(GL11.GL_LOGIC_OP_MODE), "LogicOp should be unchanged after GL_COMPILE");
|
||||
|
||||
// Call the display list
|
||||
GLStateManager.glCallList(list);
|
||||
|
||||
// Now op should be GL_XOR
|
||||
assertEquals(GL11.GL_XOR, GL11.glGetInteger(GL11.GL_LOGIC_OP_MODE), "LogicOp should be GL_XOR after calling display list");
|
||||
|
||||
// Cleanup
|
||||
GLStateManager.glLogicOp(GL11.GL_COPY); // Reset to default
|
||||
GLStateManager.glDeleteLists(list, 1);
|
||||
GLStateManager.glCallList(list);
|
||||
assertEquals(applied, driver.getAsDouble(), 0.0001, name + " must apply when the list is called");
|
||||
} finally {
|
||||
reset.run();
|
||||
GLStateManager.glDeleteLists(list, 1);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testLogicOpCompileAndExecute() {
|
||||
int list = GL11.glGenLists(1);
|
||||
GLStateManager.glNewList(list, GL11.GL_COMPILE_AND_EXECUTE);
|
||||
GLStateManager.glLogicOp(GL11.GL_INVERT);
|
||||
GLStateManager.glEndList();
|
||||
|
||||
// After compile and execute, op should be changed
|
||||
assertEquals(GL11.GL_INVERT, GL11.glGetInteger(GL11.GL_LOGIC_OP_MODE), "LogicOp should be GL_INVERT after GL_COMPILE_AND_EXECUTE");
|
||||
|
||||
// Cleanup
|
||||
GLStateManager.glLogicOp(GL11.GL_COPY);
|
||||
GLStateManager.glDeleteLists(list, 1);
|
||||
@ParameterizedTest(name = "{0}")
|
||||
@MethodSource("states")
|
||||
void compileAndExecuteAppliesStateChangeImmediately(String name, Runnable apply, Runnable reset, DoubleSupplier driver, double applied) {
|
||||
final int list = GL11.glGenLists(1);
|
||||
try {
|
||||
GLStateManager.glNewList(list, GL11.GL_COMPILE_AND_EXECUTE);
|
||||
apply.run();
|
||||
GLStateManager.glEndList();
|
||||
assertEquals(applied, driver.getAsDouble(), 0.0001, name + " must apply under GL_COMPILE_AND_EXECUTE");
|
||||
} finally {
|
||||
reset.run();
|
||||
GLStateManager.glDeleteLists(list, 1);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testMultipleStateChangesInDisplayList() {
|
||||
// Test that multiple state commands work together
|
||||
int list = GL11.glGenLists(1);
|
||||
GLStateManager.glNewList(list, GL11.GL_COMPILE);
|
||||
GLStateManager.glCullFace(GL11.GL_FRONT);
|
||||
@@ -138,173 +96,15 @@ class GLSM_DisplayList_UnitTest {
|
||||
GLStateManager.glEnable(GL11.GL_LIGHTING);
|
||||
GLStateManager.glEndList();
|
||||
|
||||
// Call the list
|
||||
GLStateManager.glCallList(list);
|
||||
|
||||
// Verify all states changed
|
||||
assertEquals(GL11.GL_FRONT, GL11.glGetInteger(GL11.GL_CULL_FACE_MODE), "CullFace should be GL_FRONT");
|
||||
assertEquals(GL11.GL_AND, GL11.glGetInteger(GL11.GL_LOGIC_OP_MODE), "LogicOp should be GL_AND");
|
||||
verifyState(GL11.GL_LIGHTING, true, "GL_LIGHTING should be enabled");
|
||||
|
||||
// Cleanup
|
||||
GLStateManager.glCullFace(GL11.GL_BACK);
|
||||
GLStateManager.glLogicOp(GL11.GL_COPY);
|
||||
GLStateManager.glDisable(GL11.GL_LIGHTING);
|
||||
GLStateManager.glDeleteLists(list, 1);
|
||||
}
|
||||
|
||||
// ==================== ClearDepth Tests ====================
|
||||
|
||||
@Test
|
||||
void testClearDepthInDisplayList() {
|
||||
// Get initial clear depth
|
||||
double initialDepth = GL11.glGetDouble(GL11.GL_DEPTH_CLEAR_VALUE);
|
||||
|
||||
int list = GL11.glGenLists(1);
|
||||
GLStateManager.glNewList(list, GL11.GL_COMPILE);
|
||||
GLStateManager.glClearDepth(0.5);
|
||||
GLStateManager.glEndList();
|
||||
|
||||
// After compile, depth should be unchanged
|
||||
assertEquals(initialDepth, GL11.glGetDouble(GL11.GL_DEPTH_CLEAR_VALUE), 0.0001, "ClearDepth should be unchanged after GL_COMPILE");
|
||||
|
||||
// Call the display list
|
||||
GLStateManager.glCallList(list);
|
||||
|
||||
// Now depth should be 0.5
|
||||
assertEquals(0.5, GL11.glGetDouble(GL11.GL_DEPTH_CLEAR_VALUE), 0.0001, "ClearDepth should be 0.5 after calling display list");
|
||||
|
||||
// Cleanup
|
||||
GLStateManager.glClearDepth(1.0); // Reset to default
|
||||
GLStateManager.glDeleteLists(list, 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testClearDepthCompileAndExecute() {
|
||||
int list = GL11.glGenLists(1);
|
||||
GLStateManager.glNewList(list, GL11.GL_COMPILE_AND_EXECUTE);
|
||||
GLStateManager.glClearDepth(0.25);
|
||||
GLStateManager.glEndList();
|
||||
|
||||
// After compile and execute, depth should be changed
|
||||
assertEquals(0.25, GL11.glGetDouble(GL11.GL_DEPTH_CLEAR_VALUE), 0.0001, "ClearDepth should be 0.25 after GL_COMPILE_AND_EXECUTE");
|
||||
|
||||
// Cleanup
|
||||
GLStateManager.glClearDepth(1.0);
|
||||
GLStateManager.glDeleteLists(list, 1);
|
||||
}
|
||||
|
||||
// ==================== BlendColor Tests ====================
|
||||
|
||||
@Test
|
||||
void testBlendColorInDisplayList() {
|
||||
int list = GL11.glGenLists(1);
|
||||
GLStateManager.glNewList(list, GL11.GL_COMPILE);
|
||||
GLStateManager.glBlendColor(0.2f, 0.4f, 0.6f, 0.8f);
|
||||
GLStateManager.glEndList();
|
||||
|
||||
// Call the display list - should not throw
|
||||
GLStateManager.glCallList(list);
|
||||
|
||||
// Cleanup
|
||||
GLStateManager.glBlendColor(0f, 0f, 0f, 0f);
|
||||
GLStateManager.glDeleteLists(list, 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testBlendColorCompileAndExecute() {
|
||||
int list = GL11.glGenLists(1);
|
||||
GLStateManager.glNewList(list, GL11.GL_COMPILE_AND_EXECUTE);
|
||||
GLStateManager.glBlendColor(0.5f, 0.5f, 0.5f, 1.0f);
|
||||
GLStateManager.glEndList();
|
||||
|
||||
// Should not throw - display list was executed
|
||||
GLStateManager.glCallList(list);
|
||||
|
||||
// Cleanup
|
||||
GLStateManager.glBlendColor(0f, 0f, 0f, 0f);
|
||||
GLStateManager.glDeleteLists(list, 1);
|
||||
}
|
||||
|
||||
// ==================== FrontFace Tests ====================
|
||||
|
||||
@Test
|
||||
void testFrontFaceInDisplayList() {
|
||||
// Get initial front face
|
||||
int initialMode = GL11.glGetInteger(GL11.GL_FRONT_FACE);
|
||||
|
||||
int list = GL11.glGenLists(1);
|
||||
GLStateManager.glNewList(list, GL11.GL_COMPILE);
|
||||
GLStateManager.glFrontFace(GL11.GL_CW);
|
||||
GLStateManager.glEndList();
|
||||
|
||||
// After compile, mode should be unchanged
|
||||
assertEquals(initialMode, GL11.glGetInteger(GL11.GL_FRONT_FACE), "FrontFace should be unchanged after GL_COMPILE");
|
||||
|
||||
// Call the display list
|
||||
GLStateManager.glCallList(list);
|
||||
|
||||
// Now mode should be GL_CW
|
||||
assertEquals(GL11.GL_CW, GL11.glGetInteger(GL11.GL_FRONT_FACE), "FrontFace should be GL_CW after calling display list");
|
||||
|
||||
// Cleanup
|
||||
GLStateManager.glFrontFace(GL11.GL_CCW); // Reset to default
|
||||
GLStateManager.glDeleteLists(list, 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFrontFaceCompileAndExecute() {
|
||||
int list = GL11.glGenLists(1);
|
||||
GLStateManager.glNewList(list, GL11.GL_COMPILE_AND_EXECUTE);
|
||||
GLStateManager.glFrontFace(GL11.GL_CW);
|
||||
GLStateManager.glEndList();
|
||||
|
||||
// After compile and execute, mode should be changed
|
||||
assertEquals(GL11.GL_CW, GL11.glGetInteger(GL11.GL_FRONT_FACE), "FrontFace should be GL_CW after GL_COMPILE_AND_EXECUTE");
|
||||
|
||||
// Cleanup
|
||||
GLStateManager.glFrontFace(GL11.GL_CCW);
|
||||
GLStateManager.glDeleteLists(list, 1);
|
||||
}
|
||||
|
||||
// ==================== Hint Tests ====================
|
||||
|
||||
@Test
|
||||
void testHintInDisplayList() {
|
||||
// Get initial hint value
|
||||
int initialHint = GL11.glGetInteger(GL11.GL_LINE_SMOOTH_HINT);
|
||||
|
||||
int list = GL11.glGenLists(1);
|
||||
GLStateManager.glNewList(list, GL11.GL_COMPILE);
|
||||
GLStateManager.glHint(GL11.GL_LINE_SMOOTH_HINT, GL11.GL_NICEST);
|
||||
GLStateManager.glEndList();
|
||||
|
||||
// After compile, hint should be unchanged
|
||||
assertEquals(initialHint, GL11.glGetInteger(GL11.GL_LINE_SMOOTH_HINT), "Hint should be unchanged after GL_COMPILE");
|
||||
|
||||
// Call the display list
|
||||
GLStateManager.glCallList(list);
|
||||
|
||||
// Now hint should be GL_NICEST
|
||||
assertEquals(GL11.GL_NICEST, GL11.glGetInteger(GL11.GL_LINE_SMOOTH_HINT), "Hint should be GL_NICEST after calling display list");
|
||||
|
||||
// Cleanup
|
||||
GLStateManager.glHint(GL11.GL_LINE_SMOOTH_HINT, GL11.GL_DONT_CARE); // Reset to default
|
||||
GLStateManager.glDeleteLists(list, 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testHintCompileAndExecute() {
|
||||
int list = GL11.glGenLists(1);
|
||||
GLStateManager.glNewList(list, GL11.GL_COMPILE_AND_EXECUTE);
|
||||
GLStateManager.glHint(GL11.GL_LINE_SMOOTH_HINT, GL11.GL_FASTEST);
|
||||
GLStateManager.glEndList();
|
||||
|
||||
// After compile and execute, hint should be changed
|
||||
assertEquals(GL11.GL_FASTEST, GL11.glGetInteger(GL11.GL_LINE_SMOOTH_HINT), "Hint should be GL_FASTEST after GL_COMPILE_AND_EXECUTE");
|
||||
|
||||
// Cleanup
|
||||
GLStateManager.glHint(GL11.GL_LINE_SMOOTH_HINT, GL11.GL_DONT_CARE);
|
||||
GLStateManager.glDeleteLists(list, 1);
|
||||
}
|
||||
}
|
||||
@@ -3,12 +3,16 @@ package com.gtnewhorizons.angelica.glsm;
|
||||
import org.joml.Matrix4f;
|
||||
import org.joml.Vector4f;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
import org.lwjgl.BufferUtils;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.FloatBuffer;
|
||||
import java.nio.IntBuffer;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
@@ -20,37 +24,18 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
@GLCompatTest
|
||||
public class GLSM_GLU_UnitTest {
|
||||
|
||||
private static final FloatBuffer buffer = BufferUtils.createFloatBuffer(16);
|
||||
|
||||
private Matrix4f getModelviewMatrix() {
|
||||
buffer.clear();
|
||||
GLStateManager.glGetFloat(GL11.GL_MODELVIEW_MATRIX, buffer);
|
||||
return new Matrix4f(buffer);
|
||||
return new Matrix4f(GlTestSupport.modelview());
|
||||
}
|
||||
|
||||
private Matrix4f getProjectionMatrix() {
|
||||
buffer.clear();
|
||||
GLStateManager.glGetFloat(GL11.GL_PROJECTION_MATRIX, buffer);
|
||||
return new Matrix4f(buffer);
|
||||
return new Matrix4f(GlTestSupport.matrix(GL11.GL_PROJECTION_MATRIX));
|
||||
}
|
||||
|
||||
private void assertMatrixEquals(Matrix4f expected, Matrix4f actual, String message) {
|
||||
assertTrue(expected.equals(actual, 0.001f), () -> message + "\nExpected:\n" + expected + "\nActual:\n" + actual);
|
||||
}
|
||||
|
||||
@Test
|
||||
void gluPerspective_matchesJOML() {
|
||||
GLStateManager.glMatrixMode(GL11.GL_PROJECTION);
|
||||
GLStateManager.glLoadIdentity();
|
||||
|
||||
GLStateManager.gluPerspective(60.0f, 1.5f, 0.1f, 1000.0f);
|
||||
|
||||
Matrix4f expected = new Matrix4f().perspective((float) Math.toRadians(60.0f), 1.5f, 0.1f, 1000.0f);
|
||||
assertMatrixEquals(expected, getProjectionMatrix(), "gluPerspective standard");
|
||||
|
||||
GLStateManager.glMatrixMode(GL11.GL_MODELVIEW);
|
||||
}
|
||||
|
||||
@Test
|
||||
void gluPerspective_accumulates() {
|
||||
GLStateManager.glMatrixMode(GL11.GL_PROJECTION);
|
||||
@@ -67,40 +52,6 @@ public class GLSM_GLU_UnitTest {
|
||||
GLStateManager.glMatrixMode(GL11.GL_MODELVIEW);
|
||||
}
|
||||
|
||||
@Test
|
||||
void gluLookAt_matchesJOML() {
|
||||
GLStateManager.glMatrixMode(GL11.GL_MODELVIEW);
|
||||
GLStateManager.glLoadIdentity();
|
||||
|
||||
GLStateManager.gluLookAt(
|
||||
0.0f, 0.0f, 5.0f, // eye
|
||||
0.0f, 0.0f, 0.0f, // center
|
||||
0.0f, 1.0f, 0.0f); // up
|
||||
|
||||
Matrix4f expected = new Matrix4f().lookAt(
|
||||
0.0f, 0.0f, 5.0f,
|
||||
0.0f, 0.0f, 0.0f,
|
||||
0.0f, 1.0f, 0.0f);
|
||||
assertMatrixEquals(expected, getModelviewMatrix(), "gluLookAt simple");
|
||||
}
|
||||
|
||||
@Test
|
||||
void gluLookAt_offAxis() {
|
||||
GLStateManager.glMatrixMode(GL11.GL_MODELVIEW);
|
||||
GLStateManager.glLoadIdentity();
|
||||
|
||||
GLStateManager.gluLookAt(
|
||||
3.0f, 4.0f, 5.0f,
|
||||
1.0f, 2.0f, 0.0f,
|
||||
0.0f, 1.0f, 0.0f);
|
||||
|
||||
Matrix4f expected = new Matrix4f().lookAt(
|
||||
3.0f, 4.0f, 5.0f,
|
||||
1.0f, 2.0f, 0.0f,
|
||||
0.0f, 1.0f, 0.0f);
|
||||
assertMatrixEquals(expected, getModelviewMatrix(), "gluLookAt off-axis");
|
||||
}
|
||||
|
||||
@Test
|
||||
void gluLookAt_accumulates() {
|
||||
GLStateManager.glMatrixMode(GL11.GL_MODELVIEW);
|
||||
@@ -208,25 +159,23 @@ public class GLSM_GLU_UnitTest {
|
||||
GLStateManager.glMatrixMode(GL11.GL_MODELVIEW);
|
||||
}
|
||||
|
||||
@Test
|
||||
void gluErrorString_glErrors() {
|
||||
assertEquals("No error", GLStateManager.gluErrorString(GL11.GL_NO_ERROR));
|
||||
assertEquals("Invalid enum", GLStateManager.gluErrorString(GL11.GL_INVALID_ENUM));
|
||||
assertEquals("Invalid value", GLStateManager.gluErrorString(GL11.GL_INVALID_VALUE));
|
||||
assertEquals("Invalid operation", GLStateManager.gluErrorString(GL11.GL_INVALID_OPERATION));
|
||||
assertEquals("Out of memory", GLStateManager.gluErrorString(GL11.GL_OUT_OF_MEMORY));
|
||||
static Stream<Arguments> errorStrings() {
|
||||
return Stream.of(
|
||||
Arguments.of(GL11.GL_NO_ERROR, "No error"),
|
||||
Arguments.of(GL11.GL_INVALID_ENUM, "Invalid enum"),
|
||||
Arguments.of(GL11.GL_INVALID_VALUE, "Invalid value"),
|
||||
Arguments.of(GL11.GL_INVALID_OPERATION, "Invalid operation"),
|
||||
Arguments.of(GL11.GL_OUT_OF_MEMORY, "Out of memory"),
|
||||
Arguments.of(100900, "Invalid enum (glu)"),
|
||||
Arguments.of(100901, "Invalid value (glu)"),
|
||||
Arguments.of(100902, "Out of memory (glu)"),
|
||||
Arguments.of(99999, "Unknown error: 99999"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void gluErrorString_gluErrors() {
|
||||
assertEquals("Invalid enum (glu)", GLStateManager.gluErrorString(100900));
|
||||
assertEquals("Invalid value (glu)", GLStateManager.gluErrorString(100901));
|
||||
assertEquals("Out of memory (glu)", GLStateManager.gluErrorString(100902));
|
||||
}
|
||||
|
||||
@Test
|
||||
void gluErrorString_unknownCode() {
|
||||
assertEquals("Unknown error: 99999", GLStateManager.gluErrorString(99999));
|
||||
@ParameterizedTest(name = "{1}")
|
||||
@MethodSource("errorStrings")
|
||||
void gluErrorString(int code, String expected) {
|
||||
assertEquals(expected, GLStateManager.gluErrorString(code));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
+12
-23
@@ -2,11 +2,13 @@ package com.gtnewhorizons.angelica.glsm;
|
||||
|
||||
import com.gtnewhorizons.angelica.glsm.states.ImageUnitBinding;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.lwjgl.opengl.ContextCapabilities;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL15;
|
||||
import org.lwjgl.opengl.GL30;
|
||||
import org.lwjgl.opengl.GL42;
|
||||
|
||||
import static com.gtnewhorizons.angelica.glsm.GlTestSupport.drainErrors;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
@@ -16,17 +18,12 @@ import static org.junit.jupiter.api.Assumptions.assumeTrue;
|
||||
@GLCoreTest
|
||||
public class GLSM_ImageUnitBindingCache_UnitTest {
|
||||
|
||||
private static void drainErrors() {
|
||||
while (GL11.glGetError() != GL11.GL_NO_ERROR) {}
|
||||
}
|
||||
|
||||
private static void unbind(int unit) {
|
||||
GLStateManager.glBindImageTexture(unit, 0, 0, false, 0, GL15.GL_READ_ONLY, 0);
|
||||
GLStateManager.glBindImageTexture(unit, 0, 0, false, 0, GL15.GL_READ_ONLY, GL30.GL_R8);
|
||||
}
|
||||
|
||||
@Test
|
||||
void bindThenQueryReturnsFullTuple() {
|
||||
drainErrors();
|
||||
final int tex = GL11.glGenTextures();
|
||||
try {
|
||||
GLStateManager.glBindImageTexture(2, tex, 1, false, 3, GL15.GL_READ_ONLY, GL30.GL_RGBA32UI);
|
||||
@@ -40,13 +37,11 @@ public class GLSM_ImageUnitBindingCache_UnitTest {
|
||||
} finally {
|
||||
unbind(2);
|
||||
GLStateManager.glDeleteTextures(tex);
|
||||
drainErrors();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void saveRestoreRoundTripsTheWholeTuple() {
|
||||
drainErrors();
|
||||
final int a = GL11.glGenTextures();
|
||||
final int b = GL11.glGenTextures();
|
||||
try {
|
||||
@@ -55,7 +50,7 @@ public class GLSM_ImageUnitBindingCache_UnitTest {
|
||||
assertNotNull(live);
|
||||
final ImageUnitBinding saved = live.copy();
|
||||
|
||||
GLStateManager.glBindImageTexture(0, b, 0, true, 0, GL15.GL_WRITE_ONLY, 0);
|
||||
GLStateManager.glBindImageTexture(0, b, 0, true, 0, GL15.GL_WRITE_ONLY, GL30.GL_R8);
|
||||
assertEquals(b, GLStateManager.glGetInteger(GL42.GL_IMAGE_BINDING_NAME, 0));
|
||||
|
||||
GLStateManager.glBindImageTexture(0, saved.getTexture(), saved.getLevel(), saved.isLayered(), saved.getLayer(), saved.getAccess(), saved.getFormat());
|
||||
@@ -68,30 +63,26 @@ public class GLSM_ImageUnitBindingCache_UnitTest {
|
||||
unbind(0);
|
||||
GLStateManager.glDeleteTextures(a);
|
||||
GLStateManager.glDeleteTextures(b);
|
||||
drainErrors();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void resetToZeroIsNotARestore() {
|
||||
drainErrors();
|
||||
final int tex = GL11.glGenTextures();
|
||||
try {
|
||||
GLStateManager.glBindImageTexture(0, tex, 1, true, 0, GL15.GL_READ_WRITE, GL30.GL_R32UI);
|
||||
GLStateManager.glBindImageTexture(0, 0, 0, true, 0, GL15.GL_WRITE_ONLY, 0);
|
||||
GLStateManager.glBindImageTexture(0, 0, 0, true, 0, GL15.GL_WRITE_ONLY, GL30.GL_R8);
|
||||
|
||||
assertEquals(0, GLStateManager.glGetInteger(GL42.GL_IMAGE_BINDING_NAME, 0));
|
||||
assertEquals(0, GLStateManager.glGetInteger(GL42.GL_IMAGE_BINDING_LEVEL, 0));
|
||||
} finally {
|
||||
unbind(0);
|
||||
GLStateManager.glDeleteTextures(tex);
|
||||
drainErrors();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void deletingTheBoundTextureClearsTheImageUnit() {
|
||||
drainErrors();
|
||||
final int tex = GL11.glGenTextures();
|
||||
try {
|
||||
GLStateManager.glBindImageTexture(1, tex, 0, true, 0, GL15.GL_READ_WRITE, GL30.GL_R32UI);
|
||||
@@ -101,13 +92,11 @@ public class GLSM_ImageUnitBindingCache_UnitTest {
|
||||
assertEquals(0, GLStateManager.glGetInteger(GL42.GL_IMAGE_BINDING_NAME, 1), "GL unbinds a deleted texture from every image unit");
|
||||
} finally {
|
||||
unbind(1);
|
||||
drainErrors();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void unitsAreIndependentAndUnitZeroIsNotSpecial() {
|
||||
drainErrors();
|
||||
final int a = GL11.glGenTextures();
|
||||
final int b = GL11.glGenTextures();
|
||||
try {
|
||||
@@ -123,13 +112,11 @@ public class GLSM_ImageUnitBindingCache_UnitTest {
|
||||
unbind(3);
|
||||
GLStateManager.glDeleteTextures(a);
|
||||
GLStateManager.glDeleteTextures(b);
|
||||
drainErrors();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void outOfRangeUnitDoesNotCorruptNeighbours() {
|
||||
drainErrors();
|
||||
final int tex = GL11.glGenTextures();
|
||||
try {
|
||||
GLStateManager.glBindImageTexture(0, tex, 0, true, 0, GL15.GL_READ_ONLY, GL30.GL_R32UI);
|
||||
@@ -137,11 +124,14 @@ public class GLSM_ImageUnitBindingCache_UnitTest {
|
||||
assertFalse(beyond == 0, "unit 0 must resolve for this test to mean anything");
|
||||
|
||||
GLStateManager.glBindImageTexture(beyond, tex, 0, true, 0, GL15.GL_READ_ONLY, GL30.GL_R32UI);
|
||||
// Without image load/store the backend drops the call, so the driver never sees the unit.
|
||||
final ContextCapabilities caps = GLStateManager.capabilities;
|
||||
final boolean reachesDriver = caps.OpenGL42 || caps.GL_ARB_shader_image_load_store || caps.GL_EXT_shader_image_load_store;
|
||||
assertEquals(reachesDriver ? GL11.GL_INVALID_VALUE : GL11.GL_NO_ERROR, GL11.glGetError(), "driver must reject the out-of-range unit");
|
||||
assertEquals(tex, GLStateManager.glGetInteger(GL42.GL_IMAGE_BINDING_NAME, 0));
|
||||
} finally {
|
||||
unbind(0);
|
||||
GLStateManager.glDeleteTextures(tex);
|
||||
drainErrors();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -151,9 +141,9 @@ public class GLSM_ImageUnitBindingCache_UnitTest {
|
||||
drainErrors();
|
||||
final int tex = GL11.glGenTextures();
|
||||
try {
|
||||
GL11.glBindTexture(GL11.GL_TEXTURE_2D, tex);
|
||||
GL42.glTexStorage2D(GL11.GL_TEXTURE_2D, 1, GL30.GL_R32UI, 4, 4);
|
||||
GL11.glBindTexture(GL11.GL_TEXTURE_2D, 0);
|
||||
GLStateManager.glBindTexture(GL11.GL_TEXTURE_2D, tex);
|
||||
GLStateManager.glTexStorage2D(GL11.GL_TEXTURE_2D, 1, GL30.GL_R32UI, 4, 4);
|
||||
GLStateManager.glBindTexture(GL11.GL_TEXTURE_2D, 0);
|
||||
|
||||
GLStateManager.glBindImageTexture(1, tex, 0, false, 0, GL15.GL_READ_ONLY, GL30.GL_R32UI);
|
||||
drainErrors();
|
||||
@@ -164,7 +154,6 @@ public class GLSM_ImageUnitBindingCache_UnitTest {
|
||||
} finally {
|
||||
unbind(1);
|
||||
GLStateManager.glDeleteTextures(tex);
|
||||
drainErrors();
|
||||
}
|
||||
}
|
||||
}
|
||||
+529
-241
@@ -1,22 +1,34 @@
|
||||
package com.gtnewhorizons.angelica.glsm;
|
||||
|
||||
import com.gtnewhorizon.gtnhlib.client.renderer.vertex.VertexFlags;
|
||||
import com.gtnewhorizon.gtnhlib.client.renderer.vertex.VertexFormatElement.Usage;
|
||||
import com.gtnewhorizons.angelica.glsm.ffp.VAOManager;
|
||||
import com.gtnewhorizons.angelica.glsm.ffp.VertexKey;
|
||||
import com.gtnewhorizons.angelica.glsm.states.PixelStoreState;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
import org.lwjgl.BufferUtils;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL12;
|
||||
import org.lwjgl.opengl.GL13;
|
||||
import org.lwjgl.opengl.GL14;
|
||||
import org.lwjgl.opengl.GL20;
|
||||
import org.lwjgl.opengl.GL21;
|
||||
import org.lwjgl.opengl.GL30;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.DoubleBuffer;
|
||||
import java.nio.FloatBuffer;
|
||||
import java.nio.IntBuffer;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static com.gtnewhorizons.angelica.glsm.GlTestSupport.drainErrors;
|
||||
import static com.gtnewhorizons.angelica.glsm.LegacyQueryFixture.HINT_TARGETS;
|
||||
import static com.gtnewhorizons.angelica.glsm.LegacyQueryFixture.assertEnableRoundTrip;
|
||||
import static com.gtnewhorizons.angelica.glsm.LegacyQueryFixture.drainClientAttribStack;
|
||||
import static com.gtnewhorizons.angelica.glsm.LegacyQueryFixture.hex;
|
||||
import static com.gtnewhorizons.angelica.glsm.LegacyQueryFixture.legacyPnames;
|
||||
import static com.gtnewhorizons.angelica.glsm.LegacyQueryFixture.popAttribTo;
|
||||
import static com.gtnewhorizons.angelica.glsm.LegacyQueryFixture.setEnabled;
|
||||
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
@@ -27,44 +39,12 @@ import static org.junit.jupiter.api.Assumptions.assumeTrue;
|
||||
@GLCoreTest
|
||||
public class GLSM_LegacyStackQueries_GLTest {
|
||||
|
||||
private static final int[] SINGLE_VALUE_QUERIES = {
|
||||
GL11.GL_ATTRIB_STACK_DEPTH,
|
||||
GL11.GL_CLIENT_ATTRIB_STACK_DEPTH,
|
||||
GL11.GL_TEXTURE_STACK_DEPTH,
|
||||
GL11.GL_MAX_ATTRIB_STACK_DEPTH,
|
||||
GL11.GL_MAX_CLIENT_ATTRIB_STACK_DEPTH,
|
||||
GL11.GL_MAX_MODELVIEW_STACK_DEPTH,
|
||||
GL11.GL_MAX_PROJECTION_STACK_DEPTH,
|
||||
GL11.GL_MAX_TEXTURE_STACK_DEPTH,
|
||||
GL13.GL_MAX_TEXTURE_UNITS,
|
||||
GL11.GL_MAX_LIGHTS,
|
||||
GL11.GL_STENCIL_BITS,
|
||||
GL11.GL_DEPTH_BITS,
|
||||
};
|
||||
private static final int[] LEGACY_PNAMES = legacyPnames();
|
||||
|
||||
private static boolean positionArrayEnabled() {
|
||||
final VAOManager.Attrib position = GLStateManager.ctx().vaos.attrib(Usage.POSITION.getAttributeLocation());
|
||||
return position != null && position.enabled;
|
||||
}
|
||||
|
||||
private static boolean colorArrayEnabled() {
|
||||
return (GLStateManager.ctx().vaos.getVertexFlags() & VertexFlags.COLOR_BIT) != 0;
|
||||
}
|
||||
|
||||
private static void drainErrors() {
|
||||
while (GL11.glGetError() != GL11.GL_NO_ERROR) {}
|
||||
}
|
||||
|
||||
private static void drainClientAttribStack() {
|
||||
while (GLStateManager.glGetInteger(GL11.GL_CLIENT_ATTRIB_STACK_DEPTH) > 0) {
|
||||
GLStateManager.glPopClientAttrib();
|
||||
}
|
||||
}
|
||||
|
||||
private static void drainAttribStack() {
|
||||
while (GLStateManager.getAttribDepth() > 0) {
|
||||
GLStateManager.glPopAttrib();
|
||||
}
|
||||
private static void assumeDriverRejectsLegacyPnames() {
|
||||
drainErrors();
|
||||
GL11.glGetInteger(GL11.GL_ATTRIB_STACK_DEPTH);
|
||||
assumeTrue(GL11.glGetError() != GL11.GL_NO_ERROR, "driver accepts GL_ATTRIB_STACK_DEPTH, so a clean error state proves nothing");
|
||||
}
|
||||
|
||||
private static int pushToLimit(int depthPname, int maxPname) {
|
||||
@@ -95,9 +75,7 @@ public class GLSM_LegacyStackQueries_GLTest {
|
||||
assertEquals(base, GLStateManager.glGetInteger(GL11.GL_ATTRIB_STACK_DEPTH));
|
||||
assertEquals(GLStateManager.MAX_ATTRIB_STACK_DEPTH, GLStateManager.glGetInteger(GL11.GL_MAX_ATTRIB_STACK_DEPTH));
|
||||
} finally {
|
||||
while (GLStateManager.getAttribDepth() > base) {
|
||||
GLStateManager.glPopAttrib();
|
||||
}
|
||||
popAttribTo(base);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -150,42 +128,24 @@ public class GLSM_LegacyStackQueries_GLTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void maxModelviewStackDepthIsExactlyReachable() {
|
||||
try {
|
||||
GLStateManager.glMatrixMode(GL11.GL_MODELVIEW);
|
||||
assertEquals(1, GLStateManager.glGetInteger(GL11.GL_MODELVIEW_STACK_DEPTH));
|
||||
assertEquals(GLStateManager.glGetInteger(GL11.GL_MAX_MODELVIEW_STACK_DEPTH), pushToLimit(GL11.GL_MODELVIEW_STACK_DEPTH, GL11.GL_MAX_MODELVIEW_STACK_DEPTH));
|
||||
} finally {
|
||||
GLStateManager.glMatrixMode(GL11.GL_MODELVIEW);
|
||||
popToBase(GL11.GL_MODELVIEW_STACK_DEPTH);
|
||||
}
|
||||
static Stream<Arguments> matrixStacks() {
|
||||
return Stream.of(
|
||||
Arguments.of("modelview", GL11.GL_MODELVIEW, GL11.GL_MODELVIEW_STACK_DEPTH, GL11.GL_MAX_MODELVIEW_STACK_DEPTH),
|
||||
Arguments.of("projection", GL11.GL_PROJECTION, GL11.GL_PROJECTION_STACK_DEPTH, GL11.GL_MAX_PROJECTION_STACK_DEPTH),
|
||||
Arguments.of("texture", GL11.GL_TEXTURE, GL11.GL_TEXTURE_STACK_DEPTH, GL11.GL_MAX_TEXTURE_STACK_DEPTH));
|
||||
}
|
||||
|
||||
@Test
|
||||
void maxProjectionStackDepthIsExactlyReachable() {
|
||||
try {
|
||||
GLStateManager.glMatrixMode(GL11.GL_PROJECTION);
|
||||
assertEquals(1, GLStateManager.glGetInteger(GL11.GL_PROJECTION_STACK_DEPTH));
|
||||
assertEquals(GLStateManager.glGetInteger(GL11.GL_MAX_PROJECTION_STACK_DEPTH), pushToLimit(GL11.GL_PROJECTION_STACK_DEPTH, GL11.GL_MAX_PROJECTION_STACK_DEPTH));
|
||||
} finally {
|
||||
GLStateManager.glMatrixMode(GL11.GL_PROJECTION);
|
||||
popToBase(GL11.GL_PROJECTION_STACK_DEPTH);
|
||||
GLStateManager.glMatrixMode(GL11.GL_MODELVIEW);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void maxTextureStackDepthIsExactlyReachable() {
|
||||
@ParameterizedTest(name = "{0}")
|
||||
@MethodSource("matrixStacks")
|
||||
void maxMatrixStackDepthIsExactlyReachable(String name, int mode, int depthPname, int maxPname) {
|
||||
try {
|
||||
GLStateManager.glActiveTexture(GL13.GL_TEXTURE0);
|
||||
GLStateManager.glMatrixMode(GL11.GL_TEXTURE);
|
||||
assertEquals(1, GLStateManager.glGetInteger(GL11.GL_TEXTURE_STACK_DEPTH));
|
||||
assertEquals(GLStateManager.glGetInteger(GL11.GL_MAX_TEXTURE_STACK_DEPTH), pushToLimit(GL11.GL_TEXTURE_STACK_DEPTH, GL11.GL_MAX_TEXTURE_STACK_DEPTH));
|
||||
GLStateManager.glMatrixMode(mode);
|
||||
assertEquals(1, GLStateManager.glGetInteger(depthPname));
|
||||
assertEquals(GLStateManager.glGetInteger(maxPname), pushToLimit(depthPname, maxPname));
|
||||
} finally {
|
||||
GLStateManager.glActiveTexture(GL13.GL_TEXTURE0);
|
||||
GLStateManager.glMatrixMode(GL11.GL_TEXTURE);
|
||||
popToBase(GL11.GL_TEXTURE_STACK_DEPTH);
|
||||
GLStateManager.glMatrixMode(mode);
|
||||
popToBase(depthPname);
|
||||
GLStateManager.glMatrixMode(GL11.GL_MODELVIEW);
|
||||
}
|
||||
}
|
||||
@@ -203,14 +163,12 @@ public class GLSM_LegacyStackQueries_GLTest {
|
||||
final int savedRead = glCtx.readFramebuffer;
|
||||
try {
|
||||
GLStateManager.glBindFramebuffer(GL30.GL_FRAMEBUFFER, 0);
|
||||
drainErrors();
|
||||
assertEquals(
|
||||
GL30.glGetFramebufferAttachmentParameteri(GL30.GL_DRAW_FRAMEBUFFER, GL11.GL_STENCIL, GL30.GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE),
|
||||
GLStateManager.glGetInteger(GL11.GL_STENCIL_BITS));
|
||||
assertEquals(
|
||||
GL30.glGetFramebufferAttachmentParameteri(GL30.GL_DRAW_FRAMEBUFFER, GL11.GL_DEPTH, GL30.GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE),
|
||||
GLStateManager.glGetInteger(GL11.GL_DEPTH_BITS));
|
||||
assertEquals(GL11.GL_NO_ERROR, GL11.glGetError());
|
||||
} finally {
|
||||
GLStateManager.glBindFramebuffer(GL30.GL_DRAW_FRAMEBUFFER, savedDraw);
|
||||
GLStateManager.glBindFramebuffer(GL30.GL_READ_FRAMEBUFFER, savedRead);
|
||||
@@ -226,7 +184,6 @@ public class GLSM_LegacyStackQueries_GLTest {
|
||||
final int depthOnly = GLStateManager.glGenRenderbuffers();
|
||||
final int depthStencil = GLStateManager.glGenRenderbuffers();
|
||||
try {
|
||||
drainErrors();
|
||||
GLStateManager.glBindRenderbuffer(GL30.GL_RENDERBUFFER, depthOnly);
|
||||
GLStateManager.glRenderbufferStorage(GL30.GL_RENDERBUFFER, GL14.GL_DEPTH_COMPONENT24, 16, 16);
|
||||
GLStateManager.glBindRenderbuffer(GL30.GL_RENDERBUFFER, depthStencil);
|
||||
@@ -247,7 +204,6 @@ public class GLSM_LegacyStackQueries_GLTest {
|
||||
GLStateManager.glFramebufferRenderbuffer(GL30.GL_FRAMEBUFFER, GL30.GL_STENCIL_ATTACHMENT, GL30.GL_RENDERBUFFER, depthStencil);
|
||||
assertEquals(8, GLStateManager.glGetInteger(GL11.GL_STENCIL_BITS));
|
||||
assertEquals(24, GLStateManager.glGetInteger(GL11.GL_DEPTH_BITS));
|
||||
assertEquals(GL11.GL_NO_ERROR, GL11.glGetError());
|
||||
} finally {
|
||||
GLStateManager.glBindFramebuffer(GL30.GL_DRAW_FRAMEBUFFER, savedDraw);
|
||||
GLStateManager.glBindFramebuffer(GL30.GL_READ_FRAMEBUFFER, savedRead);
|
||||
@@ -257,33 +213,6 @@ public class GLSM_LegacyStackQueries_GLTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void intBufferOverloadMatchesAndDriverIsNotAsked() {
|
||||
final int base = GLStateManager.getAttribDepth();
|
||||
final IntBuffer buf = BufferUtils.createIntBuffer(16);
|
||||
try {
|
||||
GLStateManager.glPushAttrib(GL11.GL_ENABLE_BIT);
|
||||
GLStateManager.glPushClientAttrib(GL11.GL_CLIENT_PIXEL_STORE_BIT);
|
||||
GLStateManager.glClientActiveTexture(GL13.GL_TEXTURE1);
|
||||
drainErrors();
|
||||
GL11.glGetInteger(GL11.GL_ATTRIB_STACK_DEPTH);
|
||||
assumeTrue(GL11.glGetError() != GL11.GL_NO_ERROR, "driver accepts GL_ATTRIB_STACK_DEPTH, so a clean error state proves nothing");
|
||||
for (final int pname : SINGLE_VALUE_QUERIES) {
|
||||
final int direct = GLStateManager.glGetInteger(pname);
|
||||
buf.put(0, -12345);
|
||||
GLStateManager.glGetInteger(pname, buf);
|
||||
assertEquals(direct, buf.get(0), "IntBuffer overload for 0x" + Integer.toHexString(pname));
|
||||
assertEquals(GL11.GL_NO_ERROR, GL11.glGetError(), "driver error after querying 0x" + Integer.toHexString(pname));
|
||||
}
|
||||
} finally {
|
||||
GLStateManager.glClientActiveTexture(GL13.GL_TEXTURE0);
|
||||
drainClientAttribStack();
|
||||
while (GLStateManager.getAttribDepth() > base) {
|
||||
GLStateManager.glPopAttrib();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void attribDepthUnchangedWhileCompilingDisplayList() {
|
||||
final int base = GLStateManager.glGetInteger(GL11.GL_ATTRIB_STACK_DEPTH);
|
||||
@@ -306,14 +235,12 @@ public class GLSM_LegacyStackQueries_GLTest {
|
||||
|
||||
@Test
|
||||
void popAttribOnEmptyStackIsIgnored() {
|
||||
drainAttribStack();
|
||||
drainErrors();
|
||||
popAttribTo(0);
|
||||
assertEquals(0, GLStateManager.getAttribDepth());
|
||||
assertDoesNotThrow(GLStateManager::glPopAttrib);
|
||||
assertEquals(0, GLStateManager.glGetInteger(GL11.GL_ATTRIB_STACK_DEPTH));
|
||||
assertDoesNotThrow(GLStateManager::glPopAttrib);
|
||||
assertEquals(0, GLStateManager.getAttribDepth());
|
||||
assertEquals(GL11.GL_NO_ERROR, GL11.glGetError());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -322,8 +249,11 @@ public class GLSM_LegacyStackQueries_GLTest {
|
||||
final int unpackBuffer = GLStateManager.glGenBuffers();
|
||||
final int packBuffer = GLStateManager.glGenBuffers();
|
||||
try {
|
||||
GLStateManager.glPixelStorei(GL11.GL_UNPACK_ALIGNMENT, 4);
|
||||
GLStateManager.glPixelStorei(GL11.GL_PACK_ALIGNMENT, 4);
|
||||
// Pack and unpack start from different values, so a pop that crosses them is caught
|
||||
GLStateManager.glPixelStorei(GL11.GL_UNPACK_ALIGNMENT, 2);
|
||||
GLStateManager.glPixelStorei(GL11.GL_PACK_ALIGNMENT, 8);
|
||||
GLStateManager.glPixelStorei(GL11.GL_UNPACK_SKIP_ROWS, 3);
|
||||
GLStateManager.glPixelStorei(GL11.GL_PACK_SKIP_ROWS, 5);
|
||||
GLStateManager.glPixelStorei(GL11.GL_PACK_ROW_LENGTH, 0);
|
||||
GLStateManager.glBindBuffer(GL21.GL_PIXEL_UNPACK_BUFFER, 0);
|
||||
GLStateManager.glBindBuffer(GL21.GL_PIXEL_PACK_BUFFER, 0);
|
||||
@@ -332,31 +262,41 @@ public class GLSM_LegacyStackQueries_GLTest {
|
||||
|
||||
GLStateManager.glPushClientAttrib(GL11.GL_CLIENT_PIXEL_STORE_BIT);
|
||||
GLStateManager.glPixelStorei(GL11.GL_UNPACK_ALIGNMENT, 1);
|
||||
GLStateManager.glPixelStorei(GL11.GL_PACK_ALIGNMENT, 2);
|
||||
GLStateManager.glPixelStorei(GL11.GL_PACK_ALIGNMENT, 4);
|
||||
GLStateManager.glPixelStorei(GL11.GL_UNPACK_SKIP_ROWS, 6);
|
||||
GLStateManager.glPixelStorei(GL11.GL_PACK_SKIP_ROWS, 7);
|
||||
GLStateManager.glPixelStorei(GL11.GL_PACK_ROW_LENGTH, 7);
|
||||
GLStateManager.glBindBuffer(GL21.GL_PIXEL_UNPACK_BUFFER, unpackBuffer);
|
||||
GLStateManager.glBindBuffer(GL21.GL_PIXEL_PACK_BUFFER, packBuffer);
|
||||
assertEquals(1, glCtx.pixelUnpackState.alignment());
|
||||
assertEquals(2, glCtx.pixelPackState.alignment());
|
||||
assertEquals(4, glCtx.pixelPackState.alignment());
|
||||
assertEquals(6, glCtx.pixelUnpackState.skipRows());
|
||||
assertEquals(7, glCtx.pixelPackState.skipRows());
|
||||
assertEquals(7, glCtx.pixelPackState.rowLength());
|
||||
assertEquals(2, GL11.glGetInteger(GL11.GL_PACK_ALIGNMENT));
|
||||
assertEquals(4, GL11.glGetInteger(GL11.GL_PACK_ALIGNMENT));
|
||||
assertEquals(6, GL11.glGetInteger(GL11.GL_UNPACK_SKIP_ROWS));
|
||||
assertEquals(7, GL11.glGetInteger(GL11.GL_PACK_SKIP_ROWS));
|
||||
GLStateManager.glPopClientAttrib();
|
||||
|
||||
assertSame(unpackBefore, glCtx.pixelUnpackState);
|
||||
assertSame(packBefore, glCtx.pixelPackState);
|
||||
assertEquals(4, GLStateManager.glGetInteger(GL11.GL_UNPACK_ALIGNMENT));
|
||||
assertEquals(2, GLStateManager.glGetInteger(GL11.GL_UNPACK_ALIGNMENT));
|
||||
assertEquals(8, GLStateManager.glGetInteger(GL11.GL_PACK_ALIGNMENT));
|
||||
assertEquals(0, GLStateManager.glGetInteger(GL21.GL_PIXEL_UNPACK_BUFFER_BINDING));
|
||||
assertEquals(0, GLStateManager.glGetInteger(GL21.GL_PIXEL_PACK_BUFFER_BINDING));
|
||||
assertEquals(4, GL11.glGetInteger(GL11.GL_UNPACK_ALIGNMENT));
|
||||
assertEquals(4, GL11.glGetInteger(GL11.GL_PACK_ALIGNMENT));
|
||||
assertEquals(2, GL11.glGetInteger(GL11.GL_UNPACK_ALIGNMENT));
|
||||
assertEquals(8, GL11.glGetInteger(GL11.GL_PACK_ALIGNMENT));
|
||||
assertEquals(3, GL11.glGetInteger(GL11.GL_UNPACK_SKIP_ROWS));
|
||||
assertEquals(5, GL11.glGetInteger(GL11.GL_PACK_SKIP_ROWS));
|
||||
assertEquals(0, GL11.glGetInteger(GL11.GL_PACK_ROW_LENGTH));
|
||||
assertEquals(0, GL11.glGetInteger(GL21.GL_PIXEL_UNPACK_BUFFER_BINDING));
|
||||
assertEquals(0, GL11.glGetInteger(GL21.GL_PIXEL_PACK_BUFFER_BINDING));
|
||||
assertEquals(GL11.GL_NO_ERROR, GL11.glGetError());
|
||||
} finally {
|
||||
drainClientAttribStack();
|
||||
GLStateManager.glPixelStorei(GL11.GL_UNPACK_ALIGNMENT, 4);
|
||||
GLStateManager.glPixelStorei(GL11.GL_PACK_ALIGNMENT, 4);
|
||||
GLStateManager.glPixelStorei(GL11.GL_UNPACK_SKIP_ROWS, 0);
|
||||
GLStateManager.glPixelStorei(GL11.GL_PACK_SKIP_ROWS, 0);
|
||||
GLStateManager.glPixelStorei(GL11.GL_PACK_ROW_LENGTH, 0);
|
||||
GLStateManager.glBindBuffer(GL21.GL_PIXEL_UNPACK_BUFFER, 0);
|
||||
GLStateManager.glBindBuffer(GL21.GL_PIXEL_PACK_BUFFER, 0);
|
||||
@@ -428,122 +368,6 @@ public class GLSM_LegacyStackQueries_GLTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void packAndUnpackRestoreToTheirOwnPriorValues() {
|
||||
final GLContextState glCtx = GLStateManager.ctx();
|
||||
try {
|
||||
GLStateManager.glPixelStorei(GL11.GL_UNPACK_ALIGNMENT, 2);
|
||||
GLStateManager.glPixelStorei(GL11.GL_PACK_ALIGNMENT, 8);
|
||||
GLStateManager.glPixelStorei(GL11.GL_UNPACK_SKIP_ROWS, 3);
|
||||
GLStateManager.glPixelStorei(GL11.GL_PACK_SKIP_ROWS, 5);
|
||||
|
||||
GLStateManager.glPushClientAttrib(GL11.GL_CLIENT_PIXEL_STORE_BIT);
|
||||
GLStateManager.glPixelStorei(GL11.GL_UNPACK_ALIGNMENT, 1);
|
||||
GLStateManager.glPixelStorei(GL11.GL_PACK_ALIGNMENT, 4);
|
||||
GLStateManager.glPixelStorei(GL11.GL_UNPACK_SKIP_ROWS, 6);
|
||||
GLStateManager.glPixelStorei(GL11.GL_PACK_SKIP_ROWS, 7);
|
||||
assertEquals(1, glCtx.pixelUnpackState.alignment());
|
||||
assertEquals(4, glCtx.pixelPackState.alignment());
|
||||
assertEquals(6, glCtx.pixelUnpackState.skipRows());
|
||||
assertEquals(7, glCtx.pixelPackState.skipRows());
|
||||
assertEquals(6, GL11.glGetInteger(GL11.GL_UNPACK_SKIP_ROWS));
|
||||
assertEquals(7, GL11.glGetInteger(GL11.GL_PACK_SKIP_ROWS));
|
||||
GLStateManager.glPopClientAttrib();
|
||||
|
||||
assertEquals(2, glCtx.pixelUnpackState.alignment());
|
||||
assertEquals(8, glCtx.pixelPackState.alignment());
|
||||
assertEquals(3, glCtx.pixelUnpackState.skipRows());
|
||||
assertEquals(5, glCtx.pixelPackState.skipRows());
|
||||
assertEquals(2, GL11.glGetInteger(GL11.GL_UNPACK_ALIGNMENT));
|
||||
assertEquals(8, GL11.glGetInteger(GL11.GL_PACK_ALIGNMENT));
|
||||
assertEquals(3, GL11.glGetInteger(GL11.GL_UNPACK_SKIP_ROWS));
|
||||
assertEquals(5, GL11.glGetInteger(GL11.GL_PACK_SKIP_ROWS));
|
||||
assertEquals(GL11.GL_NO_ERROR, GL11.glGetError());
|
||||
} finally {
|
||||
drainClientAttribStack();
|
||||
GLStateManager.glPixelStorei(GL11.GL_UNPACK_ALIGNMENT, 4);
|
||||
GLStateManager.glPixelStorei(GL11.GL_PACK_ALIGNMENT, 4);
|
||||
GLStateManager.glPixelStorei(GL11.GL_UNPACK_SKIP_ROWS, 0);
|
||||
GLStateManager.glPixelStorei(GL11.GL_PACK_SKIP_ROWS, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void vertexArrayEnableRestoredOnlyWithVertexArrayBit() {
|
||||
final int savedVao = GLStateManager.getBoundVAO();
|
||||
final int vao = GLStateManager.glGenVertexArrays();
|
||||
final IntBuffer enabled = BufferUtils.createIntBuffer(16);
|
||||
final int position = Usage.POSITION.getAttributeLocation();
|
||||
try {
|
||||
GLStateManager.glBindVertexArray(vao);
|
||||
drainErrors();
|
||||
assertFalse(positionArrayEnabled());
|
||||
|
||||
GLStateManager.glPushClientAttrib(GL11.GL_CLIENT_VERTEX_ARRAY_BIT);
|
||||
GLStateManager.glEnableClientState(GL11.GL_VERTEX_ARRAY);
|
||||
assertTrue(positionArrayEnabled());
|
||||
GLStateManager.glPopClientAttrib();
|
||||
assertFalse(positionArrayEnabled());
|
||||
GL20.glGetVertexAttrib(position, GL20.GL_VERTEX_ATTRIB_ARRAY_ENABLED, enabled);
|
||||
assertEquals(GL11.GL_FALSE, enabled.get(0));
|
||||
|
||||
GLStateManager.glEnableClientState(GL11.GL_VERTEX_ARRAY);
|
||||
GLStateManager.glPushClientAttrib(GL11.GL_CLIENT_VERTEX_ARRAY_BIT);
|
||||
GLStateManager.glDisableClientState(GL11.GL_VERTEX_ARRAY);
|
||||
GLStateManager.glPopClientAttrib();
|
||||
assertTrue(positionArrayEnabled());
|
||||
GL20.glGetVertexAttrib(position, GL20.GL_VERTEX_ATTRIB_ARRAY_ENABLED, enabled);
|
||||
assertEquals(GL11.GL_TRUE, enabled.get(0));
|
||||
GLStateManager.glDisableClientState(GL11.GL_VERTEX_ARRAY);
|
||||
|
||||
GLStateManager.glPushClientAttrib(GL11.GL_CLIENT_PIXEL_STORE_BIT);
|
||||
GLStateManager.glEnableClientState(GL11.GL_VERTEX_ARRAY);
|
||||
GLStateManager.glPopClientAttrib();
|
||||
assertTrue(positionArrayEnabled());
|
||||
assertEquals(GL11.GL_NO_ERROR, GL11.glGetError());
|
||||
} finally {
|
||||
drainClientAttribStack();
|
||||
GLStateManager.glDisableClientState(GL11.GL_VERTEX_ARRAY);
|
||||
GLStateManager.glBindVertexArray(savedVao);
|
||||
GLStateManager.glDeleteVertexArrays(vao);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void vertexArrayStateRestoredOnlyWithVertexArrayBit() {
|
||||
final int savedVao = GLStateManager.getBoundVAO();
|
||||
final int vao = GLStateManager.glGenVertexArrays();
|
||||
try {
|
||||
GLStateManager.glBindVertexArray(vao);
|
||||
GLStateManager.glClientActiveTexture(GL13.GL_TEXTURE0);
|
||||
final int flagsBefore = GLStateManager.ctx().vaos.getVertexFlags();
|
||||
assertFalse(colorArrayEnabled());
|
||||
|
||||
GLStateManager.glPushClientAttrib(GL11.GL_CLIENT_VERTEX_ARRAY_BIT);
|
||||
GLStateManager.glEnableClientState(GL11.GL_COLOR_ARRAY);
|
||||
GLStateManager.glClientActiveTexture(GL13.GL_TEXTURE1);
|
||||
assertTrue(colorArrayEnabled());
|
||||
GLStateManager.glPopClientAttrib();
|
||||
assertFalse(colorArrayEnabled());
|
||||
assertEquals(flagsBefore, GLStateManager.ctx().vaos.getVertexFlags());
|
||||
assertEquals(0, GLStateManager.getClientActiveTextureUnit());
|
||||
|
||||
GLStateManager.glPushClientAttrib(GL11.GL_CLIENT_PIXEL_STORE_BIT);
|
||||
GLStateManager.glEnableClientState(GL11.GL_COLOR_ARRAY);
|
||||
GLStateManager.glClientActiveTexture(GL13.GL_TEXTURE1);
|
||||
GLStateManager.glPopClientAttrib();
|
||||
assertTrue(colorArrayEnabled());
|
||||
assertEquals(1, GLStateManager.getClientActiveTextureUnit());
|
||||
assertEquals(GL11.GL_NO_ERROR, GL11.glGetError());
|
||||
} finally {
|
||||
drainClientAttribStack();
|
||||
GLStateManager.glClientActiveTexture(GL13.GL_TEXTURE0);
|
||||
GLStateManager.glDisableClientState(GL11.GL_COLOR_ARRAY);
|
||||
GLStateManager.glBindVertexArray(savedVao);
|
||||
GLStateManager.glDeleteVertexArrays(vao);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void intLightGettersConvertLikeMesa() {
|
||||
final FloatBuffer savedDiffuse = BufferUtils.createFloatBuffer(16);
|
||||
@@ -570,7 +394,6 @@ public class GLSM_LegacyStackQueries_GLTest {
|
||||
GLStateManager.glLight(GL11.GL_LIGHT1, GL11.GL_SPOT_DIRECTION, values);
|
||||
GLStateManager.glLightf(GL11.GL_LIGHT1, GL11.GL_SPOT_CUTOFF, 45.75f);
|
||||
GLStateManager.glLightf(GL11.GL_LIGHT1, GL11.GL_LINEAR_ATTENUATION, 2.5f);
|
||||
drainErrors();
|
||||
|
||||
ints.position(2);
|
||||
GLStateManager.glGetLight(GL11.GL_LIGHT1, GL11.GL_DIFFUSE, ints);
|
||||
@@ -606,7 +429,6 @@ public class GLSM_LegacyStackQueries_GLTest {
|
||||
assertEquals(-777, ints.get(0));
|
||||
GLStateManager.glGetLight(GL11.GL_LIGHT1, GL11.GL_SHININESS, ints);
|
||||
assertEquals(-777, ints.get(0));
|
||||
assertEquals(GL11.GL_NO_ERROR, GL11.glGetError());
|
||||
} finally {
|
||||
GLStateManager.glLoadIdentity();
|
||||
savedDiffuse.limit(4);
|
||||
@@ -637,7 +459,6 @@ public class GLSM_LegacyStackQueries_GLTest {
|
||||
GLStateManager.glMaterialf(GL11.GL_FRONT, GL11.GL_SHININESS, 12.6f);
|
||||
values.put(0, 2.5f).put(1, -2.5f).put(2, 7.4f).put(3, 0.0f);
|
||||
GLStateManager.glMaterial(GL11.GL_BACK, GL11.GL_COLOR_INDEXES, values);
|
||||
drainErrors();
|
||||
|
||||
ints.position(1);
|
||||
GLStateManager.glGetMaterial(GL11.GL_FRONT, GL11.GL_SPECULAR, ints);
|
||||
@@ -665,7 +486,6 @@ public class GLSM_LegacyStackQueries_GLTest {
|
||||
assertEquals(-777, ints.get(0));
|
||||
GLStateManager.glGetMaterial(GL11.GL_FRONT, GL11.GL_SPOT_CUTOFF, ints);
|
||||
assertEquals(-777, ints.get(0));
|
||||
assertEquals(GL11.GL_NO_ERROR, GL11.glGetError());
|
||||
} finally {
|
||||
savedSpecular.limit(4);
|
||||
GLStateManager.glMaterial(GL11.GL_FRONT, GL11.GL_SPECULAR, savedSpecular);
|
||||
@@ -691,7 +511,6 @@ public class GLSM_LegacyStackQueries_GLTest {
|
||||
GLStateManager.glMultiTexCoord2f(GL13.GL_TEXTURE1, 240.0f, 16.0f);
|
||||
GLStateManager.glMultiTexCoord2f(GL13.GL_TEXTURE2, 0.75f, 0.125f);
|
||||
GLStateManager.glMultiTexCoord2f(GL13.GL_TEXTURE3, 0.375f, 0.625f);
|
||||
drainErrors();
|
||||
|
||||
final float[][] expected = { { 0.25f, 0.5f }, { 240.0f, 16.0f }, { 0.75f, 0.125f }, { 0.375f, 0.625f } };
|
||||
for (int unit = 0; unit < 4; unit++) {
|
||||
@@ -702,7 +521,6 @@ public class GLSM_LegacyStackQueries_GLTest {
|
||||
assertEquals(0.0f, buf.get(2), "r of unit " + unit);
|
||||
assertEquals(1.0f, buf.get(3), "q of unit " + unit);
|
||||
}
|
||||
assertEquals(GL11.GL_NO_ERROR, GL11.glGetError());
|
||||
} finally {
|
||||
for (int unit = 0; unit < 4; unit++) {
|
||||
GLStateManager.glMultiTexCoord2f(GL13.GL_TEXTURE0 + unit, saved[unit][0], saved[unit][1]);
|
||||
@@ -719,7 +537,6 @@ public class GLSM_LegacyStackQueries_GLTest {
|
||||
GLStateManager.glActiveTexture(GL13.GL_TEXTURE0);
|
||||
GLStateManager.glMultiTexCoord2f(GL13.GL_TEXTURE0, 0.25f, 0.5f);
|
||||
GLStateManager.glActiveTexture(GL13.GL_TEXTURE0 + unit);
|
||||
drainErrors();
|
||||
for (int i = 0; i < 4; i++) {
|
||||
buf.put(i, -7.0f);
|
||||
}
|
||||
@@ -728,10 +545,481 @@ public class GLSM_LegacyStackQueries_GLTest {
|
||||
assertEquals(0.0f, buf.get(1));
|
||||
assertEquals(0.0f, buf.get(2));
|
||||
assertEquals(1.0f, buf.get(3));
|
||||
assertEquals(GL11.GL_NO_ERROR, GL11.glGetError());
|
||||
} finally {
|
||||
GLStateManager.glActiveTexture(GL13.GL_TEXTURE0);
|
||||
GLStateManager.glMultiTexCoord2f(GL13.GL_TEXTURE0, 0.0f, 0.0f);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void legacyQueriesNeverReachTheDriver() {
|
||||
final int base = GLStateManager.getAttribDepth();
|
||||
final IntBuffer ints = BufferUtils.createIntBuffer(16);
|
||||
final FloatBuffer floats = BufferUtils.createFloatBuffer(16);
|
||||
final DoubleBuffer doubles = BufferUtils.createDoubleBuffer(16);
|
||||
final ByteBuffer bytes = BufferUtils.createByteBuffer(16);
|
||||
final int[] intArray = new int[16];
|
||||
final float[] floatArray = new float[16];
|
||||
final double[] doubleArray = new double[16];
|
||||
try {
|
||||
GLStateManager.glPushAttrib(GL11.GL_ENABLE_BIT);
|
||||
GLStateManager.glPushClientAttrib(GL11.GL_CLIENT_PIXEL_STORE_BIT);
|
||||
GLStateManager.glClientActiveTexture(GL13.GL_TEXTURE1);
|
||||
assumeDriverRejectsLegacyPnames();
|
||||
for (final int pname : LEGACY_PNAMES) {
|
||||
drainErrors();
|
||||
final int scalar = GLStateManager.glGetInteger(pname);
|
||||
GLStateManager.glGetFloat(pname);
|
||||
GLStateManager.glGetBoolean(pname);
|
||||
GLStateManager.glIsEnabled(pname);
|
||||
ints.clear();
|
||||
ints.put(0, -12345);
|
||||
GLStateManager.glGetInteger(pname, ints);
|
||||
floats.clear();
|
||||
GLStateManager.glGetFloat(pname, floats);
|
||||
doubles.clear();
|
||||
GLStateManager.glGetDouble(pname, doubles);
|
||||
bytes.clear();
|
||||
GLStateManager.glGetBoolean(pname, bytes);
|
||||
intArray[0] = -12345;
|
||||
GLStateManager.glGetInteger(pname, intArray);
|
||||
GLStateManager.glGetFloat(pname, floatArray);
|
||||
GLStateManager.glGetDouble(pname, doubleArray);
|
||||
if (LegacyQueries.count(LegacyQueries.desc(pname)) == 1) {
|
||||
assertEquals(scalar, ints.get(0), "IntBuffer overload for " + hex(pname));
|
||||
assertEquals(scalar, intArray[0], "int[] overload for " + hex(pname));
|
||||
}
|
||||
assertEquals(GL11.GL_NO_ERROR, GL11.glGetError(), "driver error after querying " + hex(pname));
|
||||
}
|
||||
} finally {
|
||||
GLStateManager.glClientActiveTexture(GL13.GL_TEXTURE0);
|
||||
drainClientAttribStack();
|
||||
popAttribTo(base);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void typedEntryPointsAgreeUnderMesaConversions() {
|
||||
final IntBuffer ints = BufferUtils.createIntBuffer(16);
|
||||
final FloatBuffer floats = BufferUtils.createFloatBuffer(16);
|
||||
final DoubleBuffer doubles = BufferUtils.createDoubleBuffer(16);
|
||||
final FloatBuffer savedColor = BufferUtils.createFloatBuffer(16);
|
||||
final FloatBuffer savedNormal = BufferUtils.createFloatBuffer(16);
|
||||
GLStateManager.glGetFloat(GL11.GL_CURRENT_COLOR, savedColor);
|
||||
GLStateManager.glGetFloat(GL11.GL_CURRENT_NORMAL, savedNormal);
|
||||
final int savedFunc = GLStateManager.glGetInteger(GL11.GL_ALPHA_TEST_FUNC);
|
||||
final float savedRef = GLStateManager.glGetFloat(GL11.GL_ALPHA_TEST_REF);
|
||||
final float savedStart = GLStateManager.glGetFloat(GL11.GL_FOG_START);
|
||||
final float savedEnd = GLStateManager.glGetFloat(GL11.GL_FOG_END);
|
||||
final float savedDensity = GLStateManager.glGetFloat(GL11.GL_FOG_DENSITY);
|
||||
final boolean savedLighting = GLStateManager.glIsEnabled(GL11.GL_LIGHTING);
|
||||
final boolean savedFog = GLStateManager.glIsEnabled(GL11.GL_FOG);
|
||||
final int savedShade = GLStateManager.glGetInteger(GL11.GL_SHADE_MODEL);
|
||||
final int savedHint = GLStateManager.glGetInteger(GL11.GL_FOG_HINT);
|
||||
final float savedMinSize = GLStateManager.glGetFloat(GL14.GL_POINT_SIZE_MIN);
|
||||
GLStateManager.glMatrixMode(GL11.GL_MODELVIEW);
|
||||
GLStateManager.glPushMatrix();
|
||||
try {
|
||||
GLStateManager.glAlphaFunc(GL11.GL_GREATER, 0.5f);
|
||||
GLStateManager.glFogf(GL11.GL_FOG_START, -1.5f);
|
||||
GLStateManager.glFogf(GL11.GL_FOG_END, 2.5f);
|
||||
GLStateManager.glFogf(GL11.GL_FOG_DENSITY, 0.25f);
|
||||
GLStateManager.glColor4f(0.25f, 0.5f, 0.75f, 1f);
|
||||
GLStateManager.glNormal3f(0f, -0.5f, 1f);
|
||||
GLStateManager.glEnable(GL11.GL_LIGHTING);
|
||||
GLStateManager.glEnable(GL11.GL_FOG);
|
||||
GLStateManager.glShadeModel(GL11.GL_FLAT);
|
||||
GLStateManager.glHint(GL11.GL_FOG_HINT, GL11.GL_NICEST);
|
||||
GLStateManager.glPointParameterf(GL14.GL_POINT_SIZE_MIN, 2.5f);
|
||||
GLStateManager.glTranslatef(1.5f, -2.5f, 3f);
|
||||
for (final int pname : LEGACY_PNAMES) {
|
||||
final int desc = LegacyQueries.desc(pname);
|
||||
final int type = LegacyQueries.type(desc);
|
||||
final int count = LegacyQueries.count(desc);
|
||||
final String name = hex(pname);
|
||||
if (count == 1) {
|
||||
if (type == LegacyQueries.BOOL) {
|
||||
final boolean b = GLStateManager.glGetBoolean(pname);
|
||||
assertEquals(b ? 1 : 0, GLStateManager.glGetInteger(pname), "int of bool " + name);
|
||||
assertEquals(b ? 1.0f : 0.0f, GLStateManager.glGetFloat(pname), "float of bool " + name);
|
||||
} else if (type == LegacyQueries.INT) {
|
||||
final int i = GLStateManager.glGetInteger(pname);
|
||||
assertEquals((float) i, GLStateManager.glGetFloat(pname), "float of int " + name);
|
||||
assertEquals(i != 0, GLStateManager.glGetBoolean(pname), "bool of int " + name);
|
||||
} else {
|
||||
final float f = GLStateManager.glGetFloat(pname);
|
||||
assertEquals(LegacyQueries.toInt(type, f), GLStateManager.glGetInteger(pname), "int of float " + name);
|
||||
assertEquals(f != 0.0f, GLStateManager.glGetBoolean(pname), "bool of float " + name);
|
||||
}
|
||||
} else {
|
||||
floats.clear();
|
||||
GLStateManager.glGetFloat(pname, floats);
|
||||
ints.clear();
|
||||
GLStateManager.glGetInteger(pname, ints);
|
||||
doubles.clear();
|
||||
GLStateManager.glGetDouble(pname, doubles);
|
||||
for (int i = 0; i < count; i++) {
|
||||
final float f = floats.get(i);
|
||||
assertEquals(LegacyQueries.toInt(type, f), ints.get(i), "int element " + i + " of " + name);
|
||||
assertEquals((double) f, doubles.get(i), "double element " + i + " of " + name);
|
||||
}
|
||||
assertEquals(floats.get(0), GLStateManager.glGetFloat(pname), "scalar float of " + name);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
GLStateManager.glMatrixMode(GL11.GL_MODELVIEW);
|
||||
GLStateManager.glPopMatrix();
|
||||
GLStateManager.glPointParameterf(GL14.GL_POINT_SIZE_MIN, savedMinSize);
|
||||
GLStateManager.glHint(GL11.GL_FOG_HINT, savedHint);
|
||||
GLStateManager.glShadeModel(savedShade);
|
||||
setEnabled(GL11.GL_FOG, savedFog);
|
||||
setEnabled(GL11.GL_LIGHTING, savedLighting);
|
||||
GLStateManager.glNormal3f(savedNormal.get(0), savedNormal.get(1), savedNormal.get(2));
|
||||
GLStateManager.glColor4f(savedColor.get(0), savedColor.get(1), savedColor.get(2), savedColor.get(3));
|
||||
GLStateManager.glFogf(GL11.GL_FOG_DENSITY, savedDensity);
|
||||
GLStateManager.glFogf(GL11.GL_FOG_END, savedEnd);
|
||||
GLStateManager.glFogf(GL11.GL_FOG_START, savedStart);
|
||||
GLStateManager.glAlphaFunc(savedFunc, savedRef);
|
||||
}
|
||||
}
|
||||
|
||||
private static float driverMaxPointSize() {
|
||||
final FloatBuffer range = BufferUtils.createFloatBuffer(16);
|
||||
GL11.glGetFloat(GL11.GL_POINT_SIZE_RANGE, range);
|
||||
final float smooth = range.get(1);
|
||||
// A rejected query leaves the buffer alone, so the smooth maximum stands in for the missing aliased range
|
||||
GL11.glGetFloat(GL12.GL_ALIASED_POINT_SIZE_RANGE, range);
|
||||
drainErrors();
|
||||
return Math.max(smooth, range.get(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
void edgeFlagIsCompiledIntoDisplayLists() {
|
||||
final int list = GLStateManager.glGenLists(1);
|
||||
try {
|
||||
GLStateManager.glEdgeFlag(true);
|
||||
GLStateManager.glNewList(list, GL11.GL_COMPILE);
|
||||
GLStateManager.glEdgeFlag(false);
|
||||
GLStateManager.glEndList();
|
||||
assertTrue(GLStateManager.glGetBoolean(GL11.GL_EDGE_FLAG), "compiling must not change the live edge flag");
|
||||
GLStateManager.glCallList(list);
|
||||
assertFalse(GLStateManager.glGetBoolean(GL11.GL_EDGE_FLAG));
|
||||
} finally {
|
||||
GLStateManager.glEdgeFlag(true);
|
||||
GLStateManager.glDeleteLists(list, 1);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void textureBitRestoresPerUnitTextureEnables() {
|
||||
final int base = GLStateManager.getAttribDepth();
|
||||
GLStateManager.glActiveTexture(GL13.GL_TEXTURE0);
|
||||
final boolean cube = GLStateManager.glIsEnabled(GL13.GL_TEXTURE_CUBE_MAP);
|
||||
final boolean texture2d = GLStateManager.glIsEnabled(GL11.GL_TEXTURE_2D);
|
||||
try {
|
||||
GLStateManager.glPushAttrib(GL11.GL_TEXTURE_BIT);
|
||||
setEnabled(GL13.GL_TEXTURE_CUBE_MAP, !cube);
|
||||
setEnabled(GL11.GL_TEXTURE_2D, !texture2d);
|
||||
GLStateManager.glPopAttrib();
|
||||
assertEquals(cube, GLStateManager.glIsEnabled(GL13.GL_TEXTURE_CUBE_MAP));
|
||||
assertEquals(texture2d, GLStateManager.glIsEnabled(GL11.GL_TEXTURE_2D));
|
||||
} finally {
|
||||
popAttribTo(base);
|
||||
setEnabled(GL13.GL_TEXTURE_CUBE_MAP, cube);
|
||||
setEnabled(GL11.GL_TEXTURE_2D, texture2d);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void crossTypeQueriesConvert() {
|
||||
final FloatBuffer savedColor = BufferUtils.createFloatBuffer(16);
|
||||
GLStateManager.glGetFloat(GL11.GL_CURRENT_COLOR, savedColor);
|
||||
final int savedFunc = GLStateManager.glGetInteger(GL11.GL_ALPHA_TEST_FUNC);
|
||||
final float savedRef = GLStateManager.glGetFloat(GL11.GL_ALPHA_TEST_REF);
|
||||
final float savedStart = GLStateManager.glGetFloat(GL11.GL_FOG_START);
|
||||
final boolean savedLighting = GLStateManager.glIsEnabled(GL11.GL_LIGHTING);
|
||||
final IntBuffer ints = BufferUtils.createIntBuffer(16);
|
||||
GLStateManager.glMatrixMode(GL11.GL_MODELVIEW);
|
||||
GLStateManager.glPushMatrix();
|
||||
try {
|
||||
GLStateManager.glAlphaFunc(GL11.GL_GREATER, 0.5f);
|
||||
assertEquals(1073741823, GLStateManager.glGetInteger(GL11.GL_ALPHA_TEST_REF));
|
||||
|
||||
assertEquals((float) GLStateManager.glGetInteger(GL11.GL_FOG_MODE), GLStateManager.glGetFloat(GL11.GL_FOG_MODE));
|
||||
|
||||
GLStateManager.glFogf(GL11.GL_FOG_START, -1.5f);
|
||||
assertEquals(-2, GLStateManager.glGetInteger(GL11.GL_FOG_START));
|
||||
|
||||
GLStateManager.glEnable(GL11.GL_LIGHTING);
|
||||
assertEquals(1, GLStateManager.glGetInteger(GL11.GL_LIGHTING));
|
||||
GLStateManager.glDisable(GL11.GL_LIGHTING);
|
||||
assertEquals(0, GLStateManager.glGetInteger(GL11.GL_LIGHTING));
|
||||
|
||||
GLStateManager.glColor4f(1f, 0.5f, 0f, 1f);
|
||||
ints.clear();
|
||||
GLStateManager.glGetInteger(GL11.GL_CURRENT_COLOR, ints);
|
||||
assertEquals(2147483647, ints.get(0));
|
||||
assertEquals(1073741823, ints.get(1));
|
||||
assertEquals(0, ints.get(2));
|
||||
assertEquals(2147483647, ints.get(3));
|
||||
|
||||
GLStateManager.glLoadIdentity();
|
||||
GLStateManager.glGetInteger(GL11.GL_MODELVIEW_MATRIX, ints);
|
||||
assertEquals(2147483647, ints.get(0), "matrix elements scale like normalized floats");
|
||||
assertEquals(0, ints.get(1));
|
||||
assertEquals(2147483647, ints.get(15));
|
||||
assertEquals(2147483647, GLStateManager.glGetInteger(GL11.GL_MODELVIEW_MATRIX));
|
||||
assertEquals(1.0f, GLStateManager.glGetFloat(GL11.GL_MODELVIEW_MATRIX));
|
||||
} finally {
|
||||
GLStateManager.glMatrixMode(GL11.GL_MODELVIEW);
|
||||
GLStateManager.glPopMatrix();
|
||||
GLStateManager.glFogf(GL11.GL_FOG_START, savedStart);
|
||||
GLStateManager.glColor4f(savedColor.get(0), savedColor.get(1), savedColor.get(2), savedColor.get(3));
|
||||
GLStateManager.glAlphaFunc(savedFunc, savedRef);
|
||||
setEnabled(GL11.GL_LIGHTING, savedLighting);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void conversionHelpersMatchMesa() {
|
||||
assertEquals(1, LegacyQueries.lround(0.5f));
|
||||
assertEquals(-1, LegacyQueries.lround(-0.5f));
|
||||
assertEquals(2, LegacyQueries.lround(2.4f));
|
||||
assertEquals(-3, LegacyQueries.lround(-2.6f));
|
||||
assertEquals(Integer.MAX_VALUE, LegacyQueries.floatToInt(1f));
|
||||
assertEquals(0, LegacyQueries.floatToInt(0f));
|
||||
assertEquals(-Integer.MAX_VALUE, LegacyQueries.floatToInt(-1f));
|
||||
}
|
||||
|
||||
@Test
|
||||
void queriesWriteAtBufferPosition() {
|
||||
final IntBuffer ints = BufferUtils.createIntBuffer(32);
|
||||
final FloatBuffer floats = BufferUtils.createFloatBuffer(32);
|
||||
final DoubleBuffer doubles = BufferUtils.createDoubleBuffer(32);
|
||||
final FloatBuffer reference = BufferUtils.createFloatBuffer(32);
|
||||
final FloatBuffer savedColor = BufferUtils.createFloatBuffer(16);
|
||||
GLStateManager.glGetFloat(GL11.GL_CURRENT_COLOR, savedColor);
|
||||
final float savedStart = GLStateManager.glGetFloat(GL11.GL_FOG_START);
|
||||
try {
|
||||
for (int i = 0; i < 32; i++) {
|
||||
ints.put(i, -777);
|
||||
floats.put(i, -777f);
|
||||
doubles.put(i, -777.0);
|
||||
}
|
||||
|
||||
ints.position(4);
|
||||
GLStateManager.glGetInteger(GL11.GL_MATRIX_MODE, ints);
|
||||
assertEquals(GLStateManager.glGetInteger(GL11.GL_MATRIX_MODE), ints.get(4));
|
||||
assertEquals(-777, ints.get(0));
|
||||
|
||||
floats.position(4);
|
||||
GLStateManager.glGetFloat(GL11.GL_MODELVIEW_MATRIX, floats);
|
||||
reference.clear();
|
||||
GLStateManager.glGetFloat(GL11.GL_MODELVIEW_MATRIX, reference);
|
||||
for (int i = 0; i < 16; i++) {
|
||||
assertEquals(reference.get(i), floats.get(4 + i), "modelview element " + i);
|
||||
}
|
||||
assertEquals(-777f, floats.get(0));
|
||||
|
||||
for (int i = 0; i < 32; i++) {
|
||||
ints.put(i, -777);
|
||||
}
|
||||
GLStateManager.glColor4f(0.25f, 0.5f, 0.75f, 1f);
|
||||
ints.position(4);
|
||||
GLStateManager.glGetInteger(GL11.GL_CURRENT_COLOR, ints);
|
||||
assertEquals(536870911, ints.get(4));
|
||||
assertEquals(1073741823, ints.get(5));
|
||||
assertEquals(1610612735, ints.get(6));
|
||||
assertEquals(2147483647, ints.get(7));
|
||||
assertEquals(-777, ints.get(0));
|
||||
|
||||
GLStateManager.glFogf(GL11.GL_FOG_START, 3.5f);
|
||||
doubles.position(4);
|
||||
GLStateManager.glGetDouble(GL11.GL_FOG_START, doubles);
|
||||
assertEquals(3.5, doubles.get(4));
|
||||
assertEquals(-777.0, doubles.get(0));
|
||||
|
||||
for (int i = 0; i < 32; i++) {
|
||||
floats.put(i, -777f);
|
||||
}
|
||||
floats.position(4);
|
||||
GLStateManager.glGetMaterial(GL11.GL_FRONT, GL11.GL_DIFFUSE, floats);
|
||||
reference.clear();
|
||||
GLStateManager.glGetMaterial(GL11.GL_FRONT, GL11.GL_DIFFUSE, reference);
|
||||
for (int i = 0; i < 4; i++) {
|
||||
assertEquals(reference.get(i), floats.get(4 + i), "diffuse element " + i);
|
||||
}
|
||||
assertEquals(-777f, floats.get(0));
|
||||
} finally {
|
||||
GLStateManager.glFogf(GL11.GL_FOG_START, savedStart);
|
||||
GLStateManager.glColor4f(savedColor.get(0), savedColor.get(1), savedColor.get(2), savedColor.get(3));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void hintsRoundTripAndFollowHintBit() {
|
||||
final int base = GLStateManager.getAttribDepth();
|
||||
final int[] saved = new int[HINT_TARGETS.length];
|
||||
for (int i = 0; i < HINT_TARGETS.length; i++) {
|
||||
saved[i] = GLStateManager.glGetInteger(HINT_TARGETS[i]);
|
||||
}
|
||||
try {
|
||||
for (final int target : HINT_TARGETS) {
|
||||
final String name = hex(target);
|
||||
assertEquals(GL11.GL_DONT_CARE, GLStateManager.glGetInteger(target), "default " + name);
|
||||
GLStateManager.glHint(target, GL11.GL_NICEST);
|
||||
assertEquals(GL11.GL_NICEST, GLStateManager.glGetInteger(target), "nicest " + name);
|
||||
GLStateManager.glHint(target, 12345);
|
||||
assertEquals(GL11.GL_NICEST, GLStateManager.glGetInteger(target), "invalid mode " + name);
|
||||
}
|
||||
GLStateManager.glPushAttrib(GL11.GL_HINT_BIT);
|
||||
for (final int target : HINT_TARGETS) {
|
||||
GLStateManager.glHint(target, GL11.GL_FASTEST);
|
||||
assertEquals(GL11.GL_FASTEST, GLStateManager.glGetInteger(target), "fastest " + hex(target));
|
||||
}
|
||||
GLStateManager.glPopAttrib();
|
||||
for (final int target : HINT_TARGETS) {
|
||||
assertEquals(GL11.GL_NICEST, GLStateManager.glGetInteger(target), "restored " + hex(target));
|
||||
}
|
||||
assertEquals(GL11.GL_RENDER, GLStateManager.glGetInteger(GL11.GL_RENDER_MODE));
|
||||
} finally {
|
||||
popAttribTo(base);
|
||||
for (int i = 0; i < HINT_TARGETS.length; i++) {
|
||||
GLStateManager.glHint(HINT_TARGETS[i], saved[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void pointParametersRoundTripAndFollowPointBit() {
|
||||
final int base = GLStateManager.getAttribDepth();
|
||||
final FloatBuffer attenuation = BufferUtils.createFloatBuffer(16);
|
||||
final FloatBuffer savedAttenuation = BufferUtils.createFloatBuffer(16);
|
||||
final float savedMin = GLStateManager.glGetFloat(GL14.GL_POINT_SIZE_MIN);
|
||||
final float savedMax = GLStateManager.glGetFloat(GL14.GL_POINT_SIZE_MAX);
|
||||
final float savedFade = GLStateManager.glGetFloat(GL14.GL_POINT_FADE_THRESHOLD_SIZE);
|
||||
final int savedOrigin = GLStateManager.glGetInteger(GL20.GL_POINT_SPRITE_COORD_ORIGIN);
|
||||
GLStateManager.glGetFloat(GL14.GL_POINT_DISTANCE_ATTENUATION, savedAttenuation);
|
||||
GLStateManager.glPushAttrib(GL11.GL_POINT_BIT);
|
||||
try {
|
||||
assertEquals(0f, savedMin);
|
||||
assertEquals(driverMaxPointSize(), savedMax);
|
||||
assertEquals(1f, savedFade);
|
||||
assertEquals(1f, savedAttenuation.get(0));
|
||||
assertEquals(0f, savedAttenuation.get(1));
|
||||
assertEquals(0f, savedAttenuation.get(2));
|
||||
assertEquals(GL20.GL_UPPER_LEFT, savedOrigin);
|
||||
|
||||
GLStateManager.glPointParameterf(GL14.GL_POINT_SIZE_MIN, 0.5f);
|
||||
GLStateManager.glPointParameterf(GL14.GL_POINT_SIZE_MAX, 2.5f);
|
||||
GLStateManager.glPointParameterf(GL14.GL_POINT_FADE_THRESHOLD_SIZE, 4.5f);
|
||||
assertEquals(0.5f, GLStateManager.glGetFloat(GL14.GL_POINT_SIZE_MIN));
|
||||
assertEquals(2.5f, GLStateManager.glGetFloat(GL14.GL_POINT_SIZE_MAX));
|
||||
assertEquals(4.5f, GLStateManager.glGetFloat(GL14.GL_POINT_FADE_THRESHOLD_SIZE));
|
||||
GLStateManager.glPointParameterf(GL14.GL_POINT_SIZE_MIN, -1f);
|
||||
assertEquals(0.5f, GLStateManager.glGetFloat(GL14.GL_POINT_SIZE_MIN));
|
||||
|
||||
attenuation.put(0, 0.5f).put(1, 0.25f).put(2, 0.125f);
|
||||
attenuation.position(0).limit(3);
|
||||
GLStateManager.glPointParameter(GL14.GL_POINT_DISTANCE_ATTENUATION, attenuation);
|
||||
attenuation.clear();
|
||||
for (int i = 0; i < 16; i++) {
|
||||
attenuation.put(i, -777f);
|
||||
}
|
||||
GLStateManager.glGetFloat(GL14.GL_POINT_DISTANCE_ATTENUATION, attenuation);
|
||||
assertEquals(0.5f, attenuation.get(0));
|
||||
assertEquals(0.25f, attenuation.get(1));
|
||||
assertEquals(0.125f, attenuation.get(2));
|
||||
|
||||
GLStateManager.glPointParameteri(GL20.GL_POINT_SPRITE_COORD_ORIGIN, GL20.GL_LOWER_LEFT);
|
||||
assertEquals(GL20.GL_LOWER_LEFT, GLStateManager.glGetInteger(GL20.GL_POINT_SPRITE_COORD_ORIGIN));
|
||||
|
||||
GLStateManager.glPushAttrib(GL11.GL_POINT_BIT);
|
||||
GLStateManager.glPointParameterf(GL14.GL_POINT_SIZE_MIN, 1f);
|
||||
GLStateManager.glPointParameterf(GL14.GL_POINT_SIZE_MAX, 3f);
|
||||
GLStateManager.glPointParameterf(GL14.GL_POINT_FADE_THRESHOLD_SIZE, 2f);
|
||||
attenuation.put(0, 1f).put(1, 1f).put(2, 1f);
|
||||
attenuation.position(0).limit(3);
|
||||
GLStateManager.glPointParameter(GL14.GL_POINT_DISTANCE_ATTENUATION, attenuation);
|
||||
GLStateManager.glPointParameteri(GL20.GL_POINT_SPRITE_COORD_ORIGIN, GL20.GL_UPPER_LEFT);
|
||||
assertEquals(1f, GLStateManager.glGetFloat(GL14.GL_POINT_SIZE_MIN));
|
||||
assertEquals(GL20.GL_UPPER_LEFT, GLStateManager.glGetInteger(GL20.GL_POINT_SPRITE_COORD_ORIGIN));
|
||||
GLStateManager.glPointParameterf(GL14.GL_POINT_SIZE_MIN, Float.NaN);
|
||||
assertTrue(Float.isNaN(GLStateManager.glGetFloat(GL14.GL_POINT_SIZE_MIN)));
|
||||
GLStateManager.glPopAttrib();
|
||||
|
||||
assertEquals(0.5f, GLStateManager.glGetFloat(GL14.GL_POINT_SIZE_MIN));
|
||||
assertEquals(2.5f, GLStateManager.glGetFloat(GL14.GL_POINT_SIZE_MAX));
|
||||
assertEquals(4.5f, GLStateManager.glGetFloat(GL14.GL_POINT_FADE_THRESHOLD_SIZE));
|
||||
assertEquals(GL20.GL_LOWER_LEFT, GLStateManager.glGetInteger(GL20.GL_POINT_SPRITE_COORD_ORIGIN));
|
||||
attenuation.clear();
|
||||
GLStateManager.glGetFloat(GL14.GL_POINT_DISTANCE_ATTENUATION, attenuation);
|
||||
assertEquals(0.5f, attenuation.get(0));
|
||||
assertEquals(0.25f, attenuation.get(1));
|
||||
assertEquals(0.125f, attenuation.get(2));
|
||||
} finally {
|
||||
popAttribTo(base);
|
||||
assertEquals(savedMax, GLStateManager.glGetFloat(GL14.GL_POINT_SIZE_MAX));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void cacheOnlyEnablesRoundTrip() {
|
||||
final int base = GLStateManager.getAttribDepth();
|
||||
final boolean savedSprite = GLStateManager.glIsEnabled(GL20.GL_POINT_SPRITE);
|
||||
final boolean savedTwoSide = GLStateManager.glIsEnabled(GL20.GL_VERTEX_PROGRAM_TWO_SIDE);
|
||||
final boolean savedEdge = GLStateManager.glGetBoolean(GL11.GL_EDGE_FLAG);
|
||||
GLStateManager.glActiveTexture(GL13.GL_TEXTURE0);
|
||||
final boolean savedCube0 = GLStateManager.glIsEnabled(GL13.GL_TEXTURE_CUBE_MAP);
|
||||
GLStateManager.glActiveTexture(GL13.GL_TEXTURE1);
|
||||
final boolean savedCube1 = GLStateManager.glIsEnabled(GL13.GL_TEXTURE_CUBE_MAP);
|
||||
GLStateManager.glActiveTexture(GL13.GL_TEXTURE0);
|
||||
try {
|
||||
assertEnableRoundTrip(GL20.GL_POINT_SPRITE, false);
|
||||
assertEnableRoundTrip(GL20.GL_VERTEX_PROGRAM_TWO_SIDE, false);
|
||||
assertEnableRoundTrip(GL13.GL_TEXTURE_CUBE_MAP, false);
|
||||
|
||||
GLStateManager.glPushAttrib(GL11.GL_ENABLE_BIT);
|
||||
GLStateManager.glEnable(GL20.GL_POINT_SPRITE);
|
||||
GLStateManager.glEnable(GL20.GL_VERTEX_PROGRAM_TWO_SIDE);
|
||||
GLStateManager.glEnable(GL13.GL_TEXTURE_CUBE_MAP);
|
||||
assertTrue(GLStateManager.glIsEnabled(GL20.GL_POINT_SPRITE));
|
||||
assertTrue(GLStateManager.glIsEnabled(GL20.GL_VERTEX_PROGRAM_TWO_SIDE));
|
||||
assertTrue(GLStateManager.glIsEnabled(GL13.GL_TEXTURE_CUBE_MAP));
|
||||
GLStateManager.glPopAttrib();
|
||||
assertFalse(GLStateManager.glIsEnabled(GL20.GL_POINT_SPRITE));
|
||||
assertFalse(GLStateManager.glIsEnabled(GL20.GL_VERTEX_PROGRAM_TWO_SIDE));
|
||||
assertFalse(GLStateManager.glIsEnabled(GL13.GL_TEXTURE_CUBE_MAP));
|
||||
|
||||
GLStateManager.glActiveTexture(GL13.GL_TEXTURE1);
|
||||
GLStateManager.glDisable(GL13.GL_TEXTURE_CUBE_MAP);
|
||||
GLStateManager.glActiveTexture(GL13.GL_TEXTURE0);
|
||||
GLStateManager.glEnable(GL13.GL_TEXTURE_CUBE_MAP);
|
||||
assertTrue(GLStateManager.glIsEnabled(GL13.GL_TEXTURE_CUBE_MAP));
|
||||
GLStateManager.glActiveTexture(GL13.GL_TEXTURE1);
|
||||
assertFalse(GLStateManager.glIsEnabled(GL13.GL_TEXTURE_CUBE_MAP));
|
||||
assertFalse(GLStateManager.glGetBoolean(GL13.GL_TEXTURE_CUBE_MAP));
|
||||
GLStateManager.glActiveTexture(GL13.GL_TEXTURE0);
|
||||
assertTrue(GLStateManager.glGetBoolean(GL13.GL_TEXTURE_CUBE_MAP));
|
||||
GLStateManager.glDisable(GL13.GL_TEXTURE_CUBE_MAP);
|
||||
|
||||
assertTrue(savedEdge);
|
||||
GLStateManager.glEdgeFlag(false);
|
||||
assertFalse(GLStateManager.glGetBoolean(GL11.GL_EDGE_FLAG));
|
||||
GLStateManager.glPushAttrib(GL11.GL_CURRENT_BIT);
|
||||
GLStateManager.glEdgeFlag(true);
|
||||
assertTrue(GLStateManager.glGetBoolean(GL11.GL_EDGE_FLAG));
|
||||
GLStateManager.glPopAttrib();
|
||||
assertFalse(GLStateManager.glGetBoolean(GL11.GL_EDGE_FLAG));
|
||||
} finally {
|
||||
popAttribTo(base);
|
||||
GLStateManager.glEdgeFlag(savedEdge);
|
||||
setEnabled(GL20.GL_POINT_SPRITE, savedSprite);
|
||||
setEnabled(GL20.GL_VERTEX_PROGRAM_TWO_SIDE, savedTwoSide);
|
||||
GLStateManager.glActiveTexture(GL13.GL_TEXTURE1);
|
||||
setEnabled(GL13.GL_TEXTURE_CUBE_MAP, savedCube1);
|
||||
GLStateManager.glActiveTexture(GL13.GL_TEXTURE0);
|
||||
setEnabled(GL13.GL_TEXTURE_CUBE_MAP, savedCube0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,10 +4,7 @@ import org.junit.jupiter.api.Test;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL12;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.FloatBuffer;
|
||||
|
||||
import static com.gtnewhorizons.angelica.glsm.GlTestSupport.floats;
|
||||
import static com.gtnewhorizons.angelica.util.GLSMUtil.verifyLightState;
|
||||
import static com.gtnewhorizons.angelica.util.GLSMUtil.verifyMaterialState;
|
||||
import static com.gtnewhorizons.angelica.util.GLSMUtil.verifyState;
|
||||
@@ -15,9 +12,6 @@ import static com.gtnewhorizons.angelica.util.GLSMUtil.verifyState;
|
||||
@GLCompatTest
|
||||
public class GLSM_Lighting_UnitTest {
|
||||
|
||||
static final FloatBuffer f4b = ByteBuffer.allocateDirect(4 << 2).order(ByteOrder.nativeOrder()).asFloatBuffer();
|
||||
static final FloatBuffer f3b = ByteBuffer.allocateDirect(3 << 2).order(ByteOrder.nativeOrder()).asFloatBuffer();
|
||||
|
||||
@Test
|
||||
void testLightEnablement() {
|
||||
verifyState(GL11.GL_LIGHT0, false, "GL_LIGHT0 Initial State");
|
||||
@@ -46,12 +40,10 @@ public class GLSM_Lighting_UnitTest {
|
||||
verifyLightState(GL11.GL_LIGHT1, GL11.GL_SPECULAR, new float[]{0F, 0F, 0F, 1F}, "GL_LIGHT1 Initial Specular");
|
||||
verifyLightState(GL11.GL_LIGHT1, GL11.GL_POSITION, new float[]{0F, 0F, 1F, 0F}, "GL_LIGHT1 Initial Position");
|
||||
|
||||
newf4b(0.25F, 0.5F, 0.25F, 0.5F);
|
||||
GLStateManager.glLight(GL11.GL_LIGHT0, GL11.GL_AMBIENT, f4b);
|
||||
GLStateManager.glLight(GL11.GL_LIGHT0, GL11.GL_AMBIENT, floats(0.25F, 0.5F, 0.25F, 0.5F));
|
||||
verifyLightState(GL11.GL_LIGHT0, GL11.GL_AMBIENT, new float[]{0.25F, 0.5F, 0.25F, 0.5F}, "GL_LIGHT0 Ambient Changed State");
|
||||
GLStateManager.glPushAttrib(GL11.GL_LIGHTING_BIT);
|
||||
newf4b(0.3F, 0.4F, 0.5F, 0.6F);
|
||||
GLStateManager.glLight(GL11.GL_LIGHT0, GL11.GL_AMBIENT, f4b);
|
||||
GLStateManager.glLight(GL11.GL_LIGHT0, GL11.GL_AMBIENT, floats(0.3F, 0.4F, 0.5F, 0.6F));
|
||||
verifyLightState(GL11.GL_LIGHT0, GL11.GL_AMBIENT, new float[]{0.3F, 0.4F, 0.5F, 0.6F}, "GL_LIGHT0 attrib push state changed check");
|
||||
GLStateManager.glPopAttrib();
|
||||
verifyLightState(GL11.GL_LIGHT0, GL11.GL_AMBIENT, new float[]{0.25F, 0.5F, 0.25F, 0.5F}, "GL_LIGHT0 attrib pop state check");
|
||||
@@ -64,33 +56,27 @@ public class GLSM_Lighting_UnitTest {
|
||||
GLStateManager.glPushMatrix();
|
||||
GLStateManager.glTranslatef(25.0F, 25.0F, 25.0F);
|
||||
GLStateManager.glRotatef(35.0F, 10.0F, 15.0F, 20.0F);
|
||||
newf4b(0.25F, 0.5F, 0.25F, 0.0F);
|
||||
GLStateManager.glLight(GL11.GL_LIGHT0, GL11.GL_POSITION, f4b);
|
||||
GLStateManager.glLight(GL11.GL_LIGHT0, GL11.GL_POSITION, floats(0.25F, 0.5F, 0.25F, 0.0F));
|
||||
verifyLightState(GL11.GL_LIGHT0, GL11.GL_POSITION, new float[]{0.1090F, 0.5189F, 0.3062F, 0.0F}, "GL_LIGHT0 Position Changed State");
|
||||
GLStateManager.glPushAttrib(GL11.GL_LIGHTING_BIT);
|
||||
newf4b(0.3F, 0.4F, 0.5F, 0.0F);
|
||||
GLStateManager.glLight(GL11.GL_LIGHT0, GL11.GL_POSITION, f4b);
|
||||
GLStateManager.glLight(GL11.GL_LIGHT0, GL11.GL_POSITION, floats(0.3F, 0.4F, 0.5F, 0.0F));
|
||||
verifyLightState(GL11.GL_LIGHT0, GL11.GL_POSITION, new float[]{0.2824F, 0.4200F, 0.4937F, 0.0F}, "GL_LIGHT0 attrib push state changed check");
|
||||
GLStateManager.glPopAttrib();
|
||||
verifyLightState(GL11.GL_LIGHT0, GL11.GL_POSITION, new float[]{0.1090F, 0.5189F, 0.3062F, 0.0F}, "GL_LIGHT0 attrib pop state check");
|
||||
GLStateManager.glPopMatrix();
|
||||
|
||||
newf4b(0.25F, 0.5F, 0.25F, 0.5F);
|
||||
GLStateManager.glLight(GL11.GL_LIGHT0, GL11.GL_DIFFUSE, f4b);
|
||||
GLStateManager.glLight(GL11.GL_LIGHT0, GL11.GL_DIFFUSE, floats(0.25F, 0.5F, 0.25F, 0.5F));
|
||||
verifyLightState(GL11.GL_LIGHT0, GL11.GL_DIFFUSE, new float[]{0.25F, 0.5F, 0.25F, 0.5F}, "GL_LIGHT0 Diffuse Changed State");
|
||||
GLStateManager.glPushAttrib(GL11.GL_LIGHTING_BIT);
|
||||
newf4b(0.3F, 0.4F, 0.5F, 0.6F);
|
||||
GLStateManager.glLight(GL11.GL_LIGHT0, GL11.GL_DIFFUSE, f4b);
|
||||
GLStateManager.glLight(GL11.GL_LIGHT0, GL11.GL_DIFFUSE, floats(0.3F, 0.4F, 0.5F, 0.6F));
|
||||
verifyLightState(GL11.GL_LIGHT0, GL11.GL_DIFFUSE, new float[]{0.3F, 0.4F, 0.5F, 0.6F}, "GL_LIGHT0 attrib push state changed check");
|
||||
GLStateManager.glPopAttrib();
|
||||
verifyLightState(GL11.GL_LIGHT0, GL11.GL_DIFFUSE, new float[]{0.25F, 0.5F, 0.25F, 0.5F}, "GL_LIGHT0 attrib pop state check");
|
||||
|
||||
newf4b(0.25F, 0.5F, 0.25F, 0.5F);
|
||||
GLStateManager.glLight(GL11.GL_LIGHT0, GL11.GL_SPECULAR, f4b);
|
||||
GLStateManager.glLight(GL11.GL_LIGHT0, GL11.GL_SPECULAR, floats(0.25F, 0.5F, 0.25F, 0.5F));
|
||||
verifyLightState(GL11.GL_LIGHT0, GL11.GL_SPECULAR, new float[]{0.25F, 0.5F, 0.25F, 0.5F}, "GL_LIGHT0 Specular Changed State");
|
||||
GLStateManager.glPushAttrib(GL11.GL_LIGHTING_BIT);
|
||||
newf4b(0.3F, 0.4F, 0.5F, 0.6F);
|
||||
GLStateManager.glLight(GL11.GL_LIGHT0, GL11.GL_SPECULAR, f4b);
|
||||
GLStateManager.glLight(GL11.GL_LIGHT0, GL11.GL_SPECULAR, floats(0.3F, 0.4F, 0.5F, 0.6F));
|
||||
verifyLightState(GL11.GL_LIGHT0, GL11.GL_SPECULAR, new float[]{0.3F, 0.4F, 0.5F, 0.6F}, "GL_LIGHT0 attrib push state changed check");
|
||||
GLStateManager.glPopAttrib();
|
||||
verifyLightState(GL11.GL_LIGHT0, GL11.GL_SPECULAR, new float[]{0.25F, 0.5F, 0.25F, 0.5F}, "GL_LIGHT0 attrib pop state check");
|
||||
@@ -99,12 +85,10 @@ public class GLSM_Lighting_UnitTest {
|
||||
GLStateManager.glPushMatrix();
|
||||
GLStateManager.glTranslatef(25.0F, 25.0F, 25.0F);
|
||||
GLStateManager.glRotatef(35.0F, 10.0F, 15.0F, 20.0F);
|
||||
newf4b(0.25F, 0.5F, 0.25F, 0.0F);
|
||||
GLStateManager.glLight(GL11.GL_LIGHT0, GL11.GL_SPOT_DIRECTION, f4b);
|
||||
GLStateManager.glLight(GL11.GL_LIGHT0, GL11.GL_SPOT_DIRECTION, floats(0.25F, 0.5F, 0.25F, 0.0F));
|
||||
verifyLightState(GL11.GL_LIGHT0, GL11.GL_SPOT_DIRECTION, new float[]{0.1090F, 0.5189F, 0.3062F}, "GL_LIGHT0 Spot Direction Changed State");
|
||||
GLStateManager.glPushAttrib(GL11.GL_LIGHTING_BIT);
|
||||
newf4b(0.3F, 0.4F, 0.5F, 0.0F);
|
||||
GLStateManager.glLight(GL11.GL_LIGHT0, GL11.GL_SPOT_DIRECTION, f4b);
|
||||
GLStateManager.glLight(GL11.GL_LIGHT0, GL11.GL_SPOT_DIRECTION, floats(0.3F, 0.4F, 0.5F, 0.0F));
|
||||
verifyLightState(GL11.GL_LIGHT0, GL11.GL_SPOT_DIRECTION, new float[]{0.2824F, 0.4200F, 0.4937F}, "GL_LIGHT0 attrib push state changed check");
|
||||
GLStateManager.glPopAttrib();
|
||||
verifyLightState(GL11.GL_LIGHT0, GL11.GL_SPOT_DIRECTION, new float[]{0.1090F, 0.5189F, 0.3062F}, "GL_LIGHT0 attrib pop state check");
|
||||
@@ -157,8 +141,7 @@ public class GLSM_Lighting_UnitTest {
|
||||
void testLightModel() {
|
||||
verifyState(GL11.GL_LIGHT_MODEL_AMBIENT, new float[]{0.2F, 0.2F, 0.2F, 1.0F}, "GL_LIGHT_MODEL_AMBIENT initial state");
|
||||
GLStateManager.glPushAttrib(GL11.GL_LIGHTING_BIT);
|
||||
newf4b(0.8F, 0.6F, 0.4F, 0.2F);
|
||||
GLStateManager.glLightModel(GL11.GL_LIGHT_MODEL_AMBIENT, f4b);
|
||||
GLStateManager.glLightModel(GL11.GL_LIGHT_MODEL_AMBIENT, floats(0.8F, 0.6F, 0.4F, 0.2F));
|
||||
verifyState(GL11.GL_LIGHT_MODEL_AMBIENT, new float[]{0.8F, 0.6F, 0.4F, 0.2F}, "GL_LIGHT_MODEL_AMBIENT changed state");
|
||||
GLStateManager.glPopAttrib();
|
||||
verifyState(GL11.GL_LIGHT_MODEL_AMBIENT, new float[]{0.2F, 0.2F, 0.2F, 1.0F});
|
||||
@@ -235,16 +218,14 @@ public class GLSM_Lighting_UnitTest {
|
||||
void testMaterial() {
|
||||
verifyMaterialState(GL11.GL_FRONT, GL11.GL_AMBIENT, new float[]{0.2F, 0.2F, 0.2F, 1.0F}, "");
|
||||
GLStateManager.glPushAttrib(GL11.GL_LIGHTING_BIT);
|
||||
newf4b(0.8F, 0.6F, 0.4F, 0.2F);
|
||||
GLStateManager.glMaterial(GL11.GL_FRONT, GL11.GL_AMBIENT, f4b);
|
||||
GLStateManager.glMaterial(GL11.GL_FRONT, GL11.GL_AMBIENT, floats(0.8F, 0.6F, 0.4F, 0.2F));
|
||||
verifyMaterialState(GL11.GL_FRONT, GL11.GL_AMBIENT, new float[]{0.8F, 0.6F, 0.4F, 0.2F}, "");
|
||||
GLStateManager.glPopAttrib();
|
||||
verifyMaterialState(GL11.GL_FRONT, GL11.GL_AMBIENT, new float[]{0.2F, 0.2F, 0.2F, 1.0F}, "");
|
||||
|
||||
verifyMaterialState(GL11.GL_BACK, GL11.GL_AMBIENT, new float[]{0.2F, 0.2F, 0.2F, 1.0F}, "");
|
||||
GLStateManager.glPushAttrib(GL11.GL_LIGHTING_BIT);
|
||||
newf4b(0.8F, 0.6F, 0.4F, 0.2F);
|
||||
GLStateManager.glMaterial(GL11.GL_FRONT_AND_BACK, GL11.GL_AMBIENT, f4b);
|
||||
GLStateManager.glMaterial(GL11.GL_FRONT_AND_BACK, GL11.GL_AMBIENT, floats(0.8F, 0.6F, 0.4F, 0.2F));
|
||||
verifyMaterialState(GL11.GL_FRONT, GL11.GL_AMBIENT, new float[]{0.8F, 0.6F, 0.4F, 0.2F}, "");
|
||||
verifyMaterialState(GL11.GL_BACK, GL11.GL_AMBIENT, new float[]{0.8F, 0.6F, 0.4F, 0.2F}, "");
|
||||
GLStateManager.glPopAttrib();
|
||||
@@ -254,8 +235,7 @@ public class GLSM_Lighting_UnitTest {
|
||||
verifyMaterialState(GL11.GL_FRONT, GL11.GL_DIFFUSE, new float[]{0.8F, 0.8F, 0.8F, 1.0F}, "");
|
||||
verifyMaterialState(GL11.GL_BACK, GL11.GL_DIFFUSE, new float[]{0.8F, 0.8F, 0.8F, 1.0F}, "");
|
||||
GLStateManager.glPushAttrib(GL11.GL_LIGHTING_BIT);
|
||||
newf4b(0.8F, 0.6F, 0.4F, 0.2F);
|
||||
GLStateManager.glMaterial(GL11.GL_FRONT_AND_BACK, GL11.GL_AMBIENT_AND_DIFFUSE, f4b);
|
||||
GLStateManager.glMaterial(GL11.GL_FRONT_AND_BACK, GL11.GL_AMBIENT_AND_DIFFUSE, floats(0.8F, 0.6F, 0.4F, 0.2F));
|
||||
verifyMaterialState(GL11.GL_FRONT, GL11.GL_AMBIENT, new float[]{0.8F, 0.6F, 0.4F, 0.2F}, "");
|
||||
verifyMaterialState(GL11.GL_BACK, GL11.GL_AMBIENT, new float[]{0.8F, 0.6F, 0.4F, 0.2F}, "");
|
||||
verifyMaterialState(GL11.GL_FRONT, GL11.GL_DIFFUSE, new float[]{0.8F, 0.6F, 0.4F, 0.2F}, "");
|
||||
@@ -268,16 +248,14 @@ public class GLSM_Lighting_UnitTest {
|
||||
|
||||
verifyMaterialState(GL11.GL_BACK, GL11.GL_SPECULAR, new float[]{0.0F, 0.0F, 0.0F, 1.0F}, "");
|
||||
GLStateManager.glPushAttrib(GL11.GL_LIGHTING_BIT);
|
||||
newf4b(0.8F, 0.6F, 0.4F, 0.2F);
|
||||
GLStateManager.glMaterial(GL11.GL_BACK, GL11.GL_SPECULAR, f4b);
|
||||
GLStateManager.glMaterial(GL11.GL_BACK, GL11.GL_SPECULAR, floats(0.8F, 0.6F, 0.4F, 0.2F));
|
||||
verifyMaterialState(GL11.GL_BACK, GL11.GL_SPECULAR, new float[]{0.8F, 0.6F, 0.4F, 0.2F}, "");
|
||||
GLStateManager.glPopAttrib();
|
||||
verifyMaterialState(GL11.GL_BACK, GL11.GL_SPECULAR, new float[]{0.0F, 0.0F, 0.0F, 1.0F}, "");
|
||||
|
||||
verifyMaterialState(GL11.GL_BACK, GL11.GL_EMISSION, new float[]{0.0F, 0.0F, 0.0F, 1.0F}, "");
|
||||
GLStateManager.glPushAttrib(GL11.GL_LIGHTING_BIT);
|
||||
newf4b(0.8F, 0.6F, 0.4F, 0.2F);
|
||||
GLStateManager.glMaterial(GL11.GL_BACK, GL11.GL_EMISSION, f4b);
|
||||
GLStateManager.glMaterial(GL11.GL_BACK, GL11.GL_EMISSION, floats(0.8F, 0.6F, 0.4F, 0.2F));
|
||||
verifyMaterialState(GL11.GL_BACK, GL11.GL_EMISSION, new float[]{0.8F, 0.6F, 0.4F, 0.2F}, "");
|
||||
GLStateManager.glPopAttrib();
|
||||
verifyMaterialState(GL11.GL_BACK, GL11.GL_EMISSION, new float[]{0.0F, 0.0F, 0.0F, 1.0F}, "");
|
||||
@@ -291,8 +269,7 @@ public class GLSM_Lighting_UnitTest {
|
||||
|
||||
verifyMaterialState(GL11.GL_FRONT, GL11.GL_COLOR_INDEXES, new float[]{0.0F, 1.0F, 1.0F}, "");
|
||||
GLStateManager.glPushAttrib(GL11.GL_LIGHTING_BIT);
|
||||
newf4b(0.8F, 0.6F, 0.4F, 0.0F);
|
||||
GLStateManager.glMaterial(GL11.GL_FRONT, GL11.GL_COLOR_INDEXES, f4b);
|
||||
GLStateManager.glMaterial(GL11.GL_FRONT, GL11.GL_COLOR_INDEXES, floats(0.8F, 0.6F, 0.4F, 0.0F));
|
||||
if (GLStateManager.vendorIsNVIDIA()) {
|
||||
verifyMaterialState(GL11.GL_FRONT, GL11.GL_COLOR_INDEXES, new float[]{0.8F, 0.4F, 0.6F}, "");
|
||||
} else {
|
||||
@@ -302,16 +279,4 @@ public class GLSM_Lighting_UnitTest {
|
||||
verifyMaterialState(GL11.GL_FRONT, GL11.GL_COLOR_INDEXES, new float[]{0.0F, 1.0F, 1.0F}, "");
|
||||
|
||||
}
|
||||
|
||||
static void newf4b(float x, float y, float z, float w) {
|
||||
f4b.clear();
|
||||
f4b.put(x).put(y).put(z).put(w);
|
||||
f4b.flip();
|
||||
}
|
||||
|
||||
static void newf3b(float x, float y, float z) {
|
||||
f3b.clear();
|
||||
f3b.put(x).put(y).put(z);
|
||||
f3b.flip();
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,9 @@ import com.gtnewhorizons.angelica.glsm.states.ViewportState;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
import org.lwjgl.BufferUtils;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL15;
|
||||
@@ -12,6 +15,7 @@ import org.lwjgl.opengl.GL15;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.util.function.IntPredicate;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
@@ -72,7 +76,6 @@ public class GLSM_LineStipple_GLTest {
|
||||
GLStateManager.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
|
||||
if (vbo != 0) GLStateManager.glDeleteBuffers(vbo);
|
||||
if (vao != 0) GLStateManager.glDeleteVertexArrays(vao);
|
||||
while (GL11.glGetError() != GL11.GL_NO_ERROR) {}
|
||||
}
|
||||
|
||||
private boolean[] renderLine(float x0, float x1) {
|
||||
@@ -117,35 +120,29 @@ public class GLSM_LineStipple_GLTest {
|
||||
GLStateManager.glLineStipple(factor, (short) pattern);
|
||||
}
|
||||
|
||||
@Test
|
||||
void solidPatternCoversEveryPixel() {
|
||||
stipple(1, 0xFFFF);
|
||||
assertArrayEquals(expected(i -> true), renderLine(0f, W));
|
||||
static Stream<Arguments> patterns() {
|
||||
return Stream.of(
|
||||
pattern("solid pattern covers every pixel", true, 1, 0xFFFF, i -> true),
|
||||
pattern("empty pattern covers nothing", true, 1, 0x0000, i -> false),
|
||||
pattern("alternating pattern dashes every other pixel", true, 1, 0xAAAA, i -> (i & 1) == 1),
|
||||
pattern("factor stretches each bit across that many pixels", true, 2, 0xAAAA, i -> ((i / 2) & 1) == 1),
|
||||
pattern("disabled stipple covers every pixel", false, 1, 0xAAAA, i -> true));
|
||||
}
|
||||
|
||||
@Test
|
||||
void emptyPatternCoversNothing() {
|
||||
stipple(1, 0x0000);
|
||||
assertArrayEquals(expected(i -> false), renderLine(0f, W));
|
||||
private static Arguments pattern(String name, boolean enabled, int factor, int pattern, IntPredicate on) {
|
||||
return Arguments.of(name, enabled, factor, pattern, on);
|
||||
}
|
||||
|
||||
@Test
|
||||
void alternatingPatternDashesEveryOtherPixel() {
|
||||
stipple(1, 0xAAAA);
|
||||
assertArrayEquals(expected(i -> (i & 1) == 1), renderLine(0f, W));
|
||||
}
|
||||
|
||||
@Test
|
||||
void factorStretchesEachBitAcrossThatManyPixels() {
|
||||
stipple(2, 0xAAAA);
|
||||
assertArrayEquals(expected(i -> ((i / 2) & 1) == 1), renderLine(0f, W));
|
||||
}
|
||||
|
||||
@Test
|
||||
void disabledStippleCoversEveryPixel() {
|
||||
GLStateManager.glLineStipple(1, (short) 0xAAAA);
|
||||
GLStateManager.glDisable(GL11.GL_LINE_STIPPLE);
|
||||
assertArrayEquals(expected(i -> true), renderLine(0f, W));
|
||||
@ParameterizedTest(name = "{0}")
|
||||
@MethodSource("patterns")
|
||||
void patternSelectsTheCoveredPixels(String name, boolean enabled, int factor, int pattern, IntPredicate on) {
|
||||
GLStateManager.glLineStipple(factor, (short) pattern);
|
||||
if (enabled) {
|
||||
GLStateManager.glEnable(GL11.GL_LINE_STIPPLE);
|
||||
} else {
|
||||
GLStateManager.glDisable(GL11.GL_LINE_STIPPLE);
|
||||
}
|
||||
assertArrayEquals(expected(on), renderLine(0f, W));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.gtnewhorizons.angelica.glsm;
|
||||
|
||||
import com.gtnewhorizons.angelica.glsm.testutil.TestThreads;
|
||||
import org.joml.Matrix4f;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
@@ -18,23 +19,14 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
@GLCoreTest
|
||||
public class GLSM_PerThread_UnitTest {
|
||||
|
||||
private static void runThreaded(int n, ThreadBody body) throws Throwable {
|
||||
private static void runThreaded(int n, ThreadBody body) throws InterruptedException {
|
||||
final CyclicBarrier barrier = new CyclicBarrier(n);
|
||||
final Throwable[] errs = new Throwable[n];
|
||||
final Thread[] ts = new Thread[n];
|
||||
final TestThreads.Worker[] workers = new TestThreads.Worker[n];
|
||||
for (int i = 0; i < n; i++) {
|
||||
final int tid = i;
|
||||
ts[i] = new Thread(() -> {
|
||||
try {
|
||||
body.run(tid, barrier);
|
||||
} catch (Throwable t) {
|
||||
errs[tid] = t;
|
||||
}
|
||||
}, "glsm-perthread-" + i);
|
||||
workers[i] = TestThreads.start("glsm-perthread-" + i, () -> body.run(tid, barrier));
|
||||
}
|
||||
for (Thread t : ts) t.start();
|
||||
for (Thread t : ts) t.join();
|
||||
for (int i = 0; i < n; i++) if (errs[i] != null) throw errs[i];
|
||||
for (TestThreads.Worker worker : workers) worker.join();
|
||||
}
|
||||
|
||||
interface ThreadBody {
|
||||
|
||||
@@ -13,6 +13,7 @@ import org.lwjgl.opengl.GL20;
|
||||
|
||||
import java.nio.FloatBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static com.gtnewhorizons.angelica.util.GLSMUtil.resetGLState;
|
||||
import static com.gtnewhorizons.angelica.util.GLSMUtil.verifyIsEnabled;
|
||||
@@ -49,6 +50,24 @@ class GLSM_PushPop_UnitTest {
|
||||
public static final float[] FLOAT_ARRAY_3_1 = { 1f, 1f, 1f };
|
||||
public static final float[] FLOAT_ARRAY_GL_SPOT_DIRECTION_DEFAULT = { 0f, 0f, -1f };
|
||||
|
||||
private static void toggleAndVerify(List<GLBit> bits) {
|
||||
for (GLBit bit : bits) {
|
||||
verifyState(bit.glEnum(), bit.initial(), bit.name() + " Initial State");
|
||||
if (bit.initial()) {
|
||||
GLStateManager.glDisable(bit.glEnum());
|
||||
} else {
|
||||
GLStateManager.glEnable(bit.glEnum());
|
||||
}
|
||||
verifyState(bit.glEnum(), !bit.initial(), bit.name() + " Toggle State");
|
||||
}
|
||||
}
|
||||
|
||||
private static void verifyReset(List<GLBit> bits) {
|
||||
for (GLBit bit : bits) {
|
||||
verifyState(bit.glEnum(), bit.initial(), bit.name() + " Reset State");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testPushPopColorBufferBit() {
|
||||
|
||||
@@ -241,19 +260,11 @@ class GLSM_PushPop_UnitTest {
|
||||
bits.add(new GLBit(GL11.GL_TEXTURE_GEN_Q, "Texture Gen Q", false));
|
||||
|
||||
GLStateManager.glPushAttrib(GL11.GL_ENABLE_BIT);
|
||||
bits.forEach(bit -> {
|
||||
verifyState(bit.glEnum(), bit.initial(), bit.name() + " Initial State");
|
||||
if(bit.initial()) {
|
||||
GLStateManager.glDisable(bit.glEnum());
|
||||
} else {
|
||||
GLStateManager.glEnable(bit.glEnum());
|
||||
}
|
||||
verifyState(bit.glEnum(), !bit.initial(), bit.name() + " Toggle State");
|
||||
});
|
||||
toggleAndVerify(bits);
|
||||
|
||||
GLStateManager.glPopAttrib();
|
||||
|
||||
bits.forEach(bit -> verifyState(bit.glEnum(), bit.initial(), bit.name() + " Reset State"));
|
||||
verifyReset(bits);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -329,15 +340,7 @@ class GLSM_PushPop_UnitTest {
|
||||
verifyState(GL11.GL_SHADE_MODEL, GL11.GL_FLAT, "Shade Model");
|
||||
|
||||
|
||||
bits.forEach(bit -> {
|
||||
verifyState(bit.glEnum(), bit.initial(), bit.name() + " Initial State");
|
||||
if(bit.initial()) {
|
||||
GLStateManager.glDisable(bit.glEnum());
|
||||
} else {
|
||||
GLStateManager.glEnable(bit.glEnum());
|
||||
}
|
||||
verifyState(bit.glEnum(), !bit.initial(), bit.name() + " Toggle State");
|
||||
});
|
||||
toggleAndVerify(bits);
|
||||
|
||||
GLStateManager.glPopAttrib();
|
||||
verifyState(GL11.GL_COLOR_MATERIAL_FACE, GL11.GL_FRONT_AND_BACK, "Color Material Face - Reset");
|
||||
@@ -353,7 +356,7 @@ class GLSM_PushPop_UnitTest {
|
||||
verifyLightState(GL11.GL_LIGHT0, GL11.GL_SPOT_DIRECTION, FLOAT_ARRAY_GL_SPOT_DIRECTION_DEFAULT, "Light Spot Direction - Reset");
|
||||
verifyState(GL11.GL_SHADE_MODEL, GL11.GL_SMOOTH, "Shade Model - Reset");
|
||||
|
||||
bits.forEach(bit -> verifyState(bit.glEnum(), bit.initial(), bit.name() + " Reset State"));
|
||||
verifyReset(bits);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -388,15 +391,7 @@ class GLSM_PushPop_UnitTest {
|
||||
verifyState(GL13.GL_ACTIVE_TEXTURE, GL13.GL_TEXTURE1, "Active Texture");
|
||||
verifyState(GL11.GL_TEXTURE_BINDING_2D, tex2, "Texture Binding - Unit 1");
|
||||
|
||||
bits.forEach(bit -> {
|
||||
verifyState(bit.glEnum(), bit.initial(), bit.name() + " Initial State");
|
||||
if(bit.initial()) {
|
||||
GLStateManager.glDisable(bit.glEnum());
|
||||
} else {
|
||||
GLStateManager.glEnable(bit.glEnum());
|
||||
}
|
||||
verifyState(bit.glEnum(), !bit.initial(), bit.name() + " Toggle State");
|
||||
});
|
||||
toggleAndVerify(bits);
|
||||
|
||||
GLStateManager.glPopAttrib();
|
||||
verifyState(GL13.GL_ACTIVE_TEXTURE, GL13.GL_TEXTURE0, "Active Texture Unit 0 - Reset");
|
||||
@@ -404,7 +399,7 @@ class GLSM_PushPop_UnitTest {
|
||||
GLStateManager.glActiveTexture(GL13.GL_TEXTURE1);
|
||||
verifyState(GL11.GL_TEXTURE_BINDING_2D, 0, "Texture Binding Unit 1 - Reset");
|
||||
|
||||
bits.forEach(bit -> verifyState(bit.glEnum(), bit.initial(), bit.name() + " Reset State"));
|
||||
verifyReset(bits);
|
||||
|
||||
GLStateManager.glActiveTexture(GL13.GL_TEXTURE0);
|
||||
GLStateManager.glDeleteTextures(tex1);
|
||||
@@ -1156,30 +1151,6 @@ class GLSM_PushPop_UnitTest {
|
||||
GLStateManager.glBlendFunc(GL11.GL_ONE, GL11.GL_ZERO);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testPolygonStateReadBack() {
|
||||
GLStateManager.glCullFace(GL11.GL_FRONT);
|
||||
GLStateManager.glFrontFace(GL11.GL_CW);
|
||||
GLStateManager.glPolygonMode(GL11.GL_FRONT_AND_BACK, GL11.GL_LINE);
|
||||
|
||||
verifyState(GL11.GL_CULL_FACE_MODE, GL11.GL_FRONT, "Cull Face Mode");
|
||||
verifyState(GL11.GL_FRONT_FACE, GL11.GL_CW, "Front Face");
|
||||
verifyState(GL11.GL_POLYGON_MODE, new int[] { GL11.GL_LINE, GL11.GL_LINE }, "Polygon Mode");
|
||||
|
||||
GLStateManager.glCullFace(GL11.GL_BACK);
|
||||
GLStateManager.glFrontFace(GL11.GL_CCW);
|
||||
GLStateManager.glPolygonMode(GL11.GL_FRONT_AND_BACK, GL11.GL_FILL);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testActiveTextureReadBack() {
|
||||
GLStateManager.glActiveTexture(GL13.GL_TEXTURE1);
|
||||
verifyState(GL13.GL_ACTIVE_TEXTURE, GL13.GL_TEXTURE1, "Active Texture");
|
||||
|
||||
GLStateManager.glActiveTexture(GL13.GL_TEXTURE0);
|
||||
verifyState(GL13.GL_ACTIVE_TEXTURE, GL13.GL_TEXTURE0, "Active Texture - Reset");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testUntouchedPushPopRoundTripLeavesStateIdentical() {
|
||||
GLStateManager.glDepthFunc(GL11.GL_LEQUAL);
|
||||
|
||||
@@ -6,6 +6,8 @@ import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL13;
|
||||
import org.lwjgl.opengl.GL14;
|
||||
|
||||
import static com.gtnewhorizons.angelica.glsm.GlTestSupport.drainErrors;
|
||||
import static com.gtnewhorizons.angelica.glsm.GlTestSupport.driverTextureBinding;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
@@ -15,14 +17,6 @@ public class GLSM_RetainedState_GLTest {
|
||||
|
||||
private static final StateSet ALL = StateSet.forMask(GL11.GL_ALL_ATTRIB_BITS);
|
||||
|
||||
private static int driverTextureBinding(int unit) {
|
||||
final int saved = GL11.glGetInteger(GL13.GL_ACTIVE_TEXTURE);
|
||||
GL13.glActiveTexture(GL13.GL_TEXTURE0 + unit);
|
||||
final int binding = GL11.glGetInteger(GL11.GL_TEXTURE_BINDING_2D);
|
||||
GL13.glActiveTexture(saved);
|
||||
return binding;
|
||||
}
|
||||
|
||||
private static void baseline() {
|
||||
GLStateManager.enableCull();
|
||||
GLStateManager.disableBlend();
|
||||
@@ -234,7 +228,7 @@ public class GLSM_RetainedState_GLTest {
|
||||
@Test
|
||||
void aDeletedProgramIsNotRebound() {
|
||||
final RetainedState retained = new RetainedState();
|
||||
final int program = GLSM_StateSet_GLTest.linkTrivialProgram();
|
||||
final int program = GlTestSupport.program(GlTestSupport.TRIVIAL_VS, GlTestSupport.TRIVIAL_FS);
|
||||
try {
|
||||
baseline();
|
||||
final int d = GLStateManager.pushState(ALL);
|
||||
@@ -243,11 +237,10 @@ public class GLSM_RetainedState_GLTest {
|
||||
GLStateManager.popStateTo(d);
|
||||
GLStateManager.glUseProgram(0);
|
||||
GLStateManager.glDeleteProgram(program);
|
||||
while (GL11.glGetError() != GL11.GL_NO_ERROR) {}
|
||||
drainErrors();
|
||||
|
||||
GLStateManager.applyRetainedState(retained);
|
||||
assertEquals(0, GLStateManager.getActiveProgram());
|
||||
assertEquals(GL11.GL_NO_ERROR, GL11.glGetError());
|
||||
} finally {
|
||||
GLStateManager.glUseProgram(0);
|
||||
baseline();
|
||||
|
||||
@@ -24,7 +24,6 @@ class GLSM_SamplerBinding_GLTest {
|
||||
@BeforeEach
|
||||
void requireSamplerObjects() {
|
||||
assumeTrue(RenderSystem.supportsSamplerObjects());
|
||||
drainGlErrors();
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
@@ -35,11 +34,6 @@ class GLSM_SamplerBinding_GLTest {
|
||||
GL33.glBindSampler(unit, 0);
|
||||
}
|
||||
GLStateManager.glActiveTexture(GL13.GL_TEXTURE0);
|
||||
drainGlErrors();
|
||||
}
|
||||
|
||||
private static void drainGlErrors() {
|
||||
while (GL11.glGetError() != GL11.GL_NO_ERROR) {}
|
||||
}
|
||||
|
||||
private static int driverBinding(int unit) {
|
||||
|
||||
+63
-77
@@ -3,6 +3,8 @@ package com.gtnewhorizons.angelica.glsm;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
import org.lwjgl.LWJGLException;
|
||||
import org.lwjgl.opengl.Display;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
@@ -12,6 +14,7 @@ import org.lwjgl.opengl.SharedDrawable;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
@@ -43,21 +46,13 @@ public class GLSM_ServerSideState_UnitTest {
|
||||
private boolean originalSplashComplete;
|
||||
private Thread originalDrawableGLHolder;
|
||||
|
||||
private static void setSplashComplete(boolean value) {
|
||||
SplashWindow.setSplashComplete(value);
|
||||
}
|
||||
|
||||
private static boolean getSplashComplete() {
|
||||
return SplashWindow.isSplashComplete();
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
void setupSharedDrawable() throws Exception {
|
||||
originalSplashComplete = getSplashComplete();
|
||||
originalSplashComplete = SplashWindow.isSplashComplete();
|
||||
originalDrawableGLHolder = GLStateManager.getDrawableGLHolder();
|
||||
|
||||
// Reset splash state to simulate splash screen scenario
|
||||
setSplashComplete(false);
|
||||
SplashWindow.setSplashComplete(false);
|
||||
|
||||
sharedDrawable = new SharedDrawable(Display.getDrawable());
|
||||
|
||||
@@ -149,7 +144,7 @@ public class GLSM_ServerSideState_UnitTest {
|
||||
// Restore original state
|
||||
GLStateManager.setDrawableGL(null);
|
||||
GLStateManager.setDrawableGLHolder(originalDrawableGLHolder);
|
||||
setSplashComplete(originalSplashComplete);
|
||||
SplashWindow.setSplashComplete(originalSplashComplete);
|
||||
if (originalSplashComplete) {
|
||||
GLStateManager.markSplashComplete("test");
|
||||
}
|
||||
@@ -214,46 +209,81 @@ public class GLSM_ServerSideState_UnitTest {
|
||||
GL11.glDeleteTextures(texShared[0]);
|
||||
}
|
||||
|
||||
/** One texture parameter through its typed GLSM setter and getter, plus the raw driver read. Values travel as float. */
|
||||
private static final class TexParam {
|
||||
final String name;
|
||||
final float initial;
|
||||
final float changed;
|
||||
final FloatConsumer set;
|
||||
final FloatSupplier glsm;
|
||||
final FloatSupplier driver;
|
||||
|
||||
TexParam(String name, float initial, float changed, FloatConsumer set, FloatSupplier glsm, FloatSupplier driver) {
|
||||
this.name = name;
|
||||
this.initial = initial;
|
||||
this.changed = changed;
|
||||
this.set = set;
|
||||
this.glsm = glsm;
|
||||
this.driver = driver;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
private interface FloatConsumer {
|
||||
void accept(float value);
|
||||
}
|
||||
|
||||
private interface FloatSupplier {
|
||||
float get();
|
||||
}
|
||||
|
||||
static Stream<TexParam> texParams() {
|
||||
return Stream.of(
|
||||
new TexParam("glTexParameteri MIN_FILTER", GL11.GL_LINEAR, GL11.GL_NEAREST,
|
||||
v -> GLStateManager.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, (int) v),
|
||||
() -> GLStateManager.glGetTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER),
|
||||
() -> GL11.glGetTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER)),
|
||||
new TexParam("glTexParameterf LOD_BIAS", 0.0f, 1.5f,
|
||||
v -> GLStateManager.glTexParameterf(GL11.GL_TEXTURE_2D, GL14.GL_TEXTURE_LOD_BIAS, v),
|
||||
() -> GLStateManager.glGetTexParameterf(GL11.GL_TEXTURE_2D, GL14.GL_TEXTURE_LOD_BIAS),
|
||||
() -> GL11.glGetTexParameterf(GL11.GL_TEXTURE_2D, GL14.GL_TEXTURE_LOD_BIAS)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test: SharedDrawable sets texture MIN_FILTER, verify both GLSM and actual GL state are correct on both contexts.
|
||||
* Test: SharedDrawable sets a texture parameter, verify both GLSM and actual GL state are correct on both contexts.
|
||||
*/
|
||||
@Test
|
||||
void testTexParameterFromSharedDrawable() throws InterruptedException {
|
||||
@ParameterizedTest
|
||||
@MethodSource("texParams")
|
||||
void testTexParameterFromSharedDrawable(TexParam param) throws InterruptedException {
|
||||
int texId = GL11.glGenTextures();
|
||||
|
||||
try {
|
||||
GLStateManager.glBindTexture(GL11.GL_TEXTURE_2D, texId);
|
||||
GLStateManager.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR);
|
||||
param.set.accept(param.initial);
|
||||
|
||||
int initialGLSM = GLStateManager.glGetTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER);
|
||||
assertEquals(GL11.GL_LINEAR, initialGLSM, "Initial GLSM should be GL_LINEAR");
|
||||
assertEquals(param.initial, param.glsm.get(), 0.001f, "Initial GLSM value");
|
||||
assertEquals(param.initial, param.driver.get(), 0.001f, "Initial GL value");
|
||||
|
||||
int initialGL = GL11.glGetTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER);
|
||||
assertEquals(GL11.GL_LINEAR, initialGL, "Initial GL should be GL_LINEAR");
|
||||
|
||||
// SharedDrawable: bind and change params to GL_NEAREST via GLSM
|
||||
executeOnSharedDrawable(() -> {
|
||||
GLStateManager.glBindTexture(GL11.GL_TEXTURE_2D, texId);
|
||||
|
||||
int boundTex = GL11.glGetInteger(GL11.GL_TEXTURE_BINDING_2D);
|
||||
assertEquals(texId, boundTex, "SharedDrawable should have texId bound");
|
||||
|
||||
GLStateManager.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_NEAREST);
|
||||
param.set.accept(param.changed);
|
||||
|
||||
int glsmValue = GLStateManager.glGetTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER);
|
||||
assertEquals(GL11.GL_NEAREST, glsmValue, "SharedDrawable GLSM should return GL_NEAREST");
|
||||
|
||||
int glValue = GL11.glGetTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER);
|
||||
assertEquals(GL11.GL_NEAREST, glValue, "SharedDrawable GL should be GL_NEAREST");
|
||||
assertEquals(param.changed, param.glsm.get(), 0.001f, "SharedDrawable GLSM value");
|
||||
assertEquals(param.changed, param.driver.get(), 0.001f, "SharedDrawable GL value");
|
||||
});
|
||||
|
||||
GLStateManager.glBindTexture(GL11.GL_TEXTURE_2D, texId);
|
||||
|
||||
int mainGLSM = GLStateManager.glGetTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER);
|
||||
assertEquals(GL11.GL_NEAREST, mainGLSM, "Main thread GLSM should return GL_NEAREST");
|
||||
|
||||
int mainGL = GL11.glGetTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER);
|
||||
assertEquals(GL11.GL_NEAREST, mainGL, "Main thread GL should be GL_NEAREST");
|
||||
assertEquals(param.changed, param.glsm.get(), 0.001f, "Main thread GLSM value");
|
||||
assertEquals(param.changed, param.driver.get(), 0.001f, "Main thread GL value");
|
||||
|
||||
} finally {
|
||||
GLStateManager.glBindTexture(GL11.GL_TEXTURE_2D, 0);
|
||||
@@ -358,50 +388,6 @@ public class GLSM_ServerSideState_UnitTest {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test glTexParameterf (float parameters like LOD_BIAS).
|
||||
*/
|
||||
@Test
|
||||
void testTexParameterfFromSharedDrawable() throws InterruptedException {
|
||||
int texId = GL11.glGenTextures();
|
||||
|
||||
try {
|
||||
GLStateManager.glBindTexture(GL11.GL_TEXTURE_2D, texId);
|
||||
GLStateManager.glTexParameterf(GL11.GL_TEXTURE_2D, GL14.GL_TEXTURE_LOD_BIAS, 0.0f);
|
||||
|
||||
float initialGLSM = GLStateManager.glGetTexParameterf(GL11.GL_TEXTURE_2D, GL14.GL_TEXTURE_LOD_BIAS);
|
||||
float initialGL = GL11.glGetTexParameterf(GL11.GL_TEXTURE_2D, GL14.GL_TEXTURE_LOD_BIAS);
|
||||
assertEquals(0.0f, initialGLSM, 0.001f, "Initial GLSM LOD_BIAS should be 0.0");
|
||||
assertEquals(0.0f, initialGL, 0.001f, "Initial GL LOD_BIAS should be 0.0");
|
||||
|
||||
// SharedDrawable: change LOD_BIAS
|
||||
executeOnSharedDrawable(() -> {
|
||||
GLStateManager.glBindTexture(GL11.GL_TEXTURE_2D, texId);
|
||||
|
||||
int bound = GL11.glGetInteger(GL11.GL_TEXTURE_BINDING_2D);
|
||||
assertEquals(texId, bound, "SharedDrawable should have texId bound");
|
||||
|
||||
GLStateManager.glTexParameterf(GL11.GL_TEXTURE_2D, GL14.GL_TEXTURE_LOD_BIAS, 1.5f);
|
||||
|
||||
float glsmValue = GLStateManager.glGetTexParameterf(GL11.GL_TEXTURE_2D, GL14.GL_TEXTURE_LOD_BIAS);
|
||||
assertEquals(1.5f, glsmValue, 0.001f, "SharedDrawable GLSM should return 1.5");
|
||||
float glValue = GL11.glGetTexParameterf(GL11.GL_TEXTURE_2D, GL14.GL_TEXTURE_LOD_BIAS);
|
||||
assertEquals(1.5f, glValue, 0.001f, "SharedDrawable GL should be 1.5");
|
||||
});
|
||||
|
||||
GLStateManager.glBindTexture(GL11.GL_TEXTURE_2D, texId);
|
||||
|
||||
float finalGLSM = GLStateManager.glGetTexParameterf(GL11.GL_TEXTURE_2D, GL14.GL_TEXTURE_LOD_BIAS);
|
||||
float finalGL = GL11.glGetTexParameterf(GL11.GL_TEXTURE_2D, GL14.GL_TEXTURE_LOD_BIAS);
|
||||
assertEquals(1.5f, finalGLSM, 0.001f, "Main thread GLSM should return 1.5");
|
||||
assertEquals(1.5f, finalGL, 0.001f, "Main thread GL should be 1.5");
|
||||
|
||||
} finally {
|
||||
GLStateManager.glBindTexture(GL11.GL_TEXTURE_2D, 0);
|
||||
GLStateManager.glDeleteTextures(texId);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test glTexImage2D: SharedDrawable uploads texture data, verify dimensions cached correctly.
|
||||
*/
|
||||
@@ -478,7 +464,7 @@ public class GLSM_ServerSideState_UnitTest {
|
||||
GL11.glDeleteTextures(deferredGen);
|
||||
assertTrue(GL11.glIsTexture(texId), "Delete should stay deferred while the splash is not complete");
|
||||
|
||||
setSplashComplete(true);
|
||||
SplashWindow.setSplashComplete(true);
|
||||
flushGen = GLStateManager.glGenTextures();
|
||||
assertFalse(GL11.glIsTexture(texId), "Texture should be gone after the post-splash flush");
|
||||
assertEquals(0, GLStateManager.getBoundTextureForServerState(), "Flush should scrub the main thread binding");
|
||||
|
||||
+19
-11
@@ -5,12 +5,17 @@ import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import com.gtnewhorizons.angelica.glsm.backend.BackendManager;
|
||||
import com.gtnewhorizons.angelica.glsm.stacks.BooleanStateStack;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Collections;
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.Set;
|
||||
import java.util.function.IntSupplier;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
@@ -30,13 +35,23 @@ public class GLSM_SplashCachingCoverage_UnitTest {
|
||||
void leaveSplashWindow() throws IllegalAccessException {
|
||||
SplashWindow.leave();
|
||||
GLStateManager.glDepthFunc(GL11.GL_LESS);
|
||||
GLStateManager.glCullFace(GL11.GL_BACK);
|
||||
}
|
||||
|
||||
@Test
|
||||
void depthFuncSetDuringSplashLandsInCache() {
|
||||
GLStateManager.glDepthFunc(GL11.GL_LEQUAL);
|
||||
static Stream<Arguments> stateSetDuringSplash() {
|
||||
return Stream.of(
|
||||
Arguments.of("depth func", (Runnable) () -> GLStateManager.glDepthFunc(GL11.GL_LEQUAL), GL11.GL_LEQUAL,
|
||||
(IntSupplier) () -> GLStateManager.getDepthState().getFunc()),
|
||||
Arguments.of("cull face", (Runnable) () -> GLStateManager.glCullFace(GL11.GL_FRONT), GL11.GL_FRONT,
|
||||
(IntSupplier) () -> GLStateManager.getPolygonState().getCullFaceMode()));
|
||||
}
|
||||
|
||||
assertEquals(GL11.GL_LEQUAL, GLStateManager.getDepthState().getFunc(), "cache write dropped while caching=false");
|
||||
@ParameterizedTest(name = "{0}")
|
||||
@MethodSource("stateSetDuringSplash")
|
||||
void stateSetDuringSplashLandsInCache(String name, Runnable set, int expected, IntSupplier cached) {
|
||||
set.run();
|
||||
|
||||
assertEquals(expected, cached.getAsInt(), "cache write dropped while caching=false");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -137,11 +152,4 @@ public class GLSM_SplashCachingCoverage_UnitTest {
|
||||
assertFalse(GLStateManager.takeStateSeedPending(), "seed must be consumed exactly once, not once per frame");
|
||||
assertFalse(GLStateManager.takeStateSeedPending(), "seed must stay consumed");
|
||||
}
|
||||
|
||||
@Test
|
||||
void cullFaceSetDuringSplashLandsInCache() {
|
||||
GLStateManager.glCullFace(GL11.GL_FRONT);
|
||||
|
||||
assertEquals(GL11.GL_FRONT, GLStateManager.getPolygonState().getCullFaceMode(), "cache write dropped while caching=false");
|
||||
}
|
||||
}
|
||||
+3
-7
@@ -54,18 +54,14 @@ public class GLSM_SplashCompleteLatch_UnitTest {
|
||||
@Test
|
||||
void cachingIsThreadScopedBeforeTheLatchAndGlobalAfter() throws Exception {
|
||||
final AtomicBoolean cachingOffThread = new AtomicBoolean(true);
|
||||
final Runnable probe = () -> cachingOffThread.set(GLStateManager.isCachingEnabled());
|
||||
final TestThreads.Body probe = () -> cachingOffThread.set(GLStateManager.isCachingEnabled());
|
||||
|
||||
Thread t = new Thread(probe, "non-holder");
|
||||
t.start();
|
||||
t.join();
|
||||
TestThreads.run("non-holder", probe);
|
||||
assertFalse(cachingOffThread.get(), "caching must be holder-scoped during the dual-context window");
|
||||
|
||||
GLStateManager.markSplashComplete("test");
|
||||
|
||||
t = new Thread(probe, "non-holder");
|
||||
t.start();
|
||||
t.join();
|
||||
TestThreads.run("non-holder", probe);
|
||||
assertTrue(cachingOffThread.get(), "after the latch caching is global - this is what the latch buys");
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
-13
@@ -10,13 +10,8 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
@GLCoreTest
|
||||
public class GLSM_TextureBindingTargetCache_UnitTest {
|
||||
|
||||
private static void drainErrors() {
|
||||
while (GL11.glGetError() != GL11.GL_NO_ERROR) {}
|
||||
}
|
||||
|
||||
@Test
|
||||
void flattenedCacheTracksNon2DTargets() {
|
||||
drainErrors();
|
||||
final int t3d = GL11.glGenTextures();
|
||||
final int t2d = GL11.glGenTextures();
|
||||
try {
|
||||
@@ -38,13 +33,11 @@ public class GLSM_TextureBindingTargetCache_UnitTest {
|
||||
GLStateManager.glActiveTexture(GL13.GL_TEXTURE0);
|
||||
GLStateManager.glDeleteTextures(t3d);
|
||||
GLStateManager.glDeleteTextures(t2d);
|
||||
drainErrors();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void proxyTargetBindIsNeitherForwardedNorCached() {
|
||||
drainErrors();
|
||||
final int t2d = GL11.glGenTextures();
|
||||
try {
|
||||
GLStateManager.glActiveTexture(GL13.GL_TEXTURE5);
|
||||
@@ -60,13 +53,11 @@ public class GLSM_TextureBindingTargetCache_UnitTest {
|
||||
GLStateManager.glBindTexture(GL11.GL_TEXTURE_2D, 0);
|
||||
GLStateManager.glActiveTexture(GL13.GL_TEXTURE0);
|
||||
GLStateManager.glDeleteTextures(t2d);
|
||||
drainErrors();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void popAttribRestoresRecordedTarget() {
|
||||
drainErrors();
|
||||
final int t3d = GL11.glGenTextures();
|
||||
final int t2d = GL11.glGenTextures();
|
||||
try {
|
||||
@@ -86,13 +77,11 @@ public class GLSM_TextureBindingTargetCache_UnitTest {
|
||||
GLStateManager.glActiveTexture(GL13.GL_TEXTURE0);
|
||||
GLStateManager.glDeleteTextures(t3d);
|
||||
GLStateManager.glDeleteTextures(t2d);
|
||||
drainErrors();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void unbindIsNotElidedAcrossTargets() {
|
||||
drainErrors();
|
||||
final int t2d = GL11.glGenTextures();
|
||||
try {
|
||||
GLStateManager.glActiveTexture(GL13.GL_TEXTURE4);
|
||||
@@ -100,11 +89,9 @@ public class GLSM_TextureBindingTargetCache_UnitTest {
|
||||
GLStateManager.glBindTexture(GL12.GL_TEXTURE_3D, 0);
|
||||
GLStateManager.glBindTexture(GL11.GL_TEXTURE_2D, 0);
|
||||
assertEquals(0, GL11.glGetInteger(GL11.GL_TEXTURE_BINDING_2D), "2D unbind after a 3D unbind must reach the driver");
|
||||
assertEquals(GL11.GL_NO_ERROR, GL11.glGetError());
|
||||
} finally {
|
||||
GLStateManager.glActiveTexture(GL13.GL_TEXTURE0);
|
||||
GLStateManager.glDeleteTextures(t2d);
|
||||
drainErrors();
|
||||
}
|
||||
}
|
||||
}
|
||||
+2
@@ -79,6 +79,8 @@ public class GLSM_TextureUploadGeneration_GLTest {
|
||||
final int afterSub = info.getUploadGeneration();
|
||||
GLStateManager.glTexSubImage2D(GL11.GL_TEXTURE_2D, 1, 0, 0, 1, 1, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, BufferUtils.createByteBuffer(4));
|
||||
assertEquals(afterSub, info.getUploadGeneration(), "only level 0 is tracked");
|
||||
// Level 1 was never allocated, so the driver rejects that upload.
|
||||
assertEquals(GL11.GL_INVALID_OPERATION, GL11.glGetError());
|
||||
} finally {
|
||||
GLStateManager.glDeleteTextures(texId);
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.gtnewhorizons.angelica.glsm;
|
||||
import com.gtnewhorizon.gtnhlib.client.opengl.UniversalVAO;
|
||||
import com.gtnewhorizons.angelica.glsm.ffp.VAOManager;
|
||||
import com.gtnewhorizons.angelica.util.GLSMUtil;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
@@ -15,6 +16,13 @@ import static com.gtnewhorizons.angelica.util.GLSMUtil.verifyState;
|
||||
@GLCompatTest
|
||||
public class GLSM_VAO_UnitTest {
|
||||
|
||||
@AfterEach
|
||||
void resetClientArrayState() {
|
||||
glBindVertexArray(0);
|
||||
GLStateManager.glClientActiveTexture(GL13.GL_TEXTURE0);
|
||||
GLSMUtil.setClientState(GL11.GL_NORMAL_ARRAY, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testDefaultStates() {
|
||||
verifyState(GL30.GL_VERTEX_ARRAY_BINDING, GLStateManager.ctx().defaultVAO, "GL_VERTEX_ARRAY_BINDING Initial State");
|
||||
@@ -36,14 +44,14 @@ public class GLSM_VAO_UnitTest {
|
||||
final int vaoVertexType = GL11.GL_INT;
|
||||
final int vaoVertexStride = vaoVertexSize * 4;
|
||||
|
||||
GL13.glClientActiveTexture(GL13.GL_TEXTURE1);
|
||||
GLStateManager.glClientActiveTexture(GL13.GL_TEXTURE1);
|
||||
verifyState(GL13.GL_CLIENT_ACTIVE_TEXTURE, GL13.GL_TEXTURE1, "GL_CLIENT_ACTIVE_TEXTURE - Setup");
|
||||
|
||||
// Set the vertex attrib to a defined state
|
||||
int vbo = GL15.glGenBuffers();
|
||||
GLStateManager.glBindBuffer(GL15.GL_ARRAY_BUFFER, vbo);
|
||||
|
||||
GL11.glVertexPointer(defaultVertexSize, defaultVertexType, defaultVertexStride, 0);
|
||||
GLStateManager.glVertexPointer(defaultVertexSize, defaultVertexType, defaultVertexStride, 0L);
|
||||
|
||||
GLSMUtil.setClientState(GL11.GL_NORMAL_ARRAY, true);
|
||||
verifyState(GL11.GL_NORMAL_ARRAY, true, "GL_NORMAL_ARRAY - Enabled");
|
||||
@@ -74,7 +82,7 @@ public class GLSM_VAO_UnitTest {
|
||||
GLSMUtil.setClientState(GL11.GL_VERTEX_ARRAY, vaoVertexEnabled);
|
||||
verifyState(GL11.GL_VERTEX_ARRAY, vaoVertexEnabled, "GL_VERTEX_ARRAY - Enabled");
|
||||
|
||||
GL11.glVertexPointer(vaoVertexSize, vaoVertexType, vaoVertexStride, 0);
|
||||
GLStateManager.glVertexPointer(vaoVertexSize, vaoVertexType, vaoVertexStride, 0L);
|
||||
|
||||
verifyState(GL11.GL_VERTEX_ARRAY_SIZE, vaoVertexSize, "GL_VERTEX_ARRAY_SIZE - Set");
|
||||
verifyState(GL11.GL_VERTEX_ARRAY_TYPE, vaoVertexType, "GL_VERTEX_ARRAY_TYPE - Set");
|
||||
@@ -117,7 +125,7 @@ public class GLSM_VAO_UnitTest {
|
||||
GLStateManager.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
|
||||
glBindVertexArray(0);
|
||||
|
||||
GL15.glDeleteBuffers(vbo);
|
||||
GLStateManager.glDeleteBuffers(vbo);
|
||||
UniversalVAO.deleteVertexArrays(vao);
|
||||
}
|
||||
|
||||
@@ -138,7 +146,7 @@ public class GLSM_VAO_UnitTest {
|
||||
GLStateManager.glDisableVertexAttribArray(0);
|
||||
GLStateManager.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
|
||||
glBindVertexArray(0);
|
||||
GL15.glDeleteBuffers(vbo);
|
||||
GLStateManager.glDeleteBuffers(vbo);
|
||||
UniversalVAO.deleteVertexArrays(vao);
|
||||
}
|
||||
|
||||
@@ -159,7 +167,7 @@ public class GLSM_VAO_UnitTest {
|
||||
GLStateManager.glDisableVertexAttribArray(0);
|
||||
GLStateManager.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
|
||||
glBindVertexArray(0);
|
||||
GL15.glDeleteBuffers(vbo);
|
||||
GLStateManager.glDeleteBuffers(vbo);
|
||||
UniversalVAO.deleteVertexArrays(vao);
|
||||
}
|
||||
|
||||
@@ -179,7 +187,7 @@ public class GLSM_VAO_UnitTest {
|
||||
GLStateManager.glDisableClientState(GL11.GL_VERTEX_ARRAY);
|
||||
GLStateManager.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
|
||||
glBindVertexArray(0);
|
||||
GL15.glDeleteBuffers(vbo);
|
||||
GLStateManager.glDeleteBuffers(vbo);
|
||||
UniversalVAO.deleteVertexArrays(vao);
|
||||
}
|
||||
|
||||
|
||||
@@ -31,6 +31,9 @@ public class GLSM_ValueStackCow_GLTest {
|
||||
if (fixtureTexA == -1) {
|
||||
fixtureTexA = GLStateManager.glGenTextures();
|
||||
fixtureTexB = GLStateManager.glGenTextures();
|
||||
final int bound = GL11.glGetInteger(GL11.GL_TEXTURE_BINDING_2D);
|
||||
GL11.glBindTexture(GL11.GL_TEXTURE_2D, fixtureTexB);
|
||||
GL11.glBindTexture(GL11.GL_TEXTURE_2D, bound);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+19
-27
@@ -4,12 +4,12 @@ import com.gtnewhorizon.gtnhlib.client.renderer.DirectTessellator;
|
||||
import com.gtnewhorizons.angelica.glsm.recording.CompiledDisplayList;
|
||||
import com.gtnewhorizons.angelica.glsm.recording.GLCommand;
|
||||
import com.gtnewhorizons.angelica.glsm.recording.ImmediateModeRecorder;
|
||||
import com.gtnewhorizons.angelica.glsm.testutil.TestThreads;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
@@ -29,10 +29,10 @@ class ImmediateModeThreadIsolationTest {
|
||||
final AtomicReference<DirectTessellator> bg1 = new AtomicReference<>();
|
||||
final AtomicReference<DirectTessellator> bg2 = new AtomicReference<>();
|
||||
|
||||
final Thread t1 = new Thread(() -> bg1.set(ImmediateModeRecorder.getInternalTessellator()), "iso-test-1");
|
||||
final Thread t2 = new Thread(() -> bg2.set(ImmediateModeRecorder.getInternalTessellator()), "iso-test-2");
|
||||
t1.start(); t2.start();
|
||||
t1.join(); t2.join();
|
||||
final TestThreads.Worker t1 = TestThreads.start("iso-test-1", () -> bg1.set(ImmediateModeRecorder.getInternalTessellator()));
|
||||
final TestThreads.Worker t2 = TestThreads.start("iso-test-2", () -> bg2.set(ImmediateModeRecorder.getInternalTessellator()));
|
||||
t1.join();
|
||||
t2.join();
|
||||
|
||||
assertNotNull(bg1.get());
|
||||
assertNotNull(bg2.get());
|
||||
@@ -43,28 +43,22 @@ class ImmediateModeThreadIsolationTest {
|
||||
|
||||
@Test
|
||||
void concurrentImmediateModeDoesNotCorruptRecording() throws Exception {
|
||||
final List<Throwable> failures = new CopyOnWriteArrayList<>();
|
||||
final CountDownLatch start = new CountDownLatch(1);
|
||||
final AtomicBoolean stop = new AtomicBoolean(false);
|
||||
|
||||
final Runnable spam = () -> {
|
||||
try {
|
||||
start.await();
|
||||
while (!stop.get()) {
|
||||
GLStateManager.glBegin(GL11.GL_QUADS);
|
||||
GLStateManager.glVertex3f(0, 0, 0);
|
||||
GLStateManager.glVertex3f(1, 0, 0);
|
||||
GLStateManager.glVertex3f(1, 1, 0);
|
||||
GLStateManager.glVertex3f(0, 1, 0);
|
||||
GLStateManager.glEnd();
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
failures.add(t);
|
||||
final TestThreads.Body spam = () -> {
|
||||
start.await();
|
||||
while (!stop.get()) {
|
||||
GLStateManager.glBegin(GL11.GL_QUADS);
|
||||
GLStateManager.glVertex3f(0, 0, 0);
|
||||
GLStateManager.glVertex3f(1, 0, 0);
|
||||
GLStateManager.glVertex3f(1, 1, 0);
|
||||
GLStateManager.glVertex3f(0, 1, 0);
|
||||
GLStateManager.glEnd();
|
||||
}
|
||||
};
|
||||
final Thread t1 = new Thread(spam, "iso-spam-1");
|
||||
final Thread t2 = new Thread(spam, "iso-spam-2");
|
||||
t1.start(); t2.start();
|
||||
final TestThreads.Worker t1 = TestThreads.start("iso-spam-1", spam);
|
||||
final TestThreads.Worker t2 = TestThreads.start("iso-spam-2", spam);
|
||||
start.countDown();
|
||||
|
||||
final List<Integer> lists = new ArrayList<>();
|
||||
@@ -83,10 +77,10 @@ class ImmediateModeThreadIsolationTest {
|
||||
}
|
||||
} finally {
|
||||
stop.set(true);
|
||||
t1.join(5000); t2.join(5000);
|
||||
}
|
||||
t1.join();
|
||||
t2.join();
|
||||
|
||||
assertTrue(failures.isEmpty(), "background immediate mode threw: " + failures);
|
||||
for (int list : lists) {
|
||||
final CompiledDisplayList compiled = DisplayListManager.getDisplayList(list);
|
||||
assertNotNull(compiled, "list " + list + " should be compiled");
|
||||
@@ -97,9 +91,7 @@ class ImmediateModeThreadIsolationTest {
|
||||
|
||||
@Test
|
||||
void sweepFreesDeadThreadTessellators() throws Exception {
|
||||
final Thread t = new Thread(() -> ImmediateModeRecorder.getInternalTessellator(), "iso-sweep");
|
||||
t.start();
|
||||
t.join();
|
||||
TestThreads.run("iso-sweep", ImmediateModeRecorder::getInternalTessellator);
|
||||
final int before = ImmediateModeRecorder.getThreadTessellatorCount();
|
||||
assertTrue(before >= 1);
|
||||
ImmediateModeRecorder.cleanupOrphanTessellators();
|
||||
|
||||
@@ -2,17 +2,19 @@ package com.gtnewhorizons.angelica.glsm;
|
||||
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
import org.lwjgl.BufferUtils;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL15;
|
||||
import org.lwjgl.opengl.GL20;
|
||||
|
||||
import java.nio.FloatBuffer;
|
||||
import java.nio.IntBuffer;
|
||||
import java.util.function.IntConsumer;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotEquals;
|
||||
|
||||
@GLCoreTest
|
||||
class InstancedQuadDrawGLTest {
|
||||
@@ -26,7 +28,7 @@ class InstancedQuadDrawGLTest {
|
||||
|
||||
@BeforeEach
|
||||
void setup() {
|
||||
program = buildProgram();
|
||||
program = GlTestSupport.program(VS, FS);
|
||||
GLStateManager.glUseProgram(program);
|
||||
|
||||
final FloatBuffer verts = BufferUtils.createFloatBuffer(8);
|
||||
@@ -42,63 +44,39 @@ class InstancedQuadDrawGLTest {
|
||||
ebo = GLStateManager.glGenBuffers();
|
||||
GLStateManager.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, ebo);
|
||||
GLStateManager.glBufferData(GL15.GL_ELEMENT_ARRAY_BUFFER, idx, GL15.GL_STATIC_DRAW);
|
||||
|
||||
drainErrors();
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void cleanup() {
|
||||
GLStateManager.glUseProgram(0);
|
||||
if (program != 0) GL20.glDeleteProgram(program);
|
||||
if (program != 0) GLStateManager.glDeleteProgram(program);
|
||||
GLStateManager.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
|
||||
GLStateManager.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
if (vbo != 0) GLStateManager.glDeleteBuffers(vbo);
|
||||
if (ebo != 0) GLStateManager.glDeleteBuffers(ebo);
|
||||
drainErrors();
|
||||
}
|
||||
|
||||
@Test
|
||||
void drawArraysInstanced_quads_noInvalidEnum() {
|
||||
GLStateManager.glDrawArraysInstanced(GL11.GL_QUADS, 0, 4, 3);
|
||||
assertEquals(GL11.GL_NO_ERROR, GL11.glGetError(), "GL_QUADS instanced array draw must be emulated, not rejected");
|
||||
static Stream<Arguments> draws() {
|
||||
return Stream.of(
|
||||
draw("GL_QUADS instanced array draw must be emulated, not rejected", ebo -> GLStateManager.glDrawArraysInstanced(GL11.GL_QUADS, 0, 4, 3)),
|
||||
draw("non-quad instanced array draw passes through cleanly", ebo -> {
|
||||
GLStateManager.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
GLStateManager.glDrawArraysInstanced(GL11.GL_TRIANGLES, 0, 3, 3);
|
||||
}),
|
||||
draw("GL_QUADS instanced element draw must be emulated, not rejected", ebo -> {
|
||||
GLStateManager.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, ebo);
|
||||
GLStateManager.glDrawElementsInstanced(GL11.GL_QUADS, 4, GL11.GL_UNSIGNED_INT, 0L, 3);
|
||||
}));
|
||||
}
|
||||
|
||||
@Test
|
||||
void drawArraysInstanced_triangles_fastPathClean() {
|
||||
GLStateManager.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
GLStateManager.glDrawArraysInstanced(GL11.GL_TRIANGLES, 0, 3, 3);
|
||||
assertEquals(GL11.GL_NO_ERROR, GL11.glGetError(), "non-quad instanced array draw passes through cleanly");
|
||||
private static Arguments draw(String name, IntConsumer body) {
|
||||
return Arguments.of(name, body);
|
||||
}
|
||||
|
||||
@Test
|
||||
void drawElementsInstanced_quads_noInvalidEnum() {
|
||||
GLStateManager.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, ebo);
|
||||
GLStateManager.glDrawElementsInstanced(GL11.GL_QUADS, 4, GL11.GL_UNSIGNED_INT, 0L, 3);
|
||||
assertEquals(GL11.GL_NO_ERROR, GL11.glGetError(), "GL_QUADS instanced element draw must be emulated, not rejected");
|
||||
}
|
||||
|
||||
private static int buildProgram() {
|
||||
final int vs = compile(GL20.GL_VERTEX_SHADER, VS);
|
||||
final int fs = compile(GL20.GL_FRAGMENT_SHADER, FS);
|
||||
final int p = GL20.glCreateProgram();
|
||||
GL20.glAttachShader(p, vs);
|
||||
GL20.glAttachShader(p, fs);
|
||||
GL20.glLinkProgram(p);
|
||||
assertNotEquals(0, GL20.glGetProgrami(p, GL20.GL_LINK_STATUS), "test shader must link: " + GL20.glGetProgramInfoLog(p, 1024));
|
||||
GL20.glDeleteShader(vs);
|
||||
GL20.glDeleteShader(fs);
|
||||
return p;
|
||||
}
|
||||
|
||||
private static int compile(int type, String src) {
|
||||
final int s = GL20.glCreateShader(type);
|
||||
GL20.glShaderSource(s, src);
|
||||
GL20.glCompileShader(s);
|
||||
assertNotEquals(0, GL20.glGetShaderi(s, GL20.GL_COMPILE_STATUS), "test shader must compile: " + GL20.glGetShaderInfoLog(s, 1024));
|
||||
return s;
|
||||
}
|
||||
|
||||
private static void drainErrors() {
|
||||
while (GL11.glGetError() != GL11.GL_NO_ERROR) { /* clear */ }
|
||||
@ParameterizedTest(name = "{0}")
|
||||
@MethodSource("draws")
|
||||
void instancedDrawRaisesNoGlError(String name, IntConsumer draw) {
|
||||
draw.accept(ebo);
|
||||
assertEquals(GL11.GL_NO_ERROR, GL11.glGetError(), name);
|
||||
}
|
||||
}
|
||||
@@ -81,11 +81,6 @@ class QuadConverterTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void triangulateQuads_zeroQuads_noop() {
|
||||
QuadConverter.triangulateQuads(0L, GL11.GL_UNSIGNED_INT, 0L, GL11.GL_UNSIGNED_INT, 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
void triangulateQuads_unsupportedTypes_throw() {
|
||||
final ByteBuffer src = MemoryUtilities.memAlloc(16);
|
||||
@@ -240,8 +235,6 @@ class QuadConverterTest {
|
||||
}
|
||||
}
|
||||
|
||||
// === helpers ===
|
||||
|
||||
private static void assertUintIndices(ByteBuffer buf, int... expected) {
|
||||
for (int i = 0; i < expected.length; i++) {
|
||||
assertEquals(expected[i], buf.getInt(i * 4), "uint index[" + i + "]");
|
||||
|
||||
@@ -1,72 +1,42 @@
|
||||
package com.gtnewhorizons.angelica.glsm;
|
||||
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
@GLCoreTest
|
||||
class ReadbackGLTest {
|
||||
|
||||
@AfterEach
|
||||
void noErrors() {
|
||||
void resetPack() {
|
||||
ReadbackFixture.resetPack();
|
||||
assertEquals(GL11.GL_NO_ERROR, GL11.glGetError());
|
||||
}
|
||||
|
||||
@Test
|
||||
void rgba8() {
|
||||
ReadbackFixture.rgba8();
|
||||
static Stream<Arguments> readbacks() {
|
||||
return Stream.of(
|
||||
format("rgba8", ReadbackFixture::rgba8),
|
||||
format("packState", ReadbackFixture::packState),
|
||||
format("pixelPackBuffer", ReadbackFixture::pixelPackBuffer),
|
||||
format("rgb8", ReadbackFixture::rgb8),
|
||||
format("rgba16f", ReadbackFixture::rgba16f),
|
||||
format("rgba32f", ReadbackFixture::rgba32f),
|
||||
format("r8", ReadbackFixture::r8),
|
||||
format("rg16f", ReadbackFixture::rg16f),
|
||||
format("rgb10a2", ReadbackFixture::rgb10a2),
|
||||
format("r11g11b10f", ReadbackFixture::r11g11b10f),
|
||||
format("depthStencil", ReadbackFixture::depthStencil));
|
||||
}
|
||||
|
||||
@Test
|
||||
void packState() {
|
||||
ReadbackFixture.packState();
|
||||
private static Arguments format(String name, Runnable body) {
|
||||
return Arguments.of(name, body);
|
||||
}
|
||||
|
||||
@Test
|
||||
void pixelPackBuffer() {
|
||||
ReadbackFixture.pixelPackBuffer();
|
||||
}
|
||||
|
||||
@Test
|
||||
void rgb8() {
|
||||
ReadbackFixture.rgb8();
|
||||
}
|
||||
|
||||
@Test
|
||||
void rgba16f() {
|
||||
ReadbackFixture.rgba16f();
|
||||
}
|
||||
|
||||
@Test
|
||||
void rgba32f() {
|
||||
ReadbackFixture.rgba32f();
|
||||
}
|
||||
|
||||
@Test
|
||||
void r8() {
|
||||
ReadbackFixture.r8();
|
||||
}
|
||||
|
||||
@Test
|
||||
void rg16f() {
|
||||
ReadbackFixture.rg16f();
|
||||
}
|
||||
|
||||
@Test
|
||||
void rgb10a2() {
|
||||
ReadbackFixture.rgb10a2();
|
||||
}
|
||||
|
||||
@Test
|
||||
void r11g11b10f() {
|
||||
ReadbackFixture.r11g11b10f();
|
||||
}
|
||||
|
||||
@Test
|
||||
void depthStencil() {
|
||||
ReadbackFixture.depthStencil();
|
||||
@ParameterizedTest(name = "{0}")
|
||||
@MethodSource("readbacks")
|
||||
void readback(String name, Runnable body) {
|
||||
body.run();
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -9,6 +9,7 @@ import org.lwjgl.opengl.GL13;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import static com.gtnewhorizons.angelica.glsm.GlTestSupport.drainErrors;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
@GLCoreTest
|
||||
@@ -71,8 +72,7 @@ public class DSAUnsupportedBindingTest {
|
||||
GLStateManager.glBindTexture(GL11.GL_TEXTURE_2D, t);
|
||||
GLStateManager.glBindTexture(GL11.GL_TEXTURE_2D, y);
|
||||
GLStateManager.glBindTexture(GL12.GL_TEXTURE_3D, x);
|
||||
while (GL11.glGetError() != GL11.GL_NO_ERROR) {
|
||||
}
|
||||
drainErrors();
|
||||
|
||||
dsa.texParameteri(t, GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_NEAREST);
|
||||
|
||||
|
||||
+41
-43
@@ -7,15 +7,19 @@ import org.joml.Vector3f;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
import org.lwjgl.BufferUtils;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL12;
|
||||
import org.lwjgl.opengl.GL15;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.FloatBuffer;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static com.gtnewhorizon.gtnhlib.client.renderer.vertex.VertexFlags.COLOR_BIT;
|
||||
import static com.gtnewhorizons.angelica.glsm.GlTestSupport.floats;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
@@ -112,12 +116,6 @@ class FFPVertexLightingGLTest {
|
||||
+ " light1=" + GLStateManager.getLightStates()[1].isEnabled();
|
||||
}
|
||||
|
||||
private static FloatBuffer floats(float... values) {
|
||||
final FloatBuffer buf = BufferUtils.createFloatBuffer(values.length);
|
||||
buf.put(values).flip();
|
||||
return buf;
|
||||
}
|
||||
|
||||
private void buildTriangle() {
|
||||
vao = GLStateManager.glGenVertexArrays();
|
||||
GLStateManager.glBindVertexArray(vao);
|
||||
@@ -156,9 +154,8 @@ class FFPVertexLightingGLTest {
|
||||
GLStateManager.glDrawArrays(GL11.GL_TRIANGLES, 0, 3);
|
||||
assertEquals(GL11.GL_NO_ERROR, GL11.glGetError(), "FFP draw must not raise a GL error");
|
||||
|
||||
final ByteBuffer pixel = BufferUtils.createByteBuffer(4);
|
||||
GL11.glReadPixels(400, 200, 1, 1, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, pixel);
|
||||
return new float[] { (pixel.get(0) & 0xFF) / 255.0f, (pixel.get(1) & 0xFF) / 255.0f, (pixel.get(2) & 0xFF) / 255.0f };
|
||||
final int[] pixel = FfpFixture.readPixel(400, 200);
|
||||
return new float[] { pixel[0] / 255.0f, pixel[1] / 255.0f, pixel[2] / 255.0f };
|
||||
}
|
||||
|
||||
private void assertSolverMatchesShader(String context) {
|
||||
@@ -170,23 +167,20 @@ class FFPVertexLightingGLTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void faceOnNormalMatchesGeneratedShader() {
|
||||
GLStateManager.glNormal3f(0.0f, 0.0f, 1.0f);
|
||||
assertSolverMatchesShader("face-on normal");
|
||||
static Stream<Arguments> normals() {
|
||||
return Stream.of(
|
||||
Arguments.of("face-on normal", 0.0f, 0.0f, 1.0f, Float.POSITIVE_INFINITY),
|
||||
// A 0.0104-long normal must stay at the 0.4 light model ambient floor rather than pick up 0.6 per light
|
||||
Arguments.of("sign normal", 0.0f, 0.0f, -0.010416667f, 0.45f),
|
||||
Arguments.of("tilted normal", 0.3f, 0.8f, 0.5f, Float.POSITIVE_INFINITY));
|
||||
}
|
||||
|
||||
@Test
|
||||
void signNormalMatchesGeneratedShader() {
|
||||
GLStateManager.glNormal3f(0.0f, 0.0f, -0.010416667f);
|
||||
assertSolverMatchesShader("sign normal");
|
||||
assertTrue(factor.x < 0.45f, "a 0.0104-long normal must stay at the 0.4 light model ambient floor rather than pick up 0.6 per light, got " + factor.x);
|
||||
}
|
||||
|
||||
@Test
|
||||
void tiltedNormalMatchesGeneratedShader() {
|
||||
GLStateManager.glNormal3f(0.3f, 0.8f, 0.5f);
|
||||
assertSolverMatchesShader("tilted normal");
|
||||
@ParameterizedTest(name = "{0}")
|
||||
@MethodSource("normals")
|
||||
void normalMatchesGeneratedShader(String name, float x, float y, float z, float factorCeiling) {
|
||||
GLStateManager.glNormal3f(x, y, z);
|
||||
assertSolverMatchesShader(name);
|
||||
assertTrue(factor.x < factorCeiling, name + ": factor must stay below " + factorCeiling + ", got " + factor.x);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -206,27 +200,31 @@ class FFPVertexLightingGLTest {
|
||||
assertTrue(factor.x > 1.2f, "normalize restores the unit normal, which must pick up more diffuse than rescale's 0.5-long one, got " + factor.x);
|
||||
}
|
||||
|
||||
@Test
|
||||
void materialEmissionIsNotRepresentable() {
|
||||
GLStateManager.glMaterial(GL11.GL_FRONT_AND_BACK, GL11.GL_EMISSION, floats(0.1f, 0.1f, 0.1f, 1.0f));
|
||||
assertFalse(FFPVertexLighting.modulatesVertexColor(factor), "emission is additive, so the lit colour is not vertexColor * factor");
|
||||
static Stream<Arguments> unrepresentableStates() {
|
||||
return Stream.of(
|
||||
unrepresentable("emission is additive, so the lit colour is not vertexColor * factor",
|
||||
() -> GLStateManager.glMaterial(GL11.GL_FRONT_AND_BACK, GL11.GL_EMISSION, floats(0.1f, 0.1f, 0.1f, 1.0f))),
|
||||
unrepresentable("specular is additive, so the lit colour is not vertexColor * factor", () -> {
|
||||
GLStateManager.glMaterial(GL11.GL_FRONT_AND_BACK, GL11.GL_SPECULAR, floats(1.0f, 1.0f, 1.0f, 1.0f));
|
||||
GLStateManager.glMaterialf(GL11.GL_FRONT_AND_BACK, GL11.GL_SHININESS, 16.0f);
|
||||
GLStateManager.glLight(GL11.GL_LIGHT0, GL11.GL_SPECULAR, floats(1.0f, 1.0f, 1.0f, 1.0f));
|
||||
}),
|
||||
unrepresentable("only AMBIENT_AND_DIFFUSE makes the lit colour scale with the vertex colour",
|
||||
() -> GLStateManager.glColorMaterial(GL11.GL_FRONT_AND_BACK, GL11.GL_EMISSION)));
|
||||
}
|
||||
|
||||
private static Arguments unrepresentable(String reason, Runnable state) {
|
||||
return Arguments.of(reason, state);
|
||||
}
|
||||
|
||||
@ParameterizedTest(name = "{0}")
|
||||
@MethodSource("unrepresentableStates")
|
||||
void additiveLightingIsNotRepresentable(String reason, Runnable state) {
|
||||
state.run();
|
||||
assertFalse(FFPVertexLighting.modulatesVertexColor(factor), reason);
|
||||
assertEquals(IDENTITY_FACTOR, factor, "a rejected solve must leave an identity factor");
|
||||
}
|
||||
|
||||
@Test
|
||||
void specularContributionIsNotRepresentable() {
|
||||
GLStateManager.glMaterial(GL11.GL_FRONT_AND_BACK, GL11.GL_SPECULAR, floats(1.0f, 1.0f, 1.0f, 1.0f));
|
||||
GLStateManager.glMaterialf(GL11.GL_FRONT_AND_BACK, GL11.GL_SHININESS, 16.0f);
|
||||
GLStateManager.glLight(GL11.GL_LIGHT0, GL11.GL_SPECULAR, floats(1.0f, 1.0f, 1.0f, 1.0f));
|
||||
assertFalse(FFPVertexLighting.modulatesVertexColor(factor), "specular is additive, so the lit colour is not vertexColor * factor");
|
||||
}
|
||||
|
||||
@Test
|
||||
void nonAmbientAndDiffuseColorMaterialIsNotRepresentable() {
|
||||
GLStateManager.glColorMaterial(GL11.GL_FRONT_AND_BACK, GL11.GL_EMISSION);
|
||||
assertFalse(FFPVertexLighting.modulatesVertexColor(factor), "only AMBIENT_AND_DIFFUSE makes the lit colour scale with the vertex colour");
|
||||
}
|
||||
|
||||
@Test
|
||||
void lightsBeyondTheFfpCountAreIgnored() {
|
||||
assertTrue(FFPVertexLighting.modulatesVertexColor(factor), FFPVertexLightingGLTest::gateState);
|
||||
|
||||
+1
-7
@@ -11,10 +11,10 @@ import org.lwjgl.opengl.GL30;
|
||||
import org.lwjgl.opengl.GL31;
|
||||
|
||||
import java.nio.DoubleBuffer;
|
||||
import java.nio.FloatBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static com.gtnewhorizons.angelica.glsm.GlTestSupport.floats;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotEquals;
|
||||
|
||||
@@ -25,12 +25,6 @@ class FfpUniformBlockDedupTest {
|
||||
return GL30.glGetInteger(GL31.GL_UNIFORM_BUFFER_START, FFPUniformBlock.BINDING_POINT);
|
||||
}
|
||||
|
||||
private static FloatBuffer floats(float... values) {
|
||||
final FloatBuffer buf = BufferUtils.createFloatBuffer(values.length);
|
||||
buf.put(values).flip();
|
||||
return buf;
|
||||
}
|
||||
|
||||
private static DoubleBuffer doubles(double... values) {
|
||||
final DoubleBuffer buf = BufferUtils.createDoubleBuffer(values.length);
|
||||
buf.put(values).flip();
|
||||
|
||||
@@ -21,6 +21,7 @@ import static com.gtnewhorizon.gtnhlib.bytebuf.MemoryUtilities.memAddress0;
|
||||
import static com.gtnewhorizon.gtnhlib.bytebuf.MemoryUtilities.memPutFloat;
|
||||
import static com.gtnewhorizon.gtnhlib.client.renderer.vertex.VertexFlags.COLOR_BIT;
|
||||
import static com.gtnewhorizon.gtnhlib.client.renderer.vertex.VertexFlags.NORMAL_BIT;
|
||||
import static com.gtnewhorizons.angelica.glsm.GlTestSupport.drainErrors;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
@@ -100,7 +101,7 @@ class InstancedFFPDrawGLTest {
|
||||
GLSMHooks.blendHandler = new LoggingBlendHandler();
|
||||
|
||||
GLStateManager.glDrawArrays(GL11.GL_TRIANGLES, 0, 0);
|
||||
while (GL11.glGetError() != GL11.GL_NO_ERROR) {}
|
||||
drainErrors();
|
||||
|
||||
assertEquals(List.of("resolve", "flush"), log);
|
||||
}
|
||||
|
||||
@@ -36,7 +36,6 @@ class LogicOpGLTest {
|
||||
GLStateManager.glDisable(GL11.GL_BLEND);
|
||||
LogicOpFixture.deleteResources();
|
||||
FfpFixture.resetFfpState();
|
||||
while (GL11.glGetError() != GL11.GL_NO_ERROR) {}
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -48,7 +47,6 @@ class LogicOpGLTest {
|
||||
assertRgb(op, src);
|
||||
}
|
||||
}
|
||||
assertEquals(GL11.GL_NO_ERROR, GL11.glGetError());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -5,11 +5,15 @@ import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
import org.lwjgl.BufferUtils;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL15;
|
||||
|
||||
import java.nio.FloatBuffer;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
@@ -59,17 +63,18 @@ class WideLineClipGLTest {
|
||||
GLStateManager.glLoadIdentity();
|
||||
GLStateManager.glMatrixMode(GL11.GL_MODELVIEW);
|
||||
FfpFixture.resetFfpState();
|
||||
while (GL11.glGetError() != GL11.GL_NO_ERROR) {}
|
||||
}
|
||||
|
||||
@Test
|
||||
void lineEndingBehindTheCameraKeepsItsWidth() {
|
||||
assertConstantWidth(IN_FRONT, BEHIND);
|
||||
static Stream<Arguments> linesCrossingTheNearPlane() {
|
||||
return Stream.of(
|
||||
Arguments.of("line ending behind the camera", IN_FRONT, BEHIND),
|
||||
Arguments.of("line starting behind the camera", BEHIND, IN_FRONT));
|
||||
}
|
||||
|
||||
@Test
|
||||
void lineStartingBehindTheCameraKeepsItsWidth() {
|
||||
assertConstantWidth(BEHIND, IN_FRONT);
|
||||
@ParameterizedTest(name = "{0}")
|
||||
@MethodSource("linesCrossingTheNearPlane")
|
||||
void lineCrossingTheNearPlaneKeepsItsWidth(String name, float[] start, float[] end) {
|
||||
assertConstantWidth(start, end);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -144,7 +149,6 @@ class WideLineClipGLTest {
|
||||
final int y = row, count = lit;
|
||||
assertTrue(count > 0 && count <= LINE_WIDTH + 1, () -> "row " + y + " is " + count + " pixels wide");
|
||||
}
|
||||
assertEquals(GL11.GL_NO_ERROR, GL11.glGetError());
|
||||
}
|
||||
|
||||
private int[] drawLine(float[] start, float[] end) {
|
||||
|
||||
@@ -2,6 +2,9 @@ package com.gtnewhorizons.angelica.glsm.loading;
|
||||
|
||||
import com.gtnewhorizons.angelica.glsm.redirect.GLSMRedirector;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
import org.objectweb.asm.ClassWriter;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
import org.objectweb.asm.tree.ClassNode;
|
||||
@@ -12,6 +15,7 @@ import org.objectweb.asm.tree.MethodNode;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotSame;
|
||||
@@ -71,14 +75,16 @@ class ModRedirectorTest {
|
||||
assertEquals(coreExclusions.length + 2, exclusions.size(), exclusions.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
void exclusionsCombineCoreLwjgl3AndExtra() {
|
||||
assertStandardExclusions(redirector().getTransformerExclusions());
|
||||
static Stream<Arguments> exclusionLists() {
|
||||
return Stream.of(
|
||||
Arguments.of("ModRedirector", redirector().getTransformerExclusions()),
|
||||
Arguments.of("EarlyRedirectorCore", new EarlyRedirectorCore(EXTRA_EXCLUSION).getTransformerExclusions()));
|
||||
}
|
||||
|
||||
@Test
|
||||
void earlyRedirectorExclusionsCombineCoreLwjgl3AndExtra() {
|
||||
assertStandardExclusions(new EarlyRedirectorCore(EXTRA_EXCLUSION).getTransformerExclusions());
|
||||
@ParameterizedTest(name = "{0}")
|
||||
@MethodSource("exclusionLists")
|
||||
void exclusionsCombineCoreLwjgl3AndExtra(String name, String[] exclusions) {
|
||||
assertStandardExclusions(exclusions);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -86,22 +92,17 @@ class ModRedirectorTest {
|
||||
assertNull(redirector().transform("com.example.TestClass", null, this));
|
||||
}
|
||||
|
||||
@Test
|
||||
void excludedPrefixReturnsOriginalArray() {
|
||||
final byte[] original = bytesWithGlCall();
|
||||
assertSame(original, redirector().transform(EXTRA_EXCLUSION + ".TestClass", original, this));
|
||||
static Stream<Arguments> untouchedClasses() {
|
||||
return Stream.of(
|
||||
Arguments.of("extra exclusion prefix", EXTRA_EXCLUSION + ".TestClass", bytesWithGlCall()),
|
||||
Arguments.of("core exclusion prefix", "org.lwjgl.opengl.TestClass", bytesWithGlCall()),
|
||||
Arguments.of("no GL call", "com.example.TestClass", bytesWithoutGlCall()));
|
||||
}
|
||||
|
||||
@Test
|
||||
void coreExcludedPrefixReturnsOriginalArray() {
|
||||
final byte[] original = bytesWithGlCall();
|
||||
assertSame(original, redirector().transform("org.lwjgl.opengl.TestClass", original, this));
|
||||
}
|
||||
|
||||
@Test
|
||||
void unchangedClassReturnsOriginalArray() {
|
||||
final byte[] original = bytesWithoutGlCall();
|
||||
assertSame(original, redirector().transform("com.example.TestClass", original, this));
|
||||
@ParameterizedTest(name = "{0}")
|
||||
@MethodSource("untouchedClasses")
|
||||
void untouchedClassReturnsOriginalArray(String name, String className, byte[] original) {
|
||||
assertSame(original, redirector().transform(className, original, this));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
+20
-24
@@ -1,6 +1,8 @@
|
||||
package com.gtnewhorizons.angelica.glsm.profiling;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.CsvSource;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
@@ -8,32 +10,26 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
class TracyOptionsTest {
|
||||
|
||||
@Test
|
||||
void resolveBooleanFallsBackToConfigWhenNoOverride() {
|
||||
assertTrue(TracyOptions.resolveBoolean(null, true));
|
||||
assertFalse(TracyOptions.resolveBoolean(null, false));
|
||||
@ParameterizedTest(name = "{0}")
|
||||
@CsvSource(value = {
|
||||
"no override falls back to config true, null, true, true",
|
||||
"no override falls back to config false, null, false, false",
|
||||
"override true wins, true, false, true",
|
||||
"override false wins, false, true, false"
|
||||
}, nullValues = "null")
|
||||
void resolveBoolean(String name, Boolean override, boolean config, boolean expected) {
|
||||
assertEquals(expected, TracyOptions.resolveBoolean(override, config));
|
||||
}
|
||||
|
||||
@Test
|
||||
void resolveBooleanOverrideWinsEitherWay() {
|
||||
assertTrue(TracyOptions.resolveBoolean(Boolean.TRUE, false));
|
||||
assertFalse(TracyOptions.resolveBoolean(Boolean.FALSE, true));
|
||||
}
|
||||
|
||||
@Test
|
||||
void resolveMaxSrcLocsFallsBackToConfigWhenNoOverride() {
|
||||
assertEquals(4096, TracyOptions.resolveMaxSrcLocs(null, 4096));
|
||||
}
|
||||
|
||||
@Test
|
||||
void resolveMaxSrcLocsOverrideWins() {
|
||||
assertEquals(8192, TracyOptions.resolveMaxSrcLocs(8192, 4096));
|
||||
}
|
||||
|
||||
@Test
|
||||
void resolveMaxSrcLocsClampsBothConfigAndOverrideToTheMinimum() {
|
||||
assertEquals(16, TracyOptions.resolveMaxSrcLocs(null, 4));
|
||||
assertEquals(16, TracyOptions.resolveMaxSrcLocs(1, 4096));
|
||||
@ParameterizedTest(name = "{0}")
|
||||
@CsvSource(value = {
|
||||
"no override falls back to config, null, 4096, 4096",
|
||||
"override wins, 8192, 4096, 8192",
|
||||
"config is clamped to the minimum, null, 4, 16",
|
||||
"override is clamped to the minimum, 1, 4096, 16"
|
||||
}, nullValues = "null")
|
||||
void resolveMaxSrcLocs(String name, Integer override, int config, int expected) {
|
||||
assertEquals(expected, TracyOptions.resolveMaxSrcLocs(override, config));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
-24
@@ -62,25 +62,6 @@ class IndexedDrawBatchBuilderTest extends DisplayListTestFixture {
|
||||
MemoryUtilities.memFree(read);
|
||||
}
|
||||
|
||||
@Test
|
||||
void compileAndExecute_firesLiveAndBakes() {
|
||||
final int vbo = defaultQuadVbo();
|
||||
final int ebo = uploadEbo(GL11.GL_UNSIGNED_SHORT, 0, 1, 2);
|
||||
final int vao = setupPosColorVao(vbo);
|
||||
|
||||
final int list = newList();
|
||||
GLStateManager.glNewList(list, GL11.GL_COMPILE_AND_EXECUTE);
|
||||
GLStateManager.glBindVertexArray(vao);
|
||||
GLStateManager.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, ebo);
|
||||
GLStateManager.glDrawElements(GL11.GL_TRIANGLES, 3, GL11.GL_UNSIGNED_SHORT, 0L);
|
||||
GLStateManager.glBindVertexArray(0);
|
||||
GLStateManager.glEndList();
|
||||
|
||||
final BatchedIndexedDrawCmd cmd = firstBatchedCmd(list);
|
||||
assertNotNull(cmd);
|
||||
assertEquals(3, cmd.getIndexCount());
|
||||
}
|
||||
|
||||
@Test
|
||||
void quads_triangulateAtRecord() {
|
||||
final int vbo = defaultQuadVbo();
|
||||
@@ -457,11 +438,6 @@ class IndexedDrawBatchBuilderTest extends DisplayListTestFixture {
|
||||
assertNotEquals(cmds.get(0).getSharedVAO(), cmds.get(1).getSharedVAO(), "VAOs from separate batches must be distinct");
|
||||
}
|
||||
|
||||
@Test
|
||||
void nullListProbeCompiles() {
|
||||
assertNull(DisplayListManager.getDisplayList(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
void multiLayoutDraws_emitInInsertionOrder() {
|
||||
// Two distinct layouts. The builder uses a LinkedHashMap, so the first
|
||||
|
||||
+18
-63
@@ -1,24 +1,30 @@
|
||||
package com.gtnewhorizons.angelica.glsm.recording;
|
||||
|
||||
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||
import com.gtnewhorizons.angelica.glsm.GlTestSupport;
|
||||
import com.gtnewhorizons.angelica.glsm.recording.commands.IndexedDrawBatch;
|
||||
import com.gtnewhorizons.angelica.glsm.recording.support.DisplayListTestFixture;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.ValueSource;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL15;
|
||||
import org.lwjgl.opengl.GL20;
|
||||
|
||||
import static com.gtnewhorizons.angelica.glsm.GlTestSupport.drainErrors;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
class IndexedDrawDeleteSafetyTest extends DisplayListTestFixture {
|
||||
|
||||
@Test
|
||||
void vaoEboMapSweep_clearsStaleEntryOnForeignVao() {
|
||||
@ParameterizedTest(name = "replayed before delete={0}")
|
||||
@ValueSource(booleans = {false, true})
|
||||
void listDelete_clearsSharedEboFromForeignVao(boolean replayFirst) {
|
||||
final int vbo = defaultQuadVbo();
|
||||
final int ebo = uploadEbo(GL11.GL_UNSIGNED_SHORT, 0, 1, 2, 3);
|
||||
final int vao = setupPosColorVao(vbo);
|
||||
final int list = recordSingleIndexedDraw(vao, ebo, GL11.GL_QUADS, 4, GL11.GL_UNSIGNED_SHORT);
|
||||
|
||||
if (replayFirst) compiledOf(list).render();
|
||||
|
||||
final IndexedDrawBatch batch = firstBatch(list);
|
||||
final int sharedEbo = batch.getSharedEBO();
|
||||
|
||||
@@ -31,32 +37,13 @@ class IndexedDrawDeleteSafetyTest extends DisplayListTestFixture {
|
||||
untrackList(list);
|
||||
|
||||
GLStateManager.glBindVertexArray(foreignVao);
|
||||
assertEquals(0, GLStateManager.getBoundEBO(), "vaoEboMap still references the freed sharedEBO — non-gen crash imminent");
|
||||
GLStateManager.glBindVertexArray(0);
|
||||
}
|
||||
assertEquals(0, GLStateManager.getBoundEBO(), "vaoEboMap still references the freed sharedEBO - non-gen crash imminent");
|
||||
|
||||
@Test
|
||||
void bindBufferCycle_afterListDelete_isGlNoError() {
|
||||
final int vbo = defaultQuadVbo();
|
||||
final int ebo = uploadEbo(GL11.GL_UNSIGNED_SHORT, 0, 1, 2, 3);
|
||||
final int vao = setupPosColorVao(vbo);
|
||||
final int list = recordSingleIndexedDraw(vao, ebo, GL11.GL_QUADS, 4, GL11.GL_UNSIGNED_SHORT);
|
||||
|
||||
final int sharedEbo = firstBatch(list).getSharedEBO();
|
||||
final int foreignVao = newVao();
|
||||
GLStateManager.glBindVertexArray(foreignVao);
|
||||
GLStateManager.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, sharedEbo);
|
||||
GLStateManager.glBindVertexArray(0);
|
||||
|
||||
GLStateManager.glDeleteLists(list, 1);
|
||||
untrackList(list);
|
||||
|
||||
GLStateManager.glBindVertexArray(foreignVao);
|
||||
while (GL11.glGetError() != GL11.GL_NO_ERROR) {}
|
||||
drainErrors();
|
||||
final int prevEbo = GLStateManager.getBoundEBO();
|
||||
GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, prevEbo);
|
||||
final int err = GL11.glGetError();
|
||||
assertEquals(GL11.GL_NO_ERROR, err, () -> "bindBuffer(prevEbo=" + prevEbo + ") hit GL 0x" + Integer.toHexString(err) + " — cache carried a freed id through a VAO rebind");
|
||||
assertEquals(GL11.GL_NO_ERROR, err, () -> "bindBuffer(prevEbo=" + prevEbo + ") hit GL 0x" + Integer.toHexString(err) + " - cache carried a freed id through a VAO rebind");
|
||||
GLStateManager.glBindVertexArray(0);
|
||||
}
|
||||
|
||||
@@ -85,8 +72,8 @@ class IndexedDrawDeleteSafetyTest extends DisplayListTestFixture {
|
||||
|
||||
@Test
|
||||
void glDeleteProgram_zero_isNoOpAndLeavesActiveProgram() {
|
||||
final int prog = linkMinimalProgram();
|
||||
while (GL11.glGetError() != GL11.GL_NO_ERROR) {}
|
||||
final int prog = GlTestSupport.program(GlTestSupport.TRIVIAL_VS, GlTestSupport.TRIVIAL_FS);
|
||||
drainErrors();
|
||||
|
||||
GLStateManager.glUseProgram(prog);
|
||||
assertEquals(prog, GLStateManager.getActiveProgram());
|
||||
@@ -97,13 +84,13 @@ class IndexedDrawDeleteSafetyTest extends DisplayListTestFixture {
|
||||
|
||||
GLStateManager.glUseProgram(0);
|
||||
GLStateManager.glDeleteProgram(prog);
|
||||
while (GL11.glGetError() != GL11.GL_NO_ERROR) {}
|
||||
drainErrors();
|
||||
}
|
||||
|
||||
@Test
|
||||
void activeProgram_retainedAfterDelete_perGlSpec() {
|
||||
final int prog = linkMinimalProgram();
|
||||
while (GL11.glGetError() != GL11.GL_NO_ERROR) {}
|
||||
final int prog = GlTestSupport.program(GlTestSupport.TRIVIAL_VS, GlTestSupport.TRIVIAL_FS);
|
||||
drainErrors();
|
||||
|
||||
GLStateManager.glUseProgram(prog);
|
||||
assertEquals(prog, GLStateManager.getActiveProgram());
|
||||
@@ -114,38 +101,6 @@ class IndexedDrawDeleteSafetyTest extends DisplayListTestFixture {
|
||||
|
||||
GLStateManager.glUseProgram(0);
|
||||
assertEquals(0, GLStateManager.getActiveProgram(), "activeProgram clears once the deleted program is unbound");
|
||||
while (GL11.glGetError() != GL11.GL_NO_ERROR) {}
|
||||
drainErrors();
|
||||
}
|
||||
|
||||
private static int linkMinimalProgram() {
|
||||
final int vert = GLStateManager.glCreateShader(GL20.GL_VERTEX_SHADER);
|
||||
GLStateManager.glShaderSource(vert, MIN_VERT_SRC);
|
||||
GLStateManager.glCompileShader(vert);
|
||||
if (GL20.glGetShaderi(vert, GL20.GL_COMPILE_STATUS) == GL11.GL_FALSE) {
|
||||
throw new AssertionError("vertex shader failed to compile: " + GL20.glGetShaderInfoLog(vert, 4096));
|
||||
}
|
||||
|
||||
final int frag = GLStateManager.glCreateShader(GL20.GL_FRAGMENT_SHADER);
|
||||
GLStateManager.glShaderSource(frag, MIN_FRAG_SRC);
|
||||
GLStateManager.glCompileShader(frag);
|
||||
if (GL20.glGetShaderi(frag, GL20.GL_COMPILE_STATUS) == GL11.GL_FALSE) {
|
||||
throw new AssertionError("fragment shader failed to compile: " + GL20.glGetShaderInfoLog(frag, 4096));
|
||||
}
|
||||
|
||||
final int prog = GLStateManager.glCreateProgram();
|
||||
GLStateManager.glAttachShader(prog, vert);
|
||||
GLStateManager.glAttachShader(prog, frag);
|
||||
GLStateManager.glLinkProgram(prog);
|
||||
if (GL20.glGetProgrami(prog, GL20.GL_LINK_STATUS) == GL11.GL_FALSE) {
|
||||
throw new AssertionError("program failed to link: " + GL20.glGetProgramInfoLog(prog, 4096));
|
||||
}
|
||||
GLStateManager.glDetachShader(prog, vert);
|
||||
GLStateManager.glDetachShader(prog, frag);
|
||||
GLStateManager.glDeleteShader(vert);
|
||||
GLStateManager.glDeleteShader(frag);
|
||||
return prog;
|
||||
}
|
||||
|
||||
private static final String MIN_VERT_SRC = "#version 330 core\nvoid main(){gl_Position=vec4(0.0);}";
|
||||
private static final String MIN_FRAG_SRC = "#version 330 core\nout vec4 oC;void main(){oC=vec4(1.0);}";
|
||||
}
|
||||
+5
-33
@@ -15,6 +15,7 @@ import org.lwjgl.opengl.GL15;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.List;
|
||||
|
||||
import static com.gtnewhorizons.angelica.glsm.GlTestSupport.drainErrors;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
@@ -36,7 +37,7 @@ class IndexedDrawReplayTest extends DisplayListTestFixture {
|
||||
GL11.glViewport(0, 0, 16, 16);
|
||||
GL11.glDisable(GL11.GL_DEPTH_TEST);
|
||||
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT);
|
||||
while (GL11.glGetError() != GL11.GL_NO_ERROR) {}
|
||||
drainErrors();
|
||||
|
||||
final int query = GL15.glGenQueries();
|
||||
GL15.glBeginQuery(GL15.GL_SAMPLES_PASSED, query);
|
||||
@@ -92,7 +93,7 @@ class IndexedDrawReplayTest extends DisplayListTestFixture {
|
||||
GLStateManager.glBindVertexArray(distractorVao);
|
||||
GLStateManager.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
|
||||
while (GL11.glGetError() != GL11.GL_NO_ERROR) {}
|
||||
drainErrors();
|
||||
|
||||
compiledOf(list).render();
|
||||
|
||||
@@ -103,35 +104,6 @@ class IndexedDrawReplayTest extends DisplayListTestFixture {
|
||||
GLStateManager.glBindVertexArray(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
void replayThenDelete_thenBindBufferCycle_isGlNoError() {
|
||||
final int vbo = defaultQuadVbo();
|
||||
final int ebo = uploadEbo(GL11.GL_UNSIGNED_SHORT, 0, 1, 2, 3);
|
||||
final int vao = setupPosColorVao(vbo);
|
||||
final int list = recordSingleIndexedDraw(vao, ebo, GL11.GL_QUADS, 4, GL11.GL_UNSIGNED_SHORT);
|
||||
|
||||
compiledOf(list).render();
|
||||
|
||||
|
||||
final int sharedEbo = firstBatch(list).getSharedEBO();
|
||||
final int foreignVao = newVao();
|
||||
GLStateManager.glBindVertexArray(foreignVao);
|
||||
GLStateManager.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, sharedEbo);
|
||||
GLStateManager.glBindVertexArray(0);
|
||||
|
||||
GLStateManager.glDeleteLists(list, 1);
|
||||
untrackList(list);
|
||||
|
||||
GLStateManager.glBindVertexArray(foreignVao);
|
||||
assertEquals(0, GLStateManager.getBoundEBO(), "batched EBO id survived list delete in vaoEboMap — non-gen crash imminent");
|
||||
while (GL11.glGetError() != GL11.GL_NO_ERROR) {}
|
||||
final int prevEbo = GLStateManager.getBoundEBO();
|
||||
GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, prevEbo);
|
||||
final int err = GL11.glGetError();
|
||||
assertEquals(GL11.GL_NO_ERROR, err, () -> "post-delete bindBuffer(" + prevEbo + ") hit GL 0x" + Integer.toHexString(err));
|
||||
GLStateManager.glBindVertexArray(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
void execute_doesNotRestoreVAO_backToBackDraws() {
|
||||
final int vbo = defaultQuadVbo();
|
||||
@@ -153,7 +125,7 @@ class IndexedDrawReplayTest extends DisplayListTestFixture {
|
||||
|
||||
final int distractor = newVao();
|
||||
GLStateManager.glBindVertexArray(distractor);
|
||||
while (GL11.glGetError() != GL11.GL_NO_ERROR) {}
|
||||
drainErrors();
|
||||
|
||||
compiledOf(list).render();
|
||||
|
||||
@@ -229,7 +201,7 @@ class IndexedDrawReplayTest extends DisplayListTestFixture {
|
||||
GLStateManager.glDrawElements(GL11.GL_QUADS, 4, GL11.GL_UNSIGNED_SHORT, 0L);
|
||||
GLStateManager.glEndList();
|
||||
|
||||
while (GL11.glGetError() != GL11.GL_NO_ERROR) {}
|
||||
drainErrors();
|
||||
|
||||
compiledOf(list).render();
|
||||
compiledOf(list).render();
|
||||
|
||||
-33
@@ -3,10 +3,8 @@ package com.gtnewhorizons.angelica.glsm.recording;
|
||||
import com.gtnewhorizon.gtnhlib.client.renderer.DirectTessellator;
|
||||
import com.gtnewhorizon.gtnhlib.client.renderer.vertex.DefaultVertexFormat;
|
||||
import com.gtnewhorizons.angelica.glsm.GLCompatTest;
|
||||
import com.gtnewhorizons.angelica.glsm.DisplayListManager;
|
||||
import com.gtnewhorizons.angelica.glsm.GLCompatTest;
|
||||
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||
import it.unimi.dsi.fastutil.ints.Int2IntMap;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
@@ -33,37 +31,6 @@ class RecordingDataStructuresTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCompiledDisplayListCreation() {
|
||||
// Create a display list with PushMatrix, Scale, PopMatrix
|
||||
testList = GL11.glGenLists(1);
|
||||
GLStateManager.glNewList(testList, GL11.GL_COMPILE);
|
||||
|
||||
GLStateManager.glPushMatrix();
|
||||
GLStateManager.glScalef(2.0f, 2.0f, 2.0f);
|
||||
GLStateManager.glPopMatrix();
|
||||
|
||||
GLStateManager.glEndList();
|
||||
|
||||
// Verify the compiled display list
|
||||
CompiledDisplayList compiled = DisplayListManager.getDisplayList(testList);
|
||||
assertNotNull(compiled, "Display list should be compiled");
|
||||
assertNotNull(compiled.getCommandBuffer(), "Command buffer should not be null");
|
||||
|
||||
// Get command counts to verify structure
|
||||
Int2IntMap counts = compiled.getCommandCounts();
|
||||
|
||||
// Should have PushMatrix and PopMatrix
|
||||
assertEquals(1, counts.getOrDefault(GLCommand.PUSH_MATRIX, 0), "Should have 1 PushMatrix");
|
||||
assertEquals(1, counts.getOrDefault(GLCommand.POP_MATRIX, 0), "Should have 1 PopMatrix");
|
||||
|
||||
// Scale should be collapsed into a MultMatrix (optimizer collapses transforms)
|
||||
// Or if in debug mode, might have individual commands - just check we have some transforms
|
||||
int transformCount = counts.getOrDefault(GLCommand.MULT_MATRIX, 0)
|
||||
+ counts.getOrDefault(GLCommand.SCALE, 0);
|
||||
assertTrue(transformCount >= 0, "Should have transform commands");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testImmediateModeRecorder() {
|
||||
DirectTessellator recorder = ImmediateModeRecorder.getInternalTessellator();
|
||||
|
||||
+47
-51
@@ -1,8 +1,13 @@
|
||||
package com.gtnewhorizons.angelica.glsm.recording.commands;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotEquals;
|
||||
@@ -15,59 +20,50 @@ class AttribLayoutKeyTest {
|
||||
return out;
|
||||
}
|
||||
|
||||
@Test
|
||||
void standardPosColorUvNormal_isAlignedAndPacked() {
|
||||
final AttribLayoutKey k = new AttribLayoutKey(
|
||||
new int[]{0, 1, 2, 4},
|
||||
new int[]{3, 4, 2, 3},
|
||||
new int[]{GL11.GL_FLOAT, GL11.GL_UNSIGNED_BYTE, GL11.GL_FLOAT, GL11.GL_BYTE},
|
||||
new boolean[]{false, true, false, true});
|
||||
assertArrayEquals(new int[]{0, 12, 16, 24}, offsetsOf(k));
|
||||
assertEquals(28, k.stride());
|
||||
static Stream<Arguments> layouts() {
|
||||
return Stream.of(
|
||||
Arguments.of("standard pos/color/uv/normal is aligned and packed",
|
||||
new AttribLayoutKey(
|
||||
new int[]{0, 1, 2, 4},
|
||||
new int[]{3, 4, 2, 3},
|
||||
new int[]{GL11.GL_FLOAT, GL11.GL_UNSIGNED_BYTE, GL11.GL_FLOAT, GL11.GL_BYTE},
|
||||
new boolean[]{false, true, false, true}),
|
||||
new int[]{0, 12, 16, 24}, 28),
|
||||
Arguments.of("pos/uv/normal3 rounds the tail stride to 24",
|
||||
new AttribLayoutKey(
|
||||
new int[]{0, 2, 4},
|
||||
new int[]{3, 2, 3},
|
||||
new int[]{GL11.GL_FLOAT, GL11.GL_FLOAT, GL11.GL_BYTE},
|
||||
new boolean[]{false, false, true}),
|
||||
new int[]{0, 12, 20}, 24),
|
||||
Arguments.of("byte attrib in the middle rounds the next offset",
|
||||
new AttribLayoutKey(
|
||||
new int[]{0, 4, 2},
|
||||
new int[]{3, 3, 2},
|
||||
new int[]{GL11.GL_FLOAT, GL11.GL_BYTE, GL11.GL_FLOAT},
|
||||
new boolean[]{false, true, false}),
|
||||
new int[]{0, 12, 16}, 24),
|
||||
Arguments.of("all-byte layout packs tight",
|
||||
new AttribLayoutKey(
|
||||
new int[]{0, 1, 2},
|
||||
new int[]{3, 4, 2},
|
||||
new int[]{GL11.GL_BYTE, GL11.GL_UNSIGNED_BYTE, GL11.GL_BYTE},
|
||||
new boolean[]{true, true, false}),
|
||||
new int[]{0, 3, 7}, 9),
|
||||
Arguments.of("shorts after a byte round offset and stride to even",
|
||||
new AttribLayoutKey(
|
||||
new int[]{0, 1},
|
||||
new int[]{1, 2},
|
||||
new int[]{GL11.GL_BYTE, GL11.GL_SHORT},
|
||||
new boolean[]{true, false}),
|
||||
new int[]{0, 2}, 6));
|
||||
}
|
||||
|
||||
@Test
|
||||
void posUvNormal3_roundsTailStrideTo24() {
|
||||
final AttribLayoutKey k = new AttribLayoutKey(
|
||||
new int[]{0, 2, 4},
|
||||
new int[]{3, 2, 3},
|
||||
new int[]{GL11.GL_FLOAT, GL11.GL_FLOAT, GL11.GL_BYTE},
|
||||
new boolean[]{false, false, true});
|
||||
assertArrayEquals(new int[]{0, 12, 20}, offsetsOf(k));
|
||||
assertEquals(24, k.stride());
|
||||
}
|
||||
|
||||
@Test
|
||||
void interiorHazardOrder_roundsMidAttribOffset() {
|
||||
final AttribLayoutKey k = new AttribLayoutKey(
|
||||
new int[]{0, 4, 2},
|
||||
new int[]{3, 3, 2},
|
||||
new int[]{GL11.GL_FLOAT, GL11.GL_BYTE, GL11.GL_FLOAT},
|
||||
new boolean[]{false, true, false});
|
||||
assertArrayEquals(new int[]{0, 12, 16}, offsetsOf(k));
|
||||
assertEquals(24, k.stride());
|
||||
}
|
||||
|
||||
@Test
|
||||
void allByteLayout_packsTight() {
|
||||
final AttribLayoutKey k = new AttribLayoutKey(
|
||||
new int[]{0, 1, 2},
|
||||
new int[]{3, 4, 2},
|
||||
new int[]{GL11.GL_BYTE, GL11.GL_UNSIGNED_BYTE, GL11.GL_BYTE},
|
||||
new boolean[]{true, true, false});
|
||||
assertArrayEquals(new int[]{0, 3, 7}, offsetsOf(k));
|
||||
assertEquals(9, k.stride());
|
||||
}
|
||||
|
||||
@Test
|
||||
void shortsFollowingByte_roundToEvenAndStrideToEven() {
|
||||
final AttribLayoutKey k = new AttribLayoutKey(
|
||||
new int[]{0, 1},
|
||||
new int[]{1, 2},
|
||||
new int[]{GL11.GL_BYTE, GL11.GL_SHORT},
|
||||
new boolean[]{true, false});
|
||||
assertArrayEquals(new int[]{0, 2}, offsetsOf(k));
|
||||
assertEquals(6, k.stride());
|
||||
@ParameterizedTest(name = "{0}")
|
||||
@MethodSource("layouts")
|
||||
void offsetsAndStride(String name, AttribLayoutKey key, int[] offsets, int stride) {
|
||||
assertArrayEquals(offsets, offsetsOf(key));
|
||||
assertEquals(stride, key.stride());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
+34
-132
@@ -5,6 +5,8 @@ import com.gtnewhorizons.angelica.config.SystemProperties.UnmappedGLMode;
|
||||
import com.gtnewhorizons.angelica.glsm.testutil.Reflect;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.CsvSource;
|
||||
import org.objectweb.asm.ClassWriter;
|
||||
import org.objectweb.asm.Handle;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
@@ -16,7 +18,6 @@ import org.objectweb.asm.tree.InvokeDynamicInsnNode;
|
||||
import org.objectweb.asm.tree.MethodInsnNode;
|
||||
import org.objectweb.asm.tree.MethodNode;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
@@ -32,19 +33,8 @@ class GLSMRedirectorTest {
|
||||
|
||||
private static final String GLSM = GLSMRedirector.getTargetClassName();
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static Set<String> seenSet(String field) {
|
||||
try {
|
||||
final Field f = GLSMRedirector.class.getDeclaredField(field);
|
||||
f.setAccessible(true);
|
||||
return (Set<String>) f.get(null);
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static Set<String> unmappedSeen() { return seenSet("UNMAPPED_SEEN"); }
|
||||
private static Set<String> debugSeen() { return seenSet("DEBUG_SEEN"); }
|
||||
private static Set<String> unmappedSeen() { return Reflect.getStatic(GLSMRedirector.class, "UNMAPPED_SEEN"); }
|
||||
private static Set<String> debugSeen() { return Reflect.getStatic(GLSMRedirector.class, "DEBUG_SEEN"); }
|
||||
|
||||
@BeforeEach
|
||||
void reset() {
|
||||
@@ -112,35 +102,25 @@ class GLSMRedirectorTest {
|
||||
return (Handle) dyn.bsmArgs[1];
|
||||
}
|
||||
|
||||
@Test
|
||||
void invokeDynamicGL11HandleIsRedirected() {
|
||||
final Handle impl = new Handle(Opcodes.H_INVOKESTATIC, "org/lwjgl/opengl/GL11", "glPopMatrix", "()V", false);
|
||||
final ClassNode cn = makeClassWithInvokeDynamic(impl);
|
||||
@ParameterizedTest(name = "{0}")
|
||||
@CsvSource({
|
||||
"GL11, org/lwjgl/opengl/GL11, glPopMatrix, ()V, glPopMatrix",
|
||||
"extension class with a renamed target, org/lwjgl/opengl/EXTBlendFuncSeparate, glBlendFuncSeparateEXT, (IIII)V, tryBlendFuncSeparate",
|
||||
"GLxxC variant, org/lwjgl/opengl/GL11C, glDrawArrays, (III)V, glDrawArrays"
|
||||
})
|
||||
void invokeDynamicHandleIsRedirected(String name, String owner, String method, String desc, String expectedName) {
|
||||
final ClassNode cn = makeClassWithInvokeDynamic(new Handle(Opcodes.H_INVOKESTATIC, owner, method, desc, false));
|
||||
|
||||
final boolean changed = new GLSMRedirector().transformClassNode("com.example.TestClass", cn);
|
||||
|
||||
assertTrue(changed);
|
||||
final Handle result = getResultHandle(cn);
|
||||
assertEquals(GLSM, result.getOwner());
|
||||
assertEquals("glPopMatrix", result.getName());
|
||||
assertEquals("()V", result.getDesc());
|
||||
assertEquals(expectedName, result.getName());
|
||||
assertEquals(desc, result.getDesc());
|
||||
assertEquals(Opcodes.H_INVOKESTATIC, result.getTag());
|
||||
}
|
||||
|
||||
@Test
|
||||
void invokeDynamicNamedClassHandleIsRedirected() {
|
||||
final Handle impl = new Handle(Opcodes.H_INVOKESTATIC, "org/lwjgl/opengl/EXTBlendFuncSeparate", "glBlendFuncSeparateEXT", "(IIII)V", false);
|
||||
final ClassNode cn = makeClassWithInvokeDynamic(impl);
|
||||
|
||||
final boolean changed = new GLSMRedirector().transformClassNode("com.example.TestClass", cn);
|
||||
|
||||
assertTrue(changed);
|
||||
final Handle result = getResultHandle(cn);
|
||||
assertEquals(GLSM, result.getOwner());
|
||||
assertEquals("tryBlendFuncSeparate", result.getName());
|
||||
assertEquals("(IIII)V", result.getDesc());
|
||||
}
|
||||
|
||||
@Test
|
||||
void invokeDynamicNonGLHandleIsNotTouched() {
|
||||
final Handle impl = new Handle(Opcodes.H_INVOKESTATIC, "java/lang/System", "currentTimeMillis", "()J", false);
|
||||
@@ -188,6 +168,7 @@ class GLSMRedirectorTest {
|
||||
@Test
|
||||
void nonAwareDebugCallbackIsRedirectedNotPassedThrough() {
|
||||
assertRedirected("org/lwjgl/opengl/GL43", "glDebugMessageCallback", "(Lorg/lwjgl/opengl/KHRDebugCallback;)V", "glDebugMessageCallback");
|
||||
assertRedirected("org/lwjgl/opengl/KHRDebug", "glDebugMessageCallback", "(Lorg/lwjgl/opengl/KHRDebugCallback;)V", "glDebugMessageCallback");
|
||||
assertTrue(debugSeen().isEmpty());
|
||||
assertTrue(unmappedSeen().isEmpty());
|
||||
}
|
||||
@@ -240,54 +221,16 @@ class GLSMRedirectorTest {
|
||||
assertTrue(unmappedSeen().isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
void newlyMappedFramebufferAliasIsRedirected() {
|
||||
final ClassNode cn = makeClassWithMethodCall("org/lwjgl/opengl/EXTFramebufferObject", "glBindFramebufferEXT", "(II)V");
|
||||
|
||||
final boolean changed = new GLSMRedirector().transformClassNode("com.example.TestClass", cn);
|
||||
|
||||
assertTrue(changed);
|
||||
assertEquals(GLSM, firstCall(cn).owner);
|
||||
assertEquals("glBindFramebuffer", firstCall(cn).name);
|
||||
assertTrue(unmappedSeen().isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
void arbGenerateMipmapAliasIsRedirected() {
|
||||
final ClassNode cn = makeClassWithMethodCall("org/lwjgl/opengl/ARBFramebufferObject", "glGenerateMipmap", "(I)V");
|
||||
|
||||
final boolean changed = new GLSMRedirector().transformClassNode("com.example.TestClass", cn);
|
||||
|
||||
assertTrue(changed);
|
||||
assertEquals(GLSM, firstCall(cn).owner);
|
||||
assertEquals("glGenerateMipmap", firstCall(cn).name);
|
||||
assertEquals("(I)V", firstCall(cn).desc);
|
||||
assertTrue(unmappedSeen().isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
void extGenerateMipmapAliasIsRedirected() {
|
||||
final ClassNode cn = makeClassWithMethodCall("org/lwjgl/opengl/EXTFramebufferObject", "glGenerateMipmapEXT", "(I)V");
|
||||
|
||||
final boolean changed = new GLSMRedirector().transformClassNode("com.example.TestClass", cn);
|
||||
|
||||
assertTrue(changed);
|
||||
assertEquals(GLSM, firstCall(cn).owner);
|
||||
assertEquals("glGenerateMipmap", firstCall(cn).name);
|
||||
assertEquals("(I)V", firstCall(cn).desc);
|
||||
assertTrue(unmappedSeen().isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
void newlyMappedReadPixelsIsRedirected() {
|
||||
final ClassNode cn = makeClassWithMethodCall("org/lwjgl/opengl/GL11", "glReadPixels", "(IIIIIILjava/nio/IntBuffer;)V");
|
||||
|
||||
final boolean changed = new GLSMRedirector().transformClassNode("com.example.TestClass", cn);
|
||||
|
||||
assertTrue(changed);
|
||||
assertEquals(GLSM, firstCall(cn).owner);
|
||||
assertEquals("glReadPixels", firstCall(cn).name);
|
||||
assertTrue(unmappedSeen().isEmpty());
|
||||
@ParameterizedTest(name = "{1}")
|
||||
@CsvSource(delimiter = '|', value = {
|
||||
"org/lwjgl/opengl/EXTFramebufferObject | glBindFramebufferEXT | (II)V | glBindFramebuffer",
|
||||
"org/lwjgl/opengl/ARBFramebufferObject | glGenerateMipmap | (I)V | glGenerateMipmap",
|
||||
"org/lwjgl/opengl/EXTFramebufferObject | glGenerateMipmapEXT | (I)V | glGenerateMipmap",
|
||||
"org/lwjgl/opengl/GL11 | glReadPixels | (IIIIIILjava/nio/IntBuffer;)V | glReadPixels",
|
||||
"org/lwjgl/opengl/ARBOcclusionQuery | glGenQueriesARB | (Ljava/nio/IntBuffer;)V | glGenQueries"
|
||||
})
|
||||
void aliasIsRedirected(String owner, String name, String desc, String expectedName) {
|
||||
assertEquals(desc, assertRedirected(owner, name, desc, expectedName).desc);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -299,47 +242,29 @@ class GLSMRedirectorTest {
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void newlyMappedOcclusionQueryAliasIsRedirected() {
|
||||
final ClassNode cn = makeClassWithMethodCall("org/lwjgl/opengl/ARBOcclusionQuery", "glGenQueriesARB", "(Ljava/nio/IntBuffer;)V");
|
||||
|
||||
final boolean changed = new GLSMRedirector().transformClassNode("com.example.TestClass", cn);
|
||||
|
||||
assertTrue(changed);
|
||||
assertEquals(GLSM, firstCall(cn).owner);
|
||||
assertEquals("glGenQueries", firstCall(cn).name);
|
||||
assertTrue(unmappedSeen().isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
void utilCheckGLErrorIsRedirected() throws Exception {
|
||||
assertRedirectedToDeclaredTarget(new String[][]{{"org/lwjgl/opengl/Util", "checkGLError", "()V"}});
|
||||
}
|
||||
|
||||
@Test
|
||||
void indexedGettersHaveRealTargets() throws Exception {
|
||||
final Class<?> glsm = Class.forName(GLSM.replace('/', '.'), false, getClass().getClassLoader());
|
||||
assertDoesNotThrow(() -> glsm.getDeclaredMethod("glGetInteger", int.class, int.class), "LWJGL2 GL30.glGetInteger(pname, index) redirects here");
|
||||
assertDoesNotThrow(() -> glsm.getDeclaredMethod("glGetIntegeri", int.class, int.class), "LWJGL3 GL31C.glGetIntegeri(pname, index) redirects here");
|
||||
assertDoesNotThrow(() -> glsm.getDeclaredMethod("glGetIntegeri_v", int.class, int.class, java.nio.IntBuffer.class));
|
||||
assertDoesNotThrow(() -> glsm.getDeclaredMethod("glGetBooleani_v", int.class, int.class, java.nio.ByteBuffer.class));
|
||||
void indexedGettersHaveDeclaredTargets() throws Exception {
|
||||
assertRedirectedToDeclaredTarget(new String[][]{
|
||||
{"org/lwjgl/opengl/GL30", "glGetInteger", "(II)I"},
|
||||
{"org/lwjgl/opengl/GL31C", "glGetIntegeri", "(II)I"},
|
||||
{"org/lwjgl/opengl/GL30", "glGetIntegeri_v", "(IILjava/nio/IntBuffer;)V"},
|
||||
{"org/lwjgl/opengl/GL30", "glGetBooleani_v", "(IILjava/nio/ByteBuffer;)V"},
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void indexedGettersAreRedirected() {
|
||||
assertRedirected("org/lwjgl/opengl/GL30", "glGetInteger", "(II)I", "glGetInteger");
|
||||
assertRedirected("org/lwjgl/opengl/GL31C", "glGetIntegeri", "(II)I", "glGetIntegeri");
|
||||
assertRedirected("org/lwjgl/opengl/GL30", "glGetIntegeri_v", "(IILjava/nio/IntBuffer;)V", "glGetIntegeri_v");
|
||||
assertRedirected("org/lwjgl/opengl/GL30", "glGetBooleani_v", "(IILjava/nio/ByteBuffer;)V", "glGetBooleani_v");
|
||||
}
|
||||
|
||||
private void assertRedirected(String owner, String name, String desc, String expectedName) {
|
||||
private MethodInsnNode assertRedirected(String owner, String name, String desc, String expectedName) {
|
||||
final ClassNode cn = makeClassWithMethodCall(owner, name, desc);
|
||||
final boolean changed = new GLSMRedirector().transformClassNode("com.example.TestClass", cn);
|
||||
assertTrue(changed, owner + "." + name + " should redirect");
|
||||
assertEquals(GLSM, firstCall(cn).owner);
|
||||
assertEquals(expectedName, firstCall(cn).name);
|
||||
assertTrue(unmappedSeen().isEmpty(), owner + "." + name + " should not be recorded");
|
||||
return firstCall(cn);
|
||||
}
|
||||
|
||||
private static boolean glsmDeclares(String name, String desc) throws ClassNotFoundException {
|
||||
@@ -465,20 +390,6 @@ class GLSMRedirectorTest {
|
||||
assertRedirected("org/lwjgl/opengl/APPLEVertexArrayObject", "glGenVertexArraysAPPLE", "()I", "glGenVertexArrays");
|
||||
}
|
||||
|
||||
@Test
|
||||
void invokeDynamicGLCVariantIsRedirected() {
|
||||
final Handle impl = new Handle(Opcodes.H_INVOKESTATIC, "org/lwjgl/opengl/GL11C", "glDrawArrays", "(III)V", false);
|
||||
final ClassNode cn = makeClassWithInvokeDynamic(impl);
|
||||
|
||||
final boolean changed = new GLSMRedirector().transformClassNode("com.example.TestClass", cn);
|
||||
|
||||
assertTrue(changed);
|
||||
final Handle result = getResultHandle(cn);
|
||||
assertEquals(GLSM, result.getOwner());
|
||||
assertEquals("glDrawArrays", result.getName());
|
||||
assertEquals("(III)V", result.getDesc());
|
||||
}
|
||||
|
||||
private static final String AWARE_SHIM = "com/gtnewhorizons/angelica/sdlgpu/compat/AwareGLDebugShim";
|
||||
private static final String CALLBACK_I = "Lorg/lwjgl/opengl/GLDebugMessageCallbackI;";
|
||||
|
||||
@@ -502,15 +413,6 @@ class GLSMRedirectorTest {
|
||||
assertEquals("glDebugMessageCallback", firstCall(cn).name);
|
||||
}
|
||||
|
||||
@Test
|
||||
void nonAwareDebugMessageCallbackTargetsGLStateManager() {
|
||||
final ClassNode cn = makeClassWithMethodCall("org/lwjgl/opengl/KHRDebug", "glDebugMessageCallback", "(Lorg/lwjgl/opengl/KHRDebugCallback;)V");
|
||||
|
||||
assertTrue(new GLSMRedirector().transformClassNode("com.example.TestClass", cn, false));
|
||||
|
||||
assertEquals(GLSM, firstCall(cn).owner);
|
||||
}
|
||||
|
||||
@Test
|
||||
void awareGLUtilSetupDebugMessageCallbackIsRedirected() {
|
||||
for (String desc : new String[]{"()Lorg/lwjgl/system/Callback;", "(Ljava/io/PrintStream;)Lorg/lwjgl/system/Callback;"}) {
|
||||
|
||||
@@ -5,6 +5,7 @@ import org.lwjgl.BufferUtils;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL12;
|
||||
import org.lwjgl.opengl.GL13;
|
||||
import org.lwjgl.opengl.GL14;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.FloatBuffer;
|
||||
@@ -16,14 +17,15 @@ import java.util.stream.IntStream;
|
||||
import static org.junit.jupiter.api.Assertions.assertAll;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotEquals;
|
||||
|
||||
public class GLSMUtil {
|
||||
|
||||
// Cached GL limits (queried once at class load time)
|
||||
private static final int MAX_CLIP_PLANES = GL11.glGetInteger(GL11.GL_MAX_CLIP_PLANES);
|
||||
private static final int MAX_LIGHTS = GL11.glGetInteger(GL11.GL_MAX_LIGHTS);
|
||||
private static final int MAX_TEXTURE_UNITS = GL11.glGetInteger(GL13.GL_MAX_TEXTURE_UNITS);
|
||||
// Compat-only pnames, so they load with resetGLState() and not with the class: a core driver answers GL_INVALID_ENUM
|
||||
private static final class CompatLimits {
|
||||
static final int MAX_CLIP_PLANES = GL11.glGetInteger(GL11.GL_MAX_CLIP_PLANES);
|
||||
static final int MAX_LIGHTS = GL11.glGetInteger(GL11.GL_MAX_LIGHTS);
|
||||
static final int MAX_TEXTURE_UNITS = GL11.glGetInteger(GL13.GL_MAX_TEXTURE_UNITS);
|
||||
}
|
||||
|
||||
// MAP1 evaluator constants for DRY loops
|
||||
private static final int[] MAP1_STATES = {
|
||||
@@ -76,13 +78,25 @@ public class GLSMUtil {
|
||||
GL11.GL_FOG_MODE, GL11.GL_FOG_INDEX,
|
||||
// Also removed from core profile
|
||||
GL11.GL_POINT_SMOOTH, GL11.GL_POLYGON_STIPPLE,
|
||||
GL11.GL_INDEX_LOGIC_OP, GL11.GL_AUTO_NORMAL));
|
||||
GL11.GL_INDEX_LOGIC_OP, GL11.GL_AUTO_NORMAL,
|
||||
GL13.GL_CLIENT_ACTIVE_TEXTURE,
|
||||
GL11.GL_VERTEX_ARRAY, GL11.GL_NORMAL_ARRAY, GL11.GL_COLOR_ARRAY, GL11.GL_TEXTURE_COORD_ARRAY,
|
||||
GL11.GL_INDEX_ARRAY, GL11.GL_EDGE_FLAG_ARRAY, GL14.GL_SECONDARY_COLOR_ARRAY, GL14.GL_FOG_COORDINATE_ARRAY,
|
||||
GL11.GL_VERTEX_ARRAY_SIZE, GL11.GL_VERTEX_ARRAY_TYPE, GL11.GL_VERTEX_ARRAY_STRIDE));
|
||||
|
||||
for (int cap : MAP1_STATES) caps.add(cap);
|
||||
for (int cap : MAP2_STATES) caps.add(cap);
|
||||
return caps;
|
||||
}
|
||||
|
||||
// A core driver rejects these caps with GL_INVALID_ENUM. Only that error is dropped: one already pending is the test's.
|
||||
private static boolean driverBoolean(int glCap, boolean isEnabled) {
|
||||
assertEquals(GL11.GL_NO_ERROR, GL11.glGetError(), "GL error pending before the driver query");
|
||||
final boolean value = isEnabled ? GL11.glIsEnabled(glCap) : GL11.glGetBoolean(glCap);
|
||||
while (GL11.glGetError() != GL11.GL_NO_ERROR) {}
|
||||
return value;
|
||||
}
|
||||
|
||||
private static boolean isFFPOnly(int glCap) {
|
||||
return FFP_ONLY_CAPS.contains(glCap);
|
||||
}
|
||||
@@ -94,7 +108,7 @@ public class GLSMUtil {
|
||||
public static void verifyIsEnabled(int glCap, boolean expected, String message) {
|
||||
if (isFFPOnly(glCap)) {
|
||||
assertAll(message,
|
||||
() -> assertFalse(GL11.glIsEnabled(glCap), "GL State Mismatch - cache-only cap reached the driver"),
|
||||
() -> assertFalse(driverBoolean(glCap, true), "GL State Mismatch - cache-only cap reached the driver"),
|
||||
() -> assertEquals(expected, GLStateManager.glIsEnabled(glCap), "GLSM State Mismatch")
|
||||
);
|
||||
} else {
|
||||
@@ -112,7 +126,7 @@ public class GLSMUtil {
|
||||
public static void verifyState(int glCap, boolean expected, String message) {
|
||||
if (isFFPOnly(glCap)) {
|
||||
assertAll(message,
|
||||
() -> assertFalse(GL11.glGetBoolean(glCap), "GL State Mismatch - cache-only cap reached the driver"),
|
||||
() -> assertFalse(driverBoolean(glCap, false), "GL State Mismatch - cache-only cap reached the driver"),
|
||||
() -> assertEquals(expected, GLStateManager.glGetBoolean(glCap), "GLSM State Mismatch")
|
||||
);
|
||||
} else {
|
||||
@@ -208,22 +222,6 @@ public class GLSMUtil {
|
||||
}
|
||||
}
|
||||
|
||||
public static void verifyNotDefaultState(int glCap, float[] expected, String message) {
|
||||
if (isFFPOnly(glCap)) {
|
||||
GLStateManager.glGetFloat(glCap, (FloatBuffer) glsmFloatBuffer.clear());
|
||||
IntStream.range(0, expected.length).forEach(i ->
|
||||
assertNotEquals(expected[i], glsmFloatBuffer.get(i), 0.0001f, message + " - GLSM State Mismatch: " + i)
|
||||
);
|
||||
} else {
|
||||
GL11.glGetFloat(glCap, (FloatBuffer) glFloatBuffer.clear());
|
||||
GLStateManager.glGetFloat(glCap, (FloatBuffer) glsmFloatBuffer.clear());
|
||||
IntStream.range(0, expected.length).forEach(i -> assertAll(message,
|
||||
() -> assertNotEquals(expected[i], glFloatBuffer.get(i), 0.0001f, "GL State Mismatch: " + i),
|
||||
() -> assertNotEquals(expected[i], glsmFloatBuffer.get(i), 0.0001f, "GLSM State Mismatch: " + i)
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
public static void verifyState(int glCap, boolean[] expected) {
|
||||
verifyState(glCap, expected, "Boolean State Mismatch");
|
||||
}
|
||||
@@ -275,7 +273,7 @@ public class GLSMUtil {
|
||||
GLStateManager.disableBlend();
|
||||
|
||||
// Disable all clip planes (using cached MAX_CLIP_PLANES)
|
||||
for(int i = 0; i < MAX_CLIP_PLANES; i++) {
|
||||
for(int i = 0; i < CompatLimits.MAX_CLIP_PLANES; i++) {
|
||||
GLStateManager.glDisable(GL11.GL_CLIP_PLANE0 + i);
|
||||
}
|
||||
|
||||
@@ -290,7 +288,7 @@ public class GLSMUtil {
|
||||
GLStateManager.disableLighting();
|
||||
|
||||
// Disable all lights (using cached MAX_LIGHTS)
|
||||
for(int i = 0; i < MAX_LIGHTS; i++) {
|
||||
for(int i = 0; i < CompatLimits.MAX_LIGHTS; i++) {
|
||||
GLStateManager.disableLight(i);
|
||||
}
|
||||
|
||||
@@ -330,7 +328,7 @@ public class GLSMUtil {
|
||||
GLStateManager.glDisable(GL11.GL_STENCIL_TEST);
|
||||
|
||||
// Reset texture state for all units (using cached MAX_TEXTURE_UNITS)
|
||||
for(int i = 0; i < MAX_TEXTURE_UNITS; i++) {
|
||||
for(int i = 0; i < CompatLimits.MAX_TEXTURE_UNITS; i++) {
|
||||
GLStateManager.glActiveTexture(GL13.GL_TEXTURE0 + i);
|
||||
GLStateManager.glDisable(GL11.GL_TEXTURE_1D);
|
||||
GLStateManager.disableTexture(); // GL_TEXTURE_2D
|
||||
@@ -383,9 +381,9 @@ public class GLSMUtil {
|
||||
|
||||
public static void setClientState(int glCap, boolean state) {
|
||||
if (state) {
|
||||
GL11.glEnableClientState(glCap);
|
||||
GLStateManager.glEnableClientState(glCap);
|
||||
} else {
|
||||
GL11.glDisableClientState(glCap);
|
||||
GLStateManager.glDisableClientState(glCap);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@ package com.gtnewhorizons.angelica.glsm;
|
||||
import com.gtnewhorizons.angelica.config.SystemProperties;
|
||||
import com.gtnewhorizons.angelica.glsm.ffp.ShaderManager;
|
||||
import com.gtnewhorizons.angelica.glsm.hooks.GLSMInitConfig;
|
||||
import org.junit.jupiter.api.extension.AfterEachCallback;
|
||||
import org.junit.jupiter.api.extension.BeforeAllCallback;
|
||||
import org.junit.jupiter.api.extension.BeforeEachCallback;
|
||||
import org.junit.jupiter.api.extension.ExtensionContext;
|
||||
@@ -14,12 +15,13 @@ import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL32;
|
||||
import org.lwjgl.opengl.PixelFormat;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.extension.ExtensionContext.Namespace.GLOBAL;
|
||||
|
||||
/**
|
||||
* 3.3 core forward-compatible context. FFP emulation stays enabled, so per-test isolation only deactivates it.
|
||||
*/
|
||||
public class GLSMCoreExtension implements BeforeAllCallback, BeforeEachCallback, ExtensionContext.Store.CloseableResource {
|
||||
public class GLSMCoreExtension implements BeforeAllCallback, BeforeEachCallback, AfterEachCallback, ExtensionContext.Store.CloseableResource {
|
||||
|
||||
private static boolean started = false;
|
||||
private static Throwable startFailure;
|
||||
@@ -75,6 +77,13 @@ public class GLSMCoreExtension implements BeforeAllCallback, BeforeEachCallback,
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterEach(ExtensionContext context) {
|
||||
final int error = GL11.glGetError();
|
||||
while (GL11.glGetError() != GL11.GL_NO_ERROR) {}
|
||||
assertEquals(GL11.GL_NO_ERROR, error, () -> "GL Error: 0x" + Integer.toHexString(error));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
if (Display.isCreated()) Display.destroy();
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
package com.gtnewhorizons.angelica.glsm;
|
||||
|
||||
import org.lwjgl.BufferUtils;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL13;
|
||||
import org.lwjgl.opengl.GL20;
|
||||
|
||||
import java.nio.FloatBuffer;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotEquals;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
|
||||
public final class GlTestSupport {
|
||||
|
||||
public static final String TRIVIAL_VS = "#version 330 core\nvoid main() { gl_Position = vec4(0.0); }\n";
|
||||
public static final String TRIVIAL_FS = "#version 330 core\nout vec4 color;\nvoid main() { color = vec4(1.0); }\n";
|
||||
|
||||
private GlTestSupport() {}
|
||||
|
||||
public static void drainErrors() {
|
||||
while (GL11.glGetError() != GL11.GL_NO_ERROR) {}
|
||||
}
|
||||
|
||||
public static int compile(int type, String source) {
|
||||
final int shader = GLStateManager.glCreateShader(type);
|
||||
GLStateManager.glShaderSource(shader, source);
|
||||
GLStateManager.glCompileShader(shader);
|
||||
if (GLStateManager.glGetShaderi(shader, GL20.GL_COMPILE_STATUS) == 0) {
|
||||
fail("test shader failed to compile:\n" + GLStateManager.glGetShaderInfoLog(shader, 4096) + "\n\n" + source);
|
||||
}
|
||||
return shader;
|
||||
}
|
||||
|
||||
/** Links and deletes the two shaders. */
|
||||
public static int link(int vs, int fs) {
|
||||
final int p = GLStateManager.glCreateProgram();
|
||||
GLStateManager.glAttachShader(p, vs);
|
||||
GLStateManager.glAttachShader(p, fs);
|
||||
GLStateManager.glLinkProgram(p);
|
||||
assertNotEquals(0, GLStateManager.glGetProgrami(p, GL20.GL_LINK_STATUS), () -> "test program must link: " + GLStateManager.glGetProgramInfoLog(p, 4096));
|
||||
GLStateManager.glDeleteShader(vs);
|
||||
GLStateManager.glDeleteShader(fs);
|
||||
return p;
|
||||
}
|
||||
|
||||
public static int program(String vertexSource, String fragmentSource) {
|
||||
return link(compile(GL20.GL_VERTEX_SHADER, vertexSource), compile(GL20.GL_FRAGMENT_SHADER, fragmentSource));
|
||||
}
|
||||
|
||||
/** Raw driver GL_TEXTURE_BINDING_2D of a unit, bypassing the GLSM cache. */
|
||||
public static int driverTextureBinding(int unit) {
|
||||
final int saved = GL11.glGetInteger(GL13.GL_ACTIVE_TEXTURE);
|
||||
GL13.glActiveTexture(GL13.GL_TEXTURE0 + unit);
|
||||
final int binding = GL11.glGetInteger(GL11.GL_TEXTURE_BINDING_2D);
|
||||
GL13.glActiveTexture(saved);
|
||||
return binding;
|
||||
}
|
||||
|
||||
public static FloatBuffer floats(float... values) {
|
||||
final FloatBuffer buf = BufferUtils.createFloatBuffer(values.length);
|
||||
buf.put(values).flip();
|
||||
return buf;
|
||||
}
|
||||
|
||||
/** GLSM's answer for a 16-float matrix pname. */
|
||||
public static FloatBuffer matrix(int pname) {
|
||||
final FloatBuffer buf = BufferUtils.createFloatBuffer(16);
|
||||
GLStateManager.glGetFloat(pname, buf);
|
||||
return buf;
|
||||
}
|
||||
|
||||
public static FloatBuffer modelview() {
|
||||
return matrix(GL11.GL_MODELVIEW_MATRIX);
|
||||
}
|
||||
|
||||
public static void assertMatrixEquals(FloatBuffer expected, FloatBuffer actual, String message) {
|
||||
for (int i = 0; i < 16; i++) {
|
||||
assertEquals(expected.get(i), actual.get(i), 0.001f, message + " (element " + i + ")");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
package com.gtnewhorizons.angelica.glsm;
|
||||
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL13;
|
||||
import org.lwjgl.opengl.GL14;
|
||||
import org.lwjgl.opengl.GL20;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
public final class LegacyQueryFixture {
|
||||
|
||||
public static final int[] CLIENT_ARRAY_CAPS = {
|
||||
GL11.GL_VERTEX_ARRAY, GL11.GL_NORMAL_ARRAY, GL11.GL_COLOR_ARRAY, GL11.GL_TEXTURE_COORD_ARRAY,
|
||||
GL11.GL_INDEX_ARRAY, GL11.GL_EDGE_FLAG_ARRAY, GL14.GL_SECONDARY_COLOR_ARRAY, GL14.GL_FOG_COORDINATE_ARRAY
|
||||
};
|
||||
|
||||
public static final int[] HINT_TARGETS = {
|
||||
GL11.GL_PERSPECTIVE_CORRECTION_HINT, GL11.GL_POINT_SMOOTH_HINT, GL11.GL_LINE_SMOOTH_HINT, GL11.GL_POLYGON_SMOOTH_HINT,
|
||||
GL11.GL_FOG_HINT, GL13.GL_TEXTURE_COMPRESSION_HINT, GL14.GL_GENERATE_MIPMAP_HINT, GL20.GL_FRAGMENT_SHADER_DERIVATIVE_HINT
|
||||
};
|
||||
|
||||
private LegacyQueryFixture() {}
|
||||
|
||||
/** Every pname LegacyQueries answers from the cache. */
|
||||
public static int[] legacyPnames() {
|
||||
final int[] out = new int[0x10000];
|
||||
int n = 0;
|
||||
for (int pname = 0; pname <= 0xFFFF; pname++) {
|
||||
if (LegacyQueries.desc(pname) != 0) {
|
||||
out[n++] = pname;
|
||||
}
|
||||
}
|
||||
return Arrays.copyOf(out, n);
|
||||
}
|
||||
|
||||
public static String hex(int pname) {
|
||||
return "0x" + Integer.toHexString(pname);
|
||||
}
|
||||
|
||||
public static void setEnabled(int cap, boolean on) {
|
||||
if (on) {
|
||||
GLStateManager.glEnable(cap);
|
||||
} else {
|
||||
GLStateManager.glDisable(cap);
|
||||
}
|
||||
}
|
||||
|
||||
public static void popAttribTo(int base) {
|
||||
while (GLStateManager.getAttribDepth() > base) {
|
||||
GLStateManager.glPopAttrib();
|
||||
}
|
||||
}
|
||||
|
||||
public static void drainClientAttribStack() {
|
||||
while (GLStateManager.glGetInteger(GL11.GL_CLIENT_ATTRIB_STACK_DEPTH) > 0) {
|
||||
GLStateManager.glPopClientAttrib();
|
||||
}
|
||||
}
|
||||
|
||||
/** Enables then disables {@code cap}, checking glIsEnabled, glGetBoolean and glGetInteger at each step. */
|
||||
public static void assertEnableRoundTrip(int cap, boolean clientState) {
|
||||
final String name = hex(cap);
|
||||
if (clientState) {
|
||||
GLStateManager.glEnableClientState(cap);
|
||||
} else {
|
||||
GLStateManager.glEnable(cap);
|
||||
}
|
||||
assertTrue(GLStateManager.glIsEnabled(cap), "enabled isEnabled " + name);
|
||||
assertTrue(GLStateManager.glGetBoolean(cap), "enabled getBoolean " + name);
|
||||
assertEquals(1, GLStateManager.glGetInteger(cap), "enabled getInteger " + name);
|
||||
if (clientState) {
|
||||
GLStateManager.glDisableClientState(cap);
|
||||
} else {
|
||||
GLStateManager.glDisable(cap);
|
||||
}
|
||||
assertFalse(GLStateManager.glIsEnabled(cap), "disabled isEnabled " + name);
|
||||
assertFalse(GLStateManager.glGetBoolean(cap), "disabled getBoolean " + name);
|
||||
assertEquals(0, GLStateManager.glGetInteger(cap), "disabled getInteger " + name);
|
||||
}
|
||||
}
|
||||
@@ -4,20 +4,18 @@ import com.gtnewhorizon.gtnhlib.client.renderer.vertex.VertexFormat;
|
||||
import com.gtnewhorizon.gtnhlib.client.renderer.vertex.VertexFormatElement;
|
||||
import com.gtnewhorizon.gtnhlib.client.renderer.vertex.VertexFormatElement.Usage;
|
||||
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||
import com.gtnewhorizons.angelica.glsm.GlTestSupport;
|
||||
import org.lwjgl.BufferUtils;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL13;
|
||||
import org.lwjgl.opengl.GL15;
|
||||
import org.lwjgl.opengl.GL20;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.function.IntFunction;
|
||||
|
||||
import static com.gtnewhorizon.gtnhlib.bytebuf.MemoryUtilities.memAddress0;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
|
||||
public final class FfpFixture {
|
||||
|
||||
@@ -128,26 +126,7 @@ public final class FfpFixture {
|
||||
}
|
||||
|
||||
private static int buildProgram() {
|
||||
final int vs = compile(GL20.GL_VERTEX_SHADER, VS);
|
||||
final int fs = compile(GL20.GL_FRAGMENT_SHADER, FS);
|
||||
final int p = GLStateManager.glCreateProgram();
|
||||
GLStateManager.glAttachShader(p, vs);
|
||||
GLStateManager.glAttachShader(p, fs);
|
||||
GLStateManager.glLinkProgram(p);
|
||||
assertNotEquals(0, GLStateManager.glGetProgrami(p, GL20.GL_LINK_STATUS), () -> "test program must link: " + GLStateManager.glGetProgramInfoLog(p, 4096));
|
||||
GLStateManager.glDeleteShader(vs);
|
||||
GLStateManager.glDeleteShader(fs);
|
||||
return p;
|
||||
}
|
||||
|
||||
private static int compile(int type, String source) {
|
||||
final int shader = GLStateManager.glCreateShader(type);
|
||||
GLStateManager.glShaderSource(shader, source);
|
||||
GLStateManager.glCompileShader(shader);
|
||||
if (GLStateManager.glGetShaderi(shader, GL20.GL_COMPILE_STATUS) == 0) {
|
||||
fail("test shader failed to compile:\n" + GLStateManager.glGetShaderInfoLog(shader, 4096) + "\n\n" + source);
|
||||
}
|
||||
return shader;
|
||||
return GlTestSupport.program(VS, FS);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+3
@@ -451,6 +451,7 @@ public final class Lwjgl3GLRenderBackend extends RenderBackend {
|
||||
|
||||
@Override
|
||||
public void hint(int target, int mode) {
|
||||
if (RenderSystem.isGLES() && target != GL20C.GL_FRAGMENT_SHADER_DERIVATIVE_HINT) return;
|
||||
GL11C.glHint(target, mode);
|
||||
}
|
||||
|
||||
@@ -1822,11 +1823,13 @@ public final class Lwjgl3GLRenderBackend extends RenderBackend {
|
||||
|
||||
@Override
|
||||
public void pointParameterf(int pname, float param) {
|
||||
if (RenderSystem.isGLES()) return;
|
||||
GL14C.glPointParameterf(pname, param);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pointParameteri(int pname, int param) {
|
||||
if (RenderSystem.isGLES()) return;
|
||||
GL14C.glPointParameteri(pname, param);
|
||||
}
|
||||
|
||||
|
||||
@@ -4126,7 +4126,7 @@ public class SDLGPURenderBackend extends RenderBackend {
|
||||
}
|
||||
@Override public void getFloat(int pname, FloatBuffer params) {
|
||||
if (params == null || params.remaining() == 0) return;
|
||||
if (pname == GL12.GL_ALIASED_LINE_WIDTH_RANGE || pname == GL11.GL_LINE_WIDTH_RANGE) {
|
||||
if (pname == GL12.GL_ALIASED_LINE_WIDTH_RANGE || pname == GL11.GL_LINE_WIDTH_RANGE || pname == GL12.GL_ALIASED_POINT_SIZE_RANGE || pname == GL11.GL_POINT_SIZE_RANGE) {
|
||||
if (params.remaining() >= 2) {
|
||||
params.put(params.position(), 1.0f);
|
||||
params.put(params.position() + 1, 1.0f);
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package com.gtnewhorizons.angelica.sdlgpu;
|
||||
|
||||
import com.gtnewhorizons.angelica.glsm.testutil.Reflect;
|
||||
import com.gtnewhorizons.angelica.sdlgpu.frame.ContextState;
|
||||
import com.gtnewhorizons.angelica.sdlgpu.resource.FboState;
|
||||
import com.gtnewhorizons.angelica.sdlgpu.resource.ResourceManager;
|
||||
@@ -31,7 +30,7 @@ class DrawBuffersLimitTest {
|
||||
@BeforeAll
|
||||
static void createBackend() {
|
||||
backend = new SDLGPURenderBackend();
|
||||
resourceManager = Reflect.get(backend, "resourceManager");
|
||||
resourceManager = SdlTestRig.resourceManagerOf(backend);
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
|
||||
+15
-24
@@ -1,38 +1,29 @@
|
||||
package com.gtnewhorizons.angelica.sdlgpu;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
import org.lwjgl.opengl.GL15;
|
||||
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotEquals;
|
||||
import static org.lwjgl.sdl.SDLGPU.SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_READ;
|
||||
import static org.lwjgl.sdl.SDLGPU.SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_WRITE;
|
||||
import static org.lwjgl.sdl.SDLGPU.SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_SIMULTANEOUS_READ_WRITE;
|
||||
|
||||
class ImageAccessUsageMappingTest {
|
||||
|
||||
@Test
|
||||
void readOnlyRequestsOnlyStorageRead() {
|
||||
assertEquals(SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_READ, SDLGPURenderBackend.imageUsageForAccess(GL15.GL_READ_ONLY));
|
||||
/** Never READ|WRITE together: that leaves SDL's DefaultTextureUsageMode ambiguous on a sampled texture. */
|
||||
static Stream<Arguments> accessModes() {
|
||||
return Stream.of(
|
||||
Arguments.of("GL_READ_ONLY", GL15.GL_READ_ONLY, SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_READ),
|
||||
Arguments.of("GL_WRITE_ONLY", GL15.GL_WRITE_ONLY, SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_WRITE),
|
||||
Arguments.of("GL_READ_WRITE", GL15.GL_READ_WRITE, SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_WRITE));
|
||||
}
|
||||
|
||||
@Test
|
||||
void writeOnlyRequestsOnlyStorageWrite() {
|
||||
assertEquals(SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_WRITE, SDLGPURenderBackend.imageUsageForAccess(GL15.GL_WRITE_ONLY));
|
||||
}
|
||||
|
||||
@Test
|
||||
void readWriteRequestsOnlyStorageWrite() {
|
||||
assertEquals(SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_WRITE, SDLGPURenderBackend.imageUsageForAccess(GL15.GL_READ_WRITE));
|
||||
}
|
||||
|
||||
@Test
|
||||
void noAccessModeRequestsBothStorageBits() {
|
||||
final int both = SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_READ | SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_WRITE;
|
||||
for (int access : new int[] { GL15.GL_READ_ONLY, GL15.GL_WRITE_ONLY, GL15.GL_READ_WRITE }) {
|
||||
final int usage = SDLGPURenderBackend.imageUsageForAccess(access);
|
||||
assertEquals(0, usage & SDL_GPU_TEXTUREUSAGE_COMPUTE_STORAGE_SIMULTANEOUS_READ_WRITE);
|
||||
assertNotEquals(both, usage & both, "READ|WRITE together leaves SDL's DefaultTextureUsageMode ambiguous on a sampled texture");
|
||||
}
|
||||
@ParameterizedTest(name = "{0}")
|
||||
@MethodSource("accessModes")
|
||||
void accessModeRequestsExactlyOneStorageBit(String name, int access, int expectedUsage) {
|
||||
assertEquals(expectedUsage, SDLGPURenderBackend.imageUsageForAccess(access));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package com.gtnewhorizons.angelica.sdlgpu;
|
||||
|
||||
import com.gtnewhorizons.angelica.sdlgpu.resource.PixelOps;
|
||||
import org.junit.jupiter.api.extension.AfterAllCallback;
|
||||
import org.junit.jupiter.api.extension.BeforeAllCallback;
|
||||
import org.junit.jupiter.api.extension.ExtensionContext;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL30;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.lwjgl.sdl.SDLGPU.SDL_GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET;
|
||||
|
||||
/** Owns one real SDL GPU device per test class. Runs before the class's own {@code @BeforeAll} and after its {@code @AfterAll}. */
|
||||
public final class RealDeviceExtension implements BeforeAllCallback, AfterAllCallback {
|
||||
|
||||
private static SdlTestRig rig;
|
||||
|
||||
public record Target(long texture, int sdlFormat) {}
|
||||
|
||||
public static SdlTestRig rig() {
|
||||
return rig;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beforeAll(ExtensionContext context) throws Exception {
|
||||
rig = SdlTestRig.acquireRealDevice();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterAll(ExtensionContext context) {
|
||||
if (rig != null && rig.frameManager.isFrameActive()) rig.frameManager.endFrame();
|
||||
rig = null;
|
||||
SdlTestRig.releaseRealDevice();
|
||||
}
|
||||
|
||||
public static Target colorTarget(int glId, int width, int height) {
|
||||
final long texture = rig.resourceManager.createTexture(glId, GL11.GL_TEXTURE_2D, GL11.GL_RGBA8, width, height, 1, 1);
|
||||
assertTrue(texture != 0, "color target creation failed");
|
||||
return new Target(texture, rig.resourceManager.getTextureMeta(glId).sdlFormat());
|
||||
}
|
||||
|
||||
public static Target depthStencilTarget(int glId, int width, int height) {
|
||||
rig.resourceManager.cachePreferredDepthFormats();
|
||||
rig.resourceManager.createTexture(glId, GL11.GL_TEXTURE_2D, GL30.GL_DEPTH24_STENCIL8, width, height, 1, 1);
|
||||
final long texture = rig.resourceManager.ensureTextureUsage(glId, SDL_GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET);
|
||||
assertTrue(texture != 0, "depth+stencil target creation failed");
|
||||
final int format = rig.resourceManager.getTextureMeta(glId).sdlFormat();
|
||||
assertTrue(PixelOps.isDepthStencilFormat(format), "test needs a packed depth+stencil format");
|
||||
return new Target(texture, format);
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,6 @@ import org.lwjgl.opengl.GL20;
|
||||
import org.lwjgl.opengl.GL30;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
class SDLGPUBufferQueryTest {
|
||||
|
||||
@@ -28,11 +27,6 @@ class SDLGPUBufferQueryTest {
|
||||
assertEquals(GL11.GL_NONE, SDLGPURenderBackend.bufferEnum(7, -1));
|
||||
}
|
||||
|
||||
@Test
|
||||
void defaultMatchesGLStateManagerDeclaredDefault() {
|
||||
assertEquals(0x405, SDLGPURenderBackend.bufferEnum(0, 0));
|
||||
}
|
||||
|
||||
@Test
|
||||
void boundTextureReadsTheActiveUnitsSlot() {
|
||||
final int[] bound = {11, 22, 33, 44};
|
||||
@@ -56,12 +50,6 @@ class SDLGPUBufferQueryTest {
|
||||
assertEquals(256, SDLGPURenderBackend.deviceLimit(GL30.GL_MAX_ARRAY_TEXTURE_LAYERS));
|
||||
}
|
||||
|
||||
@Test
|
||||
void uniformLimitFitsSdlsUboSection() {
|
||||
assertTrue(SDLGPURenderBackend.deviceLimit(GL20.GL_MAX_VERTEX_UNIFORM_COMPONENTS) * 4 <= 4096);
|
||||
assertTrue(SDLGPURenderBackend.deviceLimit(GL30.GL_MAX_ARRAY_TEXTURE_LAYERS) <= 256);
|
||||
}
|
||||
|
||||
@Test
|
||||
void nonLimitPnamesAreNotClaimed() {
|
||||
assertEquals(-1, SDLGPURenderBackend.deviceLimit(GL11.GL_DRAW_BUFFER));
|
||||
|
||||
@@ -5,12 +5,11 @@ import com.gtnewhorizons.angelica.sdlgpu.device.Device;
|
||||
import com.gtnewhorizons.angelica.sdlgpu.frame.ContextState;
|
||||
import com.gtnewhorizons.angelica.sdlgpu.frame.FrameManager;
|
||||
import com.gtnewhorizons.angelica.sdlgpu.resource.ResourceManager;
|
||||
import com.gtnewhorizons.angelica.sdlgpu.resource.TransferThread;
|
||||
import org.lwjgl.sdl.SDLError;
|
||||
import org.lwjgl.sdl.SDLHints;
|
||||
import org.lwjgl.sdl.SDLInit;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
import static org.junit.jupiter.api.Assumptions.assumeTrue;
|
||||
import static org.lwjgl.sdl.SDLGPU.SDL_CreateGPUDevice;
|
||||
import static org.lwjgl.sdl.SDLGPU.SDL_DestroyGPUDevice;
|
||||
@@ -31,16 +30,12 @@ public final class SdlTestRig {
|
||||
public final ResourceManager resourceManager;
|
||||
public final long sdlHandle;
|
||||
|
||||
private SdlTestRig(long sdlHandle) throws ReflectiveOperationException {
|
||||
private SdlTestRig(long sdlHandle) {
|
||||
this.sdlHandle = sdlHandle;
|
||||
this.device = new Device();
|
||||
if (sdlHandle != 0L) {
|
||||
final Field deviceField = Device.class.getDeclaredField("device");
|
||||
deviceField.setAccessible(true);
|
||||
deviceField.setLong(this.device, sdlHandle);
|
||||
final Field formatsField = Device.class.getDeclaredField("supportedShaderFormats");
|
||||
formatsField.setAccessible(true);
|
||||
formatsField.setInt(this.device, SDL_GetGPUShaderFormats(sdlHandle));
|
||||
Reflect.set(this.device, "device", sdlHandle);
|
||||
Reflect.set(this.device, "supportedShaderFormats", SDL_GetGPUShaderFormats(sdlHandle));
|
||||
Reflect.set(this.device, "driverName", SDL_GetGPUDeviceDriver(sdlHandle));
|
||||
Reflect.invoke(this.device, "probeFences", new Class<?>[] { int.class }, SDL_GetVersion());
|
||||
}
|
||||
@@ -49,11 +44,7 @@ public final class SdlTestRig {
|
||||
}
|
||||
|
||||
public static SdlTestRig create() {
|
||||
try {
|
||||
return new SdlTestRig(0L);
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
return new SdlTestRig(0L);
|
||||
}
|
||||
|
||||
public static ResourceManager resourceManager() {
|
||||
@@ -68,6 +59,31 @@ public final class SdlTestRig {
|
||||
return Reflect.invokeStatic(SDLGPURenderBackend.class, "s", new Class<?>[0]);
|
||||
}
|
||||
|
||||
public static ResourceManager resourceManagerOf(SDLGPURenderBackend backend) {
|
||||
return Reflect.get(backend, "resourceManager");
|
||||
}
|
||||
|
||||
/** Not installed on the resource manager; pair with {@link #shutdown(TransferThread)}. */
|
||||
public TransferThread newTransferThread() {
|
||||
return new TransferThread(device, resourceManager);
|
||||
}
|
||||
|
||||
public TransferThread installTransferThread() {
|
||||
final TransferThread tt = newTransferThread();
|
||||
resourceManager.setTransferThread(tt);
|
||||
return tt;
|
||||
}
|
||||
|
||||
public static void shutdown(TransferThread tt) {
|
||||
tt.shutdown();
|
||||
try {
|
||||
tt.getThread().join(5_000L);
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static long realSdlDevice;
|
||||
|
||||
private static final int SHADER_FORMATS = SDL_GPU_SHADERFORMAT_SPIRV | SDL_GPU_SHADERFORMAT_MSL | SDL_GPU_SHADERFORMAT_DXBC | SDL_GPU_SHADERFORMAT_DXIL;
|
||||
@@ -77,7 +93,7 @@ public final class SdlTestRig {
|
||||
assumeTrue(SDLInit.SDL_Init(SDL_INIT_VIDEO), () -> "SDL_Init failed: " + SDLError.SDL_GetError());
|
||||
}
|
||||
|
||||
public static SdlTestRig acquireRealDevice() throws ReflectiveOperationException {
|
||||
public static SdlTestRig acquireRealDevice() {
|
||||
initSdlVideo();
|
||||
realSdlDevice = SDL_CreateGPUDevice(SHADER_FORMATS, true, (CharSequence) null);
|
||||
assumeTrue(realSdlDevice != 0, "No SDL GPU device: " + SDLError.SDL_GetError());
|
||||
|
||||
@@ -9,7 +9,6 @@ import org.lwjgl.opengl.GL15;
|
||||
import org.lwjgl.opengl.GL31;
|
||||
import org.lwjgl.system.MemoryUtil;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
@@ -20,11 +19,9 @@ class UboShadowSubDataTest {
|
||||
private static ResourceManager resourceManager;
|
||||
|
||||
@BeforeAll
|
||||
static void createBackend() throws Exception {
|
||||
static void createBackend() {
|
||||
backend = new SDLGPURenderBackend();
|
||||
final Field f = SDLGPURenderBackend.class.getDeclaredField("resourceManager");
|
||||
f.setAccessible(true);
|
||||
resourceManager = (ResourceManager) f.get(backend);
|
||||
resourceManager = SdlTestRig.resourceManagerOf(backend);
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
|
||||
+3
-6
@@ -1,5 +1,6 @@
|
||||
package com.gtnewhorizons.angelica.sdlgpu;
|
||||
|
||||
import com.gtnewhorizons.angelica.glsm.testutil.Reflect;
|
||||
import com.gtnewhorizons.angelica.sdlgpu.frame.ContextState;
|
||||
import com.gtnewhorizons.angelica.sdlgpu.pipeline.PipelineApplier;
|
||||
import com.gtnewhorizons.angelica.sdlgpu.shader.ShaderManager;
|
||||
@@ -9,7 +10,6 @@ import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.lwjgl.system.MemoryUtil;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.nio.FloatBuffer;
|
||||
import java.nio.IntBuffer;
|
||||
|
||||
@@ -48,11 +48,8 @@ class UniformNegativeLocationTest {
|
||||
st.releaseUniformStaging(prog);
|
||||
}
|
||||
|
||||
private static void clearApplier(SDLGPURenderBackend backend) throws Exception {
|
||||
final Field f = SDLGPURenderBackend.class.getDeclaredField("pipelineApplier");
|
||||
f.setAccessible(true);
|
||||
f.set(backend, null);
|
||||
assertNull(f.get(backend), "test rig failed to null the applier");
|
||||
private static void clearApplier(SDLGPURenderBackend backend) {
|
||||
Reflect.set(backend, "pipelineApplier", null);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
+3
-25
@@ -1,5 +1,6 @@
|
||||
package com.gtnewhorizons.angelica.sdlgpu.compat;
|
||||
|
||||
import com.gtnewhorizons.angelica.glsm.testutil.TestThreads;
|
||||
import com.gtnewhorizons.angelica.sdlgpu.SDLGPURenderBackend;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.lwjgl.opengl.GL;
|
||||
@@ -9,11 +10,9 @@ import java.lang.reflect.Field;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertInstanceOf;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
@@ -31,18 +30,6 @@ class Lwjgl3GLCapabilitiesShimTest {
|
||||
assertTrue(caps.forwardCompatible, "SDL reports Core Profile Equivalent, so forwardCompatible must be true");
|
||||
}
|
||||
|
||||
@Test
|
||||
void everyAdvertisedVersionFlagIsTrue() throws ReflectiveOperationException {
|
||||
final Set<String> advertised = SDLGPURenderBackend.advertisedCapabilities();
|
||||
final GLCapabilities caps = Lwjgl3GLCapabilitiesShim.create(advertised);
|
||||
|
||||
final Set<String> missing = new TreeSet<>();
|
||||
for (String name : advertised) {
|
||||
if (name.startsWith("OpenGL") && !flag(caps, name)) missing.add(name);
|
||||
}
|
||||
assertTrue(missing.isEmpty(), () -> "advertised but reported unsupported: " + missing);
|
||||
}
|
||||
|
||||
@Test
|
||||
void advertises46() throws ReflectiveOperationException {
|
||||
final GLCapabilities caps = Lwjgl3GLCapabilitiesShim.create(SDLGPURenderBackend.advertisedCapabilities());
|
||||
@@ -92,17 +79,8 @@ class Lwjgl3GLCapabilitiesShimTest {
|
||||
try {
|
||||
assertNotNull(GL.getCapabilities());
|
||||
|
||||
final AtomicReference<Throwable> onOtherThread = new AtomicReference<>();
|
||||
final Thread other = new Thread(() -> {
|
||||
try {
|
||||
GL.getCapabilities();
|
||||
} catch (Throwable t) {
|
||||
onOtherThread.set(t);
|
||||
}
|
||||
}, "no-context-thread");
|
||||
other.start();
|
||||
other.join();
|
||||
assertInstanceOf(IllegalStateException.class, onOtherThread.get(), "a thread that does not own the context must not look like the render thread");
|
||||
TestThreads.run("no-context-thread", () -> assertThrows(IllegalStateException.class, GL::getCapabilities,
|
||||
"a thread that does not own the context must not look like the render thread"));
|
||||
} finally {
|
||||
Lwjgl3GLCapabilitiesShim.clearOnCurrentThread();
|
||||
}
|
||||
|
||||
+2
-5
@@ -1,6 +1,5 @@
|
||||
package com.gtnewhorizons.angelica.sdlgpu.compute;
|
||||
|
||||
import com.gtnewhorizons.angelica.glsm.shader.SpirvCompiler;
|
||||
import com.gtnewhorizons.angelica.glsm.testutil.TestPaths;
|
||||
import com.gtnewhorizons.angelica.sdlgpu.shader.ShaderManager;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@@ -11,9 +10,9 @@ import java.nio.ByteBuffer;
|
||||
import java.util.Arrays;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
import static com.gtnewhorizons.angelica.sdlgpu.shader.SpirvTestShaders.compileOrFail;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
|
||||
class ChunkCullSpirvCompileTest {
|
||||
|
||||
@@ -25,9 +24,7 @@ class ChunkCullSpirvCompileTest {
|
||||
|
||||
@Test
|
||||
void chunkCullReflectsExpectedBindings() {
|
||||
final SpirvCompiler.Result r = SpirvCompiler.compile(source(), Shaderc.shaderc_compute_shader, SHADER, SpirvCompiler.Options.vulkanForced460Core());
|
||||
if (r.spirv() == null) fail(SHADER + " failed to compile: " + r.error());
|
||||
final ByteBuffer spirv = r.spirv();
|
||||
final ByteBuffer spirv = compileOrFail(source(), Shaderc.shaderc_compute_shader);
|
||||
try {
|
||||
final ShaderManager.ComputeBindingMap map = ShaderManager.remapSpirvForComputeSDLGPU(spirv);
|
||||
assertEquals(0, map.samplerGlSlots().length, "the frustum cull samples no textures");
|
||||
|
||||
-35
@@ -1,35 +0,0 @@
|
||||
package com.gtnewhorizons.angelica.sdlgpu.compute;
|
||||
|
||||
import com.gtnewhorizons.angelica.sdlgpu.SdlTestRig;
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.junit.jupiter.api.Assumptions.assumeTrue;
|
||||
import static org.lwjgl.sdl.SDLGPU.SDL_GetGPUDeviceDriver;
|
||||
|
||||
class ImageAtomicsGpuTest {
|
||||
|
||||
private static SdlTestRig rig;
|
||||
private static ImageAtomicsProbe probe;
|
||||
|
||||
@BeforeAll
|
||||
static void setUp() throws Exception {
|
||||
rig = SdlTestRig.acquireRealDevice();
|
||||
assumeTrue("metal".equalsIgnoreCase(SDL_GetGPUDeviceDriver(rig.sdlHandle)), "native Metal only");
|
||||
assumeTrue(ImageAtomicsProbe.defaultMslVersion() >= ImageAtomicsProbe.MTL_LANGUAGE_VERSION_3_1, "this process compiles Metal source below MSL 3.1");
|
||||
probe = new ImageAtomicsProbe(rig.sdlHandle);
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
static void tearDown() {
|
||||
if (probe != null) probe.release();
|
||||
SdlTestRig.releaseRealDevice();
|
||||
}
|
||||
|
||||
@Test
|
||||
void atomicsCountEveryInvocationOnAnImageTheSizeOfEuphoriasEndCrystalMap() {
|
||||
assertTrue(probe.run(40, 10));
|
||||
}
|
||||
}
|
||||
+4
-14
@@ -1,9 +1,9 @@
|
||||
package com.gtnewhorizons.angelica.sdlgpu.device;
|
||||
|
||||
import com.gtnewhorizons.angelica.sdlgpu.RealDeviceExtension;
|
||||
import com.gtnewhorizons.angelica.sdlgpu.SdlTestRig;
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.lwjgl.system.MemoryStack;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
@@ -17,22 +17,12 @@ import static org.lwjgl.sdl.SDLGPU.SDL_WaitForGPUFences;
|
||||
import static org.lwjgl.sdl.SDLVersion.SDL_GetVersion;
|
||||
import static org.lwjgl.sdl.SDLVersion.SDL_VERSIONNUM;
|
||||
|
||||
@ExtendWith(RealDeviceExtension.class)
|
||||
class FenceProbeRealDeviceTest {
|
||||
|
||||
private static SdlTestRig rig;
|
||||
|
||||
@BeforeAll
|
||||
static void setUp() throws Exception {
|
||||
rig = SdlTestRig.acquireRealDevice();
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
static void tearDown() {
|
||||
SdlTestRig.releaseRealDevice();
|
||||
}
|
||||
|
||||
@Test
|
||||
void probeMatchesVersionTableAndCorrectedQueryReadsSignaled() {
|
||||
final SdlTestRig rig = RealDeviceExtension.rig();
|
||||
final String driver = SDL_GetGPUDeviceDriver(rig.sdlHandle);
|
||||
assertEquals("metal".equalsIgnoreCase(driver) && SDL_GetVersion() == SDL_VERSIONNUM(3, 4, 14), rig.device.isFenceQueryInverted(), "driver=" + driver + " sdl=" + SDL_GetVersion());
|
||||
|
||||
|
||||
+20
-23
@@ -1,34 +1,31 @@
|
||||
package com.gtnewhorizons.angelica.sdlgpu.device;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static com.gtnewhorizons.angelica.sdlgpu.device.VideoDriverRecovery.shouldRetryOnX11;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
class VideoDriverRecoveryTest {
|
||||
|
||||
@Test
|
||||
void waylandWithoutVulkanSurfaceRetries() {
|
||||
assertTrue(shouldRetryOnX11("wayland", false, ":0"));
|
||||
static Stream<Arguments> sessions() {
|
||||
return Stream.of(
|
||||
Arguments.of("wayland without a Vulkan loader, XWayland present", "wayland", false, ":0", true),
|
||||
Arguments.of("wayland with a Vulkan loader", "wayland", true, ":0", false),
|
||||
Arguments.of("wayland, DISPLAY unset", "wayland", false, null, false),
|
||||
Arguments.of("wayland, DISPLAY empty", "wayland", false, "", false),
|
||||
Arguments.of("x11", "x11", false, ":0", false),
|
||||
Arguments.of("cocoa", "cocoa", false, ":0", false),
|
||||
Arguments.of("windows", "windows", false, ":0", false),
|
||||
Arguments.of("no video driver", null, false, ":0", false));
|
||||
}
|
||||
|
||||
@Test
|
||||
void waylandWithVulkanStays() {
|
||||
assertFalse(shouldRetryOnX11("wayland", true, ":0"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void noXWaylandMeansNoRetry() {
|
||||
assertFalse(shouldRetryOnX11("wayland", false, null));
|
||||
assertFalse(shouldRetryOnX11("wayland", false, ""));
|
||||
}
|
||||
|
||||
@Test
|
||||
void otherVideoDriversAreLeftAlone() {
|
||||
assertFalse(shouldRetryOnX11("x11", false, ":0"));
|
||||
assertFalse(shouldRetryOnX11("cocoa", false, ":0"));
|
||||
assertFalse(shouldRetryOnX11("windows", false, ":0"));
|
||||
assertFalse(shouldRetryOnX11(null, false, ":0"));
|
||||
@ParameterizedTest(name = "{0}")
|
||||
@MethodSource("sessions")
|
||||
void retriesOnX11OnlyForWaylandWithoutVulkan(String name, String videoDriver, boolean vulkanLoaderAvailable, String display, boolean retry) {
|
||||
assertEquals(retry, shouldRetryOnX11(videoDriver, vulkanLoaderAvailable, display));
|
||||
}
|
||||
}
|
||||
+16
-15
@@ -1,28 +1,29 @@
|
||||
package com.gtnewhorizons.angelica.sdlgpu.frame;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
class AcquireAffinityTest {
|
||||
|
||||
private static final Thread WINDOW = new Thread("window");
|
||||
private static final Thread OTHER = new Thread("other");
|
||||
|
||||
@Test
|
||||
void acquiringOnTheWindowThreadIsTheOnlyAcceptedCase() {
|
||||
assertFalse(FrameManager.acquireAffinityViolated(WINDOW, WINDOW));
|
||||
/** A null window is never a violation: the check runs before the window is claimed. */
|
||||
static Stream<Arguments> acquires() {
|
||||
return Stream.of(
|
||||
Arguments.of("on the window thread", WINDOW, WINDOW, false),
|
||||
Arguments.of("on any other thread", OTHER, WINDOW, true),
|
||||
Arguments.of("before the window thread is known", OTHER, null, false));
|
||||
}
|
||||
|
||||
@Test
|
||||
void acquiringOnAnyOtherThreadViolatesTheSdlContract() {
|
||||
assertTrue(FrameManager.acquireAffinityViolated(OTHER, WINDOW));
|
||||
}
|
||||
|
||||
@Test
|
||||
void anUnknownWindowThreadCannotBeJudged() {
|
||||
assertFalse(FrameManager.acquireAffinityViolated(OTHER, null),
|
||||
"the check runs before the window is claimed; judging a null window would throw at startup");
|
||||
@ParameterizedTest(name = "{0}")
|
||||
@MethodSource("acquires")
|
||||
void acquireAffinityViolated(String name, Thread self, Thread window, boolean violated) {
|
||||
assertEquals(violated, FrameManager.acquireAffinityViolated(self, window));
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.gtnewhorizons.angelica.sdlgpu.frame;
|
||||
|
||||
import com.gtnewhorizons.angelica.glsm.backend.MainThreadPump;
|
||||
import com.gtnewhorizons.angelica.glsm.testutil.TestThreads;
|
||||
import com.gtnewhorizons.angelica.sdlgpu.device.Device;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.Timeout;
|
||||
@@ -115,9 +116,7 @@ class PresenterTest {
|
||||
|
||||
p.requestPresent(1L, 10, 10, SDL_FLIP_NONE);
|
||||
|
||||
final Thread windowThread = new Thread(executor::runNext, "window-thread");
|
||||
windowThread.start();
|
||||
windowThread.join();
|
||||
TestThreads.run("window-thread", executor::runNext);
|
||||
|
||||
assertEquals(before, fm.registeredFrameCount(), "the window thread must stay out of the frame registry");
|
||||
}
|
||||
|
||||
+35
-76
@@ -2,11 +2,8 @@ package com.gtnewhorizons.angelica.sdlgpu.glsm;
|
||||
|
||||
import com.gtnewhorizons.angelica.config.SystemProperties;
|
||||
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||
import com.gtnewhorizons.angelica.glsm.backend.BackendManager;
|
||||
import com.gtnewhorizons.angelica.glsm.testutil.Reflect;
|
||||
import com.gtnewhorizons.angelica.sdlgpu.frame.FrameManager;
|
||||
import com.gtnewhorizons.angelica.sdlgpu.resource.ResourceManager;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Tag;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@@ -21,6 +18,8 @@ import java.nio.FloatBuffer;
|
||||
import java.nio.IntBuffer;
|
||||
import sun.misc.Unsafe;
|
||||
|
||||
import static com.gtnewhorizons.angelica.sdlgpu.glsm.GlsmSdlHeadlessRig.BLACK;
|
||||
import static com.gtnewhorizons.angelica.sdlgpu.glsm.GlsmSdlHeadlessRig.RED;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
@@ -30,22 +29,12 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
class GlsmSdlAttachmentClearTest {
|
||||
|
||||
private static final int SIZE = GlsmSdlHeadlessRig.SIZE;
|
||||
private static final int RED = 0xFFFF0000;
|
||||
private static final int BLACK = 0xFF000000;
|
||||
|
||||
@BeforeAll
|
||||
static void boot() {
|
||||
GlsmSdlHeadlessRig.boot();
|
||||
}
|
||||
|
||||
private static FrameManager frameManager() {
|
||||
return Reflect.get(BackendManager.RENDER_BACKEND, "frameManager");
|
||||
}
|
||||
|
||||
private static FrameManager.FrameState frame() {
|
||||
return frameManager().frame();
|
||||
return GlsmSdlHeadlessRig.frameManager().frame();
|
||||
}
|
||||
|
||||
// Reflect.setStaticFinal rejects primitive fields.
|
||||
private static void setDisableInPassClear(boolean value) {
|
||||
try {
|
||||
final Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
|
||||
@@ -58,6 +47,27 @@ class GlsmSdlAttachmentClearTest {
|
||||
}
|
||||
}
|
||||
|
||||
/** Clears colour to black and depth to 0.9, then draws a quad so a render pass is open. */
|
||||
private static void primeTarget(float r, float g, float b) {
|
||||
GlsmSdlHeadlessRig.bindTarget();
|
||||
GLStateManager.glDepthMask(true);
|
||||
GLStateManager.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
GLStateManager.glClearDepth(0.9);
|
||||
GLStateManager.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
|
||||
GlsmSdlHeadlessRig.solidQuad(r, g, b);
|
||||
}
|
||||
|
||||
private static void primeTargetWithStencil(int stencil) {
|
||||
GlsmSdlHeadlessRig.bindTarget();
|
||||
GLStateManager.glDepthMask(true);
|
||||
GLStateManager.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
GLStateManager.glClearDepth(1.0);
|
||||
GLStateManager.glClearStencil(stencil);
|
||||
GLStateManager.glStencilMask(0xFF);
|
||||
GLStateManager.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT | GL11.GL_STENCIL_BUFFER_BIT);
|
||||
GlsmSdlHeadlessRig.solidQuad(0.1f, 0.1f, 0.1f);
|
||||
}
|
||||
|
||||
private static void drawFullQuadAtZ(float z, float r, float g, float b) {
|
||||
GLStateManager.glColor4f(r, g, b, 1.0f);
|
||||
GLStateManager.glNormal3f(0.0f, 0.0f, 1.0f);
|
||||
@@ -93,12 +103,7 @@ class GlsmSdlAttachmentClearTest {
|
||||
|
||||
@Test
|
||||
void depthMaskOffSuppressesTheClearAndBreaksNoPass() {
|
||||
GlsmSdlHeadlessRig.bindTarget();
|
||||
GLStateManager.glDepthMask(true);
|
||||
GLStateManager.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
GLStateManager.glClearDepth(0.9);
|
||||
GLStateManager.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
|
||||
GlsmSdlHeadlessRig.solidQuad(0.1f, 0.1f, 0.1f);
|
||||
primeTarget(0.1f, 0.1f, 0.1f);
|
||||
|
||||
final FrameManager.FrameState f = frame();
|
||||
final long passBefore = f.renderPass;
|
||||
@@ -119,12 +124,7 @@ class GlsmSdlAttachmentClearTest {
|
||||
|
||||
@Test
|
||||
void inPassPathIsTakenForACompatibleActivePass() {
|
||||
GlsmSdlHeadlessRig.bindTarget();
|
||||
GLStateManager.glDepthMask(true);
|
||||
GLStateManager.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
GLStateManager.glClearDepth(0.9);
|
||||
GLStateManager.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
|
||||
GlsmSdlHeadlessRig.solidQuad(0.1f, 0.1f, 0.1f);
|
||||
primeTarget(0.1f, 0.1f, 0.1f);
|
||||
|
||||
final FrameManager.FrameState f = frame();
|
||||
final long passBefore = f.renderPass;
|
||||
@@ -142,12 +142,7 @@ class GlsmSdlAttachmentClearTest {
|
||||
|
||||
@Test
|
||||
void disableInPassClearFlagForcesTheLegacyPath() {
|
||||
GlsmSdlHeadlessRig.bindTarget();
|
||||
GLStateManager.glDepthMask(true);
|
||||
GLStateManager.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
GLStateManager.glClearDepth(0.9);
|
||||
GLStateManager.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
|
||||
GlsmSdlHeadlessRig.solidQuad(0.1f, 0.1f, 0.1f);
|
||||
primeTarget(0.1f, 0.1f, 0.1f);
|
||||
|
||||
final FrameManager.FrameState f = frame();
|
||||
assertTrue(f.renderPass != 0, "expected an active render pass before the clear");
|
||||
@@ -177,12 +172,7 @@ class GlsmSdlAttachmentClearTest {
|
||||
try {
|
||||
GlsmSdlHeadlessRig.beginFrame();
|
||||
GlsmSdlHeadlessRig.resetState();
|
||||
GlsmSdlHeadlessRig.bindTarget();
|
||||
GLStateManager.glDepthMask(true);
|
||||
GLStateManager.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
GLStateManager.glClearDepth(0.9);
|
||||
GLStateManager.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
|
||||
GlsmSdlHeadlessRig.solidQuad(0.1f, 0.1f, 0.1f);
|
||||
primeTarget(0.1f, 0.1f, 0.1f);
|
||||
|
||||
GLStateManager.glDepthMask(true);
|
||||
GLStateManager.glClearDepth(depthValue);
|
||||
@@ -196,12 +186,7 @@ class GlsmSdlAttachmentClearTest {
|
||||
|
||||
@Test
|
||||
void scissoredClearOnlyAffectsTheScissorRect() {
|
||||
GlsmSdlHeadlessRig.bindTarget();
|
||||
GLStateManager.glDepthMask(true);
|
||||
GLStateManager.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
GLStateManager.glClearDepth(0.9);
|
||||
GLStateManager.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
|
||||
GlsmSdlHeadlessRig.solidQuad(0.1f, 0.1f, 0.1f);
|
||||
primeTarget(0.1f, 0.1f, 0.1f);
|
||||
|
||||
GLStateManager.glEnable(GL11.GL_SCISSOR_TEST);
|
||||
GLStateManager.glScissor(0, 0, SIZE / 2, SIZE);
|
||||
@@ -229,14 +214,7 @@ class GlsmSdlAttachmentClearTest {
|
||||
|
||||
@Test
|
||||
void stencilWriteMaskIsHonored() {
|
||||
GlsmSdlHeadlessRig.bindTarget();
|
||||
GLStateManager.glDepthMask(true);
|
||||
GLStateManager.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
GLStateManager.glClearDepth(1.0);
|
||||
GLStateManager.glClearStencil(0xA5);
|
||||
GLStateManager.glStencilMask(0xFF);
|
||||
GLStateManager.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT | GL11.GL_STENCIL_BUFFER_BIT);
|
||||
GlsmSdlHeadlessRig.solidQuad(0.1f, 0.1f, 0.1f);
|
||||
primeTargetWithStencil(0xA5);
|
||||
|
||||
final FrameManager.FrameState f = frame();
|
||||
final long passBefore = f.renderPass;
|
||||
@@ -258,14 +236,7 @@ class GlsmSdlAttachmentClearTest {
|
||||
@Test
|
||||
@Disabled("stencil reference >= 0x80 compares as 0xFF on this backend; see stencil reference finding")
|
||||
void stencilReferenceAtOrAbove0x80ComparesExactly() {
|
||||
GlsmSdlHeadlessRig.bindTarget();
|
||||
GLStateManager.glDepthMask(true);
|
||||
GLStateManager.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
GLStateManager.glClearDepth(1.0);
|
||||
GLStateManager.glClearStencil(0xAF);
|
||||
GLStateManager.glStencilMask(0xFF);
|
||||
GLStateManager.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT | GL11.GL_STENCIL_BUFFER_BIT);
|
||||
GlsmSdlHeadlessRig.solidQuad(0.1f, 0.1f, 0.1f);
|
||||
primeTargetWithStencil(0xAF);
|
||||
|
||||
final StencilProbeResult result = probeStencilReconcile();
|
||||
assertEquals(0xAF, result.bitPlaneValue(), "bit-plane read of a plain 0xAF stencil clear");
|
||||
@@ -274,14 +245,7 @@ class GlsmSdlAttachmentClearTest {
|
||||
|
||||
@Test
|
||||
void baselineStencilClearReadsBackExactly() {
|
||||
GlsmSdlHeadlessRig.bindTarget();
|
||||
GLStateManager.glDepthMask(true);
|
||||
GLStateManager.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
GLStateManager.glClearDepth(1.0);
|
||||
GLStateManager.glClearStencil(0xA5);
|
||||
GLStateManager.glStencilMask(0xFF);
|
||||
GLStateManager.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT | GL11.GL_STENCIL_BUFFER_BIT);
|
||||
GlsmSdlHeadlessRig.solidQuad(0.1f, 0.1f, 0.1f);
|
||||
primeTargetWithStencil(0xA5);
|
||||
|
||||
assertEquals(0xA5, readStencilByteSameFrame(), "a full-write-mask clear (the legacy load-op path) must read back exactly what was cleared");
|
||||
}
|
||||
@@ -375,12 +339,7 @@ class GlsmSdlAttachmentClearTest {
|
||||
|
||||
@Test
|
||||
void scissoredColorAndDepthClearStaysInTheRect() {
|
||||
GlsmSdlHeadlessRig.bindTarget();
|
||||
GLStateManager.glDepthMask(true);
|
||||
GLStateManager.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
GLStateManager.glClearDepth(0.9);
|
||||
GLStateManager.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
|
||||
GlsmSdlHeadlessRig.solidQuad(0.0f, 0.0f, 1.0f);
|
||||
primeTarget(0.0f, 0.0f, 1.0f);
|
||||
|
||||
final FrameManager.FrameState f = frame();
|
||||
final long passBefore = f.renderPass;
|
||||
@@ -594,7 +553,7 @@ class GlsmSdlAttachmentClearTest {
|
||||
GLStateManager.glDepthMask(true);
|
||||
GLStateManager.glClear(GL11.GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
final ResourceManager resourceManager = Reflect.get(BackendManager.RENDER_BACKEND, "resourceManager");
|
||||
final ResourceManager resourceManager = GlsmSdlHeadlessRig.resourceManager();
|
||||
final long depthTexture = resourceManager.getFbo(fbo).depthTexture;
|
||||
GlsmSdlHeadlessRig.endFrame();
|
||||
|
||||
|
||||
+8
-23
@@ -1,14 +1,12 @@
|
||||
package com.gtnewhorizons.angelica.sdlgpu.glsm;
|
||||
|
||||
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||
import com.gtnewhorizons.angelica.glsm.backend.BackendManager;
|
||||
import com.gtnewhorizons.angelica.glsm.testutil.Reflect;
|
||||
import com.gtnewhorizons.angelica.sdlgpu.frame.FrameManager;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Tag;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.ValueSource;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL14;
|
||||
|
||||
@@ -19,11 +17,6 @@ import static org.junit.jupiter.api.Assertions.assertNotEquals;
|
||||
@ExtendWith(GlsmSdlFrameExtension.class)
|
||||
class GlsmSdlBlendConstantsTest {
|
||||
|
||||
@BeforeAll
|
||||
static void boot() {
|
||||
GlsmSdlHeadlessRig.boot();
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void restoreBlend() {
|
||||
GLStateManager.glDisable(GL11.GL_BLEND);
|
||||
@@ -31,17 +24,10 @@ class GlsmSdlBlendConstantsTest {
|
||||
GLStateManager.glBlendColor(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
}
|
||||
|
||||
@Test
|
||||
void pendingConstantsSurviveADrawWithoutConstantBlending() {
|
||||
verifyConstants(false);
|
||||
}
|
||||
|
||||
@Test
|
||||
void constantsChangedWhileBlendingIsDisabledReachTheNextBlendedDraw() {
|
||||
verifyConstants(true);
|
||||
}
|
||||
|
||||
private static void verifyConstants(boolean previouslyEnabled) {
|
||||
/** With blending never enabled before, the pending constants must survive a draw that does not use them. */
|
||||
@ParameterizedTest(name = "blending enabled earlier in the frame: {0}")
|
||||
@ValueSource(booleans = {false, true})
|
||||
void constantsSetWhileBlendingIsDisabledReachTheNextBlendedDraw(boolean previouslyEnabled) {
|
||||
GlsmSdlHeadlessRig.bindTarget();
|
||||
GLStateManager.glBlendFunc(GL14.GL_CONSTANT_COLOR, GL11.GL_ZERO);
|
||||
if (previouslyEnabled) {
|
||||
@@ -52,8 +38,7 @@ class GlsmSdlBlendConstantsTest {
|
||||
GLStateManager.glDisable(GL11.GL_BLEND);
|
||||
GLStateManager.glBlendColor(0.0f, 1.0f, 0.0f, 1.0f);
|
||||
GlsmSdlHeadlessRig.solidQuad(1.0f, 1.0f, 1.0f);
|
||||
final FrameManager manager = Reflect.get(BackendManager.RENDER_BACKEND, "frameManager");
|
||||
final FrameManager.FrameState frame = manager.frame();
|
||||
final FrameManager.FrameState frame = GlsmSdlHeadlessRig.frameManager().frame();
|
||||
final long pass = frame.renderPass;
|
||||
final long generation = frame.renderPassGeneration;
|
||||
assertNotEquals(0, pass);
|
||||
@@ -64,6 +49,6 @@ class GlsmSdlBlendConstantsTest {
|
||||
assertEquals(generation, frame.renderPassGeneration);
|
||||
final int[] pixels = GlsmSdlHeadlessRig.readTarget();
|
||||
final int size = GlsmSdlHeadlessRig.SIZE;
|
||||
assertEquals(0xFF00FF00, GlsmSdlHeadlessRig.pixelAt(pixels, size, size / 2, size / 2));
|
||||
assertEquals(GlsmSdlHeadlessRig.GREEN, GlsmSdlHeadlessRig.pixelAt(pixels, size, size / 2, size / 2));
|
||||
}
|
||||
}
|
||||
+13
-17
@@ -1,10 +1,12 @@
|
||||
package com.gtnewhorizons.angelica.sdlgpu.glsm;
|
||||
|
||||
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Tag;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL15;
|
||||
import org.lwjgl.opengl.GL30;
|
||||
@@ -14,6 +16,7 @@ import org.lwjgl.opengl.GL44;
|
||||
import org.lwjgl.system.MemoryUtil;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
@@ -31,11 +34,6 @@ class GlsmSdlBufferMappingLifetimeTest {
|
||||
private static final int PERSISTENT_MAP = GL44.GL_MAP_PERSISTENT_BIT | GL30.GL_MAP_WRITE_BIT | GL44.GL_MAP_COHERENT_BIT;
|
||||
private static final int PLAIN_MAP = GL30.GL_MAP_WRITE_BIT | GL30.GL_MAP_INVALIDATE_BUFFER_BIT;
|
||||
|
||||
@BeforeAll
|
||||
static void boot() {
|
||||
GlsmSdlHeadlessRig.boot();
|
||||
}
|
||||
|
||||
private static void fill(ByteBuffer buf, int seed) {
|
||||
for (int i = 0; i < buf.capacity(); i++) buf.put(i, (byte) (seed * 37 + i * 7 + 1));
|
||||
}
|
||||
@@ -300,7 +298,15 @@ class GlsmSdlBufferMappingLifetimeTest {
|
||||
}
|
||||
}
|
||||
|
||||
private static void assertBufferDataUnmapsPlainMapping(int target) {
|
||||
static Stream<Arguments> plainMapTargets() {
|
||||
return Stream.of(
|
||||
Arguments.of("GL_ARRAY_BUFFER", GL15.GL_ARRAY_BUFFER),
|
||||
Arguments.of("GL_UNIFORM_BUFFER", GL31.GL_UNIFORM_BUFFER));
|
||||
}
|
||||
|
||||
@ParameterizedTest(name = "{0}")
|
||||
@MethodSource("plainMapTargets")
|
||||
void bufferDataOnMappedBufferUnmapsIt(String name, int target) {
|
||||
final int id = GLStateManager.glGenBuffers();
|
||||
try {
|
||||
GLStateManager.glBindBuffer(target, id);
|
||||
@@ -314,16 +320,6 @@ class GlsmSdlBufferMappingLifetimeTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void bufferDataOnMappedArrayBufferUnmapsIt() {
|
||||
assertBufferDataUnmapsPlainMapping(GL15.GL_ARRAY_BUFFER);
|
||||
}
|
||||
|
||||
@Test
|
||||
void bufferDataOnMappedUniformBufferUnmapsIt() {
|
||||
assertBufferDataUnmapsPlainMapping(GL31.GL_UNIFORM_BUFFER);
|
||||
}
|
||||
|
||||
@Test
|
||||
void outOfRangeFlushOfPersistentMappingIsIgnored() {
|
||||
final int target = GL15.GL_ARRAY_BUFFER;
|
||||
|
||||
+37
-78
@@ -1,16 +1,14 @@
|
||||
package com.gtnewhorizons.angelica.sdlgpu.glsm;
|
||||
|
||||
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||
import com.gtnewhorizons.angelica.glsm.backend.BackendManager;
|
||||
import com.gtnewhorizons.angelica.glsm.testutil.Reflect;
|
||||
import com.gtnewhorizons.angelica.sdlgpu.SDLGPUGate;
|
||||
import com.gtnewhorizons.angelica.sdlgpu.frame.FrameManager;
|
||||
import com.gtnewhorizons.angelica.sdlgpu.resource.ResourceManager;
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Tag;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL12;
|
||||
import org.lwjgl.opengl.GL13;
|
||||
@@ -20,39 +18,30 @@ import org.lwjgl.system.MemoryUtil;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.IntBuffer;
|
||||
import java.util.function.IntBinaryOperator;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static com.gtnewhorizons.angelica.sdlgpu.glsm.GlsmSdlHeadlessRig.BLUE;
|
||||
import static com.gtnewhorizons.angelica.sdlgpu.glsm.GlsmSdlHeadlessRig.GREEN;
|
||||
import static com.gtnewhorizons.angelica.sdlgpu.glsm.GlsmSdlHeadlessRig.RED;
|
||||
import static com.gtnewhorizons.angelica.sdlgpu.glsm.GlsmSdlHeadlessRig.SIZE;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
@Tag("glsm-sdl")
|
||||
@ExtendWith(GlsmSdlFrameExtension.class)
|
||||
class GlsmSdlCopyBlitTest {
|
||||
|
||||
private static final int RED = 0xFFFF0000;
|
||||
private static final int GREEN = 0xFF00FF00;
|
||||
private static final int BLUE = 0xFF0000FF;
|
||||
|
||||
private static final int SCISSOR_ROWS = 16;
|
||||
private static final byte SENTINEL_BYTE = 0x7B;
|
||||
private static final int SENTINEL = 0x7B7B7B7B;
|
||||
|
||||
private static FrameManager frameManager;
|
||||
private static ResourceManager resourceManager;
|
||||
|
||||
@BeforeAll
|
||||
static void boot() {
|
||||
GlsmSdlHeadlessRig.boot();
|
||||
frameManager = Reflect.get(BackendManager.RENDER_BACKEND, "frameManager");
|
||||
resourceManager = Reflect.get(BackendManager.RENDER_BACKEND, "resourceManager");
|
||||
frameManager.destroyFinalTarget();
|
||||
frameManager.finalTarget().create(SDLGPUGate.device(), resourceManager, SIZE, SIZE, resourceManager.mapTextureFormat(GL11.GL_RGBA8));
|
||||
assertEquals(SIZE, frameManager.getFbo0Height());
|
||||
static void installFinalTarget() {
|
||||
GlsmSdlHeadlessRig.installFinalTarget(SIZE, SIZE);
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
static void dropFinalTarget() {
|
||||
GlsmSdlHeadlessRig.endFrame();
|
||||
if (frameManager != null) frameManager.destroyFinalTarget();
|
||||
GlsmSdlHeadlessRig.dropFinalTarget();
|
||||
}
|
||||
|
||||
private static void assertRow(int[] pixels, int y, int expected, String label) {
|
||||
@@ -88,27 +77,11 @@ class GlsmSdlCopyBlitTest {
|
||||
GLStateManager.glTexParameterf(GL11.GL_TEXTURE_2D, GL12.GL_TEXTURE_MIN_LOD, 0.0f);
|
||||
GLStateManager.glTexParameterf(GL11.GL_TEXTURE_2D, GL12.GL_TEXTURE_MAX_LOD, 1.0f);
|
||||
GLStateManager.glTexParameterf(GL11.GL_TEXTURE_2D, GL14.GL_TEXTURE_LOD_BIAS, 0.0f);
|
||||
uploadLevel(0, SIZE, level0Argb);
|
||||
uploadLevel(1, SIZE / 2, level1Argb);
|
||||
GlsmSdlHeadlessRig.uploadSolidLevel(0, SIZE, level0Argb);
|
||||
GlsmSdlHeadlessRig.uploadSolidLevel(1, SIZE / 2, level1Argb);
|
||||
return id;
|
||||
}
|
||||
|
||||
private static void uploadLevel(int level, int size, int argb) {
|
||||
final ByteBuffer texels = MemoryUtil.memAlloc(size * size * 4);
|
||||
try {
|
||||
for (int i = 0; i < size * size; i++) {
|
||||
texels.put(i * 4, (byte) ((argb >> 16) & 0xFF));
|
||||
texels.put(i * 4 + 1, (byte) ((argb >> 8) & 0xFF));
|
||||
texels.put(i * 4 + 2, (byte) (argb & 0xFF));
|
||||
texels.put(i * 4 + 3, (byte) ((argb >>> 24) & 0xFF));
|
||||
}
|
||||
GLStateManager.glTexImage2D(GL11.GL_TEXTURE_2D, level, GL11.GL_RGBA8, size, size, 0,
|
||||
GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, texels);
|
||||
} finally {
|
||||
MemoryUtil.memFree(texels);
|
||||
}
|
||||
}
|
||||
|
||||
private static int copyGreenIntoLevelOne() {
|
||||
GlsmSdlHeadlessRig.bindTarget();
|
||||
GlsmSdlHeadlessRig.clearTo(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
@@ -181,7 +154,7 @@ class GlsmSdlCopyBlitTest {
|
||||
|
||||
private static void blitLevelOneInto(int dstSize, int dstLevel) {
|
||||
final int source = GlsmSdlHeadlessRig.createSolidMipTexture(SIZE, 1, RED);
|
||||
uploadLevel(1, SIZE / 2, GREEN);
|
||||
GlsmSdlHeadlessRig.uploadSolidLevel(1, SIZE / 2, GREEN);
|
||||
final int destination = GlsmSdlHeadlessRig.createSolidMipTexture(dstSize, dstLevel, BLUE);
|
||||
final int readFbo = GlsmSdlHeadlessRig.fboWithColor(source, 1);
|
||||
final int drawFbo = GlsmSdlHeadlessRig.fboWithColor(destination, dstLevel);
|
||||
@@ -202,19 +175,17 @@ class GlsmSdlCopyBlitTest {
|
||||
GLStateManager.glDeleteTextures(destination);
|
||||
}
|
||||
|
||||
@Test
|
||||
void blitFramebufferReadsTheSourceAttachmentLevel() {
|
||||
blitLevelOneInto(SIZE / 2, 0);
|
||||
static Stream<Arguments> levelBlits() {
|
||||
return Stream.of(
|
||||
Arguments.of("1:1 into level 0: reads the source attachment level", SIZE / 2, 0),
|
||||
Arguments.of("scaled into level 0: reads the source attachment level", SIZE, 0),
|
||||
Arguments.of("into level 1: writes the destination attachment level", SIZE, 1));
|
||||
}
|
||||
|
||||
@Test
|
||||
void scaledBlitFramebufferReadsTheSourceAttachmentLevel() {
|
||||
blitLevelOneInto(SIZE, 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
void blitFramebufferWritesTheDestinationAttachmentLevel() {
|
||||
blitLevelOneInto(SIZE, 1);
|
||||
@ParameterizedTest(name = "{0}")
|
||||
@MethodSource("levelBlits")
|
||||
void blitFramebufferHonoursAttachmentLevels(String name, int dstSize, int dstLevel) {
|
||||
blitLevelOneInto(dstSize, dstLevel);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -299,12 +270,7 @@ class GlsmSdlCopyBlitTest {
|
||||
try {
|
||||
for (int y = 0; y < SIZE; y++) {
|
||||
for (int x = 0; x < SIZE; x++) {
|
||||
final int argb = pattern(x, y);
|
||||
final int i = (y * SIZE + x) * 4;
|
||||
texels.put(i, (byte) ((argb >> 16) & 0xFF));
|
||||
texels.put(i + 1, (byte) ((argb >> 8) & 0xFF));
|
||||
texels.put(i + 2, (byte) (argb & 0xFF));
|
||||
texels.put(i + 3, (byte) ((argb >>> 24) & 0xFF));
|
||||
GlsmSdlHeadlessRig.putArgb(texels, y * SIZE + x, pattern(x, y));
|
||||
}
|
||||
}
|
||||
GLStateManager.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA8, SIZE, SIZE, 0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, texels);
|
||||
@@ -331,32 +297,25 @@ class GlsmSdlCopyBlitTest {
|
||||
return pixels;
|
||||
}
|
||||
|
||||
@Test
|
||||
void blitFramebufferWithReversedSourceXMirrorsHorizontally() {
|
||||
final int[] pixels = blitPattern(SIZE, 0, 0, SIZE, 0, 0, SIZE, SIZE);
|
||||
for (int y = 0; y < SIZE; y++) {
|
||||
for (int x = 0; x < SIZE; x++) {
|
||||
GlsmSdlHeadlessRig.assertPixel(pixels, SIZE, x, y, pattern(SIZE - 1 - x, y), "horizontal mirror");
|
||||
}
|
||||
}
|
||||
private static Arguments mirror(String name, int[] srcRect, int[] dstRect, IntBinaryOperator expected) {
|
||||
return Arguments.of(name, srcRect, dstRect, expected);
|
||||
}
|
||||
|
||||
@Test
|
||||
void blitFramebufferWithReversedDestinationYMirrorsVertically() {
|
||||
final int[] pixels = blitPattern(0, 0, SIZE, SIZE, 0, SIZE, SIZE, 0);
|
||||
for (int y = 0; y < SIZE; y++) {
|
||||
for (int x = 0; x < SIZE; x++) {
|
||||
GlsmSdlHeadlessRig.assertPixel(pixels, SIZE, x, y, pattern(x, SIZE - 1 - y), "vertical mirror");
|
||||
}
|
||||
}
|
||||
/** Rects are x0, y0, x1, y1; {@code expected} maps a destination pixel to the pattern colour it must hold. */
|
||||
static Stream<Arguments> mirroredBlits() {
|
||||
return Stream.of(
|
||||
mirror("reversed source X mirrors horizontally", new int[]{SIZE, 0, 0, SIZE}, new int[]{0, 0, SIZE, SIZE}, (x, y) -> pattern(SIZE - 1 - x, y)),
|
||||
mirror("reversed destination Y mirrors vertically", new int[]{0, 0, SIZE, SIZE}, new int[]{0, SIZE, SIZE, 0}, (x, y) -> pattern(x, SIZE - 1 - y)),
|
||||
mirror("both ranges reversed does not mirror", new int[]{SIZE, SIZE, 0, 0}, new int[]{SIZE, SIZE, 0, 0}, (x, y) -> pattern(x, y)));
|
||||
}
|
||||
|
||||
@Test
|
||||
void blitFramebufferWithBothRangesReversedDoesNotMirror() {
|
||||
final int[] pixels = blitPattern(SIZE, SIZE, 0, 0, SIZE, SIZE, 0, 0);
|
||||
@ParameterizedTest(name = "{0}")
|
||||
@MethodSource("mirroredBlits")
|
||||
void blitFramebufferMirrorsByRangeDirection(String name, int[] src, int[] dst, IntBinaryOperator expected) {
|
||||
final int[] pixels = blitPattern(src[0], src[1], src[2], src[3], dst[0], dst[1], dst[2], dst[3]);
|
||||
for (int y = 0; y < SIZE; y++) {
|
||||
for (int x = 0; x < SIZE; x++) {
|
||||
GlsmSdlHeadlessRig.assertPixel(pixels, SIZE, x, y, pattern(x, y), "both ranges reversed");
|
||||
GlsmSdlHeadlessRig.assertPixel(pixels, SIZE, x, y, expected.applyAsInt(x, y), name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+9
-20
@@ -1,34 +1,23 @@
|
||||
package com.gtnewhorizons.angelica.sdlgpu.glsm;
|
||||
|
||||
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Tag;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.ValueSource;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import static com.gtnewhorizons.angelica.sdlgpu.glsm.GlsmSdlHeadlessRig.RED;
|
||||
|
||||
@Tag("glsm-sdl")
|
||||
@ExtendWith(GlsmSdlFrameExtension.class)
|
||||
class GlsmSdlDegenerateDrawTest {
|
||||
|
||||
private static final int RED = 0xFFFF0000;
|
||||
|
||||
@BeforeAll
|
||||
static void boot() {
|
||||
GlsmSdlHeadlessRig.boot();
|
||||
}
|
||||
|
||||
@Test
|
||||
void zeroCountDrawArraysLeavesTheFollowingDrawIntact() {
|
||||
GLStateManager.glDrawArrays(GL11.GL_TRIANGLES, 0, 0);
|
||||
@ParameterizedTest(name = "count {0}")
|
||||
@ValueSource(ints = {0, -3})
|
||||
void degenerateCountDrawArraysLeavesTheFollowingDrawIntact(int count) {
|
||||
GLStateManager.glDrawArrays(GL11.GL_TRIANGLES, 0, count);
|
||||
GlsmSdlHeadlessRig.solidQuad(1.0f, 0.0f, 0.0f);
|
||||
GlsmSdlHeadlessRig.assertUniform(GlsmSdlHeadlessRig.readTarget(), RED, "after a zero-count drawArrays");
|
||||
}
|
||||
|
||||
@Test
|
||||
void negativeCountDrawArraysLeavesTheFollowingDrawIntact() {
|
||||
GLStateManager.glDrawArrays(GL11.GL_TRIANGLES, 0, -3);
|
||||
GlsmSdlHeadlessRig.solidQuad(1.0f, 0.0f, 0.0f);
|
||||
GlsmSdlHeadlessRig.assertUniform(GlsmSdlHeadlessRig.readTarget(), RED, "after a negative-count drawArrays");
|
||||
GlsmSdlHeadlessRig.assertUniform(GlsmSdlHeadlessRig.readTarget(), RED, "after a drawArrays with count " + count);
|
||||
}
|
||||
}
|
||||
+8
-22
@@ -1,10 +1,6 @@
|
||||
package com.gtnewhorizons.angelica.sdlgpu.glsm;
|
||||
|
||||
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||
import com.gtnewhorizons.angelica.glsm.backend.BackendManager;
|
||||
import com.gtnewhorizons.angelica.glsm.testutil.Reflect;
|
||||
import com.gtnewhorizons.angelica.sdlgpu.SDLGPUGate;
|
||||
import com.gtnewhorizons.angelica.sdlgpu.frame.FrameManager;
|
||||
import com.gtnewhorizons.angelica.sdlgpu.resource.ResourceManager;
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
@@ -19,6 +15,9 @@ import org.lwjgl.system.MemoryUtil;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import static com.gtnewhorizons.angelica.sdlgpu.glsm.GlsmSdlHeadlessRig.BLUE;
|
||||
import static com.gtnewhorizons.angelica.sdlgpu.glsm.GlsmSdlHeadlessRig.GREEN;
|
||||
import static com.gtnewhorizons.angelica.sdlgpu.glsm.GlsmSdlHeadlessRig.RED;
|
||||
import static com.gtnewhorizons.angelica.sdlgpu.glsm.GlsmSdlHeadlessRig.SIZE;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
@@ -32,27 +31,14 @@ class GlsmSdlFbo0ViewportTest {
|
||||
private static final int FBO0_H = 96;
|
||||
private static final int VIEW = 32;
|
||||
|
||||
private static final int RED = 0xFFFF0000;
|
||||
private static final int GREEN = 0xFF00FF00;
|
||||
private static final int BLUE = 0xFF0000FF;
|
||||
|
||||
private static FrameManager frameManager;
|
||||
private static ResourceManager resourceManager;
|
||||
|
||||
@BeforeAll
|
||||
static void boot() {
|
||||
GlsmSdlHeadlessRig.boot();
|
||||
frameManager = Reflect.get(BackendManager.RENDER_BACKEND, "frameManager");
|
||||
resourceManager = Reflect.get(BackendManager.RENDER_BACKEND, "resourceManager");
|
||||
frameManager.destroyFinalTarget();
|
||||
frameManager.finalTarget().create(SDLGPUGate.device(), resourceManager, FBO0_W, FBO0_H, resourceManager.mapTextureFormat(GL11.GL_RGBA8));
|
||||
assertEquals(FBO0_H, frameManager.getFbo0Height());
|
||||
static void installFinalTarget() {
|
||||
GlsmSdlHeadlessRig.installFinalTarget(FBO0_W, FBO0_H);
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
static void dropFinalTarget() {
|
||||
GlsmSdlHeadlessRig.endFrame();
|
||||
if (frameManager != null) frameManager.destroyFinalTarget();
|
||||
GlsmSdlHeadlessRig.dropFinalTarget();
|
||||
}
|
||||
|
||||
private static void bindFbo0WithSmallViewport() {
|
||||
@@ -161,11 +147,11 @@ class GlsmSdlFbo0ViewportTest {
|
||||
GLStateManager.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_NEAREST);
|
||||
GLStateManager.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_NEAREST);
|
||||
GLStateManager.glTexParameteri(GL11.GL_TEXTURE_2D, GL12.GL_TEXTURE_MAX_LEVEL, 0);
|
||||
assertNull(resourceManager.getTextureMeta(copy), "destination was allocated before the copy");
|
||||
assertNull(GlsmSdlHeadlessRig.resourceManager().getTextureMeta(copy), "destination was allocated before the copy");
|
||||
|
||||
GLStateManager.glCopyTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA8, 0, 0, VIEW, VIEW, 0);
|
||||
|
||||
final ResourceManager.TextureMeta meta = resourceManager.getTextureMeta(copy);
|
||||
final ResourceManager.TextureMeta meta = GlsmSdlHeadlessRig.resourceManager().getTextureMeta(copy);
|
||||
assertNotNull(meta, "copyTexImage2D did not allocate the destination");
|
||||
assertEquals(VIEW, meta.width());
|
||||
assertEquals(VIEW, meta.height());
|
||||
|
||||
@@ -10,17 +10,17 @@ import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Tag;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.ValueSource;
|
||||
import org.lwjgl.BufferUtils;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL12;
|
||||
import org.lwjgl.opengl.GL13;
|
||||
import org.lwjgl.system.MemoryUtil;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.FloatBuffer;
|
||||
import java.nio.IntBuffer;
|
||||
|
||||
import static com.gtnewhorizons.angelica.sdlgpu.glsm.GlsmSdlHeadlessRig.SIZE;
|
||||
import static com.gtnewhorizons.angelica.sdlgpu.glsm.GlsmSdlHeadlessRig.TEXEL;
|
||||
import static com.gtnewhorizons.angelica.sdlgpu.glsm.GlsmSdlHeadlessRig.describe;
|
||||
import static com.gtnewhorizons.angelica.sdlgpu.glsm.GlsmSdlHeadlessRig.pixelAt;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
@@ -30,18 +30,14 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
@ExtendWith(GlsmSdlFrameExtension.class)
|
||||
class GlsmSdlFfpTest {
|
||||
|
||||
private static final int TEXEL = 0xFFFF4020;
|
||||
private static final int LIGHTMAP_SIZE = 16;
|
||||
|
||||
private static int baseTexture;
|
||||
private static int lightmapTexture;
|
||||
|
||||
@BeforeAll
|
||||
static void boot() {
|
||||
GlsmSdlHeadlessRig.boot();
|
||||
GlsmSdlHeadlessRig.beginFrame();
|
||||
baseTexture = GlsmSdlHeadlessRig.createSolidTexture(TEXEL);
|
||||
lightmapTexture = createLightmapTexture();
|
||||
lightmapTexture = GlsmSdlHeadlessRig.createLightmapTexture(true);
|
||||
GlsmSdlHeadlessRig.endFrame();
|
||||
}
|
||||
|
||||
@@ -53,37 +49,8 @@ class GlsmSdlFfpTest {
|
||||
FfpFixture.IntegerInstances.delete();
|
||||
}
|
||||
|
||||
private static int createLightmapTexture() {
|
||||
final int id = GLStateManager.glGenTextures();
|
||||
GLStateManager.glActiveTexture(GL13.GL_TEXTURE1);
|
||||
GLStateManager.glBindTexture(GL11.GL_TEXTURE_2D, id);
|
||||
GLStateManager.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_NEAREST);
|
||||
GLStateManager.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_NEAREST);
|
||||
GLStateManager.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA8, LIGHTMAP_SIZE, LIGHTMAP_SIZE, 0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, (ByteBuffer) null);
|
||||
final ByteBuffer texels = MemoryUtil.memAlloc(LIGHTMAP_SIZE * LIGHTMAP_SIZE * 4);
|
||||
try {
|
||||
for (int y = 0; y < LIGHTMAP_SIZE; y++) {
|
||||
for (int x = 0; x < LIGHTMAP_SIZE; x++) {
|
||||
final boolean brightest = (x == 0 && y == 0) || (x == LIGHTMAP_SIZE - 1 && y == LIGHTMAP_SIZE - 1);
|
||||
texels.put((byte) (brightest ? 255 : 0));
|
||||
texels.put((byte) 255);
|
||||
texels.put((byte) (brightest ? 255 : 0));
|
||||
texels.put((byte) 255);
|
||||
}
|
||||
}
|
||||
texels.flip();
|
||||
GLStateManager.glTexSubImage2D(GL11.GL_TEXTURE_2D, 0, 0, 0, LIGHTMAP_SIZE, LIGHTMAP_SIZE, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, texels);
|
||||
} finally {
|
||||
MemoryUtil.memFree(texels);
|
||||
}
|
||||
GLStateManager.glActiveTexture(GL13.GL_TEXTURE0);
|
||||
return id;
|
||||
}
|
||||
|
||||
private static void bindBaseTexture() {
|
||||
GLStateManager.glActiveTexture(GL13.GL_TEXTURE0);
|
||||
GLStateManager.glBindTexture(GL11.GL_TEXTURE_2D, baseTexture);
|
||||
GLStateManager.glEnable(GL11.GL_TEXTURE_2D);
|
||||
GlsmSdlHeadlessRig.bindBaseTexture(baseTexture);
|
||||
}
|
||||
|
||||
private static void enableLightmapUnit(boolean vanillaTextureMatrix) {
|
||||
@@ -100,13 +67,7 @@ class GlsmSdlFfpTest {
|
||||
}
|
||||
|
||||
private static void quadTwoUnits(boolean vanillaBrightness) {
|
||||
final short brightness = (short) (vanillaBrightness ? 240 : 0);
|
||||
GLStateManager.glBegin(GL11.GL_QUADS);
|
||||
GlsmSdlHeadlessRig.emitVertex(-1.0f, -1.0f, 0.0f, 0.0f, true, brightness);
|
||||
GlsmSdlHeadlessRig.emitVertex(1.0f, -1.0f, 1.0f, 0.0f, true, brightness);
|
||||
GlsmSdlHeadlessRig.emitVertex(1.0f, 1.0f, 1.0f, 1.0f, true, brightness);
|
||||
GlsmSdlHeadlessRig.emitVertex(-1.0f, 1.0f, 0.0f, 1.0f, true, brightness);
|
||||
GLStateManager.glEnd();
|
||||
GlsmSdlHeadlessRig.quadTwoUnits((short) (vanillaBrightness ? 240 : 0));
|
||||
}
|
||||
|
||||
private static void assertTexelEverywhere(String label) {
|
||||
@@ -124,22 +85,15 @@ class GlsmSdlFfpTest {
|
||||
assertTexelEverywhere("single unit");
|
||||
}
|
||||
|
||||
@Test
|
||||
void twoUnitTerrainQuadWithVanillaLightmapMatrixShowsTheTexel() {
|
||||
/** Vanilla pairs its lightmap texture matrix with brightness 240; the identity matrix case uses brightness 0. */
|
||||
@ParameterizedTest(name = "vanilla lightmap matrix and brightness: {0}")
|
||||
@ValueSource(booleans = {true, false})
|
||||
void twoUnitTerrainQuadShowsTheTexel(boolean vanilla) {
|
||||
bindBaseTexture();
|
||||
enableLightmapUnit(true);
|
||||
enableLightmapUnit(vanilla);
|
||||
GlsmSdlHeadlessRig.terrainRenderState();
|
||||
quadTwoUnits(true);
|
||||
assertTexelEverywhere("two units, vanilla lightmap matrix");
|
||||
}
|
||||
|
||||
@Test
|
||||
void twoUnitTerrainQuadWithIdentityLightmapMatrixShowsTheTexel() {
|
||||
bindBaseTexture();
|
||||
enableLightmapUnit(false);
|
||||
GlsmSdlHeadlessRig.terrainRenderState();
|
||||
quadTwoUnits(false);
|
||||
assertTexelEverywhere("two units, identity lightmap matrix, zero brightness");
|
||||
quadTwoUnits(vanilla);
|
||||
assertTexelEverywhere(vanilla ? "two units, vanilla lightmap matrix" : "two units, identity lightmap matrix, zero brightness");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -226,9 +180,9 @@ class GlsmSdlFfpTest {
|
||||
|
||||
final int[] pixels = GlsmSdlHeadlessRig.readTarget();
|
||||
|
||||
GlsmSdlHeadlessRig.assertPixel(pixels, SIZE, 13, SIZE / 2, 0xFFFF0000, "entity -1 must render red");
|
||||
GlsmSdlHeadlessRig.assertPixel(pixels, SIZE, 32, SIZE / 2, 0xFF00FF00, "entity 7 must render green");
|
||||
GlsmSdlHeadlessRig.assertPixel(pixels, SIZE, 51, SIZE / 2, 0xFF0000FF, "entity 50020 must render blue");
|
||||
GlsmSdlHeadlessRig.assertPixel(pixels, SIZE, 13, SIZE / 2, GlsmSdlHeadlessRig.RED, "entity -1 must render red");
|
||||
GlsmSdlHeadlessRig.assertPixel(pixels, SIZE, 32, SIZE / 2, GlsmSdlHeadlessRig.GREEN, "entity 7 must render green");
|
||||
GlsmSdlHeadlessRig.assertPixel(pixels, SIZE, 51, SIZE / 2, GlsmSdlHeadlessRig.BLUE, "entity 50020 must render blue");
|
||||
}
|
||||
|
||||
private static void enableGuiStandardItemLighting() {
|
||||
|
||||
+7
-1
@@ -1,12 +1,18 @@
|
||||
package com.gtnewhorizons.angelica.sdlgpu.glsm;
|
||||
|
||||
import org.junit.jupiter.api.extension.AfterEachCallback;
|
||||
import org.junit.jupiter.api.extension.BeforeAllCallback;
|
||||
import org.junit.jupiter.api.extension.BeforeEachCallback;
|
||||
import org.junit.jupiter.api.extension.ExtensionContext;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
public final class GlsmSdlFrameExtension implements BeforeEachCallback, AfterEachCallback {
|
||||
public final class GlsmSdlFrameExtension implements BeforeAllCallback, BeforeEachCallback, AfterEachCallback {
|
||||
|
||||
@Override
|
||||
public void beforeAll(ExtensionContext context) {
|
||||
GlsmSdlHeadlessRig.boot();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beforeEach(ExtensionContext context) {
|
||||
|
||||
+89
-26
@@ -9,6 +9,7 @@ import com.gtnewhorizons.angelica.glsm.testutil.Reflect;
|
||||
import com.gtnewhorizons.angelica.sdlgpu.SDLGPUGate;
|
||||
import com.gtnewhorizons.angelica.sdlgpu.SDLGPURenderBackend;
|
||||
import com.gtnewhorizons.angelica.sdlgpu.SdlTestRig;
|
||||
import com.gtnewhorizons.angelica.sdlgpu.frame.FrameManager;
|
||||
import com.gtnewhorizons.angelica.sdlgpu.pipeline.PipelineCache;
|
||||
import com.gtnewhorizons.angelica.sdlgpu.resource.ResourceManager;
|
||||
import it.unimi.dsi.fastutil.ints.Int2IntMap;
|
||||
@@ -29,6 +30,14 @@ public final class GlsmSdlHeadlessRig {
|
||||
|
||||
public static final int SIZE = 64;
|
||||
|
||||
public static final int RED = 0xFFFF0000;
|
||||
public static final int GREEN = 0xFF00FF00;
|
||||
public static final int BLUE = 0xFF0000FF;
|
||||
public static final int BLACK = 0xFF000000;
|
||||
|
||||
public static final int TEXEL = 0xFFFF4020;
|
||||
public static final int LIGHTMAP_SIZE = 16;
|
||||
|
||||
private static boolean booted;
|
||||
private static int fbo;
|
||||
private static int colorTexture;
|
||||
@@ -91,9 +100,30 @@ public final class GlsmSdlHeadlessRig {
|
||||
return bound.get(target);
|
||||
}
|
||||
|
||||
public static FrameManager frameManager() {
|
||||
return Reflect.get(BackendManager.RENDER_BACKEND, "frameManager");
|
||||
}
|
||||
|
||||
public static ResourceManager resourceManager() {
|
||||
return Reflect.get(BackendManager.RENDER_BACKEND, "resourceManager");
|
||||
}
|
||||
|
||||
/** Replaces FBO 0's backing target; pair with {@link #dropFinalTarget()}. */
|
||||
public static void installFinalTarget(int width, int height) {
|
||||
final FrameManager fm = frameManager();
|
||||
final ResourceManager rm = resourceManager();
|
||||
fm.destroyFinalTarget();
|
||||
fm.finalTarget().create(SDLGPUGate.device(), rm, width, height, rm.mapTextureFormat(GL11.GL_RGBA8));
|
||||
assertEquals(height, fm.getFbo0Height());
|
||||
}
|
||||
|
||||
public static void dropFinalTarget() {
|
||||
endFrame();
|
||||
if (booted) frameManager().destroyFinalTarget();
|
||||
}
|
||||
|
||||
static int colorTargetSdlFormat() {
|
||||
final ResourceManager rm = Reflect.get(BackendManager.RENDER_BACKEND, "resourceManager");
|
||||
final ResourceManager.TextureMeta meta = rm.getTextureMeta(colorTexture);
|
||||
final ResourceManager.TextureMeta meta = resourceManager().getTextureMeta(colorTexture);
|
||||
return meta != null ? meta.sdlFormat() : 0;
|
||||
}
|
||||
|
||||
@@ -229,24 +259,69 @@ public final class GlsmSdlHeadlessRig {
|
||||
return fbo;
|
||||
}
|
||||
|
||||
public static int createSolidTexture(int argb) {
|
||||
final int id = newNearestTexture();
|
||||
final ByteBuffer texels = MemoryUtil.memAlloc(2 * 2 * 4);
|
||||
public static void putArgb(ByteBuffer texels, int index, int argb) {
|
||||
texels.put(index * 4, (byte) ((argb >> 16) & 0xFF));
|
||||
texels.put(index * 4 + 1, (byte) ((argb >> 8) & 0xFF));
|
||||
texels.put(index * 4 + 2, (byte) (argb & 0xFF));
|
||||
texels.put(index * 4 + 3, (byte) ((argb >>> 24) & 0xFF));
|
||||
}
|
||||
|
||||
/** Uploads one solid RGBA8 level of the GL_TEXTURE_2D bound on the active unit. */
|
||||
public static void uploadSolidLevel(int level, int size, int argb) {
|
||||
final ByteBuffer texels = MemoryUtil.memAlloc(size * size * 4);
|
||||
try {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
texels.put((byte) ((argb >> 16) & 0xFF));
|
||||
texels.put((byte) ((argb >> 8) & 0xFF));
|
||||
texels.put((byte) (argb & 0xFF));
|
||||
texels.put((byte) ((argb >>> 24) & 0xFF));
|
||||
}
|
||||
texels.flip();
|
||||
GLStateManager.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA8, 2, 2, 0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, texels);
|
||||
for (int i = 0; i < size * size; i++) putArgb(texels, i, argb);
|
||||
GLStateManager.glTexImage2D(GL11.GL_TEXTURE_2D, level, GL11.GL_RGBA8, size, size, 0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, texels);
|
||||
} finally {
|
||||
MemoryUtil.memFree(texels);
|
||||
}
|
||||
}
|
||||
|
||||
public static int createSolidTexture(int argb) {
|
||||
final int id = newNearestTexture();
|
||||
uploadSolidLevel(0, 2, argb);
|
||||
return id;
|
||||
}
|
||||
|
||||
public static int createLightmapTexture(boolean brightCornersOnly) {
|
||||
final int id = GLStateManager.glGenTextures();
|
||||
GLStateManager.glActiveTexture(GL13.GL_TEXTURE1);
|
||||
GLStateManager.glBindTexture(GL11.GL_TEXTURE_2D, id);
|
||||
GLStateManager.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_NEAREST);
|
||||
GLStateManager.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_NEAREST);
|
||||
GLStateManager.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA8, LIGHTMAP_SIZE, LIGHTMAP_SIZE, 0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, (ByteBuffer) null);
|
||||
final ByteBuffer texels = MemoryUtil.memAlloc(LIGHTMAP_SIZE * LIGHTMAP_SIZE * 4);
|
||||
try {
|
||||
final int last = LIGHTMAP_SIZE - 1;
|
||||
for (int y = 0; y < LIGHTMAP_SIZE; y++) {
|
||||
for (int x = 0; x < LIGHTMAP_SIZE; x++) {
|
||||
final boolean bright = !brightCornersOnly || (x == 0 && y == 0) || (x == last && y == last);
|
||||
putArgb(texels, y * LIGHTMAP_SIZE + x, bright ? 0xFFFFFFFF : GREEN);
|
||||
}
|
||||
}
|
||||
GLStateManager.glTexSubImage2D(GL11.GL_TEXTURE_2D, 0, 0, 0, LIGHTMAP_SIZE, LIGHTMAP_SIZE, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, texels);
|
||||
} finally {
|
||||
MemoryUtil.memFree(texels);
|
||||
}
|
||||
GLStateManager.glActiveTexture(GL13.GL_TEXTURE0);
|
||||
return id;
|
||||
}
|
||||
|
||||
public static void bindBaseTexture(int texture) {
|
||||
GLStateManager.glActiveTexture(GL13.GL_TEXTURE0);
|
||||
GLStateManager.glBindTexture(GL11.GL_TEXTURE_2D, texture);
|
||||
GLStateManager.glEnable(GL11.GL_TEXTURE_2D);
|
||||
}
|
||||
|
||||
public static void quadTwoUnits(short brightness) {
|
||||
GLStateManager.glBegin(GL11.GL_QUADS);
|
||||
emitVertex(-1.0f, -1.0f, 0.0f, 0.0f, true, brightness);
|
||||
emitVertex(1.0f, -1.0f, 1.0f, 0.0f, true, brightness);
|
||||
emitVertex(1.0f, 1.0f, 1.0f, 1.0f, true, brightness);
|
||||
emitVertex(-1.0f, 1.0f, 0.0f, 1.0f, true, brightness);
|
||||
GLStateManager.glEnd();
|
||||
}
|
||||
|
||||
public static void enableLightmapUnit(int lightmapTexture, boolean vanillaTextureMatrix) {
|
||||
GLStateManager.glActiveTexture(GL13.GL_TEXTURE1);
|
||||
GLStateManager.glBindTexture(GL11.GL_TEXTURE_2D, lightmapTexture);
|
||||
@@ -339,19 +414,7 @@ public final class GlsmSdlHeadlessRig {
|
||||
GLStateManager.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_NEAREST);
|
||||
GLStateManager.glTexParameteri(GL11.GL_TEXTURE_2D, GL12.GL_TEXTURE_MAX_LEVEL, maxLevel);
|
||||
for (int level = 0; level <= maxLevel; level++) {
|
||||
final int levelSize = Math.max(1, size >> level);
|
||||
final ByteBuffer texels = MemoryUtil.memAlloc(levelSize * levelSize * 4);
|
||||
try {
|
||||
for (int i = 0; i < levelSize * levelSize; i++) {
|
||||
texels.put(i * 4, (byte) ((argb >> 16) & 0xFF));
|
||||
texels.put(i * 4 + 1, (byte) ((argb >> 8) & 0xFF));
|
||||
texels.put(i * 4 + 2, (byte) (argb & 0xFF));
|
||||
texels.put(i * 4 + 3, (byte) ((argb >>> 24) & 0xFF));
|
||||
}
|
||||
GLStateManager.glTexImage2D(GL11.GL_TEXTURE_2D, level, GL11.GL_RGBA8, levelSize, levelSize, 0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, texels);
|
||||
} finally {
|
||||
MemoryUtil.memFree(texels);
|
||||
}
|
||||
uploadSolidLevel(level, Math.max(1, size >> level), argb);
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
+2
-10
@@ -2,12 +2,10 @@ package com.gtnewhorizons.angelica.sdlgpu.glsm;
|
||||
|
||||
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||
import com.gtnewhorizons.angelica.glsm.RenderSystem;
|
||||
import com.gtnewhorizons.angelica.glsm.testutil.Reflect;
|
||||
import com.gtnewhorizons.angelica.sdlgpu.SDLGPURenderBackend;
|
||||
import com.gtnewhorizons.angelica.sdlgpu.SdlAsserts;
|
||||
import com.gtnewhorizons.angelica.sdlgpu.SdlTestRig;
|
||||
import com.gtnewhorizons.angelica.sdlgpu.frame.ContextState;
|
||||
import com.gtnewhorizons.angelica.sdlgpu.pipeline.PipelineCache;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Tag;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
@@ -22,14 +20,8 @@ import static org.lwjgl.sdl.SDLGPU.SDL_GPU_BLENDFACTOR_SRC_ALPHA;
|
||||
@ExtendWith(GlsmSdlFrameExtension.class)
|
||||
class GlsmSdlIndexedBlendRestoreTest {
|
||||
|
||||
@BeforeAll
|
||||
static void boot() {
|
||||
GlsmSdlHeadlessRig.boot();
|
||||
}
|
||||
|
||||
private static PipelineCache pipeline() {
|
||||
final ContextState st = Reflect.invokeStatic(SDLGPURenderBackend.class, "s", new Class<?>[0]);
|
||||
return st.pipeline;
|
||||
return SdlTestRig.contextState().pipeline;
|
||||
}
|
||||
|
||||
private static void vanillaBlendFunc() {
|
||||
|
||||
+2
-21
@@ -1,22 +1,20 @@
|
||||
package com.gtnewhorizons.angelica.sdlgpu.glsm;
|
||||
|
||||
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||
import com.gtnewhorizons.angelica.glsm.GlTestSupport;
|
||||
import com.gtnewhorizons.angelica.glsm.testutil.Reflect;
|
||||
import com.gtnewhorizons.angelica.sdlgpu.SDLGPUGate;
|
||||
import com.gtnewhorizons.angelica.sdlgpu.device.Device;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Tag;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL15;
|
||||
import org.lwjgl.opengl.GL20;
|
||||
import org.lwjgl.system.MemoryUtil;
|
||||
|
||||
import java.nio.FloatBuffer;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
/**
|
||||
* Metal steps a per-instance constant binding by 16 bytes per instance.
|
||||
@@ -48,29 +46,12 @@ class GlsmSdlInstancedConstantTest {
|
||||
}
|
||||
""";
|
||||
|
||||
@BeforeAll
|
||||
static void boot() {
|
||||
GlsmSdlHeadlessRig.boot();
|
||||
}
|
||||
|
||||
private static int compile(int type, String source) {
|
||||
final int shader = GLStateManager.glCreateShader(type);
|
||||
GLStateManager.glShaderSource(shader, source);
|
||||
GLStateManager.glCompileShader(shader);
|
||||
assertTrue(GLStateManager.glGetShaderi(shader, GL20.GL_COMPILE_STATUS) != 0, () -> GLStateManager.glGetShaderInfoLog(shader));
|
||||
return shader;
|
||||
}
|
||||
|
||||
@Test
|
||||
void everyInstanceReadsTheConstantWhenInstancesStepTheBinding() {
|
||||
final Device device = SDLGPUGate.device();
|
||||
final String driver = device.getDriverName();
|
||||
Reflect.set(device, "driverName", "metal");
|
||||
final int program = GLStateManager.glCreateProgram();
|
||||
GLStateManager.glAttachShader(program, compile(GL20.GL_VERTEX_SHADER, VERT));
|
||||
GLStateManager.glAttachShader(program, compile(GL20.GL_FRAGMENT_SHADER, FRAG));
|
||||
GLStateManager.glLinkProgram(program);
|
||||
assertTrue(GLStateManager.glGetProgrami(program, GL20.GL_LINK_STATUS) != 0, "program did not link");
|
||||
final int program = GlTestSupport.program(VERT, FRAG);
|
||||
|
||||
final int vao = GLStateManager.glGenVertexArrays();
|
||||
final int vbo = GLStateManager.glGenBuffers();
|
||||
|
||||
-1
@@ -26,7 +26,6 @@ class GlsmSdlLWJGLServiceRoutingTest {
|
||||
|
||||
@BeforeAll
|
||||
static void boot() {
|
||||
GlsmSdlHeadlessRig.boot();
|
||||
svc = SDLGPULWJGLService.create();
|
||||
}
|
||||
|
||||
|
||||
+187
@@ -0,0 +1,187 @@
|
||||
package com.gtnewhorizons.angelica.sdlgpu.glsm;
|
||||
|
||||
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||
import com.gtnewhorizons.angelica.glsm.LegacyQueryFixture;
|
||||
import org.junit.jupiter.api.Tag;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.lwjgl.BufferUtils;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL13;
|
||||
import org.lwjgl.opengl.GL14;
|
||||
import org.lwjgl.opengl.GL15;
|
||||
import org.lwjgl.opengl.GL20;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.DoubleBuffer;
|
||||
import java.nio.FloatBuffer;
|
||||
import java.nio.IntBuffer;
|
||||
|
||||
import static com.gtnewhorizons.angelica.glsm.LegacyQueryFixture.CLIENT_ARRAY_CAPS;
|
||||
import static com.gtnewhorizons.angelica.glsm.LegacyQueryFixture.HINT_TARGETS;
|
||||
import static com.gtnewhorizons.angelica.glsm.LegacyQueryFixture.assertEnableRoundTrip;
|
||||
import static com.gtnewhorizons.angelica.glsm.LegacyQueryFixture.drainClientAttribStack;
|
||||
import static com.gtnewhorizons.angelica.glsm.LegacyQueryFixture.hex;
|
||||
import static com.gtnewhorizons.angelica.glsm.LegacyQueryFixture.popAttribTo;
|
||||
import static com.gtnewhorizons.angelica.glsm.LegacyQueryFixture.setEnabled;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
@Tag("glsm-sdl")
|
||||
@ExtendWith(GlsmSdlFrameExtension.class)
|
||||
class GlsmSdlLegacyQueryTest {
|
||||
|
||||
private static final int[] CACHE_ONLY_CAPS = { GL20.GL_POINT_SPRITE, GL20.GL_VERTEX_PROGRAM_TWO_SIDE, GL13.GL_TEXTURE_CUBE_MAP };
|
||||
|
||||
// The SDL backend answers 0 or false for a pname it does not know, so a query that fell through to it
|
||||
// fails the non-zero expectations below.
|
||||
@Test
|
||||
void legacyQueriesAreAnsweredWithoutTheBackend() {
|
||||
final int base = GLStateManager.getAttribDepth();
|
||||
final IntBuffer ints = BufferUtils.createIntBuffer(16);
|
||||
final FloatBuffer floats = BufferUtils.createFloatBuffer(16);
|
||||
final DoubleBuffer doubles = BufferUtils.createDoubleBuffer(16);
|
||||
final ByteBuffer bytes = BufferUtils.createByteBuffer(16);
|
||||
final FloatBuffer positions = BufferUtils.createFloatBuffer(12);
|
||||
final FloatBuffer other = BufferUtils.createFloatBuffer(12);
|
||||
final FloatBuffer savedColor = BufferUtils.createFloatBuffer(16);
|
||||
GLStateManager.glGetFloat(GL11.GL_CURRENT_COLOR, savedColor);
|
||||
final boolean savedLighting = GLStateManager.glIsEnabled(GL11.GL_LIGHTING);
|
||||
final boolean savedEdge = GLStateManager.glGetBoolean(GL11.GL_EDGE_FLAG);
|
||||
final int[] savedHints = new int[HINT_TARGETS.length];
|
||||
for (int i = 0; i < HINT_TARGETS.length; i++) {
|
||||
savedHints[i] = GLStateManager.glGetInteger(HINT_TARGETS[i]);
|
||||
}
|
||||
try {
|
||||
GLStateManager.glClientActiveTexture(GL13.GL_TEXTURE1);
|
||||
assertEquals(GL13.GL_TEXTURE1, GLStateManager.glGetInteger(GL13.GL_CLIENT_ACTIVE_TEXTURE));
|
||||
GLStateManager.glClientActiveTexture(0);
|
||||
assertEquals(1, GLStateManager.getClientActiveTextureUnit(), "an invalid unit is rejected");
|
||||
assertEquals(GLStateManager.MAX_TEXTURE_COORDS, GLStateManager.glGetInteger(GL20.GL_MAX_TEXTURE_COORDS));
|
||||
GLStateManager.glClientActiveTexture(GL13.GL_TEXTURE0);
|
||||
|
||||
for (final int cap : CLIENT_ARRAY_CAPS) {
|
||||
final boolean was = GLStateManager.glIsEnabled(cap);
|
||||
assertEnableRoundTrip(cap, true);
|
||||
if (was) GLStateManager.glEnableClientState(cap);
|
||||
}
|
||||
for (final int cap : CACHE_ONLY_CAPS) {
|
||||
final boolean was = GLStateManager.glIsEnabled(cap);
|
||||
assertEnableRoundTrip(cap, false);
|
||||
setEnabled(cap, was);
|
||||
}
|
||||
GLStateManager.glEdgeFlag(false);
|
||||
assertFalse(GLStateManager.glGetBoolean(GL11.GL_EDGE_FLAG));
|
||||
GLStateManager.glEdgeFlag(true);
|
||||
assertTrue(GLStateManager.glGetBoolean(GL11.GL_EDGE_FLAG));
|
||||
|
||||
for (final int target : HINT_TARGETS) {
|
||||
final String name = hex(target);
|
||||
GLStateManager.glHint(target, GL11.GL_NICEST);
|
||||
assertEquals(GL11.GL_NICEST, GLStateManager.glGetInteger(target), "set " + name);
|
||||
assertEquals((float) GL11.GL_NICEST, GLStateManager.glGetFloat(target), "float " + name);
|
||||
GLStateManager.glPushAttrib(GL11.GL_HINT_BIT);
|
||||
GLStateManager.glHint(target, GL11.GL_FASTEST);
|
||||
assertEquals(GL11.GL_FASTEST, GLStateManager.glGetInteger(target), "inside push " + name);
|
||||
GLStateManager.glPopAttrib();
|
||||
assertEquals(GL11.GL_NICEST, GLStateManager.glGetInteger(target), "after pop " + name);
|
||||
}
|
||||
|
||||
GLStateManager.glVertexPointer(3, 12, positions);
|
||||
GLStateManager.glFogCoordPointer(4, positions);
|
||||
assertEquals(3, GLStateManager.glGetInteger(GL11.GL_VERTEX_ARRAY_SIZE));
|
||||
assertEquals(GL11.GL_FLOAT, GLStateManager.glGetInteger(GL11.GL_VERTEX_ARRAY_TYPE));
|
||||
assertEquals(12, GLStateManager.glGetInteger(GL11.GL_VERTEX_ARRAY_STRIDE));
|
||||
assertEquals(0, GLStateManager.glGetInteger(GL15.GL_VERTEX_ARRAY_BUFFER_BINDING));
|
||||
assertEquals(4, GLStateManager.glGetInteger(GL14.GL_FOG_COORDINATE_ARRAY_STRIDE));
|
||||
assertEquals(3, GLStateManager.glGetInteger(GL14.GL_SECONDARY_COLOR_ARRAY_SIZE));
|
||||
GLStateManager.glPushClientAttrib(GL11.GL_CLIENT_VERTEX_ARRAY_BIT);
|
||||
GLStateManager.glVertexPointer(2, 8, other);
|
||||
GLStateManager.glFogCoordPointer(8, other);
|
||||
GLStateManager.glEnableClientState(GL14.GL_FOG_COORDINATE_ARRAY);
|
||||
assertEquals(2, GLStateManager.glGetInteger(GL11.GL_VERTEX_ARRAY_SIZE));
|
||||
GLStateManager.glPopClientAttrib();
|
||||
assertEquals(3, GLStateManager.glGetInteger(GL11.GL_VERTEX_ARRAY_SIZE), "client attrib pop restores the pointer");
|
||||
assertEquals(12, GLStateManager.glGetInteger(GL11.GL_VERTEX_ARRAY_STRIDE));
|
||||
assertEquals(4, GLStateManager.glGetInteger(GL14.GL_FOG_COORDINATE_ARRAY_STRIDE));
|
||||
assertFalse(GLStateManager.glIsEnabled(GL14.GL_FOG_COORDINATE_ARRAY));
|
||||
|
||||
GLStateManager.glColor4f(1.0f, 0.5f, 0.0f, 1.0f);
|
||||
GLStateManager.glGetInteger(GL11.GL_CURRENT_COLOR, ints);
|
||||
assertEquals(2147483647, ints.get(0));
|
||||
assertEquals(1073741823, ints.get(1));
|
||||
assertEquals(0, ints.get(2));
|
||||
GLStateManager.glEnable(GL11.GL_LIGHTING);
|
||||
assertEquals(1, GLStateManager.glGetInteger(GL11.GL_LIGHTING));
|
||||
assertEquals(1.0f, GLStateManager.glGetFloat(GL11.GL_LIGHTING));
|
||||
assertEquals((float) GLStateManager.glGetInteger(GL11.GL_FOG_MODE), GLStateManager.glGetFloat(GL11.GL_FOG_MODE));
|
||||
assertEquals(GL11.GL_RENDER, GLStateManager.glGetInteger(GL11.GL_RENDER_MODE));
|
||||
|
||||
for (final int pname : LegacyQueryFixture.legacyPnames()) {
|
||||
final String name = hex(pname);
|
||||
final int scalar = GLStateManager.glGetInteger(pname);
|
||||
final float scalarFloat = GLStateManager.glGetFloat(pname);
|
||||
final boolean scalarBool = GLStateManager.glGetBoolean(pname);
|
||||
ints.clear();
|
||||
GLStateManager.glGetInteger(pname, ints);
|
||||
floats.clear();
|
||||
GLStateManager.glGetFloat(pname, floats);
|
||||
doubles.clear();
|
||||
GLStateManager.glGetDouble(pname, doubles);
|
||||
bytes.clear();
|
||||
GLStateManager.glGetBoolean(pname, bytes);
|
||||
assertEquals(scalar, ints.get(0), "IntBuffer overload for " + name);
|
||||
assertEquals(scalarFloat, floats.get(0), "FloatBuffer overload for " + name);
|
||||
assertEquals((double) scalarFloat, doubles.get(0), "DoubleBuffer overload for " + name);
|
||||
assertEquals(scalarBool, bytes.get(0) != 0, "ByteBuffer overload for " + name);
|
||||
}
|
||||
} finally {
|
||||
drainClientAttribStack();
|
||||
popAttribTo(base);
|
||||
GLStateManager.glClientActiveTexture(GL13.GL_TEXTURE0);
|
||||
GLStateManager.glDisableClientState(GL14.GL_FOG_COORDINATE_ARRAY);
|
||||
for (int i = 0; i < HINT_TARGETS.length; i++) {
|
||||
GLStateManager.glHint(HINT_TARGETS[i], savedHints[i]);
|
||||
}
|
||||
GLStateManager.glEdgeFlag(savedEdge);
|
||||
GLStateManager.glColor4f(savedColor.get(0), savedColor.get(1), savedColor.get(2), savedColor.get(3));
|
||||
setEnabled(GL11.GL_LIGHTING, savedLighting);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void pointParametersRoundTrip() {
|
||||
final FloatBuffer attenuation = BufferUtils.createFloatBuffer(16);
|
||||
final float savedMin = GLStateManager.glGetFloat(GL14.GL_POINT_SIZE_MIN);
|
||||
final float savedMax = GLStateManager.glGetFloat(GL14.GL_POINT_SIZE_MAX);
|
||||
final float savedThreshold = GLStateManager.glGetFloat(GL14.GL_POINT_FADE_THRESHOLD_SIZE);
|
||||
final int savedOrigin = GLStateManager.glGetInteger(GL20.GL_POINT_SPRITE_COORD_ORIGIN);
|
||||
final int base = GLStateManager.getAttribDepth();
|
||||
try {
|
||||
assertEquals(1.0f, savedMax);
|
||||
GLStateManager.glPushAttrib(GL11.GL_POINT_BIT);
|
||||
GLStateManager.glPointParameterf(GL14.GL_POINT_SIZE_MIN, 2.0f);
|
||||
GLStateManager.glPointParameterf(GL14.GL_POINT_SIZE_MAX, 8.0f);
|
||||
GLStateManager.glPointParameterf(GL14.GL_POINT_FADE_THRESHOLD_SIZE, 3.0f);
|
||||
GLStateManager.glPointParameteri(GL20.GL_POINT_SPRITE_COORD_ORIGIN, GL20.GL_LOWER_LEFT);
|
||||
attenuation.clear();
|
||||
attenuation.put(0, 0.5f).put(1, 0.25f).put(2, 0.125f);
|
||||
GLStateManager.glPointParameter(GL14.GL_POINT_DISTANCE_ATTENUATION, attenuation);
|
||||
assertEquals(2.0f, GLStateManager.glGetFloat(GL14.GL_POINT_SIZE_MIN));
|
||||
assertEquals(8.0f, GLStateManager.glGetFloat(GL14.GL_POINT_SIZE_MAX));
|
||||
assertEquals(3.0f, GLStateManager.glGetFloat(GL14.GL_POINT_FADE_THRESHOLD_SIZE));
|
||||
assertEquals(GL20.GL_LOWER_LEFT, GLStateManager.glGetInteger(GL20.GL_POINT_SPRITE_COORD_ORIGIN));
|
||||
attenuation.clear();
|
||||
GLStateManager.glGetFloat(GL14.GL_POINT_DISTANCE_ATTENUATION, attenuation);
|
||||
assertEquals(0.25f, attenuation.get(1));
|
||||
GLStateManager.glPopAttrib();
|
||||
assertEquals(savedMin, GLStateManager.glGetFloat(GL14.GL_POINT_SIZE_MIN));
|
||||
assertEquals(savedMax, GLStateManager.glGetFloat(GL14.GL_POINT_SIZE_MAX));
|
||||
assertEquals(savedThreshold, GLStateManager.glGetFloat(GL14.GL_POINT_FADE_THRESHOLD_SIZE));
|
||||
assertEquals(savedOrigin, GLStateManager.glGetInteger(GL20.GL_POINT_SPRITE_COORD_ORIGIN));
|
||||
} finally {
|
||||
popAttribTo(base);
|
||||
}
|
||||
}
|
||||
}
|
||||
Loaded 100 of 264 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user